Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4145772
ForeignAPIFile.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
ForeignAPIFile.php
View Options
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
use
MediaWiki\MediaWikiServices
;
use
MediaWiki\Permissions\Authority
;
use
MediaWiki\Title\Title
;
use
MediaWiki\User\UserIdentity
;
use
MediaWiki\User\UserIdentityValue
;
/**
* Foreign file accessible through api.php requests.
*
* @ingroup FileAbstraction
*/
class
ForeignAPIFile
extends
File
{
/** @var bool */
private
$mExists
;
/** @var array */
private
$mInfo
;
/** @inheritDoc */
protected
$repoClass
=
ForeignAPIRepo
::
class
;
/**
* @param Title|string|false $title
* @param ForeignApiRepo $repo
* @param array $info
* @param bool $exists
*/
public
function
__construct
(
$title
,
$repo
,
$info
,
$exists
=
false
)
{
parent
::
__construct
(
$title
,
$repo
);
$this
->
mInfo
=
$info
;
$this
->
mExists
=
$exists
;
$this
->
assertRepoDefined
();
}
/**
* @param Title $title
* @param ForeignApiRepo $repo
* @return ForeignAPIFile|null
*/
public
static
function
newFromTitle
(
Title
$title
,
$repo
)
{
$data
=
$repo
->
fetchImageQuery
(
[
'titles'
=>
'File:'
.
$title
->
getDBkey
(),
'iiprop'
=>
self
::
getProps
(),
'prop'
=>
'imageinfo'
,
'iimetadataversion'
=>
MediaHandler
::
getMetadataVersion
(),
// extmetadata is language-dependent, accessing the current language here
// would be problematic, so we just get them all
'iiextmetadatamultilang'
=>
1
,
]
);
$info
=
$repo
->
getImageInfo
(
$data
);
if
(
$info
)
{
$lastRedirect
=
count
(
$data
[
'query'
][
'redirects'
]
??
[]
)
-
1
;
if
(
$lastRedirect
>=
0
)
{
// @phan-suppress-next-line PhanTypeArraySuspiciousNullable
$newtitle
=
Title
::
newFromText
(
$data
[
'query'
][
'redirects'
][
$lastRedirect
][
'to'
]
);
$img
=
new
self
(
$newtitle
,
$repo
,
$info
,
true
);
$img
->
redirectedFrom
(
$title
->
getDBkey
()
);
}
else
{
$img
=
new
self
(
$title
,
$repo
,
$info
,
true
);
}
return
$img
;
}
else
{
return
null
;
}
}
/**
* Get the property string for iiprop and aiprop
* @return string
*/
public
static
function
getProps
()
{
return
'timestamp|user|comment|url|size|sha1|metadata|mime|mediatype|extmetadata'
;
}
/**
* @return ForeignAPIRepo|false
*/
public
function
getRepo
()
{
return
$this
->
repo
;
}
// Dummy functions...
/**
* @return bool
*/
public
function
exists
()
{
return
$this
->
mExists
;
}
/**
* @return bool
*/
public
function
getPath
()
{
return
false
;
}
/**
* @param array $params
* @param int $flags
* @return MediaTransformOutput|false
*/
public
function
transform
(
$params
,
$flags
=
0
)
{
if
(
!
$this
->
canRender
()
)
{
// show icon
return
parent
::
transform
(
$params
,
$flags
);
}
// Note, the this->canRender() check above implies
// that we have a handler, and it can do makeParamString.
$otherParams
=
$this
->
handler
->
makeParamString
(
$params
);
$width
=
$params
[
'width'
]
??
-
1
;
$height
=
$params
[
'height'
]
??
-
1
;
$thumbUrl
=
false
;
if
(
$width
>
0
||
$height
>
0
)
{
// Only query the remote if there are dimensions
$thumbUrl
=
$this
->
repo
->
getThumbUrlFromCache
(
$this
->
getName
(),
$width
,
$height
,
$otherParams
);
}
elseif
(
$this
->
getMediaType
()
===
MEDIATYPE_AUDIO
)
{
// This has no dimensions, but we still need to pass a value to getTransform()
$thumbUrl
=
'/'
;
}
if
(
$thumbUrl
===
false
)
{
global
$wgLang
;
return
$this
->
repo
->
getThumbError
(
$this
->
getName
(),
$width
,
$height
,
$otherParams
,
$wgLang
->
getCode
()
);
}
return
$this
->
handler
->
getTransform
(
$this
,
'bogus'
,
$thumbUrl
,
$params
);
}
// Info we can get from API...
/**
* @param int $page
* @return int
*/
public
function
getWidth
(
$page
=
1
)
{
return
(
int
)(
$this
->
mInfo
[
'width'
]
??
0
);
}
/**
* @param int $page
* @return int
*/
public
function
getHeight
(
$page
=
1
)
{
return
(
int
)(
$this
->
mInfo
[
'height'
]
??
0
);
}
/**
* @return string|false
*/
public
function
getMetadata
()
{
if
(
isset
(
$this
->
mInfo
[
'metadata'
]
)
)
{
return
serialize
(
self
::
parseMetadata
(
$this
->
mInfo
[
'metadata'
]
)
);
}
return
false
;
}
/**
* @return array
*/
public
function
getMetadataArray
():
array
{
if
(
isset
(
$this
->
mInfo
[
'metadata'
]
)
)
{
return
self
::
parseMetadata
(
$this
->
mInfo
[
'metadata'
]
);
}
return
[];
}
/**
* @return array|null Extended metadata (see imageinfo API for format) or
* null on error
*/
public
function
getExtendedMetadata
()
{
return
$this
->
mInfo
[
'extmetadata'
]
??
null
;
}
/**
* @param mixed $metadata
* @return array
*/
public
static
function
parseMetadata
(
$metadata
)
{
if
(
!
is_array
(
$metadata
)
)
{
return
[
'_error'
=>
$metadata
];
}
'@phan-var array[] $metadata'
;
$ret
=
[];
foreach
(
$metadata
as
$meta
)
{
$ret
[
$meta
[
'name'
]]
=
self
::
parseMetadataValue
(
$meta
[
'value'
]
);
}
return
$ret
;
}
/**
* @param mixed $metadata
* @return mixed
*/
private
static
function
parseMetadataValue
(
$metadata
)
{
if
(
!
is_array
(
$metadata
)
)
{
return
$metadata
;
}
'@phan-var array[] $metadata'
;
$ret
=
[];
foreach
(
$metadata
as
$meta
)
{
$ret
[
$meta
[
'name'
]]
=
self
::
parseMetadataValue
(
$meta
[
'value'
]
);
}
return
$ret
;
}
/**
* @return int|null|false
*/
public
function
getSize
()
{
return
isset
(
$this
->
mInfo
[
'size'
]
)
?
intval
(
$this
->
mInfo
[
'size'
]
)
:
null
;
}
/**
* @return null|string
*/
public
function
getUrl
()
{
return
isset
(
$this
->
mInfo
[
'url'
]
)
?
strval
(
$this
->
mInfo
[
'url'
]
)
:
null
;
}
/**
* Get short description URL for a file based on the foreign API response,
* or if unavailable, the short URL is constructed from the foreign page ID.
*
* @return null|string
* @since 1.27
*/
public
function
getDescriptionShortUrl
()
{
if
(
isset
(
$this
->
mInfo
[
'descriptionshorturl'
]
)
)
{
return
$this
->
mInfo
[
'descriptionshorturl'
];
}
elseif
(
isset
(
$this
->
mInfo
[
'pageid'
]
)
)
{
$url
=
$this
->
repo
->
makeUrl
(
[
'curid'
=>
$this
->
mInfo
[
'pageid'
]
]
);
if
(
$url
!==
false
)
{
return
$url
;
}
}
return
null
;
}
public
function
getUploader
(
int
$audience
=
self
::
FOR_PUBLIC
,
?
Authority
$performer
=
null
):
?
UserIdentity
{
if
(
isset
(
$this
->
mInfo
[
'user'
]
)
)
{
return
UserIdentityValue
::
newExternal
(
$this
->
getRepoName
(),
$this
->
mInfo
[
'user'
]
);
}
return
null
;
}
/**
* @param int $audience
* @param Authority|null $performer
* @return null|string
*/
public
function
getDescription
(
$audience
=
self
::
FOR_PUBLIC
,
?
Authority
$performer
=
null
)
{
return
isset
(
$this
->
mInfo
[
'comment'
]
)
?
strval
(
$this
->
mInfo
[
'comment'
]
)
:
null
;
}
/**
* @return null|string
*/
public
function
getSha1
()
{
return
isset
(
$this
->
mInfo
[
'sha1'
]
)
?
Wikimedia\base_convert
(
strval
(
$this
->
mInfo
[
'sha1'
]
),
16
,
36
,
31
)
:
null
;
}
/**
* @return string|false
*/
public
function
getTimestamp
()
{
return
wfTimestamp
(
TS_MW
,
isset
(
$this
->
mInfo
[
'timestamp'
]
)
?
strval
(
$this
->
mInfo
[
'timestamp'
]
)
:
null
);
}
/**
* @return string
*/
public
function
getMimeType
()
{
if
(
!
isset
(
$this
->
mInfo
[
'mime'
]
)
)
{
$magic
=
MediaWikiServices
::
getInstance
()->
getMimeAnalyzer
();
$this
->
mInfo
[
'mime'
]
=
$magic
->
getMimeTypeFromExtensionOrNull
(
$this
->
getExtension
()
);
}
return
$this
->
mInfo
[
'mime'
];
}
/**
* @return int|string
*/
public
function
getMediaType
()
{
if
(
isset
(
$this
->
mInfo
[
'mediatype'
]
)
)
{
return
$this
->
mInfo
[
'mediatype'
];
}
$magic
=
MediaWikiServices
::
getInstance
()->
getMimeAnalyzer
();
return
$magic
->
getMediaType
(
null
,
$this
->
getMimeType
()
);
}
/**
* @return string|false
*/
public
function
getDescriptionUrl
()
{
return
$this
->
mInfo
[
'descriptionurl'
]
??
false
;
}
/**
* Only useful if we're locally caching thumbs anyway...
* @param string $suffix
* @return null|string
*/
public
function
getThumbPath
(
$suffix
=
''
)
{
if
(
!
$this
->
repo
->
canCacheThumbs
()
)
{
return
null
;
}
$path
=
$this
->
repo
->
getZonePath
(
'thumb'
)
.
'/'
.
$this
->
getHashPath
();
if
(
$suffix
)
{
$path
.=
$suffix
.
'/'
;
}
return
$path
;
}
/**
* @return string[]
*/
protected
function
getThumbnails
()
{
$dir
=
$this
->
getThumbPath
(
$this
->
getName
()
);
$iter
=
$this
->
repo
->
getBackend
()->
getFileList
(
[
'dir'
=>
$dir
]
);
$files
=
[];
if
(
$iter
)
{
foreach
(
$iter
as
$file
)
{
$files
[]
=
$file
;
}
}
return
$files
;
}
public
function
purgeCache
(
$options
=
[]
)
{
$this
->
purgeThumbnails
(
$options
);
$this
->
purgeDescriptionPage
();
}
private
function
purgeDescriptionPage
()
{
$services
=
MediaWikiServices
::
getInstance
();
$langCode
=
$services
->
getContentLanguage
()->
getCode
();
// Key must match File::getDescriptionText
$key
=
$this
->
repo
->
getLocalCacheKey
(
'file-remote-description'
,
$langCode
,
md5
(
$this
->
getName
()
)
);
$services
->
getMainWANObjectCache
()->
delete
(
$key
);
}
/**
* @param array $options
*/
public
function
purgeThumbnails
(
$options
=
[]
)
{
$key
=
$this
->
repo
->
getLocalCacheKey
(
'file-thumb-url'
,
sha1
(
$this
->
getName
()
)
);
MediaWikiServices
::
getInstance
()->
getMainWANObjectCache
()->
delete
(
$key
);
$files
=
$this
->
getThumbnails
();
// Give media handler a chance to filter the purge list
$handler
=
$this
->
getHandler
();
if
(
$handler
)
{
$handler
->
filterThumbnailPurgeList
(
$files
,
$options
);
}
$dir
=
$this
->
getThumbPath
(
$this
->
getName
()
);
$purgeList
=
[];
foreach
(
$files
as
$file
)
{
$purgeList
[]
=
"{$dir}{$file}"
;
}
# Delete the thumbnails
$this
->
repo
->
quickPurgeBatch
(
$purgeList
);
# Clear out the thumbnail directory if empty
$this
->
repo
->
quickCleanDir
(
$dir
);
}
/**
* The thumbnail is created on the foreign server and fetched over internet
* @since 1.25
* @return bool
*/
public
function
isTransformedLocally
()
{
return
false
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Aug 19 2026, 17:46 (5 w, 3 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
97/1d/c3acadd5359ccfb92ed252a6a888
Default Alt Text
ForeignAPIFile.php (10 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment