MediaWiki
REL1_24
|
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;