MediaWiki  master
WikiMap.php
Go to the documentation of this file.
1 <?php
26 
30 class WikiMap {
31 
38  public static function getWiki( $wikiID ) {
39  $wikiReference = self::getWikiReferenceFromWgConf( $wikiID );
40  if ( $wikiReference ) {
41  return $wikiReference;
42  }
43 
44  // Try sites, if $wgConf failed
45  return self::getWikiWikiReferenceFromSites( $wikiID );
46  }
47 
52  private static function getWikiReferenceFromWgConf( $wikiID ) {
53  global $wgConf;
54 
55  $wgConf->loadFullData();
56 
57  [ $major, $minor ] = $wgConf->siteFromDB( $wikiID );
58  if ( $major === null ) {
59  return null;
60  }
61  $server = $wgConf->get( 'wgServer', $wikiID, $major,
62  [ 'lang' => $minor, 'site' => $major ] );
63 
64  $canonicalServer = $wgConf->get( 'wgCanonicalServer', $wikiID, $major,
65  [ 'lang' => $minor, 'site' => $major ] );
66  if ( $canonicalServer === false || $canonicalServer === null ) {
67  $canonicalServer = $server;
68  }
69 
70  $path = $wgConf->get( 'wgArticlePath', $wikiID, $major,
71  [ 'lang' => $minor, 'site' => $major ] );
72 
73  // If we don't have a canonical server or a path containing $1, the
74  // WikiReference isn't going to function properly. Just return null in
75  // that case.
76  if ( !is_string( $canonicalServer ) || !is_string( $path ) || strpos( $path, '$1' ) === false ) {
77  return null;
78  }
79 
80  return new WikiReference( $canonicalServer, $path, $server );
81  }
82 
87  private static function getWikiWikiReferenceFromSites( $wikiID ) {
88  $siteLookup = MediaWikiServices::getInstance()->getSiteLookup();
89  $site = $siteLookup->getSite( $wikiID );
90 
91  if ( !$site instanceof MediaWikiSite ) {
92  // Abort if not a MediaWikiSite, as this is about Wikis
93  return null;
94  }
95 
96  $urlParts = wfParseUrl( $site->getPageUrl() );
97  if ( $urlParts === false || !isset( $urlParts['path'] ) || !isset( $urlParts['host'] ) ) {
98  // We can't create a meaningful WikiReference without URLs
99  return null;
100  }
101 
102  // XXX: Check whether path contains a $1?
103  $path = $urlParts['path'];
104  if ( isset( $urlParts['query'] ) ) {
105  $path .= '?' . $urlParts['query'];
106  }
107 
108  $canonicalServer = $urlParts['scheme'] ?? 'http';
109  $canonicalServer .= '://' . $urlParts['host'];
110 
111  return new WikiReference( $canonicalServer, $path );
112  }
113 
121  public static function getWikiName( $wikiID ) {
122  $wiki = self::getWiki( $wikiID );
123  return $wiki ? $wiki->getDisplayName() : $wikiID;
124  }
125 
134  public static function foreignUserLink( $wikiID, $user, $text = null ) {
135  return self::makeForeignLink( $wikiID, "User:$user", $text );
136  }
137 
146  public static function makeForeignLink( $wikiID, $page, $text = null ) {
147  if ( !$text ) {
148  $text = $page;
149  }
150 
151  $url = self::getForeignURL( $wikiID, $page );
152  if ( $url === false ) {
153  return false;
154  }
155 
156  return Linker::makeExternalLink( $url, $text );
157  }
158 
168  public static function getForeignURL( $wikiID, $page, $fragmentId = null ) {
169  $wiki = self::getWiki( $wikiID );
170 
171  if ( $wiki ) {
172  return $wiki->getFullUrl( $page, $fragmentId );
173  }
174 
175  return false;
176  }
177 
185  public static function getCanonicalServerInfoForAllWikis() {
186  $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
187 
188  return $cache->getWithSetCallback(
189  $cache->makeGlobalKey( 'wikimap', 'canonical-urls' ),
190  $cache::TTL_DAY,
191  function () {
193 
194  $infoMap = [];
195  // Make sure at least the current wiki is set, for simple configurations.
196  // This also makes it the first in the map, which is useful for common cases.
197  $wikiId = self::getCurrentWikiId();
198  $infoMap[$wikiId] = [
199  'url' => $wgCanonicalServer,
200  'parts' => wfParseUrl( $wgCanonicalServer )
201  ];
202 
203  foreach ( $wgLocalDatabases as $wikiId ) {
204  $wikiReference = self::getWiki( $wikiId );
205  if ( $wikiReference ) {
206  $url = $wikiReference->getCanonicalServer();
207  $infoMap[$wikiId] = [ 'url' => $url, 'parts' => wfParseUrl( $url ) ];
208  }
209  }
210 
211  return $infoMap;
212  }
213  );
214  }
215 
221  public static function getWikiFromUrl( $url ) {
222  global $wgCanonicalServer;
223 
224  if ( strpos( $url, "$wgCanonicalServer/" ) === 0 ) {
225  // Optimisation: Handle the common case.
226  // (Duplicates self::getCanonicalServerInfoForAllWikis)
227  return self::getCurrentWikiId();
228  }
229 
230  $urlPartsCheck = wfParseUrl( $url );
231  if ( $urlPartsCheck === false ) {
232  return false;
233  }
234 
235  static $relevantKeys = [ 'host' => 1, 'port' => 1 ];
236  $urlPartsCheck = array_intersect_key( $urlPartsCheck, $relevantKeys );
237 
238  foreach ( self::getCanonicalServerInfoForAllWikis() as $wikiId => $info ) {
239  $urlParts = $info['parts'];
240  if ( $urlParts === false ) {
241  continue;
242  }
243 
244  $urlParts = array_intersect_key( $urlParts, $relevantKeys );
245  if ( $urlParts == $urlPartsCheck ) {
246  return $wikiId;
247  }
248  }
249 
250  return false;
251  }
252 
266  public static function getWikiIdFromDbDomain( $domain ) {
267  $domain = DatabaseDomain::newFromId( $domain );
268  // Since the schema was not always part of the wiki ID, try to maintain backwards
269  // compatibility with some common cases. Assume that if the DB domain schema is just
270  // the installer default then it is probably the case that the schema is the same for
271  // all wikis in the farm. Historically, any wiki farm had to make the database/prefix
272  // combination unique per wiki. Omit the schema if it does not seem wiki specific.
273  if ( !in_array( $domain->getSchema(), [ null, 'mediawiki' ], true ) ) {
274  // This means a site admin may have specifically tailored the schemas.
275  // Domain IDs might use the form <DB>-<project>- or <DB>-<project>-<language>_,
276  // meaning that the schema portion must be accounted for to disambiguate wikis.
277  return "{$domain->getDatabase()}-{$domain->getSchema()}-{$domain->getTablePrefix()}";
278  }
279  // Note that if this wiki ID is passed as a domain ID to LoadBalancer, then it can
280  // handle the schema by assuming the generic "mediawiki" schema if needed.
281  return strlen( $domain->getTablePrefix() )
282  ? "{$domain->getDatabase()}-{$domain->getTablePrefix()}"
283  : (string)$domain->getDatabase();
284  }
285 
290  public static function getCurrentWikiDbDomain() {
292  // Avoid invoking LBFactory to avoid any chance of recursion
293  return new DatabaseDomain( $wgDBname, $wgDBmwschema, (string)$wgDBprefix );
294  }
295 
300  public static function getCurrentWikiId() {
301  return self::getWikiIdFromDbDomain( self::getCurrentWikiDbDomain() );
302  }
303 
309  public static function isCurrentWikiDbDomain( $domain ) {
310  return self::getCurrentWikiDbDomain()->equals( $domain );
311  }
312 
318  public static function isCurrentWikiId( $wikiId ) {
319  return ( self::getCurrentWikiId() === $wikiId );
320  }
321 }
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
$wgConf
$wgConf hold the site configuration.
Definition: Setup.php:139
Class representing a MediaWiki site.
Some internal bits split of from Skin.php.
Definition: Linker.php:65
Service locator for MediaWiki core services.
Helper tools for dealing with other locally-hosted wikis.
Definition: WikiMap.php:30
static makeForeignLink( $wikiID, $page, $text=null)
Convenience to get a link to a page on a foreign wiki.
Definition: WikiMap.php:146
static getCanonicalServerInfoForAllWikis()
Get canonical server info for all local wikis in the map that have one.
Definition: WikiMap.php:185
static getCurrentWikiId()
Definition: WikiMap.php:300
static getWikiIdFromDbDomain( $domain)
Get the wiki ID of a database domain.
Definition: WikiMap.php:266
static getWiki( $wikiID)
Get a WikiReference object for $wikiID.
Definition: WikiMap.php:38
static isCurrentWikiId( $wikiId)
Definition: WikiMap.php:318
static getWikiName( $wikiID)
Convenience to get the wiki's display name.
Definition: WikiMap.php:121
static getCurrentWikiDbDomain()
Definition: WikiMap.php:290
static foreignUserLink( $wikiID, $user, $text=null)
Convenience to get a link to a user page on a foreign wiki.
Definition: WikiMap.php:134
static getWikiFromUrl( $url)
Definition: WikiMap.php:221
static getForeignURL( $wikiID, $page, $fragmentId=null)
Convenience to get a url to a page on a foreign wiki.
Definition: WikiMap.php:168
static isCurrentWikiDbDomain( $domain)
Definition: WikiMap.php:309
Reference to a locally-hosted wiki.
Class to handle database/schema/prefix specifications for IDatabase.
$wgDBprefix
Config variable stub for the DBprefix setting, for use by phpdoc and IDEs.
$wgLocalDatabases
Config variable stub for the LocalDatabases setting, for use by phpdoc and IDEs.
$wgDBmwschema
Config variable stub for the DBmwschema setting, for use by phpdoc and IDEs.
$wgDBname
Config variable stub for the DBname setting, for use by phpdoc and IDEs.
$wgCanonicalServer
Config variable stub for the CanonicalServer setting, for use by phpdoc and IDEs.
Definition: config-vars.php:31