MediaWiki  master
WikiMap.php
Go to the documentation of this file.
1 <?php
25 
29 class WikiMap {
30 
37  public static function getWiki( $wikiID ) {
38  $wikiReference = self::getWikiReferenceFromWgConf( $wikiID );
39  if ( $wikiReference ) {
40  return $wikiReference;
41  }
42 
43  // Try sites, if $wgConf failed
44  return self::getWikiWikiReferenceFromSites( $wikiID );
45  }
46 
51  private static function getWikiReferenceFromWgConf( $wikiID ) {
52  global $wgConf;
53 
54  $wgConf->loadFullData();
55 
56  list( $major, $minor ) = $wgConf->siteFromDB( $wikiID );
57  if ( $major === null ) {
58  return null;
59  }
60  $server = $wgConf->get( 'wgServer', $wikiID, $major,
61  [ 'lang' => $minor, 'site' => $major ] );
62 
63  $canonicalServer = $wgConf->get( 'wgCanonicalServer', $wikiID, $major,
64  [ 'lang' => $minor, 'site' => $major ] );
65  if ( $canonicalServer === false || $canonicalServer === null ) {
66  $canonicalServer = $server;
67  }
68 
69  $path = $wgConf->get( 'wgArticlePath', $wikiID, $major,
70  [ 'lang' => $minor, 'site' => $major ] );
71 
72  // If we don't have a canonical server or a path containing $1, the
73  // WikiReference isn't going to function properly. Just return null in
74  // that case.
75  if ( !is_string( $canonicalServer ) || !is_string( $path ) || strpos( $path, '$1' ) === false ) {
76  return null;
77  }
78 
79  return new WikiReference( $canonicalServer, $path, $server );
80  }
81 
86  private static function getWikiWikiReferenceFromSites( $wikiID ) {
87  $siteLookup = MediaWikiServices::getInstance()->getSiteLookup();
88  $site = $siteLookup->getSite( $wikiID );
89 
90  if ( !$site instanceof MediaWikiSite ) {
91  // Abort if not a MediaWikiSite, as this is about Wikis
92  return null;
93  }
94 
95  $urlParts = wfParseUrl( $site->getPageUrl() );
96  if ( $urlParts === false || !isset( $urlParts['path'] ) || !isset( $urlParts['host'] ) ) {
97  // We can't create a meaningful WikiReference without URLs
98  return null;
99  }
100 
101  // XXX: Check whether path contains a $1?
102  $path = $urlParts['path'];
103  if ( isset( $urlParts['query'] ) ) {
104  $path .= '?' . $urlParts['query'];
105  }
106 
107  $canonicalServer = $urlParts['scheme'] ?? 'http';
108  $canonicalServer .= '://' . $urlParts['host'];
109 
110  return new WikiReference( $canonicalServer, $path );
111  }
112 
120  public static function getWikiName( $wikiID ) {
121  $wiki = self::getWiki( $wikiID );
122 
123  if ( $wiki ) {
124  return $wiki->getDisplayName();
125  }
126  return $wikiID;
127  }
128 
137  public static function foreignUserLink( $wikiID, $user, $text = null ) {
138  return self::makeForeignLink( $wikiID, "User:$user", $text );
139  }
140 
149  public static function makeForeignLink( $wikiID, $page, $text = null ) {
150  if ( !$text ) {
151  $text = $page;
152  }
153 
154  $url = self::getForeignURL( $wikiID, $page );
155  if ( $url === false ) {
156  return false;
157  }
158 
159  return Linker::makeExternalLink( $url, $text );
160  }
161 
171  public static function getForeignURL( $wikiID, $page, $fragmentId = null ) {
172  $wiki = self::getWiki( $wikiID );
173 
174  if ( $wiki ) {
175  return $wiki->getFullUrl( $page, $fragmentId );
176  }
177 
178  return false;
179  }
180 
188  public static function getCanonicalServerInfoForAllWikis() {
189  $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
190 
191  return $cache->getWithSetCallback(
192  $cache->makeGlobalKey( 'wikimap', 'canonical-urls' ),
193  $cache::TTL_DAY,
194  function () {
196 
197  $infoMap = [];
198  // Make sure at least the current wiki is set, for simple configurations.
199  // This also makes it the first in the map, which is useful for common cases.
200  $wikiId = self::getWikiIdFromDbDomain( self::getCurrentWikiDbDomain() );
201  $infoMap[$wikiId] = [
202  'url' => $wgCanonicalServer,
203  'parts' => wfParseUrl( $wgCanonicalServer )
204  ];
205 
206  foreach ( $wgLocalDatabases as $wikiId ) {
207  $wikiReference = self::getWiki( $wikiId );
208  if ( $wikiReference ) {
209  $url = $wikiReference->getCanonicalServer();
210  $infoMap[$wikiId] = [ 'url' => $url, 'parts' => wfParseUrl( $url ) ];
211  }
212  }
213 
214  return $infoMap;
215  }
216  );
217  }
218 
224  public static function getWikiFromUrl( $url ) {
225  global $wgCanonicalServer;
226 
227  if ( strpos( $url, "$wgCanonicalServer/" ) === 0 ) {
228  // Optimisation: Handle the the common case.
229  // (Duplicates self::getCanonicalServerInfoForAllWikis)
230  return self::getWikiIdFromDbDomain( self::getCurrentWikiDbDomain() );
231  }
232 
233  $urlPartsCheck = wfParseUrl( $url );
234  if ( $urlPartsCheck === false ) {
235  return false;
236  }
237 
238  static $relevantKeys = [ 'host' => 1, 'port' => 1 ];
239  $urlPartsCheck = array_intersect_key( $urlPartsCheck, $relevantKeys );
240 
241  foreach ( self::getCanonicalServerInfoForAllWikis() as $wikiId => $info ) {
242  $urlParts = $info['parts'];
243  if ( $urlParts === false ) {
244  continue; // sanity
245  }
246 
247  $urlParts = array_intersect_key( $urlParts, $relevantKeys );
248  if ( $urlParts == $urlPartsCheck ) {
249  return $wikiId;
250  }
251  }
252 
253  return false;
254  }
255 
269  public static function getWikiIdFromDbDomain( $domain ) {
270  $domain = DatabaseDomain::newFromId( $domain );
271  // Since the schema was not always part of the wiki ID, try to maintain backwards
272  // compatibility with some common cases. Assume that if the DB domain schema is just
273  // the installer default then it is probably the case that the schema is the same for
274  // all wikis in the farm. Historically, any wiki farm had to make the database/prefix
275  // combination unique per wiki. Ommit the schema if it does not seem wiki specific.
276  if ( !in_array( $domain->getSchema(), [ null, 'mediawiki' ], true ) ) {
277  // This means a site admin may have specifically taylored the schemas.
278  // Domain IDs might use the form <DB>-<project>- or <DB>-<project>-<language>_,
279  // meaning that the schema portion must be accounted for to disambiguate wikis.
280  return "{$domain->getDatabase()}-{$domain->getSchema()}-{$domain->getTablePrefix()}";
281  }
282  // Note that if this wiki ID is passed a a domain ID to LoadBalancer, then it can
283  // handle the schema by assuming the generic "mediawiki" schema if needed.
284  return strlen( $domain->getTablePrefix() )
285  ? "{$domain->getDatabase()}-{$domain->getTablePrefix()}"
286  : (string)$domain->getDatabase();
287  }
288 
293  public static function getCurrentWikiDbDomain() {
295  // Avoid invoking LBFactory to avoid any chance of recursion
296  return new DatabaseDomain( $wgDBname, $wgDBmwschema, (string)$wgDBprefix );
297  }
298 
304  public static function isCurrentWikiDbDomain( $domain ) {
305  return self::getCurrentWikiDbDomain()->equals( $domain );
306  }
307 
313  public static function isCurrentWikiId( $wikiId ) {
314  return ( self::getWikiIdFromDbDomain( self::getCurrentWikiDbDomain() ) === $wikiId );
315  }
316 }
static getWikiReferenceFromWgConf( $wikiID)
Definition: WikiMap.php:51
static getWikiName( $wikiID)
Convenience to get the wiki&#39;s display name.
Definition: WikiMap.php:120
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
static getWikiIdFromDbDomain( $domain)
Get the wiki ID of a database domain.
Definition: WikiMap.php:269
$wgDBmwschema
Current wiki database schema name.
static getWiki( $wikiID)
Get a WikiReference object for $wikiID.
Definition: WikiMap.php:37
static getWikiWikiReferenceFromSites( $wikiID)
Definition: WikiMap.php:86
static getForeignURL( $wikiID, $page, $fragmentId=null)
Convenience to get a url to a page on a foreign wiki.
Definition: WikiMap.php:171
Reference to a locally-hosted wiki.
static getCanonicalServerInfoForAllWikis()
Get canonical server info for all local wikis in the map that have one.
Definition: WikiMap.php:188
$cache
Definition: mcc.php:33
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition: Linker.php:848
static makeForeignLink( $wikiID, $page, $text=null)
Convenience to get a link to a page on a foreign wiki.
Definition: WikiMap.php:149
$wgDBname
Current wiki database name.
$wgConf
wgConf hold the site configuration.
static getCurrentWikiDbDomain()
Definition: WikiMap.php:293
Class to handle database/schema/prefix specifications for IDatabase.
static isCurrentWikiId( $wikiId)
Definition: WikiMap.php:313
$wgDBprefix
Current wiki database table name prefix.
static isCurrentWikiDbDomain( $domain)
Definition: WikiMap.php:304
$wgCanonicalServer
Canonical URL of the server, to use in IRC feeds and notification e-mails.
string [] $wgLocalDatabases
Other wikis on this site, can be administered from a single developer account.
static foreignUserLink( $wikiID, $user, $text=null)
Convenience to get a link to a user page on a foreign wiki.
Definition: WikiMap.php:137
static getWikiFromUrl( $url)
Definition: WikiMap.php:224
return true
Definition: router.php:92