84 $prop = array_fill_keys( $params[
'prop'],
true );
89 'version' => $params[
'metadataversion'],
90 'language' => $params[
'extmetadatalanguage'],
91 'multilang' => $params[
'extmetadatamultilang'],
92 'extmetadatafilter' => $params[
'extmetadatafilter'],
96 if ( isset( $params[
'badfilecontexttitle'] ) ) {
97 $badFileContextTitle = Title::newFromText( $params[
'badfilecontexttitle'] );
98 if ( !$badFileContextTitle || $badFileContextTitle->isExternal() ) {
100 $this->
dieWithError( [
'apierror-bad-badfilecontexttitle', $p ],
'invalid-title' );
103 $badFileContextTitle =
null;
106 $pageIds = $this->
getPageSet()->getGoodAndMissingTitlesByNamespace();
107 if ( !empty( $pageIds[
NS_FILE] ) ) {
108 $titles = array_keys( $pageIds[
NS_FILE] );
112 if ( $params[
'continue'] !==
null ) {
114 $fromTitle = $cont[0];
115 $fromTimestamp = $cont[1];
117 foreach ( $titles as $key => $title ) {
118 if ( $title < $fromTitle ) {
119 unset( $titles[$key] );
127 $findTitles = array_map(
static function ( $title ) use ( $performer ) {
130 'private' => $performer,
134 if ( $params[
'localonly'] ) {
135 $images = $this->repoGroup->getLocalRepo()->findFiles( $findTitles );
137 $images = $this->repoGroup->findFiles( $findTitles );
141 foreach ( $titles as $title ) {
143 $pageId = $pageIds[
NS_FILE][$title];
146 $start = $title === $fromTitle ? $fromTimestamp : $params[
'start'];
148 if ( !isset( $images[$title] ) ) {
149 if ( isset( $prop[
'uploadwarning'] ) || isset( $prop[
'badfile'] ) ) {
151 $images[$title] = $this->repoGroup->getLocalRepo()->newFile( $title );
153 $info[
'imagerepository'] =
'';
156 [
'query',
'pages', (
int)$pageId ],
157 'imagerepository',
''
165 $img = $images[$title];
167 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
168 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
171 $start ??
wfTimestamp( TS::ISO_8601, $img->getTimestamp() )
180 if ( !isset( $info[
'imagerepository'] ) ) {
181 $info[
'imagerepository'] = $img->getRepoName();
183 if ( isset( $prop[
'badfile'] ) ) {
184 $info[
'badfile'] = (bool)$this->badFileLookup->isBadFile( $title, $badFileContextTitle );
190 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
197 $start ??
wfTimestamp( TS::ISO_8601, $img->getTimestamp() )
207 $finalThumbParams = $this->
mergeThumbParams( $img, $scale, $params[
'urlparam'] );
213 if ( $badFileContextTitle && $finalThumbParams ) {
214 $finalThumbParams[
'targetlang'] = $badFileContextTitle->getPageLanguage()->getCode();
221 ( $start ===
null || $img->getTimestamp() <= $start ) &&
222 ( $params[
'end'] ===
null || $img->getTimestamp() >= $params[
'end'] )
227 static::getInfo( $img, $prop, $result,
228 $finalThumbParams, $opts
232 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
235 wfTimestamp( TS::ISO_8601, $img->getTimestamp() ) );
246 $count = ( $gotOne ? 1 : 0 );
247 $oldies = $img->getHistory( $params[
'limit'] - $count + 1, $start, $params[
'end'] );
249 foreach ( $oldies as $oldie ) {
250 if ( ++$count > $params[
'limit'] ) {
254 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
256 wfTimestamp( TS::ISO_8601, $oldie->getTimestamp() ) );
262 static::getInfo( $oldie, $prop, $result,
263 $finalThumbParams, $opts
267 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
269 wfTimestamp( TS::ISO_8601, $oldie->getTimestamp() ) );
426 public static function getInfo( $file, $prop, $result, $thumbParams =
null, $opts =
false ) {
431 if ( !$opts || is_string( $opts ) ) {
433 'version' => $opts ?:
'latest',
434 'language' => $services->getContentLanguage(),
435 'multilang' =>
false,
436 'extmetadatafilter' => [],
437 'revdelUser' =>
null,
440 $version = $opts[
'version'];
446 $exists = $file->exists();
450 $hasDbMetadata = $exists
455 if ( isset( $prop[
'timestamp'] ) && $hasDbMetadata ) {
456 $vals[
'timestamp'] =
wfTimestamp( TS::ISO_8601, $file->getTimestamp() );
460 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser'] ) {
461 $revdelUser = $opts[
'revdelUser'];
462 $canShowField =
static function ( $field ) use ( $file, $revdelUser ) {
463 return $file->userCan( $field, $revdelUser );
466 $canShowField =
static function ( $field ) use ( $file ) {
467 return !$file->isDeleted( $field );
471 $user = isset( $prop[
'user'] );
472 $userid = isset( $prop[
'userid'] );
474 if ( ( $user || $userid ) && $hasDbMetadata ) {
475 if ( $file->isDeleted( File::DELETED_USER ) ) {
476 $vals[
'userhidden'] =
true;
479 if ( $canShowField( File::DELETED_USER ) ) {
481 $uploader = $file->getUploader( File::RAW );
483 $vals[
'user'] = $uploader ? $uploader->getName() :
'';
486 $vals[
'userid'] = $uploader ? $uploader->getId() : 0;
488 if ( $uploader && $services->getUserNameUtils()->isTemp( $uploader->getName() ) ) {
489 $vals[
'temp'] =
true;
491 if ( $uploader && !$uploader->isRegistered() ) {
492 $vals[
'anon'] =
true;
499 if ( ( isset( $prop[
'size'] ) || isset( $prop[
'dimensions'] ) ) && $hasDbMetadata ) {
500 $vals[
'size'] = (int)$file->getSize();
501 $vals[
'width'] = (int)$file->getWidth();
502 $vals[
'height'] = (int)$file->getHeight();
507 $pageCount = $file->pageCount();
508 if ( $pageCount !==
false ) {
509 $vals[
'pagecount'] = $pageCount;
513 $length = $file->getLength();
516 $vals[
'duration'] = (float)$length;
521 $pcomment = isset( $prop[
'parsedcomment'] );
522 $comment = isset( $prop[
'comment'] );
524 if ( ( $pcomment || $comment ) && $hasDbMetadata ) {
525 if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
526 $vals[
'commenthidden'] =
true;
529 if ( $canShowField( File::DELETED_COMMENT ) ) {
531 $vals[
'parsedcomment'] = $services->getCommentFormatter()->format(
532 $file->getDescription( File::RAW ), $file->getTitle() );
535 $vals[
'comment'] = $file->getDescription( File::RAW );
540 $canonicaltitle = isset( $prop[
'canonicaltitle'] );
541 $url = isset( $prop[
'url'] );
542 $sha1 = isset( $prop[
'sha1'] );
543 $meta = isset( $prop[
'metadata'] );
544 $extmetadata = isset( $prop[
'extmetadata'] );
545 $commonmeta = isset( $prop[
'commonmetadata'] );
546 $mime = isset( $prop[
'mime'] );
547 $mediatype = isset( $prop[
'mediatype'] );
548 $archive = isset( $prop[
'archivename'] );
549 $bitdepth = isset( $prop[
'bitdepth'] );
550 $uploadwarning = isset( $prop[
'uploadwarning'] );
552 if ( $uploadwarning ) {
553 $vals[
'html'] = SpecialUpload::getExistsWarning( UploadBase::getExistsWarning( $file ) );
556 if ( $file->isDeleted( File::DELETED_FILE ) ) {
557 $vals[
'filehidden'] =
true;
561 if ( $anyHidden && $file->isDeleted( File::DELETED_RESTRICTED ) ) {
562 $vals[
'suppressed'] =
true;
566 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser']
567 && !$file->userCan( File::DELETED_FILE, $opts[
'revdelUser'] )
570 } elseif ( $file->isDeleted( File::DELETED_FILE ) ) {
574 if ( $canonicaltitle ) {
575 $vals[
'canonicaltitle'] = $file->getTitle()->getPrefixedText();
579 $urlUtils = $services->getUrlUtils();
582 if ( $thumbParams !==
null ) {
583 $thumbParams[
'requestProvenance'] =
'imageinfo';
584 $mto = $file->transform( $thumbParams );
585 self::$transformCount++;
586 if ( $mto && !$mto->isError() ) {
587 $vals[
'thumburl'] = (string)$urlUtils->expand( $mto->getUrl(),
PROTO_CURRENT );
591 if ( $mto->getUrl() !== $file->getUrl() ) {
592 $vals[
'thumbwidth'] = (int)$mto->getWidth();
593 $vals[
'thumbheight'] = (int)$mto->getHeight();
595 $vals[
'thumbwidth'] = (int)$file->getWidth();
596 $vals[
'thumbheight'] = (int)$file->getHeight();
599 if ( isset( $prop[
'thumbmime'] ) && $file->getHandler() ) {
600 [ , $mime ] = $file->getHandler()->getThumbType(
601 $mto->getExtension(), $file->getMimeType(), $thumbParams );
602 $vals[
'thumbmime'] = $mime;
605 Linker::processResponsiveImages( $file, $mto, [
606 'width' => $vals[
'thumbwidth'],
607 'height' => $vals[
'thumbheight']
609 foreach ( $mto->responsiveUrls as $density =>
$url ) {
610 $vals[
'responsiveUrls'][$density] = (string)$urlUtils->expand(
$url,
PROTO_CURRENT );
615 $vals[
'thumbattribs'] = $mto->getAttribs();
616 } elseif ( $mto && $mto->isError() ) {
618 '@phan-var MediaTransformError $mto';
619 $vals[
'thumberror'] = $mto->toText();
622 $vals[
'url'] = (string)$urlUtils->expand( $file->appendRequestProvenance( $file->getFullUrl(), [
623 'format' =>
'original',
624 'generator' =>
'imageinfo',
627 $vals[
'descriptionurl'] = (string)$urlUtils->expand( $file->getDescriptionUrl(),
PROTO_CURRENT );
629 $shortDescriptionUrl = $file->getDescriptionShortUrl();
630 if ( $shortDescriptionUrl !==
null ) {
631 $vals[
'descriptionshorturl'] = (string)$urlUtils->expand( $shortDescriptionUrl,
PROTO_CURRENT );
635 if ( $exists && isset( $prop[
'thumburls'] ) ) {
636 $urlUtils = $services->getUrlUtils();
637 $config = $services->getMainConfig();
640 if ( is_array( $thumbnailSteps ) ) {
642 foreach ( $thumbnailSteps as $width ) {
643 $sizes[] = [
'width' => $width ];
647 $userOptionsLookup = $services->getUserOptionsLookup();
650 $sizes[] = [
'width' => $thumbWidth ];
652 $sizes[] = [
'width' => $thumbWidth * 2 ];
655 $sizes[] = [
'width' => $width,
'height' => $height ];
660 $handlerParams = $thumbParams ? array_diff_key(
662 [
'width' =>
true,
'height' =>
true,
'requestProvenance' =>
true ]
664 $vals[
'thumburls'] = [];
665 foreach ( $sizes as $size ) {
666 $size += $handlerParams;
667 $size[
'requestProvenance'] =
'imageinfo';
668 $size[
'usePhysicalSize'] =
true;
669 $mto = $file->transform( $size );
670 if ( !$mto || $mto->isError() ) {
673 if ( isset( $vals[
'thumburls'][$mto->getWidth()] ) ) {
676 self::$transformCount++;
677 $thumburl = (string)$urlUtils->expand( $mto->getUrl(),
PROTO_CURRENT );
678 $vals[
'thumburls'][$mto->getWidth()] = [
680 'width' => $mto->getWidth(),
681 'height' => $mto->getHeight(),
682 ] + $mto->getAttribs();
687 $vals[
'filemissing'] =
true;
690 if ( $sha1 && $exists ) {
691 $vals[
'sha1'] = \Wikimedia\base_convert( $file->getSha1(), 36, 16, 40 );
694 if ( $meta && $exists ) {
695 $metadata = $file->getMetadataArray();
696 if ( $metadata && $version !==
'latest' ) {
697 $metadata = $file->convertMetadataVersion( $metadata, $version );
699 $vals[
'metadata'] = $metadata ? static::processMetaData( $metadata, $result ) :
null;
701 if ( $commonmeta && $exists ) {
702 $metaArray = $file->getCommonMetaArray();
703 $vals[
'commonmetadata'] = $metaArray ? static::processMetaData( $metaArray, $result ) : [];
706 if ( $extmetadata && $exists ) {
713 $format->getContext()->setLanguage( $opts[
'language'] );
714 $extmetaArray = $format->fetchExtendedMetadata( $file );
715 if ( $opts[
'extmetadatafilter'] ) {
716 $extmetaArray = array_intersect_key(
717 $extmetaArray, array_fill_keys( $opts[
'extmetadatafilter'],
true )
720 $vals[
'extmetadata'] = $extmetaArray;
723 if ( $mime && $exists ) {
724 $vals[
'mime'] = $file->getMimeType();
727 if ( $mediatype && $exists ) {
728 $vals[
'mediatype'] = $file->getMediaType();
731 if ( $archive && $file->isOld() ) {
733 '@phan-var OldLocalFile $file';
734 $vals[
'archivename'] = $file->getArchiveName();
737 if ( $bitdepth && $exists ) {
738 $vals[
'bitdepth'] = $file->getBitDepth();
810 ParamValidator::PARAM_ISMULTI =>
true,
811 ParamValidator::PARAM_DEFAULT =>
'timestamp|user',
812 ParamValidator::PARAM_TYPE => static::getPropertyNames(),
816 ParamValidator::PARAM_TYPE =>
'limit',
817 ParamValidator::PARAM_DEFAULT => 1,
818 IntegerDef::PARAM_MIN => 1,
823 ParamValidator::PARAM_TYPE =>
'timestamp'
826 ParamValidator::PARAM_TYPE =>
'timestamp'
829 ParamValidator::PARAM_TYPE =>
'integer',
830 ParamValidator::PARAM_DEFAULT => -1,
832 'apihelp-query+imageinfo-param-urlwidth',
837 ParamValidator::PARAM_TYPE =>
'integer',
838 ParamValidator::PARAM_DEFAULT => -1
840 'metadataversion' => [
841 ParamValidator::PARAM_TYPE =>
'string',
842 ParamValidator::PARAM_DEFAULT =>
'1',
844 'extmetadatalanguage' => [
845 ParamValidator::PARAM_TYPE =>
'string',
846 ParamValidator::PARAM_DEFAULT =>
847 $this->contentLanguage->getCode(),
849 'extmetadatamultilang' => [
850 ParamValidator::PARAM_TYPE =>
'boolean',
851 ParamValidator::PARAM_DEFAULT =>
false,
853 'extmetadatafilter' => [
854 ParamValidator::PARAM_TYPE =>
'string',
855 ParamValidator::PARAM_ISMULTI =>
true,
858 ParamValidator::PARAM_DEFAULT =>
'',
859 ParamValidator::PARAM_TYPE =>
'string',
861 'badfilecontexttitle' => [
862 ParamValidator::PARAM_TYPE =>
'string',
868 ParamValidator::PARAM_TYPE =>
'boolean',
869 ParamValidator::PARAM_DEFAULT =>
false,