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