[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/interwiki/ -> Interwiki.php (source)

   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  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1