MediaWiki  master
PageProps.php
Go to the documentation of this file.
1 <?php
22 use Wikimedia\ScopedCallback;
23 
29 class PageProps {
30 
34  private static $instance;
35 
50  public static function overrideInstance( PageProps $store = null ) {
51  if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
52  throw new MWException(
53  'Cannot override ' . __CLASS__ . 'default instance in operation.'
54  );
55  }
56  $previousValue = self::$instance;
57  self::$instance = $store;
58  return new ScopedCallback( function () use ( $previousValue ) {
59  self::$instance = $previousValue;
60  } );
61  }
62 
66  public static function getInstance() {
67  if ( self::$instance === null ) {
68  self::$instance = new self();
69  }
70  return self::$instance;
71  }
72 
74  const CACHE_TTL = 10; // integer; TTL in seconds
75  const CACHE_SIZE = 100; // integer; max cached pages
76 
78  private $cache = null;
79 
83  private function __construct() {
84  $this->cache = new MapCacheLRU( self::CACHE_SIZE );
85  }
86 
91  public function ensureCacheSize( $size ) {
92  if ( $this->cache->getMaxSize() < $size ) {
93  $this->cache->setMaxSize( $size );
94  }
95  }
96 
115  public function getProperties( $titles, $propertyNames ) {
116  if ( is_array( $propertyNames ) ) {
117  $gotArray = true;
118  } else {
119  $propertyNames = [ $propertyNames ];
120  $gotArray = false;
121  }
122 
123  $values = [];
124  $goodIDs = $this->getGoodIDs( $titles );
125  $queryIDs = [];
126  foreach ( $goodIDs as $pageID ) {
127  foreach ( $propertyNames as $propertyName ) {
128  $propertyValue = $this->getCachedProperty( $pageID, $propertyName );
129  if ( $propertyValue === false ) {
130  $queryIDs[] = $pageID;
131  break;
132  } elseif ( $gotArray ) {
133  $values[$pageID][$propertyName] = $propertyValue;
134  } else {
135  $values[$pageID] = $propertyValue;
136  }
137  }
138  }
139 
140  if ( $queryIDs ) {
141  $dbr = wfGetDB( DB_REPLICA );
142  $result = $dbr->select(
143  'page_props',
144  [
145  'pp_page',
146  'pp_propname',
147  'pp_value'
148  ],
149  [
150  'pp_page' => $queryIDs,
151  'pp_propname' => $propertyNames
152  ],
153  __METHOD__
154  );
155 
156  foreach ( $result as $row ) {
157  $pageID = $row->pp_page;
158  $propertyName = $row->pp_propname;
159  $propertyValue = $row->pp_value;
160  $this->cacheProperty( $pageID, $propertyName, $propertyValue );
161  if ( $gotArray ) {
162  $values[$pageID][$propertyName] = $propertyValue;
163  } else {
164  $values[$pageID] = $propertyValue;
165  }
166  }
167  }
168 
169  return $values;
170  }
171 
185  public function getAllProperties( $titles ) {
186  $values = [];
187  $goodIDs = $this->getGoodIDs( $titles );
188  $queryIDs = [];
189  foreach ( $goodIDs as $pageID ) {
190  $pageProperties = $this->getCachedProperties( $pageID );
191  if ( $pageProperties === false ) {
192  $queryIDs[] = $pageID;
193  } else {
194  $values[$pageID] = $pageProperties;
195  }
196  }
197 
198  if ( $queryIDs != [] ) {
199  $dbr = wfGetDB( DB_REPLICA );
200  $result = $dbr->select(
201  'page_props',
202  [
203  'pp_page',
204  'pp_propname',
205  'pp_value'
206  ],
207  [
208  'pp_page' => $queryIDs,
209  ],
210  __METHOD__
211  );
212 
213  $currentPageID = 0;
214  $pageProperties = [];
215  foreach ( $result as $row ) {
216  $pageID = $row->pp_page;
217  if ( $currentPageID != $pageID ) {
218  if ( $pageProperties != [] ) {
219  $this->cacheProperties( $currentPageID, $pageProperties );
220  $values[$currentPageID] = $pageProperties;
221  }
222  $currentPageID = $pageID;
223  $pageProperties = [];
224  }
225  $pageProperties[$row->pp_propname] = $row->pp_value;
226  }
227  if ( $pageProperties != [] ) {
228  $this->cacheProperties( $pageID, $pageProperties );
229  $values[$pageID] = $pageProperties;
230  }
231  }
232 
233  return $values;
234  }
235 
240  private function getGoodIDs( $titles ) {
241  $result = [];
242  if ( is_array( $titles ) ) {
243  ( new LinkBatch( $titles ) )->execute();
244 
245  foreach ( $titles as $title ) {
246  $pageID = $title->getArticleID();
247  if ( $pageID > 0 ) {
248  $result[] = $pageID;
249  }
250  }
251  } else {
252  $pageID = $titles->getArticleID();
253  if ( $pageID > 0 ) {
254  $result[] = $pageID;
255  }
256  }
257  return $result;
258  }
259 
267  private function getCachedProperty( $pageID, $propertyName ) {
268  if ( $this->cache->hasField( $pageID, $propertyName, self::CACHE_TTL ) ) {
269  return $this->cache->getField( $pageID, $propertyName );
270  }
271  if ( $this->cache->hasField( 0, $pageID, self::CACHE_TTL ) ) {
272  $pageProperties = $this->cache->getField( 0, $pageID );
273  if ( isset( $pageProperties[$propertyName] ) ) {
274  return $pageProperties[$propertyName];
275  }
276  }
277  return false;
278  }
279 
286  private function getCachedProperties( $pageID ) {
287  if ( $this->cache->hasField( 0, $pageID, self::CACHE_TTL ) ) {
288  return $this->cache->getField( 0, $pageID );
289  }
290  return false;
291  }
292 
300  private function cacheProperty( $pageID, $propertyName, $propertyValue ) {
301  $this->cache->setField( $pageID, $propertyName, $propertyValue );
302  }
303 
310  private function cacheProperties( $pageID, $pageProperties ) {
311  $this->cache->clear( $pageID );
312  $this->cache->setField( 0, $pageID, $pageProperties );
313  }
314 }
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:34
PageProps\getProperties
getProperties( $titles, $propertyNames)
Given one or more Titles and one or more names of properties, returns an associative array mapping pa...
Definition: PageProps.php:115
PageProps\getCachedProperty
getCachedProperty( $pageID, $propertyName)
Get a property from the cache.
Definition: PageProps.php:267
$dbr
$dbr
Definition: testCompression.php:52
MWException
MediaWiki exception.
Definition: MWException.php:26
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2579
PageProps\getInstance
static getInstance()
Definition: PageProps.php:66
PageProps\overrideInstance
static overrideInstance(PageProps $store=null)
Overrides the default instance of this class This is intended for use while testing and will fail if ...
Definition: PageProps.php:50
MapCacheLRU
Handles a simple LRU key/value map with a maximum number of entries.
Definition: MapCacheLRU.php:37
$title
$title
Definition: testCompression.php:36
PageProps\__construct
__construct()
Create a PageProps object.
Definition: PageProps.php:83
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
PageProps\getGoodIDs
getGoodIDs( $titles)
Definition: PageProps.php:240
PageProps\$instance
static PageProps $instance
Definition: PageProps.php:34
PageProps\CACHE_TTL
const CACHE_TTL
Cache parameters.
Definition: PageProps.php:74
PageProps\getAllProperties
getAllProperties( $titles)
Get all page property values.
Definition: PageProps.php:185
PageProps\CACHE_SIZE
const CACHE_SIZE
Definition: PageProps.php:75
PageProps\cacheProperty
cacheProperty( $pageID, $propertyName, $propertyValue)
Save a property to the cache.
Definition: PageProps.php:300
PageProps\ensureCacheSize
ensureCacheSize( $size)
Ensure that cache has at least this size.
Definition: PageProps.php:91
PageProps
Gives access to properties of a page.
Definition: PageProps.php:29
PageProps\getCachedProperties
getCachedProperties( $pageID)
Get properties from the cache.
Definition: PageProps.php:286
PageProps\$cache
$cache
Property cache.
Definition: PageProps.php:78
PageProps\cacheProperties
cacheProperties( $pageID, $pageProperties)
Save properties to the cache.
Definition: PageProps.php:310