3 * Deleted file in the 'filearchive' table.
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.
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.
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
21 * @ingroup FileAbstraction
25 * Class representing a row of the 'filearchive' table
27 * @ingroup FileAbstraction
30 /** @var int Filearchive row ID */
33 /** @var string File name */
36 /** @var string FileStore storage group */
39 /** @var string FileStore SHA-1 key */
42 /** @var int File size in bytes */
45 /** @var int Size in bytes */
51 /** @var int Height */
54 /** @var string Metadata string */
57 /** @var string MIME type */
60 /** @var string Media type */
63 /** @var string Upload description */
66 /** @var int User ID of uploader */
69 /** @var string User name of uploader */
72 /** @var string Time of upload */
75 /** @var bool Whether or not all this has been loaded from the database (loadFromXxx) */
78 /** @var int Bitfield akin to rev_deleted */
81 /** @var string SHA-1 hash of file content */
84 /** @var int|false Number of pages of a multipage document, or false for
85 * documents which aren't multipage documents
89 /** @var string Original base filename */
90 private $archive_name;
92 /** @var MediaHandler */
96 protected $title; # image title
100 * @param Title $title
103 * @param string $sha1
105 function __construct( $title, $id = 0, $key = '', $sha1 = '' ) {
107 $this->title = false;
109 $this->group = 'deleted'; // needed for direct use of constructor
115 $this->metadata = '';
116 $this->mime = "unknown/unknown";
117 $this->media_type = '';
118 $this->description = '';
120 $this->user_text = '';
121 $this->timestamp = null;
123 $this->dataLoaded = false;
124 $this->exists = false;
127 if ( $title instanceof Title ) {
128 $this->title = File::normalizeTitle( $title, 'exception' );
129 $this->name = $title->getDBkey();
144 if ( !$id && !$key && !( $title instanceof Title ) && !$sha1 ) {
145 throw new MWException( "No specifications provided to ArchivedFile constructor." );
150 * Loads a file object from the filearchive table
151 * @throws MWException
152 * @return bool|null True on success or null
154 public function load() {
155 if ( $this->dataLoaded ) {
160 if ( $this->id > 0 ) {
161 $conds['fa_id'] = $this->id;
164 $conds['fa_storage_group'] = $this->group;
165 $conds['fa_storage_key'] = $this->key;
167 if ( $this->title ) {
168 $conds['fa_name'] = $this->title->getDBkey();
171 $conds['fa_sha1'] = $this->sha1;
174 if ( !count( $conds ) ) {
175 throw new MWException( "No specific information for retrieving archived file" );
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(
183 self::selectFields(),
186 [ 'ORDER BY' => 'fa_timestamp DESC' ]
189 // this revision does not exist?
193 // initialize fields for filestore image object
194 $this->loadFromRow( $row );
196 throw new MWException( 'This title does not correspond to an image page.' );
198 $this->exists = true;
204 * Loads a file object from the filearchive table
206 * @param stdClass $row
207 * @return ArchivedFile
209 public static function newFromRow( $row ) {
210 $file = new ArchivedFile( Title::makeTitle( NS_FILE, $row->fa_name ) );
211 $file->loadFromRow( $row );
217 * Fields in the filearchive table
218 * @todo Deprecate this in favor of a method that returns tables and joins
219 * as well, and use CommentStore::getJoin().
222 static function selectFields() {
241 'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
243 ] + CommentStore::newKey( 'fa_description' )->getFields();
247 * Load ArchivedFile object fields from a DB row.
249 * @param stdClass $row Object database row
252 public function loadFromRow( $row ) {
253 $this->id = intval( $row->fa_id );
254 $this->name = $row->fa_name;
255 $this->archive_name = $row->fa_archive_name;
256 $this->group = $row->fa_storage_group;
257 $this->key = $row->fa_storage_key;
258 $this->size = $row->fa_size;
259 $this->bits = $row->fa_bits;
260 $this->width = $row->fa_width;
261 $this->height = $row->fa_height;
262 $this->metadata = $row->fa_metadata;
263 $this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
264 $this->media_type = $row->fa_media_type;
265 $this->description = CommentStore::newKey( 'fa_description' )
266 // Legacy because $row probably came from self::selectFields()
267 ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row )->text;
268 $this->user = $row->fa_user;
269 $this->user_text = $row->fa_user_text;
270 $this->timestamp = $row->fa_timestamp;
271 $this->deleted = $row->fa_deleted;
272 if ( isset( $row->fa_sha1 ) ) {
273 $this->sha1 = $row->fa_sha1;
275 // old row, populate from key
276 $this->sha1 = LocalRepo::getHashFromKey( $this->key );
278 if ( !$this->title ) {
279 $this->title = Title::makeTitleSafe( NS_FILE, $row->fa_name );
284 * Return the associated title object
288 public function getTitle() {
289 if ( !$this->title ) {
296 * Return the file name
300 public function getName() {
301 if ( $this->name === false ) {
311 public function getID() {
320 public function exists() {
323 return $this->exists;
327 * Return the FileStore key
330 public function getKey() {
337 * Return the FileStore key (overriding base File class)
340 public function getStorageKey() {
341 return $this->getKey();
345 * Return the FileStore storage group
348 public function getGroup() {
353 * Return the width of the image
356 public function getWidth() {
363 * Return the height of the image
366 public function getHeight() {
369 return $this->height;
373 * Get handler-specific metadata
376 public function getMetadata() {
379 return $this->metadata;
383 * Return the size of the image file, in bytes
386 public function getSize() {
393 * Return the bits of the image file, in bytes
396 public function getBits() {
403 * Returns the MIME type of the file.
406 public function getMimeType() {
413 * Get a MediaHandler instance for this file
414 * @return MediaHandler
416 function getHandler() {
417 if ( !isset( $this->handler ) ) {
418 $this->handler = MediaHandler::getHandler( $this->getMimeType() );
421 return $this->handler;
425 * Returns the number of pages of a multipage document, or false for
426 * documents which aren't multipage documents
429 function pageCount() {
430 if ( !isset( $this->pageCount ) ) {
431 // @FIXME: callers expect File objects
432 if ( $this->getHandler() && $this->handler->isMultiPage( $this ) ) {
433 $this->pageCount = $this->handler->pageCount( $this );
435 $this->pageCount = false;
439 return $this->pageCount;
443 * Return the type of the media in the file.
444 * Use the value returned by this function with the MEDIATYPE_xxx constants.
447 public function getMediaType() {
450 return $this->media_type;
454 * Return upload timestamp.
458 public function getTimestamp() {
461 return wfTimestamp( TS_MW, $this->timestamp );
465 * Get the SHA-1 base 36 hash of the file
477 * Returns ID or name of user who uploaded the file
479 * @note Prior to MediaWiki 1.23, this method always
480 * returned the user id, and was inconsistent with
481 * the rest of the file classes.
482 * @param string $type 'text' or 'id'
484 * @throws MWException
486 public function getUser( $type = 'text' ) {
489 if ( $type == 'text' ) {
490 return $this->user_text;
491 } elseif ( $type == 'id' ) {
492 return (int)$this->user;
495 throw new MWException( "Unknown type '$type'." );
499 * Return upload description.
503 public function getDescription() {
505 if ( $this->isDeleted( File::DELETED_COMMENT ) ) {
508 return $this->description;
513 * Return the user ID of the uploader.
517 public function getRawUser() {
524 * Return the user name of the uploader.
528 public function getRawUserText() {
531 return $this->user_text;
535 * Return upload description.
539 public function getRawDescription() {
542 return $this->description;
546 * Returns the deletion bitfield
549 public function getVisibility() {
552 return $this->deleted;
556 * for file or revision rows
558 * @param int $field One of DELETED_* bitfield constants
561 public function isDeleted( $field ) {
564 return ( $this->deleted & $field ) == $field;
568 * Determine if the current user is allowed to view a particular
569 * field of this FileStore image file, if it's marked as deleted.
571 * @param null|User $user User object to check, or null to use $wgUser
574 public function userCan( $field, User $user = null ) {
577 $title = $this->getTitle();
578 return Revision::userCanBitfield( $this->deleted, $field, $user, $title ?: null );