* @ingroup FileRepo
*/
class ForeignAPIRepo extends FileRepo {
+ /* This version string is used in the user agent for requests and will help
+ * server maintainers in identify ForeignAPI usage.
+ * 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;
+ var $apiThumbCacheExpiry = 86400; /* 24*60*60 */
/* Redownload thumbnail files after a month */
- var $fileCacheExpiry = 2629743;
+ var $fileCacheExpiry = 2592000; /* 86400*30 */
/* Local image directory */
var $directory;
var $thumbDir;
return false;
}
-
function fileExistsBatch( $files, $flags = 0 ) {
$results = array();
foreach ( $files as $k => $f ) {
}
}
- $results = $this->fetchImageQuery( array( 'titles' => implode( $files, '|' ),
+ $data = $this->fetchImageQuery( array( 'titles' => implode( $files, '|' ),
'prop' => 'imageinfo' ) );
if( isset( $data['query']['pages'] ) ) {
$i = 0;
$i++;
}
}
+ return $results;
}
+
function getFileProps( $virtualUrl ) {
return false;
}
$key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'Metadata', md5( $url ) );
$data = $wgMemc->get( $key );
if( !$data ) {
- $data = Http::get( $url );
+ $data = self::httpGet( $url );
if ( !$data ) {
return null;
}
return $ret;
}
- function getThumbUrl( $name, $width=-1, $height=-1, &$result ) {
+ function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
$data = $this->fetchImageQuery( array(
'titles' => 'File:' . $name,
'iiprop' => 'url|timestamp',
'iiurlwidth' => $width,
'iiurlheight' => $height,
+ 'iiurlparam' => $otherParams,
'prop' => 'imageinfo' ) );
$info = $this->getImageInfo( $data );
* @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.
*/
- function getThumbUrlFromCache( $name, $width, $height ) {
+ function getThumbUrlFromCache( $name, $width, $height, $params="" ) {
global $wgMemc;
if ( !$this->canCacheThumbs() ) {
- return $this->getThumbUrl( $name, $width, $height );
+ return $this->getThumbUrl( $name, $width, $height, null, $params );
}
- $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $name, $width );
+ $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $name );
+ $sizekey = "$width:$height:$params";
- $thumbUrl = $wgMemc->get($key);
- if ( $thumbUrl ) {
- wfDebug("Got thumb from local cache. $thumbUrl \n");
- return $thumbUrl;
+ /* Get the array of urls that we already know */
+ $knownThumbUrls = $wgMemc->get($key);
+ if( !$knownThumbUrls ) {
+ /* No knownThumbUrls for this file */
+ $knownThumbUrls = array();
+ } else {
+ if( isset( $knownThumbUrls[$sizekey] ) ) {
+ wfDebug( __METHOD__ . ': Got thumburl from local cache: ' .
+ "{$knownThumbUrls[$sizekey]} \n");
+ return $knownThumbUrls[$sizekey];
+ }
+ /* This size is not yet known */
}
- else {
- $metadata = null;
- $foreignUrl = $this->getThumbUrl( $name, $width, $height, $metadata );
- if( !$foreignUrl ) {
- wfDebug( __METHOD__ . " Could not find thumburl\n" );
- return false;
- }
+ $metadata = null;
+ $foreignUrl = $this->getThumbUrl( $name, $width, $height, $metadata, $params );
- // We need the same filename as the remote one :)
- $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 ) . urlencode( $name ) . "/" . urlencode( $fileName );
-
- if( file_exists( $localFilename ) && isset( $metadata['timestamp'] ) ) {
- wfDebug( __METHOD__ . " Thumbnail was already downloaded before\n" );
- $modified = filemtime( $localFilename );
- $remoteModified = strtotime( $metadata['timestamp'] );
- $diff = abs( $modified - $remoteModified );
- if( $remoteModified < $modified && $diff < $this->fileCacheExpiry ) {
- /* Use our current and already downloaded thumbnail */
- $wgMemc->set( $key, $localUrl, $this->apiThumbCacheExpiry );
- return $localUrl;
- }
- /* There is a new Commons file, or existing thumbnail older than a month */
- }
- $thumb = Http::get( $foreignUrl );
- if( !$thumb ) {
- 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;
- }
- }
+ if( !$foreignUrl ) {
+ wfDebug( __METHOD__ . " Could not find thumburl\n" );
+ return false;
+ }
- # 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" );
+ // We need the same filename as the remote one :)
+ $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 );
+
+ if( file_exists( $localFilename ) && isset( $metadata['timestamp'] ) ) {
+ wfDebug( __METHOD__ . " Thumbnail was already downloaded before\n" );
+ $modified = filemtime( $localFilename );
+ $remoteModified = strtotime( $metadata['timestamp'] );
+ $current = time();
+ $diff = abs( $modified - $current );
+ if( $remoteModified < $modified && $diff < $this->fileCacheExpiry ) {
+ /* 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 */
+ }
+ $thumb = self::httpGet( $foreignUrl );
+ if( !$thumb ) {
+ 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();
- $wgMemc->set( $key, $localUrl, $this->apiThumbCacheExpiry );
- wfDebug( __METHOD__ . " got local thumb $localUrl, saving to cache \n" );
- return $localUrl;
+ wfDebug( __METHOD__ . " could not write to thumb path\n" );
+ return $foreignUrl;
}
+ wfRestoreWarnings();
+ $knownThumbUrls[$sizekey] = $localUrl;
+ $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
+ wfDebug( __METHOD__ . " got local thumb $localUrl, saving to cache \n" );
+ return $localUrl;
}
/**
default:
return false;
}
- }
+ }
/**
* Are we locally caching the thumbnails?
public function canCacheThumbs() {
return ( $this->apiThumbCacheExpiry > 0 );
}
+
+ /**
+ * The user agent the ForeignAPIRepo will use.
+ */
+ public static function getUserAgent() {
+ return Http::userAgent() . " ForeignAPIRepo/" . self::VERSION;
+ }
+
+ /**
+ * Like a Http:get request, but with custom User-Agent.
+ * @see Http:get
+ */
+ public static function httpGet( $url, $timeout = 'default', $options = array() ) {
+ $options['timeout'] = $timeout;
+ /* Http::get */
+ $url = wfExpandUrl( $url );
+ wfDebug( "ForeignAPIRepo: HTTP GET: $url\n" );
+ $options['method'] = "GET";
+
+ if ( !isset( $options['timeout'] ) ) {
+ $options['timeout'] = 'default';
+ }
+
+ $req = MWHttpRequest::factory( $url, $options );
+ $req->setUserAgent( ForeignAPIRepo::getUserAgent() );
+ $status = $req->execute();
+
+ if ( $status->isOK() ) {
+ return $req->getContent();
+ } else {
+ return false;
+ }
+ }
}