754fb3b17552a85567af5d32ef22c1bce7cefba6
[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 if(! $iw->load( $prefix ) ){
44 return false;
45 }
46 if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ){
47 array_shift( self::$smCache );
48 }
49 self::$smCache[$prefix] = &$iw;
50 return $iw;
51 }
52
53 /**
54 * Fetch interwiki prefix data from local cache in constant database.
55 *
56 * @note More logic is explained in DefaultSettings.
57 *
58 * @param $key \type{\string} Database key
59 * @return \type{\string} URL of interwiki site
60 */
61 protected static function getInterwikiCached( $key ) {
62 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite;
63 static $db, $site;
64
65 if (!$db)
66 $db=dba_open($wgInterwikiCache,'r','cdb');
67 /* Resolve site name */
68 if ($wgInterwikiScopes>=3 and !$site) {
69 $site = dba_fetch('__sites:' . wfWikiID(), $db);
70 if ($site=="")
71 $site = $wgInterwikiFallbackSite;
72 }
73 $value = dba_fetch( wfMemcKey( $key ), $db);
74 if ($value=='' and $wgInterwikiScopes>=3) {
75 /* try site-level */
76 $value = dba_fetch("_{$site}:{$key}", $db);
77 }
78 if ($value=='' and $wgInterwikiScopes>=2) {
79 /* try globals */
80 $value = dba_fetch("__global:{$key}", $db);
81 }
82 if ($value=='undef')
83 $value='';
84 $s = new Interwiki( $key );
85 if ( $value != '' ) {
86 list( $local, $url ) = explode( ' ', $value, 2 );
87 $s->mURL = $url;
88 $s->mLocal = (int)$local;
89 }else{
90 return false;
91 }
92 if( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ){
93 array_shift( self::$smCache );
94 }
95 self::$smCache[$prefix] = &$s;
96 return $s;
97 }
98
99 /**
100 * Get the DB object
101 *
102 * @return Database
103 */
104 function &getDB(){
105 $db = wfGetDB( DB_SLAVE );
106 return $db;
107 }
108
109 /**
110 * Load interwiki from the DB
111 *
112 * @param $prefix The interwiki prefix
113 * @return bool The prefix is valid
114 *
115 */
116 function load( $prefix ) {
117 global $wgMemc;
118 $key = wfMemcKey( 'interwiki', $prefix );
119 $mc = $wgMemc->get( $key );
120 if( $mc && is_array( $mc ) && $this->loadFromArray( $mc ) ){ // is_array is hack for old keys
121 wfDebug("Succeeded\n");
122 return true;
123 }
124
125 $db =& $this->getDB();
126 $res = $db->resultObject( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ),
127 __METHOD__ ) );
128 if ( $this->loadFromResult( $res ) ) {
129 $mc = array( 'url' => $this->mURL, 'local' => $this->mLocal, 'trans' => $this->mTrans );
130 $wgMemc->add( $key, $mc );
131 return true;
132 }
133 return false;
134 }
135
136 /**
137 * Fill in member variables from an array (e.g. memcached result)
138 *
139 * @return bool Whether everything was there
140 * @param $res ResultWrapper Row from the interwiki table
141 */
142 function loadFromArray( $mc ) {
143 if( isset( $mc['url'] ) && isset( $mc['local'] ) && isset( $mc['trans'] ) ){
144 $this->mURL = $mc['url'];
145 $this->mLocal = $mc['local'];
146 $this->mTrans = $mc['trans'];
147 return true;
148 }
149 return false;
150 }
151
152 /**
153 * Fill in member variables from a result wrapper
154 *
155 * @return bool Whether there was a row there
156 * @param $res ResultWrapper Row from the interwiki table
157 */
158 function loadFromResult( ResultWrapper $res ) {
159 $ret = false;
160 if ( 0 != $res->numRows() ) {
161 # Get first entry
162 $row = $res->fetchObject();
163 $this->initFromRow( $row );
164 $ret = true;
165 }
166 $res->free();
167 return $ret;
168 }
169
170 /**
171 * Given a database row from the interwiki table, initialize
172 * member variables
173 *
174 * @param $row ResultWrapper A row from the interwiki table
175 */
176 function initFromRow( $row ) {
177 $this->mPrefix = $row->iw_prefix;
178 $this->mURL = $row->iw_url;
179 $this->mLocal = $row->iw_local;
180 $this->mTrans = $row->iw_trans;
181 }
182
183 /**
184 * Get the URL for a particular title (or with $1 if no title given)
185 *
186 * @param $title string What text to put for the article name
187 * @return string The URL
188 */
189 function getURL( $title = null ){
190 $url = $this->mURL;
191 if( $title != null ){
192 $url = str_replace( "$1", $title, $url );
193 }
194 return $url;
195 }
196
197 function isLocal(){
198 return $this->mLocal;
199 }
200
201 function isTranscludable(){
202 return $this->mTrans;
203 }
204
205 }