]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/site/Site.php
MediaWiki 1.30.2
[autoinstalls/mediawiki.git] / includes / site / Site.php
1 <?php
2
3 /**
4  * Represents a single site.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  * http://www.gnu.org/copyleft/gpl.html
20  *
21  * @since 1.21
22  *
23  * @file
24  * @ingroup Site
25  *
26  * @license GNU GPL v2+
27  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
28  */
29 class Site implements Serializable {
30         const TYPE_UNKNOWN = 'unknown';
31         const TYPE_MEDIAWIKI = 'mediawiki';
32
33         const GROUP_NONE = 'none';
34
35         const ID_INTERWIKI = 'interwiki';
36         const ID_EQUIVALENT = 'equivalent';
37
38         const SOURCE_LOCAL = 'local';
39
40         const PATH_LINK = 'link';
41
42         /**
43          * A version ID that identifies the serialization structure used by getSerializationData()
44          * and unserialize(). This is useful for constructing cache keys in cases where the cache relies
45          * on serialization for storing the SiteList.
46          *
47          * @var string A string uniquely identifying the version of the serialization structure.
48          */
49         const SERIAL_VERSION_ID = '2013-01-23';
50
51         /**
52          * @since 1.21
53          *
54          * @var string|null
55          */
56         protected $globalId = null;
57
58         /**
59          * @since 1.21
60          *
61          * @var string
62          */
63         protected $type = self::TYPE_UNKNOWN;
64
65         /**
66          * @since 1.21
67          *
68          * @var string
69          */
70         protected $group = self::GROUP_NONE;
71
72         /**
73          * @since 1.21
74          *
75          * @var string
76          */
77         protected $source = self::SOURCE_LOCAL;
78
79         /**
80          * @since 1.21
81          *
82          * @var string|null
83          */
84         protected $languageCode = null;
85
86         /**
87          * Holds the local ids for this site.
88          * local id type => [ ids for this type (strings) ]
89          *
90          * @since 1.21
91          *
92          * @var array[]
93          */
94         protected $localIds = [];
95
96         /**
97          * @since 1.21
98          *
99          * @var array
100          */
101         protected $extraData = [];
102
103         /**
104          * @since 1.21
105          *
106          * @var array
107          */
108         protected $extraConfig = [];
109
110         /**
111          * @since 1.21
112          *
113          * @var bool
114          */
115         protected $forward = false;
116
117         /**
118          * @since 1.21
119          *
120          * @var int|null
121          */
122         protected $internalId = null;
123
124         /**
125          * @since 1.21
126          *
127          * @param string $type
128          */
129         public function __construct( $type = self::TYPE_UNKNOWN ) {
130                 $this->type = $type;
131         }
132
133         /**
134          * Returns the global site identifier (ie enwiktionary).
135          *
136          * @since 1.21
137          *
138          * @return string|null
139          */
140         public function getGlobalId() {
141                 return $this->globalId;
142         }
143
144         /**
145          * Sets the global site identifier (ie enwiktionary).
146          *
147          * @since 1.21
148          *
149          * @param string|null $globalId
150          *
151          * @throws MWException
152          */
153         public function setGlobalId( $globalId ) {
154                 if ( $globalId !== null && !is_string( $globalId ) ) {
155                         throw new MWException( '$globalId needs to be string or null' );
156                 }
157
158                 $this->globalId = $globalId;
159         }
160
161         /**
162          * Returns the type of the site (ie mediawiki).
163          *
164          * @since 1.21
165          *
166          * @return string
167          */
168         public function getType() {
169                 return $this->type;
170         }
171
172         /**
173          * Gets the group of the site (ie wikipedia).
174          *
175          * @since 1.21
176          *
177          * @return string
178          */
179         public function getGroup() {
180                 return $this->group;
181         }
182
183         /**
184          * Sets the group of the site (ie wikipedia).
185          *
186          * @since 1.21
187          *
188          * @param string $group
189          *
190          * @throws MWException
191          */
192         public function setGroup( $group ) {
193                 if ( !is_string( $group ) ) {
194                         throw new MWException( '$group needs to be a string' );
195                 }
196
197                 $this->group = $group;
198         }
199
200         /**
201          * Returns the source of the site data (ie 'local', 'wikidata', 'my-magical-repo').
202          *
203          * @since 1.21
204          *
205          * @return string
206          */
207         public function getSource() {
208                 return $this->source;
209         }
210
211         /**
212          * Sets the source of the site data (ie 'local', 'wikidata', 'my-magical-repo').
213          *
214          * @since 1.21
215          *
216          * @param string $source
217          *
218          * @throws MWException
219          */
220         public function setSource( $source ) {
221                 if ( !is_string( $source ) ) {
222                         throw new MWException( '$source needs to be a string' );
223                 }
224
225                 $this->source = $source;
226         }
227
228         /**
229          * Gets if site.tld/path/key:pageTitle should forward users to  the page on
230          * the actual site, where "key" is the local identifier.
231          *
232          * @since 1.21
233          *
234          * @return bool
235          */
236         public function shouldForward() {
237                 return $this->forward;
238         }
239
240         /**
241          * Sets if site.tld/path/key:pageTitle should forward users to  the page on
242          * the actual site, where "key" is the local identifier.
243          *
244          * @since 1.21
245          *
246          * @param bool $shouldForward
247          *
248          * @throws MWException
249          */
250         public function setForward( $shouldForward ) {
251                 if ( !is_bool( $shouldForward ) ) {
252                         throw new MWException( '$shouldForward needs to be a boolean' );
253                 }
254
255                 $this->forward = $shouldForward;
256         }
257
258         /**
259          * Returns the domain of the site, ie en.wikipedia.org
260          * Or false if it's not known.
261          *
262          * @since 1.21
263          *
264          * @return string|null
265          */
266         public function getDomain() {
267                 $path = $this->getLinkPath();
268
269                 if ( $path === null ) {
270                         return null;
271                 }
272
273                 return parse_url( $path, PHP_URL_HOST );
274         }
275
276         /**
277          * Returns the protocol of the site.
278          *
279          * @since 1.21
280          *
281          * @throws MWException
282          * @return string
283          */
284         public function getProtocol() {
285                 $path = $this->getLinkPath();
286
287                 if ( $path === null ) {
288                         return '';
289                 }
290
291                 $protocol = parse_url( $path, PHP_URL_SCHEME );
292
293                 // Malformed URL
294                 if ( $protocol === false ) {
295                         throw new MWException( "failed to parse URL '$path'" );
296                 }
297
298                 // No schema
299                 if ( $protocol === null ) {
300                         // Used for protocol relative URLs
301                         $protocol = '';
302                 }
303
304                 return $protocol;
305         }
306
307         /**
308          * Sets the path used to construct links with.
309          * Shall be equivalent to setPath( getLinkPathType(), $fullUrl ).
310          *
311          * @param string $fullUrl
312          *
313          * @since 1.21
314          *
315          * @throws MWException
316          */
317         public function setLinkPath( $fullUrl ) {
318                 $type = $this->getLinkPathType();
319
320                 if ( $type === null ) {
321                         throw new MWException( "This Site does not support link paths." );
322                 }
323
324                 $this->setPath( $type, $fullUrl );
325         }
326
327         /**
328          * Returns the path used to construct links with or false if there is no such path.
329          *
330          * Shall be equivalent to getPath( getLinkPathType() ).
331          *
332          * @return string|null
333          */
334         public function getLinkPath() {
335                 $type = $this->getLinkPathType();
336                 return $type === null ? null : $this->getPath( $type );
337         }
338
339         /**
340          * Returns the main path type, that is the type of the path that should
341          * generally be used to construct links to the target site.
342          *
343          * This default implementation returns Site::PATH_LINK as the default path
344          * type. Subclasses can override this to define a different default path
345          * type, or return false to disable site links.
346          *
347          * @since 1.21
348          *
349          * @return string|null
350          */
351         public function getLinkPathType() {
352                 return self::PATH_LINK;
353         }
354
355         /**
356          * Returns the full URL for the given page on the site.
357          * Or false if the needed information is not known.
358          *
359          * This generated URL is usually based upon the path returned by getLinkPath(),
360          * but this is not a requirement.
361          *
362          * This implementation returns a URL constructed using the path returned by getLinkPath().
363          *
364          * @since 1.21
365          *
366          * @param bool|string $pageName
367          *
368          * @return string|bool
369          */
370         public function getPageUrl( $pageName = false ) {
371                 $url = $this->getLinkPath();
372
373                 if ( $url === false ) {
374                         return false;
375                 }
376
377                 if ( $pageName !== false ) {
378                         $url = str_replace( '$1', rawurlencode( $pageName ), $url );
379                 }
380
381                 return $url;
382         }
383
384         /**
385          * Returns $pageName without changes.
386          * Subclasses may override this to apply some kind of normalization.
387          *
388          * @see Site::normalizePageName
389          *
390          * @since 1.21
391          *
392          * @param string $pageName
393          *
394          * @return string
395          */
396         public function normalizePageName( $pageName ) {
397                 return $pageName;
398         }
399
400         /**
401          * Returns the type specific fields.
402          *
403          * @since 1.21
404          *
405          * @return array
406          */
407         public function getExtraData() {
408                 return $this->extraData;
409         }
410
411         /**
412          * Sets the type specific fields.
413          *
414          * @since 1.21
415          *
416          * @param array $extraData
417          */
418         public function setExtraData( array $extraData ) {
419                 $this->extraData = $extraData;
420         }
421
422         /**
423          * Returns the type specific config.
424          *
425          * @since 1.21
426          *
427          * @return array
428          */
429         public function getExtraConfig() {
430                 return $this->extraConfig;
431         }
432
433         /**
434          * Sets the type specific config.
435          *
436          * @since 1.21
437          *
438          * @param array $extraConfig
439          */
440         public function setExtraConfig( array $extraConfig ) {
441                 $this->extraConfig = $extraConfig;
442         }
443
444         /**
445          * Returns language code of the sites primary language.
446          * Or null if it's not known.
447          *
448          * @since 1.21
449          *
450          * @return string|null
451          */
452         public function getLanguageCode() {
453                 return $this->languageCode;
454         }
455
456         /**
457          * Sets language code of the sites primary language.
458          *
459          * @since 1.21
460          *
461          * @param string $languageCode
462          */
463         public function setLanguageCode( $languageCode ) {
464                 if ( !Language::isValidCode( $languageCode ) ) {
465                         throw new InvalidArgumentException( "$languageCode is not a valid language code." );
466                 }
467                 $this->languageCode = $languageCode;
468         }
469
470         /**
471          * Returns the set internal identifier for the site.
472          *
473          * @since 1.21
474          *
475          * @return string|null
476          */
477         public function getInternalId() {
478                 return $this->internalId;
479         }
480
481         /**
482          * Sets the internal identifier for the site.
483          * This typically is a primary key in a db table.
484          *
485          * @since 1.21
486          *
487          * @param int|null $internalId
488          */
489         public function setInternalId( $internalId = null ) {
490                 $this->internalId = $internalId;
491         }
492
493         /**
494          * Adds a local identifier.
495          *
496          * @since 1.21
497          *
498          * @param string $type
499          * @param string $identifier
500          */
501         public function addLocalId( $type, $identifier ) {
502                 if ( $this->localIds === false ) {
503                         $this->localIds = [];
504                 }
505
506                 if ( !array_key_exists( $type, $this->localIds ) ) {
507                         $this->localIds[$type] = [];
508                 }
509
510                 if ( !in_array( $identifier, $this->localIds[$type] ) ) {
511                         $this->localIds[$type][] = $identifier;
512                 }
513         }
514
515         /**
516          * Adds an interwiki id to the site.
517          *
518          * @since 1.21
519          *
520          * @param string $identifier
521          */
522         public function addInterwikiId( $identifier ) {
523                 $this->addLocalId( self::ID_INTERWIKI, $identifier );
524         }
525
526         /**
527          * Adds a navigation id to the site.
528          *
529          * @since 1.21
530          *
531          * @param string $identifier
532          */
533         public function addNavigationId( $identifier ) {
534                 $this->addLocalId( self::ID_EQUIVALENT, $identifier );
535         }
536
537         /**
538          * Returns the interwiki link identifiers that can be used for this site.
539          *
540          * @since 1.21
541          *
542          * @return string[]
543          */
544         public function getInterwikiIds() {
545                 return array_key_exists( self::ID_INTERWIKI, $this->localIds )
546                         ? $this->localIds[self::ID_INTERWIKI]
547                         : [];
548         }
549
550         /**
551          * Returns the equivalent link identifiers that can be used to make
552          * the site show up in interfaces such as the "language links" section.
553          *
554          * @since 1.21
555          *
556          * @return string[]
557          */
558         public function getNavigationIds() {
559                 return array_key_exists( self::ID_EQUIVALENT, $this->localIds )
560                         ? $this->localIds[self::ID_EQUIVALENT] :
561                         [];
562         }
563
564         /**
565          * Returns all local ids
566          *
567          * @since 1.21
568          *
569          * @return array[]
570          */
571         public function getLocalIds() {
572                 return $this->localIds;
573         }
574
575         /**
576          * Sets the path used to construct links with.
577          * Shall be equivalent to setPath( getLinkPathType(), $fullUrl ).
578          *
579          * @since 1.21
580          *
581          * @param string $pathType
582          * @param string $fullUrl
583          *
584          * @throws MWException
585          */
586         public function setPath( $pathType, $fullUrl ) {
587                 if ( !is_string( $fullUrl ) ) {
588                         throw new MWException( '$fullUrl needs to be a string' );
589                 }
590
591                 if ( !array_key_exists( 'paths', $this->extraData ) ) {
592                         $this->extraData['paths'] = [];
593                 }
594
595                 $this->extraData['paths'][$pathType] = $fullUrl;
596         }
597
598         /**
599          * Returns the path of the provided type or false if there is no such path.
600          *
601          * @since 1.21
602          *
603          * @param string $pathType
604          *
605          * @return string|null
606          */
607         public function getPath( $pathType ) {
608                 $paths = $this->getAllPaths();
609                 return array_key_exists( $pathType, $paths ) ? $paths[$pathType] : null;
610         }
611
612         /**
613          * Returns the paths as associative array.
614          * The keys are path types, the values are the path urls.
615          *
616          * @since 1.21
617          *
618          * @return string[]
619          */
620         public function getAllPaths() {
621                 return array_key_exists( 'paths', $this->extraData ) ? $this->extraData['paths'] : [];
622         }
623
624         /**
625          * Removes the path of the provided type if it's set.
626          *
627          * @since 1.21
628          *
629          * @param string $pathType
630          */
631         public function removePath( $pathType ) {
632                 if ( array_key_exists( 'paths', $this->extraData ) ) {
633                         unset( $this->extraData['paths'][$pathType] );
634                 }
635         }
636
637         /**
638          * @since 1.21
639          *
640          * @param string $siteType
641          *
642          * @return Site
643          */
644         public static function newForType( $siteType ) {
645                 global $wgSiteTypes;
646
647                 if ( array_key_exists( $siteType, $wgSiteTypes ) ) {
648                         return new $wgSiteTypes[$siteType]();
649                 }
650
651                 return new Site();
652         }
653
654         /**
655          * @see Serializable::serialize
656          *
657          * @since 1.21
658          *
659          * @return string
660          */
661         public function serialize() {
662                 $fields = [
663                         'globalid' => $this->globalId,
664                         'type' => $this->type,
665                         'group' => $this->group,
666                         'source' => $this->source,
667                         'language' => $this->languageCode,
668                         'localids' => $this->localIds,
669                         'config' => $this->extraConfig,
670                         'data' => $this->extraData,
671                         'forward' => $this->forward,
672                         'internalid' => $this->internalId,
673
674                 ];
675
676                 return serialize( $fields );
677         }
678
679         /**
680          * @see Serializable::unserialize
681          *
682          * @since 1.21
683          *
684          * @param string $serialized
685          */
686         public function unserialize( $serialized ) {
687                 $fields = unserialize( $serialized );
688
689                 $this->__construct( $fields['type'] );
690
691                 $this->setGlobalId( $fields['globalid'] );
692                 $this->setGroup( $fields['group'] );
693                 $this->setSource( $fields['source'] );
694                 $this->setLanguageCode( $fields['language'] );
695                 $this->localIds = $fields['localids'];
696                 $this->setExtraConfig( $fields['config'] );
697                 $this->setExtraData( $fields['data'] );
698                 $this->setForward( $fields['forward'] );
699                 $this->setInternalId( $fields['internalid'] );
700         }
701 }