Merge "reinstating Change Ifb1f6125..."
[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 $dbr = wfGetDB( DB_SLAVE );
139 $res = $dbr->select( 'filearchive',
140 array(
141 'fa_id',
142 'fa_name',
143 'fa_archive_name',
144 'fa_storage_key',
145 'fa_storage_group',
146 'fa_size',
147 'fa_bits',
148 'fa_width',
149 'fa_height',
150 'fa_metadata',
151 'fa_media_type',
152 'fa_major_mime',
153 'fa_minor_mime',
154 'fa_description',
155 'fa_user',
156 'fa_user_text',
157 'fa_timestamp',
158 'fa_deleted',
159 'fa_sha1' ),
160 $conds,
161 __METHOD__,
162 array( 'ORDER BY' => 'fa_timestamp DESC' ) );
163 if ( $res == false || $dbr->numRows( $res ) == 0 ) {
164 // this revision does not exist?
165 return null;
166 }
167 $ret = $dbr->resultObject( $res );
168 $row = $ret->fetchObject();
169
170 // initialize fields for filestore image object
171 $this->loadFromRow( $row );
172 } else {
173 throw new MWException( 'This title does not correspond to an image page.' );
174 }
175 $this->dataLoaded = true;
176 $this->exists = true;
177
178 return true;
179 }
180
181 /**
182 * Loads a file object from the filearchive table
183 *
184 * @param $row
185 *
186 * @return ArchivedFile
187 */
188 public static function newFromRow( $row ) {
189 $file = new ArchivedFile( Title::makeTitle( NS_FILE, $row->fa_name ) );
190 $file->loadFromRow( $row );
191 return $file;
192 }
193
194 /**
195 * Load ArchivedFile object fields from a DB row.
196 *
197 * @param $row Object database row
198 * @since 1.21
199 */
200 public function loadFromRow( $row ) {
201 $this->id = intval($row->fa_id);
202 $this->name = $row->fa_name;
203 $this->archive_name = $row->fa_archive_name;
204 $this->group = $row->fa_storage_group;
205 $this->key = $row->fa_storage_key;
206 $this->size = $row->fa_size;
207 $this->bits = $row->fa_bits;
208 $this->width = $row->fa_width;
209 $this->height = $row->fa_height;
210 $this->metadata = $row->fa_metadata;
211 $this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
212 $this->media_type = $row->fa_media_type;
213 $this->description = $row->fa_description;
214 $this->user = $row->fa_user;
215 $this->user_text = $row->fa_user_text;
216 $this->timestamp = $row->fa_timestamp;
217 $this->deleted = $row->fa_deleted;
218 if( isset( $row->fa_sha1 ) ) {
219 $this->sha1 = $row->fa_sha1;
220 } else {
221 // old row, populate from key
222 $this->sha1 = LocalRepo::getHashFromKey( $this->key );
223 }
224 }
225
226 /**
227 * Return the associated title object
228 *
229 * @return Title
230 */
231 public function getTitle() {
232 return $this->title;
233 }
234
235 /**
236 * Return the file name
237 *
238 * @return string
239 */
240 public function getName() {
241 return $this->name;
242 }
243
244 /**
245 * @return int
246 */
247 public function getID() {
248 $this->load();
249 return $this->id;
250 }
251
252 /**
253 * @return bool
254 */
255 public function exists() {
256 $this->load();
257 return $this->exists;
258 }
259
260 /**
261 * Return the FileStore key
262 * @return string
263 */
264 public function getKey() {
265 $this->load();
266 return $this->key;
267 }
268
269 /**
270 * Return the FileStore key (overriding base File class)
271 * @return string
272 */
273 public function getStorageKey() {
274 return $this->getKey();
275 }
276
277 /**
278 * Return the FileStore storage group
279 * @return string
280 */
281 public function getGroup() {
282 return $this->group;
283 }
284
285 /**
286 * Return the width of the image
287 * @return int
288 */
289 public function getWidth() {
290 $this->load();
291 return $this->width;
292 }
293
294 /**
295 * Return the height of the image
296 * @return int
297 */
298 public function getHeight() {
299 $this->load();
300 return $this->height;
301 }
302
303 /**
304 * Get handler-specific metadata
305 * @return string
306 */
307 public function getMetadata() {
308 $this->load();
309 return $this->metadata;
310 }
311
312 /**
313 * Return the size of the image file, in bytes
314 * @return int
315 */
316 public function getSize() {
317 $this->load();
318 return $this->size;
319 }
320
321 /**
322 * Return the bits of the image file, in bytes
323 * @return int
324 */
325 public function getBits() {
326 $this->load();
327 return $this->bits;
328 }
329
330 /**
331 * Returns the mime type of the file.
332 * @return string
333 */
334 public function getMimeType() {
335 $this->load();
336 return $this->mime;
337 }
338
339 /**
340 * Get a MediaHandler instance for this file
341 * @return MediaHandler
342 */
343 function getHandler() {
344 if ( !isset( $this->handler ) ) {
345 $this->handler = MediaHandler::getHandler( $this->getMimeType() );
346 }
347 return $this->handler;
348 }
349
350 /**
351 * Returns the number of pages of a multipage document, or false for
352 * documents which aren't multipage documents
353 */
354 function pageCount() {
355 if ( !isset( $this->pageCount ) ) {
356 if ( $this->getHandler() && $this->handler->isMultiPage( $this ) ) {
357 $this->pageCount = $this->handler->pageCount( $this );
358 } else {
359 $this->pageCount = false;
360 }
361 }
362 return $this->pageCount;
363 }
364
365 /**
366 * Return the type of the media in the file.
367 * Use the value returned by this function with the MEDIATYPE_xxx constants.
368 * @return string
369 */
370 public function getMediaType() {
371 $this->load();
372 return $this->media_type;
373 }
374
375 /**
376 * Return upload timestamp.
377 *
378 * @return string
379 */
380 public function getTimestamp() {
381 $this->load();
382 return wfTimestamp( TS_MW, $this->timestamp );
383 }
384
385 /**
386 * Get the SHA-1 base 36 hash of the file
387 *
388 * @return string
389 * @since 1.21
390 */
391 function getSha1() {
392 $this->load();
393 return $this->sha1;
394 }
395
396 /**
397 * Return the user ID of the uploader.
398 *
399 * @return int
400 */
401 public function getUser() {
402 $this->load();
403 if( $this->isDeleted( File::DELETED_USER ) ) {
404 return 0;
405 } else {
406 return $this->user;
407 }
408 }
409
410 /**
411 * Return the user name of the uploader.
412 *
413 * @return string
414 */
415 public function getUserText() {
416 $this->load();
417 if( $this->isDeleted( File::DELETED_USER ) ) {
418 return 0;
419 } else {
420 return $this->user_text;
421 }
422 }
423
424 /**
425 * Return upload description.
426 *
427 * @return string
428 */
429 public function getDescription() {
430 $this->load();
431 if( $this->isDeleted( File::DELETED_COMMENT ) ) {
432 return 0;
433 } else {
434 return $this->description;
435 }
436 }
437
438 /**
439 * Return the user ID of the uploader.
440 *
441 * @return int
442 */
443 public function getRawUser() {
444 $this->load();
445 return $this->user;
446 }
447
448 /**
449 * Return the user name of the uploader.
450 *
451 * @return string
452 */
453 public function getRawUserText() {
454 $this->load();
455 return $this->user_text;
456 }
457
458 /**
459 * Return upload description.
460 *
461 * @return string
462 */
463 public function getRawDescription() {
464 $this->load();
465 return $this->description;
466 }
467
468 /**
469 * Returns the deletion bitfield
470 * @return int
471 */
472 public function getVisibility() {
473 $this->load();
474 return $this->deleted;
475 }
476
477 /**
478 * for file or revision rows
479 *
480 * @param $field Integer: one of DELETED_* bitfield constants
481 * @return bool
482 */
483 public function isDeleted( $field ) {
484 $this->load();
485 return ($this->deleted & $field) == $field;
486 }
487
488 /**
489 * Determine if the current user is allowed to view a particular
490 * field of this FileStore image file, if it's marked as deleted.
491 * @param $field Integer
492 * @param $user User object to check, or null to use $wgUser
493 * @return bool
494 */
495 public function userCan( $field, User $user = null ) {
496 $this->load();
497 return Revision::userCanBitfield( $this->deleted, $field, $user );
498 }
499 }