X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/includes/WikiMap.php diff --git a/includes/WikiMap.php b/includes/WikiMap.php index e12f7abe..8bb37b5c 100644 --- a/includes/WikiMap.php +++ b/includes/WikiMap.php @@ -1,42 +1,124 @@ loadFullData(); list( $major, $minor ) = $wgConf->siteFromDB( $wikiID ); - if( isset( $major ) ) { - $server = $wgConf->get( 'wgServer', $wikiID, $major, - array( 'lang' => $minor, 'site' => $major ) ); - $path = $wgConf->get( 'wgArticlePath', $wikiID, $major, - array( 'lang' => $minor, 'site' => $major ) ); - return new WikiReference( $major, $minor, $server, $path ); - } else { + if ( $major === null ) { + return null; + } + $server = $wgConf->get( 'wgServer', $wikiID, $major, + [ 'lang' => $minor, 'site' => $major ] ); + + $canonicalServer = $wgConf->get( 'wgCanonicalServer', $wikiID, $major, + [ 'lang' => $minor, 'site' => $major ] ); + if ( $canonicalServer === false || $canonicalServer === null ) { + $canonicalServer = $server; + } + + $path = $wgConf->get( 'wgArticlePath', $wikiID, $major, + [ 'lang' => $minor, 'site' => $major ] ); + + // If we don't have a canonical server or a path containing $1, the + // WikiReference isn't going to function properly. Just return null in + // that case. + if ( !is_string( $canonicalServer ) || !is_string( $path ) || strpos( $path, '$1' ) === false ) { return null; } + + return new WikiReference( $canonicalServer, $path, $server ); } - + + /** + * @param string $wikiID + * @return WikiReference|null WikiReference object or null if the wiki was not found + */ + private static function getWikiWikiReferenceFromSites( $wikiID ) { + $siteLookup = MediaWikiServices::getInstance()->getSiteLookup(); + $site = $siteLookup->getSite( $wikiID ); + + if ( !$site instanceof MediaWikiSite ) { + // Abort if not a MediaWikiSite, as this is about Wikis + return null; + } + + $urlParts = wfParseUrl( $site->getPageUrl() ); + if ( $urlParts === false || !isset( $urlParts['path'] ) || !isset( $urlParts['host'] ) ) { + // We can't create a meaningful WikiReference without URLs + return null; + } + + // XXX: Check whether path contains a $1? + $path = $urlParts['path']; + if ( isset( $urlParts['query'] ) ) { + $path .= '?' . $urlParts['query']; + } + + $canonicalServer = isset( $urlParts['scheme'] ) ? $urlParts['scheme'] : 'http'; + $canonicalServer .= '://' . $urlParts['host']; + + return new WikiReference( $canonicalServer, $path ); + } + /** * Convenience to get the wiki's display name * * @todo We can give more info than just the wiki id! - * @param $wikiID String: wiki'd id (generally database name) - * @return Wiki's name or $wiki_id if the wiki was not found + * @param string $wikiID Wiki'd id (generally database name) + * @return string|int Wiki's name or $wiki_id if the wiki was not found */ public static function getWikiName( $wikiID ) { - $wiki = WikiMap::getWiki( $wikiID ); + $wiki = self::getWiki( $wikiID ); if ( $wiki ) { return $wiki->getDisplayName(); @@ -47,27 +129,24 @@ class WikiMap { /** * Convenience to get a link to a user page on a foreign wiki * - * @param $wikiID String: wiki'd id (generally database name) - * @param $user String: user name (must be normalised before calling this function!) - * @param $text String: link's text; optional, default to "User:$user" - * @return String: HTML link or false if the wiki was not found + * @param string $wikiID Wiki'd id (generally database name) + * @param string $user User name (must be normalised before calling this function!) + * @param string $text Link's text; optional, default to "User:$user" + * @return string HTML link or false if the wiki was not found */ - public static function foreignUserLink( $wikiID, $user, $text=null ) { + public static function foreignUserLink( $wikiID, $user, $text = null ) { return self::makeForeignLink( $wikiID, "User:$user", $text ); } /** * Convenience to get a link to a page on a foreign wiki * - * @param $wikiID String: wiki'd id (generally database name) - * @param $page String: page name (must be normalised before calling this function!) - * @param $text String: link's text; optional, default to $page - * @return String: HTML link or false if the wiki was not found + * @param string $wikiID Wiki'd id (generally database name) + * @param string $page Page name (must be normalised before calling this function!) + * @param string $text Link's text; optional, default to $page + * @return string|false HTML link or false if the wiki was not found */ - public static function makeForeignLink( $wikiID, $page, $text=null ) { - global $wgUser; - $sk = $wgUser->getSkin(); - + public static function makeForeignLink( $wikiID, $page, $text = null ) { if ( !$text ) { $text = $page; } @@ -77,88 +156,106 @@ class WikiMap { return false; } - return $sk->makeExternalLink( $url, $text ); + return Linker::makeExternalLink( $url, $text ); } /** * Convenience to get a url to a page on a foreign wiki * - * @param $wikiID String: wiki'd id (generally database name) - * @param $page String: page name (must be normalised before calling this function!) - * @return String: URL or false if the wiki was not found + * @param string $wikiID Wiki'd id (generally database name) + * @param string $page Page name (must be normalised before calling this function!) + * @param string|null $fragmentId + * + * @return string|bool URL or false if the wiki was not found */ - public static function getForeignURL( $wikiID, $page ) { - $wiki = WikiMap::getWiki( $wikiID ); - + public static function getForeignURL( $wikiID, $page, $fragmentId = null ) { + $wiki = self::getWiki( $wikiID ); + if ( $wiki ) { - return $wiki->getUrl( $page ); + return $wiki->getFullUrl( $page, $fragmentId ); } - - return false; - } -} - -/** - * Reference to a locally-hosted wiki - */ -class WikiReference { - private $mMinor; ///< 'en', 'meta', 'mediawiki', etc - private $mMajor; ///< 'wiki', 'wiktionary', etc - private $mServer; ///< server override, 'www.mediawiki.org' - private $mPath; ///< path override, '/wiki/$1' - - public function __construct( $major, $minor, $server, $path ) { - $this->mMajor = $major; - $this->mMinor = $minor; - $this->mServer = $server; - $this->mPath = $path; - } - public function getHostname() { - $prefixes = array( 'http://', 'https://' ); - foreach ( $prefixes as $prefix ) { - if ( substr( $this->mServer, 0, strlen( $prefix ) ) ) { - return substr( $this->mServer, strlen( $prefix ) ); - } - } - throw new MWException( "Invalid hostname for wiki {$this->mMinor}.{$this->mMajor}" ); + return false; } /** - * Get the the URL in a way to de displayed to the user - * More or less Wikimedia specific + * Get canonical server info for all local wikis in the map that have one * - * @return String + * @return array Map of (local wiki ID => map of (url,parts)) + * @since 1.30 */ - public function getDisplayName() { - $url = $this->getUrl( '' ); - $url = preg_replace( '!^https?://!', '', $url ); - $url = preg_replace( '!/index\.php(\?title=|/)$!', '/', $url ); - $url = preg_replace( '!/wiki/$!', '/', $url ); - $url = preg_replace( '!/$!', '', $url ); - return $url; + public static function getCanonicalServerInfoForAllWikis() { + $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache(); + + return $cache->getWithSetCallback( + $cache->makeGlobalKey( 'wikimap', 'canonical-urls' ), + $cache::TTL_DAY, + function () { + global $wgLocalDatabases, $wgCanonicalServer; + + $infoMap = []; + // Make sure at least the current wiki is set, for simple configurations. + // This also makes it the first in the map, which is useful for common cases. + $infoMap[wfWikiID()] = [ + 'url' => $wgCanonicalServer, + 'parts' => wfParseUrl( $wgCanonicalServer ) + ]; + + foreach ( $wgLocalDatabases as $wikiId ) { + $wikiReference = self::getWiki( $wikiId ); + if ( $wikiReference ) { + $url = $wikiReference->getCanonicalServer(); + $infoMap[$wikiId] = [ 'url' => $url, 'parts' => wfParseUrl( $url ) ]; + } + } + + return $infoMap; + } + ); } /** - * Helper function for getUrl() - * - * @todo FIXME: this may be generalized... - * @param $page String: page name (must be normalised before calling this function!) - * @return String: Url fragment + * @param string $url + * @return bool|string Wiki ID or false + * @since 1.30 */ - private function getLocalUrl( $page ) { - return str_replace( '$1', wfUrlEncode( str_replace( ' ', '_', $page ) ), $this->mPath ); + public static function getWikiFromUrl( $url ) { + $urlPartsCheck = wfParseUrl( $url ); + if ( $urlPartsCheck === false ) { + return false; + } + + $urlPartsCheck = array_intersect_key( $urlPartsCheck, [ 'host' => 1, 'port' => 1 ] ); + foreach ( self::getCanonicalServerInfoForAllWikis() as $wikiId => $info ) { + $urlParts = $info['parts']; + if ( $urlParts === false ) { + continue; // sanity + } + + $urlParts = array_intersect_key( $urlParts, [ 'host' => 1, 'port' => 1 ] ); + if ( $urlParts == $urlPartsCheck ) { + return $wikiId; + } + } + + return false; } /** - * Get a URL to a page on this foreign wiki + * Get the wiki ID of a database domain * - * @param $page String: page name (must be normalised before calling this function!) - * @return String: Url + * This is like DatabaseDomain::getId() without encoding (for legacy reasons) + * + * @param string|DatabaseDomain $domain + * @return string */ - public function getUrl( $page ) { - return - $this->mServer . - $this->getLocalUrl( $page ); + public static function getWikiIdFromDomain( $domain ) { + if ( !( $domain instanceof DatabaseDomain ) ) { + $domain = DatabaseDomain::newFromId( $domain ); + } + + return strlen( $domain->getTablePrefix() ) + ? "{$domain->getDatabase()}-{$domain->getTablePrefix()}" + : $domain->getDatabase(); } }