From: jenkins-bot Date: Fri, 28 Oct 2016 13:25:18 +0000 (+0000) Subject: Merge "Introduce InterwikiLookupAdapter on top of SiteLookup" X-Git-Tag: 1.31.0-rc.0~5010 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/comptes/ajouter.php?a=commitdiff_plain;h=53779578b44575ef91feb3fad488f09b52f737d7;hp=cf8f2c8299c0d4e24589830807eca3d06895c552;p=lhc%2Fweb%2Fwiklou.git Merge "Introduce InterwikiLookupAdapter on top of SiteLookup" --- diff --git a/autoload.php b/autoload.php index 8b1e9c55f4..17e5df6597 100644 --- a/autoload.php +++ b/autoload.php @@ -859,6 +859,7 @@ $wgAutoloadLocalClasses = [ 'MediaWiki\\Diff\\WordAccumulator' => __DIR__ . '/includes/diff/WordAccumulator.php', 'MediaWiki\\Interwiki\\ClassicInterwikiLookup' => __DIR__ . '/includes/interwiki/ClassicInterwikiLookup.php', 'MediaWiki\\Interwiki\\InterwikiLookup' => __DIR__ . '/includes/interwiki/InterwikiLookup.php', + 'MediaWiki\\Interwiki\\InterwikiLookupAdapter' => __DIR__ . '/includes/interwiki/InterwikiLookupAdapter.php', 'MediaWiki\\Languages\\Data\\Names' => __DIR__ . '/languages/data/Names.php', 'MediaWiki\\Languages\\Data\\ZhConversion' => __DIR__ . '/languages/data/ZhConversion.php', 'MediaWiki\\Linker\\LinkRenderer' => __DIR__ . '/includes/linker/LinkRenderer.php', diff --git a/includes/interwiki/InterwikiLookupAdapter.php b/includes/interwiki/InterwikiLookupAdapter.php new file mode 100644 index 0000000000..a17bdd9b2e --- /dev/null +++ b/includes/interwiki/InterwikiLookupAdapter.php @@ -0,0 +1,175 @@ +siteLookup = $siteLookup; + $this->interwikiMap = $interwikiMap; + } + + /** + * See InterwikiLookup::isValidInterwiki + * It loads the whole interwiki map. + * + * @param string $prefix Interwiki prefix to use + * @return bool Whether it exists + */ + public function isValidInterwiki( $prefix ) { + + return array_key_exists( $prefix, $this->getInterwikiMap() ); + } + + /** + * See InterwikiLookup::fetch + * It loads the whole interwiki map. + * + * @param string $prefix Interwiki prefix to use + * @return Interwiki|null|bool + */ + public function fetch( $prefix ) { + if ( $prefix == '' ) { + return null; + } + + if ( !$this->isValidInterwiki( $prefix ) ) { + return false; + } + + return $this->interwikiMap[$prefix]; + } + + /** + * See InterwikiLookup::getAllPrefixes + * + * @param string|null $local If set, limits output to local/non-local interwikis + * @return string[] List of prefixes + */ + public function getAllPrefixes( $local = null ) { + if ( $local === null ) { + return array_keys( $this->getInterwikiMap() ); + } + $res = []; + foreach ( $this->getInterwikiMap() as $interwikiId => $interwiki ) { + if ( $interwiki->isLocal() === $local ) { + $res[] = $interwikiId; + } + } + return $res; + } + + /** + * See InterwikiLookup::invalidateCache + * + * @param string $prefix + */ + public function invalidateCache( $prefix ) { + if ( !isset( $this->interwikiMap[$prefix] ) ) { + return; + } + $globalId = $this->interwikiMap[$prefix]->getWikiID(); + unset( $this->interwikiMap[$prefix] ); + + // Reload the interwiki + $site = $this->siteLookup->getSites()->getSite( $globalId ); + $interwikis = $this->getSiteInterwikis( $site ); + $this->interwikiMap = array_merge( $this->interwikiMap, [ $interwikis[$prefix] ] ); + } + + /** + * Load interwiki map to use as cache + */ + private function loadInterwikiMap() { + $interwikiMap = []; + $siteList = $this->siteLookup->getSites(); + foreach ( $siteList as $site ) { + $interwikis = $this->getSiteInterwikis( $site ); + $interwikiMap = array_merge( $interwikiMap, $interwikis ); + } + $this->interwikiMap = $interwikiMap; + } + + /** + * Get interwikiMap attribute, load if needed. + * + * @return Interwiki[] + */ + private function getInterwikiMap() { + if ( $this->interwikiMap === null ) { + $this->loadInterwikiMap(); + } + return $this->interwikiMap; + } + + /** + * Load interwikis for the given site + * + * @param Site $site + * @return Interwiki[] + */ + private function getSiteInterwikis( Site $site ) { + $interwikis = []; + foreach ( $site->getInterwikiIds() as $interwiki ) { + $url = $site->getPageUrl(); + if ( $site instanceof MediawikiSite ) { + $path = $site->getFileUrl( 'api.php' ); + } else { + $path = ''; + } + $local = $site->getSource() === 'local'; + // TODO: How to adapt trans? + $interwikis[$interwiki] = new Interwiki( + $interwiki, + $url, + $path, + $site->getGlobalId(), + $local + ); + } + return $interwikis; + } +} diff --git a/tests/phpunit/includes/interwiki/InterwikiLookupAdapterTest.php b/tests/phpunit/includes/interwiki/InterwikiLookupAdapterTest.php new file mode 100644 index 0000000000..4754b040f9 --- /dev/null +++ b/tests/phpunit/includes/interwiki/InterwikiLookupAdapterTest.php @@ -0,0 +1,117 @@ +interwikiLookup = new InterwikiLookupAdapter( + $this->getSiteLookup( $this->getSites() ) + ); + } + + public function testIsValidInterwiki() { + $this->assertTrue( + $this->interwikiLookup->isValidInterwiki( 'enwt' ), + 'enwt known prefix is valid' + ); + $this->assertTrue( + $this->interwikiLookup->isValidInterwiki( 'foo' ), + 'foo site known prefix is valid' + ); + $this->assertFalse( + $this->interwikiLookup->isValidInterwiki( 'xyz' ), + 'unknown prefix is not valid' + ); + } + + public function testFetch() { + + $interwiki = $this->interwikiLookup->fetch( '' ); + $this->assertNull( $interwiki ); + + $interwiki = $this->interwikiLookup->fetch( 'xyz' ); + $this->assertFalse( $interwiki ); + + $interwiki = $this->interwikiLookup->fetch( 'foo' ); + $this->assertInstanceOf( Interwiki::class, $interwiki ); + $this->assertSame( 'foobar', $interwiki->getWikiID() ); + + $interwiki = $this->interwikiLookup->fetch( 'enwt' ); + $this->assertInstanceOf( Interwiki::class, $interwiki ); + + $this->assertSame( 'https://en.wiktionary.org/wiki/$1', $interwiki->getURL(), 'getURL' ); + $this->assertSame( 'https://en.wiktionary.org/w/api.php', $interwiki->getAPI(), 'getAPI' ); + $this->assertSame( 'enwiktionary', $interwiki->getWikiID(), 'getWikiID' ); + $this->assertTrue( $interwiki->isLocal(), 'isLocal' ); + } + + public function testGetAllPrefixes() { + $this->assertEquals( + [ 'foo', 'enwt' ], + $this->interwikiLookup->getAllPrefixes(), + 'getAllPrefixes()' + ); + + $this->assertEquals( + [ 'foo' ], + $this->interwikiLookup->getAllPrefixes( false ), + 'get external prefixes' + ); + + $this->assertEquals( + [ 'enwt' ], + $this->interwikiLookup->getAllPrefixes( true ), + 'get local prefixes' + ); + } + + private function getSiteLookup( SiteList $sites ) { + $siteLookup = $this->getMockBuilder( SiteLookup::class ) + ->disableOriginalConstructor() + ->getMock(); + + $siteLookup->expects( $this->any() ) + ->method( 'getSites' ) + ->will( $this->returnValue( $sites ) ); + + return $siteLookup; + } + + private function getSites() { + $sites = []; + + $site = new Site(); + $site->setGlobalId( 'foobar' ); + $site->addInterwikiId( 'foo' ); + $site->setSource( 'external' ); + $sites[] = $site; + + $site = new MediaWikiSite(); + $site->setGlobalId( 'enwiktionary' ); + $site->setGroup( 'wiktionary' ); + $site->setLanguageCode( 'en' ); + $site->addNavigationId( 'enwiktionary' ); + $site->addInterwikiId( 'enwt' ); + $site->setSource( 'local' ); + $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" ); + $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" ); + $sites[] = $site; + + return new SiteList( $sites ); + } + +}