115 $parms = explode(
'/', $par );
116 $symsForAll = [
'*',
'user' ];
118 if ( $parms[0] !=
'' &&
119 ( in_array( $par, $userGroupManager->
listAllGroups() ) || in_array( $par, $symsForAll ) )
121 $this->requestedGroup = $par;
122 $un = $request->getText(
'username' );
123 } elseif ( count( $parms ) == 2 ) {
124 $this->requestedGroup = $parms[0];
127 $this->requestedGroup = $request->getVal(
'group' );
128 $un = ( $par !=
'' ) ? $par : $request->getText(
'username' );
131 if ( in_array( $this->requestedGroup, $symsForAll ) ) {
132 $this->requestedGroup =
'';
134 $this->editsOnly = $request->getBool(
'editsOnly' );
135 $this->temporaryGroupsOnly = $request->getBool(
'temporaryGroupsOnly' );
136 $this->creationSort = $request->getBool(
'creationSort' );
138 $this->mDefaultDirection = $request->getBool(
'desc' )
142 $this->requestedUser =
'';
145 $username = Title::makeTitleSafe(
NS_USER, $un );
147 if ( $username !==
null ) {
148 $this->requestedUser = $username->getText();
154 parent::__construct();
155 $this->userGroupManager = $userGroupManager;
156 $this->hookRunner =
new HookRunner( $hookContainer );
157 $this->linkBatchFactory = $linkBatchFactory;
158 $this->userIdentityLookup = $userIdentityLookup;
159 $this->blockTargetReadStage = $this->
getConfig()
167 return $this->creationSort ?
'user_id' :
'user_name';
181 $conds[
'ipb_deleted'] = [
null, 0 ];
187 $options[
'HAVING'][
'deleted'] = [
null, 0 ];
191 if ( $this->requestedGroup !=
'' || $this->temporaryGroupsOnly ) {
192 $cond = $dbr->expr(
'ug_expiry',
'>=', $dbr->timestamp() );
193 if ( !$this->temporaryGroupsOnly ) {
194 $cond = $cond->or(
'ug_expiry',
'=',
null );
199 if ( $this->requestedGroup !=
'' ) {
203 if ( $this->requestedUser !=
'' ) {
204 # Sorted either by account creation or name
205 if ( $this->creationSort ) {
206 $userIdentity = $this->userIdentityLookup->getUserIdentityByName( $this->requestedUser );
207 if ( $userIdentity && $userIdentity->isRegistered() ) {
208 $conds[] =
'user_id >= ' . $userIdentity->getId();
211 $conds[] = $dbr->expr(
'user_name',
'>=', $this->requestedUser );
215 if ( $this->editsOnly ) {
216 $conds[] =
'user_editcount > 0';
219 $options[
'GROUP BY'] = $this->creationSort ?
'user_id' :
'user_name';
223 'tables' => [
'user',
'user_groups',
'ipblocks' ],
225 'user_name' => $this->creationSort ?
'MAX(user_name)' :
'user_name',
226 'user_id' => $this->creationSort ?
'user_id' :
'MAX(user_id)',
227 'edits' =>
'MAX(user_editcount)',
228 'creation' =>
'MIN(user_registration)',
229 'deleted' =>
'MAX(ipb_deleted)',
230 'sitewide' =>
'MAX(ipb_sitewide)'
232 'options' => $options,
234 'user_groups' => [
'LEFT JOIN',
'user_id=ug_user' ],
249 'block_with_target' => [
255 'user_name' => $this->creationSort ?
'MAX(user_name)' :
'user_name',
256 'user_id' => $this->creationSort ?
'user_id' :
'MAX(user_id)',
257 'edits' =>
'MAX(user_editcount)',
258 'creation' =>
'MIN(user_registration)',
259 'deleted' =>
'MAX(bl_deleted)',
260 'sitewide' =>
'MAX(bl_sitewide)'
262 'options' => $options,
264 'user_groups' => [
'LEFT JOIN',
'user_id=ug_user' ],
265 'block_with_target' => [
271 'block' => [
'JOIN',
'bl_target=bt_id' ]
277 $this->hookRunner->onSpecialListusersQueryInfo( $this, $query );
287 if ( $row->user_id == 0 ) { # T18487
291 $userName = $row->user_name;
293 $ulinks = Linker::userLink( $row->user_id, $userName );
294 $ulinks .= Linker::userToolLinksRedContribs(
308 if ( !$this->including && count( $ugms ) > 0 ) {
310 foreach ( $ugms as $ugm ) {
313 $groups = $lang->commaList( $list );
316 $item = $lang->specialList( $ulinks, $groups );
318 if ( $row->deleted ) {
319 $item =
"<span class=\"deleted\">$item</span>";
324 $count = $this->
msg(
'usereditcount' )->numParams( $row->edits )->escaped();
325 $edits = $this->
msg(
'word-separator' )->escaped() . $this->
msg(
'brackets', $count )->escaped();
329 # Some rows may be null
330 if ( !$this->including && $row->creation ) {
332 $d = $lang->userDate( $row->creation, $user );
333 $t = $lang->userTime( $row->creation, $user );
334 $created = $this->
msg(
'usercreated', $d, $t, $row->user_name )->escaped();
335 $created =
' ' . $this->
msg(
'parentheses' )->rawParams( $created )->escaped();
338 $blocked = $row->deleted !==
null && $row->sitewide ===
'1' ?
339 ' ' . $this->
msg(
'listusers-blocked', $userName )->escaped() :
342 $this->hookRunner->onSpecialListusersFormatRow( $item, $row );
344 return Html::rawElement(
'li', [],
"{$item}{$edits}{$created}{$blocked}" );
348 $batch = $this->linkBatchFactory->newLinkBatch();
350 # Give some pointers to make user links
351 foreach ( $this->mResult as $row ) {
352 $batch->add(
NS_USER, $row->user_name );
354 $userIds[] = (int)$row->user_id;
358 $queryBuilder = $this->userGroupManager->newQueryBuilder( $this->
getDatabase() );
359 $groupRes = $queryBuilder->where( [
'ug_user' => $userIds ] )
360 ->caller( __METHOD__ )
364 foreach ( $groupRes as $row ) {
365 $ugm = $this->userGroupManager->newGroupMembershipFromRow( $row );
366 if ( !$ugm->isExpired() ) {
367 $cache[$row->ug_user][$row->ug_group] = $ugm;
368 $groups[$row->ug_group] =
true;
374 $this->hookRunner->onUsersPagerDoBatchLookups( $this->
getDatabase(), $userIds, $cache, $groups );
376 $this->userGroupCache = $cache;
379 foreach ( $groups as $group => $unused ) {
380 $groupPage = UserGroupMembership::getGroupPage( $group );
382 $batch->addObj( $groupPage );
387 $this->mResult->rewind();
394 $self = explode(
'/', $this->
getTitle()->getPrefixedDBkey(), 2 )[0];
396 $groupOptions = [ $this->
msg(
'group-all' )->text() =>
'' ];
397 foreach ( $this->getAllGroups() as $group => $groupText ) {
398 $groupOptions[ $groupText ] = $group;
403 'class' => HTMLUserTextField::class,
404 'label' => $this->
msg(
'listusersfrom' )->text(),
405 'name' =>
'username',
409 'label' => $this->
msg(
'group' )->text(),
412 'class' => HTMLSelectField::class,
413 'options' => $groupOptions,
417 'label' => $this->
msg(
'listusers-editsonly' )->text(),
418 'name' =>
'editsOnly',
422 'temporaryGroupsOnly' => [
424 'label' => $this->
msg(
'listusers-temporarygroupsonly' )->text(),
425 'name' =>
'temporaryGroupsOnly',
426 'id' =>
'temporaryGroupsOnly',
431 'label' => $this->
msg(
'listusers-creationsort' )->text(),
432 'name' =>
'creationSort',
433 'id' =>
'creationSort',
438 'label' => $this->
msg(
'listusers-desc' )->text(),
443 'limithiddenfield' => [
444 'class' => HTMLHiddenField::class,
450 $beforeSubmitButtonHookOut =
'';
451 $this->hookRunner->onSpecialListusersHeaderForm( $this, $beforeSubmitButtonHookOut );
453 if ( $beforeSubmitButtonHookOut !==
'' ) {
454 $formDescriptor[
'beforeSubmitButtonHookOut' ] = [
455 'class' => HTMLInfoField::class,
457 'default' => $beforeSubmitButtonHookOut
461 $formDescriptor[
'submit' ] = [
462 'class' => HTMLSubmitField::class,
463 'buttonlabel-message' =>
'listusers-submit',
466 $beforeClosingFieldsetHookOut =
'';
467 $this->hookRunner->onSpecialListusersHeader( $this, $beforeClosingFieldsetHookOut );
469 if ( $beforeClosingFieldsetHookOut !==
'' ) {
470 $formDescriptor[
'beforeClosingFieldsetHookOut' ] = [
471 'class' => HTMLInfoField::class,
473 'default' => $beforeClosingFieldsetHookOut
477 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $this->
getContext() );
480 ->setTitle( Title::newFromText(
$self ) )
481 ->setId(
'mw-listusers-form' )
482 ->setFormIdentifier(
'mw-listusers-form' )
483 ->suppressDefaultSubmit()
484 ->setWrapperLegendMsg(
'listusers' );
485 return $htmlForm->prepareForm()->getHTML(
true );
496 private function getAllGroups() {
499 foreach ( $this->userGroupManager->listAllGroups() as $group ) {
500 $result[$group] = $lang->getGroupName( $group );
512 $query = parent::getDefaultQuery();
513 if ( $this->requestedGroup !=
'' ) {
516 if ( $this->requestedUser !=
'' ) {
519 $this->hookRunner->onSpecialListusersDefaultQuery( $this, $query );
532 if ( $this->userGroupCache ===
null ) {
533 return $this->userGroupManager->getUserGroupMemberships( $user );
535 return $this->userGroupCache[$user->getId()] ?? [];
547 return UserGroupMembership::getLinkHTML( $group, $this->
getContext(), $username );
555class_alias( UsersPager::class,
'UsersPager' );
const SCHEMA_COMPAT_READ_OLD
const SCHEMA_COMPAT_READ_MASK
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
getContext()
Get the base IContextSource object.
setContext(IContextSource $context)
An information field (text blob), not a proper input.
Add a submit button inline in the form (as opposed to HTMLForm::addButton(), which will add it at the...
Implements a text input field for user names.
A class containing constants representing the names of configuration variables.
const Edititis
Name constant for the Edititis setting, for use with Config::get()
const BlockTargetMigrationStage
Name constant for the BlockTargetMigrationStage setting, for use with Config::get()
Interface for objects which can provide a MediaWiki context on request.