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