112 $parms = explode(
'/', $par );
113 $symsForAll = [
'*',
'user' ];
115 if ( $parms[0] !=
'' &&
116 ( in_array( $par, $userGroupManager->
listAllGroups() ) || in_array( $par, $symsForAll ) )
118 $this->requestedGroup = $par;
119 $un = $request->getText(
'username' );
120 } elseif ( count( $parms ) == 2 ) {
121 $this->requestedGroup = $parms[0];
124 $this->requestedGroup = $request->getVal(
'group' );
125 $un = ( $par !=
'' ) ? $par : $request->getText(
'username' );
128 if ( in_array( $this->requestedGroup, $symsForAll ) ) {
129 $this->requestedGroup =
'';
131 $this->editsOnly = $request->getBool(
'editsOnly' );
132 $this->temporaryGroupsOnly = $request->getBool(
'temporaryGroupsOnly' );
133 $this->creationSort = $request->getBool(
'creationSort' );
135 $this->mDefaultDirection = $request->getBool(
'desc' )
139 $this->requestedUser =
'';
142 $username = Title::makeTitleSafe(
NS_USER, $un );
144 if ( $username !==
null ) {
145 $this->requestedUser = $username->getText();
151 parent::__construct();
152 $this->userGroupManager = $userGroupManager;
153 $this->hookRunner =
new HookRunner( $hookContainer );
154 $this->linkBatchFactory = $linkBatchFactory;
155 $this->userIdentityLookup = $userIdentityLookup;
174 $conds[
'ipb_deleted'] = [
null, 0 ];
179 if ( $this->requestedGroup !=
'' || $this->temporaryGroupsOnly ) {
180 $conds[] =
'ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() ) .
181 ( !$this->temporaryGroupsOnly ?
' OR ug_expiry IS NULL' :
'' );
184 if ( $this->requestedGroup !=
'' ) {
188 if ( $this->requestedUser !=
'' ) {
189 # Sorted either by account creation or name
190 if ( $this->creationSort ) {
191 $userIdentity = $this->userIdentityLookup->getUserIdentityByName( $this->requestedUser );
192 if ( $userIdentity && $userIdentity->isRegistered() ) {
193 $conds[] =
'user_id >= ' . $userIdentity->getId();
196 $conds[] =
'user_name >= ' . $dbr->addQuotes( $this->requestedUser );
200 if ( $this->editsOnly ) {
201 $conds[] =
'user_editcount > 0';
204 $options[
'GROUP BY'] = $this->creationSort ?
'user_id' :
'user_name';
207 'tables' => [
'user',
'user_groups',
'ipblocks' ],
209 'user_name' => $this->creationSort ?
'MAX(user_name)' :
'user_name',
210 'user_id' => $this->creationSort ?
'user_id' :
'MAX(user_id)',
211 'edits' =>
'MAX(user_editcount)',
212 'creation' =>
'MIN(user_registration)',
213 'ipb_deleted' =>
'MAX(ipb_deleted)',
214 'ipb_sitewide' =>
'MAX(ipb_sitewide)'
216 'options' => $options,
218 'user_groups' => [
'LEFT JOIN',
'user_id=ug_user' ],
229 $this->hookRunner->onSpecialListusersQueryInfo( $this, $query );
239 if ( $row->user_id == 0 ) { # T18487
243 $userName = $row->user_name;
245 $ulinks = Linker::userLink( $row->user_id, $userName );
246 $ulinks .= Linker::userToolLinksRedContribs(
260 if ( !$this->including && count( $ugms ) > 0 ) {
262 foreach ( $ugms as $ugm ) {
265 $groups = $lang->commaList( $list );
268 $item = $lang->specialList( $ulinks, $groups );
270 if ( $row->ipb_deleted ) {
271 $item =
"<span class=\"deleted\">$item</span>";
276 $count = $this->
msg(
'usereditcount' )->numParams( $row->edits )->escaped();
277 $edits = $this->
msg(
'word-separator' )->escaped() . $this->
msg(
'brackets', $count )->escaped();
281 # Some rows may be null
282 if ( !$this->including && $row->creation ) {
284 $d = $lang->userDate( $row->creation, $user );
285 $t = $lang->userTime( $row->creation, $user );
286 $created = $this->
msg(
'usercreated', $d, $t, $row->user_name )->escaped();
287 $created =
' ' . $this->
msg(
'parentheses' )->rawParams( $created )->escaped();
290 $blocked = $row->ipb_deleted !==
null && $row->ipb_sitewide ===
'1' ?
291 ' ' . $this->
msg(
'listusers-blocked', $userName )->escaped() :
294 $this->hookRunner->onSpecialListusersFormatRow( $item, $row );
296 return Html::rawElement(
'li', [],
"{$item}{$edits}{$created}{$blocked}" );
300 $batch = $this->linkBatchFactory->newLinkBatch();
302 # Give some pointers to make user links
303 foreach ( $this->mResult as $row ) {
304 $batch->add(
NS_USER, $row->user_name );
306 $userIds[] = (int)$row->user_id;
310 $queryBuilder = $this->userGroupManager->newQueryBuilder( $this->
getDatabase() );
311 $groupRes = $queryBuilder->where( [
'ug_user' => $userIds ] )
312 ->caller( __METHOD__ )
316 foreach ( $groupRes as $row ) {
317 $ugm = $this->userGroupManager->newGroupMembershipFromRow( $row );
318 if ( !$ugm->isExpired() ) {
319 $cache[$row->ug_user][$row->ug_group] = $ugm;
320 $groups[$row->ug_group] =
true;
326 $this->hookRunner->onUsersPagerDoBatchLookups( $this->
getDatabase(), $userIds, $cache, $groups );
328 $this->userGroupCache = $cache;
331 foreach ( $groups as $group => $unused ) {
332 $groupPage = UserGroupMembership::getGroupPage( $group );
334 $batch->addObj( $groupPage );
339 $this->mResult->rewind();
346 $self = explode(
'/', $this->
getTitle()->getPrefixedDBkey(), 2 )[0];
348 $groupOptions = [ $this->
msg(
'group-all' )->text() =>
'' ];
349 foreach ( $this->getAllGroups() as $group => $groupText ) {
350 $groupOptions[ $groupText ] = $group;
355 'class' => HTMLUserTextField::class,
356 'label' => $this->
msg(
'listusersfrom' )->text(),
357 'name' =>
'username',
361 'label' => $this->
msg(
'group' )->text(),
364 'class' => HTMLSelectField::class,
365 'options' => $groupOptions,
369 'label' => $this->
msg(
'listusers-editsonly' )->text(),
370 'name' =>
'editsOnly',
374 'temporaryGroupsOnly' => [
376 'label' => $this->
msg(
'listusers-temporarygroupsonly' )->text(),
377 'name' =>
'temporaryGroupsOnly',
378 'id' =>
'temporaryGroupsOnly',
383 'label' => $this->
msg(
'listusers-creationsort' )->text(),
384 'name' =>
'creationSort',
385 'id' =>
'creationSort',
390 'label' => $this->
msg(
'listusers-desc' )->text(),
395 'limithiddenfield' => [
396 'class' => HTMLHiddenField::class,
402 $beforeSubmitButtonHookOut =
'';
403 $this->hookRunner->onSpecialListusersHeaderForm( $this, $beforeSubmitButtonHookOut );
405 if ( $beforeSubmitButtonHookOut !==
'' ) {
406 $formDescriptor[
'beforeSubmitButtonHookOut' ] = [
407 'class' => HTMLInfoField::class,
409 'default' => $beforeSubmitButtonHookOut
413 $formDescriptor[
'submit' ] = [
414 'class' => HTMLSubmitField::class,
415 'buttonlabel-message' =>
'listusers-submit',
418 $beforeClosingFieldsetHookOut =
'';
419 $this->hookRunner->onSpecialListusersHeader( $this, $beforeClosingFieldsetHookOut );
421 if ( $beforeClosingFieldsetHookOut !==
'' ) {
422 $formDescriptor[
'beforeClosingFieldsetHookOut' ] = [
423 'class' => HTMLInfoField::class,
425 'default' => $beforeClosingFieldsetHookOut
429 $htmlForm = HTMLForm::factory(
'ooui', $formDescriptor, $this->
getContext() );
432 ->setTitle( Title::newFromText(
$self ) )
433 ->setId(
'mw-listusers-form' )
434 ->setFormIdentifier(
'mw-listusers-form' )
435 ->suppressDefaultSubmit()
436 ->setWrapperLegendMsg(
'listusers' );
437 return $htmlForm->prepareForm()->getHTML(
true );