MediaWiki REL1_35
GenderCache.php
Go to the documentation of this file.
1<?php
30
37 protected $cache = [];
38 protected $default;
39 protected $misses = 0;
40 protected $missLimit = 1000;
41
43 private $nsInfo;
44
47
50
51 public function __construct(
52 NamespaceInfo $nsInfo = null,
53 ILoadBalancer $loadBalancer = null,
54 UserOptionsLookup $userOptionsLookup = null
55 ) {
56 $this->nsInfo = $nsInfo ?? MediaWikiServices::getInstance()->getNamespaceInfo();
57 $this->loadBalancer = $loadBalancer;
58 $this->userOptionsLookup = $userOptionsLookup ?? MediaWikiServices::getInstance()->getUserOptionsLookup();
59 }
60
66 public static function singleton() {
67 wfDeprecated( __METHOD__, '1.28' );
68 return MediaWikiServices::getInstance()->getGenderCache();
69 }
70
75 protected function getDefault() {
76 if ( $this->default === null ) {
77 $this->default = $this->userOptionsLookup->getDefaultOption( 'gender' );
78 }
79
80 return $this->default;
81 }
82
89 public function getGenderOf( $username, $caller = '' ) {
90 global $wgUser;
91
92 if ( $username instanceof UserIdentity ) {
93 $username = $username->getName();
94 }
95
96 $username = self::normalizeUsername( $username );
97 if ( !isset( $this->cache[$username] ) ) {
98 if ( $this->misses >= $this->missLimit && $wgUser->getName() !== $username ) {
99 if ( $this->misses === $this->missLimit ) {
100 $this->misses++;
101 wfDebug( __METHOD__ . ": too many misses, returning default onwards" );
102 }
103
104 return $this->getDefault();
105 } else {
106 $this->misses++;
107 $this->doQuery( $username, $caller );
108 }
109 }
110
111 /* Undefined if there is a valid username which for some reason doesn't
112 * exist in the database.
113 */
114 return $this->cache[$username] ?? $this->getDefault();
115 }
116
123 public function doLinkBatch( $data, $caller = '' ) {
124 $users = [];
125 foreach ( $data as $ns => $pagenames ) {
126 if ( !$this->nsInfo->hasGenderDistinction( $ns ) ) {
127 continue;
128 }
129 foreach ( array_keys( $pagenames ) as $username ) {
130 $users[$username] = true;
131 }
132 }
133
134 $this->doQuery( array_keys( $users ), $caller );
135 }
136
144 public function doTitlesArray( $titles, $caller = '' ) {
145 $users = [];
146 foreach ( $titles as $titleObj ) {
147 if ( !$this->nsInfo->hasGenderDistinction( $titleObj->getNamespace() ) ) {
148 continue;
149 }
150 $users[] = $titleObj->getText();
151 }
152
153 $this->doQuery( $users, $caller );
154 }
155
161 public function doQuery( $users, $caller = '' ) {
162 $default = $this->getDefault();
163
164 $usersToCheck = [];
165 foreach ( (array)$users as $value ) {
166 $name = self::normalizeUsername( $value );
167 // Skip users whose gender setting we already know
168 if ( !isset( $this->cache[$name] ) ) {
169 // For existing users, this value will be overwritten by the correct value
170 $this->cache[$name] = $default;
171 // query only for valid names, which can be in the database
172 if ( User::isValidUserName( $name ) ) {
173 $usersToCheck[] = $name;
174 }
175 }
176 }
177
178 if ( count( $usersToCheck ) === 0 ) {
179 return;
180 }
181
182 // Only query database, when load balancer is provided by service wiring
183 // This maybe not happen when running as part of the installer
184 if ( $this->loadBalancer === null ) {
185 return;
186 }
187
188 $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
189 $table = [ 'user', 'user_properties' ];
190 $fields = [ 'user_name', 'up_value' ];
191 $conds = [ 'user_name' => $usersToCheck ];
192 $joins = [ 'user_properties' =>
193 [ 'LEFT JOIN', [ 'user_id = up_user', 'up_property' => 'gender' ] ] ];
194
195 $comment = __METHOD__;
196 if ( strval( $caller ) !== '' ) {
197 $comment .= "/$caller";
198 }
199 $res = $dbr->select( $table, $fields, $conds, $comment, [], $joins );
200
201 foreach ( $res as $row ) {
202 $this->cache[$row->user_name] = $row->up_value ?: $default;
203 }
204 }
205
206 private static function normalizeUsername( $username ) {
207 // Strip off subpages
208 $indexSlash = strpos( $username, '/' );
209 if ( $indexSlash !== false ) {
210 $username = substr( $username, 0, $indexSlash );
211 }
212
213 // normalize underscore/spaces
214 return strtr( $username, '_', ' ' );
215 }
216}
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Caches user genders when needed to use correct namespace aliases.
static singleton()
__construct(NamespaceInfo $nsInfo=null, ILoadBalancer $loadBalancer=null, UserOptionsLookup $userOptionsLookup=null)
getGenderOf( $username, $caller='')
Returns the gender for given username.
static normalizeUsername( $username)
NamespaceInfo $nsInfo
UserOptionsLookup $userOptionsLookup
doLinkBatch( $data, $caller='')
Wrapper for doQuery that processes raw LinkBatch data.
getDefault()
Returns the default gender option in this wiki.
ILoadBalancer null $loadBalancer
doTitlesArray( $titles, $caller='')
Wrapper for doQuery that processes a title array.
doQuery( $users, $caller='')
Preloads genders for given list of users.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Provides access to user options.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
static isValidUserName( $name)
Is the input a valid username?
Definition User.php:979
Interface for objects representing user identity.
Database cluster connection, tracking, load balancing, and transaction manager interface.
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:25