MediaWiki  REL1_24
rebuildImages.php
Go to the documentation of this file.
00001 <?php
00033 require_once __DIR__ . '/Maintenance.php';
00034 
00040 class ImageBuilder extends Maintenance {
00041 
00045     protected $dbw;
00046 
00047     function __construct() {
00048         parent::__construct();
00049 
00050         global $wgUpdateCompatibleMetadata;
00051         //make sure to update old, but compatible img_metadata fields.
00052         $wgUpdateCompatibleMetadata = true;
00053 
00054         $this->mDescription = 'Script to update image metadata records';
00055 
00056         $this->addOption( 'missing', 'Check for files without associated database record' );
00057         $this->addOption( 'dry-run', 'Only report, don\'t update the database' );
00058     }
00059 
00060     public function execute() {
00061         $this->dbw = wfGetDB( DB_MASTER );
00062         $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
00063         $this->dryrun = $this->hasOption( 'dry-run' );
00064         if ( $this->dryrun ) {
00065             $GLOBALS['wgReadOnly'] = 'Dry run mode, image upgrades are suppressed';
00066         }
00067 
00068         if ( $this->hasOption( 'missing' ) ) {
00069             $this->crawlMissing();
00070         } else {
00071             $this->build();
00072         }
00073     }
00074 
00078     function getRepo() {
00079         if ( !isset( $this->repo ) ) {
00080             $this->repo = RepoGroup::singleton()->getLocalRepo();
00081         }
00082 
00083         return $this->repo;
00084     }
00085 
00086     function build() {
00087         $this->buildImage();
00088         $this->buildOldImage();
00089     }
00090 
00091     function init( $count, $table ) {
00092         $this->processed = 0;
00093         $this->updated = 0;
00094         $this->count = $count;
00095         $this->startTime = microtime( true );
00096         $this->table = $table;
00097     }
00098 
00099     function progress( $updated ) {
00100         $this->updated += $updated;
00101         $this->processed++;
00102         if ( $this->processed % 100 != 0 ) {
00103             return;
00104         }
00105         $portion = $this->processed / $this->count;
00106         $updateRate = $this->updated / $this->processed;
00107 
00108         $now = microtime( true );
00109         $delta = $now - $this->startTime;
00110         $estimatedTotalTime = $delta / $portion;
00111         $eta = $this->startTime + $estimatedTotalTime;
00112         $rate = $this->processed / $delta;
00113 
00114         $this->output( sprintf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
00115             wfTimestamp( TS_DB, intval( $now ) ),
00116             $portion * 100.0,
00117             $this->table,
00118             wfTimestamp( TS_DB, intval( $eta ) ),
00119             $this->processed,
00120             $this->count,
00121             $rate,
00122             $updateRate * 100.0 ) );
00123         flush();
00124     }
00125 
00126     function buildTable( $table, $key, $callback ) {
00127         $count = $this->dbw->selectField( $table, 'count(*)', '', __METHOD__ );
00128         $this->init( $count, $table );
00129         $this->output( "Processing $table...\n" );
00130 
00131         $result = wfGetDB( DB_SLAVE )->select( $table, '*', array(), __METHOD__ );
00132 
00133         foreach ( $result as $row ) {
00134             $update = call_user_func( $callback, $row, null );
00135             if ( $update ) {
00136                 $this->progress( 1 );
00137             } else {
00138                 $this->progress( 0 );
00139             }
00140         }
00141         $this->output( "Finished $table... $this->updated of $this->processed rows updated\n" );
00142     }
00143 
00144     function buildImage() {
00145         $callback = array( $this, 'imageCallback' );
00146         $this->buildTable( 'image', 'img_name', $callback );
00147     }
00148 
00149     function imageCallback( $row, $copy ) {
00150         // Create a File object from the row
00151         // This will also upgrade it
00152         $file = $this->getRepo()->newFileFromRow( $row );
00153 
00154         return $file->getUpgraded();
00155     }
00156 
00157     function buildOldImage() {
00158         $this->buildTable( 'oldimage', 'oi_archive_name', array( $this, 'oldimageCallback' ) );
00159     }
00160 
00161     function oldimageCallback( $row, $copy ) {
00162         // Create a File object from the row
00163         // This will also upgrade it
00164         if ( $row->oi_archive_name == '' ) {
00165             $this->output( "Empty oi_archive_name for oi_name={$row->oi_name}\n" );
00166 
00167             return false;
00168         }
00169         $file = $this->getRepo()->newFileFromRow( $row );
00170 
00171         return $file->getUpgraded();
00172     }
00173 
00174     function crawlMissing() {
00175         $this->getRepo()->enumFiles( array( $this, 'checkMissingImage' ) );
00176     }
00177 
00178     function checkMissingImage( $fullpath ) {
00179         $filename = wfBaseName( $fullpath );
00180         $row = $this->dbw->selectRow( 'image',
00181             array( 'img_name' ),
00182             array( 'img_name' => $filename ),
00183             __METHOD__ );
00184 
00185         if ( !$row ) { // file not registered
00186             $this->addMissingImage( $filename, $fullpath );
00187         }
00188     }
00189 
00190     function addMissingImage( $filename, $fullpath ) {
00191         global $wgContLang;
00192 
00193         $timestamp = $this->dbw->timestamp( $this->getRepo()->getFileTimestamp( $fullpath ) );
00194 
00195         $altname = $wgContLang->checkTitleEncoding( $filename );
00196         if ( $altname != $filename ) {
00197             if ( $this->dryrun ) {
00198                 $filename = $altname;
00199                 $this->output( "Estimating transcoding... $altname\n" );
00200             } else {
00201                 # @todo FIXME: create renameFile()
00202                 $filename = $this->renameFile( $filename );
00203             }
00204         }
00205 
00206         if ( $filename == '' ) {
00207             $this->output( "Empty filename for $fullpath\n" );
00208 
00209             return;
00210         }
00211         if ( !$this->dryrun ) {
00212             $file = wfLocalFile( $filename );
00213             if ( !$file->recordUpload(
00214                 '',
00215                 '(recovered file, missing upload log entry)',
00216                 '',
00217                 '',
00218                 '',
00219                 false,
00220                 $timestamp
00221             ) ) {
00222                 $this->output( "Error uploading file $fullpath\n" );
00223 
00224                 return;
00225             }
00226         }
00227         $this->output( $fullpath . "\n" );
00228     }
00229 }
00230 
00231 $maintClass = 'ImageBuilder';
00232 require_once RUN_MAINTENANCE_IF_MAIN;