Merge "Dont count RC_CATEGORIZE in Special:ActiveUsers"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 24 Mar 2016 17:10:35 +0000 (17:10 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 24 Mar 2016 17:10:35 +0000 (17:10 +0000)
includes/WatchedItemStore.php
includes/page/Article.php
includes/specials/SpecialEditWatchlist.php
includes/specials/SpecialWatchlist.php
includes/utils/ZipDirectoryReader.php
tests/phpunit/includes/WatchedItemStoreUnitTest.php
tests/phpunit/includes/specials/SpecialEditWatchlistTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialWatchlistTest.php [new file with mode: 0644]

index 20ec592..4eea54d 100644 (file)
@@ -12,6 +12,9 @@ use Wikimedia\Assert\Assert;
  */
 class WatchedItemStore {
 
+       const SORT_DESC = 'DESC';
+       const SORT_ASC = 'ASC';
+
        /**
         * @var LoadBalancer
         */
@@ -494,18 +497,34 @@ class WatchedItemStore {
         * @param User $user
         * @param array $options Allowed keys:
         *        'forWrite' => bool defaults to false
+        *        'sort' => string optional sorting by namespace ID and title
+        *                     one of the self::SORT_* constants
         *
         * @return WatchedItem[]
         */
        public function getWatchedItemsForUser( User $user, array $options = [] ) {
                $options += [ 'forWrite' => false ];
 
+               $dbOptions = [];
+               if ( array_key_exists( 'sort', $options ) ) {
+                       Assert::parameter(
+                               ( in_array( $options['sort'], [ self::SORT_ASC, self::SORT_DESC ] ) ),
+                               '$options[\'sort\']',
+                               'must be SORT_ASC or SORT_DESC'
+                       );
+                       $dbOptions['ORDER BY'] = [
+                               "wl_namespace {$options['sort']}",
+                               "wl_title {$options['sort']}"
+                       ];
+               }
                $db = $this->getConnection( $options['forWrite'] ? DB_MASTER : DB_SLAVE );
+
                $res = $db->select(
                        'watchlist',
                        [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
                        [ 'wl_user' => $user->getId() ],
-                       __METHOD__
+                       __METHOD__,
+                       $dbOptions
                );
                $this->reuseConnection( $db );
 
index b561407..d57d3fd 100644 (file)
@@ -1574,7 +1574,7 @@ class Article implements Page {
                                [],
                                // Automatically append redirect=no to each link, since most of them are
                                // redirect pages themselves.
-                               [ 'redirect' => 'no' ],
+                               $title->isRedirect() ? [ 'redirect' => 'no' ] : [],
                                ( $forceKnown ? [ 'known', 'noclasses' ] : [] )
                        ) . '</li>';
                }
index 9c1f224..a9753ae 100644 (file)
@@ -347,22 +347,18 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         */
        protected function getWatchlistInfo() {
                $titles = [];
-               $dbr = wfGetDB( DB_SLAVE );
 
-               $res = $dbr->select(
-                       [ 'watchlist' ],
-                       [ 'wl_namespace', 'wl_title' ],
-                       [ 'wl_user' => $this->getUser()->getId() ],
-                       __METHOD__,
-                       [ 'ORDER BY' => [ 'wl_namespace', 'wl_title' ] ]
-               );
+               $watchedItems = WatchedItemStore::getDefaultInstance()
+                       ->getWatchedItemsForUser( $this->getUser(), [ 'sort' => WatchedItemStore::SORT_ASC ] );
 
                $lb = new LinkBatch();
 
-               foreach ( $res as $row ) {
-                       $lb->add( $row->wl_namespace, $row->wl_title );
-                       if ( !MWNamespace::isTalk( $row->wl_namespace ) ) {
-                               $titles[$row->wl_namespace][$row->wl_title] = 1;
+               foreach ( $watchedItems as $watchedItem ) {
+                       $namespace = $watchedItem->getLinkTarget()->getNamespace();
+                       $dbKey = $watchedItem->getLinkTarget()->getDBkey();
+                       $lb->add( $namespace, $dbKey );
+                       if ( !MWNamespace::isTalk( $namespace ) ) {
+                               $titles[$namespace][$dbKey] = 1;
                        }
                }
 
index 2dda093..27e5829 100644 (file)
@@ -382,7 +382,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                        }
 
                        if ( isset( $watchedItemStore ) ) {
-                               $rcTitleValue = new TitleValue( $obj->rc_namespace, $obj->rc_title );
+                               $rcTitleValue = new TitleValue( (int)$obj->rc_namespace, $obj->rc_title );
                                $rc->numberofWatchingusers = $watchedItemStore->countWatchers( $rcTitleValue );
                        } else {
                                $rc->numberofWatchingusers = 0;
index 44815b4..516e9ae 100644 (file)
@@ -215,6 +215,10 @@ class ZipDirectoryReader {
                        $startPos = 0;
                }
 
+               if ( $this->getFileLength() === 0 ) {
+                       $this->error( 'zip-wrong-format', "The file is empty." );
+               }
+
                $block = $this->getBlock( $startPos );
                $sigPos = strrpos( $block, "PK\x05\x06" );
                if ( $sigPos === false ) {
index 1354b1c..afde88c 100644 (file)
@@ -1458,7 +1458,9 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
                        ->with(
                                'watchlist',
                                [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
-                               [ 'wl_user' => 1 ]
+                               [ 'wl_user' => 1 ],
+                               $this->isType( 'string' ),
+                               [ 'ORDER BY' => [ 'wl_namespace ASC', 'wl_title ASC' ] ]
                        )
                        ->will( $this->returnValue( [] ) );
 
@@ -1469,11 +1471,24 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase {
 
                $watchedItems = $store->getWatchedItemsForUser(
                        $user,
-                       [ 'forWrite' => $forWrite ]
+                       [ 'forWrite' => $forWrite, 'sort' => WatchedItemStore::SORT_ASC ]
                );
                $this->assertEquals( [], $watchedItems );
        }
 
+       public function testGetWatchedItemsForUser_badSortOptionThrowsException() {
+               $store = new WatchedItemStore(
+                       $this->getMockLoadBalancer( $this->getMockDb() ),
+                       $this->getMockCache()
+               );
+
+               $this->setExpectedException( 'InvalidArgumentException' );
+               $store->getWatchedItemsForUser(
+                       $this->getMockNonAnonUserWithId( 1 ),
+                       [ 'sort' => 'foo' ]
+               );
+       }
+
        public function testIsWatchedItem_existingItem() {
                $mockDb = $this->getMockDb();
                $mockDb->expects( $this->once() )
diff --git a/tests/phpunit/includes/specials/SpecialEditWatchlistTest.php b/tests/phpunit/includes/specials/SpecialEditWatchlistTest.php
new file mode 100644 (file)
index 0000000..cd84d79
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @author Addshore
+ *
+ * @group Database
+ *
+ * @covers SpecialEditWatchlist
+ */
+class SpecialEditWatchlistTest extends SpecialPageTestBase {
+
+       /**
+        * Returns a new instance of the special page under test.
+        *
+        * @return SpecialPage
+        */
+       protected function newSpecialPage() {
+               return new SpecialEditWatchlist();
+       }
+
+       public function testNotLoggedIn_throwsException() {
+               $this->setExpectedException( 'UserNotLoggedIn' );
+               $this->executeSpecialPage();
+       }
+
+       public function testRootPage_displaysExplanationMessage() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( '', null, 'qqx', $user->getUser() );
+               $this->assertContains( '(watchlistedit-normal-explain)', $html );
+       }
+
+       public function testClearPage_hasClearButtonForm() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( 'clear', null, 'qqx', $user->getUser() );
+               $this->assertRegExp(
+                       '/<form action=".*?Special:EditWatchlist\/clear" method="post" class="visualClear">/',
+                       $html
+               );
+       }
+
+       public function testEditRawPage_hasTitlesBox() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( 'raw', null, 'qqx', $user->getUser() );
+               $this->assertContains(
+                       '<textarea id="mw-input-wpTitles"',
+                       $html
+               );
+       }
+
+}
diff --git a/tests/phpunit/includes/specials/SpecialWatchlistTest.php b/tests/phpunit/includes/specials/SpecialWatchlistTest.php
new file mode 100644 (file)
index 0000000..6e702b6
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @author Addshore
+ *
+ * @group Database
+ *
+ * @covers SpecialWatchlist
+ */
+class SpecialWatchlistTest extends SpecialPageTestBase {
+
+       /**
+        * Returns a new instance of the special page under test.
+        *
+        * @return SpecialPage
+        */
+       protected function newSpecialPage() {
+               return new SpecialWatchlist();
+       }
+
+       public function testNotLoggedIn_throwsException() {
+               $this->setExpectedException( 'UserNotLoggedIn' );
+               $this->executeSpecialPage();
+       }
+
+       public function testUserWithNoWatchedItems_displaysNoWatchlistMessage() {
+               $user = new TestUser( __METHOD__ );
+               list( $html, ) = $this->executeSpecialPage( '', null, 'qqx', $user->getUser() );
+               $this->assertContains( '(nowatchlist)', $html );
+       }
+
+}