MediaWiki
REL1_22
|
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 return $this->repo; 00083 } 00084 00085 function build() { 00086 $this->buildImage(); 00087 $this->buildOldImage(); 00088 } 00089 00090 function init( $count, $table ) { 00091 $this->processed = 0; 00092 $this->updated = 0; 00093 $this->count = $count; 00094 $this->startTime = microtime( true ); 00095 $this->table = $table; 00096 } 00097 00098 function progress( $updated ) { 00099 $this->updated += $updated; 00100 $this->processed++; 00101 if ( $this->processed % 100 != 0 ) { 00102 return; 00103 } 00104 $portion = $this->processed / $this->count; 00105 $updateRate = $this->updated / $this->processed; 00106 00107 $now = microtime( true ); 00108 $delta = $now - $this->startTime; 00109 $estimatedTotalTime = $delta / $portion; 00110 $eta = $this->startTime + $estimatedTotalTime; 00111 $rate = $this->processed / $delta; 00112 00113 $this->output( sprintf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n", 00114 wfTimestamp( TS_DB, intval( $now ) ), 00115 $portion * 100.0, 00116 $this->table, 00117 wfTimestamp( TS_DB, intval( $eta ) ), 00118 $this->processed, 00119 $this->count, 00120 $rate, 00121 $updateRate * 100.0 ) ); 00122 flush(); 00123 } 00124 00125 function buildTable( $table, $key, $callback ) { 00126 $count = $this->dbw->selectField( $table, 'count(*)', '', __METHOD__ ); 00127 $this->init( $count, $table ); 00128 $this->output( "Processing $table...\n" ); 00129 00130 $result = wfGetDB( DB_SLAVE )->select( $table, '*', array(), __METHOD__ ); 00131 00132 foreach ( $result as $row ) { 00133 $update = call_user_func( $callback, $row, null ); 00134 if ( $update ) { 00135 $this->progress( 1 ); 00136 } else { 00137 $this->progress( 0 ); 00138 } 00139 } 00140 $this->output( "Finished $table... $this->updated of $this->processed rows updated\n" ); 00141 } 00142 00143 function buildImage() { 00144 $callback = array( $this, 'imageCallback' ); 00145 $this->buildTable( 'image', 'img_name', $callback ); 00146 } 00147 00148 function imageCallback( $row, $copy ) { 00149 // Create a File object from the row 00150 // This will also upgrade it 00151 $file = $this->getRepo()->newFileFromRow( $row ); 00152 return $file->getUpgraded(); 00153 } 00154 00155 function buildOldImage() { 00156 $this->buildTable( 'oldimage', 'oi_archive_name', array( $this, 'oldimageCallback' ) ); 00157 } 00158 00159 function oldimageCallback( $row, $copy ) { 00160 // Create a File object from the row 00161 // This will also upgrade it 00162 if ( $row->oi_archive_name == '' ) { 00163 $this->output( "Empty oi_archive_name for oi_name={$row->oi_name}\n" ); 00164 return false; 00165 } 00166 $file = $this->getRepo()->newFileFromRow( $row ); 00167 return $file->getUpgraded(); 00168 } 00169 00170 function crawlMissing() { 00171 $this->getRepo()->enumFiles( array( $this, 'checkMissingImage' ) ); 00172 } 00173 00174 function checkMissingImage( $fullpath ) { 00175 $filename = wfBaseName( $fullpath ); 00176 $row = $this->dbw->selectRow( 'image', 00177 array( 'img_name' ), 00178 array( 'img_name' => $filename ), 00179 __METHOD__ ); 00180 00181 if ( !$row ) { // file not registered 00182 $this->addMissingImage( $filename, $fullpath ); 00183 } 00184 } 00185 00186 function addMissingImage( $filename, $fullpath ) { 00187 global $wgContLang; 00188 00189 $timestamp = $this->dbw->timestamp( $this->getRepo()->getFileTimestamp( $fullpath ) ); 00190 00191 $altname = $wgContLang->checkTitleEncoding( $filename ); 00192 if ( $altname != $filename ) { 00193 if ( $this->dryrun ) { 00194 $filename = $altname; 00195 $this->output( "Estimating transcoding... $altname\n" ); 00196 } else { 00197 # @todo FIXME: create renameFile() 00198 $filename = $this->renameFile( $filename ); 00199 } 00200 } 00201 00202 if ( $filename == '' ) { 00203 $this->output( "Empty filename for $fullpath\n" ); 00204 return; 00205 } 00206 if ( !$this->dryrun ) { 00207 $file = wfLocalFile( $filename ); 00208 if ( !$file->recordUpload( '', '(recovered file, missing upload log entry)', '', '', '', 00209 false, $timestamp ) ) 00210 { 00211 $this->output( "Error uploading file $fullpath\n" ); 00212 return; 00213 } 00214 } 00215 $this->output( $fullpath . "\n" ); 00216 } 00217 } 00218 00219 $maintClass = 'ImageBuilder'; 00220 require_once RUN_MAINTENANCE_IF_MAIN;