These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Old file in the oldimage table. |
||
4 | * |
||
5 | * This program is free software; you can redistribute it and/or modify |
||
6 | * it under the terms of the GNU General Public License as published by |
||
7 | * the Free Software Foundation; either version 2 of the License, or |
||
8 | * (at your option) any later version. |
||
9 | * |
||
10 | * This program is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | * GNU General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU General Public License along |
||
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
18 | * http://www.gnu.org/copyleft/gpl.html |
||
19 | * |
||
20 | * @file |
||
21 | * @ingroup FileAbstraction |
||
22 | */ |
||
23 | |||
24 | /** |
||
25 | * Class to represent a file in the oldimage table |
||
26 | * |
||
27 | * @ingroup FileAbstraction |
||
28 | */ |
||
29 | class OldLocalFile extends LocalFile { |
||
30 | /** @var string Timestamp */ |
||
31 | protected $requestedTime; |
||
32 | |||
33 | /** @var string Archive name */ |
||
34 | protected $archive_name; |
||
35 | |||
36 | const CACHE_VERSION = 1; |
||
37 | const MAX_CACHE_ROWS = 20; |
||
38 | |||
39 | /** |
||
40 | * @param Title $title |
||
41 | * @param FileRepo $repo |
||
42 | * @param null|int $time Timestamp or null |
||
43 | * @return OldLocalFile |
||
44 | * @throws MWException |
||
45 | */ |
||
46 | static function newFromTitle( $title, $repo, $time = null ) { |
||
47 | # The null default value is only here to avoid an E_STRICT |
||
48 | if ( $time === null ) { |
||
49 | throw new MWException( __METHOD__ . ' got null for $time parameter' ); |
||
50 | } |
||
51 | |||
52 | return new self( $title, $repo, $time, null ); |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * @param Title $title |
||
57 | * @param FileRepo $repo |
||
58 | * @param string $archiveName |
||
59 | * @return OldLocalFile |
||
60 | */ |
||
61 | static function newFromArchiveName( $title, $repo, $archiveName ) { |
||
62 | return new self( $title, $repo, null, $archiveName ); |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * @param stdClass $row |
||
67 | * @param FileRepo $repo |
||
68 | * @return OldLocalFile |
||
69 | */ |
||
70 | static function newFromRow( $row, $repo ) { |
||
71 | $title = Title::makeTitle( NS_FILE, $row->oi_name ); |
||
72 | $file = new self( $title, $repo, null, $row->oi_archive_name ); |
||
73 | $file->loadFromRow( $row, 'oi_' ); |
||
74 | |||
75 | return $file; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Create a OldLocalFile from a SHA-1 key |
||
80 | * Do not call this except from inside a repo class. |
||
81 | * |
||
82 | * @param string $sha1 Base-36 SHA-1 |
||
83 | * @param LocalRepo $repo |
||
84 | * @param string|bool $timestamp MW_timestamp (optional) |
||
85 | * |
||
86 | * @return bool|OldLocalFile |
||
87 | */ |
||
88 | View Code Duplication | static function newFromKey( $sha1, $repo, $timestamp = false ) { |
|
89 | $dbr = $repo->getSlaveDB(); |
||
90 | |||
91 | $conds = [ 'oi_sha1' => $sha1 ]; |
||
92 | if ( $timestamp ) { |
||
93 | $conds['oi_timestamp'] = $dbr->timestamp( $timestamp ); |
||
94 | } |
||
95 | |||
96 | $row = $dbr->selectRow( 'oldimage', self::selectFields(), $conds, __METHOD__ ); |
||
97 | if ( $row ) { |
||
98 | return self::newFromRow( $row, $repo ); |
||
99 | } else { |
||
100 | return false; |
||
101 | } |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Fields in the oldimage table |
||
106 | * @return array |
||
107 | */ |
||
108 | static function selectFields() { |
||
109 | return [ |
||
110 | 'oi_name', |
||
111 | 'oi_archive_name', |
||
112 | 'oi_size', |
||
113 | 'oi_width', |
||
114 | 'oi_height', |
||
115 | 'oi_metadata', |
||
116 | 'oi_bits', |
||
117 | 'oi_media_type', |
||
118 | 'oi_major_mime', |
||
119 | 'oi_minor_mime', |
||
120 | 'oi_description', |
||
121 | 'oi_user', |
||
122 | 'oi_user_text', |
||
123 | 'oi_timestamp', |
||
124 | 'oi_deleted', |
||
125 | 'oi_sha1', |
||
126 | ]; |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * @param Title $title |
||
131 | * @param FileRepo $repo |
||
132 | * @param string $time Timestamp or null to load by archive name |
||
133 | * @param string $archiveName Archive name or null to load by timestamp |
||
134 | * @throws MWException |
||
135 | */ |
||
136 | function __construct( $title, $repo, $time, $archiveName ) { |
||
137 | parent::__construct( $title, $repo ); |
||
138 | $this->requestedTime = $time; |
||
139 | $this->archive_name = $archiveName; |
||
140 | if ( is_null( $time ) && is_null( $archiveName ) ) { |
||
141 | throw new MWException( __METHOD__ . ': must specify at least one of $time or $archiveName' ); |
||
142 | } |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * @return bool |
||
147 | */ |
||
148 | function getCacheKey() { |
||
149 | return false; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * @return string |
||
154 | */ |
||
155 | function getArchiveName() { |
||
156 | if ( !isset( $this->archive_name ) ) { |
||
157 | $this->load(); |
||
158 | } |
||
159 | |||
160 | return $this->archive_name; |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * @return bool |
||
165 | */ |
||
166 | function isOld() { |
||
167 | return true; |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * @return bool |
||
172 | */ |
||
173 | function isVisible() { |
||
174 | return $this->exists() && !$this->isDeleted( File::DELETED_FILE ); |
||
175 | } |
||
176 | |||
177 | function loadFromDB( $flags = 0 ) { |
||
178 | $this->dataLoaded = true; |
||
179 | |||
180 | $dbr = ( $flags & self::READ_LATEST ) |
||
181 | ? $this->repo->getMasterDB() |
||
182 | : $this->repo->getSlaveDB(); |
||
183 | |||
184 | $conds = [ 'oi_name' => $this->getName() ]; |
||
185 | View Code Duplication | if ( is_null( $this->requestedTime ) ) { |
|
186 | $conds['oi_archive_name'] = $this->archive_name; |
||
187 | } else { |
||
188 | $conds['oi_timestamp'] = $dbr->timestamp( $this->requestedTime ); |
||
189 | } |
||
190 | $row = $dbr->selectRow( 'oldimage', $this->getCacheFields( 'oi_' ), |
||
191 | $conds, __METHOD__, [ 'ORDER BY' => 'oi_timestamp DESC' ] ); |
||
192 | if ( $row ) { |
||
193 | $this->loadFromRow( $row, 'oi_' ); |
||
194 | } else { |
||
195 | $this->fileExists = false; |
||
196 | } |
||
197 | |||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Load lazy file metadata from the DB |
||
202 | */ |
||
203 | protected function loadExtraFromDB() { |
||
204 | |||
205 | $this->extraDataLoaded = true; |
||
206 | $dbr = $this->repo->getSlaveDB(); |
||
207 | $conds = [ 'oi_name' => $this->getName() ]; |
||
208 | View Code Duplication | if ( is_null( $this->requestedTime ) ) { |
|
209 | $conds['oi_archive_name'] = $this->archive_name; |
||
210 | } else { |
||
211 | $conds['oi_timestamp'] = $dbr->timestamp( $this->requestedTime ); |
||
212 | } |
||
213 | // In theory the file could have just been renamed/deleted...oh well |
||
214 | $row = $dbr->selectRow( 'oldimage', $this->getLazyCacheFields( 'oi_' ), |
||
215 | $conds, __METHOD__, [ 'ORDER BY' => 'oi_timestamp DESC' ] ); |
||
216 | |||
217 | if ( !$row ) { // fallback to master |
||
218 | $dbr = $this->repo->getMasterDB(); |
||
219 | $row = $dbr->selectRow( 'oldimage', $this->getLazyCacheFields( 'oi_' ), |
||
220 | $conds, __METHOD__, [ 'ORDER BY' => 'oi_timestamp DESC' ] ); |
||
221 | } |
||
222 | |||
223 | if ( $row ) { |
||
224 | foreach ( $this->unprefixRow( $row, 'oi_' ) as $name => $value ) { |
||
225 | $this->$name = $value; |
||
226 | } |
||
227 | } else { |
||
228 | throw new MWException( "Could not find data for image '{$this->archive_name}'." ); |
||
229 | } |
||
230 | |||
231 | } |
||
232 | |||
233 | /** |
||
234 | * @param string $prefix |
||
235 | * @return array |
||
236 | */ |
||
237 | function getCacheFields( $prefix = 'img_' ) { |
||
238 | $fields = parent::getCacheFields( $prefix ); |
||
239 | $fields[] = $prefix . 'archive_name'; |
||
240 | $fields[] = $prefix . 'deleted'; |
||
241 | |||
242 | return $fields; |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * @return string |
||
247 | */ |
||
248 | function getRel() { |
||
249 | return 'archive/' . $this->getHashPath() . $this->getArchiveName(); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * @return string |
||
254 | */ |
||
255 | function getUrlRel() { |
||
256 | return 'archive/' . $this->getHashPath() . rawurlencode( $this->getArchiveName() ); |
||
257 | } |
||
258 | |||
259 | function upgradeRow() { |
||
260 | $this->loadFromFile(); |
||
261 | |||
262 | # Don't destroy file info of missing files |
||
263 | if ( !$this->fileExists ) { |
||
264 | wfDebug( __METHOD__ . ": file does not exist, aborting\n" ); |
||
265 | |||
266 | return; |
||
267 | } |
||
268 | |||
269 | $dbw = $this->repo->getMasterDB(); |
||
270 | list( $major, $minor ) = self::splitMime( $this->mime ); |
||
271 | |||
272 | wfDebug( __METHOD__ . ': upgrading ' . $this->archive_name . " to the current schema\n" ); |
||
273 | $dbw->update( 'oldimage', |
||
274 | [ |
||
275 | 'oi_size' => $this->size, // sanity |
||
276 | 'oi_width' => $this->width, |
||
277 | 'oi_height' => $this->height, |
||
278 | 'oi_bits' => $this->bits, |
||
279 | 'oi_media_type' => $this->media_type, |
||
280 | 'oi_major_mime' => $major, |
||
281 | 'oi_minor_mime' => $minor, |
||
282 | 'oi_metadata' => $this->metadata, |
||
283 | 'oi_sha1' => $this->sha1, |
||
284 | ], [ |
||
285 | 'oi_name' => $this->getName(), |
||
286 | 'oi_archive_name' => $this->archive_name ], |
||
287 | __METHOD__ |
||
288 | ); |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * @param int $field One of DELETED_* bitfield constants for file or |
||
293 | * revision rows |
||
294 | * @return bool |
||
295 | */ |
||
296 | function isDeleted( $field ) { |
||
297 | $this->load(); |
||
298 | |||
299 | return ( $this->deleted & $field ) == $field; |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | * Returns bitfield value |
||
304 | * @return int |
||
305 | */ |
||
306 | function getVisibility() { |
||
307 | $this->load(); |
||
308 | |||
309 | return (int)$this->deleted; |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * Determine if the current user is allowed to view a particular |
||
314 | * field of this image file, if it's marked as deleted. |
||
315 | * |
||
316 | * @param int $field |
||
317 | * @param User|null $user User object to check, or null to use $wgUser |
||
318 | * @return bool |
||
319 | */ |
||
320 | function userCan( $field, User $user = null ) { |
||
321 | $this->load(); |
||
322 | |||
323 | return Revision::userCanBitfield( $this->deleted, $field, $user ); |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Upload a file directly into archive. Generally for Special:Import. |
||
328 | * |
||
329 | * @param string $srcPath File system path of the source file |
||
330 | * @param string $archiveName Full archive name of the file, in the form |
||
331 | * $timestamp!$filename, where $filename must match $this->getName() |
||
332 | * @param string $timestamp |
||
333 | * @param string $comment |
||
334 | * @param User $user |
||
335 | * @return Status |
||
336 | */ |
||
337 | function uploadOld( $srcPath, $archiveName, $timestamp, $comment, $user ) { |
||
338 | $this->lock(); |
||
339 | |||
340 | $dstRel = 'archive/' . $this->getHashPath() . $archiveName; |
||
341 | $status = $this->publishTo( $srcPath, $dstRel ); |
||
342 | |||
343 | if ( $status->isGood() ) { |
||
344 | if ( !$this->recordOldUpload( $srcPath, $archiveName, $timestamp, $comment, $user ) ) { |
||
345 | $status->fatal( 'filenotfound', $srcPath ); |
||
346 | } |
||
347 | } |
||
348 | |||
349 | $this->unlock(); |
||
350 | |||
351 | return $status; |
||
352 | } |
||
353 | |||
354 | /** |
||
355 | * Record a file upload in the oldimage table, without adding log entries. |
||
356 | * |
||
357 | * @param string $srcPath File system path to the source file |
||
358 | * @param string $archiveName The archive name of the file |
||
359 | * @param string $timestamp |
||
360 | * @param string $comment Upload comment |
||
361 | * @param User $user User who did this upload |
||
362 | * @return bool |
||
363 | */ |
||
364 | protected function recordOldUpload( $srcPath, $archiveName, $timestamp, $comment, $user ) { |
||
365 | $dbw = $this->repo->getMasterDB(); |
||
0 ignored issues
–
show
|
|||
366 | |||
367 | $dstPath = $this->repo->getZonePath( 'public' ) . '/' . $this->getRel(); |
||
368 | $props = $this->repo->getFileProps( $dstPath ); |
||
369 | if ( !$props['fileExists'] ) { |
||
370 | return false; |
||
371 | } |
||
372 | |||
373 | $dbw->insert( 'oldimage', |
||
374 | [ |
||
375 | 'oi_name' => $this->getName(), |
||
376 | 'oi_archive_name' => $archiveName, |
||
377 | 'oi_size' => $props['size'], |
||
378 | 'oi_width' => intval( $props['width'] ), |
||
379 | 'oi_height' => intval( $props['height'] ), |
||
380 | 'oi_bits' => $props['bits'], |
||
381 | 'oi_timestamp' => $dbw->timestamp( $timestamp ), |
||
382 | 'oi_description' => $comment, |
||
383 | 'oi_user' => $user->getId(), |
||
384 | 'oi_user_text' => $user->getName(), |
||
385 | 'oi_metadata' => $props['metadata'], |
||
386 | 'oi_media_type' => $props['media_type'], |
||
387 | 'oi_major_mime' => $props['major_mime'], |
||
388 | 'oi_minor_mime' => $props['minor_mime'], |
||
389 | 'oi_sha1' => $props['sha1'], |
||
390 | ], __METHOD__ |
||
391 | ); |
||
392 | |||
393 | return true; |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * If archive name is an empty string, then file does not "exist" |
||
398 | * |
||
399 | * This is the case for a couple files on Wikimedia servers where |
||
400 | * the old version is "lost". |
||
401 | */ |
||
402 | public function exists() { |
||
403 | $archiveName = $this->getArchiveName(); |
||
404 | if ( $archiveName === '' || !is_string( $archiveName ) ) { |
||
405 | return false; |
||
406 | } |
||
407 | return parent::exists(); |
||
408 | } |
||
409 | } |
||
410 |
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: