MediaWiki  master
UserEditTracker.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\User;
4 
7 use InvalidArgumentException;
8 use JobQueueGroup;
12 use Wikimedia\Timestamp\ConvertibleTimestamp;
13 
22 
23  private const FIRST_EDIT = 1;
24  private const LATEST_EDIT = 2;
25 
27  private $actorMigration;
28 
30  private $loadBalancer;
31 
33  private $jobQueueGroup;
34 
41  private $userEditCountCache = [];
42 
48  public function __construct(
52  ) {
53  $this->actorMigration = $actorMigration;
54  $this->loadBalancer = $loadBalancer;
55  $this->jobQueueGroup = $jobQueueGroup;
56  }
57 
64  public function getUserEditCount( UserIdentity $user ): ?int {
65  if ( !$user->isRegistered() ) {
66  return null;
67  }
68 
69  $userId = $user->getId();
70  $cacheKey = 'u' . (string)$userId;
71 
72  if ( isset( $this->userEditCountCache[ $cacheKey ] ) ) {
73  return $this->userEditCountCache[ $cacheKey ];
74  }
75 
76  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
77  $count = $dbr->selectField(
78  'user',
79  'user_editcount',
80  [ 'user_id' => $userId ],
81  __METHOD__
82  );
83 
84  if ( $count === null ) {
85  // it has not been initialized. do so.
86  $count = $this->initializeUserEditCount( $user );
87  }
88 
89  $this->userEditCountCache[ $cacheKey ] = $count;
90  return $count;
91  }
92 
98  public function initializeUserEditCount( UserIdentity $user ): int {
99  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
100  $actorWhere = $this->actorMigration->getWhere( $dbr, 'rev_user', $user );
101 
102  $count = (int)$dbr->selectField(
103  [ 'revision' ] + $actorWhere['tables'],
104  'COUNT(*)',
105  [ $actorWhere['conds'] ],
106  __METHOD__,
107  [],
108  $actorWhere['joins']
109  );
110 
111  // Defer updating the edit count via a job (T259719)
112  $this->jobQueueGroup->push( new UserEditCountInitJob( [
113  'userId' => $user->getId(),
114  'editCount' => $count,
115  ] ) );
116 
117  return $count;
118  }
119 
126  public function incrementUserEditCount( UserIdentity $user ) {
127  if ( !$user->isRegistered() ) {
128  // Anonymous users don't have edit counts
129  return;
130  }
131 
133  new UserEditCountUpdate( $user, 1 ),
134  DeferredUpdates::POSTSEND
135  );
136  }
137 
145  public function getFirstEditTimestamp( UserIdentity $user ) {
146  return $this->getUserEditTimestamp( $user, self::FIRST_EDIT );
147  }
148 
156  public function getLatestEditTimestamp( UserIdentity $user ) {
157  return $this->getUserEditTimestamp( $user, self::LATEST_EDIT );
158  }
159 
167  private function getUserEditTimestamp( UserIdentity $user, int $type ) {
168  if ( $user->getId() === 0 ) {
169  return false; // anonymous user
170  }
171 
172  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
173  $actorWhere = $this->actorMigration->getWhere( $dbr, 'rev_user', $user );
174 
175  $tsField = isset( $actorWhere['tables']['temp_rev_user'] ) // SCHEMA_COMPAT_READ_TEMP
176  ? 'revactor_timestamp' : 'rev_timestamp';
177 
178  $sortOrder = ( $type === self::FIRST_EDIT ) ? 'ASC' : 'DESC';
179  $time = $dbr->selectField(
180  [ 'revision' ] + $actorWhere['tables'],
181  $tsField,
182  [ $actorWhere['conds'] ],
183  __METHOD__,
184  [ 'ORDER BY' => "$tsField $sortOrder" ],
185  $actorWhere['joins']
186  );
187 
188  if ( !$time ) {
189  return false; // no edits
190  }
191 
192  return ConvertibleTimestamp::convert( TS_MW, $time );
193  }
194 
199  public function clearUserEditCache( UserIdentity $user ) {
200  if ( !$user->isRegistered() ) {
201  return;
202  }
203 
204  $userId = $user->getId();
205  $cacheKey = 'u' . (string)$userId;
206 
207  unset( $this->userEditCountCache[ $cacheKey ] );
208  }
209 
216  public function setCachedUserEditCount( UserIdentity $user, int $editCount ) {
217  if ( !$user->isRegistered() ) {
218  throw new InvalidArgumentException( __METHOD__ . ' with an anonymous user' );
219  }
220 
221  $userId = $user->getId();
222  $cacheKey = 'u' . (string)$userId;
223 
224  $this->userEditCountCache[ $cacheKey ] = $editCount;
225  }
226 
227 }
MediaWiki\User\UserEditTracker\getUserEditCount
getUserEditCount(UserIdentity $user)
Get a user's edit count from the user_editcount field, falling back to initialize.
Definition: UserEditTracker.php:64
MediaWiki\User\UserEditTracker\LATEST_EDIT
const LATEST_EDIT
Definition: UserEditTracker.php:24
MediaWiki\User\UserEditTracker\__construct
__construct(ActorMigration $actorMigration, ILoadBalancer $loadBalancer, JobQueueGroup $jobQueueGroup)
Definition: UserEditTracker.php:48
DeferredUpdates\addUpdate
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the pending update queue for execution at the appropriate time.
Definition: DeferredUpdates.php:119
MediaWiki\User\UserEditTracker\getUserEditTimestamp
getUserEditTimestamp(UserIdentity $user, int $type)
Get the timestamp of a user's edit, either their first or latest.
Definition: UserEditTracker.php:167
MediaWiki\User\UserIdentity\getId
getId( $wikiId=self::LOCAL)
ActorMigration
This is not intended to be a long-term part of MediaWiki; it will be deprecated and removed once acto...
Definition: ActorMigration.php:15
UserEditCountUpdate
Handles increment the edit count for a given set of users.
Definition: UserEditCountUpdate.php:30
UserEditCountInitJob
Job that initializes an user's edit count if it's not yet set or the current value is outdated.
Definition: UserEditCountInitJob.php:35
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
$dbr
$dbr
Definition: testCompression.php:54
MediaWiki\User\UserEditTracker\getLatestEditTimestamp
getLatestEditTimestamp(UserIdentity $user)
Get the user's latest edit timestamp.
Definition: UserEditTracker.php:156
MediaWiki\User\UserIdentity\isRegistered
isRegistered()
MediaWiki\User\UserEditTracker\getFirstEditTimestamp
getFirstEditTimestamp(UserIdentity $user)
Get the user's first edit timestamp.
Definition: UserEditTracker.php:145
MediaWiki\User\UserEditTracker\$loadBalancer
ILoadBalancer $loadBalancer
Definition: UserEditTracker.php:30
DeferredUpdates
Class for managing the deferral of updates within the scope of a PHP script invocation.
Definition: DeferredUpdates.php:82
MediaWiki\User\UserEditTracker\FIRST_EDIT
const FIRST_EDIT
Definition: UserEditTracker.php:23
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
MediaWiki\User\UserEditTracker\$actorMigration
ActorMigration $actorMigration
Definition: UserEditTracker.php:27
MediaWiki\User\UserEditTracker\$userEditCountCache
array $userEditCountCache
Mapping of user id to edit count for caching To avoid using non-sequential numerical keys,...
Definition: UserEditTracker.php:41
MediaWiki\User
Definition: ActorCache.php:21
MediaWiki\User\UserEditTracker\initializeUserEditCount
initializeUserEditCount(UserIdentity $user)
Definition: UserEditTracker.php:98
MediaWiki\User\UserEditTracker
Track info about user edit counts and timings.
Definition: UserEditTracker.php:21
MediaWiki\User\UserEditTracker\incrementUserEditCount
incrementUserEditCount(UserIdentity $user)
Schedule a job to increase a user's edit count.
Definition: UserEditTracker.php:126
MediaWiki\User\UserEditTracker\clearUserEditCache
clearUserEditCache(UserIdentity $user)
Definition: UserEditTracker.php:199
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
JobQueueGroup
Class to handle enqueueing of background jobs.
Definition: JobQueueGroup.php:32
MediaWiki\User\UserEditTracker\$jobQueueGroup
JobQueueGroup $jobQueueGroup
Definition: UserEditTracker.php:33
MediaWiki\User\UserEditTracker\setCachedUserEditCount
setCachedUserEditCount(UserIdentity $user, int $editCount)
Definition: UserEditTracker.php:216
$type
$type
Definition: testCompression.php:52