From 3d85fde609727bea68fce619a1bc2050c66895eb Mon Sep 17 00:00:00 2001 From: Marius Hoch Date: Thu, 1 Oct 2015 12:57:25 +0200 Subject: [PATCH] Make WikiMap fall back to sites if a site couldn't be found using $wgConf The mapping is not very good, but should be good enough, given that only the URL parts are really being used. Bug: T114107 Change-Id: I8186140aed5620cf7b4ba84aa4c9492c61f406d0 --- includes/WikiMap.php | 52 +++++++++++++++++++++++++- tests/phpunit/includes/WikiMapTest.php | 48 +++++++++++++++++++++--- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/includes/WikiMap.php b/includes/WikiMap.php index 6215af16a9..325831eef0 100644 --- a/includes/WikiMap.php +++ b/includes/WikiMap.php @@ -21,7 +21,7 @@ */ /** - * Helper tools for dealing with other locally-hosted wikis + * Helper tools for dealing with other wikis. */ class WikiMap { @@ -32,6 +32,20 @@ class WikiMap { * @return WikiReference|null WikiReference object or null if the wiki was not found */ public static function getWiki( $wikiID ) { + $wikiReference = self::getWikiReferenceFromWgConf( $wikiID ); + if ( $wikiReference ) { + return $wikiReference; + } + + // Try sites, if $wgConf failed + return self::getWikiWikiReferenceFromSites( $wikiID ); + } + + /** + * @param string $wikiID + * @return WikiReference|null WikiReference object or null if the wiki was not found + */ + private static function getWikiReferenceFromWgConf( $wikiID ) { global $wgConf; $wgConf->loadFullData(); @@ -54,6 +68,42 @@ class WikiMap { 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 ) { + static $siteStore = null; + if ( !$siteStore ) { + // Replace once T114471 got fixed and don't do the caching here. + $siteStore = SiteSQLStore::newInstance(); + } + + $site = $siteStore->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 * diff --git a/tests/phpunit/includes/WikiMapTest.php b/tests/phpunit/includes/WikiMapTest.php index 08ba41d9a1..e86559e7d8 100644 --- a/tests/phpunit/includes/WikiMapTest.php +++ b/tests/phpunit/includes/WikiMapTest.php @@ -2,8 +2,9 @@ /** * @covers WikiMap + * + * @group Database */ - class WikiMapTest extends MediaWikiLangTestCase { public function setUp() { @@ -24,23 +25,40 @@ class WikiMapTest extends MediaWikiLangTestCase { $this->setMwGlobals( array( 'wgConf' => $conf, ) ); + + TestSites::insertIntoDb(); } public function provideGetWiki() { + // As provided by $wgConf $enwiki = new WikiReference( 'http://en.example.org', '/w/$1' ); $ruwiki = new WikiReference( '//ru.example.org', '/wiki/$1' ); + // Created from site objects + $nlwiki = new WikiReference( 'https://nl.wikipedia.org', '/wiki/$1' ); + // enwiktionary doesn't have an interwiki id, thus this falls back to minor = lang code + $enwiktionary = new WikiReference( 'https://en.wiktionary.org', '/wiki/$1' ); + return array( - 'unknown' => array( false, 'xyzzy' ), - 'enwiki' => array( $enwiki, 'enwiki' ), - 'ruwiki' => array( $ruwiki, 'ruwiki' ), + 'unknown' => array( null, 'xyzzy' ), + 'enwiki (wgConf)' => array( $enwiki, 'enwiki' ), + 'ruwiki (wgConf)' => array( $ruwiki, 'ruwiki' ), + 'nlwiki (sites)' => array( $nlwiki, 'nlwiki', false ), + 'enwiktionary (sites)' => array( $enwiktionary, 'enwiktionary', false ), + 'non MediaWiki site' => array( null, 'spam', false ), ); } /** * @dataProvider provideGetWiki */ - public function testGetWiki( $expected, $wikiId ) { + public function testGetWiki( $expected, $wikiId, $useWgConf = true ) { + if ( !$useWgConf ) { + $this->setMwGlobals( array( + 'wgConf' => new SiteConfiguration(), + ) ); + } + $this->assertEquals( $expected, WikiMap::getWiki( $wikiId ) ); } @@ -49,6 +67,7 @@ class WikiMapTest extends MediaWikiLangTestCase { 'unknown' => array( 'xyzzy', 'xyzzy' ), 'enwiki' => array( 'en.example.org', 'enwiki' ), 'ruwiki' => array( 'ru.example.org', 'ruwiki' ), + 'enwiktionary (sites)' => array( 'en.wiktionary.org', 'enwiktionary' ), ); } @@ -75,6 +94,13 @@ class WikiMapTest extends MediaWikiLangTestCase { 'Фу', 'вар' ), + 'enwiktionary (sites)' => array( + 'Kittens!', + 'enwiktionary', + 'Kitten', + 'Kittens!' + ), ); } @@ -104,6 +130,13 @@ class WikiMapTest extends MediaWikiLangTestCase { 'Фу', 'вар' ), + 'enwiktionary (sites)' => array( + 'Whatever', + 'enwiktionary', + 'Dummy', + 'Whatever' + ), ); } @@ -118,6 +151,11 @@ class WikiMapTest extends MediaWikiLangTestCase { return array( 'unknown' => array( false, 'xyzzy', 'Foo' ), 'enwiki' => array( 'http://en.example.org/w/Foo', 'enwiki', 'Foo' ), + 'enwiktionary (sites)' => array( + 'https://en.wiktionary.org/wiki/Testme', + 'enwiktionary', + 'Testme' + ), 'ruwiki with fragment' => array( '//ru.example.org/wiki/%D0%A4%D1%83#%D0%B2%D0%B0%D1%80', 'ruwiki', -- 2.20.1