MediaWiki REL1_31
rebuildImages.php
Go to the documentation of this file.
1<?php
33require_once __DIR__ . '/Maintenance.php';
34
36
43
47 protected $dbw;
48
49 function __construct() {
50 parent::__construct();
51
53 // make sure to update old, but compatible img_metadata fields.
55
56 $this->addDescription( 'Script to update image metadata records' );
57
58 $this->addOption( 'missing', 'Check for files without associated database record' );
59 $this->addOption( 'dry-run', 'Only report, don\'t update the database' );
60 }
61
62 public function execute() {
63 $this->dbw = $this->getDB( DB_MASTER );
64 $this->dryrun = $this->hasOption( 'dry-run' );
65 if ( $this->dryrun ) {
66 MediaWiki\MediaWikiServices::getInstance()->getReadOnlyMode()
67 ->setReason( 'Dry run mode, image upgrades are suppressed' );
68 }
69
70 if ( $this->hasOption( 'missing' ) ) {
71 $this->crawlMissing();
72 } else {
73 $this->build();
74 }
75 }
76
80 function getRepo() {
81 if ( !isset( $this->repo ) ) {
82 $this->repo = RepoGroup::singleton()->getLocalRepo();
83 }
84
85 return $this->repo;
86 }
87
88 function build() {
89 $this->buildImage();
90 $this->buildOldImage();
91 }
92
93 function init( $count, $table ) {
94 $this->processed = 0;
95 $this->updated = 0;
96 $this->count = $count;
97 $this->startTime = microtime( true );
98 $this->table = $table;
99 }
100
101 function progress( $updated ) {
102 $this->updated += $updated;
103 $this->processed++;
104 if ( $this->processed % 100 != 0 ) {
105 return;
106 }
107 $portion = $this->processed / $this->count;
108 $updateRate = $this->updated / $this->processed;
109
110 $now = microtime( true );
111 $delta = $now - $this->startTime;
112 $estimatedTotalTime = $delta / $portion;
113 $eta = $this->startTime + $estimatedTotalTime;
114 $rate = $this->processed / $delta;
115
116 $this->output( sprintf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
117 wfTimestamp( TS_DB, intval( $now ) ),
118 $portion * 100.0,
119 $this->table,
120 wfTimestamp( TS_DB, intval( $eta ) ),
121 $this->processed,
122 $this->count,
123 $rate,
124 $updateRate * 100.0 ) );
125 flush();
126 }
127
128 function buildTable( $table, $key, $queryInfo, $callback ) {
129 $count = $this->dbw->selectField( $table, 'count(*)', '', __METHOD__ );
130 $this->init( $count, $table );
131 $this->output( "Processing $table...\n" );
132
133 $result = $this->getDB( DB_REPLICA )->select(
134 $queryInfo['tables'], $queryInfo['fields'], [], __METHOD__, [], $queryInfo['joins']
135 );
136
137 foreach ( $result as $row ) {
138 $update = call_user_func( $callback, $row, null );
139 if ( $update ) {
140 $this->progress( 1 );
141 } else {
142 $this->progress( 0 );
143 }
144 }
145 $this->output( "Finished $table... $this->updated of $this->processed rows updated\n" );
146 }
147
148 function buildImage() {
149 $callback = [ $this, 'imageCallback' ];
150 $this->buildTable( 'image', 'img_name', LocalFile::getQueryInfo(), $callback );
151 }
152
153 function imageCallback( $row, $copy ) {
154 // Create a File object from the row
155 // This will also upgrade it
156 $file = $this->getRepo()->newFileFromRow( $row );
157
158 return $file->getUpgraded();
159 }
160
161 function buildOldImage() {
162 $this->buildTable( 'oldimage', 'oi_archive_name', OldLocalFile::getQueryInfo(),
163 [ $this, 'oldimageCallback' ] );
164 }
165
166 function oldimageCallback( $row, $copy ) {
167 // Create a File object from the row
168 // This will also upgrade it
169 if ( $row->oi_archive_name == '' ) {
170 $this->output( "Empty oi_archive_name for oi_name={$row->oi_name}\n" );
171
172 return false;
173 }
174 $file = $this->getRepo()->newFileFromRow( $row );
175
176 return $file->getUpgraded();
177 }
178
179 function crawlMissing() {
180 $this->getRepo()->enumFiles( [ $this, 'checkMissingImage' ] );
181 }
182
183 function checkMissingImage( $fullpath ) {
184 $filename = wfBaseName( $fullpath );
185 $row = $this->dbw->selectRow( 'image',
186 [ 'img_name' ],
187 [ 'img_name' => $filename ],
188 __METHOD__ );
189
190 if ( !$row ) { // file not registered
191 $this->addMissingImage( $filename, $fullpath );
192 }
193 }
194
195 function addMissingImage( $filename, $fullpath ) {
196 global $wgContLang;
197
198 $timestamp = $this->dbw->timestamp( $this->getRepo()->getFileTimestamp( $fullpath ) );
199
200 $altname = $wgContLang->checkTitleEncoding( $filename );
201 if ( $altname != $filename ) {
202 if ( $this->dryrun ) {
203 $filename = $altname;
204 $this->output( "Estimating transcoding... $altname\n" );
205 } else {
206 # @todo FIXME: create renameFile()
207 $filename = $this->renameFile( $filename );
208 }
209 }
210
211 if ( $filename == '' ) {
212 $this->output( "Empty filename for $fullpath\n" );
213
214 return;
215 }
216 if ( !$this->dryrun ) {
217 $file = wfLocalFile( $filename );
218 if ( !$file->recordUpload(
219 '',
220 '(recovered file, missing upload log entry)',
221 '',
222 '',
223 '',
224 false,
225 $timestamp
226 ) ) {
227 $this->output( "Error uploading file $fullpath\n" );
228
229 return;
230 }
231 }
232 $this->output( $fullpath . "\n" );
233 }
234}
235
236$maintClass = ImageBuilder::class;
237require_once RUN_MAINTENANCE_IF_MAIN;
$wgUpdateCompatibleMetadata
If to automatically update the img_metadata field if the metadata field is outdated but compatible wi...
wfBaseName( $path, $suffix='')
Return the final portion of a pathname.
wfLocalFile( $title)
Get an object referring to a locally registered file.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Maintenance script to update image metadata records.
__construct()
Default constructor.
buildTable( $table, $key, $queryInfo, $callback)
oldimageCallback( $row, $copy)
checkMissingImage( $fullpath)
IMaintainableDatabase $dbw
imageCallback( $row, $copy)
progress( $updated)
execute()
Do the actual work.
init( $count, $table)
addMissingImage( $filename, $fullpath)
static getQueryInfo(array $options=[])
Return the tables, fields, and join conditions to be selected to create a new localfile object.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
getDB( $db, $groups=[], $wiki=false)
Returns a database to be used by current maintenance script.
hasOption( $name)
Checks to see if a particular param exists.
addDescription( $text)
Set the description text.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
static getQueryInfo(array $options=[])
Return the tables, fields, and join conditions to be selected to create a new oldlocalfile object.
static singleton()
Get a RepoGroup instance.
Definition RepoGroup.php:59
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global then executing the whole list after the page is displayed We don t do anything smart like collating updates to the same table or such because the list is almost always going to have just one item on if so it s not worth the trouble Since there is a job queue in the jobs table
Definition deferred.txt:16
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any and then calling output() to send it all. It could be easily changed to send incrementally if that becomes useful
Advanced database interface for IDatabase handles that include maintenance methods.
require_once RUN_MAINTENANCE_IF_MAIN
const DB_REPLICA
Definition defines.php:25
const DB_MASTER
Definition defines.php:29
$maintClass