MediaWiki
REL1_24
|
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 00035 protected $mPrefix; 00036 00038 protected $mURL; 00039 00041 protected $mAPI; 00042 00046 protected $mWikiID; 00047 00049 protected $mLocal; 00050 00052 protected $mTrans; 00053 00054 public function __construct( $prefix = null, $url = '', $api = '', $wikiId = '', $local = 0, 00055 $trans = 0 00056 ) { 00057 $this->mPrefix = $prefix; 00058 $this->mURL = $url; 00059 $this->mAPI = $api; 00060 $this->mWikiID = $wikiId; 00061 $this->mLocal = $local; 00062 $this->mTrans = $trans; 00063 } 00064 00071 public static function isValidInterwiki( $prefix ) { 00072 $result = self::fetch( $prefix ); 00073 00074 return (bool)$result; 00075 } 00076 00083 public static function fetch( $prefix ) { 00084 global $wgContLang; 00085 00086 if ( $prefix == '' ) { 00087 return null; 00088 } 00089 00090 $prefix = $wgContLang->lc( $prefix ); 00091 if ( isset( self::$smCache[$prefix] ) ) { 00092 return self::$smCache[$prefix]; 00093 } 00094 00095 global $wgInterwikiCache; 00096 if ( $wgInterwikiCache ) { 00097 $iw = Interwiki::getInterwikiCached( $prefix ); 00098 } else { 00099 $iw = Interwiki::load( $prefix ); 00100 if ( !$iw ) { 00101 $iw = false; 00102 } 00103 } 00104 00105 if ( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ) { 00106 reset( self::$smCache ); 00107 unset( self::$smCache[key( self::$smCache )] ); 00108 } 00109 00110 self::$smCache[$prefix] = $iw; 00111 00112 return $iw; 00113 } 00114 00123 protected static function getInterwikiCached( $prefix ) { 00124 $value = self::getInterwikiCacheEntry( $prefix ); 00125 00126 $s = new Interwiki( $prefix ); 00127 if ( $value != '' ) { 00128 // Split values 00129 list( $local, $url ) = explode( ' ', $value, 2 ); 00130 $s->mURL = $url; 00131 $s->mLocal = (int)$local; 00132 } else { 00133 $s = false; 00134 } 00135 00136 return $s; 00137 } 00138 00147 protected static function getInterwikiCacheEntry( $prefix ) { 00148 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00149 static $db, $site; 00150 00151 wfDebug( __METHOD__ . "( $prefix )\n" ); 00152 $value = false; 00153 try { 00154 if ( !$db ) { 00155 $db = CdbReader::open( $wgInterwikiCache ); 00156 } 00157 /* Resolve site name */ 00158 if ( $wgInterwikiScopes >= 3 && !$site ) { 00159 $site = $db->get( '__sites:' . wfWikiID() ); 00160 if ( $site == '' ) { 00161 $site = $wgInterwikiFallbackSite; 00162 } 00163 } 00164 00165 $value = $db->get( wfMemcKey( $prefix ) ); 00166 // Site level 00167 if ( $value == '' && $wgInterwikiScopes >= 3 ) { 00168 $value = $db->get( "_{$site}:{$prefix}" ); 00169 } 00170 // Global Level 00171 if ( $value == '' && $wgInterwikiScopes >= 2 ) { 00172 $value = $db->get( "__global:{$prefix}" ); 00173 } 00174 if ( $value == 'undef' ) { 00175 $value = ''; 00176 } 00177 } catch ( CdbException $e ) { 00178 wfDebug( __METHOD__ . ": CdbException caught, error message was " 00179 . $e->getMessage() ); 00180 } 00181 00182 return $value; 00183 } 00184 00191 protected static function load( $prefix ) { 00192 global $wgMemc, $wgInterwikiExpiry; 00193 00194 $iwData = array(); 00195 if ( !wfRunHooks( 'InterwikiLoadPrefix', array( $prefix, &$iwData ) ) ) { 00196 return Interwiki::loadFromArray( $iwData ); 00197 } 00198 00199 if ( !$iwData ) { 00200 $key = wfMemcKey( 'interwiki', $prefix ); 00201 $iwData = $wgMemc->get( $key ); 00202 if ( $iwData === '!NONEXISTENT' ) { 00203 // negative cache hit 00204 return false; 00205 } 00206 } 00207 00208 // is_array is hack for old keys 00209 if ( $iwData && is_array( $iwData ) ) { 00210 $iw = Interwiki::loadFromArray( $iwData ); 00211 if ( $iw ) { 00212 return $iw; 00213 } 00214 } 00215 00216 $db = wfGetDB( DB_SLAVE ); 00217 00218 $row = $db->fetchRow( $db->select( 00219 'interwiki', 00220 self::selectFields(), 00221 array( 'iw_prefix' => $prefix ), 00222 __METHOD__ 00223 ) ); 00224 00225 $iw = Interwiki::loadFromArray( $row ); 00226 if ( $iw ) { 00227 $mc = array( 00228 'iw_url' => $iw->mURL, 00229 'iw_api' => $iw->mAPI, 00230 'iw_local' => $iw->mLocal, 00231 'iw_trans' => $iw->mTrans 00232 ); 00233 $wgMemc->add( $key, $mc, $wgInterwikiExpiry ); 00234 00235 return $iw; 00236 } 00237 00238 // negative cache hit 00239 $wgMemc->add( $key, '!NONEXISTENT', $wgInterwikiExpiry ); 00240 00241 return false; 00242 } 00243 00250 protected static function loadFromArray( $mc ) { 00251 if ( isset( $mc['iw_url'] ) ) { 00252 $iw = new Interwiki(); 00253 $iw->mURL = $mc['iw_url']; 00254 $iw->mLocal = isset( $mc['iw_local'] ) ? $mc['iw_local'] : 0; 00255 $iw->mTrans = isset( $mc['iw_trans'] ) ? $mc['iw_trans'] : 0; 00256 $iw->mAPI = isset( $mc['iw_api'] ) ? $mc['iw_api'] : ''; 00257 $iw->mWikiID = isset( $mc['iw_wikiid'] ) ? $mc['iw_wikiid'] : ''; 00258 00259 return $iw; 00260 } 00261 00262 return false; 00263 } 00264 00272 protected static function getAllPrefixesCached( $local ) { 00273 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00274 static $db, $site; 00275 00276 wfDebug( __METHOD__ . "()\n" ); 00277 $data = array(); 00278 try { 00279 if ( !$db ) { 00280 $db = CdbReader::open( $wgInterwikiCache ); 00281 } 00282 /* Resolve site name */ 00283 if ( $wgInterwikiScopes >= 3 && !$site ) { 00284 $site = $db->get( '__sites:' . wfWikiID() ); 00285 if ( $site == '' ) { 00286 $site = $wgInterwikiFallbackSite; 00287 } 00288 } 00289 00290 // List of interwiki sources 00291 $sources = array(); 00292 // Global Level 00293 if ( $wgInterwikiScopes >= 2 ) { 00294 $sources[] = '__global'; 00295 } 00296 // Site level 00297 if ( $wgInterwikiScopes >= 3 ) { 00298 $sources[] = '_' . $site; 00299 } 00300 $sources[] = wfWikiID(); 00301 00302 foreach ( $sources as $source ) { 00303 $list = $db->get( "__list:{$source}" ); 00304 foreach ( explode( ' ', $list ) as $iw_prefix ) { 00305 $row = $db->get( "{$source}:{$iw_prefix}" ); 00306 if ( !$row ) { 00307 continue; 00308 } 00309 00310 list( $iw_local, $iw_url ) = explode( ' ', $row ); 00311 00312 if ( $local !== null && $local != $iw_local ) { 00313 continue; 00314 } 00315 00316 $data[$iw_prefix] = array( 00317 'iw_prefix' => $iw_prefix, 00318 'iw_url' => $iw_url, 00319 'iw_local' => $iw_local, 00320 ); 00321 } 00322 } 00323 } catch ( CdbException $e ) { 00324 wfDebug( __METHOD__ . ": CdbException caught, error message was " 00325 . $e->getMessage() ); 00326 } 00327 00328 ksort( $data ); 00329 00330 return array_values( $data ); 00331 } 00332 00340 protected static function getAllPrefixesDB( $local ) { 00341 $db = wfGetDB( DB_SLAVE ); 00342 00343 $where = array(); 00344 00345 if ( $local !== null ) { 00346 if ( $local == 1 ) { 00347 $where['iw_local'] = 1; 00348 } elseif ( $local == 0 ) { 00349 $where['iw_local'] = 0; 00350 } 00351 } 00352 00353 $res = $db->select( 'interwiki', 00354 self::selectFields(), 00355 $where, __METHOD__, array( 'ORDER BY' => 'iw_prefix' ) 00356 ); 00357 00358 $retval = array(); 00359 foreach ( $res as $row ) { 00360 $retval[] = (array)$row; 00361 } 00362 00363 return $retval; 00364 } 00365 00373 public static function getAllPrefixes( $local = null ) { 00374 global $wgInterwikiCache; 00375 00376 if ( $wgInterwikiCache ) { 00377 return self::getAllPrefixesCached( $local ); 00378 } 00379 00380 return self::getAllPrefixesDB( $local ); 00381 } 00382 00392 public function getURL( $title = null ) { 00393 $url = $this->mURL; 00394 if ( $title !== null ) { 00395 $url = str_replace( "$1", wfUrlencode( $title ), $url ); 00396 } 00397 00398 return $url; 00399 } 00400 00406 public function getAPI() { 00407 return $this->mAPI; 00408 } 00409 00415 public function getWikiID() { 00416 return $this->mWikiID; 00417 } 00418 00425 public function isLocal() { 00426 return $this->mLocal; 00427 } 00428 00435 public function isTranscludable() { 00436 return $this->mTrans; 00437 } 00438 00444 public function getName() { 00445 $msg = wfMessage( 'interwiki-name-' . $this->mPrefix )->inContentLanguage(); 00446 00447 return !$msg->exists() ? '' : $msg; 00448 } 00449 00455 public function getDescription() { 00456 $msg = wfMessage( 'interwiki-desc-' . $this->mPrefix )->inContentLanguage(); 00457 00458 return !$msg->exists() ? '' : $msg; 00459 } 00460 00466 public static function selectFields() { 00467 return array( 00468 'iw_prefix', 00469 'iw_url', 00470 'iw_api', 00471 'iw_wikiid', 00472 'iw_local', 00473 'iw_trans' 00474 ); 00475 } 00476 }