38 private static $transformCount = 0;
44 private $contentLanguage;
47 private $badFileLookup;
60 $prefixOrRepoGroup =
null,
61 $repoGroupOrContentLanguage =
null,
62 $contentLanguageOrBadFileLookup =
null,
63 $badFileLookupOrUnused =
null
67 if ( !is_string( $prefixOrRepoGroup ) ) {
69 $repoGroup = $prefixOrRepoGroup;
70 $contentLanguage = $repoGroupOrContentLanguage;
71 $badFileLookup = $contentLanguageOrBadFileLookup;
74 $prefix = $prefixOrRepoGroup;
75 $repoGroup = $repoGroupOrContentLanguage;
76 $contentLanguage = $contentLanguageOrBadFileLookup;
77 $badFileLookup = $badFileLookupOrUnused;
79 parent::__construct( $query, $moduleName, $prefix );
81 $services = MediaWikiServices::getInstance();
82 $this->repoGroup = $repoGroup ?? $services->getRepoGroup();
83 $this->contentLanguage = $contentLanguage ?? $services->getContentLanguage();
84 $this->badFileLookup = $badFileLookup ?? $services->getBadFileLookup();
90 $prop = array_fill_keys( $params[
'prop'],
true );
95 'version' => $params[
'metadataversion'],
96 'language' => $params[
'extmetadatalanguage'],
97 'multilang' => $params[
'extmetadatamultilang'],
98 'extmetadatafilter' => $params[
'extmetadatafilter'],
102 if ( isset( $params[
'badfilecontexttitle'] ) ) {
103 $badFileContextTitle = Title::newFromText( $params[
'badfilecontexttitle'] );
104 if ( !$badFileContextTitle || $badFileContextTitle->isExternal() ) {
106 $this->
dieWithError( [
'apierror-bad-badfilecontexttitle', $p ],
'invalid-title' );
109 $badFileContextTitle =
null;
112 $pageIds = $this->
getPageSet()->getGoodAndMissingTitlesByNamespace();
113 if ( !empty( $pageIds[
NS_FILE] ) ) {
114 $titles = array_keys( $pageIds[
NS_FILE] );
118 if ( $params[
'continue'] !==
null ) {
120 $fromTitle = $cont[0];
121 $fromTimestamp = $cont[1];
123 foreach ( $titles as $key =>
$title ) {
124 if (
$title < $fromTitle ) {
125 unset( $titles[$key] );
133 $findTitles = array_map(
static function (
$title ) use ( $performer ) {
136 'private' => $performer,
140 if ( $params[
'localonly'] ) {
141 $images = $this->repoGroup->getLocalRepo()->findFiles( $findTitles );
143 $images = $this->repoGroup->findFiles( $findTitles );
147 foreach ( $titles as
$title ) {
152 $start =
$title === $fromTitle ? $fromTimestamp : $params[
'start'];
154 if ( !isset( $images[
$title] ) ) {
155 if ( isset( $prop[
'uploadwarning'] ) || isset( $prop[
'badfile'] ) ) {
157 $images[
$title] = $this->repoGroup->getLocalRepo()->newFile(
$title );
159 $info[
'imagerepository'] =
'';
162 [
'query',
'pages', (
int)$pageId ],
163 'imagerepository',
''
173 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
174 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
177 $start ??
wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
186 if ( !isset( $info[
'imagerepository'] ) ) {
187 $info[
'imagerepository'] = $img->getRepoName();
189 if ( isset( $prop[
'badfile'] ) ) {
190 $info[
'badfile'] = (bool)$this->badFileLookup->isBadFile(
$title, $badFileContextTitle );
193 $fit = $result->addValue( [
'query',
'pages' ], (
int)$pageId, $info );
195 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
202 $start ??
wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
212 $finalThumbParams = $this->
mergeThumbParams( $img, $scale, $params[
'urlparam'] );
218 if ( $badFileContextTitle && $finalThumbParams ) {
219 $finalThumbParams[
'targetlang'] = $badFileContextTitle->getPageLanguage()->getCode();
226 ( $start ===
null || $img->getTimestamp() <= $start ) &&
227 ( $params[
'end'] ===
null || $img->getTimestamp() >= $params[
'end'] )
232 static::getInfo( $img, $prop, $result,
233 $finalThumbParams, $opts
237 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
240 wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
251 $count = ( $gotOne ? 1 : 0 );
252 $oldies = $img->getHistory( $params[
'limit'] - $count + 1, $start, $params[
'end'] );
254 foreach ( $oldies as $oldie ) {
255 if ( ++$count > $params[
'limit'] ) {
259 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
261 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
267 static::getInfo( $oldie, $prop, $result,
268 $finalThumbParams, $opts
272 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
274 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
295 if ( $params[
'urlwidth'] != -1 ) {
297 $scale[
'width'] = $params[
'urlwidth'];
298 $scale[
'height'] = $params[
'urlheight'];
299 } elseif ( $params[
'urlheight'] != -1 ) {
303 $scale[
'height'] = $params[
'urlheight'];
304 } elseif ( $params[
'urlparam'] ) {
324 if ( $thumbParams ===
null ) {
328 if ( !isset( $thumbParams[
'width'] ) && isset( $thumbParams[
'height'] ) ) {
333 if ( $image->getWidth() <= 0 ) {
334 $thumbParams[
'width'] =
335 max( $this->
getConfig()->
get( MainConfigNames::ThumbLimits ) );
337 $thumbParams[
'width'] = $image->getWidth();
341 if ( !$otherParams ) {
347 $h = $image->getHandler();
354 $paramList = $h->parseParamString( $otherParams );
366 isset( $paramList[
'width'] ) && isset( $thumbParams[
'width'] ) &&
367 (
int)$paramList[
'width'] != (
int)$thumbParams[
'width']
370 [
'apiwarn-urlparamwidth', $p, $paramList[
'width'], $thumbParams[
'width'] ]
374 foreach ( $paramList as $name => $value ) {
375 if ( !$h->validateParam( $name, $value ) ) {
382 $finalParams = $thumbParams + $paramList;
399 $h = $image->getHandler();
406 if ( !$h->normaliseParams( $image, $finalParams ) ) {
426 public static function getInfo(
$file, $prop, $result, $thumbParams =
null, $opts =
false ) {
429 if ( !$opts || is_string( $opts ) ) {
431 'version' => $opts ?:
'latest',
432 'language' => MediaWikiServices::getInstance()->getContentLanguage(),
433 'multilang' =>
false,
434 'extmetadatafilter' => [],
435 'revdelUser' =>
null,
438 $version = $opts[
'version'];
440 ApiResult::META_TYPE =>
'assoc',
444 $exists =
$file->exists();
448 if ( isset( $prop[
'timestamp'] ) && $exists ) {
453 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser'] ) {
454 $revdelUser = $opts[
'revdelUser'];
455 $canShowField =
static function ( $field ) use (
$file, $revdelUser ) {
456 return $file->userCan( $field, $revdelUser );
459 $canShowField =
static function ( $field ) use (
$file ) {
460 return !
$file->isDeleted( $field );
464 $user = isset( $prop[
'user'] );
465 $userid = isset( $prop[
'userid'] );
467 if ( ( $user || $userid ) && $exists ) {
468 if (
$file->isDeleted( File::DELETED_USER ) ) {
469 $vals[
'userhidden'] =
true;
472 if ( $canShowField( File::DELETED_USER ) ) {
474 $uploader =
$file->getUploader( File::RAW );
476 $vals[
'user'] = $uploader ? $uploader->getName() :
'';
479 $vals[
'userid'] = $uploader ? $uploader->getId() : 0;
481 if ( $uploader && !$uploader->isRegistered() ) {
482 $vals[
'anon'] =
true;
489 if ( ( isset( $prop[
'size'] ) || isset( $prop[
'dimensions'] ) ) && $exists ) {
490 $vals[
'size'] = (int)
$file->getSize();
491 $vals[
'width'] = (int)
$file->getWidth();
492 $vals[
'height'] = (int)
$file->getHeight();
494 $pageCount =
$file->pageCount();
495 if ( $pageCount !==
false ) {
496 $vals[
'pagecount'] = $pageCount;
500 $length =
$file->getLength();
503 $vals[
'duration'] = (float)$length;
507 $pcomment = isset( $prop[
'parsedcomment'] );
508 $comment = isset( $prop[
'comment'] );
510 if ( ( $pcomment || $comment ) && $exists ) {
511 if (
$file->isDeleted( File::DELETED_COMMENT ) ) {
512 $vals[
'commenthidden'] =
true;
515 if ( $canShowField( File::DELETED_COMMENT ) ) {
517 $vals[
'parsedcomment'] = MediaWikiServices::getInstance()->getCommentFormatter()->format(
518 $file->getDescription( File::RAW ),
$file->getTitle() );
521 $vals[
'comment'] =
$file->getDescription( File::RAW );
526 $canonicaltitle = isset( $prop[
'canonicaltitle'] );
527 $url = isset( $prop[
'url'] );
528 $sha1 = isset( $prop[
'sha1'] );
529 $meta = isset( $prop[
'metadata'] );
530 $extmetadata = isset( $prop[
'extmetadata'] );
531 $commonmeta = isset( $prop[
'commonmetadata'] );
532 $mime = isset( $prop[
'mime'] );
533 $mediatype = isset( $prop[
'mediatype'] );
534 $archive = isset( $prop[
'archivename'] );
535 $bitdepth = isset( $prop[
'bitdepth'] );
536 $uploadwarning = isset( $prop[
'uploadwarning'] );
538 if ( $uploadwarning ) {
539 $vals[
'html'] = SpecialUpload::getExistsWarning( UploadBase::getExistsWarning(
$file ) );
542 if (
$file->isDeleted( File::DELETED_FILE ) ) {
543 $vals[
'filehidden'] =
true;
547 if ( $anyHidden &&
$file->isDeleted( File::DELETED_RESTRICTED ) ) {
548 $vals[
'suppressed'] =
true;
552 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser']
553 && !
$file->userCan( File::DELETED_FILE, $opts[
'revdelUser'] )
556 } elseif (
$file->isDeleted( File::DELETED_FILE ) ) {
560 if ( $canonicaltitle ) {
561 $vals[
'canonicaltitle'] =
$file->getTitle()->getPrefixedText();
566 if ( $thumbParams !==
null ) {
567 $mto =
$file->transform( $thumbParams );
568 self::$transformCount++;
569 if ( $mto && !$mto->isError() ) {
574 if ( $mto->getUrl() !==
$file->getUrl() ) {
575 $vals[
'thumbwidth'] = (int)$mto->getWidth();
576 $vals[
'thumbheight'] = (int)$mto->getHeight();
578 $vals[
'thumbwidth'] = (int)
$file->getWidth();
579 $vals[
'thumbheight'] = (int)
$file->getHeight();
582 if ( isset( $prop[
'thumbmime'] ) &&
$file->getHandler() ) {
583 [ ,
$mime ] =
$file->getHandler()->getThumbType(
584 $mto->getExtension(),
$file->getMimeType(), $thumbParams );
585 $vals[
'thumbmime'] =
$mime;
588 Linker::processResponsiveImages(
$file, $mto, [
589 'width' => $vals[
'thumbwidth'],
590 'height' => $vals[
'thumbheight']
592 foreach ( $mto->responsiveUrls as $density => $url ) {
595 } elseif ( $mto && $mto->isError() ) {
597 '@phan-var MediaTransformError $mto';
598 $vals[
'thumberror'] = $mto->toText();
605 $shortDescriptionUrl =
$file->getDescriptionShortUrl();
606 if ( $shortDescriptionUrl !==
null ) {
612 $vals[
'filemissing'] =
true;
615 if ( $sha1 && $exists ) {
616 $vals[
'sha1'] = Wikimedia\base_convert(
$file->getSha1(), 36, 16, 40 );
619 if ( $meta && $exists ) {
620 $metadata =
$file->getMetadataArray();
621 if ( $metadata && $version !==
'latest' ) {
622 $metadata =
$file->convertMetadataVersion( $metadata, $version );
624 $vals[
'metadata'] = $metadata ? static::processMetaData( $metadata, $result ) :
null;
626 if ( $commonmeta && $exists ) {
627 $metaArray =
$file->getCommonMetaArray();
628 $vals[
'commonmetadata'] = $metaArray ? static::processMetaData( $metaArray, $result ) : [];
631 if ( $extmetadata && $exists ) {
638 $format->getContext()->setLanguage( $opts[
'language'] );
639 $extmetaArray = $format->fetchExtendedMetadata(
$file );
640 if ( $opts[
'extmetadatafilter'] ) {
641 $extmetaArray = array_intersect_key(
642 $extmetaArray, array_fill_keys( $opts[
'extmetadatafilter'],
true )
645 $vals[
'extmetadata'] = $extmetaArray;
648 if (
$mime && $exists ) {
649 $vals[
'mime'] =
$file->getMimeType();
652 if ( $mediatype && $exists ) {
653 $vals[
'mediatype'] =
$file->getMediaType();
656 if ( $archive &&
$file->isOld() ) {
658 '@phan-var OldLocalFile $file';
659 $vals[
'archivename'] =
$file->getArchiveName();
662 if ( $bitdepth && $exists ) {
663 $vals[
'bitdepth'] =
$file->getBitDepth();
677 return self::$transformCount;
687 if ( is_array( $metadata ) ) {
688 foreach ( $metadata as $key => $value ) {
691 ApiResult::META_BC_BOOLS => [
'value' ],
693 if ( is_array( $value ) ) {
694 $r[
'value'] = static::processMetaData( $value, $result );
696 $r[
'value'] = $value;
701 ApiResult::setIndexedTagName( $retval,
'metadata' );
720 return $img->getOriginalTitle()->getDBkey() .
'|' . ( $start ?? $img->getTimestamp() );
726 ParamValidator::PARAM_ISMULTI =>
true,
727 ParamValidator::PARAM_DEFAULT =>
'timestamp|user',
728 ParamValidator::PARAM_TYPE => static::getPropertyNames(),
732 ParamValidator::PARAM_TYPE =>
'limit',
733 ParamValidator::PARAM_DEFAULT => 1,
734 IntegerDef::PARAM_MIN => 1,
739 ParamValidator::PARAM_TYPE =>
'timestamp'
742 ParamValidator::PARAM_TYPE =>
'timestamp'
745 ParamValidator::PARAM_TYPE =>
'integer',
746 ParamValidator::PARAM_DEFAULT => -1,
748 'apihelp-query+imageinfo-param-urlwidth',
753 ParamValidator::PARAM_TYPE =>
'integer',
754 ParamValidator::PARAM_DEFAULT => -1
756 'metadataversion' => [
757 ParamValidator::PARAM_TYPE =>
'string',
758 ParamValidator::PARAM_DEFAULT =>
'1',
760 'extmetadatalanguage' => [
761 ParamValidator::PARAM_TYPE =>
'string',
762 ParamValidator::PARAM_DEFAULT =>
763 $this->contentLanguage->getCode(),
765 'extmetadatamultilang' => [
766 ParamValidator::PARAM_TYPE =>
'boolean',
767 ParamValidator::PARAM_DEFAULT =>
false,
769 'extmetadatafilter' => [
770 ParamValidator::PARAM_TYPE =>
'string',
771 ParamValidator::PARAM_ISMULTI =>
true,
774 ParamValidator::PARAM_DEFAULT =>
'',
775 ParamValidator::PARAM_TYPE =>
'string',
777 'badfilecontexttitle' => [
778 ParamValidator::PARAM_TYPE =>
'string',
784 ParamValidator::PARAM_TYPE =>
'boolean',
785 ParamValidator::PARAM_DEFAULT =>
false,
797 return array_keys( static::getPropertyMessages( $filter ) );
807 return array_diff_key(
809 'timestamp' =>
'apihelp-query+imageinfo-paramvalue-prop-timestamp',
810 'user' =>
'apihelp-query+imageinfo-paramvalue-prop-user',
811 'userid' =>
'apihelp-query+imageinfo-paramvalue-prop-userid',
812 'comment' =>
'apihelp-query+imageinfo-paramvalue-prop-comment',
813 'parsedcomment' =>
'apihelp-query+imageinfo-paramvalue-prop-parsedcomment',
814 'canonicaltitle' =>
'apihelp-query+imageinfo-paramvalue-prop-canonicaltitle',
815 'url' =>
'apihelp-query+imageinfo-paramvalue-prop-url',
816 'size' =>
'apihelp-query+imageinfo-paramvalue-prop-size',
817 'dimensions' =>
'apihelp-query+imageinfo-paramvalue-prop-dimensions',
818 'sha1' =>
'apihelp-query+imageinfo-paramvalue-prop-sha1',
819 'mime' =>
'apihelp-query+imageinfo-paramvalue-prop-mime',
820 'thumbmime' =>
'apihelp-query+imageinfo-paramvalue-prop-thumbmime',
821 'mediatype' =>
'apihelp-query+imageinfo-paramvalue-prop-mediatype',
822 'metadata' =>
'apihelp-query+imageinfo-paramvalue-prop-metadata',
823 'commonmetadata' =>
'apihelp-query+imageinfo-paramvalue-prop-commonmetadata',
824 'extmetadata' =>
'apihelp-query+imageinfo-paramvalue-prop-extmetadata',
825 'archivename' =>
'apihelp-query+imageinfo-paramvalue-prop-archivename',
826 'bitdepth' =>
'apihelp-query+imageinfo-paramvalue-prop-bitdepth',
827 'uploadwarning' =>
'apihelp-query+imageinfo-paramvalue-prop-uploadwarning',
828 'badfile' =>
'apihelp-query+imageinfo-paramvalue-prop-badfile',
830 array_fill_keys( $filter,
true )
836 'action=query&titles=File:Albert%20Einstein%20Head.jpg&prop=imageinfo'
837 =>
'apihelp-query+imageinfo-example-simple',
838 'action=query&titles=File:Test.jpg&prop=imageinfo&iilimit=50&' .
839 'iiend=2007-12-31T23:59:59Z&iiprop=timestamp|user|url'
840 =>
'apihelp-query+imageinfo-example-dated',
845 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Imageinfo';
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
parseContinueParamOrDie(string $continue, array $types)
Parse the 'continue' parameter in the usual format and validate the types of each part,...
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, or 'string' with PARAM_ISMULTI,...
const LIMIT_BIG1
Fast query, standard limit.
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
const LIMIT_BIG2
Fast query, apihighlimits limit.
This is a base class for all Query modules.
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.
addPageSubItem( $pageId, $item, $elemname=null)
Same as addPageSubItems(), but one element of $data at a time.
getPageSet()
Get the PageSet object to work on.
userCanSeeRevDel()
Check whether the current user has permission to view revision-deleted fields.
A query action to get image information and upload history.
checkParameterNormalise( $image, $finalParams)
Verify that the final image parameters can be normalised.
mergeThumbParams( $image, $thumbParams, $otherParams)
Validate and merge scale parameters with handler thumb parameters, give error if invalid.
getCacheMode( $params)
Get the cache mode for the data generated by this module.
getScale( $params)
From parameters, construct a 'scale' array.
__construct(ApiQuery $query, $moduleName, $prefixOrRepoGroup=null, $repoGroupOrContentLanguage=null, $contentLanguageOrBadFileLookup=null, $badFileLookupOrUnused=null)
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
getHelpUrls()
Return links to more detailed help pages about the module.
static getPropertyNames( $filter=[])
Returns all possible parameters to iiprop.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getContinueStr( $img, $start=null)
static getInfo( $file, $prop, $result, $thumbParams=null, $opts=false)
Get result information for an image revision.
static getTransformCount()
Get the count of image transformations performed.
static getPropertyMessages( $filter=[])
Returns messages for all possible parameters to iiprop.
static processMetaData( $metadata, $result)
getExamplesMessages()
Returns usage examples for this module.
This is the main query class.
Implements some public methods and some protected utility functions which are required by multiple ch...
Base class for language-specific code.
A class containing constants representing the names of configuration variables.
Prioritized list of file repositories.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.