Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / site / SiteList.php
blob6feaece88417e4c493537d2ec671d11df53ad928
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
18 * @file
21 namespace MediaWiki\Site;
23 use ArrayObject;
24 use InvalidArgumentException;
26 /**
27 * Array-like collection of Site objects.
29 * This uses ArrayObject to intercept additions and deletions for purposes
30 * such as additional indexing, and to enforce that values are restricted
31 * to Site objects only.
33 * @since 1.21
34 * @ingroup Site
35 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
37 class SiteList extends ArrayObject {
38 /**
39 * @see SiteList::getNewOffset()
40 * @since 1.20
41 * @var int
43 protected $indexOffset = 0;
45 /**
46 * Internal site identifiers pointing to their sites offset value.
48 * @since 1.21
50 * @var array Maps int identifiers to local ArrayObject keys
52 protected $byInternalId = [];
54 /**
55 * Global site identifiers pointing to their sites offset value.
57 * @since 1.21
59 * @var array Maps string identifiers to local ArrayObject keys
61 protected $byGlobalId = [];
63 /**
64 * Navigational site identifiers alias inter-language prefixes
65 * pointing to their sites offset value.
67 * @since 1.23
69 * @var array Maps string identifiers to local ArrayObject keys
71 protected $byNavigationId = [];
73 /**
74 * @see Overrides ArrayObject::__construct https://www.php.net/manual/en/arrayobject.construct.php
75 * @since 1.20
76 * @param null|array $input
77 * @param int $flags
78 * @param string $iterator_class
80 public function __construct( $input = null, $flags = 0, $iterator_class = 'ArrayIterator' ) {
81 parent::__construct( [], $flags, $iterator_class );
83 if ( $input !== null ) {
84 foreach ( $input as $offset => $value ) {
85 $this->offsetSet( $offset, $value );
90 /**
91 * @see Overrides ArrayObject::append
92 * @since 1.20
93 * @param mixed $value
95 public function append( $value ): void {
96 $this->setElement( null, $value );
99 /**
100 * @since 1.20
101 * @see Overrides ArrayObject::offsetSet()
102 * @param mixed $index
103 * @param mixed $value
105 public function offsetSet( $index, $value ): void {
106 $this->setElement( $index, $value );
110 * Returns if the provided value has the same type as the elements
111 * that can be added to this ArrayObject.
113 * @since 1.20
114 * @param mixed $value
115 * @return bool
117 protected function hasValidType( $value ) {
118 $class = $this->getObjectType();
119 return $value instanceof $class;
123 * The class or interface type that array elements must match.
125 * @since 1.21
126 * @return string
128 public function getObjectType() {
129 return Site::class;
133 * Find a new offset for when appending an element.
135 * @since 1.20
136 * @return int
138 protected function getNewOffset() {
139 while ( $this->offsetExists( $this->indexOffset ) ) {
140 $this->indexOffset++;
143 return $this->indexOffset;
147 * Actually set the element and enforce type checking and offset resolving.
149 * @since 1.20
150 * @param int|string|null $index
151 * @param Site $site
153 protected function setElement( $index, $site ) {
154 if ( !$this->hasValidType( $site ) ) {
155 throw new InvalidArgumentException(
156 'Can only add ' . $this->getObjectType() . ' implementing objects to ' . static::class . '.'
160 $index ??= $this->getNewOffset();
162 if ( $this->hasSite( $site->getGlobalId() ) ) {
163 $this->removeSite( $site->getGlobalId() );
166 $this->byGlobalId[$site->getGlobalId()] = $index;
167 $this->byInternalId[$site->getInternalId()] = $index;
169 $ids = $site->getNavigationIds();
170 foreach ( $ids as $navId ) {
171 $this->byNavigationId[$navId] = $index;
174 parent::offsetSet( $index, $site );
178 * @see ArrayObject::offsetUnset()
180 * @since 1.21
182 * @param mixed $index
184 public function offsetUnset( $index ): void {
185 if ( $this->offsetExists( $index ) ) {
187 * @var Site $site
189 $site = $this->offsetGet( $index );
191 unset( $this->byGlobalId[$site->getGlobalId()] );
192 unset( $this->byInternalId[$site->getInternalId()] );
194 $ids = $site->getNavigationIds();
195 foreach ( $ids as $navId ) {
196 unset( $this->byNavigationId[$navId] );
200 parent::offsetUnset( $index );
204 * Returns all the global site identifiers.
205 * Optionally only those belonging to the specified group.
207 * @since 1.21
209 * @return array
211 public function getGlobalIdentifiers() {
212 return array_keys( $this->byGlobalId );
216 * Returns if the list contains the site with the provided global site identifier.
218 * @param string $globalSiteId
220 * @return bool
222 public function hasSite( $globalSiteId ) {
223 return array_key_exists( $globalSiteId, $this->byGlobalId );
227 * Returns the Site with the provided global site identifier.
228 * The site needs to exist, so if not sure, call hasGlobalId first.
230 * @since 1.21
232 * @param string $globalSiteId
234 * @return Site
236 public function getSite( $globalSiteId ) {
237 return $this->offsetGet( $this->byGlobalId[$globalSiteId] );
241 * Removes the site with the specified global site identifier.
242 * The site needs to exist, so if not sure, call hasGlobalId first.
244 * @since 1.21
246 * @param string $globalSiteId
248 public function removeSite( $globalSiteId ) {
249 $this->offsetUnset( $this->byGlobalId[$globalSiteId] );
253 * Whether the list contains no sites.
255 * @since 1.21
256 * @return bool
258 public function isEmpty() {
259 return $this->byGlobalId === [];
263 * Returns if the list contains the site with the provided site id.
265 * @param int $id
267 * @return bool
269 public function hasInternalId( $id ) {
270 return array_key_exists( $id, $this->byInternalId );
274 * Returns the Site with the provided site id.
275 * The site needs to exist, so if not sure, call has first.
277 * @since 1.21
279 * @param int $id
281 * @return Site
283 public function getSiteByInternalId( $id ) {
284 return $this->offsetGet( $this->byInternalId[$id] );
288 * Removes the site with the specified site id.
289 * The site needs to exist, so if not sure, call has first.
291 * @since 1.21
293 * @param int $id
295 public function removeSiteByInternalId( $id ) {
296 $this->offsetUnset( $this->byInternalId[$id] );
300 * Returns if the list contains the site with the provided navigational site id.
302 * @param string $id
304 * @return bool
306 public function hasNavigationId( $id ) {
307 return array_key_exists( $id, $this->byNavigationId );
311 * Returns the Site with the provided navigational site id.
312 * The site needs to exist, so if not sure, call has first.
314 * @since 1.23
316 * @param string $id
318 * @return Site
320 public function getSiteByNavigationId( $id ) {
321 return $this->offsetGet( $this->byNavigationId[$id] );
325 * Removes the site with the specified navigational site id.
326 * The site needs to exist, so if not sure, call has first.
328 * @since 1.23
330 * @param string $id
332 public function removeSiteByNavigationId( $id ) {
333 $this->offsetUnset( $this->byNavigationId[$id] );
337 * Sets a site in the list. If the site was not there,
338 * it will be added. If it was, it will be updated.
340 * @since 1.21
342 * @param Site $site
344 public function setSite( Site $site ) {
345 $this[] = $site;
349 * Returns the sites that are in the provided group.
351 * @since 1.21
353 * @param string $groupName
355 * @return SiteList
357 public function getGroup( $groupName ) {
358 $group = new self();
361 * @var Site $site
363 foreach ( $this as $site ) {
364 if ( $site->getGroup() === $groupName ) {
365 $group[] = $site;
369 return $group;
373 * A version ID that identifies the serialization structure used by __serialize()
374 * and unserialize(). This is useful for constructing cache keys in cases where the cache relies
375 * on serialization for storing the SiteList.
377 * @var string A string uniquely identifying the version of the serialization structure,
378 * not including any sub-structures.
380 private const SERIAL_VERSION_ID = '2014-03-17';
383 * Returns the version ID that identifies the serialization structure used by
384 * __serialize() and unserialize(), including the structure of any nested structures.
385 * This is useful for constructing cache keys in cases where the cache relies
386 * on serialization for storing the SiteList.
388 * @return string A string uniquely identifying the version of the serialization structure,
389 * including any sub-structures.
391 public static function getSerialVersionId() {
392 return self::SERIAL_VERSION_ID . '+Site:' . Site::SERIAL_VERSION_ID;
396 * @see Overrides Serializable::serialize
397 * @since 1.38
398 * @return array
400 public function __serialize(): array {
401 // Data that should go into serialization calls.
403 // NOTE: When changing the structure, either implement unserialize() to handle the
404 // old structure too, or update SERIAL_VERSION_ID to kill any caches.
405 return [
406 'data' => $this->getArrayCopy(),
407 'index' => $this->indexOffset,
408 'internalIds' => $this->byInternalId,
409 'globalIds' => $this->byGlobalId,
410 'navigationIds' => $this->byNavigationId,
415 * @see Overrides Serializable::unserialize
416 * @since 1.38
417 * @param array $serializationData
419 public function __unserialize( $serializationData ): void {
420 foreach ( $serializationData['data'] as $offset => $value ) {
421 // Just set the element, bypassing checks and offset resolving,
422 // as these elements have already gone through this.
423 parent::offsetSet( $offset, $value );
426 $this->indexOffset = $serializationData['index'];
428 $this->byInternalId = $serializationData['internalIds'];
429 $this->byGlobalId = $serializationData['globalIds'];
430 $this->byNavigationId = $serializationData['navigationIds'];
434 /** @deprecated class alias since 1.42 */
435 class_alias( SiteList::class, 'SiteList' );