If user only has foreign messages, the messages badge should not be suppressed

Bug: T124372
Change-Id: Id9699c56e9b8c6af77e74cbfc48b6e4e3464b3a5
This commit is contained in:
Matthias Mullie 2016-01-25 16:33:06 +01:00
parent a2563fe587
commit b9f2d026a6
3 changed files with 53 additions and 19 deletions

View file

@ -753,6 +753,8 @@ class EchoHooks {
'notifications-alert' => $alertLink, 'notifications-alert' => $alertLink,
); );
// hasMessages() checks if the user has ever had (local) messages, or if they
// have any currently unread message at all (including on foreign wikis)
if ( $notifUser->hasMessages() ) { if ( $notifUser->hasMessages() ) {
$msgLink = array( $msgLink = array(
'href' => $url, 'href' => $url,

View file

@ -183,7 +183,16 @@ class MWEchoNotifUser {
private function getHasMessagesKey() { private function getHasMessagesKey() {
global $wgEchoConfig; global $wgEchoConfig;
$lookup = CentralIdLookup::factory();
$id = $lookup->centralIdFromLocalUser( $this->mUser, CentralIdLookup::AUDIENCE_RAW );
if ( !$id ) {
// local user
return wfMemcKey( 'echo', 'user', 'had', 'messages', $this->mUser->getId(), $wgEchoConfig['version'] ); return wfMemcKey( 'echo', 'user', 'had', 'messages', $this->mUser->getId(), $wgEchoConfig['version'] );
} else {
// central user: we don't want a per-wiki cache key: as soon as the user
// gets a message on another wiki, this cache key should be altered
return wfGlobalCacheKey( 'echo', 'user', 'had', 'messages', $id, $wgEchoConfig['version'] );
}
} }
/** /**
@ -206,13 +215,39 @@ class MWEchoNotifUser {
$eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', array( $section ) ); $eventTypesToLoad = $attributeManager->getUserEnabledEventsbySections( $this->mUser, 'web', array( $section ) );
$count = count( $this->notifMapper->fetchByUser( $this->mUser, 1, 0, $eventTypesToLoad ) ); $count = count( $this->notifMapper->fetchByUser( $this->mUser, 1, 0, $eventTypesToLoad ) );
$result = (int)( $count > 0 ) || $this->hasForeignMessages();
$result = (int)( $count > 0 );
$this->cache->set( $memcKey, $result, 86400 ); $this->cache->set( $memcKey, $result, 86400 );
return (bool)$result; return (bool)$result;
} }
protected function hasForeignMessages() {
if ( !$this->mUser->getOption( 'echo-cross-wiki-notifications' ) ) {
return false;
}
$uw = EchoUnreadWikis::newFromUser( $this->mUser );
if ( $uw === false ) {
return false;
}
$counts = $uw->getUnreadCounts();
foreach ( $counts as $wiki => $data ) {
if ( $data[EchoAttributeManager::MESSAGE]['count'] > 0 ) {
// currently has unread notifications
return true;
}
if ( $data[EchoAttributeManager::MESSAGE]['ts'] !== EchoUnreadWikis::DEFAULT_TS ) {
// a timestamp at which notifications were read was recorded,
// which means the user must've had messages somewhere, at some point
return true;
}
}
return false;
}
/** /**
* Cache the fact that the user has messages. * Cache the fact that the user has messages.
* This is used after the user receives a message, making the system skip the actual test * This is used after the user receives a message, making the system skip the actual test

View file

@ -2,9 +2,13 @@
/** /**
* Manages what wikis a user has unread notifications on * Manages what wikis a user has unread notifications on
*
*/ */
class EchoUnreadWikis { class EchoUnreadWikis {
/**
* @var string
*/
const DEFAULT_TS = '00000000000000';
/** /**
* @var int * @var int
*/ */
@ -48,7 +52,7 @@ class EchoUnreadWikis {
} }
/** /**
* @return array * @return array Note that also wikis with 0 notifications and/or messages may be included
*/ */
public function getUnreadCounts() { public function getUnreadCounts() {
$dbr = $this->getDB( DB_SLAVE ); $dbr = $this->getDB( DB_SLAVE );
@ -69,10 +73,6 @@ class EchoUnreadWikis {
$wikis = array(); $wikis = array();
foreach ( $rows as $row ) { foreach ( $rows as $row ) {
if ( !$row->euw_alerts && !$row->euw_messages ) {
// This shouldn't happen, but lets be safe...
continue;
}
$wikis[$row->euw_wiki] = array( $wikis[$row->euw_wiki] = array(
EchoAttributeManager::ALERT => array( EchoAttributeManager::ALERT => array(
'count' => $row->euw_alerts, 'count' => $row->euw_alerts,
@ -101,18 +101,16 @@ class EchoUnreadWikis {
return; return;
} }
$defaultTS = '00000000000000';
if ( $alertCount || $msgCount ) { if ( $alertCount || $msgCount ) {
$values = array( $values = array(
'euw_alerts' => $alertCount, 'euw_alerts' => $alertCount,
'euw_alerts_ts' => $alertCount 'euw_alerts_ts' => $alertCount
? $alertTime->getTimestamp( TS_MW ) ? $alertTime->getTimestamp( TS_MW )
: $defaultTS, : static::DEFAULT_TS,
'euw_messages' => $msgCount, 'euw_messages' => $msgCount,
'euw_messages_ts' => $msgCount 'euw_messages_ts' => $msgCount
? $msgTime->getTimestamp( TS_MW ) ? $msgTime->getTimestamp( TS_MW )
: $defaultTS, : static::DEFAULT_TS,
); );
$dbw->upsert( $dbw->upsert(
'echo_unread_wikis', 'echo_unread_wikis',
@ -125,12 +123,11 @@ class EchoUnreadWikis {
__METHOD__ __METHOD__
); );
} else { } else {
// No unread notifications, delete the row // Even if there are no unread notifications, don't delete the row!
$dbw->delete( // That (empty) row helps us tell the difference between "has had
'echo_unread_wikis', // notifications but all have been seen" (0 count, non-0 timestamp)
array( 'euw_user' => $this->id, 'euw_wiki' => $wiki ), // and "has never had a notifications before" (row with 0 count and
__METHOD__ // 000 timestamp or no row at all)
);
} }
} }
} }