Hide hiddencat catwatch changes in special changelists
authorWMDE-Fisch <christoph.fischer@wikimedia.de>
Wed, 13 Apr 2016 15:52:48 +0000 (17:52 +0200)
committerWMDE-Fisch <christoph.fischer@wikimedia.de>
Mon, 18 Apr 2016 14:41:26 +0000 (16:41 +0200)
If a hidden category has a member added or removed
this will only be shown to users that have the user
preference "display hidden categories".

Also added method to WikiCategoryPage to check
for hidden status.

Added unit tests for both.

Bug: T127944
Change-Id: Ic53d51391fa29d5e18fef4c42b8a275816c7ba4a

includes/PageProps.php
includes/changes/RecentChange.php
includes/page/WikiCategoryPage.php
includes/page/WikiPage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialWatchlist.php
tests/phpunit/includes/changes/RecentChangeTest.php
tests/phpunit/includes/page/WikiCategoryPageTest.php [new file with mode: 0644]

index bc3e3f1..3654384 100644 (file)
@@ -33,6 +33,33 @@ class PageProps {
         */
        private static $instance;
 
+       /**
+        * Overrides the default instance of this class
+        * This is intended for use while testing and will fail if MW_PHPUNIT_TEST is not defined.
+        *
+        * If this method is used it MUST also be called with null after a test to ensure a new
+        * default instance is created next time getInstance is called.
+        *
+        * @since 1.27
+        *
+        * @param PageProps|null $store
+        *
+        * @return ScopedCallback to reset the overridden value
+        * @throws MWException
+        */
+       public static function overrideInstance( PageProps $store = null ) {
+               if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+                       throw new MWException(
+                               'Cannot override ' . __CLASS__ . 'default instance in operation.'
+                       );
+               }
+               $previousValue = self::$instance;
+               self::$instance = $store;
+               return new ScopedCallback( function() use ( $previousValue ) {
+                       self::$instance = $previousValue;
+               } );
+       }
+
        /**
         * @return PageProps
         */
index 2508304..6a901d0 100644 (file)
@@ -851,7 +851,9 @@ class RecentChange {
                        'rc_logid' => 0,
                        'rc_log_type' => null,
                        'rc_log_action' => '',
-                       'rc_params' => ''
+                       'rc_params' =>  serialize( [
+                               'hidden-cat' => WikiCategoryPage::factory( $categoryTitle )->isHidden()
+                       ] )
                ];
 
                $rc->mExtra = [
@@ -865,6 +867,19 @@ class RecentChange {
                return $rc;
        }
 
+       /**
+        * Get a parameter value
+        *
+        * @since 1.27
+        *
+        * @param string $name parameter name
+        * @return mixed
+        */
+       public function getParam( $name ) {
+               $params = $this->parseParams();
+               return isset( $params[$name] ) ? $params[$name] : null;
+       }
+
        /**
         * Initialises the members of this object from a mysql row object
         *
index d382001..6c93202 100644 (file)
@@ -47,4 +47,18 @@ class WikiCategoryPage extends WikiPage {
                }
                return false;
        }
+
+       /**
+        * Checks if a category is hidden.
+        *
+        * @since 1.27
+        *
+        * @return bool
+        */
+       public function isHidden() {
+               $pageId = $this->getTitle()->getArticleID();
+               $pageProps = PageProps::getInstance()->getProperties( $this->getTitle(), 'hiddencat' );
+
+               return isset( $pageProps[$pageId] ) ? true : false;
+       }
 }
index 82e66aa..06785b7 100644 (file)
@@ -94,7 +94,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param Title $title
         *
         * @throws MWException
-        * @return WikiPage Object of the appropriate type
+        * @return WikiPage|WikiCategoryPage|WikiFilePage
         */
        public static function factory( Title $title ) {
                $ns = $title->getNamespace();
index de77380..8e52f14 100644 (file)
@@ -324,12 +324,23 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $list = ChangesList::newFromContext( $this->getContext() );
                $list->initChangesListRows( $rows );
 
+               $userShowHiddenCats = $this->getUser()->getBoolOption( 'showhiddencats' );
                $rclistOutput = $list->beginRecentChangesList();
                foreach ( $rows as $obj ) {
                        if ( $limit == 0 ) {
                                break;
                        }
                        $rc = RecentChange::newFromRow( $obj );
+
+                       # Skip CatWatch entries for hidden cats based on user preference
+                       if (
+                               $rc->getAttribute( 'rc_type' ) == RC_CATEGORIZE &&
+                               !$userShowHiddenCats &&
+                               $rc->getParam( 'hidden-cat' )
+                       ) {
+                               continue;
+                       }
+
                        $rc->counter = $counter++;
                        # Check if the page has been updated since the last visit
                        if ( $this->getConfig()->get( 'ShowUpdatedMarker' )
index 27e5829..15691f2 100644 (file)
@@ -369,10 +369,21 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                }
 
                $s = $list->beginRecentChangesList();
+               $userShowHiddenCats = $this->getUser()->getBoolOption( 'showhiddencats' );
                $counter = 1;
                foreach ( $rows as $obj ) {
                        # Make RC entry
                        $rc = RecentChange::newFromRow( $obj );
+
+                       # Skip CatWatch entries for hidden cats based on user preference
+                       if (
+                               $rc->getAttribute( 'rc_type' ) == RC_CATEGORIZE &&
+                               !$userShowHiddenCats &&
+                               $rc->getParam( 'hidden-cat' )
+                       ) {
+                               continue;
+                       }
+
                        $rc->counter = $counter++;
 
                        if ( $this->getConfig()->get( 'ShowUpdatedMarker' ) ) {
index 4abe9ee..2efc802 100644 (file)
@@ -134,4 +134,51 @@ class RecentChangeTest extends MediaWikiTestCase {
                $this->assertEquals( $rcType, RecentChange::parseToRCType( $type ) );
        }
 
+       /**
+        * @return PHPUnit_Framework_MockObject_MockObject|PageProps
+        */
+       private function getMockPageProps() {
+               return $this->getMockBuilder( PageProps::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+       }
+
+       public function provideCategoryContent() {
+               return [
+                       [ true ],
+                       [ false ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideCategoryContent
+        * @covers RecentChange::newForCategorization
+        */
+       public function testHiddenCategoryChange( $isHidden ) {
+               $categoryTitle = Title::newFromText( 'CategoryPage', NS_CATEGORY );
+
+               $pageProps = $this->getMockPageProps();
+               $pageProps->expects( $this->once() )
+                       ->method( 'getProperties' )
+                       ->with( $categoryTitle, 'hiddencat' )
+                       ->will( $this->returnValue( $isHidden ? [ $categoryTitle->getArticleID() => '' ] : [ ] ) );
+
+               $scopedOverride = PageProps::overrideInstance( $pageProps );
+
+               $rc = RecentChange::newForCategorization(
+                       '0',
+                       $categoryTitle,
+                       $this->user,
+                       $this->user_comment,
+                       $this->title,
+                       $categoryTitle->getLatestRevID(),
+                       $categoryTitle->getLatestRevID(),
+                       '0',
+                       false
+               );
+
+               $this->assertEquals( $isHidden, $rc->getParam( 'hidden-cat' ) );
+
+               ScopedCallback::consume( $scopedOverride );
+       }
 }
diff --git a/tests/phpunit/includes/page/WikiCategoryPageTest.php b/tests/phpunit/includes/page/WikiCategoryPageTest.php
new file mode 100644 (file)
index 0000000..d6e1d9e
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+
+class WikiCategoryPageTest extends MediaWikiLangTestCase {
+
+       /**
+        * @return PHPUnit_Framework_MockObject_MockObject|PageProps
+        */
+       private function getMockPageProps() {
+               return $this->getMockBuilder( PageProps::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+       }
+
+       /**
+        * @covers WikiCategoryPage::isHidden
+        */
+       public function testHiddenCategory_PropertyNotSet() {
+               $title = Title::makeTitle( NS_CATEGORY, 'CategoryPage' );
+               $categoryPage = WikiCategoryPage::factory( $title );
+
+               $pageProps = $this->getMockPageProps();
+               $pageProps->expects( $this->once() )
+                       ->method( 'getProperties' )
+                       ->with( $title, 'hiddencat' )
+                       ->will( $this->returnValue( [ ] ) );
+
+               $scopedOverride = PageProps::overrideInstance( $pageProps );
+
+               $this->assertFalse( $categoryPage->isHidden() );
+
+               ScopedCallback::consume( $scopedOverride );
+       }
+
+       public function provideCategoryContent() {
+               return [
+                       [ true ],
+                       [ false ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideCategoryContent
+        * @covers WikiCategoryPage::isHidden
+        */
+       public function testHiddenCategory_PropertyIsSet( $isHidden ) {
+               $categoryTitle = Title::makeTitle( NS_CATEGORY, 'CategoryPage' );
+               $categoryPage = WikiCategoryPage::factory( $categoryTitle );
+
+               $pageProps = $this->getMockPageProps();
+               $pageProps->expects( $this->once() )
+                       ->method( 'getProperties' )
+                       ->with( $categoryTitle, 'hiddencat' )
+                       ->will( $this->returnValue( $isHidden ? [ $categoryTitle->getArticleID() => '' ] : [ ] ) );
+
+               $scopedOverride = PageProps::overrideInstance( $pageProps );
+
+               $this->assertEquals( $isHidden, $categoryPage->isHidden() );
+
+               ScopedCallback::consume( $scopedOverride );
+       }
+}