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