MediaWiki
REL1_21
|
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 module. 00038 // Some other parts of MediaWiki construct this with a null $prefix, which used to be ignored when this only took two arguments 00039 if ( is_null( $prefix ) ) { 00040 $prefix = 'ii'; 00041 } 00042 parent::__construct( $query, $moduleName, $prefix ); 00043 } 00044 00045 public function execute() { 00046 $params = $this->extractRequestParams(); 00047 00048 $prop = array_flip( $params['prop'] ); 00049 00050 $scale = $this->getScale( $params ); 00051 00052 $pageIds = $this->getPageSet()->getAllTitlesByNamespace(); 00053 if ( !empty( $pageIds[NS_FILE] ) ) { 00054 $titles = array_keys( $pageIds[NS_FILE] ); 00055 asort( $titles ); // Ensure the order is always the same 00056 00057 $fromTitle = null; 00058 if ( !is_null( $params['continue'] ) ) { 00059 $cont = explode( '|', $params['continue'] ); 00060 $this->dieContinueUsageIf( count( $cont ) != 2 ); 00061 $fromTitle = strval( $cont[0] ); 00062 $fromTimestamp = $cont[1]; 00063 // Filter out any titles before $fromTitle 00064 foreach ( $titles as $key => $title ) { 00065 if ( $title < $fromTitle ) { 00066 unset( $titles[$key] ); 00067 } else { 00068 break; 00069 } 00070 } 00071 } 00072 00073 $result = $this->getResult(); 00074 //search only inside the local repo 00075 if( $params['localonly'] ) { 00076 $images = RepoGroup::singleton()->getLocalRepo()->findFiles( $titles ); 00077 } else { 00078 $images = RepoGroup::singleton()->findFiles( $titles ); 00079 } 00080 foreach ( $titles as $title ) { 00081 $pageId = $pageIds[NS_FILE][$title]; 00082 $start = $title === $fromTitle ? $fromTimestamp : $params['start']; 00083 00084 if ( !isset( $images[$title] ) ) { 00085 $result->addValue( 00086 array( 'query', 'pages', intval( $pageId ) ), 00087 'imagerepository', '' 00088 ); 00089 // The above can't fail because it doesn't increase the result size 00090 continue; 00091 } 00092 00094 $img = $images[$title]; 00095 00096 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) { 00097 if ( count( $pageIds[NS_FILE] ) == 1 ) { 00098 // See the 'the user is screwed' comment below 00099 $this->setContinueEnumParameter( 'start', 00100 $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) 00101 ); 00102 } else { 00103 $this->setContinueEnumParameter( 'continue', 00104 $this->getContinueStr( $img, $start ) ); 00105 } 00106 break; 00107 } 00108 00109 $fit = $result->addValue( 00110 array( 'query', 'pages', intval( $pageId ) ), 00111 'imagerepository', $img->getRepoName() 00112 ); 00113 if ( !$fit ) { 00114 if ( count( $pageIds[NS_FILE] ) == 1 ) { 00115 // The user is screwed. imageinfo can't be solely 00116 // responsible for exceeding the limit in this case, 00117 // so set a query-continue that just returns the same 00118 // thing again. When the violating queries have been 00119 // out-continued, the result will get through 00120 $this->setContinueEnumParameter( 'start', 00121 $start !== null ? $start : wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) 00122 ); 00123 } else { 00124 $this->setContinueEnumParameter( 'continue', 00125 $this->getContinueStr( $img, $start ) ); 00126 } 00127 break; 00128 } 00129 00130 // Check if we can make the requested thumbnail, and get transform parameters. 00131 $finalThumbParams = $this->mergeThumbParams( $img, $scale, $params['urlparam'] ); 00132 00133 // Get information about the current version first 00134 // Check that the current version is within the start-end boundaries 00135 $gotOne = false; 00136 if ( 00137 ( is_null( $start ) || $img->getTimestamp() <= $start ) && 00138 ( is_null( $params['end'] ) || $img->getTimestamp() >= $params['end'] ) 00139 ) { 00140 $gotOne = true; 00141 00142 $fit = $this->addPageSubItem( $pageId, 00143 self::getInfo( $img, $prop, $result, 00144 $finalThumbParams, $params['metadataversion'] ) ); 00145 if ( !$fit ) { 00146 if ( count( $pageIds[NS_FILE] ) == 1 ) { 00147 // See the 'the user is screwed' comment above 00148 $this->setContinueEnumParameter( 'start', 00149 wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) ); 00150 } else { 00151 $this->setContinueEnumParameter( 'continue', 00152 $this->getContinueStr( $img ) ); 00153 } 00154 break; 00155 } 00156 } 00157 00158 // Now get the old revisions 00159 // Get one more to facilitate query-continue functionality 00160 $count = ( $gotOne ? 1 : 0 ); 00161 $oldies = $img->getHistory( $params['limit'] - $count + 1, $start, $params['end'] ); 00163 foreach ( $oldies as $oldie ) { 00164 if ( ++$count > $params['limit'] ) { 00165 // We've reached the extra one which shows that there are additional pages to be had. Stop here... 00166 // Only set a query-continue if there was only one title 00167 if ( count( $pageIds[NS_FILE] ) == 1 ) { 00168 $this->setContinueEnumParameter( 'start', 00169 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) ); 00170 } 00171 break; 00172 } 00173 $fit = $this->addPageSubItem( $pageId, 00174 self::getInfo( $oldie, $prop, $result, 00175 $finalThumbParams, $params['metadataversion'] ) ); 00176 if ( !$fit ) { 00177 if ( count( $pageIds[NS_FILE] ) == 1 ) { 00178 $this->setContinueEnumParameter( 'start', 00179 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) ); 00180 } else { 00181 $this->setContinueEnumParameter( 'continue', 00182 $this->getContinueStr( $oldie ) ); 00183 } 00184 break; 00185 } 00186 } 00187 if ( !$fit ) { 00188 break; 00189 } 00190 } 00191 } 00192 } 00193 00199 public function getScale( $params ) { 00200 $p = $this->getModulePrefix(); 00201 00202 // Height and width. 00203 if ( $params['urlheight'] != -1 && $params['urlwidth'] == -1 ) { 00204 $this->dieUsage( "{$p}urlheight cannot be used without {$p}urlwidth", "{$p}urlwidth" ); 00205 } 00206 00207 if ( $params['urlwidth'] != -1 ) { 00208 $scale = array(); 00209 $scale['width'] = $params['urlwidth']; 00210 $scale['height'] = $params['urlheight']; 00211 } else { 00212 $scale = null; 00213 if ( $params['urlparam'] ) { 00214 $this->dieUsage( "{$p}urlparam requires {$p}urlwidth", "urlparam_no_width" ); 00215 } 00216 return $scale; 00217 } 00218 00219 return $scale; 00220 } 00221 00231 protected function mergeThumbParams ( $image, $thumbParams, $otherParams ) { 00232 if ( !$otherParams ) { 00233 return $thumbParams; 00234 } 00235 $p = $this->getModulePrefix(); 00236 00237 $h = $image->getHandler(); 00238 if ( !$h ) { 00239 $this->setWarning( 'Could not create thumbnail because ' . 00240 $image->getName() . ' does not have an associated image handler' ); 00241 return $thumbParams; 00242 } 00243 00244 $paramList = $h->parseParamString( $otherParams ); 00245 if ( !$paramList ) { 00246 // Just set a warning (instead of dieUsage), as in many cases 00247 // we could still render the image using width and height parameters, 00248 // and this type of thing could happen between different versions of 00249 // handlers. 00250 $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName() 00251 . '. Using only width and height' ); 00252 return $thumbParams; 00253 } 00254 00255 if ( isset( $paramList['width'] ) ) { 00256 if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) { 00257 $this->dieUsage( "{$p}urlparam had width of {$paramList['width']} but " 00258 . "{$p}urlwidth was {$thumbParams['width']}", "urlparam_urlwidth_mismatch" ); 00259 } 00260 } 00261 00262 foreach ( $paramList as $name => $value ) { 00263 if ( !$h->validateParam( $name, $value ) ) { 00264 $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", "urlparam" ); 00265 } 00266 } 00267 00268 return $thumbParams + $paramList; 00269 } 00270 00281 static function getInfo( $file, $prop, $result, $thumbParams = null, $version = 'latest' ) { 00282 $vals = array(); 00283 // Timestamp is shown even if the file is revdelete'd in interface 00284 // so do same here. 00285 if ( isset( $prop['timestamp'] ) ) { 00286 $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $file->getTimestamp() ); 00287 } 00288 00289 $user = isset( $prop['user'] ); 00290 $userid = isset( $prop['userid'] ); 00291 00292 if ( $user || $userid ) { 00293 if ( $file->isDeleted( File::DELETED_USER ) ) { 00294 $vals['userhidden'] = ''; 00295 } else { 00296 if ( $user ) { 00297 $vals['user'] = $file->getUser(); 00298 } 00299 if ( $userid ) { 00300 $vals['userid'] = $file->getUser( 'id' ); 00301 } 00302 if ( !$file->getUser( 'id' ) ) { 00303 $vals['anon'] = ''; 00304 } 00305 } 00306 } 00307 00308 // This is shown even if the file is revdelete'd in interface 00309 // so do same here. 00310 if ( isset( $prop['size'] ) || isset( $prop['dimensions'] ) ) { 00311 $vals['size'] = intval( $file->getSize() ); 00312 $vals['width'] = intval( $file->getWidth() ); 00313 $vals['height'] = intval( $file->getHeight() ); 00314 00315 $pageCount = $file->pageCount(); 00316 if ( $pageCount !== false ) { 00317 $vals['pagecount'] = $pageCount; 00318 } 00319 } 00320 00321 $pcomment = isset( $prop['parsedcomment'] ); 00322 $comment = isset( $prop['comment'] ); 00323 00324 if ( $pcomment || $comment ) { 00325 if ( $file->isDeleted( File::DELETED_COMMENT ) ) { 00326 $vals['commenthidden'] = ''; 00327 } else { 00328 if ( $pcomment ) { 00329 $vals['parsedcomment'] = Linker::formatComment( 00330 $file->getDescription(), $file->getTitle() ); 00331 } 00332 if ( $comment ) { 00333 $vals['comment'] = $file->getDescription(); 00334 } 00335 } 00336 } 00337 00338 $url = isset( $prop['url'] ); 00339 $sha1 = isset( $prop['sha1'] ); 00340 $meta = isset( $prop['metadata'] ); 00341 $mime = isset( $prop['mime'] ); 00342 $mediatype = isset( $prop['mediatype'] ); 00343 $archive = isset( $prop['archivename'] ); 00344 $bitdepth = isset( $prop['bitdepth'] ); 00345 00346 if ( ( $url || $sha1 || $meta || $mime || $mediatype || $archive || $bitdepth ) 00347 && $file->isDeleted( File::DELETED_FILE ) ) { 00348 $vals['filehidden'] = ''; 00349 00350 //Early return, tidier than indenting all following things one level 00351 return $vals; 00352 } 00353 00354 if ( $url ) { 00355 if ( !is_null( $thumbParams ) ) { 00356 $mto = $file->transform( $thumbParams ); 00357 self::$transformCount++; 00358 if ( $mto && !$mto->isError() ) { 00359 $vals['thumburl'] = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT ); 00360 00361 // bug 23834 - If the URL's are the same, we haven't resized it, so shouldn't give the wanted 00362 // thumbnail sizes for the thumbnail actual size 00363 if ( $mto->getUrl() !== $file->getUrl() ) { 00364 $vals['thumbwidth'] = intval( $mto->getWidth() ); 00365 $vals['thumbheight'] = intval( $mto->getHeight() ); 00366 } else { 00367 $vals['thumbwidth'] = intval( $file->getWidth() ); 00368 $vals['thumbheight'] = intval( $file->getHeight() ); 00369 } 00370 00371 if ( isset( $prop['thumbmime'] ) && $file->getHandler() ) { 00372 list( , $mime ) = $file->getHandler()->getThumbType( 00373 $mto->getExtension(), $file->getMimeType(), $thumbParams ); 00374 $vals['thumbmime'] = $mime; 00375 } 00376 } elseif ( $mto && $mto->isError() ) { 00377 $vals['thumberror'] = $mto->toText(); 00378 } 00379 } 00380 $vals['url'] = wfExpandUrl( $file->getFullURL(), PROTO_CURRENT ); 00381 $vals['descriptionurl'] = wfExpandUrl( $file->getDescriptionUrl(), PROTO_CURRENT ); 00382 } 00383 00384 if ( $sha1 ) { 00385 $vals['sha1'] = wfBaseConvert( $file->getSha1(), 36, 16, 40 ); 00386 } 00387 00388 if ( $meta ) { 00389 wfSuppressWarnings(); 00390 $metadata = unserialize( $file->getMetadata() ); 00391 wfRestoreWarnings(); 00392 if ( $metadata && $version !== 'latest' ) { 00393 $metadata = $file->convertMetadataVersion( $metadata, $version ); 00394 } 00395 $vals['metadata'] = $metadata ? self::processMetaData( $metadata, $result ) : null; 00396 } 00397 00398 if ( $mime ) { 00399 $vals['mime'] = $file->getMimeType(); 00400 } 00401 00402 if ( $mediatype ) { 00403 $vals['mediatype'] = $file->getMediaType(); 00404 } 00405 00406 if ( $archive && $file->isOld() ) { 00407 $vals['archivename'] = $file->getArchiveName(); 00408 } 00409 00410 if ( $bitdepth ) { 00411 $vals['bitdepth'] = $file->getBitDepth(); 00412 } 00413 00414 return $vals; 00415 } 00416 00424 static function getTransformCount() { 00425 return self::$transformCount; 00426 } 00427 00434 public static function processMetaData( $metadata, $result ) { 00435 $retval = array(); 00436 if ( is_array( $metadata ) ) { 00437 foreach ( $metadata as $key => $value ) { 00438 $r = array( 'name' => $key ); 00439 if ( is_array( $value ) ) { 00440 $r['value'] = self::processMetaData( $value, $result ); 00441 } else { 00442 $r['value'] = $value; 00443 } 00444 $retval[] = $r; 00445 } 00446 } 00447 $result->setIndexedTagName( $retval, 'metadata' ); 00448 return $retval; 00449 } 00450 00451 public function getCacheMode( $params ) { 00452 return 'public'; 00453 } 00454 00460 protected function getContinueStr( $img, $start = null ) { 00461 if ( $start === null ) { 00462 $start = $img->getTimestamp(); 00463 } 00464 return $img->getOriginalTitle()->getText() . '|' . $start; 00465 } 00466 00467 public function getAllowedParams() { 00468 return array( 00469 'prop' => array( 00470 ApiBase::PARAM_ISMULTI => true, 00471 ApiBase::PARAM_DFLT => 'timestamp|user', 00472 ApiBase::PARAM_TYPE => self::getPropertyNames() 00473 ), 00474 'limit' => array( 00475 ApiBase::PARAM_TYPE => 'limit', 00476 ApiBase::PARAM_DFLT => 1, 00477 ApiBase::PARAM_MIN => 1, 00478 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, 00479 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 00480 ), 00481 'start' => array( 00482 ApiBase::PARAM_TYPE => 'timestamp' 00483 ), 00484 'end' => array( 00485 ApiBase::PARAM_TYPE => 'timestamp' 00486 ), 00487 'urlwidth' => array( 00488 ApiBase::PARAM_TYPE => 'integer', 00489 ApiBase::PARAM_DFLT => -1 00490 ), 00491 'urlheight' => array( 00492 ApiBase::PARAM_TYPE => 'integer', 00493 ApiBase::PARAM_DFLT => -1 00494 ), 00495 'metadataversion' => array( 00496 ApiBase::PARAM_TYPE => 'string', 00497 ApiBase::PARAM_DFLT => '1', 00498 ), 00499 'urlparam' => array( 00500 ApiBase::PARAM_DFLT => '', 00501 ApiBase::PARAM_TYPE => 'string', 00502 ), 00503 'continue' => null, 00504 'localonly' => false, 00505 ); 00506 } 00507 00515 public static function getPropertyNames( $filter = array() ) { 00516 return array_diff( array_keys( self::getProperties() ), $filter ); 00517 } 00518 00525 private static function getProperties( $modulePrefix = '' ) { 00526 return array( 00527 'timestamp' => ' timestamp - Adds timestamp for the uploaded version', 00528 'user' => ' user - Adds the user who uploaded the image version', 00529 'userid' => ' userid - Add the user ID that uploaded the image version', 00530 'comment' => ' comment - Comment on the version', 00531 'parsedcomment' => ' parsedcomment - Parse the comment on the version', 00532 'url' => ' url - Gives URL to the image and the description page', 00533 'size' => ' size - Adds the size of the image in bytes and the height, width and page count (if applicable)', 00534 'dimensions' => ' dimensions - Alias for size', // For backwards compatibility with Allimages 00535 'sha1' => ' sha1 - Adds SHA-1 hash for the image', 00536 'mime' => ' mime - Adds MIME type of the image', 00537 'thumbmime' => ' thumbmime - Adds MIME type of the image thumbnail' . 00538 ' (requires url and param ' . $modulePrefix . 'urlwidth)', 00539 'mediatype' => ' mediatype - Adds the media type of the image', 00540 'metadata' => ' metadata - Lists EXIF metadata for the version of the image', 00541 'archivename' => ' archivename - Adds the file name of the archive version for non-latest versions', 00542 'bitdepth' => ' bitdepth - Adds the bit depth of the version', 00543 ); 00544 } 00545 00553 public static function getPropertyDescriptions( $filter = array(), $modulePrefix = '' ) { 00554 return array_merge( 00555 array( 'What image information to get:' ), 00556 array_values( array_diff_key( self::getProperties( $modulePrefix ), array_flip( $filter ) ) ) 00557 ); 00558 } 00559 00564 public function getParamDescription() { 00565 $p = $this->getModulePrefix(); 00566 return array( 00567 'prop' => self::getPropertyDescriptions( array(), $p ), 00568 'urlwidth' => array( "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.", 00569 'Only the current version of the image can be scaled' ), 00570 'urlheight' => "Similar to {$p}urlwidth. Cannot be used without {$p}urlwidth", 00571 'urlparam' => array( "A handler specific parameter string. For example, pdf's ", 00572 "might use 'page15-100px'. {$p}urlwidth must be used and be consistent with {$p}urlparam" ), 00573 'limit' => 'How many image revisions to return', 00574 'start' => 'Timestamp to start listing from', 00575 'end' => 'Timestamp to stop listing at', 00576 'metadataversion' => array( "Version of metadata to use. if 'latest' is specified, use latest version.", 00577 "Defaults to '1' for backwards compatibility" ), 00578 'continue' => 'If the query response includes a continue value, use it here to get another page of results', 00579 'localonly' => 'Look only for files in the local repository', 00580 ); 00581 } 00582 00583 public static function getResultPropertiesFiltered( $filter = array() ) { 00584 $props = array( 00585 'timestamp' => array( 00586 'timestamp' => 'timestamp' 00587 ), 00588 'user' => array( 00589 'userhidden' => 'boolean', 00590 'user' => 'string', 00591 'anon' => 'boolean' 00592 ), 00593 'userid' => array( 00594 'userhidden' => 'boolean', 00595 'userid' => 'integer', 00596 'anon' => 'boolean' 00597 ), 00598 'size' => array( 00599 'size' => 'integer', 00600 'width' => 'integer', 00601 'height' => 'integer', 00602 'pagecount' => array( 00603 ApiBase::PROP_TYPE => 'integer', 00604 ApiBase::PROP_NULLABLE => true 00605 ) 00606 ), 00607 'dimensions' => array( 00608 'size' => 'integer', 00609 'width' => 'integer', 00610 'height' => 'integer', 00611 'pagecount' => array( 00612 ApiBase::PROP_TYPE => 'integer', 00613 ApiBase::PROP_NULLABLE => true 00614 ) 00615 ), 00616 'comment' => array( 00617 'commenthidden' => 'boolean', 00618 'comment' => array( 00619 ApiBase::PROP_TYPE => 'string', 00620 ApiBase::PROP_NULLABLE => true 00621 ) 00622 ), 00623 'parsedcomment' => array( 00624 'commenthidden' => 'boolean', 00625 'parsedcomment' => array( 00626 ApiBase::PROP_TYPE => 'string', 00627 ApiBase::PROP_NULLABLE => true 00628 ) 00629 ), 00630 'url' => array( 00631 'filehidden' => 'boolean', 00632 'thumburl' => array( 00633 ApiBase::PROP_TYPE => 'string', 00634 ApiBase::PROP_NULLABLE => true 00635 ), 00636 'thumbwidth' => array( 00637 ApiBase::PROP_TYPE => 'integer', 00638 ApiBase::PROP_NULLABLE => true 00639 ), 00640 'thumbheight' => array( 00641 ApiBase::PROP_TYPE => 'integer', 00642 ApiBase::PROP_NULLABLE => true 00643 ), 00644 'thumberror' => array( 00645 ApiBase::PROP_TYPE => 'string', 00646 ApiBase::PROP_NULLABLE => true 00647 ), 00648 'url' => array( 00649 ApiBase::PROP_TYPE => 'string', 00650 ApiBase::PROP_NULLABLE => true 00651 ), 00652 'descriptionurl' => array( 00653 ApiBase::PROP_TYPE => 'string', 00654 ApiBase::PROP_NULLABLE => true 00655 ) 00656 ), 00657 'sha1' => array( 00658 'filehidden' => 'boolean', 00659 'sha1' => array( 00660 ApiBase::PROP_TYPE => 'string', 00661 ApiBase::PROP_NULLABLE => true 00662 ) 00663 ), 00664 'mime' => array( 00665 'filehidden' => 'boolean', 00666 'mime' => array( 00667 ApiBase::PROP_TYPE => 'string', 00668 ApiBase::PROP_NULLABLE => true 00669 ) 00670 ), 00671 'thumbmime' => array( 00672 'filehidden' => 'boolean', 00673 'thumbmime' => array( 00674 ApiBase::PROP_TYPE => 'string', 00675 ApiBase::PROP_NULLABLE => true 00676 ) 00677 ), 00678 'mediatype' => array( 00679 'filehidden' => 'boolean', 00680 'mediatype' => array( 00681 ApiBase::PROP_TYPE => 'string', 00682 ApiBase::PROP_NULLABLE => true 00683 ) 00684 ), 00685 'archivename' => array( 00686 'filehidden' => 'boolean', 00687 'archivename' => array( 00688 ApiBase::PROP_TYPE => 'string', 00689 ApiBase::PROP_NULLABLE => true 00690 ) 00691 ), 00692 'bitdepth' => array( 00693 'filehidden' => 'boolean', 00694 'bitdepth' => array( 00695 ApiBase::PROP_TYPE => 'integer', 00696 ApiBase::PROP_NULLABLE => true 00697 ) 00698 ), 00699 ); 00700 return array_diff_key( $props, array_flip( $filter ) ); 00701 } 00702 00703 public function getResultProperties() { 00704 return self::getResultPropertiesFiltered(); 00705 } 00706 00707 public function getDescription() { 00708 return 'Returns image information and upload history'; 00709 } 00710 00711 public function getPossibleErrors() { 00712 $p = $this->getModulePrefix(); 00713 return array_merge( parent::getPossibleErrors(), array( 00714 array( 'code' => "{$p}urlwidth", 'info' => "{$p}urlheight cannot be used without {$p}urlwidth" ), 00715 array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ), 00716 array( 'code' => 'urlparam_no_width', 'info' => "{$p}urlparam requires {$p}urlwidth" ), 00717 array( 'code' => 'urlparam_urlwidth_mismatch', 'info' => "The width set in {$p}urlparm doesn't " . 00718 "match the one in {$p}urlwidth" ), 00719 ) ); 00720 } 00721 00722 public function getExamples() { 00723 return array( 00724 'api.php?action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo', 00725 'api.php?action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&iiend=20071231235959&iiprop=timestamp|user|url', 00726 ); 00727 } 00728 00729 public function getHelpUrls() { 00730 return 'https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii'; 00731 } 00732 }