MediaWiki  REL1_24
ApiQueryImageInfo.php
Go to the documentation of this file.
00001 <?php
00032 class ApiQueryImageInfo extends ApiQueryBase {
00033     const TRANSFORM_LIMIT = 50;
00034     private static $transformCount = 0;
00035 
00036     public function __construct( ApiQuery $query, $moduleName, $prefix = 'ii' ) {
00037         // We allow a subclass to override the prefix, to create a related API
00038         // module. Some other parts of MediaWiki construct this with a null
00039         // $prefix, which used to be ignored when this only took two arguments
00040         if ( is_null( $prefix ) ) {
00041             $prefix = 'ii';
00042         }
00043         parent::__construct( $query, $moduleName, $prefix );
00044     }
00045 
00046     public function execute() {
00047         $params = $this->extractRequestParams();
00048 
00049         $prop = array_flip( $params['prop'] );
00050 
00051         $scale = $this->getScale( $params );
00052 
00053         $opts = array(
00054             'version' => $params['metadataversion'],
00055             'language' => $params['extmetadatalanguage'],
00056             'multilang' => $params['extmetadatamultilang'],
00057             'extmetadatafilter' => $params['extmetadatafilter'],
00058             'revdelUser' => $this->getUser(),
00059         );
00060 
00061         $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
00062         if ( !empty( $pageIds[NS_FILE] ) ) {
00063             $titles = array_keys( $pageIds[NS_FILE] );
00064             asort( $titles ); // Ensure the order is always the same
00065 
00066             $fromTitle = null;
00067             if ( !is_null( $params['continue'] ) ) {
00068                 $cont = explode( '|', $params['continue'] );
00069                 $this->dieContinueUsageIf( count( $cont ) != 2 );
00070                 $fromTitle = strval( $cont[0] );
00071                 $fromTimestamp = $cont[1];
00072                 // Filter out any titles before $fromTitle
00073                 foreach ( $titles as $key => $title ) {
00074                     if ( $title < $fromTitle ) {
00075                         unset( $titles[$key] );
00076                     } else {
00077                         break;
00078                     }
00079                 }
00080             }
00081 
00082             $user = $this->getUser();
00083             $findTitles = array_map( function ( $title ) use ( $user ) {
00084                 return array(
00085                     'title' => $title,
00086                     'private' => $user,
00087                 );
00088             }, $titles );
00089 
00090             if ( $params['localonly'] ) {
00091                 $images = RepoGroup::singleton()->getLocalRepo()->findFiles( $findTitles );
00092             } else {
00093                 $images = RepoGroup::singleton()->findFiles( $findTitles );
00094             }
00095 
00096             $result = $this->getResult();
00097             foreach ( $titles as $title ) {
00098                 $pageId = $pageIds[NS_FILE][$title];
00099                 $start = $title === $fromTitle ? $fromTimestamp : $params['start'];
00100 
00101                 if ( !isset( $images[$title] ) ) {
00102                     if ( isset( $prop['uploadwarning'] ) ) {
00103                         // Uploadwarning needs info about non-existing files
00104                         $images[$title] = wfLocalFile( $title );
00105                     } else {
00106                         $result->addValue(
00107                             array( 'query', 'pages', intval( $pageId ) ),
00108                             'imagerepository', ''
00109                         );
00110                         // The above can't fail because it doesn't increase the result size
00111                         continue;
00112                     }
00113                 }
00114 
00116                 $img = $images[$title];
00117 
00118                 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
00119                     if ( count( $pageIds[NS_FILE] ) == 1 ) {
00120                         // See the 'the user is screwed' comment below
00121                         $this->setContinueEnumParameter( 'start',
00122                             $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
00123                         );
00124                     } else {
00125                         $this->setContinueEnumParameter( 'continue',
00126                             $this->getContinueStr( $img, $start ) );
00127                     }
00128                     break;
00129                 }
00130 
00131                 $fit = $result->addValue(
00132                     array( 'query', 'pages', intval( $pageId ) ),
00133                     'imagerepository', $img->getRepoName()
00134                 );
00135                 if ( !$fit ) {
00136                     if ( count( $pageIds[NS_FILE] ) == 1 ) {
00137                         // The user is screwed. imageinfo can't be solely
00138                         // responsible for exceeding the limit in this case,
00139                         // so set a query-continue that just returns the same
00140                         // thing again. When the violating queries have been
00141                         // out-continued, the result will get through
00142                         $this->setContinueEnumParameter( 'start',
00143                             $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
00144                         );
00145                     } else {
00146                         $this->setContinueEnumParameter( 'continue',
00147                             $this->getContinueStr( $img, $start ) );
00148                     }
00149                     break;
00150                 }
00151 
00152                 // Check if we can make the requested thumbnail, and get transform parameters.
00153                 $finalThumbParams = $this->mergeThumbParams( $img, $scale, $params['urlparam'] );
00154 
00155                 // Get information about the current version first
00156                 // Check that the current version is within the start-end boundaries
00157                 $gotOne = false;
00158                 if (
00159                     ( is_null( $start ) || $img->getTimestamp() <= $start ) &&
00160                     ( is_null( $params['end'] ) || $img->getTimestamp() >= $params['end'] )
00161                 ) {
00162                     $gotOne = true;
00163 
00164                     $fit = $this->addPageSubItem( $pageId,
00165                         self::getInfo( $img, $prop, $result,
00166                             $finalThumbParams, $opts
00167                         )
00168                     );
00169                     if ( !$fit ) {
00170                         if ( count( $pageIds[NS_FILE] ) == 1 ) {
00171                             // See the 'the user is screwed' comment above
00172                             $this->setContinueEnumParameter( 'start',
00173                                 wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
00174                         } else {
00175                             $this->setContinueEnumParameter( 'continue',
00176                                 $this->getContinueStr( $img ) );
00177                         }
00178                         break;
00179                     }
00180                 }
00181 
00182                 // Now get the old revisions
00183                 // Get one more to facilitate query-continue functionality
00184                 $count = ( $gotOne ? 1 : 0 );
00185                 $oldies = $img->getHistory( $params['limit'] - $count + 1, $start, $params['end'] );
00187                 foreach ( $oldies as $oldie ) {
00188                     if ( ++$count > $params['limit'] ) {
00189                         // We've reached the extra one which shows that there are
00190                         // additional pages to be had. Stop here...
00191                         // Only set a query-continue if there was only one title
00192                         if ( count( $pageIds[NS_FILE] ) == 1 ) {
00193                             $this->setContinueEnumParameter( 'start',
00194                                 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
00195                         }
00196                         break;
00197                     }
00198                     $fit = self::getTransformCount() < self::TRANSFORM_LIMIT &&
00199                         $this->addPageSubItem( $pageId,
00200                             self::getInfo( $oldie, $prop, $result,
00201                                 $finalThumbParams, $opts
00202                             )
00203                         );
00204                     if ( !$fit ) {
00205                         if ( count( $pageIds[NS_FILE] ) == 1 ) {
00206                             $this->setContinueEnumParameter( 'start',
00207                                 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
00208                         } else {
00209                             $this->setContinueEnumParameter( 'continue',
00210                                 $this->getContinueStr( $oldie ) );
00211                         }
00212                         break;
00213                     }
00214                 }
00215                 if ( !$fit ) {
00216                     break;
00217                 }
00218             }
00219         }
00220     }
00221 
00227     public function getScale( $params ) {
00228         $p = $this->getModulePrefix();
00229 
00230         if ( $params['urlwidth'] != -1 ) {
00231             $scale = array();
00232             $scale['width'] = $params['urlwidth'];
00233             $scale['height'] = $params['urlheight'];
00234         } elseif ( $params['urlheight'] != -1 ) {
00235             // Height is specified but width isn't
00236             // Don't set $scale['width']; this signals mergeThumbParams() to fill it with the image's width
00237             $scale = array();
00238             $scale['height'] = $params['urlheight'];
00239         } else {
00240             if ( $params['urlparam'] ) {
00241                 // Audio files might not have a width/height.
00242                 $scale = array();
00243             } else {
00244                 $scale = null;
00245             }
00246         }
00247 
00248         return $scale;
00249     }
00250 
00260     protected function mergeThumbParams( $image, $thumbParams, $otherParams ) {
00261         if ( $thumbParams === null ) {
00262             // No scaling requested
00263             return null;
00264         }
00265         if ( !isset( $thumbParams['width'] ) && isset( $thumbParams['height'] ) ) {
00266             // We want to limit only by height in this situation, so pass the
00267             // image's full width as the limiting width. But some file types
00268             // don't have a width of their own, so pick something arbitrary so
00269             // thumbnailing the default icon works.
00270             if ( $image->getWidth() <= 0 ) {
00271                 $thumbParams['width'] = max( $this->getConfig()->get( 'ThumbLimits' ) );
00272             } else {
00273                 $thumbParams['width'] = $image->getWidth();
00274             }
00275         }
00276 
00277         if ( !$otherParams ) {
00278             $this->checkParameterNormalise( $image, $thumbParams );
00279             return $thumbParams;
00280         }
00281         $p = $this->getModulePrefix();
00282 
00283         $h = $image->getHandler();
00284         if ( !$h ) {
00285             $this->setWarning( 'Could not create thumbnail because ' .
00286                 $image->getName() . ' does not have an associated image handler' );
00287 
00288             return $thumbParams;
00289         }
00290 
00291         $paramList = $h->parseParamString( $otherParams );
00292         if ( !$paramList ) {
00293             // Just set a warning (instead of dieUsage), as in many cases
00294             // we could still render the image using width and height parameters,
00295             // and this type of thing could happen between different versions of
00296             // handlers.
00297             $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName()
00298                 . '. Using only width and height' );
00299             $this->checkParameterNormalise( $image, $thumbParams );
00300             return $thumbParams;
00301         }
00302 
00303         if ( isset( $paramList['width'] ) && isset( $thumbParams['width'] ) ) {
00304             if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
00305                 $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
00306                     . "in favor of width value derived from {$p}urlwidth/{$p}urlheight "
00307                     . "({$thumbParams['width']})" );
00308             }
00309         }
00310 
00311         foreach ( $paramList as $name => $value ) {
00312             if ( !$h->validateParam( $name, $value ) ) {
00313                 $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", "urlparam" );
00314             }
00315         }
00316 
00317         $finalParams = $thumbParams + $paramList;
00318         $this->checkParameterNormalise( $image, $finalParams );
00319         return $finalParams;
00320     }
00321 
00333     protected function checkParameterNormalise( $image, $finalParams ) {
00334         $h = $image->getHandler();
00335         if ( !$h ) {
00336             return;
00337         }
00338         // Note: normaliseParams modifies the array in place, but we aren't interested
00339         // in the actual normalised version, only if we can actually normalise them,
00340         // so we use the functions scope to throw away the normalisations.
00341         if ( !$h->normaliseParams( $image, $finalParams ) ) {
00342             $this->dieUsage( "Could not normalise image parameters for " . $image->getName(), "urlparamnormal" );
00343         }
00344     }
00345 
00361     static function getInfo( $file, $prop, $result, $thumbParams = null, $opts = false ) {
00362         global $wgContLang;
00363 
00364         $anyHidden = false;
00365 
00366         if ( !$opts || is_string( $opts ) ) {
00367             $opts = array(
00368                 'version' => $opts ?: 'latest',
00369                 'language' => $wgContLang,
00370                 'multilang' => false,
00371                 'extmetadatafilter' => array(),
00372                 'revdelUser' => null,
00373             );
00374         }
00375         $version = $opts['version'];
00376         $vals = array();
00377         // Timestamp is shown even if the file is revdelete'd in interface
00378         // so do same here.
00379         if ( isset( $prop['timestamp'] ) ) {
00380             $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
00381         }
00382 
00383         // Handle external callers who don't pass revdelUser
00384         if ( isset( $opts['revdelUser'] ) && $opts['revdelUser'] ) {
00385             $revdelUser = $opts['revdelUser'];
00386             $canShowField = function ( $field ) use ( $file, $revdelUser ) {
00387                 return $file->userCan( $field, $revdelUser );
00388             };
00389         } else {
00390             $canShowField = function ( $field ) use ( $file ) {
00391                 return !$file->isDeleted( $field );
00392             };
00393         }
00394 
00395         $user = isset( $prop['user'] );
00396         $userid = isset( $prop['userid'] );
00397 
00398         if ( $user || $userid ) {
00399             if ( $file->isDeleted( File::DELETED_USER ) ) {
00400                 $vals['userhidden'] = '';
00401                 $anyHidden = true;
00402             }
00403             if ( $canShowField( File::DELETED_USER ) ) {
00404                 if ( $user ) {
00405                     $vals['user'] = $file->getUser();
00406                 }
00407                 if ( $userid ) {
00408                     $vals['userid'] = $file->getUser( 'id' );
00409                 }
00410                 if ( !$file->getUser( 'id' ) ) {
00411                     $vals['anon'] = '';
00412                 }
00413             }
00414         }
00415 
00416         // This is shown even if the file is revdelete'd in interface
00417         // so do same here.
00418         if ( isset( $prop['size'] ) || isset( $prop['dimensions'] ) ) {
00419             $vals['size'] = intval( $file->getSize() );
00420             $vals['width'] = intval( $file->getWidth() );
00421             $vals['height'] = intval( $file->getHeight() );
00422 
00423             $pageCount = $file->pageCount();
00424             if ( $pageCount !== false ) {
00425                 $vals['pagecount'] = $pageCount;
00426             }
00427 
00428             // length as in how many seconds long a video is.
00429             $length = $file->getLength();
00430             if ( $length ) {
00431                 // Call it duration, because "length" can be ambiguous.
00432                 $vals['duration'] = (float)$length;
00433             }
00434         }
00435 
00436         $pcomment = isset( $prop['parsedcomment'] );
00437         $comment = isset( $prop['comment'] );
00438 
00439         if ( $pcomment || $comment ) {
00440             if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
00441                 $vals['commenthidden'] = '';
00442                 $anyHidden = true;
00443             }
00444             if ( $canShowField( File::DELETED_COMMENT ) ) {
00445                 if ( $pcomment ) {
00446                     $vals['parsedcomment'] = Linker::formatComment(
00447                         $file->getDescription( File::RAW ), $file->getTitle() );
00448                 }
00449                 if ( $comment ) {
00450                     $vals['comment'] = $file->getDescription( File::RAW );
00451                 }
00452             }
00453         }
00454 
00455         $canonicaltitle = isset( $prop['canonicaltitle'] );
00456         $url = isset( $prop['url'] );
00457         $sha1 = isset( $prop['sha1'] );
00458         $meta = isset( $prop['metadata'] );
00459         $extmetadata = isset( $prop['extmetadata'] );
00460         $commonmeta = isset( $prop['commonmetadata'] );
00461         $mime = isset( $prop['mime'] );
00462         $mediatype = isset( $prop['mediatype'] );
00463         $archive = isset( $prop['archivename'] );
00464         $bitdepth = isset( $prop['bitdepth'] );
00465         $uploadwarning = isset( $prop['uploadwarning'] );
00466 
00467         if ( $uploadwarning ) {
00468             $vals['html'] = SpecialUpload::getExistsWarning( UploadBase::getExistsWarning( $file ) );
00469         }
00470 
00471         if ( $file->isDeleted( File::DELETED_FILE ) ) {
00472             $vals['filehidden'] = '';
00473             $anyHidden = true;
00474         }
00475 
00476         if ( $anyHidden && $file->isDeleted( File::DELETED_RESTRICTED ) ) {
00477             $vals['suppressed'] = true;
00478         }
00479 
00480         if ( !$canShowField( File::DELETED_FILE ) ) {
00481             //Early return, tidier than indenting all following things one level
00482             return $vals;
00483         }
00484 
00485         if ( $canonicaltitle ) {
00486             $vals['canonicaltitle'] = $file->getTitle()->getPrefixedText();
00487         }
00488 
00489         if ( $url ) {
00490             if ( !is_null( $thumbParams ) ) {
00491                 $mto = $file->transform( $thumbParams );
00492                 self::$transformCount++;
00493                 if ( $mto && !$mto->isError() ) {
00494                     $vals['thumburl'] = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT );
00495 
00496                     // bug 23834 - If the URL's are the same, we haven't resized it, so shouldn't give the wanted
00497                     // thumbnail sizes for the thumbnail actual size
00498                     if ( $mto->getUrl() !== $file->getUrl() ) {
00499                         $vals['thumbwidth'] = intval( $mto->getWidth() );
00500                         $vals['thumbheight'] = intval( $mto->getHeight() );
00501                     } else {
00502                         $vals['thumbwidth'] = intval( $file->getWidth() );
00503                         $vals['thumbheight'] = intval( $file->getHeight() );
00504                     }
00505 
00506                     if ( isset( $prop['thumbmime'] ) && $file->getHandler() ) {
00507                         list( , $mime ) = $file->getHandler()->getThumbType(
00508                             $mto->getExtension(), $file->getMimeType(), $thumbParams );
00509                         $vals['thumbmime'] = $mime;
00510                     }
00511                 } elseif ( $mto && $mto->isError() ) {
00512                     $vals['thumberror'] = $mto->toText();
00513                 }
00514             }
00515             $vals['url'] = wfExpandUrl( $file->getFullURL(), PROTO_CURRENT );
00516             $vals['descriptionurl'] = wfExpandUrl( $file->getDescriptionUrl(), PROTO_CURRENT );
00517         }
00518 
00519         if ( $sha1 ) {
00520             $vals['sha1'] = wfBaseConvert( $file->getSha1(), 36, 16, 40 );
00521         }
00522 
00523         if ( $meta ) {
00524             wfSuppressWarnings();
00525             $metadata = unserialize( $file->getMetadata() );
00526             wfRestoreWarnings();
00527             if ( $metadata && $version !== 'latest' ) {
00528                 $metadata = $file->convertMetadataVersion( $metadata, $version );
00529             }
00530             $vals['metadata'] = $metadata ? self::processMetaData( $metadata, $result ) : null;
00531         }
00532         if ( $commonmeta ) {
00533             $metaArray = $file->getCommonMetaArray();
00534             $vals['commonmetadata'] = $metaArray ? self::processMetaData( $metaArray, $result ) : array();
00535         }
00536 
00537         if ( $extmetadata ) {
00538             // Note, this should return an array where all the keys
00539             // start with a letter, and all the values are strings.
00540             // Thus there should be no issue with format=xml.
00541             $format = new FormatMetadata;
00542             $format->setSingleLanguage( !$opts['multilang'] );
00543             $format->getContext()->setLanguage( $opts['language'] );
00544             $extmetaArray = $format->fetchExtendedMetadata( $file );
00545             if ( $opts['extmetadatafilter'] ) {
00546                 $extmetaArray = array_intersect_key(
00547                     $extmetaArray, array_flip( $opts['extmetadatafilter'] )
00548                 );
00549             }
00550             $vals['extmetadata'] = $extmetaArray;
00551         }
00552 
00553         if ( $mime ) {
00554             $vals['mime'] = $file->getMimeType();
00555         }
00556 
00557         if ( $mediatype ) {
00558             $vals['mediatype'] = $file->getMediaType();
00559         }
00560 
00561         if ( $archive && $file->isOld() ) {
00562             $vals['archivename'] = $file->getArchiveName();
00563         }
00564 
00565         if ( $bitdepth ) {
00566             $vals['bitdepth'] = $file->getBitDepth();
00567         }
00568 
00569         return $vals;
00570     }
00571 
00579     static function getTransformCount() {
00580         return self::$transformCount;
00581     }
00582 
00589     public static function processMetaData( $metadata, $result ) {
00590         $retval = array();
00591         if ( is_array( $metadata ) ) {
00592             foreach ( $metadata as $key => $value ) {
00593                 $r = array( 'name' => $key );
00594                 if ( is_array( $value ) ) {
00595                     $r['value'] = self::processMetaData( $value, $result );
00596                 } else {
00597                     $r['value'] = $value;
00598                 }
00599                 $retval[] = $r;
00600             }
00601         }
00602         $result->setIndexedTagName( $retval, 'metadata' );
00603 
00604         return $retval;
00605     }
00606 
00607     public function getCacheMode( $params ) {
00608         if ( $this->userCanSeeRevDel() ) {
00609             return 'private';
00610         }
00611 
00612         return 'public';
00613     }
00614 
00620     protected function getContinueStr( $img, $start = null ) {
00621         if ( $start === null ) {
00622             $start = $img->getTimestamp();
00623         }
00624 
00625         return $img->getOriginalTitle()->getDBkey() . '|' . $start;
00626     }
00627 
00628     public function getAllowedParams() {
00629         global $wgContLang;
00630 
00631         return array(
00632             'prop' => array(
00633                 ApiBase::PARAM_ISMULTI => true,
00634                 ApiBase::PARAM_DFLT => 'timestamp|user',
00635                 ApiBase::PARAM_TYPE => self::getPropertyNames()
00636             ),
00637             'limit' => array(
00638                 ApiBase::PARAM_TYPE => 'limit',
00639                 ApiBase::PARAM_DFLT => 1,
00640                 ApiBase::PARAM_MIN => 1,
00641                 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
00642                 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
00643             ),
00644             'start' => array(
00645                 ApiBase::PARAM_TYPE => 'timestamp'
00646             ),
00647             'end' => array(
00648                 ApiBase::PARAM_TYPE => 'timestamp'
00649             ),
00650             'urlwidth' => array(
00651                 ApiBase::PARAM_TYPE => 'integer',
00652                 ApiBase::PARAM_DFLT => -1
00653             ),
00654             'urlheight' => array(
00655                 ApiBase::PARAM_TYPE => 'integer',
00656                 ApiBase::PARAM_DFLT => -1
00657             ),
00658             'metadataversion' => array(
00659                 ApiBase::PARAM_TYPE => 'string',
00660                 ApiBase::PARAM_DFLT => '1',
00661             ),
00662             'extmetadatalanguage' => array(
00663                 ApiBase::PARAM_TYPE => 'string',
00664                 ApiBase::PARAM_DFLT => $wgContLang->getCode(),
00665             ),
00666             'extmetadatamultilang' => array(
00667                 ApiBase::PARAM_TYPE => 'boolean',
00668                 ApiBase::PARAM_DFLT => false,
00669             ),
00670             'extmetadatafilter' => array(
00671                 ApiBase::PARAM_TYPE => 'string',
00672                 ApiBase::PARAM_ISMULTI => true,
00673             ),
00674             'urlparam' => array(
00675                 ApiBase::PARAM_DFLT => '',
00676                 ApiBase::PARAM_TYPE => 'string',
00677             ),
00678             'continue' => null,
00679             'localonly' => false,
00680         );
00681     }
00682 
00690     public static function getPropertyNames( $filter = array() ) {
00691         return array_diff( array_keys( self::getProperties() ), $filter );
00692     }
00693 
00700     private static function getProperties( $modulePrefix = '' ) {
00701         return array(
00702             'timestamp' =>      ' timestamp     - Adds timestamp for the uploaded version',
00703             'user' =>           ' user          - Adds the user who uploaded the image version',
00704             'userid' =>         ' userid        - Add the user ID that uploaded the image version',
00705             'comment' =>        ' comment       - Comment on the version',
00706             'parsedcomment' =>  ' parsedcomment - Parse the comment on the version',
00707             'canonicaltitle' => ' canonicaltitle - Adds the canonical title of the image file',
00708             'url' =>            ' url           - Gives URL to the image and the description page',
00709             'size' =>           ' size          - Adds the size of the image in bytes, ' .
00710                 'its height and its width. Page count and duration are added if applicable',
00711             'dimensions' =>     ' dimensions    - Alias for size', // B/C with Allimages
00712             'sha1' =>           ' sha1          - Adds SHA-1 hash for the image',
00713             'mime' =>           ' mime          - Adds MIME type of the image',
00714             'thumbmime' =>      ' thumbmime     - Adds MIME type of the image thumbnail' .
00715                 ' (requires url and param ' . $modulePrefix . 'urlwidth)',
00716             'mediatype' =>      ' mediatype     - Adds the media type of the image',
00717             'metadata' =>       ' metadata      - Lists Exif metadata for the version of the image',
00718             'commonmetadata' => ' commonmetadata - Lists file format generic metadata ' .
00719                 'for the version of the image',
00720             'extmetadata' =>    ' extmetadata   - Lists formatted metadata combined ' .
00721                 'from multiple sources. Results are HTML formatted.',
00722             'archivename' =>    ' archivename   - Adds the file name of the archive ' .
00723                 'version for non-latest versions',
00724             'bitdepth' =>       ' bitdepth      - Adds the bit depth of the version',
00725             'uploadwarning' =>  ' uploadwarning - Used by the Special:Upload page to ' .
00726                 'get information about an existing file. Not intended for use outside MediaWiki core',
00727         );
00728     }
00729 
00737     public static function getPropertyDescriptions( $filter = array(), $modulePrefix = '' ) {
00738         return array_merge(
00739             array( 'What image information to get:' ),
00740             array_values( array_diff_key( self::getProperties( $modulePrefix ), array_flip( $filter ) ) )
00741         );
00742     }
00743 
00748     public function getParamDescription() {
00749         $p = $this->getModulePrefix();
00750 
00751         return array(
00752             'prop' => self::getPropertyDescriptions( array(), $p ),
00753             'urlwidth' => array(
00754                 "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
00755                 'For performance reasons if this option is used, ' .
00756                     'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.'
00757             ),
00758             'urlheight' => "Similar to {$p}urlwidth.",
00759             'urlparam' => array(
00760                 "A handler specific parameter string. For example, pdf's ",
00761                 "might use 'page15-100px'."
00762             ),
00763             'limit' => 'How many image revisions to return per image',
00764             'start' => 'Timestamp to start listing from',
00765             'end' => 'Timestamp to stop listing at',
00766             'metadataversion'
00767                 => array( "Version of metadata to use. if 'latest' is specified, use latest version.",
00768                 "Defaults to '1' for backwards compatibility" ),
00769             'extmetadatalanguage' => array(
00770                 'What language to fetch extmetadata in. This affects both which',
00771                 'translation to fetch, if multiple are available, as well as how things',
00772                 'like numbers and various values are formatted.'
00773             ),
00774             'extmetadatamultilang'
00775                 =>'If translations for extmetadata property are available, fetch all of them.',
00776             'extmetadatafilter'
00777                 => "If specified and non-empty, only these keys will be returned for {$p}prop=extmetadata",
00778             'continue' => 'If the query response includes a continue value, ' .
00779                 'use it here to get another page of results',
00780             'localonly' => 'Look only for files in the local repository',
00781         );
00782     }
00783 
00784     public function getDescription() {
00785         return 'Returns image information and upload history.';
00786     }
00787 
00788     public function getExamples() {
00789         return array(
00790             'api.php?action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo',
00791             'api.php?action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&' .
00792                 'iiend=20071231235959&iiprop=timestamp|user|url',
00793         );
00794     }
00795 
00796     public function getHelpUrls() {
00797         return 'https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii';
00798     }
00799 }