Merge "mediawiki.inspect#dumpTable: fix broken FF workaround"
[mediawiki.git] / includes / api / ApiQueryImageInfo.php
blob81c9faf0c868f7f5cc87d7693accab49e0cb8b53
1 <?php
2 /**
5 * Created on July 6, 2007
7 * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * http://www.gnu.org/copyleft/gpl.html
24 * @file
27 /**
28 * A query action to get image information and upload history.
30 * @ingroup API
32 class ApiQueryImageInfo extends ApiQueryBase {
33 const TRANSFORM_LIMIT = 50;
34 private static $transformCount = 0;
36 public function __construct( $query, $moduleName, $prefix = 'ii' ) {
37 // We allow a subclass to override the prefix, to create a related API module.
38 // Some other parts of MediaWiki construct this with a null $prefix, which used to be ignored when this only took two arguments
39 if ( is_null( $prefix ) ) {
40 $prefix = 'ii';
42 parent::__construct( $query, $moduleName, $prefix );
45 public function execute() {
46 $params = $this->extractRequestParams();
48 $prop = array_flip( $params['prop'] );
50 $scale = $this->getScale( $params );
52 $metadataOpts = array(
53 'version' => $params['metadataversion'],
54 'language' => $params['extmetadatalanguage'],
55 'multilang' => $params['extmetadatamultilang'],
58 $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
59 if ( !empty( $pageIds[NS_FILE] ) ) {
60 $titles = array_keys( $pageIds[NS_FILE] );
61 asort( $titles ); // Ensure the order is always the same
63 $fromTitle = null;
64 if ( !is_null( $params['continue'] ) ) {
65 $cont = explode( '|', $params['continue'] );
66 $this->dieContinueUsageIf( count( $cont ) != 2 );
67 $fromTitle = strval( $cont[0] );
68 $fromTimestamp = $cont[1];
69 // Filter out any titles before $fromTitle
70 foreach ( $titles as $key => $title ) {
71 if ( $title < $fromTitle ) {
72 unset( $titles[$key] );
73 } else {
74 break;
79 $result = $this->getResult();
80 //search only inside the local repo
81 if ( $params['localonly'] ) {
82 $images = RepoGroup::singleton()->getLocalRepo()->findFiles( $titles );
83 } else {
84 $images = RepoGroup::singleton()->findFiles( $titles );
86 foreach ( $titles as $title ) {
87 $pageId = $pageIds[NS_FILE][$title];
88 $start = $title === $fromTitle ? $fromTimestamp : $params['start'];
90 if ( !isset( $images[$title] ) ) {
91 if ( isset( $prop['uploadwarning'] ) ) {
92 // Uploadwarning needs info about non-existing files
93 $images[$title] = wfLocalFile( $title );
94 } else {
95 $result->addValue(
96 array( 'query', 'pages', intval( $pageId ) ),
97 'imagerepository', ''
99 // The above can't fail because it doesn't increase the result size
100 continue;
104 /** @var $img File */
105 $img = $images[$title];
107 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
108 if ( count( $pageIds[NS_FILE] ) == 1 ) {
109 // See the 'the user is screwed' comment below
110 $this->setContinueEnumParameter( 'start',
111 $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
113 } else {
114 $this->setContinueEnumParameter( 'continue',
115 $this->getContinueStr( $img, $start ) );
117 break;
120 $fit = $result->addValue(
121 array( 'query', 'pages', intval( $pageId ) ),
122 'imagerepository', $img->getRepoName()
124 if ( !$fit ) {
125 if ( count( $pageIds[NS_FILE] ) == 1 ) {
126 // The user is screwed. imageinfo can't be solely
127 // responsible for exceeding the limit in this case,
128 // so set a query-continue that just returns the same
129 // thing again. When the violating queries have been
130 // out-continued, the result will get through
131 $this->setContinueEnumParameter( 'start',
132 $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
134 } else {
135 $this->setContinueEnumParameter( 'continue',
136 $this->getContinueStr( $img, $start ) );
138 break;
141 // Check if we can make the requested thumbnail, and get transform parameters.
142 $finalThumbParams = $this->mergeThumbParams( $img, $scale, $params['urlparam'] );
144 // Get information about the current version first
145 // Check that the current version is within the start-end boundaries
146 $gotOne = false;
147 if (
148 ( is_null( $start ) || $img->getTimestamp() <= $start ) &&
149 ( is_null( $params['end'] ) || $img->getTimestamp() >= $params['end'] )
151 $gotOne = true;
153 $fit = $this->addPageSubItem( $pageId,
154 self::getInfo( $img, $prop, $result,
155 $finalThumbParams, $metadataOpts
158 if ( !$fit ) {
159 if ( count( $pageIds[NS_FILE] ) == 1 ) {
160 // See the 'the user is screwed' comment above
161 $this->setContinueEnumParameter( 'start',
162 wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
163 } else {
164 $this->setContinueEnumParameter( 'continue',
165 $this->getContinueStr( $img ) );
167 break;
171 // Now get the old revisions
172 // Get one more to facilitate query-continue functionality
173 $count = ( $gotOne ? 1 : 0 );
174 $oldies = $img->getHistory( $params['limit'] - $count + 1, $start, $params['end'] );
175 /** @var $oldie File */
176 foreach ( $oldies as $oldie ) {
177 if ( ++$count > $params['limit'] ) {
178 // We've reached the extra one which shows that there are additional pages to be had. Stop here...
179 // Only set a query-continue if there was only one title
180 if ( count( $pageIds[NS_FILE] ) == 1 ) {
181 $this->setContinueEnumParameter( 'start',
182 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
184 break;
186 $fit = self::getTransformCount() < self::TRANSFORM_LIMIT &&
187 $this->addPageSubItem( $pageId,
188 self::getInfo( $oldie, $prop, $result,
189 $finalThumbParams, $metadataOpts
192 if ( !$fit ) {
193 if ( count( $pageIds[NS_FILE] ) == 1 ) {
194 $this->setContinueEnumParameter( 'start',
195 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
196 } else {
197 $this->setContinueEnumParameter( 'continue',
198 $this->getContinueStr( $oldie ) );
200 break;
203 if ( !$fit ) {
204 break;
211 * From parameters, construct a 'scale' array
212 * @param array $params Parameters passed to api.
213 * @return Array or Null: key-val array of 'width' and 'height', or null
215 public function getScale( $params ) {
216 $p = $this->getModulePrefix();
218 if ( $params['urlwidth'] != -1 ) {
219 $scale = array();
220 $scale['width'] = $params['urlwidth'];
221 $scale['height'] = $params['urlheight'];
222 } elseif ( $params['urlheight'] != -1 ) {
223 // Height is specified but width isn't
224 // Don't set $scale['width']; this signals mergeThumbParams() to fill it with the image's width
225 $scale = array();
226 $scale['height'] = $params['urlheight'];
227 } else {
228 $scale = null;
229 if ( $params['urlparam'] ) {
230 $this->dieUsage( "{$p}urlparam requires {$p}urlwidth", "urlparam_no_width" );
234 return $scale;
237 /** Validate and merge scale parameters with handler thumb parameters, give error if invalid.
239 * We do this later than getScale, since we need the image
240 * to know which handler, since handlers can make their own parameters.
241 * @param File $image Image that params are for.
242 * @param array $thumbParams thumbnail parameters from getScale
243 * @param string $otherParams of otherParams (iiurlparam).
244 * @return Array of parameters for transform.
246 protected function mergeThumbParams( $image, $thumbParams, $otherParams ) {
247 global $wgThumbLimits;
249 if ( !isset( $thumbParams['width'] ) && isset( $thumbParams['height'] ) ) {
250 // We want to limit only by height in this situation, so pass the
251 // image's full width as the limiting width. But some file types
252 // don't have a width of their own, so pick something arbitrary so
253 // thumbnailing the default icon works.
254 if ( $image->getWidth() <= 0 ) {
255 $thumbParams['width'] = max( $wgThumbLimits );
256 } else {
257 $thumbParams['width'] = $image->getWidth();
261 if ( !$otherParams ) {
262 return $thumbParams;
264 $p = $this->getModulePrefix();
266 $h = $image->getHandler();
267 if ( !$h ) {
268 $this->setWarning( 'Could not create thumbnail because ' .
269 $image->getName() . ' does not have an associated image handler' );
270 return $thumbParams;
273 $paramList = $h->parseParamString( $otherParams );
274 if ( !$paramList ) {
275 // Just set a warning (instead of dieUsage), as in many cases
276 // we could still render the image using width and height parameters,
277 // and this type of thing could happen between different versions of
278 // handlers.
279 $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName()
280 . '. Using only width and height' );
281 return $thumbParams;
284 if ( isset( $paramList['width'] ) ) {
285 if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
286 $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
287 . "in favor of width value derived from {$p}urlwidth/{$p}urlheight ({$thumbParams['width']})" );
291 foreach ( $paramList as $name => $value ) {
292 if ( !$h->validateParam( $name, $value ) ) {
293 $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", "urlparam" );
297 return $thumbParams + $paramList;
301 * Get result information for an image revision
303 * @param $file File object
304 * @param array $prop of properties to get (in the keys)
305 * @param $result ApiResult object
306 * @param array $thumbParams containing 'width' and 'height' items, or null
307 * @param string|array $metadataOpts Options for metadata fetching.
308 * This is an array consisting of the keys:
309 * 'version': The metadata version for the metadata option
310 * 'language': The language for extmetadata property
311 * 'multilang': Return all translations in extmetadata property
312 * @return Array: result array
314 static function getInfo( $file, $prop, $result, $thumbParams = null, $metadataOpts = false ) {
315 global $wgContLang;
317 if ( !$metadataOpts || is_string( $metadataOpts ) ) {
318 $metadataOpts = array(
319 'version' => $metadataOpts ?: 'latest',
320 'language' => $wgContLang,
321 'multilang' => false,
324 $version = $metadataOpts['version'];
325 $vals = array();
326 // Timestamp is shown even if the file is revdelete'd in interface
327 // so do same here.
328 if ( isset( $prop['timestamp'] ) ) {
329 $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
332 $user = isset( $prop['user'] );
333 $userid = isset( $prop['userid'] );
335 if ( $user || $userid ) {
336 if ( $file->isDeleted( File::DELETED_USER ) ) {
337 $vals['userhidden'] = '';
338 } else {
339 if ( $user ) {
340 $vals['user'] = $file->getUser();
342 if ( $userid ) {
343 $vals['userid'] = $file->getUser( 'id' );
345 if ( !$file->getUser( 'id' ) ) {
346 $vals['anon'] = '';
351 // This is shown even if the file is revdelete'd in interface
352 // so do same here.
353 if ( isset( $prop['size'] ) || isset( $prop['dimensions'] ) ) {
354 $vals['size'] = intval( $file->getSize() );
355 $vals['width'] = intval( $file->getWidth() );
356 $vals['height'] = intval( $file->getHeight() );
358 $pageCount = $file->pageCount();
359 if ( $pageCount !== false ) {
360 $vals['pagecount'] = $pageCount;
364 $pcomment = isset( $prop['parsedcomment'] );
365 $comment = isset( $prop['comment'] );
367 if ( $pcomment || $comment ) {
368 if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
369 $vals['commenthidden'] = '';
370 } else {
371 if ( $pcomment ) {
372 $vals['parsedcomment'] = Linker::formatComment(
373 $file->getDescription(), $file->getTitle() );
375 if ( $comment ) {
376 $vals['comment'] = $file->getDescription();
381 $url = isset( $prop['url'] );
382 $sha1 = isset( $prop['sha1'] );
383 $meta = isset( $prop['metadata'] );
384 $extmetadata = isset( $prop['extmetadata'] );
385 $mime = isset( $prop['mime'] );
386 $mediatype = isset( $prop['mediatype'] );
387 $archive = isset( $prop['archivename'] );
388 $bitdepth = isset( $prop['bitdepth'] );
389 $uploadwarning = isset( $prop['uploadwarning'] );
391 if ( ( $url || $sha1 || $meta || $mime || $mediatype || $archive || $bitdepth )
392 && $file->isDeleted( File::DELETED_FILE ) ) {
393 $vals['filehidden'] = '';
395 //Early return, tidier than indenting all following things one level
396 return $vals;
399 if ( $url ) {
400 if ( !is_null( $thumbParams ) ) {
401 $mto = $file->transform( $thumbParams );
402 self::$transformCount++;
403 if ( $mto && !$mto->isError() ) {
404 $vals['thumburl'] = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT );
406 // bug 23834 - If the URL's are the same, we haven't resized it, so shouldn't give the wanted
407 // thumbnail sizes for the thumbnail actual size
408 if ( $mto->getUrl() !== $file->getUrl() ) {
409 $vals['thumbwidth'] = intval( $mto->getWidth() );
410 $vals['thumbheight'] = intval( $mto->getHeight() );
411 } else {
412 $vals['thumbwidth'] = intval( $file->getWidth() );
413 $vals['thumbheight'] = intval( $file->getHeight() );
416 if ( isset( $prop['thumbmime'] ) && $file->getHandler() ) {
417 list( , $mime ) = $file->getHandler()->getThumbType(
418 $mto->getExtension(), $file->getMimeType(), $thumbParams );
419 $vals['thumbmime'] = $mime;
421 } elseif ( $mto && $mto->isError() ) {
422 $vals['thumberror'] = $mto->toText();
425 $vals['url'] = wfExpandUrl( $file->getFullURL(), PROTO_CURRENT );
426 $vals['descriptionurl'] = wfExpandUrl( $file->getDescriptionUrl(), PROTO_CURRENT );
429 if ( $sha1 ) {
430 $vals['sha1'] = wfBaseConvert( $file->getSha1(), 36, 16, 40 );
433 if ( $meta ) {
434 wfSuppressWarnings();
435 $metadata = unserialize( $file->getMetadata() );
436 wfRestoreWarnings();
437 if ( $metadata && $version !== 'latest' ) {
438 $metadata = $file->convertMetadataVersion( $metadata, $version );
440 $vals['metadata'] = $metadata ? self::processMetaData( $metadata, $result ) : null;
443 if ( $extmetadata ) {
444 // Note, this should return an array where all the keys
445 // start with a letter, and all the values are strings.
446 // Thus there should be no issue with format=xml.
447 $format = new FormatMetadata;
448 $format->setSingleLanguage( !$metadataOpts['multilang'] );
449 $format->getContext()->setLanguage( $metadataOpts['language'] );
450 $extmetaArray = $format->fetchExtendedMetadata( $file );
451 $vals['extmetadata'] = $extmetaArray;
454 if ( $mime ) {
455 $vals['mime'] = $file->getMimeType();
458 if ( $mediatype ) {
459 $vals['mediatype'] = $file->getMediaType();
462 if ( $archive && $file->isOld() ) {
463 $vals['archivename'] = $file->getArchiveName();
466 if ( $bitdepth ) {
467 $vals['bitdepth'] = $file->getBitDepth();
470 if ( $uploadwarning ) {
471 $vals['html'] = SpecialUpload::getExistsWarning( UploadBase::getExistsWarning( $file ) );
474 return $vals;
478 * Get the count of image transformations performed
480 * If this is >= TRANSFORM_LIMIT, you should probably stop processing images.
482 * @return integer count
484 static function getTransformCount() {
485 return self::$transformCount;
490 * @param $metadata Array
491 * @param $result ApiResult
492 * @return Array
494 public static function processMetaData( $metadata, $result ) {
495 $retval = array();
496 if ( is_array( $metadata ) ) {
497 foreach ( $metadata as $key => $value ) {
498 $r = array( 'name' => $key );
499 if ( is_array( $value ) ) {
500 $r['value'] = self::processMetaData( $value, $result );
501 } else {
502 $r['value'] = $value;
504 $retval[] = $r;
507 $result->setIndexedTagName( $retval, 'metadata' );
508 return $retval;
511 public function getCacheMode( $params ) {
512 return 'public';
516 * @param $img File
517 * @param null|string $start
518 * @return string
520 protected function getContinueStr( $img, $start = null ) {
521 if ( $start === null ) {
522 $start = $img->getTimestamp();
524 return $img->getOriginalTitle()->getDBkey() . '|' . $start;
527 public function getAllowedParams() {
528 global $wgContLang;
529 return array(
530 'prop' => array(
531 ApiBase::PARAM_ISMULTI => true,
532 ApiBase::PARAM_DFLT => 'timestamp|user',
533 ApiBase::PARAM_TYPE => self::getPropertyNames()
535 'limit' => array(
536 ApiBase::PARAM_TYPE => 'limit',
537 ApiBase::PARAM_DFLT => 1,
538 ApiBase::PARAM_MIN => 1,
539 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
540 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
542 'start' => array(
543 ApiBase::PARAM_TYPE => 'timestamp'
545 'end' => array(
546 ApiBase::PARAM_TYPE => 'timestamp'
548 'urlwidth' => array(
549 ApiBase::PARAM_TYPE => 'integer',
550 ApiBase::PARAM_DFLT => -1
552 'urlheight' => array(
553 ApiBase::PARAM_TYPE => 'integer',
554 ApiBase::PARAM_DFLT => -1
556 'metadataversion' => array(
557 ApiBase::PARAM_TYPE => 'string',
558 ApiBase::PARAM_DFLT => '1',
560 'extmetadatalanguage' => array(
561 ApiBase::PARAM_TYPE => 'string',
562 ApiBase::PARAM_DFLT => $wgContLang->getCode(),
564 'extmetadatamultilang' => array(
565 ApiBase::PARAM_TYPE => 'boolean',
566 ApiBase::PARAM_DFLT => false,
568 'urlparam' => array(
569 ApiBase::PARAM_DFLT => '',
570 ApiBase::PARAM_TYPE => 'string',
572 'continue' => null,
573 'localonly' => false,
578 * Returns all possible parameters to iiprop
580 * @param array $filter List of properties to filter out
582 * @return Array
584 public static function getPropertyNames( $filter = array() ) {
585 return array_diff( array_keys( self::getProperties() ), $filter );
589 * Returns array key value pairs of properties and their descriptions
591 * @param string $modulePrefix
592 * @return array
594 private static function getProperties( $modulePrefix = '' ) {
595 return array(
596 'timestamp' => ' timestamp - Adds timestamp for the uploaded version',
597 'user' => ' user - Adds the user who uploaded the image version',
598 'userid' => ' userid - Add the user ID that uploaded the image version',
599 'comment' => ' comment - Comment on the version',
600 'parsedcomment' => ' parsedcomment - Parse the comment on the version',
601 'url' => ' url - Gives URL to the image and the description page',
602 'size' => ' size - Adds the size of the image in bytes and the height, width and page count (if applicable)',
603 'dimensions' => ' dimensions - Alias for size', // For backwards compatibility with Allimages
604 'sha1' => ' sha1 - Adds SHA-1 hash for the image',
605 'mime' => ' mime - Adds MIME type of the image',
606 'thumbmime' => ' thumbmime - Adds MIME type of the image thumbnail' .
607 ' (requires url and param ' . $modulePrefix . 'urlwidth)',
608 'mediatype' => ' mediatype - Adds the media type of the image',
609 'metadata' => ' metadata - Lists Exif metadata for the version of the image',
610 'extmetadata' => ' extmetadata - Lists formatted metadata combined from multiple sources. Results are HTML formatted.',
611 'archivename' => ' archivename - Adds the file name of the archive version for non-latest versions',
612 'bitdepth' => ' bitdepth - Adds the bit depth of the version',
613 'uploadwarning' => ' uploadwarning - Used by the Special:Upload page to get information about an existing file. Not intended for use outside MediaWiki core',
618 * Returns the descriptions for the properties provided by getPropertyNames()
620 * @param array $filter List of properties to filter out
621 * @param string $modulePrefix
622 * @return array
624 public static function getPropertyDescriptions( $filter = array(), $modulePrefix = '' ) {
625 return array_merge(
626 array( 'What image information to get:' ),
627 array_values( array_diff_key( self::getProperties( $modulePrefix ), array_flip( $filter ) ) )
632 * Return the API documentation for the parameters.
633 * @return Array parameter documentation.
635 public function getParamDescription() {
636 $p = $this->getModulePrefix();
637 return array(
638 'prop' => self::getPropertyDescriptions( array(), $p ),
639 'urlwidth' => array( "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
640 'For performance reasons if this option is used, ' .
641 'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.' ),
642 'urlheight' => "Similar to {$p}urlwidth.",
643 'urlparam' => array( "A handler specific parameter string. For example, pdf's ",
644 "might use 'page15-100px'. {$p}urlwidth must be used and be consistent with {$p}urlparam" ),
645 'limit' => 'How many image revisions to return per image',
646 'start' => 'Timestamp to start listing from',
647 'end' => 'Timestamp to stop listing at',
648 'metadataversion' => array( "Version of metadata to use. if 'latest' is specified, use latest version.",
649 "Defaults to '1' for backwards compatibility" ),
650 'extmetadatalanguage' => array( 'What language to fetch extmetadata in. This affects both which',
651 'translation to fetch, if multiple are available, as well as how things',
652 'like numbers and various values are formatted.' ),
653 'extmetadatamultilang' => 'If translations for extmetadata property are available, fetch all of them.',
654 'continue' => 'If the query response includes a continue value, use it here to get another page of results',
655 'localonly' => 'Look only for files in the local repository',
659 public static function getResultPropertiesFiltered( $filter = array() ) {
660 $props = array(
661 'timestamp' => array(
662 'timestamp' => 'timestamp'
664 'user' => array(
665 'userhidden' => 'boolean',
666 'user' => 'string',
667 'anon' => 'boolean'
669 'userid' => array(
670 'userhidden' => 'boolean',
671 'userid' => 'integer',
672 'anon' => 'boolean'
674 'size' => array(
675 'size' => 'integer',
676 'width' => 'integer',
677 'height' => 'integer',
678 'pagecount' => array(
679 ApiBase::PROP_TYPE => 'integer',
680 ApiBase::PROP_NULLABLE => true
683 'dimensions' => array(
684 'size' => 'integer',
685 'width' => 'integer',
686 'height' => 'integer',
687 'pagecount' => array(
688 ApiBase::PROP_TYPE => 'integer',
689 ApiBase::PROP_NULLABLE => true
692 'comment' => array(
693 'commenthidden' => 'boolean',
694 'comment' => array(
695 ApiBase::PROP_TYPE => 'string',
696 ApiBase::PROP_NULLABLE => true
699 'parsedcomment' => array(
700 'commenthidden' => 'boolean',
701 'parsedcomment' => array(
702 ApiBase::PROP_TYPE => 'string',
703 ApiBase::PROP_NULLABLE => true
706 'url' => array(
707 'filehidden' => 'boolean',
708 'thumburl' => array(
709 ApiBase::PROP_TYPE => 'string',
710 ApiBase::PROP_NULLABLE => true
712 'thumbwidth' => array(
713 ApiBase::PROP_TYPE => 'integer',
714 ApiBase::PROP_NULLABLE => true
716 'thumbheight' => array(
717 ApiBase::PROP_TYPE => 'integer',
718 ApiBase::PROP_NULLABLE => true
720 'thumberror' => array(
721 ApiBase::PROP_TYPE => 'string',
722 ApiBase::PROP_NULLABLE => true
724 'url' => array(
725 ApiBase::PROP_TYPE => 'string',
726 ApiBase::PROP_NULLABLE => true
728 'descriptionurl' => array(
729 ApiBase::PROP_TYPE => 'string',
730 ApiBase::PROP_NULLABLE => true
733 'sha1' => array(
734 'filehidden' => 'boolean',
735 'sha1' => array(
736 ApiBase::PROP_TYPE => 'string',
737 ApiBase::PROP_NULLABLE => true
740 'mime' => array(
741 'filehidden' => 'boolean',
742 'mime' => array(
743 ApiBase::PROP_TYPE => 'string',
744 ApiBase::PROP_NULLABLE => true
747 'thumbmime' => array(
748 'filehidden' => 'boolean',
749 'thumbmime' => array(
750 ApiBase::PROP_TYPE => 'string',
751 ApiBase::PROP_NULLABLE => true
754 'mediatype' => array(
755 'filehidden' => 'boolean',
756 'mediatype' => array(
757 ApiBase::PROP_TYPE => 'string',
758 ApiBase::PROP_NULLABLE => true
761 'archivename' => array(
762 'filehidden' => 'boolean',
763 'archivename' => array(
764 ApiBase::PROP_TYPE => 'string',
765 ApiBase::PROP_NULLABLE => true
768 'bitdepth' => array(
769 'filehidden' => 'boolean',
770 'bitdepth' => array(
771 ApiBase::PROP_TYPE => 'integer',
772 ApiBase::PROP_NULLABLE => true
776 return array_diff_key( $props, array_flip( $filter ) );
779 public function getResultProperties() {
780 return self::getResultPropertiesFiltered();
783 public function getDescription() {
784 return 'Returns image information and upload history';
787 public function getPossibleErrors() {
788 $p = $this->getModulePrefix();
789 return array_merge( parent::getPossibleErrors(), array(
790 array( 'code' => "{$p}urlwidth", 'info' => "{$p}urlheight cannot be used without {$p}urlwidth" ),
791 array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ),
792 array( 'code' => 'urlparam_no_width', 'info' => "{$p}urlparam requires {$p}urlwidth" ),
793 ) );
796 public function getExamples() {
797 return array(
798 'api.php?action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo',
799 'api.php?action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&iiend=20071231235959&iiprop=timestamp|user|url',
803 public function getHelpUrls() {
804 return 'https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii';