MediaWiki  master
ActorStore.php
Go to the documentation of this file.
1 <?php
21 namespace MediaWiki\User;
22 
26 use InvalidArgumentException;
28 use Psr\Log\LoggerInterface;
29 use stdClass;
30 use User;
31 use Wikimedia\Assert\Assert;
32 use Wikimedia\IPUtils;
36 
44 
45  public const UNKNOWN_USER_NAME = 'Unknown user';
46 
47  private const LOCAL_CACHE_SIZE = 100;
48 
50  private $loadBalancer;
51 
53  private $userNameUtils;
54 
56  private $logger;
57 
59  private $wikiId;
60 
62  private $cache;
63 
70  public function __construct(
73  LoggerInterface $logger,
74  $wikiId = WikiAwareEntity::LOCAL
75  ) {
76  Assert::parameterType( 'string|boolean', $wikiId, '$wikiId' );
77  Assert::parameter( $wikiId !== true, '$wikiId', 'must be false or a string' );
78 
79  $this->loadBalancer = $loadBalancer;
80  $this->userNameUtils = $userNameUtils;
81  $this->logger = $logger;
82  $this->wikiId = $wikiId;
83 
84  $this->cache = new ActorCache( self::LOCAL_CACHE_SIZE );
85  }
86 
101  public function newActorFromRow( stdClass $row ): UserIdentity {
102  $actorId = (int)$row->actor_id;
103  $userId = isset( $row->actor_user ) ? (int)$row->actor_user : 0;
104  if ( $actorId === 0 ) {
105  throw new InvalidArgumentException( "Actor ID is 0 for {$row->actor_name} and {$userId}" );
106  }
107 
108  $normalizedName = $this->normalizeUserName( $row->actor_name );
109  if ( $normalizedName === null ) {
110  $this->logger->warning( 'Encountered invalid actor name in database', [
111  'user_id' => $userId,
112  'actor_id' => $actorId,
113  'actor_name' => $row->actor_name,
114  'wiki_id' => $this->wikiId ?: 'local'
115  ] );
116  // TODO: once we have guaranteed db only contains valid actor names,
117  // we can skip normalization here - T273933
118  if ( $row->actor_name === '' ) {
119  throw new InvalidArgumentException( "Actor name can not be empty for {$userId} and {$actorId}" );
120  }
121  }
122 
123  $actor = new UserIdentityValue( $userId, $row->actor_name, $this->wikiId );
124  $this->cache->add( $actorId, $actor );
125  return $actor;
126  }
127 
144  public function newActorFromRowFields( $userId, $name, $actorId ): UserIdentity {
145  // For backwards compatibility we are quite relaxed about what to accept,
146  // but try not to create entirely insane objects. As we move more code
147  // from ActorMigration aliases to proper join with the actor table,
148  // we should use ::newActorFromRow more, and eventually deprecate this method.
149  $userId = $userId === null ? 0 : (int)$userId;
150  $name = $name ?? '';
151  if ( $actorId === null ) {
152  throw new InvalidArgumentException( "Actor ID is null for {$name} and {$userId}" );
153  }
154  if ( (int)$actorId === 0 ) {
155  throw new InvalidArgumentException( "Actor ID is 0 for {$name} and {$userId}" );
156  }
157 
158  $normalizedName = $this->normalizeUserName( $name );
159  if ( $normalizedName === null ) {
160  $this->logger->warning( 'Encountered invalid actor name in database', [
161  'user_id' => $userId,
162  'actor_id' => $actorId,
163  'actor_name' => $name,
164  'wiki_id' => $this->wikiId ?: 'local'
165  ] );
166  // TODO: once we have guaranteed the DB entries only exist for normalized names,
167  // we can skip normalization here - T273933
168  if ( $name === '' ) {
169  throw new InvalidArgumentException( "Actor name can not be empty for {$userId} and {$actorId}" );
170  }
171  }
172 
173  $actorId = (int)$actorId;
174  $actor = new UserIdentityValue(
175  $userId,
176  $name,
177  $this->wikiId
178  );
179 
180  $this->cache->add( $actorId, $actor );
181  return $actor;
182  }
183 
188  public function deleteUserIdentityFromCache( UserIdentity $actor ) {
189  $this->cache->remove( $actor );
190  }
191 
196  public function clearCaches() {
197  $this->cache->clear();
198  }
199 
208  public function getActorById( int $actorId, IDatabase $db ): ?UserIdentity {
209  $this->checkDatabaseDomain( $db );
210 
211  if ( !$actorId ) {
212  return null;
213  }
214 
215  return $this->cache->getActor( ActorCache::KEY_ACTOR_ID, $actorId ) ??
216  $this->newSelectQueryBuilder( $db )
217  ->caller( __METHOD__ )
218  ->conds( [ 'actor_id' => $actorId ] )
219  ->fetchUserIdentity() ??
220  // The actor ID mostly comes from DB, so if we can't find an actor by ID,
221  // it's most likely due to lagged replica and not cause it doesn't actually exist.
222  // Probably we just inserted it? Try master.
223  $this->newSelectQueryBuilder( self::READ_LATEST )
224  ->caller( __METHOD__ )
225  ->conds( [ 'actor_id' => $actorId ] )
226  ->fetchUserIdentity();
227  }
228 
236  public function getUserIdentityByName( string $name, int $queryFlags = self::READ_NORMAL ): ?UserIdentity {
237  $normalizedName = $this->normalizeUserName( $name );
238  if ( $normalizedName === null ) {
239  return null;
240  }
241 
242  return $this->cache->getActor( ActorCache::KEY_USER_NAME, $normalizedName ) ??
243  $this->newSelectQueryBuilder( $queryFlags )
244  ->caller( __METHOD__ )
245  ->userNames( $normalizedName )
246  ->fetchUserIdentity();
247  }
248 
256  public function getUserIdentityByUserId( int $userId, int $queryFlags = self::READ_NORMAL ): ?UserIdentity {
257  if ( !$userId ) {
258  return null;
259  }
260 
261  return $this->cache->getActor( ActorCache::KEY_USER_ID, $userId ) ??
262  $this->newSelectQueryBuilder( $queryFlags )
263  ->caller( __METHOD__ )
264  ->userIds( $userId )
265  ->fetchUserIdentity();
266  }
267 
277  private function attachActorId( UserIdentity $user, int $id, bool $assigned ) {
278  if ( $user instanceof User ) {
279  $user->setActorId( $id );
280  if ( $assigned ) {
281  $user->invalidateCache();
282  }
283  }
284  }
285 
293  private function detachActorId( UserIdentity $user ) {
294  if ( $user instanceof User ) {
295  $user->setActorId( 0 );
296  }
297  }
298 
307  public function findActorId( UserIdentity $user, IDatabase $db ): ?int {
308  // TODO: we want to assert this user belongs to the correct wiki,
309  // but User objects are always local and we used to use them
310  // on a non-local DB connection. We need to first deprecate this
311  // possibility and then throw on mismatching User object - T273972
312  // $user->assertWiki( $this->wikiId );
313  $this->deprecateInvalidCrossWikiParam( $user );
314 
315  // TODO: In the future we would be able to assume UserIdentity name is ok
316  // and will be able to skip normalization here - T273933
317  $name = $this->normalizeUserName( $user->getName() );
318  if ( $name === null ) {
319  $this->logger->warning( 'Encountered a UserIdentity with invalid name', [
320  'user_name' => $user->getName()
321  ] );
322  return null;
323  }
324 
325  $id = $this->findActorIdInternal( $name, $db );
326 
327  // Set the actor ID in the User object. To be removed, see T274148.
328  if ( $id && $user instanceof User ) {
329  $user->setActorId( $id );
330  }
331 
332  return $id;
333  }
334 
343  public function findActorIdByName( $name, IDatabase $db ): ?int {
344  $name = $this->normalizeUserName( $name );
345  if ( $name === null ) {
346  return null;
347  }
348 
349  return $this->findActorIdInternal( $name, $db );
350  }
351 
361  private function findActorIdInternal(
362  string $name,
363  IDatabase $db,
364  array $queryOptions = []
365  ): ?int {
366  // Note: UserIdentity::getActorId will be deprecated and removed,
367  // and this is the replacement for it. Can't call User::getActorId, cause
368  // User always thinks it's local, so we could end up fetching the ID
369  // from the wrong database.
370 
371  $cachedValue = $this->cache->getActorId( ActorCache::KEY_USER_NAME, $name );
372  if ( $cachedValue ) {
373  return $cachedValue;
374  }
375 
376  $row = $db->selectRow(
377  'actor',
378  [ 'actor_user', 'actor_name', 'actor_id' ],
379  [ 'actor_name' => $name ],
380  __METHOD__,
381  $queryOptions
382  );
383 
384  if ( !$row || !$row->actor_id ) {
385  return null;
386  }
387  // to cache row
388  $this->newActorFromRow( $row );
389 
390  return (int)$row->actor_id;
391  }
392 
407  public function acquireActorId( UserIdentity $user, IDatabase $dbw ): int {
408  $this->checkDatabaseDomain( $dbw );
409  [ $userId, $userName ] = $this->validateActorForInsertion( $user );
410 
411  // allow cache to be used, because if it is in the cache, it already has an actor ID
412  $existingActorId = $this->findActorIdInternal( $userName, $dbw );
413  if ( $existingActorId ) {
414  $this->attachActorId( $user, $existingActorId, false );
415  return $existingActorId;
416  }
417 
418  $dbw->insert(
419  'actor',
420  [
421  'actor_user' => $userId,
422  'actor_name' => $userName,
423  ],
424  __METHOD__,
425  [ 'IGNORE' ]
426  );
427 
428  if ( $dbw->affectedRows() ) {
429  $actorId = $dbw->insertId();
430  } else {
431  // Outdated cache?
432  // Use LOCK IN SHARE MODE to bypass any MySQL REPEATABLE-READ snapshot.
433  $actorId = $this->findActorIdInternal(
434  $userName,
435  $dbw,
436  [ 'LOCK IN SHARE MODE' ]
437  );
438  if ( !$actorId ) {
439  throw new CannotCreateActorException(
440  "Failed to create actor ID for " .
441  "user_id={$userId} user_name=\"{$userName}\""
442  );
443  }
444  }
445 
446  $this->attachActorId( $user, $actorId, true );
447  // Cache row we've just created
448  $cachedUserIdentity = $this->newActorFromRowFields( $userId, $userName, $actorId );
449  $this->setUpRollbackHandler( $dbw, $cachedUserIdentity, $user );
450  return $actorId;
451  }
452 
467  public function createNewActor( UserIdentity $user, IDatabase $dbw ): int {
468  $this->checkDatabaseDomain( $dbw );
469  [ $userId, $userName ] = $this->validateActorForInsertion( $user );
470 
471  try {
472  $dbw->insert(
473  'actor',
474  [
475  'actor_user' => $userId,
476  'actor_name' => $userName,
477  ],
478  __METHOD__
479  );
480  } catch ( DBQueryError $e ) {
481  // We rely on the database to crash on unique actor_name constraint.
482  throw new CannotCreateActorException( $e->getMessage() );
483  }
484  $actorId = $dbw->insertId();
485 
486  $this->attachActorId( $user, $actorId, true );
487  // Cache row we've just created
488  $cachedUserIdentity = $this->newActorFromRowFields( $userId, $userName, $actorId );
489  $this->setUpRollbackHandler( $dbw, $cachedUserIdentity, $user );
490 
491  return $actorId;
492  }
493 
511  public function acquireSystemActorId( UserIdentity $user, IDatabase $dbw ): int {
512  $this->checkDatabaseDomain( $dbw );
513  [ $userId, $userName ] = $this->validateActorForInsertion( $user );
514 
515  $existingActorId = $this->findActorIdInternal( $userName, $dbw );
516  if ( $existingActorId ) {
517  // It certainly will be cached if we just found it.
518  $existingActor = $this->cache->getActor( ActorCache::KEY_ACTOR_ID, $existingActorId );
519 
520  // If we already have an existing actor with a matching user ID
521  // just return it, nothing to do here.
522  if ( $existingActor->getId( $this->wikiId ) === $user->getId( $this->wikiId ) ) {
523  return $existingActorId;
524  }
525 
526  // Allow overwriting user ID for already existing actor with reserved user name, see T236444
527  if ( $this->userNameUtils->isUsable( $userName ) || $existingActor->isRegistered() ) {
528  throw new CannotCreateActorException(
529  'Cannot replace user for existing actor: ' .
530  "actor_id=$existingActorId, new user_id=$userId"
531  );
532  }
533  }
534 
535  $dbw->upsert(
536  'actor',
537  [ 'actor_name' => $userName, 'actor_user' => $userId ],
538  [ 'actor_name' ],
539  [ 'actor_user' => $userId ],
540  __METHOD__
541  );
542  if ( !$dbw->affectedRows() ) {
543  throw new CannotCreateActorException(
544  'Failed to replace user for actor: ' .
545  "actor_id=$existingActorId, new user_id=$userId"
546  );
547  }
548  $actorId = $dbw->insertId() ?: $existingActorId;
549 
550  $this->cache->remove( $user );
551  $this->attachActorId( $user, $actorId, true );
552  // Cache row we've just created
553  $cachedUserIdentity = $this->newActorFromRowFields( $userId, $userName, $actorId );
554  $this->setUpRollbackHandler( $dbw, $cachedUserIdentity, $user );
555  return $actorId;
556  }
557 
570  public function deleteActor( UserIdentity $actor, IDatabase $dbw ): bool {
571  $this->checkDatabaseDomain( $dbw );
572  $this->deprecateInvalidCrossWikiParam( $actor );
573 
574  $normalizedName = $this->normalizeUserName( $actor->getName() );
575  if ( $normalizedName === null ) {
576  throw new InvalidArgumentException(
577  "Unable to normalize the provided actor name {$actor->getName()}"
578  );
579  }
580  $dbw->delete(
581  'actor',
582  [ 'actor_name' => $normalizedName ],
583  __METHOD__
584  );
585  if ( $dbw->affectedRows() !== 0 ) {
586  $this->cache->remove( $actor );
587  return true;
588  }
589  return false;
590  }
591 
600  public function normalizeUserName( string $name ): ?string {
601  if ( $this->userNameUtils->isIP( $name ) ) {
602  return IPUtils::sanitizeIP( $name );
603  } elseif ( ExternalUserNames::isExternal( $name ) ) {
604  // TODO: ideally, we should probably canonicalize external usernames,
605  // but it was not done before, so we can not start doing it unless we
606  // fix existing DB rows - T273933
607  return $name;
608  } else {
609  $normalized = $this->userNameUtils->getCanonical( $name );
610  return $normalized === false ? null : $normalized;
611  }
612  }
613 
620  private function validateActorForInsertion( UserIdentity $user ): array {
621  // TODO: we want to assert this user belongs to the correct wiki,
622  // but User objects are always local and we used to use them
623  // on a non-local DB connection. We need to first deprecate this
624  // possibility and then throw on mismatching User object - T273972
625  // $user->assertWiki( $this->wikiId );
626  $this->deprecateInvalidCrossWikiParam( $user );
627 
628  $userName = $this->normalizeUserName( $user->getName() );
629  if ( $userName === null || $userName === '' ) {
630  $userIdForErrorMessage = $user->getId( $this->wikiId );
631  throw new CannotCreateActorException(
632  'Cannot create an actor for a user with no name: ' .
633  "user_id={$userIdForErrorMessage} user_name=\"{$user->getName()}\""
634  );
635  }
636 
637  $userId = $user->getId( $this->wikiId ) ?: null;
638  if ( $userId === null && $this->userNameUtils->isUsable( $user->getName() ) ) {
639  throw new CannotCreateActorException(
640  'Cannot create an actor for a usable name that is not an existing user: ' .
641  "user_name=\"{$user->getName()}\""
642  );
643  }
644  return [ $userId, $userName ];
645  }
646 
654  private function setUpRollbackHandler(
655  IDatabase $dbw,
656  UserIdentity $cachedActor,
657  UserIdentity $originalActor
658  ) {
659  if ( $dbw->trxLevel() ) {
660  // If called within a transaction and it was rolled back, the cached actor ID
661  // becomes invalid, so cache needs to be invalidated as well. See T277795.
663  function ( int $trigger ) use ( $cachedActor, $originalActor ) {
664  if ( $trigger === IDatabase::TRIGGER_ROLLBACK ) {
665  $this->cache->remove( $cachedActor );
666  $this->detachActorId( $originalActor );
667  }
668  },
669  __METHOD__
670  );
671  }
672  }
673 
678  private function getDBConnectionRefForQueryFlags( int $queryFlags ): array {
679  [ $mode, $options ] = DBAccessObjectUtils::getDBOptions( $queryFlags );
680  return [ $this->loadBalancer->getConnectionRef( $mode, [], $this->wikiId ), $options ];
681  }
682 
689  private function checkDatabaseDomain( IDatabase $db ) {
690  $dbDomain = $db->getDomainID();
691  $storeDomain = $this->loadBalancer->resolveDomainID( $this->wikiId );
692  if ( $dbDomain !== $storeDomain ) {
693  throw new InvalidArgumentException(
694  "DB connection domain '$dbDomain' does not match '$storeDomain'"
695  );
696  }
697  }
698 
705  public function getUnknownActor(): UserIdentity {
706  $actor = $this->getUserIdentityByName( self::UNKNOWN_USER_NAME );
707  if ( $actor ) {
708  return $actor;
709  }
710  $actor = new UserIdentityValue( 0, self::UNKNOWN_USER_NAME, $this->wikiId );
711 
712  [ $db, ] = $this->getDBConnectionRefForQueryFlags( self::READ_LATEST );
713  $this->acquireActorId( $actor, $db );
714  return $actor;
715  }
716 
724  public function newSelectQueryBuilder( $dbOrQueryFlags = self::READ_NORMAL ): UserSelectQueryBuilder {
725  if ( $dbOrQueryFlags instanceof IDatabase ) {
726  [ $db, $options ] = [ $dbOrQueryFlags, [] ];
727  $this->checkDatabaseDomain( $db );
728  } else {
729  [ $db, $options ] = $this->getDBConnectionRefForQueryFlags( $dbOrQueryFlags );
730  }
731 
732  return ( new UserSelectQueryBuilder( $db, $this ) )->options( $options );
733  }
734 
741  private function deprecateInvalidCrossWikiParam( UserIdentity $user ) {
742  if ( $user->getWikiId() !== $this->wikiId ) {
743  $expected = $this->wikiIdToString( $user->getWikiId() );
744  $actual = $this->wikiIdToString( $this->wikiId );
746  'Deprecated passing invalid cross-wiki user. ' .
747  "Expected: {$expected}, Actual: {$actual}.",
748  '1.37'
749  );
750  }
751  }
752 
759  private function wikiIdToString( $wikiId ): string {
760  return $wikiId === WikiAwareEntity::LOCAL ? 'the local wiki' : "'{$wikiId}'";
761  }
762 }
MediaWiki\User\UserIdentityValue
Value object representing a user's identity.
Definition: UserIdentityValue.php:35
MediaWiki\User\ActorStore\__construct
__construct(ILoadBalancer $loadBalancer, UserNameUtils $userNameUtils, LoggerInterface $logger, $wikiId=WikiAwareEntity::LOCAL)
Definition: ActorStore.php:70
MediaWiki\User\ActorStore\validateActorForInsertion
validateActorForInsertion(UserIdentity $user)
Validates actor before insertion.
Definition: ActorStore.php:620
Wikimedia\Rdbms\IDatabase\affectedRows
affectedRows()
Get the number of rows affected by the last write query.
MediaWiki\User\ActorStore\newActorFromRowFields
newActorFromRowFields( $userId, $name, $actorId)
Instantiate a new UserIdentity object based on field values from a DB row.
Definition: ActorStore.php:144
if
if(ini_get( 'mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition: Setup.php:88
MediaWiki\User\ActorStore\deleteUserIdentityFromCache
deleteUserIdentityFromCache(UserIdentity $actor)
Definition: ActorStore.php:188
Wikimedia\Rdbms\IDatabase\upsert
upsert( $table, array $rows, $uniqueKeys, array $set, $fname=__METHOD__)
Upsert the given row(s) into a table.
Wikimedia\Rdbms\IDatabase\trxLevel
trxLevel()
Gets the current transaction level.
ExternalUserNames
Class to parse and build external user names.
Definition: ExternalUserNames.php:30
MediaWiki\User\ActorStore\wikiIdToString
wikiIdToString( $wikiId)
Convert $wikiId to a string for logging.
Definition: ActorStore.php:759
MediaWiki\User\ActorStore\setUpRollbackHandler
setUpRollbackHandler(IDatabase $dbw, UserIdentity $cachedActor, UserIdentity $originalActor)
Clear in-process caches if transaction gets rolled back.
Definition: ActorStore.php:654
MediaWiki\User\UserIdentity\getId
getId( $wikiId=self::LOCAL)
DBAccessObjectUtils\getDBOptions
static getDBOptions( $bitfield)
Get an appropriate DB index, options, and fallback DB index for a query.
Definition: DBAccessObjectUtils.php:52
MediaWiki\User\ActorStore\findActorIdInternal
findActorIdInternal(string $name, IDatabase $db, array $queryOptions=[])
Find actor_id of the given $user using the passed $db connection.
Definition: ActorStore.php:361
MediaWiki\DAO\WikiAwareEntity
Marker interface for entities aware of the wiki they belong to.
Definition: WikiAwareEntity.php:34
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
MediaWiki\User\ActorStore\normalizeUserName
normalizeUserName(string $name)
Returns a canonical form of user name suitable for storage.
Definition: ActorStore.php:600
wfDeprecatedMsg
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: GlobalFunctions.php:1028
MediaWiki\User\ActorStore\$loadBalancer
ILoadBalancer $loadBalancer
Definition: ActorStore.php:50
MediaWiki\User\ActorStore\findActorIdByName
findActorIdByName( $name, IDatabase $db)
Find the actor_id of the given $name.
Definition: ActorStore.php:343
MediaWiki\User\ActorStore\$wikiId
string false $wikiId
Definition: ActorStore.php:59
MediaWiki\User\ActorStore\acquireActorId
acquireActorId(UserIdentity $user, IDatabase $dbw)
Attempt to assign an actor ID to the given $user.
Definition: ActorStore.php:407
MediaWiki\User\ActorStore\acquireSystemActorId
acquireSystemActorId(UserIdentity $user, IDatabase $dbw)
Attempt to assign an ID to an actor for a system user.
Definition: ActorStore.php:511
MediaWiki\User\UserIdentity\getName
getName()
MediaWiki\User\ActorStore\getDBConnectionRefForQueryFlags
getDBConnectionRefForQueryFlags(int $queryFlags)
Definition: ActorStore.php:678
MediaWiki\User\ActorStore\newSelectQueryBuilder
newSelectQueryBuilder( $dbOrQueryFlags=self::READ_NORMAL)
Returns a specialized SelectQueryBuilder for querying the UserIdentity objects.
Definition: ActorStore.php:724
MediaWiki\User\ActorCache
Definition: ActorCache.php:36
DBAccessObjectUtils
Helper class for DAO classes.
Definition: DBAccessObjectUtils.php:29
Wikimedia\Rdbms\DBQueryError
@newable
Definition: DBQueryError.php:29
MediaWiki\User\ActorStore\attachActorId
attachActorId(UserIdentity $user, int $id, bool $assigned)
Attach the actor ID to $user for backwards compatibility.
Definition: ActorStore.php:277
MediaWiki\User\ActorStore\deleteActor
deleteActor(UserIdentity $actor, IDatabase $dbw)
Delete the actor from the actor table.
Definition: ActorStore.php:570
MediaWiki\User\ActorStore\UNKNOWN_USER_NAME
const UNKNOWN_USER_NAME
Definition: ActorStore.php:45
MediaWiki\User\ActorStore\LOCAL_CACHE_SIZE
const LOCAL_CACHE_SIZE
Definition: ActorStore.php:47
MediaWiki\User\ActorStore\getUserIdentityByName
getUserIdentityByName(string $name, int $queryFlags=self::READ_NORMAL)
Find an actor by $name.
Definition: ActorStore.php:236
MediaWiki\User\UserIdentityLookup
Definition: UserIdentityLookup.php:33
MediaWiki\DAO\WikiAwareEntity\getWikiId
getWikiId()
Get the ID of the wiki this page belongs to.
Wikimedia\Rdbms\IDatabase\selectRow
selectRow( $table, $vars, $conds, $fname=__METHOD__, $options=[], $join_conds=[])
Wrapper to IDatabase::select() that only fetches one row (via LIMIT)
Wikimedia\Rdbms\IDatabase\getDomainID
getDomainID()
Return the currently selected domain ID.
CannotCreateActorException
Exception thrown when an actor can't be created.
Definition: CannotCreateActorException.php:29
MediaWiki\User
Definition: ActorCache.php:21
MediaWiki\User\ActorStore\createNewActor
createNewActor(UserIdentity $user, IDatabase $dbw)
Create a new actor for the given $user.
Definition: ActorStore.php:467
MediaWiki\User\ActorStore\clearCaches
clearCaches()
Definition: ActorStore.php:196
MediaWiki\User\ActorStore\getUnknownActor
getUnknownActor()
In case all reasonable attempts of initializing a proper actor from the database have failed,...
Definition: ActorStore.php:705
MediaWiki\User\ActorStore\$logger
LoggerInterface $logger
Definition: ActorStore.php:56
Wikimedia\Rdbms\IDatabase\insert
insert( $table, $rows, $fname=__METHOD__, $options=[])
Insert the given row(s) into a table.
MediaWiki\User\ActorStore\$cache
ActorCache $cache
Definition: ActorStore.php:62
MediaWiki\User\UserSelectQueryBuilder
Definition: UserSelectQueryBuilder.php:29
MediaWiki\User\UserNameUtils
UserNameUtils service.
Definition: UserNameUtils.php:42
MediaWiki\User\ActorStore\getActorById
getActorById(int $actorId, IDatabase $db)
Find an actor by $id.
Definition: ActorStore.php:208
MediaWiki\User\ActorStore\detachActorId
detachActorId(UserIdentity $user)
Detach the actor ID from $user for backwards compatibility.
Definition: ActorStore.php:293
MediaWiki\User\ActorStore\checkDatabaseDomain
checkDatabaseDomain(IDatabase $db)
Throws an exception if the given database connection does not belong to the wiki this RevisionStore i...
Definition: ActorStore.php:689
MediaWiki\User\ActorStore\deprecateInvalidCrossWikiParam
deprecateInvalidCrossWikiParam(UserIdentity $user)
Emits a deprecation warning if $user does not belong to the same wiki this store belongs to.
Definition: ActorStore.php:741
Wikimedia\Rdbms\IDatabase\insertId
insertId()
Get the inserted value of an auto-increment row.
Wikimedia\Rdbms\IDatabase\onTransactionResolution
onTransactionResolution(callable $callback, $fname=__METHOD__)
Run a callback when the current transaction commits or rolls back.
MediaWiki\User\ActorStore\$userNameUtils
UserNameUtils $userNameUtils
Definition: ActorStore.php:53
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:68
ExternalUserNames\isExternal
static isExternal( $username)
Tells whether the username is external or not.
Definition: ExternalUserNames.php:149
Wikimedia\Rdbms\IDatabase\delete
delete( $table, $conds, $fname=__METHOD__)
Delete all rows in a table that match a condition.
MediaWiki\User\ActorStore\findActorId
findActorId(UserIdentity $user, IDatabase $db)
Find the actor_id of the given $user.
Definition: ActorStore.php:307
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
MediaWiki\User\ActorStore
Definition: ActorStore.php:43
MediaWiki\User\ActorStore\newActorFromRow
newActorFromRow(stdClass $row)
Instantiate a new UserIdentity object based on a $row from the actor table.
Definition: ActorStore.php:101
MediaWiki\User\ActorStore\getUserIdentityByUserId
getUserIdentityByUserId(int $userId, int $queryFlags=self::READ_NORMAL)
Find an actor by $userId.
Definition: ActorStore.php:256
MediaWiki\User\ActorNormalization
Service for dealing with the actor table.
Definition: ActorNormalization.php:32