MediaWiki REL1_41
GenderCache.php
Go to the documentation of this file.
1<?php
28
40 protected $cache = [];
41 protected $default = null;
42 protected $misses = 0;
43 /* @internal Exposed for MediaWiki core unit tests. */
44 protected $missLimit = 1000;
45
46 private NamespaceInfo $nsInfo;
47 private ?IConnectionProvider $dbProvider;
48 private UserOptionsLookup $userOptionsLookup;
49
50 public function __construct(
51 NamespaceInfo $nsInfo = null,
52 IConnectionProvider $dbProvider = null,
53 UserOptionsLookup $userOptionsLookup = null
54 ) {
55 $this->nsInfo = $nsInfo ?? MediaWikiServices::getInstance()->getNamespaceInfo();
56 $this->dbProvider = $dbProvider;
57 $this->userOptionsLookup = $userOptionsLookup ?? MediaWikiServices::getInstance()->getUserOptionsLookup();
58 }
59
65 protected function getDefault() {
66 $this->default ??= $this->userOptionsLookup->getDefaultOption( 'gender' );
67 return $this->default;
68 }
69
77 public function getGenderOf( $username, $caller = '' ) {
78 if ( $username instanceof UserIdentity ) {
79 $username = $username->getName();
80 }
81
82 $username = self::normalizeUsername( $username );
83 if ( !isset( $this->cache[$username] ) ) {
84 if ( $this->misses < $this->missLimit ||
85 RequestContext::getMain()->getUser()->getName() === $username
86 ) {
87 $this->misses++;
88 $this->doQuery( $username, $caller );
89 }
90 if ( $this->misses === $this->missLimit ) {
91 // Log only once and don't bother incrementing beyond limit+1
92 $this->misses++;
93 wfDebug( __METHOD__ . ': too many misses, returning default onwards' );
94 }
95 }
96
97 return $this->cache[$username] ?? $this->getDefault();
98 }
99
106 public function doLinkBatch( array $data, $caller = '' ) {
107 $users = [];
108 foreach ( $data as $ns => $pagenames ) {
109 if ( $this->nsInfo->hasGenderDistinction( $ns ) ) {
110 $users += $pagenames;
111 }
112 }
113 $this->doQuery( array_keys( $users ), $caller );
114 }
115
123 public function doTitlesArray( $titles, $caller = '' ) {
124 $users = [];
125 foreach ( $titles as $titleObj ) {
126 if ( $this->nsInfo->hasGenderDistinction( $titleObj->getNamespace() ) ) {
127 $users[] = $titleObj->getText();
128 }
129 }
130 $this->doQuery( $users, $caller );
131 }
132
139 public function doQuery( $users, $caller = '' ) {
140 $default = $this->getDefault();
141
142 $usersToFetch = [];
143 foreach ( (array)$users as $value ) {
144 $name = self::normalizeUsername( $value );
145 if ( !isset( $this->cache[$name] ) ) {
146 // This may be overwritten below by a fetched value
147 $this->cache[$name] = $default;
148 // T267054: We don't need to fetch data for invalid usernames, but filtering breaks DI
149 $usersToFetch[] = $name;
150 }
151 }
152
153 // Skip query when database is unavailable (e.g. via the installer)
154 if ( !$usersToFetch || !$this->dbProvider ) {
155 return;
156 }
157
158 $caller = __METHOD__ . ( $caller ? "/$caller" : '' );
159
160 $res = $queryBuilder = $this->dbProvider->getReplicaDatabase()->newSelectQueryBuilder()
161 ->select( [ 'user_name', 'up_value' ] )
162 ->from( 'user' )
163 ->leftJoin( 'user_properties', null, [ 'user_id = up_user', 'up_property' => 'gender' ] )
164 ->where( [ 'user_name' => $usersToFetch ] )
165 ->caller( $caller )
166 ->fetchResultSet();
167
168 foreach ( $res as $row ) {
169 $this->cache[$row->user_name] = $row->up_value ?: $default;
170 }
171 }
172
173 private static function normalizeUsername( $username ) {
174 // Strip off subpages
175 $indexSlash = strpos( $username, '/' );
176 if ( $indexSlash !== false ) {
177 $username = substr( $username, 0, $indexSlash );
178 }
179
180 // normalize underscore/spaces
181 return strtr( $username, '_', ' ' );
182 }
183}
getUser()
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Look up "gender" user preference.
__construct(NamespaceInfo $nsInfo=null, IConnectionProvider $dbProvider=null, UserOptionsLookup $userOptionsLookup=null)
getGenderOf( $username, $caller='')
Get the gender option for given username.
doLinkBatch(array $data, $caller='')
Wrapper for doQuery that processes raw LinkBatch data.
getDefault()
Get the default gender option on this wiki.
doTitlesArray( $titles, $caller='')
Wrapper for doQuery that processes a title array.
doQuery( $users, $caller='')
Preload gender option for multiple user names.
Service locator for MediaWiki core services.
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Provides access to user options.
Represents the target of a wiki link.
Interface for objects representing user identity.
Provide primary and replica IDatabase connections.