Add JavaScript variable wgContentNamespaces
[lhc/web/wiklou.git] / includes / filerepo / ForeignAPIRepo.php
index 128412c..bb16c8b 100644 (file)
@@ -42,13 +42,27 @@ class ForeignAPIRepo extends FileRepo {
         * Update the version every time you make breaking or significant changes. */
        const VERSION = "2.1";
 
-       var $fileFactory = array( 'ForeignAPIFile', 'newFromTitle' );
-       /* Check back with Commons after a day */
-       var $apiThumbCacheExpiry = 86400; /* 24*60*60 */
-       /* Redownload thumbnail files after a month */
-       var $fileCacheExpiry = 2592000; /* 86400*30 */
+       /**
+        * List of iiprop values for the thumbnail fetch queries.
+        * @since 1.23
+        */
+       protected static $imageInfoProps = array(
+               'url',
+               'thumbnail',
+               'timestamp',
+       );
+
+       protected $fileFactory = array( 'ForeignAPIFile', 'newFromTitle' );
+       /** @var int Check back with Commons after a day (24*60*60) */
+       protected $apiThumbCacheExpiry = 86400;
+
+       /** @var int Redownload thumbnail files after a month (86400*30) */
+       protected $fileCacheExpiry = 2592000;
 
-       protected $mQueryCache = array();
+       /** @var array  */
+       private $mQueryCache = array();
+
+       /** @var array  */
        protected $mFileExists = array();
 
        /**
@@ -80,6 +94,14 @@ class ForeignAPIRepo extends FileRepo {
                }
        }
 
+       /**
+        * @return string
+        * @since 1.22
+        */
+       function getApiUrl() {
+               return $this->mApiBase;
+       }
+
        /**
         * Per docs in FileRepo, this needs to return false if we don't support versioned
         * files. Well, we don't.
@@ -92,6 +114,7 @@ class ForeignAPIRepo extends FileRepo {
                if ( $time ) {
                        return false;
                }
+
                return parent::newFile( $title, $time );
        }
 
@@ -102,8 +125,8 @@ class ForeignAPIRepo extends FileRepo {
        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
@@ -118,15 +141,35 @@ class ForeignAPIRepo extends FileRepo {
                        }
                }
 
-               $data = $this->fetchImageQuery( array( 'titles' => implode( $files, '|' ),
-                                                                                       'prop' => 'imageinfo' ) );
+               $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;
        }
 
@@ -143,7 +186,7 @@ class ForeignAPIRepo extends FileRepo {
         * @return string
         */
        function fetchImageQuery( $query ) {
-               global $wgMemc, $wgLanguageCode;
+               global $wgLanguageCode;
 
                $query = array_merge( $query,
                        array(
@@ -151,33 +194,18 @@ class ForeignAPIRepo extends FileRepo {
                                '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 );
        }
 
        /**
@@ -192,6 +220,7 @@ class ForeignAPIRepo extends FileRepo {
                                }
                        }
                }
+
                return false;
        }
 
@@ -215,6 +244,7 @@ class ForeignAPIRepo extends FileRepo {
                                $ret[] = new ForeignAPIFile( Title::makeTitle( NS_FILE, $img['name'] ), $this, $img );
                        }
                }
+
                return $ret;
        }
 
@@ -229,7 +259,7 @@ class ForeignAPIRepo extends FileRepo {
        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,
@@ -239,6 +269,7 @@ class ForeignAPIRepo extends FileRepo {
                if ( $data && $info && isset( $info['thumburl'] ) ) {
                        wfDebug( __METHOD__ . " got remote thumb " . $info['thumburl'] . "\n" );
                        $result = $info;
+
                        return $info['thumburl'];
                } else {
                        return false;
@@ -256,7 +287,7 @@ class ForeignAPIRepo extends FileRepo {
        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,
@@ -267,6 +298,7 @@ class ForeignAPIRepo extends FileRepo {
 
                if ( $data && $info && isset( $info['thumberror'] ) ) {
                        wfDebug( __METHOD__ . " got remote thumb error " . $info['thumberror'] . "\n" );
+
                        return new MediaTransformError(
                                'thumbnail_error_remote',
                                $width,
@@ -288,7 +320,8 @@ class ForeignAPIRepo extends FileRepo {
         * @param string $name is a dbkey form of a title
         * @param $width
         * @param $height
-        * @param string $params Other rendering parameters (page number, etc) from handler's makeParamString.
+        * @param string $params Other rendering parameters (page number, etc)
+        *   from handler's makeParamString.
         * @return bool|string
         */
        function getThumbUrlFromCache( $name, $width, $height, $params = "" ) {
@@ -313,6 +346,7 @@ class ForeignAPIRepo extends FileRepo {
                        if ( isset( $knownThumbUrls[$sizekey] ) ) {
                                wfDebug( __METHOD__ . ': Got thumburl from local cache: ' .
                                        "{$knownThumbUrls[$sizekey]} \n" );
+
                                return $knownThumbUrls[$sizekey];
                        }
                        /* This size is not yet known */
@@ -323,6 +357,7 @@ class ForeignAPIRepo extends FileRepo {
 
                if ( !$foreignUrl ) {
                        wfDebug( __METHOD__ . " Could not find thumburl\n" );
+
                        return false;
                }
 
@@ -330,14 +365,17 @@ class ForeignAPIRepo extends FileRepo {
                $fileName = rawurldecode( pathinfo( $foreignUrl, PATHINFO_BASENAME ) );
                if ( !$this->validateFilename( $fileName ) ) {
                        wfDebug( __METHOD__ . " The deduced filename $fileName is not safe\n" );
+
                        return false;
                }
                $localPath = $this->getZonePath( 'thumb' ) . "/" . $this->getHashPath( $name ) . $name;
                $localFilename = $localPath . "/" . $fileName;
-               $localUrl = $this->getZoneUrl( 'thumb' ) . "/" . $this->getHashPath( $name ) . rawurlencode( $name ) . "/" . rawurlencode( $fileName );
+               $localUrl = $this->getZoneUrl( 'thumb' ) . "/" . $this->getHashPath( $name ) .
+                       rawurlencode( $name ) . "/" . rawurlencode( $fileName );
 
                if ( $backend->fileExists( array( 'src' => $localFilename ) )
-                       && isset( $metadata['timestamp'] ) ) {
+                       && isset( $metadata['timestamp'] )
+               ) {
                        wfDebug( __METHOD__ . " Thumbnail was already downloaded before\n" );
                        $modified = $backend->getFileTimestamp( array( 'src' => $localFilename ) );
                        $remoteModified = strtotime( $metadata['timestamp'] );
@@ -347,6 +385,7 @@ class ForeignAPIRepo extends FileRepo {
                                /* Use our current and already downloaded thumbnail */
                                $knownThumbUrls[$sizekey] = $localUrl;
                                $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
+
                                return $localUrl;
                        }
                        /* There is a new Commons file, or existing thumbnail older than a month */
@@ -354,6 +393,7 @@ class ForeignAPIRepo extends FileRepo {
                $thumb = self::httpGet( $foreignUrl );
                if ( !$thumb ) {
                        wfDebug( __METHOD__ . " Could not download thumb\n" );
+
                        return false;
                }
 
@@ -362,11 +402,13 @@ class ForeignAPIRepo extends FileRepo {
                $params = array( 'dst' => $localFilename, 'content' => $thumb );
                if ( !$backend->quickCreate( $params )->isOK() ) {
                        wfDebug( __METHOD__ . " could not write to thumb path '$localFilename'\n" );
+
                        return $foreignUrl;
                }
                $knownThumbUrls[$sizekey] = $localUrl;
                $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
                wfDebug( __METHOD__ . " got local thumb $localUrl, saving to cache \n" );
+
                return $localUrl;
        }
 
@@ -397,6 +439,7 @@ class ForeignAPIRepo extends FileRepo {
                if ( in_array( $zone, $supported ) ) {
                        return parent::getZonePath( $zone );
                }
+
                return false;
        }
 
@@ -416,6 +459,36 @@ class ForeignAPIRepo extends FileRepo {
                return Http::userAgent() . " ForeignAPIRepo/" . self::VERSION;
        }
 
+       /**
+        * Get information about the repo - overrides/extends the parent
+        * class's information.
+        * @return array
+        * @since 1.22
+        */
+       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;
+       }
+
        /**
         * Like a Http:get request, but with custom User-Agent.
         * @see Http:get
@@ -446,6 +519,54 @@ class ForeignAPIRepo extends FileRepo {
                }
        }
 
+       /**
+        * @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