MediaWiki
REL1_20
|
00001 <?php 00029 class Interwiki { 00030 00031 // Cache - removes oldest entry when it hits limit 00032 protected static $smCache = array(); 00033 const CACHE_LIMIT = 100; // 0 means unlimited, any other value is max number of entries. 00034 00035 protected $mPrefix, $mURL, $mAPI, $mWikiID, $mLocal, $mTrans; 00036 00037 public function __construct( $prefix = null, $url = '', $api = '', $wikiId = '', $local = 0, $trans = 0 ) { 00038 $this->mPrefix = $prefix; 00039 $this->mURL = $url; 00040 $this->mAPI = $api; 00041 $this->mWikiID = $wikiId; 00042 $this->mLocal = $local; 00043 $this->mTrans = $trans; 00044 } 00045 00052 static public function isValidInterwiki( $prefix ) { 00053 $result = self::fetch( $prefix ); 00054 return (bool)$result; 00055 } 00056 00063 static public function fetch( $prefix ) { 00064 global $wgContLang; 00065 if( $prefix == '' ) { 00066 return null; 00067 } 00068 $prefix = $wgContLang->lc( $prefix ); 00069 if( isset( self::$smCache[$prefix] ) ) { 00070 return self::$smCache[$prefix]; 00071 } 00072 global $wgInterwikiCache; 00073 if( $wgInterwikiCache ) { 00074 $iw = Interwiki::getInterwikiCached( $prefix ); 00075 } else { 00076 $iw = Interwiki::load( $prefix ); 00077 if( !$iw ) { 00078 $iw = false; 00079 } 00080 } 00081 if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ) { 00082 reset( self::$smCache ); 00083 unset( self::$smCache[key( self::$smCache )] ); 00084 } 00085 self::$smCache[$prefix] = $iw; 00086 return $iw; 00087 } 00088 00097 protected static function getInterwikiCached( $prefix ) { 00098 $value = self::getInterwikiCacheEntry( $prefix ); 00099 00100 $s = new Interwiki( $prefix ); 00101 if ( $value != '' ) { 00102 // Split values 00103 list( $local, $url ) = explode( ' ', $value, 2 ); 00104 $s->mURL = $url; 00105 $s->mLocal = (int)$local; 00106 } else { 00107 $s = false; 00108 } 00109 return $s; 00110 } 00111 00120 protected static function getInterwikiCacheEntry( $prefix ) { 00121 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00122 static $db, $site; 00123 00124 wfDebug( __METHOD__ . "( $prefix )\n" ); 00125 if( !$db ) { 00126 $db = CdbReader::open( $wgInterwikiCache ); 00127 } 00128 /* Resolve site name */ 00129 if( $wgInterwikiScopes >= 3 && !$site ) { 00130 $site = $db->get( '__sites:' . wfWikiID() ); 00131 if ( $site == '' ) { 00132 $site = $wgInterwikiFallbackSite; 00133 } 00134 } 00135 00136 $value = $db->get( wfMemcKey( $prefix ) ); 00137 // Site level 00138 if ( $value == '' && $wgInterwikiScopes >= 3 ) { 00139 $value = $db->get( "_{$site}:{$prefix}" ); 00140 } 00141 // Global Level 00142 if ( $value == '' && $wgInterwikiScopes >= 2 ) { 00143 $value = $db->get( "__global:{$prefix}" ); 00144 } 00145 if ( $value == 'undef' ) { 00146 $value = ''; 00147 } 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 }