MediaWiki  master
ActiveUsersPager.php
Go to the documentation of this file.
1 <?php
26 
35 
39  protected $opts;
40 
44  protected $groups;
45 
50 
52  private $RCMaxAge;
53 
55  private $excludegroups;
56 
65  public function __construct(
69  HookContainer $hookContainer,
70  ILoadBalancer $loadBalancer,
72  ) {
73  parent::__construct(
74  $context,
75  null,
76  null,
78  $hookContainer,
79  $loadBalancer,
81  );
82 
83  $this->RCMaxAge = $this->getConfig()->get( 'ActiveUserDays' );
84  $this->requestedUser = '';
85 
86  $un = $opts->getValue( 'username' );
87  if ( $un != '' ) {
88  $username = Title::makeTitleSafe( NS_USER, $un );
89  if ( $username !== null ) {
90  $this->requestedUser = $username->getText();
91  }
92  }
93 
94  $this->groups = $opts->getValue( 'groups' );
95  $this->excludegroups = $opts->getValue( 'excludegroups' );
96  // Backwards-compatibility with old URLs
97  if ( $opts->getValue( 'hidebots' ) ) {
98  $this->excludegroups[] = 'bot';
99  }
100  if ( $opts->getValue( 'hidesysops' ) ) {
101  $this->excludegroups[] = 'sysop';
102  }
103  }
104 
105  public function getIndexField() {
106  return 'qcc_title';
107  }
108 
109  public function getQueryInfo( $data = null ) {
110  $dbr = $this->getDatabase();
111 
112  $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
113  $timestamp = $dbr->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
114  $fname = __METHOD__ . ' (' . $this->getSqlComment() . ')';
115 
116  // Inner subselect to pull the active users out of querycachetwo
117  $tables = [ 'querycachetwo', 'user', 'actor' ];
118  $fields = [ 'qcc_title', 'user_id', 'actor_id' ];
119  $jconds = [
120  'user' => [ 'JOIN', 'user_name = qcc_title' ],
121  'actor' => [ 'JOIN', 'actor_user = user_id' ],
122  ];
123  $conds = [
124  'qcc_type' => 'activeusers',
125  'qcc_namespace' => NS_USER,
126  ];
127  $options = [];
128  if ( $data !== null ) {
129  $options['ORDER BY'] = 'qcc_title ' . $data['order'];
130  $options['LIMIT'] = $data['limit'];
131  $conds = array_merge( $conds, $data['conds'] );
132  }
133  if ( $this->requestedUser != '' ) {
134  $conds[] = 'qcc_title >= ' . $dbr->addQuotes( $this->requestedUser );
135  }
136  if ( $this->groups !== [] ) {
137  $tables['ug1'] = 'user_groups';
138  $jconds['ug1'] = [ 'JOIN', 'ug1.ug_user = user_id' ];
139  $conds['ug1.ug_group'] = $this->groups;
140  $conds[] = 'ug1.ug_expiry IS NULL OR ug1.ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() );
141  }
142  if ( $this->excludegroups !== [] ) {
143  $tables['ug2'] = 'user_groups';
144  $jconds['ug2'] = [ 'LEFT JOIN', [
145  'ug2.ug_user = user_id',
146  'ug2.ug_group' => $this->excludegroups,
147  'ug2.ug_expiry IS NULL OR ug2.ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() ),
148  ] ];
149  $conds['ug2.ug_user'] = null;
150  }
151  if ( !$this->canSeeHideuser() ) {
152  $conds[] = 'NOT EXISTS (' . $dbr->selectSQLText(
153  'ipblocks', '1', [ 'ipb_user=user_id', 'ipb_deleted' => 1 ], __METHOD__
154  ) . ')';
155  }
156  $subquery = $dbr->buildSelectSubquery( $tables, $fields, $conds, $fname, $options, $jconds );
157 
158  // Outer query to select the recent edit counts for the selected active users
159  $tables = [ 'qcc_users' => $subquery, 'recentchanges' ];
160  $jconds = [ 'recentchanges' => [ 'LEFT JOIN', [
161  'rc_actor = actor_id',
162  'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ), // Don't count wikidata.
163  'rc_type != ' . $dbr->addQuotes( RC_CATEGORIZE ), // Don't count categorization changes.
164  'rc_log_type IS NULL OR rc_log_type != ' . $dbr->addQuotes( 'newusers' ),
165  'rc_timestamp >= ' . $dbr->addQuotes( $timestamp ),
166  ] ] ];
167  $conds = [];
168 
169  return [
170  'tables' => $tables,
171  'fields' => [
172  'qcc_title',
173  'user_name' => 'qcc_title',
174  'user_id' => 'user_id',
175  'recentedits' => 'COUNT(rc_id)'
176  ],
177  'options' => [ 'GROUP BY' => [ 'qcc_title', 'user_id' ] ],
178  'conds' => $conds,
179  'join_conds' => $jconds,
180  ];
181  }
182 
183  protected function buildQueryInfo( $offset, $limit, $order ) {
184  $fname = __METHOD__ . ' (' . $this->getSqlComment() . ')';
185 
186  $sortColumns = array_merge( [ $this->mIndexField ], $this->mExtraSortFields );
187  if ( $order === self::QUERY_ASCENDING ) {
188  $dir = 'ASC';
189  $orderBy = $sortColumns;
190  $operator = $this->mIncludeOffset ? '>=' : '>';
191  } else {
192  $dir = 'DESC';
193  $orderBy = [];
194  foreach ( $sortColumns as $col ) {
195  $orderBy[] = $col . ' DESC';
196  }
197  $operator = $this->mIncludeOffset ? '<=' : '<';
198  }
199  $info = $this->getQueryInfo( [
200  'limit' => intval( $limit ),
201  'order' => $dir,
202  'conds' =>
203  $offset != '' ? [ $this->mIndexField . $operator . $this->getDatabase()->addQuotes( $offset ) ] : [],
204  ] );
205 
206  $tables = $info['tables'];
207  $fields = $info['fields'];
208  $conds = $info['conds'];
209  $options = $info['options'];
210  $join_conds = $info['join_conds'];
211  $options['ORDER BY'] = $orderBy;
212  return [ $tables, $fields, $conds, $fname, $options, $join_conds ];
213  }
214 
215  protected function doBatchLookups() {
216  parent::doBatchLookups();
217 
218  $uids = [];
219  foreach ( $this->mResult as $row ) {
220  $uids[] = $row->user_id;
221  }
222  // Fetch the block status of the user for showing "(blocked)" text and for
223  // striking out names of suppressed users when privileged user views the list.
224  // Although the first query already hits the block table for un-privileged, this
225  // is done in two queries to avoid huge quicksorts and to make COUNT(*) correct.
226  $dbr = $this->getDatabase();
227  $res = $dbr->select( 'ipblocks',
228  [ 'ipb_user', 'deleted' => 'MAX(ipb_deleted)', 'sitewide' => 'MAX(ipb_sitewide)' ],
229  [ 'ipb_user' => $uids ],
230  __METHOD__,
231  [ 'GROUP BY' => [ 'ipb_user' ] ]
232  );
233  $this->blockStatusByUid = [];
234  foreach ( $res as $row ) {
235  $this->blockStatusByUid[$row->ipb_user] = [
236  'deleted' => $row->deleted,
237  'sitewide' => $row->sitewide,
238  ];
239  }
240  $this->mResult->seek( 0 );
241  }
242 
243  public function formatRow( $row ) {
244  $userName = $row->user_name;
245 
246  $ulinks = Linker::userLink( $row->user_id, $userName );
247  $ulinks .= Linker::userToolLinks(
248  $row->user_id,
249  $userName,
250  // Should the contributions link be red if the user has no edits (using default)
251  false,
252  // Customisation flags (using default 0)
253  0,
254  // User edit count (using default)
255  null,
256  // do not wrap the message in parentheses (CSS will provide these)
257  false
258  );
259 
260  $lang = $this->getLanguage();
261 
262  $list = [];
263 
264  $ugms = self::getGroupMemberships( intval( $row->user_id ), $this->userGroupCache );
265  foreach ( $ugms as $ugm ) {
266  $list[] = $this->buildGroupLink( $ugm, $userName );
267  }
268 
269  $groups = $lang->commaList( $list );
270 
271  $item = $lang->specialList( $ulinks, $groups );
272 
273  // If there is a block, 'deleted' and 'sitewide' are both set on
274  // $this->blockStatusByUid[$row->user_id].
275  $blocked = '';
276  $isBlocked = isset( $this->blockStatusByUid[$row->user_id] );
277  if ( $isBlocked ) {
278  if ( $this->blockStatusByUid[$row->user_id]['deleted'] == 1 ) {
279  $item = "<span class=\"deleted\">$item</span>";
280  }
281  if ( $this->blockStatusByUid[$row->user_id]['sitewide'] == 1 ) {
282  $blocked = ' ' . $this->msg( 'listusers-blocked', $userName )->escaped();
283  }
284  }
285  $count = $this->msg( 'activeusers-count' )->numParams( $row->recentedits )
286  ->params( $userName )->numParams( $this->RCMaxAge )->escaped();
287 
288  return Html::rawElement( 'li', [], "{$item} [{$count}]{$blocked}" );
289  }
290 
291 }
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:38
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:71
Linker\userLink
static userLink( $userId, $userName, $altUserName=false)
Make user link (or user contributions for unregistered users)
Definition: Linker.php:900
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
FormOptions\getValue
getValue( $name)
Get the value for the given option name.
Definition: FormOptions.php:182
ActiveUsersPager\buildQueryInfo
buildQueryInfo( $offset, $limit, $order)
Build variables to use by the database wrapper.
Definition: ActiveUsersPager.php:183
UsersPager\buildGroupLink
buildGroupLink( $group, $username)
Format a link to a group description page.
Definition: UsersPager.php:485
UsersPager\$linkBatchFactory
LinkBatchFactory $linkBatchFactory
Definition: UsersPager.php:65
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1692
Linker\userToolLinks
static userToolLinks( $userId, $userText, $redContribsWhenNoEdits=false, $flags=0, $edits=null, $useParentheses=true)
Generate standard user tool links (talk, contributions, block link, etc.)
Definition: Linker.php:945
ActiveUsersPager\$blockStatusByUid
array $blockStatusByUid
Definition: ActiveUsersPager.php:49
IndexPager\getDatabase
getDatabase()
Get the Database object in use.
Definition: IndexPager.php:244
ActiveUsersPager\getQueryInfo
getQueryInfo( $data=null)
Definition: ActiveUsersPager.php:109
ActiveUsersPager\$excludegroups
string[] $excludegroups
Definition: ActiveUsersPager.php:55
$res
$res
Definition: testCompression.php:57
ActiveUsersPager\$RCMaxAge
int $RCMaxAge
Definition: ActiveUsersPager.php:52
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:152
ActiveUsersPager
This class is used to get a list of active users.
Definition: ActiveUsersPager.php:34
MediaWiki\User\UserGroupManager
Managers user groups.
Definition: UserGroupManager.php:52
MediaWiki\Cache\LinkBatchFactory
Definition: LinkBatchFactory.php:39
UsersPager
This class is used to get a list of user.
Definition: UsersPager.php:39
ActiveUsersPager\formatRow
formatRow( $row)
Definition: ActiveUsersPager.php:243
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:196
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:676
ActiveUsersPager\getIndexField
getIndexField()
Definition: ActiveUsersPager.php:105
RC_EXTERNAL
const RC_EXTERNAL
Definition: Defines.php:118
ActiveUsersPager\__construct
__construct(?IContextSource $context, FormOptions $opts, LinkBatchFactory $linkBatchFactory, HookContainer $hookContainer, ILoadBalancer $loadBalancer, UserGroupManager $userGroupManager)
Definition: ActiveUsersPager.php:65
UsersPager\$userGroupManager
UserGroupManager $userGroupManager
Definition: UsersPager.php:71
NS_USER
const NS_USER
Definition: Defines.php:66
ActiveUsersPager\$opts
FormOptions $opts
Definition: ActiveUsersPager.php:39
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:57
UsersPager\getGroupMemberships
static getGroupMemberships( $uid, $cache=null)
Get an associative array containing groups the specified user belongs to, and the relevant UserGroupM...
Definition: UsersPager.php:469
IndexPager\getSqlComment
getSqlComment()
Get some text to go in brackets in the "function name" part of the SQL comment.
Definition: IndexPager.php:429
UsersPager\getQueryInfo
getQueryInfo()
Definition: UsersPager.php:153
RC_CATEGORIZE
const RC_CATEGORIZE
Definition: Defines.php:119
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
ActiveUsersPager\$groups
string[] $groups
Definition: ActiveUsersPager.php:44
MediaWiki\HookContainer\HookContainer
HookContainer class.
Definition: HookContainer.php:45
FormOptions
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
ActiveUsersPager\doBatchLookups
doBatchLookups()
Called from getBody(), before getStartBody() is called and after doQuery() was called.
Definition: ActiveUsersPager.php:215
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
UsersPager\canSeeHideuser
canSeeHideuser()
Definition: UsersPager.php:426