MediaWiki  master
GenderCache.php
Go to the documentation of this file.
1 <?php
30 
36 class GenderCache {
37  protected $cache = [];
38  protected $default;
39  protected $misses = 0;
40  protected $missLimit = 1000;
41 
43  private $nsInfo;
44 
46  private $loadBalancer;
47 
50 
51  public function __construct(
52  NamespaceInfo $nsInfo = null,
55  ) {
56  $this->nsInfo = $nsInfo ?? MediaWikiServices::getInstance()->getNamespaceInfo();
57  $this->loadBalancer = $loadBalancer;
58  $this->userOptionsLookup = $userOptionsLookup ?? MediaWikiServices::getInstance()->getUserOptionsLookup();
59  }
60 
65  protected function getDefault() {
66  if ( $this->default === null ) {
67  $this->default = $this->userOptionsLookup->getDefaultOption( 'gender' );
68  }
69 
70  return $this->default;
71  }
72 
79  public function getGenderOf( $username, $caller = '' ) {
80  if ( $username instanceof UserIdentity ) {
81  $username = $username->getName();
82  }
83 
84  $username = self::normalizeUsername( $username );
85  if ( !isset( $this->cache[$username] ) ) {
86  if ( $this->misses >= $this->missLimit &&
87  RequestContext::getMain()->getUser()->getName() !== $username
88  ) {
89  if ( $this->misses === $this->missLimit ) {
90  $this->misses++;
91  wfDebug( __METHOD__ . ": too many misses, returning default onwards" );
92  }
93 
94  return $this->getDefault();
95  } else {
96  $this->misses++;
97  $this->doQuery( $username, $caller );
98  }
99  }
100 
101  /* Undefined if there is a valid username which for some reason doesn't
102  * exist in the database.
103  */
104  return $this->cache[$username] ?? $this->getDefault();
105  }
106 
113  public function doLinkBatch( $data, $caller = '' ) {
114  $users = [];
115  foreach ( $data as $ns => $pagenames ) {
116  if ( !$this->nsInfo->hasGenderDistinction( $ns ) ) {
117  continue;
118  }
119  foreach ( array_keys( $pagenames ) as $username ) {
120  $users[$username] = true;
121  }
122  }
123 
124  $this->doQuery( array_keys( $users ), $caller );
125  }
126 
134  public function doTitlesArray( $titles, $caller = '' ) {
135  $users = [];
136  foreach ( $titles as $titleObj ) {
137  if ( !$this->nsInfo->hasGenderDistinction( $titleObj->getNamespace() ) ) {
138  continue;
139  }
140  $users[] = $titleObj->getText();
141  }
142 
143  $this->doQuery( $users, $caller );
144  }
145 
151  public function doQuery( $users, $caller = '' ) {
152  $default = $this->getDefault();
153 
154  $usersToCheck = [];
155  foreach ( (array)$users as $value ) {
156  $name = self::normalizeUsername( $value );
157  // Skip users whose gender setting we already know
158  if ( !isset( $this->cache[$name] ) ) {
159  // For existing users, this value will be overwritten by the correct value
160  $this->cache[$name] = $default;
161  // query only for valid names, which can be in the database
162  if ( User::isValidUserName( $name ) ) {
163  $usersToCheck[] = $name;
164  }
165  }
166  }
167 
168  if ( count( $usersToCheck ) === 0 ) {
169  return;
170  }
171 
172  // Only query database, when load balancer is provided by service wiring
173  // This maybe not happen when running as part of the installer
174  if ( $this->loadBalancer === null ) {
175  return;
176  }
177 
178  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
179  $table = [ 'user', 'user_properties' ];
180  $fields = [ 'user_name', 'up_value' ];
181  $conds = [ 'user_name' => $usersToCheck ];
182  $joins = [ 'user_properties' =>
183  [ 'LEFT JOIN', [ 'user_id = up_user', 'up_property' => 'gender' ] ] ];
184 
185  $comment = __METHOD__;
186  if ( strval( $caller ) !== '' ) {
187  $comment .= "/$caller";
188  }
189  $res = $dbr->select( $table, $fields, $conds, $comment, [], $joins );
190 
191  foreach ( $res as $row ) {
192  $this->cache[$row->user_name] = $row->up_value ?: $default;
193  }
194  }
195 
196  private static function normalizeUsername( $username ) {
197  // Strip off subpages
198  $indexSlash = strpos( $username, '/' );
199  if ( $indexSlash !== false ) {
200  $username = substr( $username, 0, $indexSlash );
201  }
202 
203  // normalize underscore/spaces
204  return strtr( $username, '_', ' ' );
205  }
206 }
GenderCache\doLinkBatch
doLinkBatch( $data, $caller='')
Wrapper for doQuery that processes raw LinkBatch data.
Definition: GenderCache.php:113
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:166
GenderCache\__construct
__construct(NamespaceInfo $nsInfo=null, ILoadBalancer $loadBalancer=null, UserOptionsLookup $userOptionsLookup=null)
Definition: GenderCache.php:51
getUser
getUser()
GenderCache
Caches user genders when needed to use correct namespace aliases.
Definition: GenderCache.php:36
GenderCache\$loadBalancer
ILoadBalancer null $loadBalancer
Definition: GenderCache.php:46
User\isValidUserName
static isValidUserName( $name)
Is the input a valid username?
Definition: User.php:986
$res
$res
Definition: testCompression.php:57
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:32
GenderCache\getGenderOf
getGenderOf( $username, $caller='')
Returns the gender for given username.
Definition: GenderCache.php:79
GenderCache\doTitlesArray
doTitlesArray( $titles, $caller='')
Wrapper for doQuery that processes a title array.
Definition: GenderCache.php:134
$dbr
$dbr
Definition: testCompression.php:54
GenderCache\getDefault
getDefault()
Returns the default gender option in this wiki.
Definition: GenderCache.php:65
GenderCache\$missLimit
$missLimit
Definition: GenderCache.php:40
GenderCache\$nsInfo
NamespaceInfo $nsInfo
Definition: GenderCache.php:43
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:914
GenderCache\normalizeUsername
static normalizeUsername( $username)
Definition: GenderCache.php:196
GenderCache\$cache
$cache
Definition: GenderCache.php:37
GenderCache\doQuery
doQuery( $users, $caller='')
Preloads genders for given list of users.
Definition: GenderCache.php:151
GenderCache\$default
$default
Definition: GenderCache.php:38
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:454
MediaWiki\User\UserOptionsLookup
Provides access to user options.
Definition: UserOptionsLookup.php:29
GenderCache\$misses
$misses
Definition: GenderCache.php:39
NamespaceInfo
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Definition: NamespaceInfo.php:35
GenderCache\$userOptionsLookup
UserOptionsLookup $userOptionsLookup
Definition: GenderCache.php:49
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81