MediaWiki REL1_39
PageProps.php
Go to the documentation of this file.
1<?php
27
33class PageProps {
34
36 private $linkBatchFactory;
37
39 private $loadBalancer;
40
42 private const CACHE_TTL = 10; // integer; TTL in seconds
43 private const CACHE_SIZE = 100; // integer; max cached pages
44
46 private $cache;
47
54 public static function getInstance() {
55 wfDeprecated( __METHOD__, '1.38' );
56 return MediaWikiServices::getInstance()->getPageProps();
57 }
58
63 public function __construct(
64 LinkBatchFactory $linkBatchFactory,
65 ILoadBalancer $loadBalancer
66 ) {
67 $this->linkBatchFactory = $linkBatchFactory;
68 $this->loadBalancer = $loadBalancer;
69 $this->cache = new MapCacheLRU( self::CACHE_SIZE );
70 }
71
76 public function ensureCacheSize( $size ) {
77 if ( $this->cache->getMaxSize() < $size ) {
78 $this->cache->setMaxSize( $size );
79 }
80 }
81
100 public function getProperties( $titles, $propertyNames ) {
101 if ( is_array( $propertyNames ) ) {
102 $gotArray = true;
103 } else {
104 $propertyNames = [ $propertyNames ];
105 $gotArray = false;
106 }
107
108 $values = [];
109 $goodIDs = $this->getGoodIDs( $titles );
110 $queryIDs = [];
111 foreach ( $goodIDs as $pageID ) {
112 foreach ( $propertyNames as $propertyName ) {
113 $propertyValue = $this->getCachedProperty( $pageID, $propertyName );
114 if ( $propertyValue === false ) {
115 $queryIDs[] = $pageID;
116 break;
117 } elseif ( $gotArray ) {
118 $values[$pageID][$propertyName] = $propertyValue;
119 } else {
120 $values[$pageID] = $propertyValue;
121 }
122 }
123 }
124
125 if ( $queryIDs ) {
126 $queryBuilder = $this->loadBalancer->getConnectionRef( DB_REPLICA )->newSelectQueryBuilder();
127 $queryBuilder->select( [ 'pp_page', 'pp_propname', 'pp_value' ] )
128 ->from( 'page_props' )
129 ->where( [ 'pp_page' => $queryIDs, 'pp_propname' => $propertyNames ] )
130 ->caller( __METHOD__ );
131 $result = $queryBuilder->fetchResultSet();
132
133 foreach ( $result as $row ) {
134 $pageID = $row->pp_page;
135 $propertyName = $row->pp_propname;
136 $propertyValue = $row->pp_value;
137 $this->cache->setField( $pageID, $propertyName, $propertyValue );
138 if ( $gotArray ) {
139 $values[$pageID][$propertyName] = $propertyValue;
140 } else {
141 $values[$pageID] = $propertyValue;
142 }
143 }
144 }
145
146 return $values;
147 }
148
162 public function getAllProperties( $titles ) {
163 $values = [];
164 $goodIDs = $this->getGoodIDs( $titles );
165 $queryIDs = [];
166 foreach ( $goodIDs as $pageID ) {
167 $pageProperties = $this->getCachedProperties( $pageID );
168 if ( $pageProperties === false ) {
169 $queryIDs[] = $pageID;
170 } else {
171 $values[$pageID] = $pageProperties;
172 }
173 }
174
175 if ( $queryIDs != [] ) {
176 $queryBuilder = $this->loadBalancer->getConnectionRef( DB_REPLICA )->newSelectQueryBuilder();
177 $queryBuilder->select( [ 'pp_page', 'pp_propname', 'pp_value' ] )
178 ->from( 'page_props' )
179 ->where( [ 'pp_page' => $queryIDs ] )
180 ->caller( __METHOD__ );
181 $result = $queryBuilder->fetchResultSet();
182
183 $currentPageID = 0;
184 $pageProperties = [];
185 foreach ( $result as $row ) {
186 $pageID = $row->pp_page;
187 if ( $currentPageID != $pageID ) {
188 if ( $pageProperties ) {
189 // @phan-suppress-next-line PhanTypeMismatchArgument False positive
190 $this->cacheProperties( $currentPageID, $pageProperties );
191 $values[$currentPageID] = $pageProperties;
192 }
193 $currentPageID = $pageID;
194 $pageProperties = [];
195 }
196 $pageProperties[$row->pp_propname] = $row->pp_value;
197 }
198 if ( $pageProperties != [] ) {
199 // @phan-suppress-next-next-line PhanPossiblyUndeclaredVariable pageID set when used
200 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable pageID set when used
201 $this->cacheProperties( $pageID, $pageProperties );
202 // @phan-suppress-next-next-line PhanPossiblyUndeclaredVariable pageID set when used
203 // @phan-suppress-next-line PhanTypeMismatchDimAssignment pageID set when used
204 $values[$pageID] = $pageProperties;
205 }
206 }
207
208 return $values;
209 }
210
215 private function getGoodIDs( $titles ) {
216 $result = [];
217 if ( is_iterable( $titles ) ) {
218 if ( $titles instanceof TitleArray ||
219 ( is_array( $titles ) && reset( $titles ) instanceof Title
220 ) ) {
221 // If the first element is a Title, assume all elements are Titles,
222 // and pre-fetch their IDs using a batch query. For PageIdentityValues
223 // or PageStoreRecords, this is not necessary, since they already
224 // know their ID.
225 $this->linkBatchFactory->newLinkBatch( $titles )->execute();
226 }
227
228 foreach ( $titles as $title ) {
229 // Until we only allow ProperPageIdentity, Title objects
230 // can deceive us with an unexpected Special page
231 if ( $title->canExist() ) {
232 $pageID = $title->getId();
233 if ( $pageID > 0 ) {
234 $result[] = $pageID;
235 }
236 }
237 }
238 } else {
239 // Until we only allow ProperPageIdentity, Title objects
240 // can deceive us with an unexpected Special page
241 if ( $titles->canExist() ) {
242 $pageID = $titles->getId();
243 if ( $pageID > 0 ) {
244 $result[] = $pageID;
245 }
246 }
247 }
248 return $result;
249 }
250
258 private function getCachedProperty( $pageID, $propertyName ) {
259 if ( $this->cache->hasField( $pageID, $propertyName, self::CACHE_TTL ) ) {
260 return $this->cache->getField( $pageID, $propertyName );
261 }
262 if ( $this->cache->hasField( 0, $pageID, self::CACHE_TTL ) ) {
263 $pageProperties = $this->cache->getField( 0, $pageID );
264 if ( isset( $pageProperties[$propertyName] ) ) {
265 return $pageProperties[$propertyName];
266 }
267 }
268 return false;
269 }
270
277 private function getCachedProperties( $pageID ) {
278 if ( $this->cache->hasField( 0, $pageID, self::CACHE_TTL ) ) {
279 return $this->cache->getField( 0, $pageID );
280 }
281 return false;
282 }
283
290 private function cacheProperties( $pageID, $pageProperties ) {
291 $this->cache->clear( $pageID );
292 $this->cache->setField( 0, $pageID, $pageProperties );
293 }
294}
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Handles a simple LRU key/value map with a maximum number of entries.
Service locator for MediaWiki core services.
Gives access to properties of a page.
Definition PageProps.php:33
__construct(LinkBatchFactory $linkBatchFactory, ILoadBalancer $loadBalancer)
Definition PageProps.php:63
ensureCacheSize( $size)
Ensure that cache has at least this size.
Definition PageProps.php:76
getProperties( $titles, $propertyNames)
Given one or more Titles and one or more names of properties, returns an associative array mapping pa...
static getInstance()
Definition PageProps.php:54
getAllProperties( $titles)
Get all page property values.
The TitleArray class only exists to provide the newFromResult method at pre- sent.
Represents a title within MediaWiki.
Definition Title.php:49
Interface for objects (potentially) representing an editable wiki page.
Create and track the database connections and transactions for a given database cluster.
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:26