Completed
Branch master (939199)
by
unknown
39:35
created

includes/filerepo/file/ArchivedFile.php (1 issue)

assigning incompatible types to properties.

Bug Documentation Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Deleted file in the 'filearchive' 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 representing a row of the 'filearchive' table
26
 *
27
 * @ingroup FileAbstraction
28
 */
29
class ArchivedFile {
30
	/** @var int Filearchive row ID */
31
	private $id;
32
33
	/** @var string File name */
34
	private $name;
35
36
	/** @var string FileStore storage group */
37
	private $group;
38
39
	/** @var string FileStore SHA-1 key */
40
	private $key;
41
42
	/** @var int File size in bytes */
43
	private $size;
44
45
	/** @var int Size in bytes */
46
	private $bits;
47
48
	/** @var int Width */
49
	private $width;
50
51
	/** @var int Height */
52
	private $height;
53
54
	/** @var string Metadata string */
55
	private $metadata;
56
57
	/** @var string MIME type */
58
	private $mime;
59
60
	/** @var string Media type */
61
	private $media_type;
62
63
	/** @var string Upload description */
64
	private $description;
65
66
	/** @var int User ID of uploader */
67
	private $user;
68
69
	/** @var string User name of uploader */
70
	private $user_text;
71
72
	/** @var string Time of upload */
73
	private $timestamp;
74
75
	/** @var bool Whether or not all this has been loaded from the database (loadFromXxx) */
76
	private $dataLoaded;
77
78
	/** @var int Bitfield akin to rev_deleted */
79
	private $deleted;
80
81
	/** @var string SHA-1 hash of file content */
82
	private $sha1;
83
84
	/** @var string Number of pages of a multipage document, or false for
85
	 * documents which aren't multipage documents
86
	 */
87
	private $pageCount;
88
89
	/** @var string Original base filename */
90
	private $archive_name;
91
92
	/** @var MediaHandler */
93
	protected $handler;
94
95
	/** @var Title */
96
	protected $title; # image title
97
98
	/**
99
	 * @throws MWException
100
	 * @param Title $title
101
	 * @param int $id
102
	 * @param string $key
103
	 * @param string $sha1
104
	 */
105
	function __construct( $title, $id = 0, $key = '', $sha1 = '' ) {
106
		$this->id = -1;
107
		$this->title = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type object<Title> of property $title.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
108
		$this->name = false;
109
		$this->group = 'deleted'; // needed for direct use of constructor
110
		$this->key = '';
111
		$this->size = 0;
112
		$this->bits = 0;
113
		$this->width = 0;
114
		$this->height = 0;
115
		$this->metadata = '';
116
		$this->mime = "unknown/unknown";
117
		$this->media_type = '';
118
		$this->description = '';
119
		$this->user = 0;
120
		$this->user_text = '';
121
		$this->timestamp = null;
122
		$this->deleted = 0;
123
		$this->dataLoaded = false;
124
		$this->exists = false;
125
		$this->sha1 = '';
126
127
		if ( $title instanceof Title ) {
128
			$this->title = File::normalizeTitle( $title, 'exception' );
129
			$this->name = $title->getDBkey();
130
		}
131
132
		if ( $id ) {
133
			$this->id = $id;
134
		}
135
136
		if ( $key ) {
137
			$this->key = $key;
138
		}
139
140
		if ( $sha1 ) {
141
			$this->sha1 = $sha1;
142
		}
143
144
		if ( !$id && !$key && !( $title instanceof Title ) && !$sha1 ) {
145
			throw new MWException( "No specifications provided to ArchivedFile constructor." );
146
		}
147
	}
148
149
	/**
150
	 * Loads a file object from the filearchive table
151
	 * @throws MWException
152
	 * @return bool|null True on success or null
153
	 */
154
	public function load() {
155
		if ( $this->dataLoaded ) {
156
			return true;
157
		}
158
		$conds = [];
159
160
		if ( $this->id > 0 ) {
161
			$conds['fa_id'] = $this->id;
162
		}
163
		if ( $this->key ) {
164
			$conds['fa_storage_group'] = $this->group;
165
			$conds['fa_storage_key'] = $this->key;
166
		}
167
		if ( $this->title ) {
168
			$conds['fa_name'] = $this->title->getDBkey();
169
		}
170
		if ( $this->sha1 ) {
171
			$conds['fa_sha1'] = $this->sha1;
172
		}
173
174
		if ( !count( $conds ) ) {
175
			throw new MWException( "No specific information for retrieving archived file" );
176
		}
177
178
		if ( !$this->title || $this->title->getNamespace() == NS_FILE ) {
179
			$this->dataLoaded = true; // set it here, to have also true on miss
180
			$dbr = wfGetDB( DB_REPLICA );
181
			$row = $dbr->selectRow(
182
				'filearchive',
183
				self::selectFields(),
184
				$conds,
185
				__METHOD__,
186
				[ 'ORDER BY' => 'fa_timestamp DESC' ]
187
			);
188
			if ( !$row ) {
189
				// this revision does not exist?
190
				return null;
191
			}
192
193
			// initialize fields for filestore image object
194
			$this->loadFromRow( $row );
195
		} else {
196
			throw new MWException( 'This title does not correspond to an image page.' );
197
		}
198
		$this->exists = true;
199
200
		return true;
201
	}
202
203
	/**
204
	 * Loads a file object from the filearchive table
205
	 *
206
	 * @param stdClass $row
207
	 * @return ArchivedFile
208
	 */
209
	public static function newFromRow( $row ) {
210
		$file = new ArchivedFile( Title::makeTitle( NS_FILE, $row->fa_name ) );
211
		$file->loadFromRow( $row );
212
213
		return $file;
214
	}
215
216
	/**
217
	 * Fields in the filearchive table
218
	 * @return array
219
	 */
220
	static function selectFields() {
221
		return [
222
			'fa_id',
223
			'fa_name',
224
			'fa_archive_name',
225
			'fa_storage_key',
226
			'fa_storage_group',
227
			'fa_size',
228
			'fa_bits',
229
			'fa_width',
230
			'fa_height',
231
			'fa_metadata',
232
			'fa_media_type',
233
			'fa_major_mime',
234
			'fa_minor_mime',
235
			'fa_description',
236
			'fa_user',
237
			'fa_user_text',
238
			'fa_timestamp',
239
			'fa_deleted',
240
			'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
241
			'fa_sha1',
242
		];
243
	}
244
245
	/**
246
	 * Load ArchivedFile object fields from a DB row.
247
	 *
248
	 * @param stdClass $row Object database row
249
	 * @since 1.21
250
	 */
251
	public function loadFromRow( $row ) {
252
		$this->id = intval( $row->fa_id );
253
		$this->name = $row->fa_name;
254
		$this->archive_name = $row->fa_archive_name;
255
		$this->group = $row->fa_storage_group;
256
		$this->key = $row->fa_storage_key;
257
		$this->size = $row->fa_size;
258
		$this->bits = $row->fa_bits;
259
		$this->width = $row->fa_width;
260
		$this->height = $row->fa_height;
261
		$this->metadata = $row->fa_metadata;
262
		$this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
263
		$this->media_type = $row->fa_media_type;
264
		$this->description = $row->fa_description;
265
		$this->user = $row->fa_user;
266
		$this->user_text = $row->fa_user_text;
267
		$this->timestamp = $row->fa_timestamp;
268
		$this->deleted = $row->fa_deleted;
269
		if ( isset( $row->fa_sha1 ) ) {
270
			$this->sha1 = $row->fa_sha1;
271
		} else {
272
			// old row, populate from key
273
			$this->sha1 = LocalRepo::getHashFromKey( $this->key );
274
		}
275
		if ( !$this->title ) {
276
			$this->title = Title::makeTitleSafe( NS_FILE, $row->fa_name );
277
		}
278
	}
279
280
	/**
281
	 * Return the associated title object
282
	 *
283
	 * @return Title
284
	 */
285
	public function getTitle() {
286
		if ( !$this->title ) {
287
			$this->load();
288
		}
289
		return $this->title;
290
	}
291
292
	/**
293
	 * Return the file name
294
	 *
295
	 * @return string
296
	 */
297
	public function getName() {
298
		if ( $this->name === false ) {
299
			$this->load();
300
		}
301
302
		return $this->name;
303
	}
304
305
	/**
306
	 * @return int
307
	 */
308
	public function getID() {
309
		$this->load();
310
311
		return $this->id;
312
	}
313
314
	/**
315
	 * @return bool
316
	 */
317
	public function exists() {
318
		$this->load();
319
320
		return $this->exists;
321
	}
322
323
	/**
324
	 * Return the FileStore key
325
	 * @return string
326
	 */
327
	public function getKey() {
328
		$this->load();
329
330
		return $this->key;
331
	}
332
333
	/**
334
	 * Return the FileStore key (overriding base File class)
335
	 * @return string
336
	 */
337
	public function getStorageKey() {
338
		return $this->getKey();
339
	}
340
341
	/**
342
	 * Return the FileStore storage group
343
	 * @return string
344
	 */
345
	public function getGroup() {
346
		return $this->group;
347
	}
348
349
	/**
350
	 * Return the width of the image
351
	 * @return int
352
	 */
353
	public function getWidth() {
354
		$this->load();
355
356
		return $this->width;
357
	}
358
359
	/**
360
	 * Return the height of the image
361
	 * @return int
362
	 */
363
	public function getHeight() {
364
		$this->load();
365
366
		return $this->height;
367
	}
368
369
	/**
370
	 * Get handler-specific metadata
371
	 * @return string
372
	 */
373
	public function getMetadata() {
374
		$this->load();
375
376
		return $this->metadata;
377
	}
378
379
	/**
380
	 * Return the size of the image file, in bytes
381
	 * @return int
382
	 */
383
	public function getSize() {
384
		$this->load();
385
386
		return $this->size;
387
	}
388
389
	/**
390
	 * Return the bits of the image file, in bytes
391
	 * @return int
392
	 */
393
	public function getBits() {
394
		$this->load();
395
396
		return $this->bits;
397
	}
398
399
	/**
400
	 * Returns the MIME type of the file.
401
	 * @return string
402
	 */
403
	public function getMimeType() {
404
		$this->load();
405
406
		return $this->mime;
407
	}
408
409
	/**
410
	 * Get a MediaHandler instance for this file
411
	 * @return MediaHandler
412
	 */
413
	function getHandler() {
414
		if ( !isset( $this->handler ) ) {
415
			$this->handler = MediaHandler::getHandler( $this->getMimeType() );
416
		}
417
418
		return $this->handler;
419
	}
420
421
	/**
422
	 * Returns the number of pages of a multipage document, or false for
423
	 * documents which aren't multipage documents
424
	 * @return bool|int
425
	 */
426 View Code Duplication
	function pageCount() {
427
		if ( !isset( $this->pageCount ) ) {
428
			// @FIXME: callers expect File objects
429
			if ( $this->getHandler() && $this->handler->isMultiPage( $this ) ) {
430
				$this->pageCount = $this->handler->pageCount( $this );
431
			} else {
432
				$this->pageCount = false;
433
			}
434
		}
435
436
		return $this->pageCount;
437
	}
438
439
	/**
440
	 * Return the type of the media in the file.
441
	 * Use the value returned by this function with the MEDIATYPE_xxx constants.
442
	 * @return string
443
	 */
444
	public function getMediaType() {
445
		$this->load();
446
447
		return $this->media_type;
448
	}
449
450
	/**
451
	 * Return upload timestamp.
452
	 *
453
	 * @return string
454
	 */
455
	public function getTimestamp() {
456
		$this->load();
457
458
		return wfTimestamp( TS_MW, $this->timestamp );
459
	}
460
461
	/**
462
	 * Get the SHA-1 base 36 hash of the file
463
	 *
464
	 * @return string
465
	 * @since 1.21
466
	 */
467
	function getSha1() {
468
		$this->load();
469
470
		return $this->sha1;
471
	}
472
473
	/**
474
	 * Returns ID or name of user who uploaded the file
475
	 *
476
	 * @note Prior to MediaWiki 1.23, this method always
477
	 *   returned the user id, and was inconsistent with
478
	 *   the rest of the file classes.
479
	 * @param string $type 'text' or 'id'
480
	 * @return int|string
481
	 * @throws MWException
482
	 */
483
	public function getUser( $type = 'text' ) {
484
		$this->load();
485
486
		if ( $type == 'text' ) {
487
			return $this->user_text;
488
		} elseif ( $type == 'id' ) {
489
			return (int)$this->user;
490
		}
491
492
		throw new MWException( "Unknown type '$type'." );
493
	}
494
495
	/**
496
	 * Return the user name of the uploader.
497
	 *
498
	 * @deprecated since 1.23 Use getUser( 'text' ) instead.
499
	 * @return string
500
	 */
501
	public function getUserText() {
502
		wfDeprecated( __METHOD__, '1.23' );
503
		$this->load();
504
		if ( $this->isDeleted( File::DELETED_USER ) ) {
505
			return 0;
506
		} else {
507
			return $this->user_text;
508
		}
509
	}
510
511
	/**
512
	 * Return upload description.
513
	 *
514
	 * @return string
515
	 */
516
	public function getDescription() {
517
		$this->load();
518
		if ( $this->isDeleted( File::DELETED_COMMENT ) ) {
519
			return 0;
520
		} else {
521
			return $this->description;
522
		}
523
	}
524
525
	/**
526
	 * Return the user ID of the uploader.
527
	 *
528
	 * @return int
529
	 */
530
	public function getRawUser() {
531
		$this->load();
532
533
		return $this->user;
534
	}
535
536
	/**
537
	 * Return the user name of the uploader.
538
	 *
539
	 * @return string
540
	 */
541
	public function getRawUserText() {
542
		$this->load();
543
544
		return $this->user_text;
545
	}
546
547
	/**
548
	 * Return upload description.
549
	 *
550
	 * @return string
551
	 */
552
	public function getRawDescription() {
553
		$this->load();
554
555
		return $this->description;
556
	}
557
558
	/**
559
	 * Returns the deletion bitfield
560
	 * @return int
561
	 */
562
	public function getVisibility() {
563
		$this->load();
564
565
		return $this->deleted;
566
	}
567
568
	/**
569
	 * for file or revision rows
570
	 *
571
	 * @param int $field One of DELETED_* bitfield constants
572
	 * @return bool
573
	 */
574
	public function isDeleted( $field ) {
575
		$this->load();
576
577
		return ( $this->deleted & $field ) == $field;
578
	}
579
580
	/**
581
	 * Determine if the current user is allowed to view a particular
582
	 * field of this FileStore image file, if it's marked as deleted.
583
	 * @param int $field
584
	 * @param null|User $user User object to check, or null to use $wgUser
585
	 * @return bool
586
	 */
587
	public function userCan( $field, User $user = null ) {
588
		$this->load();
589
590
		$title = $this->getTitle();
591
		return Revision::userCanBitfield( $this->deleted, $field, $user, $title ?: null );
592
	}
593
}
594