MediaWiki REL1_39
UserEditTracker.php
Go to the documentation of this file.
1<?php
2
3namespace MediaWiki\User;
4
7use InvalidArgumentException;
12use 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(
49 ActorMigration $actorMigration,
50 ILoadBalancer $loadBalancer,
51 JobQueueGroup $jobQueueGroup
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
132 DeferredUpdates::addUpdate(
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->isRegistered() ) {
169 return false;
170 }
171
172 $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
173 $actorWhere = $this->actorMigration->getWhere( $dbr, 'rev_user', $user );
174
175 $sortOrder = ( $type === self::FIRST_EDIT ) ? 'ASC' : 'DESC';
176 $time = $dbr->selectField(
177 [ 'revision' ] + $actorWhere['tables'],
178 'rev_timestamp',
179 [ $actorWhere['conds'] ],
180 __METHOD__,
181 [ 'ORDER BY' => "rev_timestamp $sortOrder" ],
182 $actorWhere['joins']
183 );
184
185 if ( !$time ) {
186 return false; // no edits
187 }
188
189 return ConvertibleTimestamp::convert( TS_MW, $time );
190 }
191
196 public function clearUserEditCache( UserIdentity $user ) {
197 if ( !$user->isRegistered() ) {
198 return;
199 }
200
201 $userId = $user->getId();
202 $cacheKey = 'u' . (string)$userId;
203
204 unset( $this->userEditCountCache[ $cacheKey ] );
205 }
206
213 public function setCachedUserEditCount( UserIdentity $user, int $editCount ) {
214 if ( !$user->isRegistered() ) {
215 throw new InvalidArgumentException( __METHOD__ . ' with an anonymous user' );
216 }
217
218 $userId = $user->getId();
219 $cacheKey = 'u' . (string)$userId;
220
221 $this->userEditCountCache[ $cacheKey ] = $editCount;
222 }
223
224}
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
Definition WebStart.php:82
This is not intended to be a long-term part of MediaWiki; it will be deprecated and removed once acto...
Class for managing the deferral of updates within the scope of a PHP script invocation.
Class to handle enqueueing of background jobs.
Track info about user edit counts and timings.
getLatestEditTimestamp(UserIdentity $user)
Get the user's latest edit timestamp.
__construct(ActorMigration $actorMigration, ILoadBalancer $loadBalancer, JobQueueGroup $jobQueueGroup)
getUserEditCount(UserIdentity $user)
Get a user's edit count from the user_editcount field, falling back to initialize.
incrementUserEditCount(UserIdentity $user)
Schedule a job to increase a user's edit count.
getFirstEditTimestamp(UserIdentity $user)
Get the user's first edit timestamp.
initializeUserEditCount(UserIdentity $user)
clearUserEditCache(UserIdentity $user)
setCachedUserEditCount(UserIdentity $user, int $editCount)
Job that initializes an user's edit count if it's not yet set or the current value is outdated.
Handles increment the edit count for a given set of users.
Interface for objects representing user identity.
getId( $wikiId=self::LOCAL)
Create and track the database connections and transactions for a given database cluster.
const DB_REPLICA
Definition defines.php:26