00001 <?php
00002
00020 class ForeignAPIRepo extends FileRepo {
00021 var $fileFactory = array( 'ForeignAPIFile', 'newFromTitle' );
00022 var $apiThumbCacheExpiry = 86400;
00023 protected $mQueryCache = array();
00024 protected $mFileExists = array();
00025
00026 function __construct( $info ) {
00027 parent::__construct( $info );
00028 $this->mApiBase = $info['apibase'];
00029 if( isset( $info['apiThumbCacheExpiry'] ) ) {
00030 $this->apiThumbCacheExpiry = $info['apiThumbCacheExpiry'];
00031 }
00032 if( !$this->scriptDirUrl ) {
00033
00034 $this->scriptDirUrl = dirname( $this->mApiBase );
00035 }
00036
00037 if( $this->canCacheThumbs() && !$this->url ) {
00038 global $wgLocalFileRepo;
00039 $this->url = $wgLocalFileRepo['url'];
00040 }
00041 if( $this->canCacheThumbs() && !$this->thumbUrl ) {
00042 $this->thumbUrl = $this->url . '/thumb';
00043 }
00044 }
00045
00050 function newFile( $title, $time = false ) {
00051 if ( $time ) {
00052 return false;
00053 }
00054 return parent::newFile( $title, $time );
00055 }
00056
00060 function storeBatch( $triplets, $flags = 0 ) {
00061 return false;
00062 }
00063 function storeTemp( $originalName, $srcPath ) {
00064 return false;
00065 }
00066 function append( $srcPath, $toAppendPath, $flags = 0 ){
00067 return false;
00068 }
00069 function publishBatch( $triplets, $flags = 0 ) {
00070 return false;
00071 }
00072 function deleteBatch( $sourceDestPairs ) {
00073 return false;
00074 }
00075
00076
00077 function fileExistsBatch( $files, $flags = 0 ) {
00078 $results = array();
00079 foreach ( $files as $k => $f ) {
00080 if ( isset( $this->mFileExists[$k] ) ) {
00081 $results[$k] = true;
00082 unset( $files[$k] );
00083 } elseif( self::isVirtualUrl( $f ) ) {
00084 # TODO! FIXME! We need to be able to handle virtual
00085 # URLs better, at least when we know they refer to the
00086 # same repo.
00087 $results[$k] = false;
00088 unset( $files[$k] );
00089 }
00090 }
00091
00092 $results = $this->fetchImageQuery( array( 'titles' => implode( $files, '|' ),
00093 'prop' => 'imageinfo' ) );
00094 if( isset( $data['query']['pages'] ) ) {
00095 $i = 0;
00096 foreach( $files as $key => $file ) {
00097 $results[$key] = $this->mFileExists[$key] = !isset( $data['query']['pages'][$i]['missing'] );
00098 $i++;
00099 }
00100 }
00101 }
00102 function getFileProps( $virtualUrl ) {
00103 return false;
00104 }
00105
00106 protected function queryImage( $query ) {
00107 $data = $this->fetchImageQuery( $query );
00108
00109 if( isset( $data['query']['pages'] ) ) {
00110 foreach( $data['query']['pages'] as $pageid => $info ) {
00111 if( isset( $info['imageinfo'][0] ) ) {
00112 return $info['imageinfo'][0];
00113 }
00114 }
00115 }
00116 return false;
00117 }
00118
00119 protected function fetchImageQuery( $query ) {
00120 global $wgMemc;
00121
00122 $url = $this->mApiBase .
00123 '?' .
00124 wfArrayToCgi(
00125 array_merge( $query,
00126 array(
00127 'format' => 'json',
00128 'action' => 'query' ) ) );
00129
00130 if( !isset( $this->mQueryCache[$url] ) ) {
00131 $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'Metadata', md5( $url ) );
00132 $data = $wgMemc->get( $key );
00133 if( !$data ) {
00134 $data = Http::get( $url );
00135 if ( !$data ) {
00136 return null;
00137 }
00138 $wgMemc->set( $key, $data, 3600 );
00139 }
00140
00141 if( count( $this->mQueryCache ) > 100 ) {
00142
00143 $this->mQueryCache = array();
00144 }
00145 $this->mQueryCache[$url] = $data;
00146 }
00147 return FormatJson::decode( $this->mQueryCache[$url], true );
00148 }
00149
00150 function getImageInfo( $title, $time = false ) {
00151 return $this->queryImage( array(
00152 'titles' => 'Image:' . $title->getText(),
00153 'iiprop' => 'timestamp|user|comment|url|size|sha1|metadata|mime',
00154 'prop' => 'imageinfo' ) );
00155 }
00156
00157 function findBySha1( $hash ) {
00158 $results = $this->fetchImageQuery( array(
00159 'aisha1base36' => $hash,
00160 'aiprop' => 'timestamp|user|comment|url|size|sha1|metadata|mime',
00161 'list' => 'allimages', ) );
00162 $ret = array();
00163 if ( isset( $results['query']['allimages'] ) ) {
00164 foreach ( $results['query']['allimages'] as $img ) {
00165 $ret[] = new ForeignAPIFile( Title::makeTitle( NS_FILE, $img['name'] ), $this, $img );
00166 }
00167 }
00168 return $ret;
00169 }
00170
00171 function getThumbUrl( $name, $width=-1, $height=-1 ) {
00172 $info = $this->queryImage( array(
00173 'titles' => 'Image:' . $name,
00174 'iiprop' => 'url',
00175 'iiurlwidth' => $width,
00176 'iiurlheight' => $height,
00177 'prop' => 'imageinfo' ) );
00178 if( $info && $info['thumburl'] ) {
00179 wfDebug( __METHOD__ . " got remote thumb " . $info['thumburl'] . "\n" );
00180 return $info['thumburl'];
00181 } else {
00182 return false;
00183 }
00184 }
00185
00186 function getThumbUrlFromCache( $name, $width, $height ) {
00187 global $wgMemc, $wgUploadPath, $wgServer, $wgUploadDirectory;
00188
00189 if ( !$this->canCacheThumbs() ) {
00190 return $this->getThumbUrl( $name, $width, $height );
00191 }
00192
00193 $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $name );
00194 if ( $thumbUrl = $wgMemc->get($key) ) {
00195 wfDebug("Got thumb from local cache. $thumbUrl \n");
00196 return $thumbUrl;
00197 }
00198 else {
00199 $foreignUrl = $this->getThumbUrl( $name, $width, $height );
00200 if( !$foreignUrl ) {
00201 wfDebug( __METHOD__ . " Could not find thumburl\n" );
00202 return false;
00203 }
00204 $thumb = Http::get( $foreignUrl );
00205 if( !$thumb ) {
00206 wfDebug( __METHOD__ . " Could not download thumb\n" );
00207 return false;
00208 }
00209
00210 $fileName = rawurldecode( pathinfo( $foreignUrl, PATHINFO_BASENAME ) );
00211 $path = 'thumb/' . $this->getHashPath( $name ) . $name . "/";
00212 if ( !is_dir($wgUploadDirectory . '/' . $path) ) {
00213 wfMkdirParents($wgUploadDirectory . '/' . $path);
00214 }
00215 $localUrl = $wgServer . $wgUploadPath . '/' . $path . $fileName;
00216 # FIXME: Delete old thumbs that aren't being used. Maintenance script?
00217 if( !file_put_contents($wgUploadDirectory . '/' . $path . $fileName, $thumb ) ) {
00218 wfDebug( __METHOD__ . " could not write to thumb path\n" );
00219 return $foreignUrl;
00220 }
00221 $wgMemc->set( $key, $localUrl, $this->apiThumbCacheExpiry );
00222 wfDebug( __METHOD__ . " got local thumb $localUrl, saving to cache \n" );
00223 return $localUrl;
00224 }
00225 }
00226
00230 function getZoneUrl( $zone ) {
00231 switch ( $zone ) {
00232 case 'public':
00233 return $this->url;
00234 case 'thumb':
00235 return $this->thumbUrl;
00236 default:
00237 return parent::getZoneUrl( $zone );
00238 }
00239 }
00240
00245 public function canCacheThumbs() {
00246 return ( $this->apiThumbCacheExpiry > 0 );
00247 }
00248 }