MediaWiki master
GenderCache.php
Go to the documentation of this file.
1<?php
8namespace MediaWiki\Cache;
9
16
29 protected $cache = [];
31 protected $default = null;
33 protected $misses = 0;
38 protected $missLimit = 1000;
39
40 private NamespaceInfo $nsInfo;
41 private UserOptionsLookup $userOptionsLookup;
42
43 public function __construct(
44 NamespaceInfo $nsInfo,
45 UserOptionsLookup $userOptionsLookup
46 ) {
47 $this->nsInfo = $nsInfo;
48 $this->userOptionsLookup = $userOptionsLookup;
49 }
50
56 protected function getDefault() {
57 $this->default ??= $this->userOptionsLookup->getDefaultOption( 'gender' );
58 return $this->default;
59 }
60
68 public function getGenderOf( $username, $caller = '' ) {
69 if ( $username instanceof UserIdentity ) {
70 $username = $username->getName();
71 }
72
73 $username = self::normalizeUsername( $username );
74 if ( !isset( $this->cache[$username] ) ) {
75 if ( $this->misses < $this->missLimit ||
76 RequestContext::getMain()->getUser()->getName() === $username
77 ) {
78 $this->misses++;
79 $this->doQuery( $username );
80 }
81 if ( $this->misses === $this->missLimit ) {
82 // Log only once and don't bother incrementing beyond limit+1
83 $this->misses++;
84 wfDebug( __METHOD__ . ': too many misses, returning default onwards' );
85 }
86 }
87
88 return $this->cache[$username] ?? $this->getDefault();
89 }
90
97 public function doLinkBatch( array $data, $caller = '' ) {
98 $users = [];
99 foreach ( $data as $ns => $pagenames ) {
100 if ( $this->nsInfo->hasGenderDistinction( $ns ) ) {
101 $users += $pagenames;
102 }
103 }
104 $this->doQuery( array_keys( $users ) );
105 }
106
114 public function doTitlesArray( $titles, $caller = '' ) {
115 $users = [];
116 foreach ( $titles as $titleObj ) {
117 if ( $this->nsInfo->hasGenderDistinction( $titleObj->getNamespace() ) ) {
118 $users[] = $titleObj->getText();
119 }
120 }
121 $this->doQuery( $users );
122 }
123
130 public function doPageRows( $rows ) {
131 $users = [];
132 foreach ( $rows as $row ) {
133 if ( $this->nsInfo->hasGenderDistinction( (int)$row->page_namespace ) ) {
134 $users[] = $row->page_title;
135 }
136 }
137 $this->doQuery( $users );
138 }
139
146 public function doQuery( $users, $caller = '' ) {
147 $usersToFetch = [];
148 foreach ( (array)$users as $userName ) {
149 $userName = self::normalizeUsername( $userName );
150 if ( !isset( $this->cache[$userName] ) ) {
151 $usersToFetch[] = $userName;
152 }
153 }
154 if ( !$usersToFetch ) {
155 return;
156 }
157
158 // Limit batch size to 1000 since the usernames need to be put into an
159 // IN() expression in SQL. Could be done closer to the backend, but
160 // there are multiple backends.
161 foreach ( array_chunk( array_unique( $usersToFetch ), 1000 ) as $batch ) {
162 $genders = $this->userOptionsLookup->getOptionBatchForUserNames( $batch, 'gender' );
163 foreach ( $genders as $userName => $gender ) {
164 $this->cache[$userName] = $gender;
165 }
166 }
167 }
168
169 private static function normalizeUsername( string $username ): string {
170 // Strip off subpages
171 $indexSlash = strpos( $username, '/' );
172 if ( $indexSlash !== false ) {
173 $username = substr( $username, 0, $indexSlash );
174 }
175
176 // normalize underscore/spaces
177 return strtr( $username, '_', ' ' );
178 }
179}
180
182class_alias( GenderCache::class, 'GenderCache' );
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, UserOptionsLookup $userOptionsLookup)
doQuery( $users, $caller='')
Preload gender option for multiple user names.
doPageRows( $rows)
Process a set of rows from the page table.
getDefault()
Get the default gender option on this wiki.
getGenderOf( $username, $caller='')
Get the gender option for given username.
doTitlesArray( $titles, $caller='')
Wrapper for doQuery that processes a title array.
doLinkBatch(array $data, $caller='')
Wrapper for doQuery that processes raw LinkBatch data.
Group all the pieces relevant to the context of a request into one instance.
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.
Result wrapper for grabbing data queried from an IDatabase object.