From d46fbd1a71fbc94fb40998ee69bcffbf4b205e6e Mon Sep 17 00:00:00 2001 From: saper Date: Sun, 28 Jan 2018 03:21:51 +0100 Subject: [PATCH] Advertise feeds only if $wgFeed is enabled Wikis with $wgFeed=false should not present an Atom icon on the RecentChanges/Watchlist. Bug: T116145 Change-Id: Ic64f7f5115a77c42ed2b336f6996fe711b3822ba --- includes/OutputPage.php | 25 +++- tests/phpunit/includes/OutputPageTest.php | 144 +++++++++++++++++++++- 2 files changed, 162 insertions(+), 7 deletions(-) diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 732e363261..cb90ccf7b7 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -1145,6 +1145,20 @@ class OutputPage extends ContextSource { } } + /** + * Return effective list of advertised feed types + * @see addFeedLink() + * + * @return array Array of feed type names ( 'rss', 'atom' ) + */ + protected function getAdvertisedFeedTypes() { + if ( $this->getConfig()->get( 'Feed' ) ) { + return $this->getConfig()->get( 'AdvertisedFeedTypes' ); + } else { + return []; + } + } + /** * Add default feeds to the page header * This is mainly kept for backward compatibility, see OutputPage::addFeedLink() @@ -1157,7 +1171,7 @@ class OutputPage extends ContextSource { public function setFeedAppendQuery( $val ) { $this->mFeedLinks = []; - foreach ( $this->getConfig()->get( 'AdvertisedFeedTypes' ) as $type ) { + foreach ( $this->getAdvertisedFeedTypes() as $type ) { $query = "feed=$type"; if ( is_string( $val ) ) { $query .= '&' . $val; @@ -1173,7 +1187,7 @@ class OutputPage extends ContextSource { * @param string $href URL */ public function addFeedLink( $format, $href ) { - if ( in_array( $format, $this->getConfig()->get( 'AdvertisedFeedTypes' ) ) ) { + if ( in_array( $format, $this->getAdvertisedFeedTypes() ) ) { $this->mFeedLinks[$format] = $href; } } @@ -3737,8 +3751,9 @@ class OutputPage extends ContextSource { # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined. # If so, use it instead. $sitename = $config->get( 'Sitename' ); - if ( $config->get( 'OverrideSiteFeed' ) ) { - foreach ( $config->get( 'OverrideSiteFeed' ) as $type => $feedUrl ) { + $overrideSiteFeed = $config->get( 'OverrideSiteFeed' ); + if ( $overrideSiteFeed ) { + foreach ( $overrideSiteFeed as $type => $feedUrl ) { // Note, this->feedLink escapes the url. $feedLinks[] = $this->feedLink( $type, @@ -3748,7 +3763,7 @@ class OutputPage extends ContextSource { } } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) { $rctitle = SpecialPage::getTitleFor( 'Recentchanges' ); - foreach ( $config->get( 'AdvertisedFeedTypes' ) as $format ) { + foreach ( $this->getAdvertisedFeedTypes() as $format ) { $feedLinks[] = $this->feedLink( $format, $rctitle->getLocalURL( [ 'feed' => $format ] ), diff --git a/tests/phpunit/includes/OutputPageTest.php b/tests/phpunit/includes/OutputPageTest.php index aa14124a2c..f8c75fa35f 100644 --- a/tests/phpunit/includes/OutputPageTest.php +++ b/tests/phpunit/includes/OutputPageTest.php @@ -12,6 +12,14 @@ class OutputPageTest extends MediaWikiTestCase { const SCREEN_MEDIA_QUERY = 'screen and (min-width: 982px)'; const SCREEN_ONLY_MEDIA_QUERY = 'only screen and (min-width: 982px)'; + // @codingStandardsIgnoreStart Generic.Files.LineLength + const RSS_RC_LINK = ''; + const ATOM_RC_LINK = ''; + + const RSS_TEST_LINK = ''; + const ATOM_TEST_LINK = ''; + // @codingStandardsIgnoreEnd + // Ensure that we don't affect the global ResourceLoader state. protected function setUp() { parent::setUp(); @@ -51,6 +59,64 @@ class OutputPageTest extends MediaWikiTestCase { ]; } + private function setupFeedLinks( $feed, $types ) { + $outputPage = $this->newInstance( [ + 'AdvertisedFeedTypes' => $types, + 'Feed' => $feed, + 'OverrideSiteFeed' => false, + 'Script' => '/w', + 'Sitename' => false, + ] ); + $outputPage->setTitle( Title::makeTitle( NS_MAIN, 'Test' ) ); + $this->setMwGlobals( [ + 'wgScript' => '/w/index.php', + ] ); + return $outputPage; + } + + private function assertFeedLinks( $outputPage, $message, $present, $non_present ) { + $links = $outputPage->getHeadLinksArray(); + foreach ( $present as $link ) { + $this->assertContains( $link, $links, $message ); + } + foreach ( $non_present as $link ) { + $this->assertNotContains( $link, $links, $message ); + } + } + + private function assertFeedUILinks( $outputPage, $ui_links ) { + if ( $ui_links ) { + $this->assertTrue( $outputPage->isSyndicated(), 'Syndication should be offered' ); + $this->assertGreaterThan( 0, count( $outputPage->getSyndicationLinks() ), + 'Some syndication links should be there' ); + } else { + $this->assertFalse( $outputPage->isSyndicated(), 'No syndication should be offered' ); + $this->assertEquals( 0, count( $outputPage->getSyndicationLinks() ), + 'No syndication links should be there' ); + } + } + + public static function provideFeedLinkData() { + return [ + [ + true, [ 'rss' ], 'Only RSS RC link should be offerred', + [ self::RSS_RC_LINK ], [ self::ATOM_RC_LINK ] + ], + [ + true, [ 'atom' ], 'Only Atom RC link should be offerred', + [ self::ATOM_RC_LINK ], [ self::RSS_RC_LINK ] + ], + [ + true, [], 'No RC feed formats should be offerred', + [], [ self::ATOM_RC_LINK, self::RSS_RC_LINK ] + ], + [ + false, [ 'atom' ], 'No RC feeds should be offerred', + [], [ self::ATOM_RC_LINK, self::RSS_RC_LINK ] + ], + ]; + } + /** * @covers OutputPage::setCopyrightUrl * @covers OutputPage::getHeadLinksArray @@ -65,6 +131,67 @@ class OutputPageTest extends MediaWikiTestCase { ); } + /** + * @dataProvider provideFeedLinkData + * @covers OutputPage::getHeadLinksArray + */ + public function testRecentChangesFeed( $feed, $advertised_feed_types, + $message, $present, $non_present ) { + $outputPage = $this->setupFeedLinks( $feed, $advertised_feed_types ); + $this->assertFeedLinks( $outputPage, $message, $present, $non_present ); + } + + public static function provideAdditionalFeedData() { + return [ + [ + true, [ 'atom' ], 'Additional Atom feed should be offered', + 'atom', + [ self::ATOM_TEST_LINK, self::ATOM_RC_LINK ], + [ self::RSS_TEST_LINK, self::RSS_RC_LINK ], + true, + ], + [ + true, [ 'rss' ], 'Additional RSS feed should be offered', + 'rss', + [ self::RSS_TEST_LINK, self::RSS_RC_LINK ], + [ self::ATOM_TEST_LINK, self::ATOM_RC_LINK ], + true, + ], + [ + true, [ 'rss' ], 'Additional Atom feed should NOT be offered with RSS enabled', + 'atom', + [ self::RSS_RC_LINK ], + [ self::RSS_TEST_LINK, self::ATOM_TEST_LINK, self::ATOM_RC_LINK ], + false, + ], + [ + false, [ 'atom' ], 'Additional Atom feed should NOT be offered, all feeds disabled', + 'atom', + [], + [ + self::RSS_TEST_LINK, self::ATOM_TEST_LINK, + self::ATOM_RC_LINK, self::ATOM_RC_LINK, + ], + false, + ], + ]; + } + + /** + * @dataProvider provideAdditionalFeedData + * @covers OutputPage::getHeadLinksArray + * @covers OutputPage::addFeedLink + * @covers OutputPage::getSyndicationLinks + * @covers OutputPage::isSyndicated + */ + public function testAdditionalFeeds( $feed, $advertised_feed_types, $message, + $additional_feed_type, $present, $non_present, $any_ui_links ) { + $outputPage = $this->setupFeedLinks( $feed, $advertised_feed_types ); + $outputPage->addFeedLink( $additional_feed_type, 'fake-link' ); + $this->assertFeedLinks( $outputPage, $message, $present, $non_present ); + $this->assertFeedUILinks( $outputPage, $any_ui_links ); + } + // @todo How to test setStatusCode? /** @@ -797,7 +924,7 @@ class OutputPageTest extends MediaWikiTestCase { * @covers OutputPage::isSyndicated */ public function testSetSyndicated() { - $op = $this->newInstance(); + $op = $this->newInstance( [ 'Feed' => true ] ); $this->assertFalse( $op->isSyndicated() ); $op->setSyndicated(); @@ -805,6 +932,12 @@ class OutputPageTest extends MediaWikiTestCase { $op->setSyndicated( false ); $this->assertFalse( $op->isSyndicated() ); + + $op = $this->newInstance(); // Feed => false by default + $this->assertFalse( $op->isSyndicated() ); + + $op->setSyndicated(); + $this->assertFalse( $op->isSyndicated() ); } /** @@ -814,7 +947,7 @@ class OutputPageTest extends MediaWikiTestCase { * @covers OutputPage::getSyndicationLinks() */ public function testFeedLinks() { - $op = $this->newInstance(); + $op = $this->newInstance( [ 'Feed' => true ] ); $this->assertSame( [], $op->getSyndicationLinks() ); $op->addFeedLink( 'not a supported format', 'abc' ); @@ -839,6 +972,13 @@ class OutputPageTest extends MediaWikiTestCase { $expected[$type] = $op->getTitle()->getLocalURL( "feed=$type&apples=oranges" ); } $this->assertSame( $expected, $op->getSyndicationLinks() ); + + $op = $this->newInstance(); // Feed => false by default + $this->assertSame( [], $op->getSyndicationLinks() ); + + $op->addFeedLink( $feedTypes[0], 'def' ); + $this->assertFalse( $op->isSyndicated() ); + $this->assertSame( [], $op->getSyndicationLinks() ); } /** -- 2.20.1