5d72c0cf1a461b50aa63f59205bedf81caa3755e
[lhc/web/wiklou.git] / includes / filerepo / file / ArchivedFile.php
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 /**#@+
31 * @private
32 */
33 var $id, # filearchive row ID
34 $name, # image name
35 $group, # FileStore storage group
36 $key, # FileStore sha1 key
37 $size, # file dimensions
38 $bits, # size in bytes
39 $width, # width
40 $height, # height
41 $metadata, # metadata string
42 $mime, # mime type
43 $media_type, # media type
44 $description, # upload description
45 $user, # user ID of uploader
46 $user_text, # user name of uploader
47 $timestamp, # time of upload
48 $dataLoaded, # Whether or not all this has been loaded from the database (loadFromXxx)
49 $deleted, # Bitfield akin to rev_deleted
50 $sha1, # sha1 hash of file content
51 $pageCount,
52 $archive_name;
53
54 /**
55 * @var MediaHandler
56 */
57 var $handler;
58 /**
59 * @var Title
60 */
61 var $title; # image title
62
63 /**#@-*/
64
65 /**
66 * @throws MWException
67 * @param Title $title
68 * @param int $id
69 * @param string $key
70 */
71 function __construct( $title, $id = 0, $key = '' ) {
72 $this->id = -1;
73 $this->title = false;
74 $this->name = false;
75 $this->group = 'deleted'; // needed for direct use of constructor
76 $this->key = '';
77 $this->size = 0;
78 $this->bits = 0;
79 $this->width = 0;
80 $this->height = 0;
81 $this->metadata = '';
82 $this->mime = "unknown/unknown";
83 $this->media_type = '';
84 $this->description = '';
85 $this->user = 0;
86 $this->user_text = '';
87 $this->timestamp = null;
88 $this->deleted = 0;
89 $this->dataLoaded = false;
90 $this->exists = false;
91 $this->sha1 = '';
92
93 if ( $title instanceof Title ) {
94 $this->title = File::normalizeTitle( $title, 'exception' );
95 $this->name = $title->getDBkey();
96 }
97
98 if ( $id ) {
99 $this->id = $id;
100 }
101
102 if ( $key ) {
103 $this->key = $key;
104 }
105
106 if ( !$id && !$key && !( $title instanceof Title ) ) {
107 throw new MWException( "No specifications provided to ArchivedFile constructor." );
108 }
109 }
110
111 /**
112 * Loads a file object from the filearchive table
113 * @throws MWException
114 * @return bool|null True on success or null
115 */
116 public function load() {
117 if ( $this->dataLoaded ) {
118 return true;
119 }
120 $conds = array();
121
122 if ( $this->id > 0 ) {
123 $conds['fa_id'] = $this->id;
124 }
125 if ( $this->key ) {
126 $conds['fa_storage_group'] = $this->group;
127 $conds['fa_storage_key'] = $this->key;
128 }
129 if ( $this->title ) {
130 $conds['fa_name'] = $this->title->getDBkey();
131 }
132
133 if ( !count( $conds ) ) {
134 throw new MWException( "No specific information for retrieving archived file" );
135 }
136
137 if ( !$this->title || $this->title->getNamespace() == NS_FILE ) {
138 $this->dataLoaded = true; // set it here, to have also true on miss
139 $dbr = wfGetDB( DB_SLAVE );
140 $row = $dbr->selectRow(
141 'filearchive',
142 self::selectFields(),
143 $conds,
144 __METHOD__,
145 array( 'ORDER BY' => 'fa_timestamp DESC' )
146 );
147 if ( !$row ) {
148 // this revision does not exist?
149 return null;
150 }
151
152 // initialize fields for filestore image object
153 $this->loadFromRow( $row );
154 } else {
155 throw new MWException( 'This title does not correspond to an image page.' );
156 }
157 $this->exists = true;
158
159 return true;
160 }
161
162 /**
163 * Loads a file object from the filearchive table
164 *
165 * @param $row
166 *
167 * @return ArchivedFile
168 */
169 public static function newFromRow( $row ) {
170 $file = new ArchivedFile( Title::makeTitle( NS_FILE, $row->fa_name ) );
171 $file->loadFromRow( $row );
172
173 return $file;
174 }
175
176 /**
177 * Fields in the filearchive table
178 * @return array
179 */
180 static function selectFields() {
181 return array(
182 'fa_id',
183 'fa_name',
184 'fa_archive_name',
185 'fa_storage_key',
186 'fa_storage_group',
187 'fa_size',
188 'fa_bits',
189 'fa_width',
190 'fa_height',
191 'fa_metadata',
192 'fa_media_type',
193 'fa_major_mime',
194 'fa_minor_mime',
195 'fa_description',
196 'fa_user',
197 'fa_user_text',
198 'fa_timestamp',
199 'fa_deleted',
200 'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
201 'fa_sha1',
202 );
203 }
204
205 /**
206 * Load ArchivedFile object fields from a DB row.
207 *
208 * @param $row Object database row
209 * @since 1.21
210 */
211 public function loadFromRow( $row ) {
212 $this->id = intval( $row->fa_id );
213 $this->name = $row->fa_name;
214 $this->archive_name = $row->fa_archive_name;
215 $this->group = $row->fa_storage_group;
216 $this->key = $row->fa_storage_key;
217 $this->size = $row->fa_size;
218 $this->bits = $row->fa_bits;
219 $this->width = $row->fa_width;
220 $this->height = $row->fa_height;
221 $this->metadata = $row->fa_metadata;
222 $this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
223 $this->media_type = $row->fa_media_type;
224 $this->description = $row->fa_description;
225 $this->user = $row->fa_user;
226 $this->user_text = $row->fa_user_text;
227 $this->timestamp = $row->fa_timestamp;
228 $this->deleted = $row->fa_deleted;
229 if ( isset( $row->fa_sha1 ) ) {
230 $this->sha1 = $row->fa_sha1;
231 } else {
232 // old row, populate from key
233 $this->sha1 = LocalRepo::getHashFromKey( $this->key );
234 }
235 }
236
237 /**
238 * Return the associated title object
239 *
240 * @return Title
241 */
242 public function getTitle() {
243 return $this->title;
244 }
245
246 /**
247 * Return the file name
248 *
249 * @return string
250 */
251 public function getName() {
252 return $this->name;
253 }
254
255 /**
256 * @return int
257 */
258 public function getID() {
259 $this->load();
260
261 return $this->id;
262 }
263
264 /**
265 * @return bool
266 */
267 public function exists() {
268 $this->load();
269
270 return $this->exists;
271 }
272
273 /**
274 * Return the FileStore key
275 * @return string
276 */
277 public function getKey() {
278 $this->load();
279
280 return $this->key;
281 }
282
283 /**
284 * Return the FileStore key (overriding base File class)
285 * @return string
286 */
287 public function getStorageKey() {
288 return $this->getKey();
289 }
290
291 /**
292 * Return the FileStore storage group
293 * @return string
294 */
295 public function getGroup() {
296 return $this->group;
297 }
298
299 /**
300 * Return the width of the image
301 * @return int
302 */
303 public function getWidth() {
304 $this->load();
305
306 return $this->width;
307 }
308
309 /**
310 * Return the height of the image
311 * @return int
312 */
313 public function getHeight() {
314 $this->load();
315
316 return $this->height;
317 }
318
319 /**
320 * Get handler-specific metadata
321 * @return string
322 */
323 public function getMetadata() {
324 $this->load();
325
326 return $this->metadata;
327 }
328
329 /**
330 * Return the size of the image file, in bytes
331 * @return int
332 */
333 public function getSize() {
334 $this->load();
335
336 return $this->size;
337 }
338
339 /**
340 * Return the bits of the image file, in bytes
341 * @return int
342 */
343 public function getBits() {
344 $this->load();
345
346 return $this->bits;
347 }
348
349 /**
350 * Returns the mime type of the file.
351 * @return string
352 */
353 public function getMimeType() {
354 $this->load();
355
356 return $this->mime;
357 }
358
359 /**
360 * Get a MediaHandler instance for this file
361 * @return MediaHandler
362 */
363 function getHandler() {
364 if ( !isset( $this->handler ) ) {
365 $this->handler = MediaHandler::getHandler( $this->getMimeType() );
366 }
367
368 return $this->handler;
369 }
370
371 /**
372 * Returns the number of pages of a multipage document, or false for
373 * documents which aren't multipage documents
374 */
375 function pageCount() {
376 if ( !isset( $this->pageCount ) ) {
377 if ( $this->getHandler() && $this->handler->isMultiPage( $this ) ) {
378 $this->pageCount = $this->handler->pageCount( $this );
379 } else {
380 $this->pageCount = false;
381 }
382 }
383
384 return $this->pageCount;
385 }
386
387 /**
388 * Return the type of the media in the file.
389 * Use the value returned by this function with the MEDIATYPE_xxx constants.
390 * @return string
391 */
392 public function getMediaType() {
393 $this->load();
394
395 return $this->media_type;
396 }
397
398 /**
399 * Return upload timestamp.
400 *
401 * @return string
402 */
403 public function getTimestamp() {
404 $this->load();
405
406 return wfTimestamp( TS_MW, $this->timestamp );
407 }
408
409 /**
410 * Get the SHA-1 base 36 hash of the file
411 *
412 * @return string
413 * @since 1.21
414 */
415 function getSha1() {
416 $this->load();
417
418 return $this->sha1;
419 }
420
421 /**
422 * Return the user ID of the uploader.
423 *
424 * @return int
425 */
426 public function getUser() {
427 $this->load();
428 if ( $this->isDeleted( File::DELETED_USER ) ) {
429 return 0;
430 } else {
431 return $this->user;
432 }
433 }
434
435 /**
436 * Return the user name of the uploader.
437 *
438 * @return string
439 */
440 public function getUserText() {
441 $this->load();
442 if ( $this->isDeleted( File::DELETED_USER ) ) {
443 return 0;
444 } else {
445 return $this->user_text;
446 }
447 }
448
449 /**
450 * Return upload description.
451 *
452 * @return string
453 */
454 public function getDescription() {
455 $this->load();
456 if ( $this->isDeleted( File::DELETED_COMMENT ) ) {
457 return 0;
458 } else {
459 return $this->description;
460 }
461 }
462
463 /**
464 * Return the user ID of the uploader.
465 *
466 * @return int
467 */
468 public function getRawUser() {
469 $this->load();
470
471 return $this->user;
472 }
473
474 /**
475 * Return the user name of the uploader.
476 *
477 * @return string
478 */
479 public function getRawUserText() {
480 $this->load();
481
482 return $this->user_text;
483 }
484
485 /**
486 * Return upload description.
487 *
488 * @return string
489 */
490 public function getRawDescription() {
491 $this->load();
492
493 return $this->description;
494 }
495
496 /**
497 * Returns the deletion bitfield
498 * @return int
499 */
500 public function getVisibility() {
501 $this->load();
502
503 return $this->deleted;
504 }
505
506 /**
507 * for file or revision rows
508 *
509 * @param $field Integer: one of DELETED_* bitfield constants
510 * @return bool
511 */
512 public function isDeleted( $field ) {
513 $this->load();
514
515 return ( $this->deleted & $field ) == $field;
516 }
517
518 /**
519 * Determine if the current user is allowed to view a particular
520 * field of this FileStore image file, if it's marked as deleted.
521 * @param $field Integer
522 * @param $user User object to check, or null to use $wgUser
523 * @return bool
524 */
525 public function userCan( $field, User $user = null ) {
526 $this->load();
527
528 return Revision::userCanBitfield( $this->deleted, $field, $user );
529 }
530 }