Design improvements to sites code
[lhc/web/wiklou.git] / includes / site / SiteSQLStore.php
1 <?php
2
3 /**
4 * Represents the site configuration of a wiki.
5 * Holds a list of sites (ie SiteList) and takes care
6 * of retrieving and caching site information when appropriate.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * http://www.gnu.org/copyleft/gpl.html
22 *
23 * @since 1.21
24 *
25 * @file
26 * @ingroup Site
27 *
28 * @license GNU GPL v2+
29 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
30 */
31 class SiteSQLStore implements SiteStore {
32
33 /**
34 * @since 1.21
35 *
36 * @var SiteList|null
37 */
38 protected $sites = null;
39
40 /**
41 * @var ORMTable
42 */
43 protected $sitesTable;
44
45 /**
46 * @since 1.21
47 *
48 * @param ORMTable|null $sitesTable
49 *
50 * @return SiteStore
51 */
52 public static function newInstance( ORMTable $sitesTable = null ) {
53 return new static( $sitesTable );
54 }
55
56 /**
57 * Constructor.
58 *
59 * @since 1.21
60 *
61 * @param ORMTable|null $sitesTable
62 */
63 protected function __construct( ORMTable $sitesTable = null ) {
64 if ( $sitesTable === null ) {
65 $sitesTable = $this->newSitesTable();
66 }
67
68 $this->sitesTable = $sitesTable;
69 }
70
71 /**
72 * @see SiteStore::getSites
73 *
74 * @since 1.21
75 *
76 * @param string $source either 'cache' or 'recache'
77 *
78 * @return SiteList
79 */
80 public function getSites( $source = 'cache' ) {
81 if ( $source === 'cache' ) {
82 if ( $this->sites === null ) {
83 $cache = wfGetMainCache();
84 $sites = $cache->get( wfMemcKey( 'SiteList' ) );
85
86 if ( is_object( $sites ) ) {
87 $this->sites = $sites;
88 } else {
89 $this->loadSites();
90 }
91 }
92 }
93 else {
94 $this->loadSites();
95 }
96
97 return $this->sites;
98 }
99
100 /**
101 * Returns a new Site object constructed from the provided ORMRow.
102 *
103 * @since 1.21
104 *
105 * @param ORMRow $siteRow
106 *
107 * @return Site
108 */
109 protected function siteFromRow( ORMRow $siteRow ) {
110 $site = Site::newForType( $siteRow->getField( 'type', Site::TYPE_UNKNOWN ) );
111
112 $site->setGlobalId( $siteRow->getField( 'global_key' ) );
113
114 if ( $siteRow->hasField( 'forward' ) ) {
115 $site->setForward( $siteRow->getField( 'forward' ) );
116 }
117
118 if ( $siteRow->hasField( 'group' ) ) {
119 $site->setGroup( $siteRow->getField( 'group' ) );
120 }
121
122 if ( $siteRow->hasField( 'language' ) ) {
123 $site->setLanguageCode( $siteRow->getField( 'language' ) === '' ? null : $siteRow->getField( 'language' ) );
124 }
125
126 if ( $siteRow->hasField( 'source' ) ) {
127 $site->setSource( $siteRow->getField( 'source' ) );
128 }
129
130 if ( $siteRow->hasField( 'data' ) ) {
131 $site->setExtraData( $siteRow->getField( 'data' ) );
132 }
133
134 if ( $siteRow->hasField( 'config' ) ) {
135 $site->setExtraConfig( $siteRow->getField( 'config' ) );
136 }
137
138 return $site;
139 }
140
141 /**
142 * Fetches the site from the database and loads them into the sites field.
143 *
144 * @since 1.21
145 */
146 protected function loadSites() {
147 $this->sites = new SiteList();
148
149 foreach ( $this->sitesTable->select() as $siteRow ) {
150 $this->sites[] = $this->siteFromRow( $siteRow );
151 }
152
153 // Batch load the local site identifiers.
154 $ids = wfGetDB( $this->sitesTable->getReadDb() )->select(
155 'site_identifiers',
156 array(
157 'si_site',
158 'si_type',
159 'si_key',
160 ),
161 array(),
162 __METHOD__
163 );
164
165 foreach ( $ids as $id ) {
166 if ( $this->sites->hasInternalId( $id->si_site ) ) {
167 $site = $this->sites->getSiteByInternalId( $id->si_site );
168 $site->addLocalId( $id->si_type, $id->si_key );
169 $this->sites->setSite( $site );
170 }
171 }
172
173 $cache = wfGetMainCache();
174 $cache->set( wfMemcKey( 'SiteList' ), $this->sites );
175 }
176
177 /**
178 * @see SiteStore::getSite
179 *
180 * @since 1.21
181 *
182 * @param string $globalId
183 * @param string $source
184 *
185 * @return Site|null
186 */
187 public function getSite( $globalId, $source = 'cache' ) {
188 $sites = $this->getSites( $source );
189
190 return $sites->hasSite( $globalId ) ? $sites->getSite( $globalId ) : null;
191 }
192
193 /**
194 * @see SiteStore::saveSite
195 *
196 * @since 1.21
197 *
198 * @param Site $site
199 *
200 * @return boolean Success indicator
201 */
202 public function saveSite( Site $site ) {
203 return $this->saveSites( array( $site ) );
204 }
205
206 /**
207 * @see SiteStore::saveSites
208 *
209 * @since 1.21
210 *
211 * @param Site[] $sites
212 *
213 * @return boolean Success indicator
214 */
215 public function saveSites( array $sites ) {
216 if ( empty( $sites ) ) {
217 return true;
218 }
219
220 $dbw = $this->sitesTable->getWriteDbConnection();
221
222 $trx = $dbw->trxLevel();
223
224 if ( $trx == 0 ) {
225 $dbw->begin( __METHOD__ );
226 }
227
228 $success = true;
229
230 $internalIds = array();
231 $localIds = array();
232
233 foreach ( $sites as $site ) {
234 $fields = array(
235 // Site data
236 'global_key' => $site->getGlobalId(), // TODO: check not null
237 'type' => $site->getType(),
238 'group' => $site->getGroup(),
239 'source' => $site->getSource(),
240 'language' => $site->getLanguageCode() === null ? '' : $site->getLanguageCode(),
241 'protocol' => $site->getProtocol(),
242 'domain' => strrev( $site->getDomain() ) . '.',
243 'data' => $site->getExtraData(),
244
245 // Site config
246 'forward' => $site->shouldForward(),
247 'config' => $site->getExtraConfig(),
248 );
249
250 if ( $site->getInternalId() !== null ) {
251 $fields['id'] = $site->getInternalId();
252 $internalIds[] = $site->getInternalId();
253 }
254
255 $siteRow = new ORMRow( $this->sitesTable, $fields );
256 $success = $siteRow->save( __METHOD__ ) && $success;
257
258 foreach ( $site->getLocalIds() as $idType => $ids ) {
259 foreach ( $ids as $id ) {
260 $localIds[] = array( $siteRow->getId(), $idType, $id );
261 }
262 }
263 }
264
265 if ( $internalIds !== array() ) {
266 $dbw->delete(
267 'site_identifiers',
268 array( 'si_site' => $internalIds ),
269 __METHOD__
270 );
271 }
272
273 foreach ( $localIds as $localId ) {
274 $dbw->insert(
275 'site_identifiers',
276 array(
277 'si_site' => $localId[0],
278 'si_type' => $localId[1],
279 'si_key' => $localId[2],
280 ),
281 __METHOD__
282 );
283 }
284
285 if ( $trx == 0 ) {
286 $dbw->commit( __METHOD__ );
287 }
288
289 return $success;
290 }
291
292 /**
293 * @since 1.21
294 *
295 * @return ORMTable
296 */
297 protected function newSitesTable() {
298 return new ORMTable(
299 'sites',
300 array(
301 'id' => 'id',
302
303 // Site data
304 'global_key' => 'str',
305 'type' => 'str',
306 'group' => 'str',
307 'source' => 'str',
308 'language' => 'str',
309 'protocol' => 'str',
310 'domain' => 'str',
311 'data' => 'array',
312
313 // Site config
314 'forward' => 'bool',
315 'config' => 'array',
316 ),
317 array(
318 'type' => Site::TYPE_UNKNOWN,
319 'group' => Site::GROUP_NONE,
320 'source' => Site::SOURCE_LOCAL,
321 'data' => array(),
322
323 'forward' => false,
324 'config' => array(),
325 'language' => '',
326 ),
327 'ORMRow',
328 'site_'
329 );
330 }
331
332 }
333
334 /**
335 * @deprecated
336 */
337 class Sites extends SiteSQLStore {
338
339 /**
340 * Factory for creating new site objects.
341 *
342 * @since 1.21
343 * @deprecated
344 *
345 * @param string|boolean false $globalId
346 *
347 * @return Site
348 */
349 public static function newSite( $globalId = false ) {
350 $site = new Site();
351
352 if ( $globalId !== false ) {
353 $site->setGlobalId( $globalId );
354 }
355
356 return $site;
357 }
358
359 /**
360 * @deprecated
361 * @return SiteStore
362 */
363 public static function singleton() {
364 return new static();
365 }
366
367 /**
368 * @deprecated
369 * @return SiteList
370 */
371 public function getSiteGroup( $group ) {
372 return $this->getSites()->getGroup( $group );
373 }
374
375 }