MediaWiki  REL1_24
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 
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 }