96 $prop = array_fill_keys(
$params[
'prop'],
true );
101 'version' =>
$params[
'metadataversion'],
102 'language' =>
$params[
'extmetadatalanguage'],
103 'multilang' =>
$params[
'extmetadatamultilang'],
104 'extmetadatafilter' =>
$params[
'extmetadatafilter'],
108 if ( isset(
$params[
'badfilecontexttitle'] ) ) {
109 $badFileContextTitle = Title::newFromText(
$params[
'badfilecontexttitle'] );
110 if ( !$badFileContextTitle || $badFileContextTitle->isExternal() ) {
112 $this->
dieWithError( [
'apierror-bad-badfilecontexttitle', $p ],
'invalid-title' );
115 $badFileContextTitle =
null;
118 $pageIds = $this->
getPageSet()->getGoodAndMissingTitlesByNamespace();
119 if ( !empty( $pageIds[
NS_FILE] ) ) {
120 $titles = array_keys( $pageIds[
NS_FILE] );
124 if (
$params[
'continue'] !==
null ) {
126 $fromTitle = $cont[0];
127 $fromTimestamp = $cont[1];
129 foreach ( $titles as $key => $title ) {
130 if ( $title < $fromTitle ) {
131 unset( $titles[$key] );
139 $findTitles = array_map(
static function ( $title ) use ( $performer ) {
142 'private' => $performer,
147 $images = $this->repoGroup->getLocalRepo()->findFiles( $findTitles );
149 $images = $this->repoGroup->findFiles( $findTitles );
153 foreach ( $titles as $title ) {
155 $pageId = $pageIds[
NS_FILE][$title];
158 $start = $title === $fromTitle ? $fromTimestamp :
$params[
'start'];
160 if ( !isset( $images[$title] ) ) {
161 if ( isset( $prop[
'uploadwarning'] ) || isset( $prop[
'badfile'] ) ) {
163 $images[$title] = $this->repoGroup->getLocalRepo()->newFile( $title );
165 $info[
'imagerepository'] =
'';
168 [
'query',
'pages', (
int)$pageId ],
169 'imagerepository',
''
177 $img = $images[$title];
179 if ( self::getTransformCount() >= self::TRANSFORM_LIMIT ) {
180 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
183 $start ??
wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
192 if ( !isset( $info[
'imagerepository'] ) ) {
193 $info[
'imagerepository'] = $img->getRepoName();
195 if ( isset( $prop[
'badfile'] ) ) {
196 $info[
'badfile'] = (bool)$this->badFileLookup->isBadFile( $title, $badFileContextTitle );
199 $fit = $result->addValue( [
'query',
'pages' ], (
int)$pageId, $info );
201 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
208 $start ??
wfTimestamp( TS_ISO_8601, $img->getTimestamp() )
224 if ( $badFileContextTitle && $finalThumbParams ) {
225 $finalThumbParams[
'targetlang'] = $badFileContextTitle->getPageLanguage()->getCode();
232 ( $start ===
null || $img->getTimestamp() <= $start ) &&
233 (
$params[
'end'] ===
null || $img->getTimestamp() >=
$params[
'end'] )
238 static::getInfo( $img, $prop, $result,
239 $finalThumbParams, $opts
243 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
246 wfTimestamp( TS_ISO_8601, $img->getTimestamp() ) );
257 $count = ( $gotOne ? 1 : 0 );
258 $oldies = $img->getHistory(
$params[
'limit'] - $count + 1, $start,
$params[
'end'] );
260 foreach ( $oldies as $oldie ) {
261 if ( ++$count >
$params[
'limit'] ) {
265 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
267 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
273 static::getInfo( $oldie, $prop, $result,
274 $finalThumbParams, $opts
278 if ( count( $pageIds[
NS_FILE] ) == 1 ) {
280 wfTimestamp( TS_ISO_8601, $oldie->getTimestamp() ) );
432 public static function getInfo( $file, $prop, $result, $thumbParams =
null, $opts =
false ) {
437 if ( !$opts || is_string( $opts ) ) {
439 'version' => $opts ?:
'latest',
440 'language' => $services->getContentLanguage(),
441 'multilang' =>
false,
442 'extmetadatafilter' => [],
443 'revdelUser' =>
null,
446 $version = $opts[
'version'];
452 $exists = $file->exists();
456 if ( isset( $prop[
'timestamp'] ) && $exists ) {
457 $vals[
'timestamp'] =
wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
461 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser'] ) {
462 $revdelUser = $opts[
'revdelUser'];
463 $canShowField =
static function ( $field ) use ( $file, $revdelUser ) {
464 return $file->userCan( $field, $revdelUser );
467 $canShowField =
static function ( $field ) use ( $file ) {
468 return !$file->isDeleted( $field );
472 $user = isset( $prop[
'user'] );
473 $userid = isset( $prop[
'userid'] );
475 if ( ( $user || $userid ) && $exists ) {
476 if ( $file->isDeleted( File::DELETED_USER ) ) {
477 $vals[
'userhidden'] =
true;
480 if ( $canShowField( File::DELETED_USER ) ) {
482 $uploader = $file->getUploader( File::RAW );
484 $vals[
'user'] = $uploader ? $uploader->getName() :
'';
487 $vals[
'userid'] = $uploader ? $uploader->getId() : 0;
489 if ( $uploader && $services->getUserNameUtils()->isTemp( $uploader->getName() ) ) {
490 $vals[
'temp'] =
true;
492 if ( $uploader && !$uploader->isRegistered() ) {
493 $vals[
'anon'] =
true;
500 if ( ( isset( $prop[
'size'] ) || isset( $prop[
'dimensions'] ) ) && $exists ) {
501 $vals[
'size'] = (int)$file->getSize();
502 $vals[
'width'] = (int)$file->getWidth();
503 $vals[
'height'] = (int)$file->getHeight();
505 $pageCount = $file->pageCount();
506 if ( $pageCount !==
false ) {
507 $vals[
'pagecount'] = $pageCount;
511 $length = $file->getLength();
514 $vals[
'duration'] = (float)$length;
518 $pcomment = isset( $prop[
'parsedcomment'] );
519 $comment = isset( $prop[
'comment'] );
521 if ( ( $pcomment || $comment ) && $exists ) {
522 if ( $file->isDeleted( File::DELETED_COMMENT ) ) {
523 $vals[
'commenthidden'] =
true;
526 if ( $canShowField( File::DELETED_COMMENT ) ) {
528 $vals[
'parsedcomment'] = $services->getCommentFormatter()->format(
529 $file->getDescription( File::RAW ), $file->getTitle() );
532 $vals[
'comment'] = $file->getDescription( File::RAW );
537 $canonicaltitle = isset( $prop[
'canonicaltitle'] );
538 $url = isset( $prop[
'url'] );
539 $sha1 = isset( $prop[
'sha1'] );
540 $meta = isset( $prop[
'metadata'] );
541 $extmetadata = isset( $prop[
'extmetadata'] );
542 $commonmeta = isset( $prop[
'commonmetadata'] );
543 $mime = isset( $prop[
'mime'] );
544 $mediatype = isset( $prop[
'mediatype'] );
545 $archive = isset( $prop[
'archivename'] );
546 $bitdepth = isset( $prop[
'bitdepth'] );
547 $uploadwarning = isset( $prop[
'uploadwarning'] );
549 if ( $uploadwarning ) {
553 if ( $file->isDeleted( File::DELETED_FILE ) ) {
554 $vals[
'filehidden'] =
true;
558 if ( $anyHidden && $file->isDeleted( File::DELETED_RESTRICTED ) ) {
559 $vals[
'suppressed'] =
true;
563 if ( isset( $opts[
'revdelUser'] ) && $opts[
'revdelUser']
564 && !$file->userCan( File::DELETED_FILE, $opts[
'revdelUser'] )
567 } elseif ( $file->isDeleted( File::DELETED_FILE ) ) {
571 if ( $canonicaltitle ) {
572 $vals[
'canonicaltitle'] = $file->getTitle()->getPrefixedText();
576 $urlUtils = $services->getUrlUtils();
579 if ( $thumbParams !==
null ) {
580 $mto = $file->transform( $thumbParams );
581 self::$transformCount++;
582 if ( $mto && !$mto->isError() ) {
583 $vals[
'thumburl'] = (string)$urlUtils->expand( $mto->getUrl(),
PROTO_CURRENT );
587 if ( $mto->getUrl() !== $file->getUrl() ) {
588 $vals[
'thumbwidth'] = (int)$mto->getWidth();
589 $vals[
'thumbheight'] = (int)$mto->getHeight();
591 $vals[
'thumbwidth'] = (int)$file->getWidth();
592 $vals[
'thumbheight'] = (int)$file->getHeight();
595 if ( isset( $prop[
'thumbmime'] ) && $file->getHandler() ) {
596 [ , $mime ] = $file->getHandler()->getThumbType(
597 $mto->getExtension(), $file->getMimeType(), $thumbParams );
598 $vals[
'thumbmime'] = $mime;
601 Linker::processResponsiveImages( $file, $mto, [
602 'width' => $vals[
'thumbwidth'],
603 'height' => $vals[
'thumbheight']
605 foreach ( $mto->responsiveUrls as $density =>
$url ) {
606 $vals[
'responsiveUrls'][$density] = (string)$urlUtils->expand(
$url,
PROTO_CURRENT );
608 } elseif ( $mto && $mto->isError() ) {
610 '@phan-var MediaTransformError $mto';
611 $vals[
'thumberror'] = $mto->toText();
614 $vals[
'url'] = (string)$urlUtils->expand( $file->getFullUrl(),
PROTO_CURRENT );
616 $vals[
'descriptionurl'] = (string)$urlUtils->expand( $file->getDescriptionUrl(),
PROTO_CURRENT );
618 $shortDescriptionUrl = $file->getDescriptionShortUrl();
619 if ( $shortDescriptionUrl !==
null ) {
620 $vals[
'descriptionshorturl'] = (string)$urlUtils->expand( $shortDescriptionUrl,
PROTO_CURRENT );
625 $vals[
'filemissing'] =
true;
628 if ( $sha1 && $exists ) {
629 $vals[
'sha1'] = \Wikimedia\base_convert( $file->getSha1(), 36, 16, 40 );
632 if ( $meta && $exists ) {
633 $metadata = $file->getMetadataArray();
634 if ( $metadata && $version !==
'latest' ) {
635 $metadata = $file->convertMetadataVersion( $metadata, $version );
637 $vals[
'metadata'] = $metadata ? static::processMetaData( $metadata, $result ) :
null;
639 if ( $commonmeta && $exists ) {
640 $metaArray = $file->getCommonMetaArray();
641 $vals[
'commonmetadata'] = $metaArray ? static::processMetaData( $metaArray, $result ) : [];
644 if ( $extmetadata && $exists ) {
651 $format->getContext()->setLanguage( $opts[
'language'] );
652 $extmetaArray = $format->fetchExtendedMetadata( $file );
653 if ( $opts[
'extmetadatafilter'] ) {
654 $extmetaArray = array_intersect_key(
655 $extmetaArray, array_fill_keys( $opts[
'extmetadatafilter'],
true )
658 $vals[
'extmetadata'] = $extmetaArray;
661 if ( $mime && $exists ) {
662 $vals[
'mime'] = $file->getMimeType();
665 if ( $mediatype && $exists ) {
666 $vals[
'mediatype'] = $file->getMediaType();
669 if ( $archive && $file->isOld() ) {
671 '@phan-var OldLocalFile $file';
672 $vals[
'archivename'] = $file->getArchiveName();
675 if ( $bitdepth && $exists ) {
676 $vals[
'bitdepth'] = $file->getBitDepth();
739 ParamValidator::PARAM_ISMULTI =>
true,
740 ParamValidator::PARAM_DEFAULT =>
'timestamp|user',
741 ParamValidator::PARAM_TYPE => static::getPropertyNames(),
745 ParamValidator::PARAM_TYPE =>
'limit',
746 ParamValidator::PARAM_DEFAULT => 1,
747 IntegerDef::PARAM_MIN => 1,
752 ParamValidator::PARAM_TYPE =>
'timestamp'
755 ParamValidator::PARAM_TYPE =>
'timestamp'
758 ParamValidator::PARAM_TYPE =>
'integer',
759 ParamValidator::PARAM_DEFAULT => -1,
761 'apihelp-query+imageinfo-param-urlwidth',
766 ParamValidator::PARAM_TYPE =>
'integer',
767 ParamValidator::PARAM_DEFAULT => -1
769 'metadataversion' => [
770 ParamValidator::PARAM_TYPE =>
'string',
771 ParamValidator::PARAM_DEFAULT =>
'1',
773 'extmetadatalanguage' => [
774 ParamValidator::PARAM_TYPE =>
'string',
775 ParamValidator::PARAM_DEFAULT =>
776 $this->contentLanguage->getCode(),
778 'extmetadatamultilang' => [
779 ParamValidator::PARAM_TYPE =>
'boolean',
780 ParamValidator::PARAM_DEFAULT =>
false,
782 'extmetadatafilter' => [
783 ParamValidator::PARAM_TYPE =>
'string',
784 ParamValidator::PARAM_ISMULTI =>
true,
787 ParamValidator::PARAM_DEFAULT =>
'',
788 ParamValidator::PARAM_TYPE =>
'string',
790 'badfilecontexttitle' => [
791 ParamValidator::PARAM_TYPE =>
'string',
797 ParamValidator::PARAM_TYPE =>
'boolean',
798 ParamValidator::PARAM_DEFAULT =>
false,