From: addshore Date: Fri, 5 Feb 2016 12:04:58 +0000 (+0100) Subject: Move countVisitingWatchers to WatchedItemStore X-Git-Tag: 1.31.0-rc.0~7614^2 X-Git-Url: https://git.cyclocoop.org/%28%28?a=commitdiff_plain;h=0b852c5717fc535528825704f41ac6d50a7be022;p=lhc%2Fweb%2Fwiklou.git Move countVisitingWatchers to WatchedItemStore Also adds tests Bug: T129479 Change-Id: I2868c31fc09121de381d822e8f49194e3022bb42 --- diff --git a/includes/WatchedItemStore.php b/includes/WatchedItemStore.php index 86e4925176..c59beec4f0 100644 --- a/includes/WatchedItemStore.php +++ b/includes/WatchedItemStore.php @@ -205,6 +205,35 @@ class WatchedItemStore { return $return; } + /** + * Number of page watchers who also visited a "recent" edit + * + * @param LinkTarget $target + * @param mixed $threshold timestamp accepted by wfTimestamp + * + * @return int + * @throws DBUnexpectedError + * @throws MWException + */ + public function countVisitingWatchers( LinkTarget $target, $threshold ) { + $dbr = $this->loadBalancer->getConnection( DB_SLAVE, [ 'watchlist' ] ); + $visitingWatchers = (int)$dbr->selectField( + 'watchlist', + 'COUNT(*)', + [ + 'wl_namespace' => $target->getNamespace(), + 'wl_title' => $target->getDBkey(), + 'wl_notificationtimestamp >= ' . + $dbr->addQuotes( $dbr->timestamp( $threshold ) ) . + ' OR wl_notificationtimestamp IS NULL' + ], + __METHOD__ + ); + $this->loadBalancer->reuseConnection( $dbr ); + + return $visitingWatchers; + } + /** * @param LinkTarget[] $targets * @param array $options Allowed keys: diff --git a/includes/actions/InfoAction.php b/includes/actions/InfoAction.php index 60829b1db2..4596e41379 100644 --- a/includes/actions/InfoAction.php +++ b/includes/actions/InfoAction.php @@ -677,28 +677,17 @@ class InfoAction extends FormlessAction { $setOpts += Database::getCacheSetOptions( $dbr, $dbrWatchlist ); + $watchedItemStore = WatchedItemStore::getDefaultInstance(); + $result = []; - $result['watchers'] = WatchedItemStore::getDefaultInstance()->countWatchers( $title ); + $result['watchers'] = $watchedItemStore->countWatchers( $title ); if ( $config->get( 'ShowUpdatedMarker' ) ) { - // Threshold: last visited about 26 weeks before latest edit $updated = wfTimestamp( TS_UNIX, $page->getTimestamp() ); - $age = $config->get( 'WatchersMaxAge' ); - $threshold = $dbrWatchlist->timestamp( $updated - $age ); - // Number of page watchers who also visited a "recent" edit - $visitingWatchers = (int)$dbrWatchlist->selectField( - 'watchlist', - 'COUNT(*)', - [ - 'wl_namespace' => $title->getNamespace(), - 'wl_title' => $title->getDBkey(), - 'wl_notificationtimestamp >= ' . - $dbrWatchlist->addQuotes( $threshold ) . - ' OR wl_notificationtimestamp IS NULL' - ], - $fname + $result['visitingWatchers'] = $watchedItemStore->countVisitingWatchers( + $title, + $updated - $config->get( 'WatchersMaxAge' ) ); - $result['visitingWatchers'] = $visitingWatchers; } // Total number of edits diff --git a/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php b/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php index 3e5f261934..2aa9027408 100644 --- a/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php +++ b/tests/phpunit/includes/WatchedItemStoreIntegrationTest.php @@ -70,15 +70,24 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase { $store = WatchedItemStore::getDefaultInstance(); $store->addWatch( $user, $title ); $this->assertNull( $store->loadWatchedItem( $user, $title )->getNotificationTimestamp() ); + $initialVisitingWatchers = $store->countVisitingWatchers( $title, '20150202020202' ); $store->updateNotificationTimestamp( $otherUser, $title, '20150202010101' ); $this->assertEquals( '20150202010101', $store->loadWatchedItem( $user, $title )->getNotificationTimestamp() ); + $this->assertEquals( + $initialVisitingWatchers - 1, + $store->countVisitingWatchers( $title, '20150202020202' ) + ); $this->assertTrue( $store->resetNotificationTimestamp( $user, $title ) ); $this->assertNull( $store->getWatchedItem( $user, $title )->getNotificationTimestamp() ); + $this->assertEquals( + $initialVisitingWatchers, + $store->countVisitingWatchers( $title, '20150202020202' ) + ); } public function testDuplicateAllAssociatedEntries() { diff --git a/tests/phpunit/includes/WatchedItemStoreUnitTest.php b/tests/phpunit/includes/WatchedItemStoreUnitTest.php index c8621fc3b4..988ffed01a 100644 --- a/tests/phpunit/includes/WatchedItemStoreUnitTest.php +++ b/tests/phpunit/includes/WatchedItemStoreUnitTest.php @@ -235,6 +235,47 @@ class WatchedItemStoreUnitTest extends PHPUnit_Framework_TestCase { ); } + public function testCountVisitingWatchers() { + $titleValue = new TitleValue( 0, 'SomeDbKey' ); + + $mockDb = $this->getMockDb(); + $mockDb->expects( $this->exactly( 1 ) ) + ->method( 'selectField' ) + ->with( + 'watchlist', + 'COUNT(*)', + [ + 'wl_namespace' => $titleValue->getNamespace(), + 'wl_title' => $titleValue->getDBkey(), + 'wl_notificationtimestamp >= \'TS111TS\' OR wl_notificationtimestamp IS NULL', + ], + $this->isType( 'string' ) + ) + ->will( $this->returnValue( 7 ) ); + $mockDb->expects( $this->exactly( 1 ) ) + ->method( 'addQuotes' ) + ->will( $this->returnCallback( function( $value ) { + return "'$value'"; + } ) ); + $mockDb->expects( $this->exactly( 1 ) ) + ->method( 'timestamp' ) + ->will( $this->returnCallback( function( $value ) { + return 'TS' . $value . 'TS'; + } ) ); + + $mockCache = $this->getMockCache(); + $mockCache->expects( $this->never() )->method( 'set' ); + $mockCache->expects( $this->never() )->method( 'get' ); + $mockCache->expects( $this->never() )->method( 'delete' ); + + $store = new WatchedItemStore( + $this->getMockLoadBalancer( $mockDb ), + $mockCache + ); + + $this->assertEquals( 7, $store->countVisitingWatchers( $titleValue, '111' ) ); + } + public function testDuplicateEntry_nothingToDuplicate() { $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() )