From 58524511777e7dd5b120d873e5a1c71fb0e595f2 Mon Sep 17 00:00:00 2001 From: daniel Date: Fri, 11 Sep 2015 16:17:52 +0200 Subject: [PATCH] Add support for fragments to WikiMap WikiMap::makeForeignUrl should support fragement IDs in the generated URL. Change-Id: I612d5f465822b56356a78b3e72fb441a888668f1 --- includes/Linker.php | 2 +- includes/WikiMap.php | 41 ++++++++++++++------ tests/phpunit/includes/WikiMapTest.php | 1 + tests/phpunit/includes/WikiReferenceTest.php | 26 ++++++++----- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/includes/Linker.php b/includes/Linker.php index d6a4056f02..db6f379d52 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -1464,7 +1464,7 @@ class Linker { if ( $wikiId !== null ) { $thelink = Linker::makeExternalLink( - WikiMap::getForeignURL( $wikiId, $target->getFullText() ), + WikiMap::getForeignURL( $wikiId, $target->getPrefixedText(), $target->getFragment() ), $linkText . $inside, /* escape = */ false // Already escaped ) . $trail; diff --git a/includes/WikiMap.php b/includes/WikiMap.php index f16f5aa767..a01f1b66bd 100644 --- a/includes/WikiMap.php +++ b/includes/WikiMap.php @@ -108,13 +108,15 @@ class WikiMap { * * @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 ) { + public static function getForeignURL( $wikiID, $page, $fragmentId = null ) { $wiki = WikiMap::getWiki( $wikiID ); if ( $wiki ) { - return $wiki->getFullUrl( $page ); + return $wiki->getFullUrl( $page, $fragmentId ); } return false; @@ -181,21 +183,32 @@ class WikiReference { * Helper function for getUrl() * * @todo FIXME: This may be generalized... - * @param string $page Page name (must be normalised before calling this function!) - * @return string Url fragment + * + * @param string $page Page name (must be normalised before calling this function! May contain a section part.) + * @param string|null $fragmentId + * + * @return string relative URL, without the server part. */ - private function getLocalUrl( $page ) { - return str_replace( '$1', wfUrlEncode( str_replace( ' ', '_', $page ) ), $this->mPath ); + private function getLocalUrl( $page, $fragmentId = null ) { + $page = wfUrlEncode( str_replace( ' ', '_', $page ) ); + + if ( is_string( $fragmentId ) && $fragmentId !== '' ) { + $page .= '#' . wfUrlEncode( $fragmentId ); + } + + return str_replace( '$1', $page, $this->mPath ); } /** * Get a canonical (i.e. based on $wgCanonicalServer) URL to a page on this foreign wiki * * @param string $page Page name (must be normalised before calling this function!) + * @param string|null $fragmentId + * * @return string Url */ - public function getCanonicalUrl( $page ) { - return $this->mCanonicalServer . $this->getLocalUrl( $page ); + public function getCanonicalUrl( $page, $fragmentId = null ) { + return $this->mCanonicalServer . $this->getLocalUrl( $page, $fragmentId ); } /** @@ -209,10 +222,12 @@ class WikiReference { /** * Alias for getCanonicalUrl(), for backwards compatibility. * @param string $page + * @param string|null $fragmentId + * * @return string */ - public function getUrl( $page ) { - return $this->getCanonicalUrl( $page ); + public function getUrl( $page, $fragmentId = null ) { + return $this->getCanonicalUrl( $page, $fragmentId ); } /** @@ -220,10 +235,12 @@ class WikiReference { * when called locally on the wiki. * * @param string $page Page name (must be normalized before calling this function!) + * @param string|null $fragmentId + * * @return string URL */ - public function getFullUrl( $page ) { + public function getFullUrl( $page, $fragmentId = null ) { return $this->mServer . - $this->getLocalUrl( $page ); + $this->getLocalUrl( $page, $fragmentId ); } } diff --git a/tests/phpunit/includes/WikiMapTest.php b/tests/phpunit/includes/WikiMapTest.php index 2218d0597b..9233416c74 100644 --- a/tests/phpunit/includes/WikiMapTest.php +++ b/tests/phpunit/includes/WikiMapTest.php @@ -93,6 +93,7 @@ class WikiMapTest extends MediaWikiLangTestCase { return array( 'unknown' => array( false, 'xyzzy', 'Foo' ), 'enwiki' => array( 'http://en.example.org/w/Foo', 'enwiki', 'Foo', ), + 'ruwiki with fragement' => array( '//ru.example.org/wiki/%D0%A4%D1%83#%D0%B2%D0%B0%D1%80', 'ruwiki', 'Фу', 'вар' ), ); } diff --git a/tests/phpunit/includes/WikiReferenceTest.php b/tests/phpunit/includes/WikiReferenceTest.php index 592a4772cd..ce9fc66b12 100644 --- a/tests/phpunit/includes/WikiReferenceTest.php +++ b/tests/phpunit/includes/WikiReferenceTest.php @@ -48,30 +48,38 @@ class WikiReferenceTest extends PHPUnit_Framework_TestCase { public function provideGetCanonicalUrl() { return array( - 'wiki path' => array( 'https://acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo' ), - 'empty path' => array( 'https://acme.com/Foo', 'https://acme.com', '//acme.com', '/$1', 'Foo' ), + 'no fragement' => array( 'https://acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', null ), + 'empty fragement' => array( 'https://acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', '' ), + 'fragment' => array( 'https://acme.com/wiki/Foo#Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar' ), + 'double fragment' => array( 'https://acme.com/wiki/Foo#Bar%23Xus', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar#Xus' ), + 'escaped fragement' => array( 'https://acme.com/wiki/Foo%23Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo#Bar', null ), + 'empty path' => array( 'https://acme.com/Foo', 'https://acme.com', '//acme.com', '/$1', 'Foo', null ), ); } /** * @dataProvider provideGetCanonicalUrl */ - public function testGetCanonicalUrl( $expected, $canonicalServer, $server, $path, $page ) { + public function testGetCanonicalUrl( $expected, $canonicalServer, $server, $path, $page, $fragmentId ) { $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, $path, $server ); - $this->assertEquals( $expected, $reference->getCanonicalUrl( $page ) ); + $this->assertEquals( $expected, $reference->getCanonicalUrl( $page, $fragmentId ) ); } /** * @dataProvider provideGetCanonicalUrl */ - public function testGetUrl( $expected, $canonicalServer, $server, $path, $page ) { + public function testGetUrl( $expected, $canonicalServer, $server, $path, $page, $fragmentId ) { $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, $path, $server ); - $this->assertEquals( $expected, $reference->getUrl( $page ) ); + $this->assertEquals( $expected, $reference->getUrl( $page, $fragmentId ) ); } public function provideGetFullUrl() { return array( - 'wiki path' => array( '//acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', null ), + 'no fragement' => array( '//acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', null ), + 'empty fragement' => array( '//acme.com/wiki/Foo', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', '' ), + 'fragment' => array( '//acme.com/wiki/Foo#Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar' ), + 'double fragment' => array( '//acme.com/wiki/Foo#Bar%23Xus', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo', 'Bar#Xus' ), + 'escaped fragement' => array( '//acme.com/wiki/Foo%23Bar', 'https://acme.com', '//acme.com', '/wiki/$1', 'Foo#Bar', null ), 'empty path' => array( '//acme.com/Foo', 'https://acme.com', '//acme.com', '/$1', 'Foo', null ), ); } @@ -79,9 +87,9 @@ class WikiReferenceTest extends PHPUnit_Framework_TestCase { /** * @dataProvider provideGetFullUrl */ - public function testGetFullUrl( $expected, $canonicalServer, $server, $path, $page ) { + public function testGetFullUrl( $expected, $canonicalServer, $server, $path, $page, $fragmentId ) { $reference = new WikiReference( 'wiki', 'xx', $canonicalServer, $path, $server ); - $this->assertEquals( $expected, $reference->getFullUrl( $page ) ); + $this->assertEquals( $expected, $reference->getFullUrl( $page, $fragmentId ) ); } } -- 2.20.1