MediaWiki
REL1_19
|
00001 <?php 00013 class Interwiki { 00014 00015 // Cache - removes oldest entry when it hits limit 00016 protected static $smCache = array(); 00017 const CACHE_LIMIT = 100; // 0 means unlimited, any other value is max number of entries. 00018 00019 protected $mPrefix, $mURL, $mAPI, $mWikiID, $mLocal, $mTrans; 00020 00021 public function __construct( $prefix = null, $url = '', $api = '', $wikiId = '', $local = 0, $trans = 0 ) { 00022 $this->mPrefix = $prefix; 00023 $this->mURL = $url; 00024 $this->mAPI = $api; 00025 $this->mWikiID = $wikiId; 00026 $this->mLocal = $local; 00027 $this->mTrans = $trans; 00028 } 00029 00036 static public function isValidInterwiki( $prefix ) { 00037 $result = self::fetch( $prefix ); 00038 return (bool)$result; 00039 } 00040 00047 static public function fetch( $prefix ) { 00048 global $wgContLang; 00049 if( $prefix == '' ) { 00050 return null; 00051 } 00052 $prefix = $wgContLang->lc( $prefix ); 00053 if( isset( self::$smCache[$prefix] ) ) { 00054 return self::$smCache[$prefix]; 00055 } 00056 global $wgInterwikiCache; 00057 if( $wgInterwikiCache ) { 00058 $iw = Interwiki::getInterwikiCached( $prefix ); 00059 } else { 00060 $iw = Interwiki::load( $prefix ); 00061 if( !$iw ) { 00062 $iw = false; 00063 } 00064 } 00065 if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ) { 00066 reset( self::$smCache ); 00067 unset( self::$smCache[key( self::$smCache )] ); 00068 } 00069 self::$smCache[$prefix] = $iw; 00070 return $iw; 00071 } 00072 00081 protected static function getInterwikiCached( $prefix ) { 00082 $value = self::getInterwikiCacheEntry( $prefix ); 00083 00084 $s = new Interwiki( $prefix ); 00085 if ( $value != '' ) { 00086 // Split values 00087 list( $local, $url ) = explode( ' ', $value, 2 ); 00088 $s->mURL = $url; 00089 $s->mLocal = (int)$local; 00090 } else { 00091 $s = false; 00092 } 00093 return $s; 00094 } 00095 00104 protected static function getInterwikiCacheEntry( $prefix ) { 00105 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00106 static $db, $site; 00107 00108 wfDebug( __METHOD__ . "( $prefix )\n" ); 00109 if( !$db ) { 00110 $db = CdbReader::open( $wgInterwikiCache ); 00111 } 00112 /* Resolve site name */ 00113 if( $wgInterwikiScopes >= 3 && !$site ) { 00114 $site = $db->get( '__sites:' . wfWikiID() ); 00115 if ( $site == '' ) { 00116 $site = $wgInterwikiFallbackSite; 00117 } 00118 } 00119 00120 $value = $db->get( wfMemcKey( $prefix ) ); 00121 // Site level 00122 if ( $value == '' && $wgInterwikiScopes >= 3 ) { 00123 $value = $db->get( "_{$site}:{$prefix}" ); 00124 } 00125 // Global Level 00126 if ( $value == '' && $wgInterwikiScopes >= 2 ) { 00127 $value = $db->get( "__global:{$prefix}" ); 00128 } 00129 if ( $value == 'undef' ) { 00130 $value = ''; 00131 } 00132 00133 return $value; 00134 } 00135 00142 protected static function load( $prefix ) { 00143 global $wgMemc, $wgInterwikiExpiry; 00144 00145 $iwData = false; 00146 if ( !wfRunHooks( 'InterwikiLoadPrefix', array( $prefix, &$iwData ) ) ) { 00147 return Interwiki::loadFromArray( $iwData ); 00148 } 00149 00150 if ( !$iwData ) { 00151 $key = wfMemcKey( 'interwiki', $prefix ); 00152 $iwData = $wgMemc->get( $key ); 00153 if ( $iwData === '!NONEXISTENT' ) { 00154 return false; // negative cache hit 00155 } 00156 } 00157 00158 if( $iwData && is_array( $iwData ) ) { // is_array is hack for old keys 00159 $iw = Interwiki::loadFromArray( $iwData ); 00160 if( $iw ) { 00161 return $iw; 00162 } 00163 } 00164 00165 $db = wfGetDB( DB_SLAVE ); 00166 00167 $row = $db->fetchRow( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ), 00168 __METHOD__ ) ); 00169 $iw = Interwiki::loadFromArray( $row ); 00170 if ( $iw ) { 00171 $mc = array( 00172 'iw_url' => $iw->mURL, 00173 'iw_api' => $iw->mAPI, 00174 'iw_local' => $iw->mLocal, 00175 'iw_trans' => $iw->mTrans 00176 ); 00177 $wgMemc->add( $key, $mc, $wgInterwikiExpiry ); 00178 return $iw; 00179 } else { 00180 $wgMemc->add( $key, '!NONEXISTENT', $wgInterwikiExpiry ); // negative cache hit 00181 } 00182 00183 return false; 00184 } 00185 00192 protected static function loadFromArray( $mc ) { 00193 if( isset( $mc['iw_url'] ) ) { 00194 $iw = new Interwiki(); 00195 $iw->mURL = $mc['iw_url']; 00196 $iw->mLocal = isset( $mc['iw_local'] ) ? $mc['iw_local'] : 0; 00197 $iw->mTrans = isset( $mc['iw_trans'] ) ? $mc['iw_trans'] : 0; 00198 $iw->mAPI = isset( $mc['iw_api'] ) ? $mc['iw_api'] : ''; 00199 $iw->mWikiID = isset( $mc['iw_wikiid'] ) ? $mc['iw_wikiid'] : ''; 00200 00201 return $iw; 00202 } 00203 return false; 00204 } 00205 00213 protected static function getAllPrefixesCached( $local ) { 00214 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 00215 static $db, $site; 00216 00217 wfDebug( __METHOD__ . "()\n" ); 00218 if( !$db ) { 00219 $db = CdbReader::open( $wgInterwikiCache ); 00220 } 00221 /* Resolve site name */ 00222 if( $wgInterwikiScopes >= 3 && !$site ) { 00223 $site = $db->get( '__sites:' . wfWikiID() ); 00224 if ( $site == '' ) { 00225 $site = $wgInterwikiFallbackSite; 00226 } 00227 } 00228 00229 // List of interwiki sources 00230 $sources = array(); 00231 // Global Level 00232 if ( $wgInterwikiScopes >= 2 ) { 00233 $sources[] = '__global'; 00234 } 00235 // Site level 00236 if ( $wgInterwikiScopes >= 3 ) { 00237 $sources[] = '_' . $site; 00238 } 00239 $sources[] = wfWikiID(); 00240 00241 $data = array(); 00242 00243 foreach( $sources as $source ) { 00244 $list = $db->get( "__list:{$source}" ); 00245 foreach ( explode( ' ', $list ) as $iw_prefix ) { 00246 $row = $db->get( "{$source}:{$iw_prefix}" ); 00247 if( !$row ) { 00248 continue; 00249 } 00250 00251 list( $iw_local, $iw_url ) = explode( ' ', $row ); 00252 00253 if ( $local !== null && $local != $iw_local ) { 00254 continue; 00255 } 00256 00257 $data[$iw_prefix] = array( 00258 'iw_prefix' => $iw_prefix, 00259 'iw_url' => $iw_url, 00260 'iw_local' => $iw_local, 00261 ); 00262 } 00263 } 00264 00265 ksort( $data ); 00266 00267 return array_values( $data ); 00268 } 00269 00277 protected static function getAllPrefixesDB( $local ) { 00278 $db = wfGetDB( DB_SLAVE ); 00279 00280 $where = array(); 00281 00282 if ( $local !== null ) { 00283 if ( $local == 1 ) { 00284 $where['iw_local'] = 1; 00285 } elseif ( $local == 0 ) { 00286 $where['iw_local'] = 0; 00287 } 00288 } 00289 00290 $res = $db->select( 'interwiki', 00291 array( 'iw_prefix', 'iw_url', 'iw_api', 'iw_wikiid', 'iw_local', 'iw_trans' ), 00292 $where, __METHOD__, array( 'ORDER BY' => 'iw_prefix' ) 00293 ); 00294 $retval = array(); 00295 foreach ( $res as $row ) { 00296 $retval[] = (array)$row; 00297 } 00298 return $retval; 00299 } 00300 00308 public static function getAllPrefixes( $local = null ) { 00309 global $wgInterwikiCache; 00310 00311 if ( $wgInterwikiCache ) { 00312 return self::getAllPrefixesCached( $local ); 00313 } else { 00314 return self::getAllPrefixesDB( $local ); 00315 } 00316 } 00317 00327 public function getURL( $title = null ) { 00328 $url = $this->mURL; 00329 if( $title !== null ) { 00330 $url = str_replace( "$1", wfUrlencode( $title ), $url ); 00331 } 00332 return $url; 00333 } 00334 00340 public function getAPI() { 00341 return $this->mAPI; 00342 } 00343 00349 public function getWikiID() { 00350 return $this->mWikiID; 00351 } 00352 00359 public function isLocal() { 00360 return $this->mLocal; 00361 } 00362 00369 public function isTranscludable() { 00370 return $this->mTrans; 00371 } 00372 00378 public function getName() { 00379 $msg = wfMessage( 'interwiki-name-' . $this->mPrefix )->inContentLanguage(); 00380 return !$msg->exists() ? '' : $msg; 00381 } 00382 00388 public function getDescription() { 00389 $msg = wfMessage( 'interwiki-desc-' . $this->mPrefix )->inContentLanguage(); 00390 return !$msg->exists() ? '' : $msg; 00391 } 00392 }