Interwiki.php 5.5 KB

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