83 $prop = array_fill_keys( $params[
'prop'],
true );
88 'version' => $params[
'metadataversion'],
89 'language' => $params[
'extmetadatalanguage'],
90 'multilang' => $params[
'extmetadatamultilang'],
91 'extmetadatafilter' => $params[
'extmetadatafilter'],
95 if ( isset( $params[
'badfilecontexttitle'] ) ) {
96 $badFileContextTitle = Title::newFromText( $params[
'badfilecontexttitle'] );
97 if ( !$badFileContextTitle || $badFileContextTitle->isExternal() ) {
99 $this->
dieWithError( [
'apierror-bad-badfilecontexttitle', $p ],
'invalid-title' );
102 $badFileContextTitle =
null;
105 $pageIds = $this->
getPageSet()->getGoodAndMissingTitlesByNamespace();
106 if ( !empty( $pageIds[
NS_FILE] ) ) {
107 $titles = array_keys( $pageIds[
NS_FILE] );
111 if ( $params[
'continue'] !==
null ) {
113 $fromTitle = $cont[0];
114 $fromTimestamp = $cont[1];
116 foreach ( $titles as $key => $title ) {
117 if ( $title < $fromTitle ) {
118 unset( $titles[$key] );
126 $findTitles = array_map(
static function ( $title ) use ( $performer ) {
129 'private' => $performer,
133 if ( $params[
'localonly'] ) {
134 $images = $this->repoGroup->getLocalRepo()->findFiles( $findTitles );
136 $images = $this->repoGroup->findFiles( $findTitles );
140 foreach ( $titles as $title ) {
142 $pageId = $pageIds[
NS_FILE][$title];
145 $start = $title === $fromTitle ? $fromTimestamp : $params[
'start'];
147 if ( !isset( $images[$title] ) ) {
148 if ( isset( $prop[
'uploadwarning'] ) || isset( $prop[
'badfile'] ) ) {
150 $images[$title] = $this->repoGroup->getLocalRepo()->newFile( $title );
152 $info[
'imagerepository'] =
'';
155 [
'query',
'pages', (
int)$pageId ],
156 'imagerepository',
''
164 $img = $images[$title];
166 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
167 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
170 $start ??
wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
179 if ( !isset( $info[
'imagerepository'] ) ) {
180 $info[
'imagerepository'] = $img->getRepoName();
182 if ( isset( $prop[
'badfile'] ) ) {
183 $info[
'badfile'] = (bool)$this->badFileLookup->isBadFile( $title, $badFileContextTitle );
189 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
196 $start ??
wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
206 $finalThumbParams = $this->
mergeThumbParams( $img, $scale, $params[
'urlparam'] );
212 if ( $badFileContextTitle && $finalThumbParams ) {
213 $finalThumbParams[
'targetlang'] = $badFileContextTitle->getPageLanguage()->getCode();
220 ( $start ===
null || $img->getTimestamp() <= $start ) &&
221 ( $params[
'end'] ===
null || $img->getTimestamp() >= $params[
'end'] )
226 static::getInfo( $img, $prop, $result,
227 $finalThumbParams, $opts
231 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
234 wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
245 $count = ( $gotOne ? 1 : 0 );
246 $oldies = $img->getHistory( $params[
'limit'] - $count + 1, $start, $params[
'end'] );
248 foreach ( $oldies as $oldie ) {
249 if ( ++$count > $params[
'limit'] ) {
253 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
255 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
261 static::getInfo( $oldie, $prop, $result,
262 $finalThumbParams, $opts
266 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
268 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
415 public static function getInfo( $file, $prop, $result, $thumbParams =
null, $opts =
false ) {
420 if ( !$opts || is_string( $opts ) ) {
422 'version' => $opts ?:
'latest',
423 'language' => $services->getContentLanguage(),
424 'multilang' =>
false,
425 'extmetadatafilter' => [],
426 'revdelUser' =>
null,
429 $version = $opts[
'version'];
435 $exists = $file->exists();
439 if ( isset( $prop[
'timestamp'] ) && $exists ) {
440 $vals[
'timestamp'] =
wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
444 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser'] ) {
445 $revdelUser = $opts[
'revdelUser'];
446 $canShowField =
static function ( $field ) use ( $file, $revdelUser ) {
447 return $file->userCan( $field, $revdelUser );
450 $canShowField =
static function ( $field ) use ( $file ) {
451 return !$file->isDeleted( $field );
455 $user = isset( $prop[
'user'] );
456 $userid = isset( $prop[
'userid'] );
458 if ( ( $user || $userid ) && $exists ) {
459 if ( $file->isDeleted( File::DELETED_USER ) ) {
460 $vals[
'userhidden'] =
true;
463 if ( $canShowField( File::DELETED_USER ) ) {
465 $uploader = $file->getUploader( File::RAW );
467 $vals[
'user'] = $uploader ? $uploader->getName() :
'';
470 $vals[
'userid'] = $uploader ? $uploader->getId() : 0;
472 if ( $uploader && $services->getUserNameUtils()->isTemp( $uploader->getName() ) ) {
473 $vals[
'temp'] =
true;
475 if ( $uploader && !$uploader->isRegistered() ) {
476 $vals[
'anon'] =
true;
483 if ( ( isset( $prop[
'size'] ) || isset( $prop[
'dimensions'] ) ) && $exists ) {
484 $vals[
'size'] = (int)$file->getSize();
485 $vals[
'width'] = (int)$file->getWidth();
486 $vals[
'height'] = (int)$file->getHeight();
488 $pageCount = $file->pageCount();
489 if ( $pageCount !==
false ) {
490 $vals[
'pagecount'] = $pageCount;
494 $length = $file->getLength();
497 $vals[
'duration'] = (float)$length;
501 $pcomment = isset( $prop[
'parsedcomment'] );
502 $comment = isset( $prop[
'comment'] );
504 if ( ( $pcomment || $comment ) && $exists ) {
505 if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
506 $vals[
'commenthidden'] =
true;
509 if ( $canShowField( File::DELETED_COMMENT ) ) {
511 $vals[
'parsedcomment'] = $services->getCommentFormatter()->format(
512 $file->getDescription( File::RAW ), $file->getTitle() );
515 $vals[
'comment'] = $file->getDescription( File::RAW );
520 $canonicaltitle = isset( $prop[
'canonicaltitle'] );
521 $url = isset( $prop[
'url'] );
522 $sha1 = isset( $prop[
'sha1'] );
523 $meta = isset( $prop[
'metadata'] );
524 $extmetadata = isset( $prop[
'extmetadata'] );
525 $commonmeta = isset( $prop[
'commonmetadata'] );
526 $mime = isset( $prop[
'mime'] );
527 $mediatype = isset( $prop[
'mediatype'] );
528 $archive = isset( $prop[
'archivename'] );
529 $bitdepth = isset( $prop[
'bitdepth'] );
530 $uploadwarning = isset( $prop[
'uploadwarning'] );
532 if ( $uploadwarning ) {
536 if ( $file->isDeleted( File::DELETED_FILE ) ) {
537 $vals[
'filehidden'] =
true;
541 if ( $anyHidden && $file->isDeleted( File::DELETED_RESTRICTED ) ) {
542 $vals[
'suppressed'] =
true;
546 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser']
547 && !$file->userCan( File::DELETED_FILE, $opts[
'revdelUser'] )
550 } elseif ( $file->isDeleted( File::DELETED_FILE ) ) {
554 if ( $canonicaltitle ) {
555 $vals[
'canonicaltitle'] = $file->getTitle()->getPrefixedText();
559 $urlUtils = $services->getUrlUtils();
562 if ( $thumbParams !==
null ) {
563 $mto = $file->transform( $thumbParams );
564 self::$transformCount++;
565 if ( $mto && !$mto->isError() ) {
566 $vals[
'thumburl'] = (string)$urlUtils->expand( $mto->getUrl(),
PROTO_CURRENT );
570 if ( $mto->getUrl() !== $file->getUrl() ) {
571 $vals[
'thumbwidth'] = (int)$mto->getWidth();
572 $vals[
'thumbheight'] = (int)$mto->getHeight();
574 $vals[
'thumbwidth'] = (int)$file->getWidth();
575 $vals[
'thumbheight'] = (int)$file->getHeight();
578 if ( isset( $prop[
'thumbmime'] ) && $file->getHandler() ) {
579 [ , $mime ] = $file->getHandler()->getThumbType(
580 $mto->getExtension(), $file->getMimeType(), $thumbParams );
581 $vals[
'thumbmime'] = $mime;
584 Linker::processResponsiveImages( $file, $mto, [
585 'width' => $vals[
'thumbwidth'],
586 'height' => $vals[
'thumbheight']
588 foreach ( $mto->responsiveUrls as $density =>
$url ) {
589 $vals[
'responsiveUrls'][$density] = (string)$urlUtils->expand(
$url,
PROTO_CURRENT );
591 } elseif ( $mto && $mto->isError() ) {
593 '@phan-var MediaTransformError $mto';
594 $vals[
'thumberror'] = $mto->toText();
597 $vals[
'url'] = (string)$urlUtils->expand( $file->getFullUrl(),
PROTO_CURRENT );
599 $vals[
'descriptionurl'] = (string)$urlUtils->expand( $file->getDescriptionUrl(),
PROTO_CURRENT );
601 $shortDescriptionUrl = $file->getDescriptionShortUrl();
602 if ( $shortDescriptionUrl !==
null ) {
603 $vals[
'descriptionshorturl'] = (string)$urlUtils->expand( $shortDescriptionUrl,
PROTO_CURRENT );
608 $vals[
'filemissing'] =
true;
611 if ( $sha1 && $exists ) {
612 $vals[
'sha1'] = \Wikimedia\base_convert( $file->getSha1(), 36, 16, 40 );
615 if ( $meta && $exists ) {
616 $metadata = $file->getMetadataArray();
617 if ( $metadata && $version !==
'latest' ) {
618 $metadata = $file->convertMetadataVersion( $metadata, $version );
620 $vals[
'metadata'] = $metadata ? static::processMetaData( $metadata, $result ) :
null;
622 if ( $commonmeta && $exists ) {
623 $metaArray = $file->getCommonMetaArray();
624 $vals[
'commonmetadata'] = $metaArray ? static::processMetaData( $metaArray, $result ) : [];
627 if ( $extmetadata && $exists ) {
634 $format->getContext()->setLanguage( $opts[
'language'] );
635 $extmetaArray = $format->fetchExtendedMetadata( $file );
636 if ( $opts[
'extmetadatafilter'] ) {
637 $extmetaArray = array_intersect_key(
638 $extmetaArray, array_fill_keys( $opts[
'extmetadatafilter'],
true )
641 $vals[
'extmetadata'] = $extmetaArray;
644 if ( $mime && $exists ) {
645 $vals[
'mime'] = $file->getMimeType();
648 if ( $mediatype && $exists ) {
649 $vals[
'mediatype'] = $file->getMediaType();
652 if ( $archive && $file->isOld() ) {
654 '@phan-var OldLocalFile $file';
655 $vals[
'archivename'] = $file->getArchiveName();
658 if ( $bitdepth && $exists ) {
659 $vals[
'bitdepth'] = $file->getBitDepth();
724 ParamValidator::PARAM_ISMULTI =>
true,
725 ParamValidator::PARAM_DEFAULT =>
'timestamp|user',
726 ParamValidator::PARAM_TYPE => static::getPropertyNames(),
730 ParamValidator::PARAM_TYPE =>
'limit',
731 ParamValidator::PARAM_DEFAULT => 1,
732 IntegerDef::PARAM_MIN => 1,
737 ParamValidator::PARAM_TYPE =>
'timestamp'
740 ParamValidator::PARAM_TYPE =>
'timestamp'
743 ParamValidator::PARAM_TYPE =>
'integer',
744 ParamValidator::PARAM_DEFAULT => -1,
746 'apihelp-query+imageinfo-param-urlwidth',
751 ParamValidator::PARAM_TYPE =>
'integer',
752 ParamValidator::PARAM_DEFAULT => -1
754 'metadataversion' => [
755 ParamValidator::PARAM_TYPE =>
'string',
756 ParamValidator::PARAM_DEFAULT =>
'1',
758 'extmetadatalanguage' => [
759 ParamValidator::PARAM_TYPE =>
'string',
760 ParamValidator::PARAM_DEFAULT =>
761 $this->contentLanguage->getCode(),
763 'extmetadatamultilang' => [
764 ParamValidator::PARAM_TYPE =>
'boolean',
765 ParamValidator::PARAM_DEFAULT =>
false,
767 'extmetadatafilter' => [
768 ParamValidator::PARAM_TYPE =>
'string',
769 ParamValidator::PARAM_ISMULTI =>
true,
772 ParamValidator::PARAM_DEFAULT =>
'',
773 ParamValidator::PARAM_TYPE =>
'string',
775 'badfilecontexttitle' => [
776 ParamValidator::PARAM_TYPE =>
'string',
782 ParamValidator::PARAM_TYPE =>
'boolean',
783 ParamValidator::PARAM_DEFAULT =>
false,