Merge "Made LogEventsList extend ContextSource and use local context instead of globa...
[lhc/web/wiklou.git] / includes / filerepo / ForeignAPIRepo.php
index 55b1be3..13de9e6 100644 (file)
@@ -2,6 +2,21 @@
 /**
  * Foreign repository accessible through api.php requests.
  *
+ * 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
  * @ingroup FileRepo
  */
@@ -32,20 +47,19 @@ class ForeignAPIRepo extends FileRepo {
        var $apiThumbCacheExpiry = 86400; /* 24*60*60 */
        /* Redownload thumbnail files after a month */
        var $fileCacheExpiry = 2592000; /* 86400*30 */
-       /* Local image directory */
-       var $directory;
-       var $thumbDir;
 
        protected $mQueryCache = array();
        protected $mFileExists = array();
 
+       /**
+        * @param $info array|null
+        */
        function __construct( $info ) {
+               global $wgLocalFileRepo;
                parent::__construct( $info );
-               global $wgUploadDirectory;
 
                // http://commons.wikimedia.org/w/api.php
                $this->mApiBase = isset( $info['apibase'] ) ? $info['apibase'] : null;
-               $this->directory = isset( $info['directory'] ) ? $info['directory'] : $wgUploadDirectory;
 
                if( isset( $info['apiThumbCacheExpiry'] ) ) {
                        $this->apiThumbCacheExpiry = $info['apiThumbCacheExpiry'];
@@ -59,22 +73,20 @@ class ForeignAPIRepo extends FileRepo {
                }
                // If we can cache thumbs we can guess sane defaults for these
                if( $this->canCacheThumbs() && !$this->url ) {
-                       global $wgLocalFileRepo;
                        $this->url = $wgLocalFileRepo['url'];
                }
                if( $this->canCacheThumbs() && !$this->thumbUrl ) {
                        $this->thumbUrl = $this->url . '/thumb';
                }
-               if ( isset( $info['thumbDir'] ) ) {
-                       $this->thumbDir =  $info['thumbDir'];
-               } else {
-                       $this->thumbDir = "{$this->directory}/thumb";
-               }
        }
 
        /**
         * Per docs in FileRepo, this needs to return false if we don't support versioned
         * files. Well, we don't.
+        *
+        * @param $title Title
+        * @param $time string|bool
+        * @return File
         */
        function newFile( $title, $time = false ) {
                if ( $time ) {
@@ -83,37 +95,26 @@ class ForeignAPIRepo extends FileRepo {
                return parent::newFile( $title, $time );
        }
 
-/**
- * No-ops
- */
-       function storeBatch( $triplets, $flags = 0 ) {
-               return false;
-       }
-       function storeTemp( $originalName, $srcPath ) {
-               return false;
-       }
-       function append( $srcPath, $toAppendPath, $flags = 0 ){
-               return false;
-       }
-       function publishBatch( $triplets, $flags = 0 ) {
-               return false;
-       }
-       function deleteBatch( $sourceDestPairs ) {
-               return false;
-       }
-
-       function fileExistsBatch( $files, $flags = 0 ) {
+       /**
+        * @param $files array
+        * @return array
+        */
+       function fileExistsBatch( array $files ) {
                $results = array();
                foreach ( $files as $k => $f ) {
                        if ( isset( $this->mFileExists[$k] ) ) {
                                $results[$k] = true;
                                unset( $files[$k] );
                        } elseif( self::isVirtualUrl( $f ) ) {
-                               # TODO! FIXME! We need to be able to handle virtual
+                               # @todo FIXME: We need to be able to handle virtual
                                # URLs better, at least when we know they refer to the
                                # same repo.
                                $results[$k] = false;
                                unset( $files[$k] );
+                       } elseif ( FileBackend::isStoragePath( $f ) ) {
+                               $results[$k] = false;
+                               unset( $files[$k] );
+                               wfWarn( "Got mwstore:// path '$f'." );
                        }
                }
 
@@ -129,17 +130,25 @@ class ForeignAPIRepo extends FileRepo {
                return $results;
        }
 
+       /**
+        * @param $virtualUrl string
+        * @return bool
+        */
        function getFileProps( $virtualUrl ) {
                return false;
        }
 
+       /**
+        * @param $query array
+        * @return string
+        */
        function fetchImageQuery( $query ) {
                global $wgMemc;
 
                $query = array_merge( $query,
                        array(
-                               'format' => 'json',
-                               'action' => 'query',
+                               'format'    => 'json',
+                               'action'    => 'query',
                                'redirects' => 'true'
                        ) );
                if ( $this->mApiBase ) {
@@ -168,6 +177,10 @@ class ForeignAPIRepo extends FileRepo {
                return FormatJson::decode( $this->mQueryCache[$url], true );
        }
 
+       /**
+        * @param $data array
+        * @return bool|array
+        */
        function getImageInfo( $data ) {
                if( $data && isset( $data['query']['pages'] ) ) {
                        foreach( $data['query']['pages'] as $info ) {
@@ -179,6 +192,10 @@ class ForeignAPIRepo extends FileRepo {
                return false;
        }
 
+       /**
+        * @param $hash string
+        * @return array
+        */
        function findBySha1( $hash ) {
                $results = $this->fetchImageQuery( array(
                                                                                'aisha1base36' => $hash,
@@ -197,6 +214,14 @@ class ForeignAPIRepo extends FileRepo {
                return $ret;
        }
 
+       /**
+        * @param $name string
+        * @param $width int
+        * @param $height int
+        * @param $result null
+        * @param $otherParams string
+        * @return bool
+        */
        function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
                $data = $this->fetchImageQuery( array(
                        'titles' => 'File:' . $name,
@@ -216,7 +241,7 @@ class ForeignAPIRepo extends FileRepo {
                }
        }
 
-       /*
+       /**
         * Return the imageurl from cache if possible
         *
         * If the url has been requested today, get it from cache
@@ -225,10 +250,14 @@ class ForeignAPIRepo extends FileRepo {
         * @param $name String is a dbkey form of a title
         * @param $width
         * @param $height
-        * @param String $param 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="" ) {
+       function getThumbUrlFromCache( $name, $width, $height, $params = "" ) {
                global $wgMemc;
+               // We can't check the local cache using FileRepo functions because
+               // we override fileExistsBatch(). We have to use the FileBackend directly.
+               $backend = $this->getBackend(); // convenience
 
                if ( !$this->canCacheThumbs() ) {
                        $result = null; // can't pass "null" by reference, but it's ok as default value
@@ -269,9 +298,11 @@ class ForeignAPIRepo extends FileRepo {
                $localFilename = $localPath . "/" . $fileName;
                $localUrl =  $this->getZoneUrl( 'thumb' ) . "/" . $this->getHashPath( $name ) . rawurlencode( $name ) . "/" . rawurlencode( $fileName );
 
-               if( file_exists( $localFilename ) && isset( $metadata['timestamp'] ) ) {
+               if( $backend->fileExists( array( 'src' => $localFilename ) )
+                       && isset( $metadata['timestamp'] ) )
+               {
                        wfDebug( __METHOD__ . " Thumbnail was already downloaded before\n" );
-                       $modified = filemtime( $localFilename );
+                       $modified = $backend->getFileTimestamp( array( 'src' => $localFilename ) );
                        $remoteModified = strtotime( $metadata['timestamp'] );
                        $current = time();
                        $diff = abs( $modified - $current );
@@ -288,21 +319,15 @@ class ForeignAPIRepo extends FileRepo {
                        wfDebug( __METHOD__ . " Could not download thumb\n" );
                        return false;
                }
-               if ( !is_dir($localPath) ) {
-                       if( !wfMkdirParents($localPath) ) {
-                               wfDebug(  __METHOD__ . " could not create directory $localPath for thumb\n" );
-                               return $foreignUrl;
-                       }
-               }
 
-               # FIXME: Delete old thumbs that aren't being used. Maintenance script?
-               wfSuppressWarnings();
-               if( !file_put_contents( $localFilename, $thumb ) ) {
-                       wfRestoreWarnings();
-                       wfDebug( __METHOD__ . " could not write to thumb path\n" );
+
+               # @todo FIXME: Delete old thumbs that aren't being used. Maintenance script?
+               $backend->prepare( array( 'dir' => dirname( $localFilename ) ) );
+               $params = array( 'dst' => $localFilename, 'content' => $thumb );
+               if( !$backend->quickCreate( $params )->isOK() ) {
+                       wfDebug( __METHOD__ . " could not write to thumb path '$localFilename'\n" );
                        return $foreignUrl;
                }
-               wfRestoreWarnings();
                $knownThumbUrls[$sizekey] = $localUrl;
                $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
                wfDebug( __METHOD__ . " got local thumb $localUrl, saving to cache \n" );
@@ -311,6 +336,8 @@ class ForeignAPIRepo extends FileRepo {
 
        /**
         * @see FileRepo::getZoneUrl()
+        * @param $zone String
+        * @return String
         */
        function getZoneUrl( $zone ) {
                switch ( $zone ) {
@@ -324,17 +351,16 @@ class ForeignAPIRepo extends FileRepo {
        }
 
        /**
-        * Get the local directory corresponding to one of the three basic zones
+        * Get the local directory corresponding to one of the basic zones
+        * @param $zone string
+        * @return bool|null|string
         */
        function getZonePath( $zone ) {
-               switch ( $zone ) {
-                       case 'public':
-                               return $this->directory;
-                       case 'thumb':
-                               return $this->thumbDir;
-                       default:
-                               return false;
+               $supported = array( 'public', 'thumb' );
+               if ( in_array( $zone, $supported ) ) {
+                       return parent::getZonePath( $zone );
                }
+               return false;
        }
 
        /**
@@ -347,6 +373,7 @@ class ForeignAPIRepo extends FileRepo {
 
        /**
         * The user agent the ForeignAPIRepo will use.
+        * @return string
         */
        public static function getUserAgent() {
                return Http::userAgent() . " ForeignAPIRepo/" . self::VERSION;
@@ -355,16 +382,20 @@ class ForeignAPIRepo extends FileRepo {
        /**
         * Like a Http:get request, but with custom User-Agent.
         * @see Http:get
+        * @param $url string
+        * @param $timeout string
+        * @param $options array
+        * @return bool|String
         */
        public static function httpGet( $url, $timeout = 'default', $options = array() ) {
                $options['timeout'] = $timeout;
                /* Http::get */
-               $url = wfExpandUrl( $url );
+               $url = wfExpandUrl( $url, PROTO_HTTP );
                wfDebug( "ForeignAPIRepo: HTTP GET: $url\n" );
                $options['method'] = "GET";
 
                if ( !isset( $options['timeout'] ) ) {
-                       $options['timeout'] = 'default';
+                       $options['timeout'] = 'default';
                }
 
                $req = MWHttpRequest::factory( $url, $options );
@@ -372,9 +403,24 @@ class ForeignAPIRepo extends FileRepo {
                $status = $req->execute();
 
                if ( $status->isOK() ) {
-                       return $req->getContent();
+                       return $req->getContent();
                } else {
-                       return false;
+                       return false;
                }
        }
+
+       /**
+        * @param $callback Array|string
+        * @throws MWException
+        */
+       function enumFiles( $callback ) {
+               throw new MWException( 'enumFiles is not supported by ' . get_class( $this ) );
+       }
+
+       /**
+        * @throws MWException
+        */
+       protected function assertWritableRepo() {
+               throw new MWException( get_class( $this ) . ': write operations are not supported.' );
+       }
 }