[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Interwiki table entry. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 */ 22 23 /** 24 * The interwiki class 25 * All information is loaded on creation when called by Interwiki::fetch( $prefix ). 26 * All work is done on slave, because this should *never* change (except during 27 * schema updates etc, which aren't wiki-related) 28 */ 29 class Interwiki { 30 // Cache - removes oldest entry when it hits limit 31 protected static $smCache = array(); 32 const CACHE_LIMIT = 100; // 0 means unlimited, any other value is max number of entries. 33 34 /** @var string The interwiki prefix, (e.g. "Meatball", or the language prefix "de") */ 35 protected $mPrefix; 36 37 /** @var string The URL of the wiki, with "$1" as a placeholder for an article name. */ 38 protected $mURL; 39 40 /** @var string The URL of the file api.php */ 41 protected $mAPI; 42 43 /** @var string The name of the database (for a connection to be established 44 * with wfGetLB( 'wikiid' )) 45 */ 46 protected $mWikiID; 47 48 /** @var bool Whether the wiki is in this project */ 49 protected $mLocal; 50 51 /** @var bool Whether interwiki transclusions are allowed */ 52 protected $mTrans; 53 54 public function __construct( $prefix = null, $url = '', $api = '', $wikiId = '', $local = 0, 55 $trans = 0 56 ) { 57 $this->mPrefix = $prefix; 58 $this->mURL = $url; 59 $this->mAPI = $api; 60 $this->mWikiID = $wikiId; 61 $this->mLocal = $local; 62 $this->mTrans = $trans; 63 } 64 65 /** 66 * Check whether an interwiki prefix exists 67 * 68 * @param string $prefix Interwiki prefix to use 69 * @return bool Whether it exists 70 */ 71 public static function isValidInterwiki( $prefix ) { 72 $result = self::fetch( $prefix ); 73 74 return (bool)$result; 75 } 76 77 /** 78 * Fetch an Interwiki object 79 * 80 * @param string $prefix Interwiki prefix to use 81 * @return Interwiki|null|bool 82 */ 83 public static function fetch( $prefix ) { 84 global $wgContLang; 85 86 if ( $prefix == '' ) { 87 return null; 88 } 89 90 $prefix = $wgContLang->lc( $prefix ); 91 if ( isset( self::$smCache[$prefix] ) ) { 92 return self::$smCache[$prefix]; 93 } 94 95 global $wgInterwikiCache; 96 if ( $wgInterwikiCache ) { 97 $iw = Interwiki::getInterwikiCached( $prefix ); 98 } else { 99 $iw = Interwiki::load( $prefix ); 100 if ( !$iw ) { 101 $iw = false; 102 } 103 } 104 105 if ( self::CACHE_LIMIT && count( self::$smCache ) >= self::CACHE_LIMIT ) { 106 reset( self::$smCache ); 107 unset( self::$smCache[key( self::$smCache )] ); 108 } 109 110 self::$smCache[$prefix] = $iw; 111 112 return $iw; 113 } 114 115 /** 116 * Fetch interwiki prefix data from local cache in constant database. 117 * 118 * @note More logic is explained in DefaultSettings. 119 * 120 * @param string $prefix Interwiki prefix 121 * @return Interwiki 122 */ 123 protected static function getInterwikiCached( $prefix ) { 124 $value = self::getInterwikiCacheEntry( $prefix ); 125 126 $s = new Interwiki( $prefix ); 127 if ( $value != '' ) { 128 // Split values 129 list( $local, $url ) = explode( ' ', $value, 2 ); 130 $s->mURL = $url; 131 $s->mLocal = (int)$local; 132 } else { 133 $s = false; 134 } 135 136 return $s; 137 } 138 139 /** 140 * Get entry from interwiki cache 141 * 142 * @note More logic is explained in DefaultSettings. 143 * 144 * @param string $prefix Database key 145 * @return string The interwiki entry 146 */ 147 protected static function getInterwikiCacheEntry( $prefix ) { 148 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 149 static $db, $site; 150 151 wfDebug( __METHOD__ . "( $prefix )\n" ); 152 $value = false; 153 try { 154 if ( !$db ) { 155 $db = CdbReader::open( $wgInterwikiCache ); 156 } 157 /* Resolve site name */ 158 if ( $wgInterwikiScopes >= 3 && !$site ) { 159 $site = $db->get( '__sites:' . wfWikiID() ); 160 if ( $site == '' ) { 161 $site = $wgInterwikiFallbackSite; 162 } 163 } 164 165 $value = $db->get( wfMemcKey( $prefix ) ); 166 // Site level 167 if ( $value == '' && $wgInterwikiScopes >= 3 ) { 168 $value = $db->get( "_{$site}:{$prefix}" ); 169 } 170 // Global Level 171 if ( $value == '' && $wgInterwikiScopes >= 2 ) { 172 $value = $db->get( "__global:{$prefix}" ); 173 } 174 if ( $value == 'undef' ) { 175 $value = ''; 176 } 177 } catch ( CdbException $e ) { 178 wfDebug( __METHOD__ . ": CdbException caught, error message was " 179 . $e->getMessage() ); 180 } 181 182 return $value; 183 } 184 185 /** 186 * Load the interwiki, trying first memcached then the DB 187 * 188 * @param string $prefix The interwiki prefix 189 * @return Interwiki|bool Interwiki if $prefix is valid, otherwise false 190 */ 191 protected static function load( $prefix ) { 192 global $wgMemc, $wgInterwikiExpiry; 193 194 $iwData = array(); 195 if ( !wfRunHooks( 'InterwikiLoadPrefix', array( $prefix, &$iwData ) ) ) { 196 return Interwiki::loadFromArray( $iwData ); 197 } 198 199 if ( !$iwData ) { 200 $key = wfMemcKey( 'interwiki', $prefix ); 201 $iwData = $wgMemc->get( $key ); 202 if ( $iwData === '!NONEXISTENT' ) { 203 // negative cache hit 204 return false; 205 } 206 } 207 208 // is_array is hack for old keys 209 if ( $iwData && is_array( $iwData ) ) { 210 $iw = Interwiki::loadFromArray( $iwData ); 211 if ( $iw ) { 212 return $iw; 213 } 214 } 215 216 $db = wfGetDB( DB_SLAVE ); 217 218 $row = $db->fetchRow( $db->select( 219 'interwiki', 220 self::selectFields(), 221 array( 'iw_prefix' => $prefix ), 222 __METHOD__ 223 ) ); 224 225 $iw = Interwiki::loadFromArray( $row ); 226 if ( $iw ) { 227 $mc = array( 228 'iw_url' => $iw->mURL, 229 'iw_api' => $iw->mAPI, 230 'iw_local' => $iw->mLocal, 231 'iw_trans' => $iw->mTrans 232 ); 233 $wgMemc->add( $key, $mc, $wgInterwikiExpiry ); 234 235 return $iw; 236 } 237 238 // negative cache hit 239 $wgMemc->add( $key, '!NONEXISTENT', $wgInterwikiExpiry ); 240 241 return false; 242 } 243 244 /** 245 * Fill in member variables from an array (e.g. memcached result, Database::fetchRow, etc) 246 * 247 * @param array $mc Associative array: row from the interwiki table 248 * @return Interwiki|bool Interwiki object or false if $mc['iw_url'] is not set 249 */ 250 protected static function loadFromArray( $mc ) { 251 if ( isset( $mc['iw_url'] ) ) { 252 $iw = new Interwiki(); 253 $iw->mURL = $mc['iw_url']; 254 $iw->mLocal = isset( $mc['iw_local'] ) ? $mc['iw_local'] : 0; 255 $iw->mTrans = isset( $mc['iw_trans'] ) ? $mc['iw_trans'] : 0; 256 $iw->mAPI = isset( $mc['iw_api'] ) ? $mc['iw_api'] : ''; 257 $iw->mWikiID = isset( $mc['iw_wikiid'] ) ? $mc['iw_wikiid'] : ''; 258 259 return $iw; 260 } 261 262 return false; 263 } 264 265 /** 266 * Fetch all interwiki prefixes from interwiki cache 267 * 268 * @param null|string $local If not null, limits output to local/non-local interwikis 269 * @return array List of prefixes 270 * @since 1.19 271 */ 272 protected static function getAllPrefixesCached( $local ) { 273 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; 274 static $db, $site; 275 276 wfDebug( __METHOD__ . "()\n" ); 277 $data = array(); 278 try { 279 if ( !$db ) { 280 $db = CdbReader::open( $wgInterwikiCache ); 281 } 282 /* Resolve site name */ 283 if ( $wgInterwikiScopes >= 3 && !$site ) { 284 $site = $db->get( '__sites:' . wfWikiID() ); 285 if ( $site == '' ) { 286 $site = $wgInterwikiFallbackSite; 287 } 288 } 289 290 // List of interwiki sources 291 $sources = array(); 292 // Global Level 293 if ( $wgInterwikiScopes >= 2 ) { 294 $sources[] = '__global'; 295 } 296 // Site level 297 if ( $wgInterwikiScopes >= 3 ) { 298 $sources[] = '_' . $site; 299 } 300 $sources[] = wfWikiID(); 301 302 foreach ( $sources as $source ) { 303 $list = $db->get( "__list:{$source}" ); 304 foreach ( explode( ' ', $list ) as $iw_prefix ) { 305 $row = $db->get( "{$source}:{$iw_prefix}" ); 306 if ( !$row ) { 307 continue; 308 } 309 310 list( $iw_local, $iw_url ) = explode( ' ', $row ); 311 312 if ( $local !== null && $local != $iw_local ) { 313 continue; 314 } 315 316 $data[$iw_prefix] = array( 317 'iw_prefix' => $iw_prefix, 318 'iw_url' => $iw_url, 319 'iw_local' => $iw_local, 320 ); 321 } 322 } 323 } catch ( CdbException $e ) { 324 wfDebug( __METHOD__ . ": CdbException caught, error message was " 325 . $e->getMessage() ); 326 } 327 328 ksort( $data ); 329 330 return array_values( $data ); 331 } 332 333 /** 334 * Fetch all interwiki prefixes from DB 335 * 336 * @param string|null $local If not null, limits output to local/non-local interwikis 337 * @return array List of prefixes 338 * @since 1.19 339 */ 340 protected static function getAllPrefixesDB( $local ) { 341 $db = wfGetDB( DB_SLAVE ); 342 343 $where = array(); 344 345 if ( $local !== null ) { 346 if ( $local == 1 ) { 347 $where['iw_local'] = 1; 348 } elseif ( $local == 0 ) { 349 $where['iw_local'] = 0; 350 } 351 } 352 353 $res = $db->select( 'interwiki', 354 self::selectFields(), 355 $where, __METHOD__, array( 'ORDER BY' => 'iw_prefix' ) 356 ); 357 358 $retval = array(); 359 foreach ( $res as $row ) { 360 $retval[] = (array)$row; 361 } 362 363 return $retval; 364 } 365 366 /** 367 * Returns all interwiki prefixes 368 * 369 * @param string|null $local If set, limits output to local/non-local interwikis 370 * @return array List of prefixes 371 * @since 1.19 372 */ 373 public static function getAllPrefixes( $local = null ) { 374 global $wgInterwikiCache; 375 376 if ( $wgInterwikiCache ) { 377 return self::getAllPrefixesCached( $local ); 378 } 379 380 return self::getAllPrefixesDB( $local ); 381 } 382 383 /** 384 * Get the URL for a particular title (or with $1 if no title given) 385 * 386 * @param string $title What text to put for the article name 387 * @return string The URL 388 * @note Prior to 1.19 The getURL with an argument was broken. 389 * If you if you use this arg in an extension that supports MW earlier 390 * than 1.19 please wfUrlencode and substitute $1 on your own. 391 */ 392 public function getURL( $title = null ) { 393 $url = $this->mURL; 394 if ( $title !== null ) { 395 $url = str_replace( "$1", wfUrlencode( $title ), $url ); 396 } 397 398 return $url; 399 } 400 401 /** 402 * Get the API URL for this wiki 403 * 404 * @return string The URL 405 */ 406 public function getAPI() { 407 return $this->mAPI; 408 } 409 410 /** 411 * Get the DB name for this wiki 412 * 413 * @return string The DB name 414 */ 415 public function getWikiID() { 416 return $this->mWikiID; 417 } 418 419 /** 420 * Is this a local link from a sister project, or is 421 * it something outside, like Google 422 * 423 * @return bool 424 */ 425 public function isLocal() { 426 return $this->mLocal; 427 } 428 429 /** 430 * Can pages from this wiki be transcluded? 431 * Still requires $wgEnableScaryTransclusion 432 * 433 * @return bool 434 */ 435 public function isTranscludable() { 436 return $this->mTrans; 437 } 438 439 /** 440 * Get the name for the interwiki site 441 * 442 * @return string 443 */ 444 public function getName() { 445 $msg = wfMessage( 'interwiki-name-' . $this->mPrefix )->inContentLanguage(); 446 447 return !$msg->exists() ? '' : $msg; 448 } 449 450 /** 451 * Get a description for this interwiki 452 * 453 * @return string 454 */ 455 public function getDescription() { 456 $msg = wfMessage( 'interwiki-desc-' . $this->mPrefix )->inContentLanguage(); 457 458 return !$msg->exists() ? '' : $msg; 459 } 460 461 /** 462 * Return the list of interwiki fields that should be selected to create 463 * a new Interwiki object. 464 * @return string[] 465 */ 466 public static function selectFields() { 467 return array( 468 'iw_prefix', 469 'iw_url', 470 'iw_api', 471 'iw_wikiid', 472 'iw_local', 473 'iw_trans' 474 ); 475 } 476 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |