New format for accessing Interwiki data. Replaced all old ways within core I could...
[lhc/web/wiklou.git] / includes / Interwiki.php
1 <?php
2 /**
3 * @file
4 * Interwiki table entry
5 */
6
7 /**
8 * The interwiki class
9 * All information is loaded on creation when called by Interwiki::fetch( $prefix ).
10 * All work is done on slave, because this should *never* change (except during schema updates etc, which arent wiki-related)
11 */
12 class Interwiki {
13
14 // Cache - removed in LRU order when it hits limit
15 protected static $smCache = array();
16 const CACHE_LIMIT = 100; // 0 means unlimited, any other value is max number of entries.
17
18 protected $mPrefix, $mURL, $mLocal, $mTrans;
19
20 function __construct( $prefix = null, $url = '', $local = 0, $trans = 0 )
21 {
22 $this->mPrefix = $prefix;
23 $this->mURL = $url;
24 $this->mLocal = $local;
25 $this->mTrans = $trans;
26 }
27
28 /**
29 * Fetch an Interwiki object
30 *
31 * @return Interwiki Object, or null if not valid
32 * @param $prefix string Interwiki prefix to use
33 */
34 static public function fetch( $prefix ) {
35 if( isset( self::$smCache[$prefix] ) ){
36 return self::$smCache[$prefix];
37 }
38 global $wgInterwikiCache;
39 if ($wgInterwikiCache) {
40 return Interwiki::getInterwikiCached( $key );
41 }
42 $iw = new Interwiki;
43 $iw->load( $prefix );
44 if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ){
45 array_shift( self::$smCache );
46 }
47 self::$smCache[$prefix] = &$iw;
48 return $iw;
49 }
50
51 /**
52 * Fetch interwiki prefix data from local cache in constant database.
53 *
54 * @note More logic is explained in DefaultSettings.
55 *
56 * @param $key \type{\string} Database key
57 * @return \type{\string} URL of interwiki site
58 */
59 protected static function getInterwikiCached( $key ) {
60 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite;
61 static $db, $site;
62
63 if (!$db)
64 $db=dba_open($wgInterwikiCache,'r','cdb');
65 /* Resolve site name */
66 if ($wgInterwikiScopes>=3 and !$site) {
67 $site = dba_fetch('__sites:' . wfWikiID(), $db);
68 if ($site=="")
69 $site = $wgInterwikiFallbackSite;
70 }
71 $value = dba_fetch( wfMemcKey( $key ), $db);
72 if ($value=='' and $wgInterwikiScopes>=3) {
73 /* try site-level */
74 $value = dba_fetch("_{$site}:{$key}", $db);
75 }
76 if ($value=='' and $wgInterwikiScopes>=2) {
77 /* try globals */
78 $value = dba_fetch("__global:{$key}", $db);
79 }
80 if ($value=='undef')
81 $value='';
82 $s = new Interwiki( $key );
83 if ( $value != '' ) {
84 list( $local, $url ) = explode( ' ', $value, 2 );
85 $s->mURL = $url;
86 $s->mLocal = (int)$local;
87 }
88 if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ){
89 array_shift( self::$smCache );
90 }
91 self::$smCache[$prefix] = &$s;
92 return $s;
93 }
94
95 /**
96 * Clear all member variables in the current object. Does not clear
97 * the block from the DB.
98 */
99 function clear() {
100 $this->mURL = '';
101 $this->mLocal = $this->mTrans = 0;
102 $this->mPrefix = null;
103 }
104
105 /**
106 * Get the DB object
107 *
108 * @return Database
109 */
110 function &getDB(){
111 $db = wfGetDB( DB_SLAVE );
112 return $db;
113 }
114
115 /**
116 * Load interwiki from the DB
117 *
118 * @param $prefix The interwiki prefix
119 * @return bool The prefix is valid
120 *
121 */
122 function load( $prefix ) {
123 global $wgMemc;
124 $key = wfMemcKey( 'interwiki', $prefix );
125 $mc = $wgMemc->get( $key );
126 if( $mc ){
127 if( $this->loadFromArray( $mc ) ){
128 wfDebug("Succeeded\n");
129 return true;
130 }
131 }else{
132 $db =& $this->getDB();
133
134 $res = $db->resultObject( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ),
135 __METHOD__ ) );
136 if ( $this->loadFromResult( $res ) ) {
137 $mc = array( 'url' => $this->mURL, 'local' => $this->mLocal, 'trans' => $this->mTrans );
138 $wgMemc->add( $key, $mc );
139 return true;
140 }
141 }
142
143 # Give up
144 $this->clear();
145 return false;
146 }
147
148 /**
149 * Fill in member variables from an array (e.g. memcached result)
150 *
151 * @return bool Whether everything was there
152 * @param $res ResultWrapper Row from the interwiki table
153 */
154 function loadFromArray( $mc ) {
155 if( isset( $mc['url'] ) && isset( $mc['local'] ) && isset( $mc['trans'] ) ){
156 $this->mURL = $mc['url'];
157 $this->mLocal = $mc['local'];
158 $this->mTrans = $mc['trans'];
159 return true;
160 }
161 return false;
162 }
163
164 /**
165 * Fill in member variables from a result wrapper
166 *
167 * @return bool Whether there was a row there
168 * @param $res ResultWrapper Row from the interwiki table
169 */
170 function loadFromResult( ResultWrapper $res ) {
171 $ret = false;
172 if ( 0 != $res->numRows() ) {
173 # Get first entry
174 $row = $res->fetchObject();
175 $this->initFromRow( $row );
176 $ret = true;
177 }
178 $res->free();
179 return $ret;
180 }
181
182 /**
183 * Given a database row from the interwiki table, initialize
184 * member variables
185 *
186 * @param $row ResultWrapper A row from the interwiki table
187 */
188 function initFromRow( $row ) {
189 $this->mPrefix = $row->iw_prefix;
190 $this->mURL = $row->iw_url;
191 $this->mLocal = $row->iw_local;
192 $this->mTrans = $row->iw_trans;
193 }
194
195 /**
196 * Get the URL for a particular title (or with $1 if no title given)
197 *
198 * @param $title string What text to put for the article name
199 * @return string The URL
200 */
201 function getURL( $title = null ){
202 $url = $this->mURL;
203 if( $title != null ){
204 $url = str_replace( "$1", $title, $url );
205 }
206 return $url;
207 }
208
209 function isLocal(){
210 return $this->mLocal;
211 }
212
213 function isTranscludable(){
214 return $this->mTrans;
215 }
216
217 }