MediaWiki
REL1_23
|
00001 <?php 00032 class ApiQueryImageInfo extends ApiQueryBase { 00033 const TRANSFORM_LIMIT = 50; 00034 private static $transformCount = 0; 00035 00036 public function __construct( $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 $scale = null; 00241 if ( $params['urlparam'] ) { 00242 $this->dieUsage( "{$p}urlparam requires {$p}urlwidth", "urlparam_no_width" ); 00243 } 00244 } 00245 00246 return $scale; 00247 } 00248 00258 protected function mergeThumbParams( $image, $thumbParams, $otherParams ) { 00259 global $wgThumbLimits; 00260 00261 if ( !isset( $thumbParams['width'] ) && isset( $thumbParams['height'] ) ) { 00262 // We want to limit only by height in this situation, so pass the 00263 // image's full width as the limiting width. But some file types 00264 // don't have a width of their own, so pick something arbitrary so 00265 // thumbnailing the default icon works. 00266 if ( $image->getWidth() <= 0 ) { 00267 $thumbParams['width'] = max( $wgThumbLimits ); 00268 } else { 00269 $thumbParams['width'] = $image->getWidth(); 00270 } 00271 } 00272 00273 if ( !$otherParams ) { 00274 return $thumbParams; 00275 } 00276 $p = $this->getModulePrefix(); 00277 00278 $h = $image->getHandler(); 00279 if ( !$h ) { 00280 $this->setWarning( 'Could not create thumbnail because ' . 00281 $image->getName() . ' does not have an associated image handler' ); 00282 00283 return $thumbParams; 00284 } 00285 00286 $paramList = $h->parseParamString( $otherParams ); 00287 if ( !$paramList ) { 00288 // Just set a warning (instead of dieUsage), as in many cases 00289 // we could still render the image using width and height parameters, 00290 // and this type of thing could happen between different versions of 00291 // handlers. 00292 $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName() 00293 . '. Using only width and height' ); 00294 00295 return $thumbParams; 00296 } 00297 00298 if ( isset( $paramList['width'] ) ) { 00299 if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) { 00300 $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) " 00301 . "in favor of width value derived from {$p}urlwidth/{$p}urlheight " 00302 . "({$thumbParams['width']})" ); 00303 } 00304 } 00305 00306 foreach ( $paramList as $name => $value ) { 00307 if ( !$h->validateParam( $name, $value ) ) { 00308 $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", "urlparam" ); 00309 } 00310 } 00311 00312 return $thumbParams + $paramList; 00313 } 00314 00330 static function getInfo( $file, $prop, $result, $thumbParams = null, $opts = false ) { 00331 global $wgContLang; 00332 00333 $anyHidden = false; 00334 00335 if ( !$opts || is_string( $opts ) ) { 00336 $opts = array( 00337 'version' => $opts ?: 'latest', 00338 'language' => $wgContLang, 00339 'multilang' => false, 00340 'extmetadatafilter' => array(), 00341 'revdelUser' => null, 00342 ); 00343 } 00344 $version = $opts['version']; 00345 $vals = array(); 00346 // Timestamp is shown even if the file is revdelete'd in interface 00347 // so do same here. 00348 if ( isset( $prop['timestamp'] ) ) { 00349 $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $file->getTimestamp() ); 00350 } 00351 00352 // Handle external callers who don't pass revdelUser 00353 if ( isset( $opts['revdelUser'] ) && $opts['revdelUser'] ) { 00354 $revdelUser = $opts['revdelUser']; 00355 $canShowField = function ( $field ) use ( $file, $revdelUser ) { 00356 return $file->userCan( $field, $revdelUser ); 00357 }; 00358 } else { 00359 $canShowField = function ( $field ) use ( $file ) { 00360 return !$file->isDeleted( $field ); 00361 }; 00362 } 00363 00364 $user = isset( $prop['user'] ); 00365 $userid = isset( $prop['userid'] ); 00366 00367 if ( $user || $userid ) { 00368 if ( $file->isDeleted( File::DELETED_USER ) ) { 00369 $vals['userhidden'] = ''; 00370 $anyHidden = true; 00371 } 00372 if ( $canShowField( File::DELETED_USER ) ) { 00373 if ( $user ) { 00374 $vals['user'] = $file->getUser(); 00375 } 00376 if ( $userid ) { 00377 $vals['userid'] = $file->getUser( 'id' ); 00378 } 00379 if ( !$file->getUser( 'id' ) ) { 00380 $vals['anon'] = ''; 00381 } 00382 } 00383 } 00384 00385 // This is shown even if the file is revdelete'd in interface 00386 // so do same here. 00387 if ( isset( $prop['size'] ) || isset( $prop['dimensions'] ) ) { 00388 $vals['size'] = intval( $file->getSize() ); 00389 $vals['width'] = intval( $file->getWidth() ); 00390 $vals['height'] = intval( $file->getHeight() ); 00391 00392 $pageCount = $file->pageCount(); 00393 if ( $pageCount !== false ) { 00394 $vals['pagecount'] = $pageCount; 00395 } 00396 } 00397 00398 $pcomment = isset( $prop['parsedcomment'] ); 00399 $comment = isset( $prop['comment'] ); 00400 00401 if ( $pcomment || $comment ) { 00402 if ( $file->isDeleted( File::DELETED_COMMENT ) ) { 00403 $vals['commenthidden'] = ''; 00404 $anyHidden = true; 00405 } 00406 if ( $canShowField( File::DELETED_COMMENT ) ) { 00407 if ( $pcomment ) { 00408 $vals['parsedcomment'] = Linker::formatComment( 00409 $file->getDescription( File::RAW ), $file->getTitle() ); 00410 } 00411 if ( $comment ) { 00412 $vals['comment'] = $file->getDescription( File::RAW ); 00413 } 00414 } 00415 } 00416 00417 $canonicaltitle = isset( $prop['canonicaltitle'] ); 00418 $url = isset( $prop['url'] ); 00419 $sha1 = isset( $prop['sha1'] ); 00420 $meta = isset( $prop['metadata'] ); 00421 $extmetadata = isset( $prop['extmetadata'] ); 00422 $commonmeta = isset( $prop['commonmetadata'] ); 00423 $mime = isset( $prop['mime'] ); 00424 $mediatype = isset( $prop['mediatype'] ); 00425 $archive = isset( $prop['archivename'] ); 00426 $bitdepth = isset( $prop['bitdepth'] ); 00427 $uploadwarning = isset( $prop['uploadwarning'] ); 00428 00429 if ( $uploadwarning ) { 00430 $vals['html'] = SpecialUpload::getExistsWarning( UploadBase::getExistsWarning( $file ) ); 00431 } 00432 00433 if ( $file->isDeleted( File::DELETED_FILE ) ) { 00434 $vals['filehidden'] = ''; 00435 $anyHidden = true; 00436 } 00437 00438 if ( $anyHidden && $file->isDeleted( File::DELETED_RESTRICTED ) ) { 00439 $vals['suppressed'] = true; 00440 } 00441 00442 if ( !$canShowField( File::DELETED_FILE ) ) { 00443 //Early return, tidier than indenting all following things one level 00444 return $vals; 00445 } 00446 00447 if ( $canonicaltitle ) { 00448 $vals['canonicaltitle'] = $file->getTitle()->getPrefixedText(); 00449 } 00450 00451 if ( $url ) { 00452 if ( !is_null( $thumbParams ) ) { 00453 $mto = $file->transform( $thumbParams ); 00454 self::$transformCount++; 00455 if ( $mto && !$mto->isError() ) { 00456 $vals['thumburl'] = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT ); 00457 00458 // bug 23834 - If the URL's are the same, we haven't resized it, so shouldn't give the wanted 00459 // thumbnail sizes for the thumbnail actual size 00460 if ( $mto->getUrl() !== $file->getUrl() ) { 00461 $vals['thumbwidth'] = intval( $mto->getWidth() ); 00462 $vals['thumbheight'] = intval( $mto->getHeight() ); 00463 } else { 00464 $vals['thumbwidth'] = intval( $file->getWidth() ); 00465 $vals['thumbheight'] = intval( $file->getHeight() ); 00466 } 00467 00468 if ( isset( $prop['thumbmime'] ) && $file->getHandler() ) { 00469 list( , $mime ) = $file->getHandler()->getThumbType( 00470 $mto->getExtension(), $file->getMimeType(), $thumbParams ); 00471 $vals['thumbmime'] = $mime; 00472 } 00473 } elseif ( $mto && $mto->isError() ) { 00474 $vals['thumberror'] = $mto->toText(); 00475 } 00476 } 00477 $vals['url'] = wfExpandUrl( $file->getFullURL(), PROTO_CURRENT ); 00478 $vals['descriptionurl'] = wfExpandUrl( $file->getDescriptionUrl(), PROTO_CURRENT ); 00479 } 00480 00481 if ( $sha1 ) { 00482 $vals['sha1'] = wfBaseConvert( $file->getSha1(), 36, 16, 40 ); 00483 } 00484 00485 if ( $meta ) { 00486 wfSuppressWarnings(); 00487 $metadata = unserialize( $file->getMetadata() ); 00488 wfRestoreWarnings(); 00489 if ( $metadata && $version !== 'latest' ) { 00490 $metadata = $file->convertMetadataVersion( $metadata, $version ); 00491 } 00492 $vals['metadata'] = $metadata ? self::processMetaData( $metadata, $result ) : null; 00493 } 00494 if ( $commonmeta ) { 00495 $metaArray = $file->getCommonMetaArray(); 00496 $vals['commonmetadata'] = $metaArray ? self::processMetaData( $metaArray, $result ) : array(); 00497 } 00498 00499 if ( $extmetadata ) { 00500 // Note, this should return an array where all the keys 00501 // start with a letter, and all the values are strings. 00502 // Thus there should be no issue with format=xml. 00503 $format = new FormatMetadata; 00504 $format->setSingleLanguage( !$opts['multilang'] ); 00505 $format->getContext()->setLanguage( $opts['language'] ); 00506 $extmetaArray = $format->fetchExtendedMetadata( $file ); 00507 if ( $opts['extmetadatafilter'] ) { 00508 $extmetaArray = array_intersect_key( 00509 $extmetaArray, array_flip( $opts['extmetadatafilter'] ) 00510 ); 00511 } 00512 $vals['extmetadata'] = $extmetaArray; 00513 } 00514 00515 if ( $mime ) { 00516 $vals['mime'] = $file->getMimeType(); 00517 } 00518 00519 if ( $mediatype ) { 00520 $vals['mediatype'] = $file->getMediaType(); 00521 } 00522 00523 if ( $archive && $file->isOld() ) { 00524 $vals['archivename'] = $file->getArchiveName(); 00525 } 00526 00527 if ( $bitdepth ) { 00528 $vals['bitdepth'] = $file->getBitDepth(); 00529 } 00530 00531 return $vals; 00532 } 00533 00541 static function getTransformCount() { 00542 return self::$transformCount; 00543 } 00544 00551 public static function processMetaData( $metadata, $result ) { 00552 $retval = array(); 00553 if ( is_array( $metadata ) ) { 00554 foreach ( $metadata as $key => $value ) { 00555 $r = array( 'name' => $key ); 00556 if ( is_array( $value ) ) { 00557 $r['value'] = self::processMetaData( $value, $result ); 00558 } else { 00559 $r['value'] = $value; 00560 } 00561 $retval[] = $r; 00562 } 00563 } 00564 $result->setIndexedTagName( $retval, 'metadata' ); 00565 00566 return $retval; 00567 } 00568 00569 public function getCacheMode( $params ) { 00570 if ( $this->userCanSeeRevDel() ) { 00571 return 'private'; 00572 } 00573 00574 return 'public'; 00575 } 00576 00582 protected function getContinueStr( $img, $start = null ) { 00583 if ( $start === null ) { 00584 $start = $img->getTimestamp(); 00585 } 00586 00587 return $img->getOriginalTitle()->getDBkey() . '|' . $start; 00588 } 00589 00590 public function getAllowedParams() { 00591 global $wgContLang; 00592 00593 return array( 00594 'prop' => array( 00595 ApiBase::PARAM_ISMULTI => true, 00596 ApiBase::PARAM_DFLT => 'timestamp|user', 00597 ApiBase::PARAM_TYPE => self::getPropertyNames() 00598 ), 00599 'limit' => array( 00600 ApiBase::PARAM_TYPE => 'limit', 00601 ApiBase::PARAM_DFLT => 1, 00602 ApiBase::PARAM_MIN => 1, 00603 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, 00604 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 00605 ), 00606 'start' => array( 00607 ApiBase::PARAM_TYPE => 'timestamp' 00608 ), 00609 'end' => array( 00610 ApiBase::PARAM_TYPE => 'timestamp' 00611 ), 00612 'urlwidth' => array( 00613 ApiBase::PARAM_TYPE => 'integer', 00614 ApiBase::PARAM_DFLT => -1 00615 ), 00616 'urlheight' => array( 00617 ApiBase::PARAM_TYPE => 'integer', 00618 ApiBase::PARAM_DFLT => -1 00619 ), 00620 'metadataversion' => array( 00621 ApiBase::PARAM_TYPE => 'string', 00622 ApiBase::PARAM_DFLT => '1', 00623 ), 00624 'extmetadatalanguage' => array( 00625 ApiBase::PARAM_TYPE => 'string', 00626 ApiBase::PARAM_DFLT => $wgContLang->getCode(), 00627 ), 00628 'extmetadatamultilang' => array( 00629 ApiBase::PARAM_TYPE => 'boolean', 00630 ApiBase::PARAM_DFLT => false, 00631 ), 00632 'extmetadatafilter' => array( 00633 ApiBase::PARAM_TYPE => 'string', 00634 ApiBase::PARAM_ISMULTI => true, 00635 ), 00636 'urlparam' => array( 00637 ApiBase::PARAM_DFLT => '', 00638 ApiBase::PARAM_TYPE => 'string', 00639 ), 00640 'continue' => null, 00641 'localonly' => false, 00642 ); 00643 } 00644 00652 public static function getPropertyNames( $filter = array() ) { 00653 return array_diff( array_keys( self::getProperties() ), $filter ); 00654 } 00655 00662 private static function getProperties( $modulePrefix = '' ) { 00663 return array( 00664 'timestamp' => ' timestamp - Adds timestamp for the uploaded version', 00665 'user' => ' user - Adds the user who uploaded the image version', 00666 'userid' => ' userid - Add the user ID that uploaded the image version', 00667 'comment' => ' comment - Comment on the version', 00668 'parsedcomment' => ' parsedcomment - Parse the comment on the version', 00669 'canonicaltitle' => ' canonicaltitle - Adds the canonical title of the image file', 00670 'url' => ' url - Gives URL to the image and the description page', 00671 'size' => ' size - Adds the size of the image in bytes ' . 00672 'and the height, width and page count (if applicable)', 00673 'dimensions' => ' dimensions - Alias for size', // B/C with Allimages 00674 'sha1' => ' sha1 - Adds SHA-1 hash for the image', 00675 'mime' => ' mime - Adds MIME type of the image', 00676 'thumbmime' => ' thumbmime - Adds MIME type of the image thumbnail' . 00677 ' (requires url and param ' . $modulePrefix . 'urlwidth)', 00678 'mediatype' => ' mediatype - Adds the media type of the image', 00679 'metadata' => ' metadata - Lists Exif metadata for the version of the image', 00680 'commonmetadata' => ' commonmetadata - Lists file format generic metadata ' . 00681 'for the version of the image', 00682 'extmetadata' => ' extmetadata - Lists formatted metadata combined ' . 00683 'from multiple sources. Results are HTML formatted.', 00684 'archivename' => ' archivename - Adds the file name of the archive ' . 00685 'version for non-latest versions', 00686 'bitdepth' => ' bitdepth - Adds the bit depth of the version', 00687 'uploadwarning' => ' uploadwarning - Used by the Special:Upload page to ' . 00688 'get information about an existing file. Not intended for use outside MediaWiki core', 00689 ); 00690 } 00691 00699 public static function getPropertyDescriptions( $filter = array(), $modulePrefix = '' ) { 00700 return array_merge( 00701 array( 'What image information to get:' ), 00702 array_values( array_diff_key( self::getProperties( $modulePrefix ), array_flip( $filter ) ) ) 00703 ); 00704 } 00705 00710 public function getParamDescription() { 00711 $p = $this->getModulePrefix(); 00712 00713 return array( 00714 'prop' => self::getPropertyDescriptions( array(), $p ), 00715 'urlwidth' => array( 00716 "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.", 00717 'For performance reasons if this option is used, ' . 00718 'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.' 00719 ), 00720 'urlheight' => "Similar to {$p}urlwidth.", 00721 'urlparam' => array( "A handler specific parameter string. For example, pdf's ", 00722 "might use 'page15-100px'. {$p}urlwidth must be used and be consistent with {$p}urlparam" ), 00723 'limit' => 'How many image revisions to return per image', 00724 'start' => 'Timestamp to start listing from', 00725 'end' => 'Timestamp to stop listing at', 00726 'metadataversion' 00727 => array( "Version of metadata to use. if 'latest' is specified, use latest version.", 00728 "Defaults to '1' for backwards compatibility" ), 00729 'extmetadatalanguage' => array( 00730 'What language to fetch extmetadata in. This affects both which', 00731 'translation to fetch, if multiple are available, as well as how things', 00732 'like numbers and various values are formatted.' 00733 ), 00734 'extmetadatamultilang' 00735 =>'If translations for extmetadata property are available, fetch all of them.', 00736 'extmetadatafilter' 00737 => "If specified and non-empty, only these keys will be returned for {$p}prop=extmetadata", 00738 'continue' => 'If the query response includes a continue value, ' . 00739 'use it here to get another page of results', 00740 'localonly' => 'Look only for files in the local repository', 00741 ); 00742 } 00743 00744 public static function getResultPropertiesFiltered( $filter = array() ) { 00745 $props = array( 00746 'timestamp' => array( 00747 'timestamp' => 'timestamp' 00748 ), 00749 'user' => array( 00750 'userhidden' => 'boolean', 00751 'user' => 'string', 00752 'anon' => 'boolean' 00753 ), 00754 'userid' => array( 00755 'userhidden' => 'boolean', 00756 'userid' => 'integer', 00757 'anon' => 'boolean' 00758 ), 00759 'size' => array( 00760 'size' => 'integer', 00761 'width' => 'integer', 00762 'height' => 'integer', 00763 'pagecount' => array( 00764 ApiBase::PROP_TYPE => 'integer', 00765 ApiBase::PROP_NULLABLE => true 00766 ) 00767 ), 00768 'dimensions' => array( 00769 'size' => 'integer', 00770 'width' => 'integer', 00771 'height' => 'integer', 00772 'pagecount' => array( 00773 ApiBase::PROP_TYPE => 'integer', 00774 ApiBase::PROP_NULLABLE => true 00775 ) 00776 ), 00777 'comment' => array( 00778 'commenthidden' => 'boolean', 00779 'comment' => array( 00780 ApiBase::PROP_TYPE => 'string', 00781 ApiBase::PROP_NULLABLE => true 00782 ) 00783 ), 00784 'parsedcomment' => array( 00785 'commenthidden' => 'boolean', 00786 'parsedcomment' => array( 00787 ApiBase::PROP_TYPE => 'string', 00788 ApiBase::PROP_NULLABLE => true 00789 ) 00790 ), 00791 'canonicaltitle' => array( 00792 'canonicaltitle' => array( 00793 ApiBase::PROP_TYPE => 'string', 00794 ApiBase::PROP_NULLABLE => true 00795 ) 00796 ), 00797 'url' => array( 00798 'filehidden' => 'boolean', 00799 'thumburl' => array( 00800 ApiBase::PROP_TYPE => 'string', 00801 ApiBase::PROP_NULLABLE => true 00802 ), 00803 'thumbwidth' => array( 00804 ApiBase::PROP_TYPE => 'integer', 00805 ApiBase::PROP_NULLABLE => true 00806 ), 00807 'thumbheight' => array( 00808 ApiBase::PROP_TYPE => 'integer', 00809 ApiBase::PROP_NULLABLE => true 00810 ), 00811 'thumberror' => array( 00812 ApiBase::PROP_TYPE => 'string', 00813 ApiBase::PROP_NULLABLE => true 00814 ), 00815 'url' => array( 00816 ApiBase::PROP_TYPE => 'string', 00817 ApiBase::PROP_NULLABLE => true 00818 ), 00819 'descriptionurl' => array( 00820 ApiBase::PROP_TYPE => 'string', 00821 ApiBase::PROP_NULLABLE => true 00822 ) 00823 ), 00824 'sha1' => array( 00825 'filehidden' => 'boolean', 00826 'sha1' => array( 00827 ApiBase::PROP_TYPE => 'string', 00828 ApiBase::PROP_NULLABLE => true 00829 ) 00830 ), 00831 'mime' => array( 00832 'filehidden' => 'boolean', 00833 'mime' => array( 00834 ApiBase::PROP_TYPE => 'string', 00835 ApiBase::PROP_NULLABLE => true 00836 ) 00837 ), 00838 'thumbmime' => array( 00839 'filehidden' => 'boolean', 00840 'thumbmime' => array( 00841 ApiBase::PROP_TYPE => 'string', 00842 ApiBase::PROP_NULLABLE => true 00843 ) 00844 ), 00845 'mediatype' => array( 00846 'filehidden' => 'boolean', 00847 'mediatype' => array( 00848 ApiBase::PROP_TYPE => 'string', 00849 ApiBase::PROP_NULLABLE => true 00850 ) 00851 ), 00852 'archivename' => array( 00853 'filehidden' => 'boolean', 00854 'archivename' => array( 00855 ApiBase::PROP_TYPE => 'string', 00856 ApiBase::PROP_NULLABLE => true 00857 ) 00858 ), 00859 'bitdepth' => array( 00860 'filehidden' => 'boolean', 00861 'bitdepth' => array( 00862 ApiBase::PROP_TYPE => 'integer', 00863 ApiBase::PROP_NULLABLE => true 00864 ) 00865 ), 00866 ); 00867 00868 return array_diff_key( $props, array_flip( $filter ) ); 00869 } 00870 00871 public function getResultProperties() { 00872 return self::getResultPropertiesFiltered(); 00873 } 00874 00875 public function getDescription() { 00876 return 'Returns image information and upload history.'; 00877 } 00878 00879 public function getPossibleErrors() { 00880 $p = $this->getModulePrefix(); 00881 00882 return array_merge( parent::getPossibleErrors(), array( 00883 array( 'code' => "{$p}urlwidth", 'info' => "{$p}urlheight cannot be used without {$p}urlwidth" ), 00884 array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ), 00885 array( 'code' => 'urlparam_no_width', 'info' => "{$p}urlparam requires {$p}urlwidth" ), 00886 ) ); 00887 } 00888 00889 public function getExamples() { 00890 return array( 00891 'api.php?action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo', 00892 'api.php?action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&' . 00893 'iiend=20071231235959&iiprop=timestamp|user|url', 00894 ); 00895 } 00896 00897 public function getHelpUrls() { 00898 return 'https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii'; 00899 } 00900 }