]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/site/DBSiteStore.php
MediaWiki 1.30.2
[autoinstalls/mediawiki.git] / includes / site / DBSiteStore.php
1 <?php
2
3 use Wikimedia\Rdbms\LoadBalancer;
4
5 /**
6  * Represents the site configuration of a wiki.
7  * Holds a list of sites (ie SiteList), stored in the database.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  * http://www.gnu.org/copyleft/gpl.html
23  *
24  * @since 1.25
25  *
26  * @file
27  * @ingroup Site
28  *
29  * @license GNU GPL v2+
30  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
31  * @author Daniel Kinzler
32  */
33 class DBSiteStore implements SiteStore {
34
35         /**
36          * @var SiteList|null
37          */
38         protected $sites = null;
39
40         /**
41          * @var LoadBalancer
42          */
43         private $dbLoadBalancer;
44
45         /**
46          * @since 1.27
47          *
48          * @todo: inject some kind of connection manager that is aware of the target wiki,
49          * instead of injecting a LoadBalancer.
50          *
51          * @param LoadBalancer $dbLoadBalancer
52          */
53         public function __construct( LoadBalancer $dbLoadBalancer ) {
54                 $this->dbLoadBalancer = $dbLoadBalancer;
55         }
56
57         /**
58          * @see SiteStore::getSites
59          *
60          * @since 1.25
61          *
62          * @return SiteList
63          */
64         public function getSites() {
65                 $this->loadSites();
66
67                 return $this->sites;
68         }
69
70         /**
71          * Fetches the site from the database and loads them into the sites field.
72          *
73          * @since 1.25
74          */
75         protected function loadSites() {
76                 $this->sites = new SiteList();
77
78                 $dbr = $this->dbLoadBalancer->getConnection( DB_REPLICA );
79
80                 $res = $dbr->select(
81                         'sites',
82                         [
83                                 'site_id',
84                                 'site_global_key',
85                                 'site_type',
86                                 'site_group',
87                                 'site_source',
88                                 'site_language',
89                                 'site_protocol',
90                                 'site_domain',
91                                 'site_data',
92                                 'site_forward',
93                                 'site_config',
94                         ],
95                         '',
96                         __METHOD__,
97                         [ 'ORDER BY' => 'site_global_key' ]
98                 );
99
100                 foreach ( $res as $row ) {
101                         $site = Site::newForType( $row->site_type );
102                         $site->setGlobalId( $row->site_global_key );
103                         $site->setInternalId( (int)$row->site_id );
104                         $site->setForward( (bool)$row->site_forward );
105                         $site->setGroup( $row->site_group );
106                         $site->setLanguageCode( $row->site_language === ''
107                                 ? null
108                                 : $row->site_language
109                         );
110                         $site->setSource( $row->site_source );
111                         $site->setExtraData( unserialize( $row->site_data ) );
112                         $site->setExtraConfig( unserialize( $row->site_config ) );
113                         $this->sites[] = $site;
114                 }
115
116                 // Batch load the local site identifiers.
117                 $ids = $dbr->select(
118                         'site_identifiers',
119                         [
120                                 'si_site',
121                                 'si_type',
122                                 'si_key',
123                         ],
124                         [],
125                         __METHOD__
126                 );
127
128                 foreach ( $ids as $id ) {
129                         if ( $this->sites->hasInternalId( $id->si_site ) ) {
130                                 $site = $this->sites->getSiteByInternalId( $id->si_site );
131                                 $site->addLocalId( $id->si_type, $id->si_key );
132                                 $this->sites->setSite( $site );
133                         }
134                 }
135         }
136
137         /**
138          * @see SiteStore::getSite
139          *
140          * @since 1.25
141          *
142          * @param string $globalId
143          *
144          * @return Site|null
145          */
146         public function getSite( $globalId ) {
147                 if ( $this->sites === null ) {
148                         $this->sites = $this->getSites();
149                 }
150
151                 return $this->sites->hasSite( $globalId ) ? $this->sites->getSite( $globalId ) : null;
152         }
153
154         /**
155          * @see SiteStore::saveSite
156          *
157          * @since 1.25
158          *
159          * @param Site $site
160          *
161          * @return bool Success indicator
162          */
163         public function saveSite( Site $site ) {
164                 return $this->saveSites( [ $site ] );
165         }
166
167         /**
168          * @see SiteStore::saveSites
169          *
170          * @since 1.25
171          *
172          * @param Site[] $sites
173          *
174          * @return bool Success indicator
175          */
176         public function saveSites( array $sites ) {
177                 if ( empty( $sites ) ) {
178                         return true;
179                 }
180
181                 $dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
182
183                 $dbw->startAtomic( __METHOD__ );
184
185                 $success = true;
186
187                 $internalIds = [];
188                 $localIds = [];
189
190                 foreach ( $sites as $site ) {
191                         if ( $site->getInternalId() !== null ) {
192                                 $internalIds[] = $site->getInternalId();
193                         }
194
195                         $fields = [
196                                 // Site data
197                                 'site_global_key' => $site->getGlobalId(), // TODO: check not null
198                                 'site_type' => $site->getType(),
199                                 'site_group' => $site->getGroup(),
200                                 'site_source' => $site->getSource(),
201                                 'site_language' => $site->getLanguageCode() === null ? '' : $site->getLanguageCode(),
202                                 'site_protocol' => $site->getProtocol(),
203                                 'site_domain' => strrev( $site->getDomain() ) . '.',
204                                 'site_data' => serialize( $site->getExtraData() ),
205
206                                 // Site config
207                                 'site_forward' => $site->shouldForward() ? 1 : 0,
208                                 'site_config' => serialize( $site->getExtraConfig() ),
209                         ];
210
211                         $rowId = $site->getInternalId();
212                         if ( $rowId !== null ) {
213                                 $success = $dbw->update(
214                                         'sites', $fields, [ 'site_id' => $rowId ], __METHOD__
215                                 ) && $success;
216                         } else {
217                                 $success = $dbw->insert( 'sites', $fields, __METHOD__ ) && $success;
218                                 $rowId = $dbw->insertId();
219                         }
220
221                         foreach ( $site->getLocalIds() as $idType => $ids ) {
222                                 foreach ( $ids as $id ) {
223                                         $localIds[] = [ $rowId, $idType, $id ];
224                                 }
225                         }
226                 }
227
228                 if ( $internalIds !== [] ) {
229                         $dbw->delete(
230                                 'site_identifiers',
231                                 [ 'si_site' => $internalIds ],
232                                 __METHOD__
233                         );
234                 }
235
236                 foreach ( $localIds as $localId ) {
237                         $dbw->insert(
238                                 'site_identifiers',
239                                 [
240                                         'si_site' => $localId[0],
241                                         'si_type' => $localId[1],
242                                         'si_key' => $localId[2],
243                                 ],
244                                 __METHOD__
245                         );
246                 }
247
248                 $dbw->endAtomic( __METHOD__ );
249
250                 $this->reset();
251
252                 return $success;
253         }
254
255         /**
256          * Resets the SiteList
257          *
258          * @since 1.25
259          */
260         public function reset() {
261                 $this->sites = null;
262         }
263
264         /**
265          * Clears the list of sites stored in the database.
266          *
267          * @see SiteStore::clear()
268          *
269          * @return bool Success
270          */
271         public function clear() {
272                 $dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
273
274                 $dbw->startAtomic( __METHOD__ );
275                 $ok = $dbw->delete( 'sites', '*', __METHOD__ );
276                 $ok = $dbw->delete( 'site_identifiers', '*', __METHOD__ ) && $ok;
277                 $dbw->endAtomic( __METHOD__ );
278
279                 $this->reset();
280
281                 return $ok;
282         }
283
284 }