From: addshore Date: Tue, 15 Mar 2016 22:19:16 +0000 (+0000) Subject: Add WatchedItemStore::getWatchedItemsForUser X-Git-Tag: 1.31.0-rc.0~7541^2 X-Git-Url: http://git.cyclocoop.org/%24image?a=commitdiff_plain;h=659fd5ec9cecbb7f3774107a28a26b2b244de4a1;p=lhc%2Fweb%2Fwiklou.git Add WatchedItemStore::getWatchedItemsForUser This method is also no used in SpecialEditWatchlist Unit and Integration tests have also been added. Bug: T129481 Change-Id: Ica136b6fee63be8de4c2fe502288dd2318d99114 --- diff --git a/includes/WatchedItemStore.php b/includes/WatchedItemStore.php index b3a06e2737..26bba50d5a 100644 --- a/includes/WatchedItemStore.php +++ b/includes/WatchedItemStore.php @@ -396,6 +396,38 @@ class WatchedItemStore { return $item; } + /** + * @param User $user + * @param array $options Allowed keys: + * 'forWrite' => bool defaults to false + * + * @return WatchedItem[] + */ + public function getWatchedItemsForUser( User $user, array $options = [] ) { + $options += [ 'forWrite' => false ]; + + $db = $this->getConnection( $options['forWrite'] ? DB_MASTER : DB_SLAVE ); + $res = $db->select( + 'watchlist', + [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ], + [ 'wl_user' => $user->getId() ], + __METHOD__ + ); + $this->reuseConnection( $db ); + + $watchedItems = []; + foreach ( $res as $row ) { + // todo these could all be cached at some point? + $watchedItems[] = new WatchedItem( + $user, + new TitleValue( (int)$row->wl_namespace, $row->wl_title ), + $row->wl_notificationtimestamp + ); + } + + return $watchedItems; + } + /** * Must be called separately for Subject & Talk namespaces * diff --git a/includes/specials/SpecialEditWatchlist.php b/includes/specials/SpecialEditWatchlist.php index e76988dd7d..dd440b9689 100644 --- a/includes/specials/SpecialEditWatchlist.php +++ b/includes/specials/SpecialEditWatchlist.php @@ -307,32 +307,25 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { private function getWatchlist() { $list = []; - $index = $this->getRequest()->wasPosted() ? DB_MASTER : DB_SLAVE; - $dbr = wfGetDB( $index ); - - $res = $dbr->select( - 'watchlist', - [ - 'wl_namespace', 'wl_title' - ], [ - 'wl_user' => $this->getUser()->getId(), - ], - __METHOD__ + $watchedItems = WatchedItemStore::getDefaultInstance()->getWatchedItemsForUser( + $this->getUser(), + [ 'forWrite' => $this->getRequest()->wasPosted() ] ); - if ( $res->numRows() > 0 ) { + if ( $watchedItems ) { /** @var Title[] $titles */ $titles = []; - foreach ( $res as $row ) { - $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); + foreach ( $watchedItems as $watchedItem ) { + $namespace = $watchedItem->getLinkTarget()->getNamespace(); + $dbKey = $watchedItem->getLinkTarget()->getDBkey(); + $title = Title::makeTitleSafe( $namespace, $dbKey ); - if ( $this->checkTitle( $title, $row->wl_namespace, $row->wl_title ) + if ( $this->checkTitle( $title, $namespace, $dbKey ) && !$title->isTalkPage() ) { $titles[] = $title; } } - $res->free(); GenderCache::singleton()->doTitlesArray( $titles ); diff --git a/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php b/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php index 91dd1aae24..9eaa35a083 100644 --- a/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php +++ b/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php @@ -39,6 +39,21 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase { 'Page should be watched' ); $this->assertEquals( $initialUserWatchedItems + 1, $store->countWatchedItems( $user ) ); + $watchedItemsForUser = $store->getWatchedItemsForUser( $user ); + $this->assertCount( $initialUserWatchedItems + 1, $watchedItemsForUser ); + $watchedItemsForUserHasExpectedItem = false; + foreach ( $watchedItemsForUser as $watchedItem ) { + if ( + $watchedItem->getUser()->equals( $user ) && + $watchedItem->getLinkTarget() == $title->getTitleValue() + ) { + $watchedItemsForUserHasExpectedItem = true; + } + } + $this->assertTrue( + $watchedItemsForUserHasExpectedItem, + 'getWatchedItemsForUser should contain the page' + ); $this->assertEquals( $initialWatchers + 1, $store->countWatchers( $title ) ); $this->assertEquals( $initialWatchers + 1, @@ -59,6 +74,21 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase { 'Page should be unwatched' ); $this->assertEquals( $initialUserWatchedItems, $store->countWatchedItems( $user ) ); + $watchedItemsForUser = $store->getWatchedItemsForUser( $user ); + $this->assertCount( $initialUserWatchedItems, $watchedItemsForUser ); + $watchedItemsForUserHasExpectedItem = false; + foreach ( $watchedItemsForUser as $watchedItem ) { + if ( + $watchedItem->getUser()->equals( $user ) && + $watchedItem->getLinkTarget() == $title->getTitleValue() + ) { + $watchedItemsForUserHasExpectedItem = true; + } + } + $this->assertFalse( + $watchedItemsForUserHasExpectedItem, + 'getWatchedItemsForUser should not contain the page' + ); $this->assertEquals( $initialWatchers, $store->countWatchers( $title ) ); $this->assertEquals( $initialWatchers, diff --git a/tests/phpunit/includes/WatchedItemStoreUnitTest.php b/tests/phpunit/includes/WatchedItemStoreUnitTest.php index 983a5fe4dd..2996abf2e1 100644 --- a/tests/phpunit/includes/WatchedItemStoreUnitTest.php +++ b/tests/phpunit/includes/WatchedItemStoreUnitTest.php @@ -17,13 +17,20 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase { /** * @return PHPUnit_Framework_MockObject_MockObject|LoadBalancer */ - private function getMockLoadBalancer( $mockDb ) { + private function getMockLoadBalancer( $mockDb, $expectedConnectionType = null ) { $mock = $this->getMockBuilder( LoadBalancer::class ) ->disableOriginalConstructor() ->getMock(); - $mock->expects( $this->any() ) - ->method( 'getConnection' ) - ->will( $this->returnValue( $mockDb ) ); + if ( $expectedConnectionType !== null ) { + $mock->expects( $this->any() ) + ->method( 'getConnection' ) + ->with( $expectedConnectionType ) + ->will( $this->returnValue( $mockDb ) ); + } else { + $mock->expects( $this->any() ) + ->method( 'getConnection' ) + ->will( $this->returnValue( $mockDb ) ); + } $mock->expects( $this->any() ) ->method( 'getReadOnlyReason' ) ->will( $this->returnValue( false ) ); @@ -1139,6 +1146,93 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase { ); } + public function testGetWatchedItemsForUser() { + $mockDb = $this->getMockDb(); + $mockDb->expects( $this->once() ) + ->method( 'select' ) + ->with( + 'watchlist', + [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ], + [ 'wl_user' => 1 ] + ) + ->will( $this->returnValue( [ + $this->getFakeRow( [ + 'wl_namespace' => 0, + 'wl_title' => 'Foo1', + 'wl_notificationtimestamp' => '20151212010101', + ] ), + $this->getFakeRow( [ + 'wl_namespace' => 1, + 'wl_title' => 'Foo2', + 'wl_notificationtimestamp' => null, + ] ), + ] ) ); + + $mockCache = $this->getMockCache(); + $mockCache->expects( $this->never() )->method( 'delete' ); + $mockCache->expects( $this->never() )->method( 'get' ); + $mockCache->expects( $this->never() )->method( 'set' ); + + $store = new WatchedItemStore( + $this->getMockLoadBalancer( $mockDb ), + $mockCache + ); + $user = $this->getMockNonAnonUserWithId( 1 ); + + $watchedItems = $store->getWatchedItemsForUser( $user ); + + $this->assertInternalType( 'array', $watchedItems ); + $this->assertCount( 2, $watchedItems ); + foreach ( $watchedItems as $watchedItem ) { + $this->assertInstanceOf( 'WatchedItem', $watchedItem ); + } + $this->assertEquals( + new WatchedItem( $user, new TitleValue( 0, 'Foo1' ), '20151212010101' ), + $watchedItems[0] + ); + $this->assertEquals( + new WatchedItem( $user, new TitleValue( 1, 'Foo2' ), null ), + $watchedItems[1] + ); + } + + public function provideDbTypes() { + return [ + [ false, DB_SLAVE ], + [ true, DB_MASTER ], + ]; + } + + /** + * @dataProvider provideDbTypes + */ + public function testGetWatchedItemsForUser_optionsAndEmptyResult( $forWrite, $dbType ) { + $mockDb = $this->getMockDb(); + $mockCache = $this->getMockCache(); + $mockLoadBalancer = $this->getMockLoadBalancer( $mockDb, $dbType ); + $user = $this->getMockNonAnonUserWithId( 1 ); + + $mockDb->expects( $this->once() ) + ->method( 'select' ) + ->with( + 'watchlist', + [ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ], + [ 'wl_user' => 1 ] + ) + ->will( $this->returnValue( [] ) ); + + $store = new WatchedItemStore( + $mockLoadBalancer, + $mockCache + ); + + $watchedItems = $store->getWatchedItemsForUser( + $user, + [ 'forWrite' => $forWrite ] + ); + $this->assertEquals( [], $watchedItems ); + } + public function testIsWatchedItem_existingItem() { $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() )