LinkCache.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. /**
  3. * Cache for article titles (prefixed DB keys) and ids linked from one source
  4. *
  5. * @ingroup Cache
  6. */
  7. class LinkCache {
  8. // Increment $mClassVer whenever old serialized versions of this class
  9. // becomes incompatible with the new version.
  10. /* private */ var $mClassVer = 4;
  11. /* private */ var $mGoodLinks, $mBadLinks;
  12. /* private */ var $mForUpdate;
  13. /**
  14. * Get an instance of this class
  15. */
  16. static function &singleton() {
  17. static $instance;
  18. if ( !isset( $instance ) ) {
  19. $instance = new LinkCache;
  20. }
  21. return $instance;
  22. }
  23. function __construct() {
  24. $this->mForUpdate = false;
  25. $this->mGoodLinks = array();
  26. $this->mGoodLinkFields = array();
  27. $this->mBadLinks = array();
  28. }
  29. /**
  30. * General accessor to get/set whether SELECT FOR UPDATE should be used
  31. */
  32. public function forUpdate( $update = NULL ) {
  33. return wfSetVar( $this->mForUpdate, $update );
  34. }
  35. public function getGoodLinkID( $title ) {
  36. if ( array_key_exists( $title, $this->mGoodLinks ) ) {
  37. return $this->mGoodLinks[$title];
  38. } else {
  39. return 0;
  40. }
  41. }
  42. /**
  43. * Get a field of a title object from cache.
  44. * If this link is not good, it will return NULL.
  45. * @param Title $title
  46. * @param string $field ('length','redirect')
  47. * @return mixed
  48. */
  49. public function getGoodLinkFieldObj( $title, $field ) {
  50. $dbkey = $title->getPrefixedDbKey();
  51. if ( array_key_exists( $dbkey, $this->mGoodLinkFields ) ) {
  52. return $this->mGoodLinkFields[$dbkey][$field];
  53. } else {
  54. return NULL;
  55. }
  56. }
  57. public function isBadLink( $title ) {
  58. return array_key_exists( $title, $this->mBadLinks );
  59. }
  60. /**
  61. * Add a link for the title to the link cache
  62. * @param int $id
  63. * @param Title $title
  64. * @param int $len
  65. * @param int $redir
  66. */
  67. public function addGoodLinkObj( $id, $title, $len = -1, $redir = NULL ) {
  68. $dbkey = $title->getPrefixedDbKey();
  69. $this->mGoodLinks[$dbkey] = $id;
  70. $this->mGoodLinkFields[$dbkey] = array( 'length' => $len, 'redirect' => $redir );
  71. }
  72. public function addBadLinkObj( $title ) {
  73. $dbkey = $title->getPrefixedDbKey();
  74. if ( !$this->isBadLink( $dbkey ) ) {
  75. $this->mBadLinks[$dbkey] = 1;
  76. }
  77. }
  78. public function clearBadLink( $title ) {
  79. unset( $this->mBadLinks[$title] );
  80. }
  81. public function clearLink( $title ) {
  82. $dbkey = $title->getPrefixedDbKey();
  83. if( isset($this->mBadLinks[$dbkey]) ) {
  84. unset($this->mBadLinks[$dbkey]);
  85. }
  86. if( isset($this->mGoodLinks[$dbkey]) ) {
  87. unset($this->mGoodLinks[$dbkey]);
  88. }
  89. if( isset($this->mGoodLinkFields[$dbkey]) ) {
  90. unset($this->mGoodLinkFields[$dbkey]);
  91. }
  92. }
  93. public function getGoodLinks() { return $this->mGoodLinks; }
  94. public function getBadLinks() { return array_keys( $this->mBadLinks ); }
  95. /**
  96. * Add a title to the link cache, return the page_id or zero if non-existent
  97. * @param $title String: title to add
  98. * @param $len int, page size
  99. * @param $redir bool, is redirect?
  100. * @return integer
  101. */
  102. public function addLink( $title, $len = -1, $redir = NULL ) {
  103. $nt = Title::newFromDBkey( $title );
  104. if( $nt ) {
  105. return $this->addLinkObj( $nt, $len, $redir );
  106. } else {
  107. return 0;
  108. }
  109. }
  110. /**
  111. * Add a title to the link cache, return the page_id or zero if non-existent
  112. * @param $nt Title to add.
  113. * @param $len int, page size
  114. * @param $redir bool, is redirect?
  115. * @return integer
  116. */
  117. public function addLinkObj( &$nt, $len = -1, $redirect = NULL ) {
  118. global $wgAntiLockFlags, $wgProfiler;
  119. wfProfileIn( __METHOD__ );
  120. $key = $nt->getPrefixedDBkey();
  121. if ( $this->isBadLink( $key ) ) {
  122. wfProfileOut( __METHOD__ );
  123. return 0;
  124. }
  125. $id = $this->getGoodLinkID( $key );
  126. if ( $id != 0 ) {
  127. wfProfileOut( __METHOD__ );
  128. return $id;
  129. }
  130. if ( $key === '' ) {
  131. wfProfileOut( __METHOD__ );
  132. return 0;
  133. }
  134. # Some fields heavily used for linking...
  135. if ( $this->mForUpdate ) {
  136. $db = wfGetDB( DB_MASTER );
  137. if ( !( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) ) {
  138. $options = array( 'FOR UPDATE' );
  139. } else {
  140. $options = array();
  141. }
  142. } else {
  143. $db = wfGetDB( DB_SLAVE );
  144. $options = array();
  145. }
  146. $s = $db->selectRow( 'page',
  147. array( 'page_id', 'page_len', 'page_is_redirect' ),
  148. array( 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey() ),
  149. __METHOD__, $options );
  150. # Set fields...
  151. if ( $s !== false && is_object( $s ) ) {
  152. $id = $s->page_id;
  153. $len = $s->page_len;
  154. $redirect = $s->page_is_redirect;
  155. } else {
  156. $len = -1;
  157. $redirect = 0;
  158. }
  159. if ( $id == 0 ) {
  160. $this->addBadLinkObj( $nt );
  161. } else {
  162. $this->addGoodLinkObj( $id, $nt, $len, $redirect );
  163. }
  164. wfProfileOut( __METHOD__ );
  165. return $id;
  166. }
  167. /**
  168. * Clears cache
  169. */
  170. public function clear() {
  171. $this->mGoodLinks = array();
  172. $this->mGoodLinkFields = array();
  173. $this->mBadLinks = array();
  174. }
  175. }