MediaWiki
REL1_22
|
00001 <?php 00029 class Interwiki { 00030 // Cache - removes oldest entry when it hits limit 00031 protected static $smCache = array(); 00032 const CACHE_LIMIT = 100; // 0 means unlimited, any other value is max number of entries. 00033 00034 protected $mPrefix, $mURL, $mAPI, $mWikiID, $mLocal, $mTrans; 00035 00036 public function __construct( $prefix = null, $url = '', $api = '', $wikiId = '', $local = 0, 00037 $trans = 0 00038 ) { 00039 $this->mPrefix = $prefix; 00040 $this->mURL = $url; 00041 $this->mAPI = $api; 00042 $this->mWikiID = $wikiId; 00043 $this->mLocal = $local; 00044 $this->mTrans = $trans; 00045 } 00046 00053 public static function isValidInterwiki( $prefix ) { 00054 $result = self::fetch( $prefix ); 00055 return (bool)$result; 00056 } 00057 00064 public static function fetch( $prefix ) { 00065 global $wgContLang; 00066 if ( $prefix == '' ) { 00067 return null; 00068 } 00069 $prefix = $wgContLang->lc( $prefix ); 00070 if ( isset( self::$smCache[$prefix] ) ) { 00071 return self::$smCache[$prefix]; 00072 } 00073 global $wgInterwikiCache; 00074 if ( $wgInterwikiCache ) { 00075 $iw = Interwiki::getInterwikiCached( $prefix ); 00076 } else { 00077 $iw = Interwiki::load( $prefix ); 00078 if ( !$iw ) { 00079 $iw = false; 00080 } 00081 } 00082 if ( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ) { 00083 reset( self::$smCache ); 00084 unset( self::$smCache[key( self::$smCache )] ); 00085 } 00086 self::$smCache[$prefix] = $iw; 00087 return $iw; 00088 } 00089 00098 protected static function getInterwikiCached( $prefix ) { 00099 $value = self::getInterwikiCacheEntry( $prefix ); 00100 00101 $s = new Interwiki( $prefix ); 00102 if ( $value != '' ) { 00103 // Split values 00104 list( $local, $url ) = explode( ' ', $value, 2 ); 00105 $s->mURL = $url; 00106 $s->mLocal = (int)$local; 00107 } else { 00108 $s = false; 00109 } 00110 return $s; 00111 } 00112 00121 protected static function getInterwikiCacheEntry( $prefix ) { 00122 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00123 static $db, $site; 00124 00125 wfDebug( __METHOD__ . "( $prefix )\n" ); 00126 if ( !$db ) { 00127 $db = CdbReader::open( $wgInterwikiCache ); 00128 } 00129 /* Resolve site name */ 00130 if ( $wgInterwikiScopes >= 3 && !$site ) { 00131 $site = $db->get( '__sites:' . wfWikiID() ); 00132 if ( $site == '' ) { 00133 $site = $wgInterwikiFallbackSite; 00134 } 00135 } 00136 00137 $value = $db->get( wfMemcKey( $prefix ) ); 00138 // Site level 00139 if ( $value == '' && $wgInterwikiScopes >= 3 ) { 00140 $value = $db->get( "_{$site}:{$prefix}" ); 00141 } 00142 // Global Level 00143 if ( $value == '' && $wgInterwikiScopes >= 2 ) { 00144 $value = $db->get( "__global:{$prefix}" ); 00145 } 00146 if ( $value == 'undef' ) { 00147 $value = ''; 00148 } 00149 00150 return $value; 00151 } 00152 00159 protected static function load( $prefix ) { 00160 global $wgMemc, $wgInterwikiExpiry; 00161 00162 $iwData = false; 00163 if ( !wfRunHooks( 'InterwikiLoadPrefix', array( $prefix, &$iwData ) ) ) { 00164 return Interwiki::loadFromArray( $iwData ); 00165 } 00166 00167 if ( !$iwData ) { 00168 $key = wfMemcKey( 'interwiki', $prefix ); 00169 $iwData = $wgMemc->get( $key ); 00170 if ( $iwData === '!NONEXISTENT' ) { 00171 return false; // negative cache hit 00172 } 00173 } 00174 00175 if ( $iwData && is_array( $iwData ) ) { // is_array is hack for old keys 00176 $iw = Interwiki::loadFromArray( $iwData ); 00177 if ( $iw ) { 00178 return $iw; 00179 } 00180 } 00181 00182 $db = wfGetDB( DB_SLAVE ); 00183 00184 $row = $db->fetchRow( $db->select( 'interwiki', self::selectFields(), array( 'iw_prefix' => $prefix ), 00185 __METHOD__ ) ); 00186 $iw = Interwiki::loadFromArray( $row ); 00187 if ( $iw ) { 00188 $mc = array( 00189 'iw_url' => $iw->mURL, 00190 'iw_api' => $iw->mAPI, 00191 'iw_local' => $iw->mLocal, 00192 'iw_trans' => $iw->mTrans 00193 ); 00194 $wgMemc->add( $key, $mc, $wgInterwikiExpiry ); 00195 return $iw; 00196 } else { 00197 $wgMemc->add( $key, '!NONEXISTENT', $wgInterwikiExpiry ); // negative cache hit 00198 } 00199 00200 return false; 00201 } 00202 00209 protected static function loadFromArray( $mc ) { 00210 if ( isset( $mc['iw_url'] ) ) { 00211 $iw = new Interwiki(); 00212 $iw->mURL = $mc['iw_url']; 00213 $iw->mLocal = isset( $mc['iw_local'] ) ? $mc['iw_local'] : 0; 00214 $iw->mTrans = isset( $mc['iw_trans'] ) ? $mc['iw_trans'] : 0; 00215 $iw->mAPI = isset( $mc['iw_api'] ) ? $mc['iw_api'] : ''; 00216 $iw->mWikiID = isset( $mc['iw_wikiid'] ) ? $mc['iw_wikiid'] : ''; 00217 00218 return $iw; 00219 } 00220 return false; 00221 } 00222 00230 protected static function getAllPrefixesCached( $local ) { 00231 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00232 static $db, $site; 00233 00234 wfDebug( __METHOD__ . "()\n" ); 00235 if ( !$db ) { 00236 $db = CdbReader::open( $wgInterwikiCache ); 00237 } 00238 /* Resolve site name */ 00239 if ( $wgInterwikiScopes >= 3 && !$site ) { 00240 $site = $db->get( '__sites:' . wfWikiID() ); 00241 if ( $site == '' ) { 00242 $site = $wgInterwikiFallbackSite; 00243 } 00244 } 00245 00246 // List of interwiki sources 00247 $sources = array(); 00248 // Global Level 00249 if ( $wgInterwikiScopes >= 2 ) { 00250 $sources[] = '__global'; 00251 } 00252 // Site level 00253 if ( $wgInterwikiScopes >= 3 ) { 00254 $sources[] = '_' . $site; 00255 } 00256 $sources[] = wfWikiID(); 00257 00258 $data = array(); 00259 00260 foreach ( $sources as $source ) { 00261 $list = $db->get( "__list:{$source}" ); 00262 foreach ( explode( ' ', $list ) as $iw_prefix ) { 00263 $row = $db->get( "{$source}:{$iw_prefix}" ); 00264 if ( !$row ) { 00265 continue; 00266 } 00267 00268 list( $iw_local, $iw_url ) = explode( ' ', $row ); 00269 00270 if ( $local !== null && $local != $iw_local ) { 00271 continue; 00272 } 00273 00274 $data[$iw_prefix] = array( 00275 'iw_prefix' => $iw_prefix, 00276 'iw_url' => $iw_url, 00277 'iw_local' => $iw_local, 00278 ); 00279 } 00280 } 00281 00282 ksort( $data ); 00283 00284 return array_values( $data ); 00285 } 00286 00294 protected static function getAllPrefixesDB( $local ) { 00295 $db = wfGetDB( DB_SLAVE ); 00296 00297 $where = array(); 00298 00299 if ( $local !== null ) { 00300 if ( $local == 1 ) { 00301 $where['iw_local'] = 1; 00302 } elseif ( $local == 0 ) { 00303 $where['iw_local'] = 0; 00304 } 00305 } 00306 00307 $res = $db->select( 'interwiki', 00308 self::selectFields(), 00309 $where, __METHOD__, array( 'ORDER BY' => 'iw_prefix' ) 00310 ); 00311 $retval = array(); 00312 foreach ( $res as $row ) { 00313 $retval[] = (array)$row; 00314 } 00315 return $retval; 00316 } 00317 00325 public static function getAllPrefixes( $local = null ) { 00326 global $wgInterwikiCache; 00327 00328 if ( $wgInterwikiCache ) { 00329 return self::getAllPrefixesCached( $local ); 00330 } else { 00331 return self::getAllPrefixesDB( $local ); 00332 } 00333 } 00334 00344 public function getURL( $title = null ) { 00345 $url = $this->mURL; 00346 if ( $title !== null ) { 00347 $url = str_replace( "$1", wfUrlencode( $title ), $url ); 00348 } 00349 return $url; 00350 } 00351 00357 public function getAPI() { 00358 return $this->mAPI; 00359 } 00360 00366 public function getWikiID() { 00367 return $this->mWikiID; 00368 } 00369 00376 public function isLocal() { 00377 return $this->mLocal; 00378 } 00379 00386 public function isTranscludable() { 00387 return $this->mTrans; 00388 } 00389 00395 public function getName() { 00396 $msg = wfMessage( 'interwiki-name-' . $this->mPrefix )->inContentLanguage(); 00397 return !$msg->exists() ? '' : $msg; 00398 } 00399 00405 public function getDescription() { 00406 $msg = wfMessage( 'interwiki-desc-' . $this->mPrefix )->inContentLanguage(); 00407 return !$msg->exists() ? '' : $msg; 00408 } 00409 00415 public static function selectFields() { 00416 return array( 00417 'iw_prefix', 00418 'iw_url', 00419 'iw_api', 00420 'iw_wikiid', 00421 'iw_local', 00422 'iw_trans' 00423 ); 00424 } 00425 }