MediaWiki  master
TalkPageNotificationManager.php
Go to the documentation of this file.
1 <?php
2 
22 namespace MediaWiki\User;
23 
27 use MWTimestamp;
28 use ReadOnlyMode;
30 
36 
40  public const CONSTRUCTOR_OPTIONS = [
41  'DisableAnonTalk'
42  ];
43 
45  private $userMessagesCache = [];
46 
49 
51  private $loadBalancer;
52 
54  private $readOnlyMode;
55 
57  private $revisionLookup;
58 
65  public function __construct(
66  ServiceOptions $serviceOptions,
70  ) {
71  $serviceOptions->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
72  $this->disableAnonTalk = $serviceOptions->get( 'DisableAnonTalk' );
73  $this->loadBalancer = $loadBalancer;
74  $this->readOnlyMode = $readOnlyMode;
75  $this->revisionLookup = $revisionLookup;
76  }
77 
83  public function userHasNewMessages( UserIdentity $user ) : bool {
84  $userKey = $this->getCacheKey( $user );
85 
86  // Load the newtalk status if it is unloaded
87  if ( !isset( $this->userMessagesCache[$userKey] ) ) {
88  if ( $this->isTalkDisabled( $user ) ) {
89  // Anon disabled by configuration.
90  $this->userMessagesCache[$userKey] = false;
91  } else {
92  $this->userMessagesCache[$userKey] = $this->dbCheckNewUserMessages( $user );
93  }
94  }
95 
96  return (bool)$this->userMessagesCache[$userKey];
97  }
98 
107  public function setUserHasNewMessages(
108  UserIdentity $user,
109  RevisionRecord $curRev = null
110  ) : void {
111  if ( $this->isTalkDisabled( $user ) ) {
112  return;
113  }
114 
115  $userKey = $this->getCacheKey( $user );
116  $this->userMessagesCache[$userKey] = true;
117  $this->dbUpdateNewUserMessages( $user, $curRev );
118  }
119 
124  public function removeUserHasNewMessages( UserIdentity $user ) : void {
125  if ( $this->isTalkDisabled( $user ) ) {
126  return;
127  }
128 
129  $userKey = $this->getCacheKey( $user );
130  $this->userMessagesCache[$userKey] = false;
131 
132  $this->dbDeleteNewUserMessages( $user );
133  }
134 
143  public function getLatestSeenMessageTimestamp( UserIdentity $user ) : ?string {
144  $userKey = $this->getCacheKey( $user );
145  // Don't use self::userHasNewMessages here to avoid an extra DB query
146  // in case the value is not cached already
147  if ( $this->isTalkDisabled( $user ) ||
148  isset( $this->userMessagesCache[$userKey] ) && !$this->userMessagesCache[$userKey]
149  ) {
150  return null;
151  }
152 
153  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
154  list( $field, $id ) = $this->getQueryFieldAndId( $user );
155  // Get the "last viewed rev" timestamp from the oldest message notification
156  $timestamp = $dbr->selectField(
157  'user_newtalk',
158  'MIN(user_last_timestamp)',
159  [ $field => $id ],
160  __METHOD__
161  );
162  if ( $timestamp ) {
163  // TODO: Once passing 'null' as Revision setUserHasNewMessages is removed,
164  // null $timestamp would mean no new messages, so negatives can be cached too.
165  $this->userMessagesCache[$userKey] = true;
166  }
167  return $timestamp !== null ? MWTimestamp::convert( TS_MW, $timestamp ) : null;
168  }
169 
175  public function clearInstanceCache( UserIdentity $user ) : void {
176  $userKey = $this->getCacheKey( $user );
177  $this->userMessagesCache[$userKey] = null;
178  }
179 
185  private function isTalkDisabled( UserIdentity $user ) : bool {
186  return !$user->isRegistered() && $this->disableAnonTalk;
187  }
188 
194  private function dbCheckNewUserMessages( UserIdentity $user ) : bool {
195  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
196  list( $field, $id ) = $this->getQueryFieldAndId( $user );
197  $ok = $dbr->selectField(
198  'user_newtalk',
199  $field,
200  [ $field => $id ],
201  __METHOD__
202  );
203  return (bool)$ok;
204  }
205 
213  private function dbUpdateNewUserMessages(
214  UserIdentity $user,
215  RevisionRecord $curRev = null
216  ) : bool {
217  if ( $this->readOnlyMode->isReadOnly() ) {
218  return false;
219  }
220 
221  if ( $curRev ) {
222  $prevRev = $this->revisionLookup->getPreviousRevision( $curRev );
223  $ts = $prevRev ? $prevRev->getTimestamp() : null;
224  } else {
225  $ts = null;
226  }
227 
228  // Mark the user as having new messages since this revision
229  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
230  list( $field, $id ) = $this->getQueryFieldAndId( $user );
231  $dbw->insert(
232  'user_newtalk',
233  [
234  $field => $id,
235  'user_last_timestamp' => $dbw->timestampOrNull( $ts )
236  ],
237  __METHOD__,
238  [ 'IGNORE' ]
239  );
240  return (bool)$dbw->affectedRows();
241  }
242 
248  private function dbDeleteNewUserMessages( UserIdentity $user ) : bool {
249  if ( $this->readOnlyMode->isReadOnly() ) {
250  return false;
251  }
252  $dbw = $this->loadBalancer->getConnectionRef( DB_PRIMARY );
253  list( $field, $id ) = $this->getQueryFieldAndId( $user );
254  $dbw->delete(
255  'user_newtalk',
256  [ $field => $id ],
257  __METHOD__
258  );
259  return (bool)$dbw->affectedRows();
260  }
261 
267  private function getQueryFieldAndId( UserIdentity $user ) : array {
268  if ( $user->isRegistered() ) {
269  $field = 'user_id';
270  $id = $user->getId();
271  } else {
272  $field = 'user_ip';
273  $id = $user->getName();
274  }
275  return [ $field, $id ];
276  }
277 
283  private function getCacheKey( UserIdentity $user ) : string {
284  return $user->isRegistered() ? "u:{$user->getId()}" : "anon:{$user->getName()}";
285  }
286 }
MWTimestamp
Library for creating and parsing MW-style timestamps.
Definition: MWTimestamp.php:38
MediaWiki\User\TalkPageNotificationManager\CONSTRUCTOR_OPTIONS
const CONSTRUCTOR_OPTIONS
Definition: TalkPageNotificationManager.php:40
MediaWiki\Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:47
MediaWiki\User\TalkPageNotificationManager\$loadBalancer
ILoadBalancer $loadBalancer
Definition: TalkPageNotificationManager.php:51
MediaWiki\User\TalkPageNotificationManager\isTalkDisabled
isTalkDisabled(UserIdentity $user)
Check whether the talk page is disabled for a user.
Definition: TalkPageNotificationManager.php:185
ReadOnlyMode
A service class for fetching the wiki's current read-only mode.
Definition: ReadOnlyMode.php:11
MediaWiki\User\TalkPageNotificationManager\removeUserHasNewMessages
removeUserHasNewMessages(UserIdentity $user)
Remove the new messages status.
Definition: TalkPageNotificationManager.php:124
MediaWiki\User\TalkPageNotificationManager\__construct
__construct(ServiceOptions $serviceOptions, ILoadBalancer $loadBalancer, ReadOnlyMode $readOnlyMode, RevisionLookup $revisionLookup)
Definition: TalkPageNotificationManager.php:65
MediaWiki\User\UserIdentity\getId
getId( $wikiId=self::LOCAL)
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
MediaWiki\Revision\RevisionLookup
Service for looking up page revisions.
Definition: RevisionLookup.php:38
MediaWiki\User\TalkPageNotificationManager
Manages user talk page notifications.
Definition: TalkPageNotificationManager.php:35
$dbr
$dbr
Definition: testCompression.php:54
MediaWiki\User\TalkPageNotificationManager\dbDeleteNewUserMessages
dbDeleteNewUserMessages(UserIdentity $user)
Clear the new messages flag for the given user.
Definition: TalkPageNotificationManager.php:248
MediaWiki\User\TalkPageNotificationManager\setUserHasNewMessages
setUserHasNewMessages(UserIdentity $user, RevisionRecord $curRev=null)
Update the talk page messages status.
Definition: TalkPageNotificationManager.php:107
MediaWiki\User\TalkPageNotificationManager\getCacheKey
getCacheKey(UserIdentity $user)
Gets a unique key for various caches.
Definition: TalkPageNotificationManager.php:283
MediaWiki\Config\ServiceOptions
A class for passing options to services.
Definition: ServiceOptions.php:27
MediaWiki\User\TalkPageNotificationManager\$userMessagesCache
array $userMessagesCache
Definition: TalkPageNotificationManager.php:45
MediaWiki\User\UserIdentity\isRegistered
isRegistered()
MediaWiki\User\TalkPageNotificationManager\$revisionLookup
RevisionLookup $revisionLookup
Definition: TalkPageNotificationManager.php:57
MediaWiki\User\TalkPageNotificationManager\getQueryFieldAndId
getQueryFieldAndId(UserIdentity $user)
Get the field name and id for the user_newtalk table query.
Definition: TalkPageNotificationManager.php:267
MediaWiki\User\TalkPageNotificationManager\dbUpdateNewUserMessages
dbUpdateNewUserMessages(UserIdentity $user, RevisionRecord $curRev=null)
Add or update the new messages flag.
Definition: TalkPageNotificationManager.php:213
MediaWiki\User\UserIdentity\getName
getName()
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
DB_PRIMARY
const DB_PRIMARY
Definition: defines.php:27
MediaWiki\User
Definition: ActorCache.php:21
MediaWiki\User\TalkPageNotificationManager\dbCheckNewUserMessages
dbCheckNewUserMessages(UserIdentity $user)
Internal uncached check for new messages.
Definition: TalkPageNotificationManager.php:194
MediaWiki\User\TalkPageNotificationManager\clearInstanceCache
clearInstanceCache(UserIdentity $user)
Remove the cached newtalk status for the given user.
Definition: TalkPageNotificationManager.php:175
MediaWiki\User\TalkPageNotificationManager\$disableAnonTalk
bool $disableAnonTalk
Definition: TalkPageNotificationManager.php:48
MediaWiki\User\TalkPageNotificationManager\userHasNewMessages
userHasNewMessages(UserIdentity $user)
Check if the user has new messages.
Definition: TalkPageNotificationManager.php:83
MediaWiki\User\TalkPageNotificationManager\$readOnlyMode
ReadOnlyMode $readOnlyMode
Definition: TalkPageNotificationManager.php:54
MediaWiki\Config\ServiceOptions\get
get( $key)
Definition: ServiceOptions.php:88
MediaWiki\User\TalkPageNotificationManager\getLatestSeenMessageTimestamp
getLatestSeenMessageTimestamp(UserIdentity $user)
Returns the timestamp of the latest revision of the user talkpage that the user has already seen in T...
Definition: TalkPageNotificationManager.php:143
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
MediaWiki\Config\ServiceOptions\assertRequiredOptions
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
Definition: ServiceOptions.php:66