MediaWiki master
UserCache.php
Go to the documentation of this file.
1<?php
10namespace MediaWiki\Cache;
11
13use Psr\Log\LoggerInterface;
15
20class UserCache {
22 protected $cache = [];
24 protected $typesCached = [];
25
27 private $logger;
28
30 private $linkBatchFactory;
31
33 private $dbProvider;
34
39 public static function singleton() {
40 wfDeprecated( __METHOD__, '1.43' );
41 return MediaWikiServices::getInstance()->getUserCache();
42 }
43
51 public function __construct(
52 LoggerInterface $logger,
53 IConnectionProvider $dbProvider,
54 LinkBatchFactory $linkBatchFactory
55 ) {
56 $this->logger = $logger;
57 $this->dbProvider = $dbProvider;
58 $this->linkBatchFactory = $linkBatchFactory;
59 }
60
68 public function getProp( $userId, $prop ) {
69 if ( !isset( $this->cache[$userId][$prop] ) ) {
70 $this->logger->debug(
71 'Querying DB for prop {prop} for user ID {userId}',
72 [
73 'prop' => $prop,
74 'userId' => $userId,
75 ]
76 );
77 $this->doQuery( [ $userId ] ); // cache miss
78 }
79
80 return $this->cache[$userId][$prop] ?? false; // user does not exist?
81 }
82
91 public function getUserName( $userId, $ip ) {
92 return $userId > 0 ? $this->getProp( $userId, 'name' ) : $ip;
93 }
94
101 public function doQuery( array $userIds, $options = [], $caller = '' ) {
102 $usersToCheck = [];
103 $usersToQuery = [];
104
105 $userIds = array_unique( $userIds );
106
107 foreach ( $userIds as $userId ) {
108 $userId = (int)$userId;
109 if ( $userId <= 0 ) {
110 continue; // skip anons
111 }
112 if ( isset( $this->cache[$userId]['name'] ) ) {
113 $usersToCheck[$userId] = $this->cache[$userId]['name']; // already have name
114 } else {
115 $usersToQuery[] = $userId; // we need to get the name
116 }
117 }
118
119 // Lookup basic info for users not yet loaded...
120 if ( count( $usersToQuery ) ) {
121 $dbr = $this->dbProvider->getReplicaDatabase();
122 $queryBuilder = $dbr->newSelectQueryBuilder()
123 ->select( [ 'user_name', 'user_real_name', 'user_registration', 'user_id', 'actor_id' ] )
124 ->from( 'user' )
125 ->join( 'actor', null, 'actor_user = user_id' )
126 ->where( [ 'user_id' => $usersToQuery ] );
127
128 $comment = __METHOD__;
129 if ( strval( $caller ) !== '' ) {
130 $comment .= "/$caller";
131 }
132
133 $res = $queryBuilder->caller( $comment )->fetchResultSet();
134 foreach ( $res as $row ) { // load each user into cache
135 $userId = (int)$row->user_id;
136 $this->cache[$userId]['name'] = $row->user_name;
137 $this->cache[$userId]['real_name'] = $row->user_real_name;
138 $this->cache[$userId]['registration'] = $row->user_registration;
139 $this->cache[$userId]['actor'] = $row->actor_id;
140 $usersToCheck[$userId] = $row->user_name;
141 }
142 }
143
144 $lb = $this->linkBatchFactory->newLinkBatch()
145 ->setCaller( __METHOD__ );
146 foreach ( $usersToCheck as $userId => $name ) {
147 if ( $this->queryNeeded( $userId, 'userpage', $options ) ) {
148 $lb->add( NS_USER, $name );
149 $this->typesCached[$userId]['userpage'] = 1;
150 }
151 if ( $this->queryNeeded( $userId, 'usertalk', $options ) ) {
152 $lb->add( NS_USER_TALK, $name );
153 $this->typesCached[$userId]['usertalk'] = 1;
154 }
155 }
156 $lb->execute();
157 }
158
167 protected function queryNeeded( $uid, $type, array $options ) {
168 return ( in_array( $type, $options ) && !isset( $this->typesCached[$uid][$type] ) );
169 }
170}
171
173class_alias( UserCache::class, 'UserCache' );
const NS_USER
Definition Defines.php:53
const NS_USER_TALK
Definition Defines.php:54
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
array $cache
(uid => property => value)
Definition UserCache.php:22
__construct(LoggerInterface $logger, IConnectionProvider $dbProvider, LinkBatchFactory $linkBatchFactory)
Uses dependency injection since 1.36.
Definition UserCache.php:51
getUserName( $userId, $ip)
Get the name of a user or return $ip if the user ID is 0.
Definition UserCache.php:91
array $typesCached
(uid => cache type => 1)
Definition UserCache.php:24
queryNeeded( $uid, $type, array $options)
Check if a cache type is in $options and was not loaded for this user.
doQuery(array $userIds, $options=[], $caller='')
Preloads user names for given list of users.
getProp( $userId, $prop)
Get a property of a user based on their user ID.
Definition UserCache.php:68
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Factory for LinkBatch objects to batch query page metadata.
Provide primary and replica IDatabase connections.