MediaWiki  master
LinkCache.php
Go to the documentation of this file.
1 <?php
25 
31 class LinkCache {
35  private $mGoodLinks;
39  private $mBadLinks;
40  private $mForUpdate = false;
41 
45  private $titleFormatter;
46 
51  const MAX_SIZE = 10000;
52 
54  $this->mGoodLinks = new HashBagOStuff( [ 'maxKeys' => self::MAX_SIZE ] );
55  $this->mBadLinks = new HashBagOStuff( [ 'maxKeys' => self::MAX_SIZE ] );
56  $this->titleFormatter = $titleFormatter;
57  }
58 
65  public static function singleton() {
66  return MediaWikiServices::getInstance()->getLinkCache();
67  }
68 
79  public function forUpdate( $update = null ) {
80  return wfSetVar( $this->mForUpdate, $update );
81  }
82 
87  public function getGoodLinkID( $title ) {
88  $info = $this->mGoodLinks->get( $title );
89  if ( !$info ) {
90  return 0;
91  }
92  return $info['id'];
93  }
94 
102  public function getGoodLinkFieldObj( LinkTarget $target, $field ) {
103  $dbkey = $this->titleFormatter->getPrefixedDBkey( $target );
104  $info = $this->mGoodLinks->get( $dbkey );
105  if ( !$info ) {
106  return null;
107  }
108  return $info[$field];
109  }
110 
115  public function isBadLink( $title ) {
116  // Use get() to ensure it records as used for LRU.
117  return $this->mBadLinks->get( $title ) !== false;
118  }
119 
131  public function addGoodLinkObj( $id, LinkTarget $target, $len = -1, $redir = null,
132  $revision = 0, $model = null, $lang = null
133  ) {
134  $dbkey = $this->titleFormatter->getPrefixedDBkey( $target );
135  $this->mGoodLinks->set( $dbkey, [
136  'id' => (int)$id,
137  'length' => (int)$len,
138  'redirect' => (int)$redir,
139  'revision' => (int)$revision,
140  'model' => $model ? (string)$model : null,
141  'lang' => $lang ? (string)$lang : null,
142  ] );
143  }
144 
152  public function addGoodLinkObjFromRow( LinkTarget $target, $row ) {
153  $dbkey = $this->titleFormatter->getPrefixedDBkey( $target );
154  $this->mGoodLinks->set( $dbkey, [
155  'id' => intval( $row->page_id ),
156  'length' => intval( $row->page_len ),
157  'redirect' => intval( $row->page_is_redirect ),
158  'revision' => intval( $row->page_latest ),
159  'model' => !empty( $row->page_content_model ) ? strval( $row->page_content_model ) : null,
160  'lang' => !empty( $row->page_lang ) ? strval( $row->page_lang ) : null,
161  ] );
162  }
163 
167  public function addBadLinkObj( LinkTarget $target ) {
168  $dbkey = $this->titleFormatter->getPrefixedDBkey( $target );
169  if ( !$this->isBadLink( $dbkey ) ) {
170  $this->mBadLinks->set( $dbkey, 1 );
171  }
172  }
173 
177  public function clearBadLink( $title ) {
178  $this->mBadLinks->delete( $title );
179  }
180 
184  public function clearLink( LinkTarget $target ) {
185  $dbkey = $this->titleFormatter->getPrefixedDBkey( $target );
186  $this->mBadLinks->delete( $dbkey );
187  $this->mGoodLinks->delete( $dbkey );
188  }
189 
197  public function addLink( $title ) {
198  $nt = Title::newFromDBkey( $title );
199  if ( !$nt ) {
200  return 0;
201  }
202  return $this->addLinkObj( $nt );
203  }
204 
211  public static function getSelectFields() {
213 
214  $fields = [ 'page_id', 'page_len', 'page_is_redirect', 'page_latest' ];
215  if ( $wgContentHandlerUseDB ) {
216  $fields[] = 'page_content_model';
217  }
218  if ( $wgPageLanguageUseDB ) {
219  $fields[] = 'page_lang';
220  }
221 
222  return $fields;
223  }
224 
231  public function addLinkObj( LinkTarget $nt ) {
232  $key = $this->titleFormatter->getPrefixedDBkey( $nt );
233  if ( $this->isBadLink( $key ) || $nt->isExternal()
234  || $nt->inNamespace( NS_SPECIAL )
235  ) {
236  return 0;
237  }
238  $id = $this->getGoodLinkID( $key );
239  if ( $id != 0 ) {
240  return $id;
241  }
242 
243  if ( $key === '' ) {
244  return 0;
245  }
246 
247  // Some fields heavily used for linking...
248  $db = $this->mForUpdate ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
249 
250  $row = $db->selectRow( 'page', self::getSelectFields(),
251  [ 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey() ],
252  __METHOD__
253  );
254 
255  if ( $row !== false ) {
256  $this->addGoodLinkObjFromRow( $nt, $row );
257  $id = intval( $row->page_id );
258  } else {
259  $this->addBadLinkObj( $nt );
260  $id = 0;
261  }
262 
263  return $id;
264  }
265 
269  public function clear() {
270  $this->mGoodLinks->clear();
271  $this->mBadLinks->clear();
272  }
273 }
__construct(TitleFormatter $titleFormatter)
Definition: LinkCache.php:53
addLinkObj(LinkTarget $nt)
Add a title to the link cache, return the page_id or zero if non-existent.
Definition: LinkCache.php:231
wfGetDB($db, $groups=[], $wiki=false)
Get a Database object.
addBadLinkObj(LinkTarget $target)
Definition: LinkCache.php:167
HashBagOStuff $mGoodLinks
Definition: LinkCache.php:35
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
if(!isset($args[0])) $lang
const NS_SPECIAL
Definition: Defines.php:58
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
when a variable name is used in a it is silently declared as a new local masking the global
Definition: design.txt:93
forUpdate($update=null)
General accessor to get/set whether the master DB should be used.
Definition: LinkCache.php:79
getGoodLinkID($title)
Definition: LinkCache.php:87
getNamespace()
Get the namespace index.
clearLink(LinkTarget $target)
Definition: LinkCache.php:184
isExternal()
Whether this LinkTarget has an interwiki component.
$wgContentHandlerUseDB
Set to false to disable use of the database fields introduced by the ContentHandler facility...
TitleFormatter $titleFormatter
Definition: LinkCache.php:45
static singleton()
Get an instance of this class.
Definition: LinkCache.php:65
clear()
Clears cache.
Definition: LinkCache.php:269
static newFromDBkey($key)
Create a new Title from a prefixed DB key.
Definition: Title.php:200
getGoodLinkFieldObj(LinkTarget $target, $field)
Get a field of a title object from cache.
Definition: LinkCache.php:102
getDBkey()
Get the main part with underscores.
const DB_SLAVE
Definition: Defines.php:46
Allows to change the fields on the form that will be generated are created Can be used to omit specific feeds from being outputted You must not use this hook to add use OutputPage::addFeedLink() instead.&$feedLinks conditions will AND in the final query as a Content object as a Content object $title
Definition: hooks.txt:312
clearBadLink($title)
Definition: LinkCache.php:177
const MAX_SIZE
How many Titles to store.
Definition: LinkCache.php:51
addLink($title)
Add a title to the link cache, return the page_id or zero if non-existent.
Definition: LinkCache.php:197
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:211
bool $wgPageLanguageUseDB
Enable page language feature Allows setting page language in database.
addGoodLinkObj($id, LinkTarget $target, $len=-1, $redir=null, $revision=0, $model=null, $lang=null)
Add a link for the title to the link cache.
Definition: LinkCache.php:131
isBadLink($title)
Definition: LinkCache.php:115
Simple store for keeping values in an associative array for the current process.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
HashBagOStuff $mBadLinks
Definition: LinkCache.php:39
A title formatter service for MediaWiki.
Cache for article titles (prefixed DB keys) and ids linked from one source.
Definition: LinkCache.php:31
const DB_MASTER
Definition: Defines.php:47
inNamespace($ns)
Convenience function to test if it is in the namespace.
addGoodLinkObjFromRow(LinkTarget $target, $row)
Same as above with better interface.
Definition: LinkCache.php:152