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() ) );
416 public static function getInfo( $file, $prop, $result, $thumbParams =
null, $opts =
false ) {
421 if ( !$opts || is_string( $opts ) ) {
423 'version' => $opts ?:
'latest',
424 'language' => $services->getContentLanguage(),
425 'multilang' =>
false,
426 'extmetadatafilter' => [],
427 'revdelUser' =>
null,
430 $version = $opts[
'version'];
436 $exists = $file->exists();
440 if ( isset( $prop[
'timestamp'] ) && $exists ) {
441 $vals[
'timestamp'] =
wfTimestamp( TS::ISO_8601, $file->getTimestamp() );
445 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser'] ) {
446 $revdelUser = $opts[
'revdelUser'];
447 $canShowField =
static function ( $field ) use ( $file, $revdelUser ) {
448 return $file->userCan( $field, $revdelUser );
451 $canShowField =
static function ( $field ) use ( $file ) {
452 return !$file->isDeleted( $field );
456 $user = isset( $prop[
'user'] );
457 $userid = isset( $prop[
'userid'] );
459 if ( ( $user || $userid ) && $exists ) {
460 if ( $file->isDeleted( File::DELETED_USER ) ) {
461 $vals[
'userhidden'] =
true;
464 if ( $canShowField( File::DELETED_USER ) ) {
466 $uploader = $file->getUploader( File::RAW );
468 $vals[
'user'] = $uploader ? $uploader->getName() :
'';
471 $vals[
'userid'] = $uploader ? $uploader->getId() : 0;
473 if ( $uploader && $services->getUserNameUtils()->isTemp( $uploader->getName() ) ) {
474 $vals[
'temp'] =
true;
476 if ( $uploader && !$uploader->isRegistered() ) {
477 $vals[
'anon'] =
true;
484 if ( ( isset( $prop[
'size'] ) || isset( $prop[
'dimensions'] ) ) && $exists ) {
485 $vals[
'size'] = (int)$file->getSize();
486 $vals[
'width'] = (int)$file->getWidth();
487 $vals[
'height'] = (int)$file->getHeight();
489 $pageCount = $file->pageCount();
490 if ( $pageCount !==
false ) {
491 $vals[
'pagecount'] = $pageCount;
495 $length = $file->getLength();
498 $vals[
'duration'] = (float)$length;
502 $pcomment = isset( $prop[
'parsedcomment'] );
503 $comment = isset( $prop[
'comment'] );
505 if ( ( $pcomment || $comment ) && $exists ) {
506 if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
507 $vals[
'commenthidden'] =
true;
510 if ( $canShowField( File::DELETED_COMMENT ) ) {
512 $vals[
'parsedcomment'] = $services->getCommentFormatter()->format(
513 $file->getDescription( File::RAW ), $file->getTitle() );
516 $vals[
'comment'] = $file->getDescription( File::RAW );
521 $canonicaltitle = isset( $prop[
'canonicaltitle'] );
522 $url = isset( $prop[
'url'] );
523 $sha1 = isset( $prop[
'sha1'] );
524 $meta = isset( $prop[
'metadata'] );
525 $extmetadata = isset( $prop[
'extmetadata'] );
526 $commonmeta = isset( $prop[
'commonmetadata'] );
527 $mime = isset( $prop[
'mime'] );
528 $mediatype = isset( $prop[
'mediatype'] );
529 $archive = isset( $prop[
'archivename'] );
530 $bitdepth = isset( $prop[
'bitdepth'] );
531 $uploadwarning = isset( $prop[
'uploadwarning'] );
533 if ( $uploadwarning ) {
537 if ( $file->isDeleted( File::DELETED_FILE ) ) {
538 $vals[
'filehidden'] =
true;
542 if ( $anyHidden && $file->isDeleted( File::DELETED_RESTRICTED ) ) {
543 $vals[
'suppressed'] =
true;
547 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser']
548 && !$file->userCan( File::DELETED_FILE, $opts[
'revdelUser'] )
551 } elseif ( $file->isDeleted( File::DELETED_FILE ) ) {
555 if ( $canonicaltitle ) {
556 $vals[
'canonicaltitle'] = $file->getTitle()->getPrefixedText();
560 $urlUtils = $services->getUrlUtils();
563 if ( $thumbParams !==
null ) {
564 $mto = $file->transform( $thumbParams );
565 self::$transformCount++;
566 if ( $mto && !$mto->isError() ) {
567 $vals[
'thumburl'] = (string)$urlUtils->expand( $mto->getUrl(),
PROTO_CURRENT );
571 if ( $mto->getUrl() !== $file->getUrl() ) {
572 $vals[
'thumbwidth'] = (int)$mto->getWidth();
573 $vals[
'thumbheight'] = (int)$mto->getHeight();
575 $vals[
'thumbwidth'] = (int)$file->getWidth();
576 $vals[
'thumbheight'] = (int)$file->getHeight();
579 if ( isset( $prop[
'thumbmime'] ) && $file->getHandler() ) {
580 [ , $mime ] = $file->getHandler()->getThumbType(
581 $mto->getExtension(), $file->getMimeType(), $thumbParams );
582 $vals[
'thumbmime'] = $mime;
585 Linker::processResponsiveImages( $file, $mto, [
586 'width' => $vals[
'thumbwidth'],
587 'height' => $vals[
'thumbheight']
589 foreach ( $mto->responsiveUrls as $density =>
$url ) {
590 $vals[
'responsiveUrls'][$density] = (string)$urlUtils->expand(
$url,
PROTO_CURRENT );
592 } elseif ( $mto && $mto->isError() ) {
594 '@phan-var MediaTransformError $mto';
595 $vals[
'thumberror'] = $mto->toText();
598 $vals[
'url'] = (string)$urlUtils->expand( $file->getFullUrl(),
PROTO_CURRENT );
600 $vals[
'descriptionurl'] = (string)$urlUtils->expand( $file->getDescriptionUrl(),
PROTO_CURRENT );
602 $shortDescriptionUrl = $file->getDescriptionShortUrl();
603 if ( $shortDescriptionUrl !==
null ) {
604 $vals[
'descriptionshorturl'] = (string)$urlUtils->expand( $shortDescriptionUrl,
PROTO_CURRENT );
609 $vals[
'filemissing'] =
true;
612 if ( $sha1 && $exists ) {
613 $vals[
'sha1'] = \Wikimedia\base_convert( $file->getSha1(), 36, 16, 40 );
616 if ( $meta && $exists ) {
617 $metadata = $file->getMetadataArray();
618 if ( $metadata && $version !==
'latest' ) {
619 $metadata = $file->convertMetadataVersion( $metadata, $version );
621 $vals[
'metadata'] = $metadata ? static::processMetaData( $metadata, $result ) :
null;
623 if ( $commonmeta && $exists ) {
624 $metaArray = $file->getCommonMetaArray();
625 $vals[
'commonmetadata'] = $metaArray ? static::processMetaData( $metaArray, $result ) : [];
628 if ( $extmetadata && $exists ) {
635 $format->getContext()->setLanguage( $opts[
'language'] );
636 $extmetaArray = $format->fetchExtendedMetadata( $file );
637 if ( $opts[
'extmetadatafilter'] ) {
638 $extmetaArray = array_intersect_key(
639 $extmetaArray, array_fill_keys( $opts[
'extmetadatafilter'],
true )
642 $vals[
'extmetadata'] = $extmetaArray;
645 if ( $mime && $exists ) {
646 $vals[
'mime'] = $file->getMimeType();
649 if ( $mediatype && $exists ) {
650 $vals[
'mediatype'] = $file->getMediaType();
653 if ( $archive && $file->isOld() ) {
655 '@phan-var OldLocalFile $file';
656 $vals[
'archivename'] = $file->getArchiveName();
659 if ( $bitdepth && $exists ) {
660 $vals[
'bitdepth'] = $file->getBitDepth();
725 ParamValidator::PARAM_ISMULTI =>
true,
726 ParamValidator::PARAM_DEFAULT =>
'timestamp|user',
727 ParamValidator::PARAM_TYPE => static::getPropertyNames(),
731 ParamValidator::PARAM_TYPE =>
'limit',
732 ParamValidator::PARAM_DEFAULT => 1,
733 IntegerDef::PARAM_MIN => 1,
738 ParamValidator::PARAM_TYPE =>
'timestamp'
741 ParamValidator::PARAM_TYPE =>
'timestamp'
744 ParamValidator::PARAM_TYPE =>
'integer',
745 ParamValidator::PARAM_DEFAULT => -1,
747 'apihelp-query+imageinfo-param-urlwidth',
752 ParamValidator::PARAM_TYPE =>
'integer',
753 ParamValidator::PARAM_DEFAULT => -1
755 'metadataversion' => [
756 ParamValidator::PARAM_TYPE =>
'string',
757 ParamValidator::PARAM_DEFAULT =>
'1',
759 'extmetadatalanguage' => [
760 ParamValidator::PARAM_TYPE =>
'string',
761 ParamValidator::PARAM_DEFAULT =>
762 $this->contentLanguage->getCode(),
764 'extmetadatamultilang' => [
765 ParamValidator::PARAM_TYPE =>
'boolean',
766 ParamValidator::PARAM_DEFAULT =>
false,
768 'extmetadatafilter' => [
769 ParamValidator::PARAM_TYPE =>
'string',
770 ParamValidator::PARAM_ISMULTI =>
true,
773 ParamValidator::PARAM_DEFAULT =>
'',
774 ParamValidator::PARAM_TYPE =>
'string',
776 'badfilecontexttitle' => [
777 ParamValidator::PARAM_TYPE =>
'string',
783 ParamValidator::PARAM_TYPE =>
'boolean',
784 ParamValidator::PARAM_DEFAULT =>
false,