MediaWiki  REL1_19
Interwiki.php
Go to the documentation of this file.
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 }