MediaWiki REL1_30
ClassicInterwikiLookup.php
Go to the documentation of this file.
1<?php
3
24use \Cdb\Exception as CdbException;
25use \Cdb\Reader as CdbReader;
27use Hooks;
28use Interwiki;
29use Language;
30use MapCacheLRU;
32
46
50 private $localCache;
51
56
60 private $objectCache;
61
66
70 private $cdbData;
71
76
81
85 private $cdbReader = null;
86
90 private $thisSite = null;
91
105 function __construct(
109 $cdbData,
112 ) {
113 $this->localCache = new MapCacheLRU( 100 );
114
115 $this->contentLanguage = $contentLanguage;
116 $this->objectCache = $objectCache;
117 $this->objectCacheExpiry = $objectCacheExpiry;
118 $this->cdbData = $cdbData;
119 $this->interwikiScopes = $interwikiScopes;
120 $this->fallbackSite = $fallbackSite;
121 }
122
129 public function isValidInterwiki( $prefix ) {
130 $result = $this->fetch( $prefix );
131
132 return (bool)$result;
133 }
134
141 public function fetch( $prefix ) {
142 if ( $prefix == '' ) {
143 return null;
144 }
145
146 $prefix = $this->contentLanguage->lc( $prefix );
147 if ( $this->localCache->has( $prefix ) ) {
148 return $this->localCache->get( $prefix );
149 }
150
151 if ( $this->cdbData ) {
152 $iw = $this->getInterwikiCached( $prefix );
153 } else {
154 $iw = $this->load( $prefix );
155 if ( !$iw ) {
156 $iw = false;
157 }
158 }
159 $this->localCache->set( $prefix, $iw );
160
161 return $iw;
162 }
163
169 public function resetLocalCache() {
170 $this->localCache->clear();
171 }
172
177 public function invalidateCache( $prefix ) {
178 $this->localCache->clear( $prefix );
179
180 $key = $this->objectCache->makeKey( 'interwiki', $prefix );
181 $this->objectCache->delete( $key );
182 }
183
192 private function getInterwikiCached( $prefix ) {
193 $value = $this->getInterwikiCacheEntry( $prefix );
194
195 if ( $value ) {
196 // Split values
197 list( $local, $url ) = explode( ' ', $value, 2 );
198 return new Interwiki( $prefix, $url, '', '', (int)$local );
199 } else {
200 return false;
201 }
202 }
203
212 private function getInterwikiCacheEntry( $prefix ) {
213 wfDebug( __METHOD__ . "( $prefix )\n" );
214 $value = false;
215 try {
216 // Resolve site name
217 if ( $this->interwikiScopes >= 3 && !$this->thisSite ) {
218 $this->thisSite = $this->getCacheValue( '__sites:' . wfWikiID() );
219 if ( $this->thisSite == '' ) {
220 $this->thisSite = $this->fallbackSite;
221 }
222 }
223
224 $value = $this->getCacheValue( wfWikiID() . ':' . $prefix );
225 // Site level
226 if ( $value == '' && $this->interwikiScopes >= 3 ) {
227 $value = $this->getCacheValue( "_{$this->thisSite}:{$prefix}" );
228 }
229 // Global Level
230 if ( $value == '' && $this->interwikiScopes >= 2 ) {
231 $value = $this->getCacheValue( "__global:{$prefix}" );
232 }
233 if ( $value == 'undef' ) {
234 $value = '';
235 }
236 } catch ( CdbException $e ) {
237 wfDebug( __METHOD__ . ": CdbException caught, error message was "
238 . $e->getMessage() );
239 }
240
241 return $value;
242 }
243
244 private function getCacheValue( $key ) {
245 if ( $this->cdbReader === null ) {
246 if ( is_string( $this->cdbData ) ) {
247 $this->cdbReader = \Cdb\Reader::open( $this->cdbData );
248 } elseif ( is_array( $this->cdbData ) ) {
249 $this->cdbReader = new \Cdb\Reader\Hash( $this->cdbData );
250 } else {
251 $this->cdbReader = false;
252 }
253 }
254
255 if ( $this->cdbReader ) {
256 return $this->cdbReader->get( $key );
257 } else {
258 return false;
259 }
260 }
261
268 private function load( $prefix ) {
269 $iwData = [];
270 if ( !Hooks::run( 'InterwikiLoadPrefix', [ $prefix, &$iwData ] ) ) {
271 return $this->loadFromArray( $iwData );
272 }
273
274 if ( is_array( $iwData ) ) {
275 $iw = $this->loadFromArray( $iwData );
276 if ( $iw ) {
277 return $iw; // handled by hook
278 }
279 }
280
281 $iwData = $this->objectCache->getWithSetCallback(
282 $this->objectCache->makeKey( 'interwiki', $prefix ),
283 $this->objectCacheExpiry,
284 function ( $oldValue, &$ttl, array &$setOpts ) use ( $prefix ) {
285 $dbr = wfGetDB( DB_REPLICA ); // TODO: inject LoadBalancer
286
287 $setOpts += Database::getCacheSetOptions( $dbr );
288
289 $row = $dbr->selectRow(
290 'interwiki',
291 self::selectFields(),
292 [ 'iw_prefix' => $prefix ],
293 __METHOD__
294 );
295
296 return $row ? (array)$row : '!NONEXISTENT';
297 }
298 );
299
300 if ( is_array( $iwData ) ) {
301 return $this->loadFromArray( $iwData ) ?: false;
302 }
303
304 return false;
305 }
306
313 private function loadFromArray( $mc ) {
314 if ( isset( $mc['iw_url'] ) ) {
315 $url = $mc['iw_url'];
316 $local = isset( $mc['iw_local'] ) ? $mc['iw_local'] : 0;
317 $trans = isset( $mc['iw_trans'] ) ? $mc['iw_trans'] : 0;
318 $api = isset( $mc['iw_api'] ) ? $mc['iw_api'] : '';
319 $wikiId = isset( $mc['iw_wikiid'] ) ? $mc['iw_wikiid'] : '';
320
321 return new Interwiki( null, $url, $api, $wikiId, $local, $trans );
322 }
323
324 return false;
325 }
326
333 private function getAllPrefixesCached( $local ) {
334 wfDebug( __METHOD__ . "()\n" );
335 $data = [];
336 try {
337 /* Resolve site name */
338 if ( $this->interwikiScopes >= 3 && !$this->thisSite ) {
339 $site = $this->getCacheValue( '__sites:' . wfWikiID() );
340
341 if ( $site == '' ) {
342 $this->thisSite = $this->fallbackSite;
343 } else {
344 $this->thisSite = $site;
345 }
346 }
347
348 // List of interwiki sources
349 $sources = [];
350 // Global Level
351 if ( $this->interwikiScopes >= 2 ) {
352 $sources[] = '__global';
353 }
354 // Site level
355 if ( $this->interwikiScopes >= 3 ) {
356 $sources[] = '_' . $this->thisSite;
357 }
358 $sources[] = wfWikiID();
359
360 foreach ( $sources as $source ) {
361 $list = $this->getCacheValue( '__list:' . $source );
362 foreach ( explode( ' ', $list ) as $iw_prefix ) {
363 $row = $this->getCacheValue( "{$source}:{$iw_prefix}" );
364 if ( !$row ) {
365 continue;
366 }
367
368 list( $iw_local, $iw_url ) = explode( ' ', $row );
369
370 if ( $local !== null && $local != $iw_local ) {
371 continue;
372 }
373
374 $data[$iw_prefix] = [
375 'iw_prefix' => $iw_prefix,
376 'iw_url' => $iw_url,
377 'iw_local' => $iw_local,
378 ];
379 }
380 }
381 } catch ( CdbException $e ) {
382 wfDebug( __METHOD__ . ": CdbException caught, error message was "
383 . $e->getMessage() );
384 }
385
386 return array_values( $data );
387 }
388
395 private function getAllPrefixesDB( $local ) {
396 $db = wfGetDB( DB_REPLICA ); // TODO: inject DB LoadBalancer
397
398 $where = [];
399
400 if ( $local !== null ) {
401 if ( $local == 1 ) {
402 $where['iw_local'] = 1;
403 } elseif ( $local == 0 ) {
404 $where['iw_local'] = 0;
405 }
406 }
407
408 $res = $db->select( 'interwiki',
409 self::selectFields(),
410 $where, __METHOD__, [ 'ORDER BY' => 'iw_prefix' ]
411 );
412
413 $retval = [];
414 foreach ( $res as $row ) {
415 $retval[] = (array)$row;
416 }
417
418 return $retval;
419 }
420
427 public function getAllPrefixes( $local = null ) {
428 if ( $this->cdbData ) {
429 return $this->getAllPrefixesCached( $local );
430 }
431
432 return $this->getAllPrefixesDB( $local );
433 }
434
440 private static function selectFields() {
441 return [
442 'iw_prefix',
443 'iw_url',
444 'iw_api',
445 'iw_wikiid',
446 'iw_local',
447 'iw_trans'
448 ];
449 }
450
451}
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
Hooks class.
Definition Hooks.php:34
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition Hooks.php:203
Value object for representing interwiki records.
Definition Interwiki.php:27
Internationalisation code.
Definition Language.php:35
Handles a simple LRU key/value map with a maximum number of entries.
InterwikiLookup implementing the "classic" interwiki storage (hardcoded up to MW 1....
getAllPrefixesDB( $local)
Fetch all interwiki prefixes from DB.
load( $prefix)
Load the interwiki, trying first memcached then the DB.
fetch( $prefix)
Fetch an Interwiki object.
__construct(Language $contentLanguage, WANObjectCache $objectCache, $objectCacheExpiry, $cdbData, $interwikiScopes, $fallbackSite)
invalidateCache( $prefix)
Purge the in-process and object cache for an interwiki prefix.
resetLocalCache()
Resets locally cached Interwiki objects.
static selectFields()
Return the list of interwiki fields that should be selected to create a new Interwiki object.
getAllPrefixes( $local=null)
Returns all interwiki prefixes.
isValidInterwiki( $prefix)
Check whether an interwiki prefix exists.
loadFromArray( $mc)
Fill in member variables from an array (e.g.
getInterwikiCacheEntry( $prefix)
Get entry from interwiki cache.
getAllPrefixesCached( $local)
Fetch all interwiki prefixes from interwiki cache.
getInterwikiCached( $prefix)
Fetch interwiki prefix data from local cache in constant database.
Multi-datacenter aware caching interface.
Relational database abstraction object.
Definition Database.php:45
if(! $regexes) $dbr
Definition cleanup.php:94
$res
Definition database.txt:21
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition deferred.txt:11
when a variable name is used in a function
Definition design.txt:94
the array() calling protocol came about after MediaWiki 1.4rc1.
namespace being checked & $result
Definition hooks.txt:2293
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account incomplete not yet checked for validity & $retval
Definition hooks.txt:266
returning false will NOT prevent logging $e
Definition hooks.txt:2146
Service interface for looking up Interwiki records.
MediaWiki has optional support for a high distributed memory object caching system For general information on but for a larger site with heavy load
Definition memcached.txt:6
$source
const DB_REPLICA
Definition defines.php:25