Fix use of RawMessage in Status::getMessage()
[mediawiki.git] / includes / PageProps.php
blobbc3e3f15297aeacf5024da2811904fe02e562989
1 <?php
2 /**
3 * Access to properties of a page.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
20 * @file
23 /**
24 * Gives access to properties of a page.
26 * @since 1.27
29 class PageProps {
31 /**
32 * @var PageProps
34 private static $instance;
36 /**
37 * @return PageProps
39 public static function getInstance() {
40 if ( self::$instance === null ) {
41 self::$instance = new self();
43 return self::$instance;
46 /** Cache parameters */
47 const CACHE_TTL = 10; // integer; TTL in seconds
48 const CACHE_SIZE = 100; // integer; max cached pages
50 /** Property cache */
51 private $cache = null;
53 /**
54 * Create a PageProps object
56 private function __construct() {
57 $this->cache = new ProcessCacheLRU( self::CACHE_SIZE );
60 /**
61 * Given one or more Titles and one or more names of properties,
62 * returns an associative array mapping page ID to property value.
63 * Pages in the provided set of Titles that do not have a value for
64 * the given properties will not appear in the returned array. If a
65 * single Title is provided, it does not need to be passed in an array,
66 * but an array will always be returned. If a single property name is
67 * provided, it does not need to be passed in an array. In that case,
68 * an associtive array mapping page ID to property value will be
69 * returned; otherwise, an associative array mapping page ID to
70 * an associative array mapping property name to property value will be
71 * returned. An empty array will be returned if no matching properties
72 * were found.
74 * @param Title[]|Title $titles
75 * @param string[]|string $propertyNames
76 * @return array associative array mapping page ID to property value
78 public function getProperties( $titles, $propertyNames ) {
79 if ( is_array( $propertyNames ) ) {
80 $gotArray = true;
81 } else {
82 $propertyNames = [ $propertyNames ];
83 $gotArray = false;
86 $values = [];
87 $goodIDs = $this->getGoodIDs( $titles );
88 $queryIDs = [];
89 foreach ( $goodIDs as $pageID ) {
90 foreach ( $propertyNames as $propertyName ) {
91 $propertyValue = $this->getCachedProperty( $pageID, $propertyName );
92 if ( $propertyValue === false ) {
93 $queryIDs[] = $pageID;
94 break;
95 } else {
96 if ( $gotArray ) {
97 $values[$pageID][$propertyName] = $propertyValue;
98 } else {
99 $values[$pageID] = $propertyValue;
105 if ( $queryIDs ) {
106 $dbr = wfGetDB( DB_SLAVE );
107 $result = $dbr->select(
108 'page_props',
110 'pp_page',
111 'pp_propname',
112 'pp_value'
115 'pp_page' => $queryIDs,
116 'pp_propname' => $propertyNames
118 __METHOD__
121 foreach ( $result as $row ) {
122 $pageID = $row->pp_page;
123 $propertyName = $row->pp_propname;
124 $propertyValue = $row->pp_value;
125 $this->cacheProperty( $pageID, $propertyName, $propertyValue );
126 if ( $gotArray ) {
127 $values[$pageID][$propertyName] = $propertyValue;
128 } else {
129 $values[$pageID] = $propertyValue;
134 return $values;
138 * Get all page property values.
139 * Given one or more Titles, returns an associative array mapping page
140 * ID to an associative array mapping property names to property
141 * values. Pages in the provided set of Titles that do not have any
142 * properties will not appear in the returned array. If a single Title
143 * is provided, it does not need to be passed in an array, but an array
144 * will always be returned. An empty array will be returned if no
145 * matching properties were found.
147 * @param Title[]|Title $titles
148 * @return array associative array mapping page ID to property value array
150 public function getAllProperties( $titles ) {
151 $values = [];
152 $goodIDs = $this->getGoodIDs( $titles );
153 $queryIDs = [];
154 foreach ( $goodIDs as $pageID ) {
155 $pageProperties = $this->getCachedProperties( $pageID );
156 if ( $pageProperties === false ) {
157 $queryIDs[] = $pageID;
158 } else {
159 $values[$pageID] = $pageProperties;
163 if ( $queryIDs != [] ) {
164 $dbr = wfGetDB( DB_SLAVE );
165 $result = $dbr->select(
166 'page_props',
168 'pp_page',
169 'pp_propname',
170 'pp_value'
173 'pp_page' => $queryIDs,
175 __METHOD__
178 $currentPageID = 0;
179 $pageProperties = [];
180 foreach ( $result as $row ) {
181 $pageID = $row->pp_page;
182 if ( $currentPageID != $pageID ) {
183 if ( $pageProperties != [] ) {
184 $this->cacheProperties( $currentPageID, $pageProperties );
185 $values[$currentPageID] = $pageProperties;
187 $currentPageID = $pageID;
188 $pageProperties = [];
190 $pageProperties[$row->pp_propname] = $row->pp_value;
192 if ( $pageProperties != [] ) {
193 $this->cacheProperties( $pageID, $pageProperties );
194 $values[$pageID] = $pageProperties;
198 return $values;
202 * @param Title[]|Title $titles
203 * @return array array of good page IDs
205 private function getGoodIDs( $titles ) {
206 $result = [];
207 if ( is_array( $titles ) ) {
208 foreach ( $titles as $title ) {
209 $pageID = $title->getArticleID();
210 if ( $pageID > 0 ) {
211 $result[] = $pageID;
214 } else {
215 $pageID = $titles->getArticleID();
216 if ( $pageID > 0 ) {
217 $result[] = $pageID;
220 return $result;
224 * Get a property from the cache.
226 * @param int $pageID page ID of page being queried
227 * @param string $propertyName name of property being queried
228 * @return string|bool property value array or false if not found
230 private function getCachedProperty( $pageID, $propertyName ) {
231 if ( $this->cache->has( $pageID, $propertyName, self::CACHE_TTL ) ) {
232 return $this->cache->get( $pageID, $propertyName );
234 if ( $this->cache->has( 0, $pageID, self::CACHE_TTL ) ) {
235 $pageProperties = $this->cache->get( 0, $pageID );
236 if ( isset( $pageProperties[$propertyName] ) ) {
237 return $pageProperties[$propertyName];
240 return false;
244 * Get properties from the cache.
246 * @param int $pageID page ID of page being queried
247 * @return string|bool property value array or false if not found
249 private function getCachedProperties( $pageID ) {
250 if ( $this->cache->has( 0, $pageID, self::CACHE_TTL ) ) {
251 return $this->cache->get( 0, $pageID );
253 return false;
257 * Save a property to the cache.
259 * @param int $pageID page ID of page being cached
260 * @param string $propertyName name of property being cached
261 * @param mixed $propertyValue value of property
263 private function cacheProperty( $pageID, $propertyName, $propertyValue ) {
264 $this->cache->set( $pageID, $propertyName, $propertyValue );
268 * Save properties to the cache.
270 * @param int $pageID page ID of page being cached
271 * @param string[] $pageProperties associative array of page properties to be cached
273 private function cacheProperties( $pageID, $pageProperties ) {
274 $this->cache->clear( $pageID );
275 $this->cache->set( 0, $pageID, $pageProperties );