--- /dev/null
+<?php\r
+/**\r
+ * @file\r
+ * Interwiki table entry\r
+ */\r
+\r
+/**\r
+ * The interwiki class\r
+ * All information is loaded on creation when called by Interwiki::fetch( $prefix ).\r
+ * All work is done on slave, because this should *never* change (except during schema updates etc, which arent wiki-related)\r
+ */\r
+class Interwiki {\r
+\r
+ // Cache - removed in LRU order when it hits limit\r
+ protected static $smCache = array();\r
+ const CACHE_LIMIT = 100; // 0 means unlimited, any other value is max number of entries.\r
+\r
+ protected $mPrefix, $mURL, $mLocal, $mTrans;\r
+\r
+ function __construct( $prefix = null, $url = '', $local = 0, $trans = 0 )\r
+ {\r
+ $this->mPrefix = $prefix;\r
+ $this->mURL = $url;\r
+ $this->mLocal = $local;\r
+ $this->mTrans = $trans;\r
+ }\r
+\r
+ /**\r
+ * Fetch an Interwiki object\r
+ * \r
+ * @return Interwiki Object, or null if not valid\r
+ * @param $prefix string Interwiki prefix to use\r
+ */\r
+ static public function fetch( $prefix ) {\r
+ if( isset( self::$smCache[$prefix] ) ){\r
+ return self::$smCache[$prefix];\r
+ }\r
+ global $wgInterwikiCache;\r
+ if ($wgInterwikiCache) {\r
+ return Interwiki::getInterwikiCached( $key );\r
+ }\r
+ $iw = new Interwiki;\r
+ $iw->load( $prefix );\r
+ if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ){\r
+ array_shift( self::$smCache );\r
+ }\r
+ self::$smCache[$prefix] = &$iw;\r
+ return $iw;\r
+ }\r
+ \r
+ /**\r
+ * Fetch interwiki prefix data from local cache in constant database.\r
+ *\r
+ * @note More logic is explained in DefaultSettings.\r
+ *\r
+ * @param $key \type{\string} Database key\r
+ * @return \type{\string} URL of interwiki site\r
+ */\r
+ protected static function getInterwikiCached( $key ) {\r
+ global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite;\r
+ static $db, $site;\r
+\r
+ if (!$db)\r
+ $db=dba_open($wgInterwikiCache,'r','cdb');\r
+ /* Resolve site name */\r
+ if ($wgInterwikiScopes>=3 and !$site) {\r
+ $site = dba_fetch('__sites:' . wfWikiID(), $db);\r
+ if ($site=="")\r
+ $site = $wgInterwikiFallbackSite;\r
+ }\r
+ $value = dba_fetch( wfMemcKey( $key ), $db);\r
+ if ($value=='' and $wgInterwikiScopes>=3) {\r
+ /* try site-level */\r
+ $value = dba_fetch("_{$site}:{$key}", $db);\r
+ }\r
+ if ($value=='' and $wgInterwikiScopes>=2) {\r
+ /* try globals */\r
+ $value = dba_fetch("__global:{$key}", $db);\r
+ }\r
+ if ($value=='undef')\r
+ $value='';\r
+ $s = new Interwiki( $key );\r
+ if ( $value != '' ) {\r
+ list( $local, $url ) = explode( ' ', $value, 2 );\r
+ $s->mURL = $url;\r
+ $s->mLocal = (int)$local;\r
+ }\r
+ if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ){\r
+ array_shift( self::$smCache );\r
+ }\r
+ self::$smCache[$prefix] = &$s;\r
+ return $s;\r
+ }\r
+\r
+ /**\r
+ * Clear all member variables in the current object. Does not clear\r
+ * the block from the DB.\r
+ */\r
+ function clear() {\r
+ $this->mURL = '';\r
+ $this->mLocal = $this->mTrans = 0;\r
+ $this->mPrefix = null;\r
+ }\r
+\r
+ /**\r
+ * Get the DB object\r
+ *\r
+ * @return Database\r
+ */\r
+ function &getDB(){\r
+ $db = wfGetDB( DB_SLAVE );\r
+ return $db;\r
+ }\r
+\r
+ /**\r
+ * Load interwiki from the DB\r
+ *\r
+ * @param $prefix The interwiki prefix\r
+ * @return bool The prefix is valid\r
+ *\r
+ */\r
+ function load( $prefix ) {\r
+ global $wgMemc;\r
+ $key = wfMemcKey( 'interwiki', $prefix );\r
+ $mc = $wgMemc->get( $key );\r
+ if( $mc ){\r
+ if( $this->loadFromArray( $mc ) ){\r
+ wfDebug("Succeeded\n");\r
+ return true;\r
+ }\r
+ }else{\r
+ $db =& $this->getDB();\r
+ \r
+ $res = $db->resultObject( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ),\r
+ __METHOD__ ) );\r
+ if ( $this->loadFromResult( $res ) ) {\r
+ $mc = array( 'url' => $this->mURL, 'local' => $this->mLocal, 'trans' => $this->mTrans );\r
+ $wgMemc->add( $key, $mc );\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ # Give up\r
+ $this->clear();\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Fill in member variables from an array (e.g. memcached result)\r
+ *\r
+ * @return bool Whether everything was there\r
+ * @param $res ResultWrapper Row from the interwiki table\r
+ */\r
+ function loadFromArray( $mc ) {\r
+ if( isset( $mc['url'] ) && isset( $mc['local'] ) && isset( $mc['trans'] ) ){\r
+ $this->mURL = $mc['url'];\r
+ $this->mLocal = $mc['local'];\r
+ $this->mTrans = $mc['trans'];\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ /**\r
+ * Fill in member variables from a result wrapper\r
+ *\r
+ * @return bool Whether there was a row there\r
+ * @param $res ResultWrapper Row from the interwiki table\r
+ */\r
+ function loadFromResult( ResultWrapper $res ) {\r
+ $ret = false;\r
+ if ( 0 != $res->numRows() ) {\r
+ # Get first entry\r
+ $row = $res->fetchObject();\r
+ $this->initFromRow( $row );\r
+ $ret = true;\r
+ }\r
+ $res->free();\r
+ return $ret;\r
+ }\r
+\r
+ /**\r
+ * Given a database row from the interwiki table, initialize\r
+ * member variables\r
+ *\r
+ * @param $row ResultWrapper A row from the interwiki table\r
+ */\r
+ function initFromRow( $row ) {\r
+ $this->mPrefix = $row->iw_prefix;\r
+ $this->mURL = $row->iw_url;\r
+ $this->mLocal = $row->iw_local;\r
+ $this->mTrans = $row->iw_trans;\r
+ }\r
+ \r
+ /** \r
+ * Get the URL for a particular title (or with $1 if no title given)\r
+ * \r
+ * @param $title string What text to put for the article name\r
+ * @return string The URL\r
+ */\r
+ function getURL( $title = null ){\r
+ $url = $this->mURL;\r
+ if( $title != null ){\r
+ $url = str_replace( "$1", $title, $url );\r
+ }\r
+ return $url;\r
+ }\r
+ \r
+ function isLocal(){\r
+ return $this->mLocal;\r
+ }\r
+ \r
+ function isTranscludable(){\r
+ return $this->mTrans;\r
+ }\r
+\r
+}\r
* @return \type{\string} the associated URL, containing "$1",
* which should be replaced by an article title
* @static (arguably)
+ * @deprecated See Interwiki class
*/
public function getInterwikiLink( $key ) {
- global $wgMemc, $wgInterwikiExpiry;
- global $wgInterwikiCache, $wgContLang;
- $fname = 'Title::getInterwikiLink';
-
- if ( count( Title::$interwikiCache ) >= self::CACHE_MAX ) {
- // Don't use infinite memory
- reset( Title::$interwikiCache );
- unset( Title::$interwikiCache[ key( Title::$interwikiCache ) ] );
- }
-
- $key = $wgContLang->lc( $key );
-
- $k = wfMemcKey( 'interwiki', $key );
- if( array_key_exists( $k, Title::$interwikiCache ) ) {
- return Title::$interwikiCache[$k]->iw_url;
- }
-
- if ($wgInterwikiCache) {
- return Title::getInterwikiCached( $key );
- }
-
- $s = $wgMemc->get( $k );
- # Ignore old keys with no iw_local
- if( $s && isset( $s->iw_local ) && isset($s->iw_trans)) {
- Title::$interwikiCache[$k] = $s;
- return $s->iw_url;
- }
-
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( 'interwiki',
- array( 'iw_url', 'iw_local', 'iw_trans' ),
- array( 'iw_prefix' => $key ), $fname );
- if( !$res ) {
- return '';
- }
-
- $s = $dbr->fetchObject( $res );
- if( !$s ) {
- # Cache non-existence: create a blank object and save it to memcached
- $s = (object)false;
- $s->iw_url = '';
- $s->iw_local = 0;
- $s->iw_trans = 0;
- }
- $wgMemc->set( $k, $s, $wgInterwikiExpiry );
- Title::$interwikiCache[$k] = $s;
-
- return $s->iw_url;
- }
-
- /**
- * Fetch interwiki prefix data from local cache in constant database.
- *
- * @note More logic is explained in DefaultSettings.
- *
- * @param $key \type{\string} Database key
- * @return \type{\string} URL of interwiki site
- */
- public static function getInterwikiCached( $key ) {
- global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite;
- static $db, $site;
-
- if (!$db)
- $db=dba_open($wgInterwikiCache,'r','cdb');
- /* Resolve site name */
- if ($wgInterwikiScopes>=3 and !$site) {
- $site = dba_fetch('__sites:' . wfWikiID(), $db);
- if ($site=="")
- $site = $wgInterwikiFallbackSite;
- }
- $value = dba_fetch( wfMemcKey( $key ), $db);
- if ($value=='' and $wgInterwikiScopes>=3) {
- /* try site-level */
- $value = dba_fetch("_{$site}:{$key}", $db);
- }
- if ($value=='' and $wgInterwikiScopes>=2) {
- /* try globals */
- $value = dba_fetch("__global:{$key}", $db);
- }
- if ($value=='undef')
- $value='';
- $s = (object)false;
- $s->iw_url = '';
- $s->iw_local = 0;
- $s->iw_trans = 0;
- if ($value!='') {
- list($local,$url)=explode(' ',$value,2);
- $s->iw_url=$url;
- $s->iw_local=(int)$local;
- }
- Title::$interwikiCache[wfMemcKey( 'interwiki', $key )] = $s;
- return $s->iw_url;
+ return Interwiki::fetch( $key )->getURL( );
}
/**
*/
public function isLocal() {
if ( $this->mInterwiki != '' ) {
- # Make sure key is loaded into cache
- $this->getInterwikiLink( $this->mInterwiki );
- $k = wfMemcKey( 'interwiki', $this->mInterwiki );
- return (bool)(Title::$interwikiCache[$k]->iw_local);
+ return Interwiki::fetch( $this->mInterwiki )->isLocal();
} else {
return true;
}
public function isTrans() {
if ($this->mInterwiki == '')
return false;
- # Make sure key is loaded into cache
- $this->getInterwikiLink( $this->mInterwiki );
- $k = wfMemcKey( 'interwiki', $this->mInterwiki );
- return (bool)(Title::$interwikiCache[$k]->iw_trans);
+
+ return Interwiki::fetch( $this->mInterwiki )->isTranscludable();
}
/**
$url = $wgServer . $url;
}
} else {
- $baseUrl = $this->getInterwikiLink( $this->mInterwiki );
+ $baseUrl = Interwiki::fetch( $this->mInterwiki )->getURL( );
$namespace = wfUrlencode( $this->getNsText() );
if ( '' != $namespace ) {
# Ordinary namespace
$dbkey = $m[2];
$this->mNamespace = $ns;
- } elseif( $this->getInterwikiLink( $p ) ) {
+ } elseif( new Interwiki( $p ) ) {
if( !$firstPass ) {
# Can't make a local interwiki link to an interwiki link.
# That's just crazy!