* Update the version every time you make breaking or significant changes. */
const VERSION = "2.1";
+ /**
+ * List of iiprop values for the thumbnail fetch queries.
+ * @since 1.23
+ */
+ protected static $imageInfoProps = array(
+ 'url',
+ 'thumbnail',
+ 'timestamp',
+ );
+
var $fileFactory = array( 'ForeignAPIFile', 'newFromTitle' );
/* Check back with Commons after a day */
var $apiThumbCacheExpiry = 86400; /* 24*60*60 */
function fileExistsBatch( array $files ) {
$results = array();
foreach ( $files as $k => $f ) {
- if ( isset( $this->mFileExists[$k] ) ) {
- $results[$k] = true;
+ if ( isset( $this->mFileExists[$f] ) ) {
+ $results[$k] = $this->mFileExists[$f];
unset( $files[$k] );
} elseif ( self::isVirtualUrl( $f ) ) {
# @todo FIXME: We need to be able to handle virtual
$data = $this->fetchImageQuery( array( 'titles' => implode( $files, '|' ),
'prop' => 'imageinfo' ) );
if ( isset( $data['query']['pages'] ) ) {
- $i = 0;
+ # First, get results from the query. Note we only care whether the image exists,
+ # not whether it has a description page.
+ foreach ( $data['query']['pages'] as $p ) {
+ $this->mFileExists[$p['title']] = ( $p['imagerepository'] !== '' );
+ }
+ # Second, copy the results to any redirects that were queried
+ if ( isset( $data['query']['redirects'] ) ) {
+ foreach ( $data['query']['redirects'] as $r ) {
+ $this->mFileExists[$r['from']] = $this->mFileExists[$r['to']];
+ }
+ }
+ # Third, copy the results to any non-normalized titles that were queried
+ if ( isset( $data['query']['normalized'] ) ) {
+ foreach ( $data['query']['normalized'] as $n ) {
+ $this->mFileExists[$n['from']] = $this->mFileExists[$n['to']];
+ }
+ }
+ # Finally, copy the results to the output
foreach ( $files as $key => $file ) {
- $results[$key] = $this->mFileExists[$key] = !isset( $data['query']['pages'][$i]['missing'] );
- $i++;
+ $results[$key] = $this->mFileExists[$file];
}
}
return $results;
'action' => 'query',
'redirects' => 'true'
) );
+
if ( !isset( $query['uselang'] ) ) { // uselang is unset or null
$query['uselang'] = $wgLanguageCode;
}
- if ( $this->mApiBase ) {
- $url = wfAppendQuery( $this->mApiBase, $query );
- } else {
- $url = $this->makeUrl( $query, 'api' );
- }
- if ( !isset( $this->mQueryCache[$url] ) ) {
- $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'Metadata', md5( $url ) );
- $data = $wgMemc->get( $key );
- if ( !$data ) {
- $data = self::httpGet( $url );
- if ( !$data ) {
- return null;
- }
- $wgMemc->set( $key, $data, 3600 );
- }
+ $data = $this->httpGetCached( 'Metadata', $query );
- if ( count( $this->mQueryCache ) > 100 ) {
- // Keep the cache from growing infinitely
- $this->mQueryCache = array();
- }
- $this->mQueryCache[$url] = $data;
+ if ( $data ) {
+ return FormatJson::decode( $data, true );
+ } else {
+ return null;
}
- return FormatJson::decode( $this->mQueryCache[$url], true );
}
/**
function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
$data = $this->fetchImageQuery( array(
'titles' => 'File:' . $name,
- 'iiprop' => 'url|timestamp',
+ 'iiprop' => self::getIIProps(),
'iiurlwidth' => $width,
'iiurlheight' => $height,
'iiurlparam' => $otherParams,
function getThumbError( $name, $width = -1, $height = -1, $otherParams = '', $lang = null ) {
$data = $this->fetchImageQuery( array(
'titles' => 'File:' . $name,
- 'iiprop' => 'url|timestamp',
+ 'iiprop' => self::getIIProps(),
'iiurlwidth' => $width,
'iiurlheight' => $height,
'iiurlparam' => $otherParams,
function getInfo() {
$info = parent::getInfo();
$info['apiurl'] = $this->getApiUrl();
+
+ $query = array(
+ 'format' => 'json',
+ 'action' => 'query',
+ 'meta' => 'siteinfo',
+ 'siprop' => 'general',
+ );
+
+ $data = $this->httpGetCached( 'SiteInfo', $query, 7200 );
+
+ if ( $data ) {
+ $siteInfo = FormatJson::decode( $data, true );
+ $general = $siteInfo['query']['general'];
+
+ $info['articlepath'] = $general['articlepath'];
+ $info['server'] = $general['server'];
+ }
+
return $info;
}
}
}
+ /**
+ * @return string
+ * @since 1.23
+ */
+ protected static function getIIProps() {
+ return join( '|', self::$imageInfoProps );
+ }
+
+ /**
+ * HTTP GET request to a mediawiki API (with caching)
+ * @param $target string Used in cache key creation, mostly
+ * @param $query array The query parameters for the API request
+ * @param $cacheTTL int Time to live for the memcached caching
+ */
+ public function httpGetCached( $target, $query, $cacheTTL = 3600 ) {
+ if ( $this->mApiBase ) {
+ $url = wfAppendQuery( $this->mApiBase, $query );
+ } else {
+ $url = $this->makeUrl( $query, 'api' );
+ }
+
+ if ( !isset( $this->mQueryCache[$url] ) ) {
+ global $wgMemc;
+
+ $key = $this->getLocalCacheKey( get_class( $this ), $target, md5( $url ) );
+ $data = $wgMemc->get( $key );
+
+ if ( !$data ) {
+ $data = self::httpGet( $url );
+
+ if ( !$data ) {
+ return null;
+ }
+
+ $wgMemc->set( $key, $data, $cacheTTL );
+ }
+
+ if ( count( $this->mQueryCache ) > 100 ) {
+ // Keep the cache from growing infinitely
+ $this->mQueryCache = array();
+ }
+
+ $this->mQueryCache[$url] = $data;
+ }
+
+ return $this->mQueryCache[$url];
+ }
+
/**
* @param $callback Array|string
* @throws MWException