MediaWiki REL1_37
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
28
31
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
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->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}
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition Setup.php:88
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.
getUserEditTimestamp(UserIdentity $user, int $type)
Get the timestamp of a user's edit, either their first or latest.
__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.
array $userEditCountCache
Mapping of user id to edit count for caching To avoid using non-sequential numerical keys,...
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)
Database cluster connection, tracking, load balancing, and transaction manager interface.
const DB_REPLICA
Definition defines.php:25