add setNotificationTimestampsForUser to WatchedItemStore
Bug: T134387 Change-Id: Ia6abe7687b51aabe67e8461375075692db28c9a2
This commit is contained in:
parent
33cb9e803a
commit
eacec0a223
4 changed files with 152 additions and 9 deletions
|
|
@ -145,16 +145,28 @@ class WatchedItemStore implements StatsdAwareInterface {
|
|||
}
|
||||
|
||||
private function uncacheLinkTarget( LinkTarget $target ) {
|
||||
$this->stats->increment( 'WatchedItemStore.uncacheLinkTarget' );
|
||||
if ( !isset( $this->cacheIndex[$target->getNamespace()][$target->getDBkey()] ) ) {
|
||||
return;
|
||||
}
|
||||
$this->stats->increment( 'WatchedItemStore.uncacheLinkTarget' );
|
||||
foreach ( $this->cacheIndex[$target->getNamespace()][$target->getDBkey()] as $key ) {
|
||||
$this->stats->increment( 'WatchedItemStore.uncacheLinkTarget.items' );
|
||||
$this->cache->delete( $key );
|
||||
}
|
||||
}
|
||||
|
||||
private function uncacheUser( User $user ) {
|
||||
$this->stats->increment( 'WatchedItemStore.uncacheUser' );
|
||||
foreach ( $this->cacheIndex as $ns => $dbKeyArray ) {
|
||||
foreach ( $dbKeyArray as $dbKey => $userArray ) {
|
||||
if ( isset( $userArray[$user->getId()] ) ) {
|
||||
$this->stats->increment( 'WatchedItemStore.uncacheUser.items' );
|
||||
$this->cache->delete( $userArray[$user->getId()] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param LinkTarget $target
|
||||
|
|
@ -667,6 +679,41 @@ class WatchedItemStore implements StatsdAwareInterface {
|
|||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user The user to set the timestamp for
|
||||
* @param string $timestamp Set the update timestamp to this value
|
||||
* @param LinkTarget[] $targets List of targets to update. Default to all targets
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function setNotificationTimestampsForUser( User $user, $timestamp, array $targets = [] ) {
|
||||
// Only loggedin user can have a watchlist
|
||||
if ( $user->isAnon() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dbw = $this->getConnection( DB_MASTER );
|
||||
|
||||
$conds = [ 'wl_user' => $user->getId() ];
|
||||
if ( $targets ) {
|
||||
$batch = new LinkBatch( $targets );
|
||||
$conds[] = $batch->constructSet( 'wl', $dbw );
|
||||
}
|
||||
|
||||
$success = $dbw->update(
|
||||
'watchlist',
|
||||
[ 'wl_notificationtimestamp' => $dbw->timestamp( $timestamp ) ],
|
||||
$conds,
|
||||
__METHOD__
|
||||
);
|
||||
|
||||
$this->reuseConnection( $dbw );
|
||||
|
||||
$this->uncacheUser( $user );
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $editor The editor that triggered the update. Their notification
|
||||
* timestamp will not be updated(they have already seen it)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*
|
||||
* @file
|
||||
*/
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
/**
|
||||
* API interface for setting the wl_notificationtimestamp field
|
||||
|
|
@ -98,13 +99,14 @@ class ApiSetNotificationTimestamp extends ApiBase {
|
|||
}
|
||||
}
|
||||
|
||||
$watchedItemStore = MediaWikiServices::getInstance()->getWatchedItemStore();
|
||||
$apiResult = $this->getResult();
|
||||
$result = [];
|
||||
if ( $params['entirewatchlist'] ) {
|
||||
// Entire watchlist mode: Just update the thing and return a success indicator
|
||||
$dbw->update( 'watchlist', [ 'wl_notificationtimestamp' => $timestamp ],
|
||||
[ 'wl_user' => $user->getId() ],
|
||||
__METHOD__
|
||||
$watchedItemStore->setNotificationTimestampsForUser(
|
||||
$user,
|
||||
$timestamp
|
||||
);
|
||||
|
||||
$result['notificationtimestamp'] = is_null( $timestamp )
|
||||
|
|
@ -133,14 +135,15 @@ class ApiSetNotificationTimestamp extends ApiBase {
|
|||
|
||||
if ( $pageSet->getTitles() ) {
|
||||
// Now process the valid titles
|
||||
$lb = new LinkBatch( $pageSet->getTitles() );
|
||||
$dbw->update( 'watchlist', [ 'wl_notificationtimestamp' => $timestamp ],
|
||||
[ 'wl_user' => $user->getId(), $lb->constructSet( 'wl', $dbw ) ],
|
||||
__METHOD__
|
||||
$watchedItemStore->setNotificationTimestampsForUser(
|
||||
$user,
|
||||
$timestamp,
|
||||
$pageSet->getTitles()
|
||||
);
|
||||
|
||||
// Query the results of our update
|
||||
$timestamps = [];
|
||||
$lb = new LinkBatch( $pageSet->getTitles() );
|
||||
$res = $dbw->select(
|
||||
'watchlist',
|
||||
[ 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ],
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public function testUpdateAndResetNotificationTimestamp() {
|
||||
public function testUpdateResetAndSetNotificationTimestamp() {
|
||||
$user = $this->getUser();
|
||||
$otherUser = ( new TestUser( 'WatchedItemStoreIntegrationTestUser_otherUser' ) )->getUser();
|
||||
$title = Title::newFromText( 'WatchedItemStoreIntegrationTestPage' );
|
||||
|
|
@ -172,6 +172,24 @@ class WatchedItemStoreIntegrationTest extends MediaWikiTestCase {
|
|||
[ [ $title, '20150202020202' ] ], $initialVisitingWatchers + 1
|
||||
)
|
||||
);
|
||||
|
||||
// setNotificationTimestampsForUser specifying a title
|
||||
$this->assertTrue(
|
||||
$store->setNotificationTimestampsForUser( $user, '20200202020202', [ $title ] )
|
||||
);
|
||||
$this->assertEquals(
|
||||
'20200202020202',
|
||||
$store->getWatchedItem( $user, $title )->getNotificationTimestamp()
|
||||
);
|
||||
|
||||
// setNotificationTimestampsForUser not specifying a title
|
||||
$this->assertTrue(
|
||||
$store->setNotificationTimestampsForUser( $user, '20210202020202' )
|
||||
);
|
||||
$this->assertEquals(
|
||||
'20210202020202',
|
||||
$store->getWatchedItem( $user, $title )->getNotificationTimestamp()
|
||||
);
|
||||
}
|
||||
|
||||
public function testDuplicateAllAssociatedEntries() {
|
||||
|
|
|
|||
|
|
@ -2366,6 +2366,81 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
|
|||
ScopedCallback::consume( $scopedOverrideRevision );
|
||||
}
|
||||
|
||||
public function testSetNotificationTimestampsForUser_anonUser() {
|
||||
$store = $this->newWatchedItemStore(
|
||||
$this->getMockLoadBalancer( $this->getMockDb() ),
|
||||
$this->getMockCache()
|
||||
);
|
||||
$this->assertFalse( $store->setNotificationTimestampsForUser( $this->getAnonUser(), '' ) );
|
||||
}
|
||||
|
||||
public function testSetNotificationTimestampsForUser_allRows() {
|
||||
$user = $this->getMockNonAnonUserWithId( 1 );
|
||||
$timestamp = '20100101010101';
|
||||
|
||||
$mockDb = $this->getMockDb();
|
||||
$mockDb->expects( $this->once() )
|
||||
->method( 'update' )
|
||||
->with(
|
||||
'watchlist',
|
||||
[ 'wl_notificationtimestamp' => 'TS' . $timestamp . 'TS' ],
|
||||
[ 'wl_user' => 1 ]
|
||||
)
|
||||
->will( $this->returnValue( true ) );
|
||||
$mockDb->expects( $this->exactly( 1 ) )
|
||||
->method( 'timestamp' )
|
||||
->will( $this->returnCallback( function( $value ) {
|
||||
return 'TS' . $value . 'TS';
|
||||
} ) );
|
||||
|
||||
$store = $this->newWatchedItemStore(
|
||||
$this->getMockLoadBalancer( $mockDb ),
|
||||
$this->getMockCache()
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$store->setNotificationTimestampsForUser( $user, $timestamp )
|
||||
);
|
||||
}
|
||||
|
||||
public function testSetNotificationTimestampsForUser_specificTargets() {
|
||||
$user = $this->getMockNonAnonUserWithId( 1 );
|
||||
$timestamp = '20100101010101';
|
||||
$targets = [ new TitleValue( 0, 'Foo' ), new TitleValue( 0, 'Bar' ) ];
|
||||
|
||||
$mockDb = $this->getMockDb();
|
||||
$mockDb->expects( $this->once() )
|
||||
->method( 'update' )
|
||||
->with(
|
||||
'watchlist',
|
||||
[ 'wl_notificationtimestamp' => 'TS' . $timestamp . 'TS' ],
|
||||
[ 'wl_user' => 1, 0 => 'makeWhereFrom2d return value' ]
|
||||
)
|
||||
->will( $this->returnValue( true ) );
|
||||
$mockDb->expects( $this->exactly( 1 ) )
|
||||
->method( 'timestamp' )
|
||||
->will( $this->returnCallback( function( $value ) {
|
||||
return 'TS' . $value . 'TS';
|
||||
} ) );
|
||||
$mockDb->expects( $this->once() )
|
||||
->method( 'makeWhereFrom2d' )
|
||||
->with(
|
||||
[ [ 'Foo' => 1, 'Bar' => 1 ] ],
|
||||
$this->isType( 'string' ),
|
||||
$this->isType( 'string' )
|
||||
)
|
||||
->will( $this->returnValue( 'makeWhereFrom2d return value' ) );
|
||||
|
||||
$store = $this->newWatchedItemStore(
|
||||
$this->getMockLoadBalancer( $mockDb ),
|
||||
$this->getMockCache()
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$store->setNotificationTimestampsForUser( $user, $timestamp, $targets )
|
||||
);
|
||||
}
|
||||
|
||||
public function testUpdateNotificationTimestamp_watchersExist() {
|
||||
$mockDb = $this->getMockDb();
|
||||
$mockDb->expects( $this->once() )
|
||||
|
|
|
|||
Loading…
Reference in a new issue