87 $activeUserDays = $this->
getConfig()->get( MainConfigNames::ActiveUserDays );
91 $prop = $params[
'prop'];
92 if ( $prop !==
null ) {
93 $prop = array_fill_keys( $prop,
true );
94 $fld_blockinfo = isset( $prop[
'blockinfo'] );
95 $fld_editcount = isset( $prop[
'editcount'] );
96 $fld_groups = isset( $prop[
'groups'] );
97 $fld_rights = isset( $prop[
'rights'] );
98 $fld_registration = isset( $prop[
'registration'] );
99 $fld_implicitgroups = isset( $prop[
'implicitgroups'] );
100 $fld_centralids = isset( $prop[
'centralids'] );
102 $fld_blockinfo = $fld_editcount = $fld_groups = $fld_registration =
103 $fld_rights = $fld_implicitgroups = $fld_centralids =
false;
106 $limit = $params[
'limit'];
110 $dir = ( $params[
'dir'] ==
'descending' ?
'older' :
'newer' );
111 $from = $params[
'from'] ===
null ? null : $this->getCanonicalUserName( $params[
'from'] );
112 $to = $params[
'to'] ===
null ? null : $this->getCanonicalUserName( $params[
'to'] );
114 # MySQL can't figure out that 'user_name' and 'qcc_title' are the same
115 # despite the JOIN condition, so manually sort on the correct one.
116 $userFieldToSort = $params[
'activeusers'] ?
'qcc_title' :
'user_name';
118 # Some of these subtable joins are going to give us duplicate rows, so
119 # calculate the maximum number of duplicates we might see.
120 $maxDuplicateRows = 1;
124 if ( $params[
'prefix'] !==
null ) {
126 $db->buildLike( $this->getCanonicalUserName( $params[
'prefix'] ), $db->anyString() ) );
129 if ( $params[
'rights'] !==
null && count( $params[
'rights'] ) ) {
131 foreach ( $params[
'rights'] as $r ) {
132 $groups = array_merge( $groups, $this->groupPermissionsLookup->getGroupsWithPermission( $r ) );
136 if ( $groups === [] ) {
142 $groups = array_unique( $groups );
144 if ( $params[
'group'] ===
null ) {
145 $params[
'group'] = $groups;
147 $params[
'group'] = array_unique( array_merge( $params[
'group'], $groups ) );
153 if ( $params[
'group'] !==
null && count( $params[
'group'] ) ) {
156 $this->
addTables(
'user_groups',
'ug1' );
161 'ug1.ug_user=user_id',
162 'ug1.ug_group' => $params[
'group'],
163 'ug1.ug_expiry IS NULL OR ug1.ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
167 $maxDuplicateRows *= count( $params[
'group'] );
170 if ( $params[
'excludegroup'] !==
null && count( $params[
'excludegroup'] ) ) {
173 $this->
addTables(
'user_groups',
'ug1' );
175 if ( count( $params[
'excludegroup'] ) == 1 ) {
176 $exclude = [
'ug1.ug_group' => $params[
'excludegroup'][0] ];
178 $exclude = [ $db->makeList(
179 [
'ug1.ug_group' => $params[
'excludegroup'] ],
185 'ug1.ug_user=user_id',
186 'ug1.ug_expiry IS NULL OR ug1.ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
189 $this->
addWhere(
'ug1.ug_user IS NULL' );
192 if ( $params[
'witheditsonly'] ) {
193 $this->
addWhere(
'user_editcount > 0' );
196 $this->addBlockInfoToQuery( $fld_blockinfo );
198 if ( $fld_groups || $fld_rights ) {
200 $db->buildGroupConcatField(
'|',
'user_groups',
'ug_group', [
202 'ug_expiry IS NULL OR ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
207 if ( $params[
'activeusers'] ) {
208 $activeUserSeconds = $activeUserDays * 86400;
215 'qcc_type' =>
'activeusers',
217 'qcc_title=user_name',
222 $timestamp = $db->timestamp( (
int)
wfTimestamp( TS_UNIX ) - $activeUserSeconds );
223 $subqueryBuilder = $db->newSelectQueryBuilder()
224 ->select(
'COUNT(*)' )
225 ->from(
'recentchanges' )
226 ->join(
'actor',
null,
'rc_actor = actor_id' )
228 'actor_user = user_id',
230 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes(
'newusers' ),
231 $db->buildComparison(
'>=', [
'rc_timestamp' => $timestamp ] ),
234 'recentactions' =>
'(' . $subqueryBuilder->caller( __METHOD__ )->getSQL() .
')'
238 $sqlLimit = $limit + $maxDuplicateRows;
245 $this->
addFieldsIf(
'user_editcount', $fld_editcount );
246 $this->
addFieldsIf(
'user_registration', $fld_registration );
250 $countDuplicates = 0;
253 foreach (
$res as $row ) {
256 if ( $lastUser === $row->user_name ) {
261 if ( $countDuplicates == $maxDuplicateRows ) {
267 $countDuplicates = 0;
268 $lastUser = $row->user_name;
270 if ( $count > $limit ) {
277 if ( $count == $sqlLimit ) {
284 if ( $params[
'activeusers'] && (
int)$row->recentactions === 0 ) {
290 'userid' => (int)$row->user_id,
291 'name' => $row->user_name,
294 if ( $fld_centralids ) {
296 $this->
getConfig(), $this->userFactory->newFromId( (
int)$row->user_id ), $params[
'attachedwiki']
300 if ( $fld_blockinfo && $row->ipb_id !==
null ) {
301 $data += $this->getBlockDetails( DatabaseBlock::newFromRow( $row ) );
303 if ( $row->ipb_deleted ) {
304 $data[
'hidden'] =
true;
306 if ( $fld_editcount ) {
307 $data[
'editcount'] = (int)$row->user_editcount;
309 if ( $params[
'activeusers'] ) {
310 $data[
'recentactions'] = (int)$row->recentactions;
312 if ( $fld_registration ) {
313 $data[
'registration'] = $row->user_registration ?
314 wfTimestamp( TS_ISO_8601, $row->user_registration ) :
'';
317 if ( $fld_implicitgroups || $fld_groups || $fld_rights ) {
318 $implicitGroups = $this->userGroupManager
319 ->getUserImplicitGroups( $this->userFactory->newFromId( (
int)$row->user_id ) );
320 if ( isset( $row->groups ) && $row->groups !==
'' ) {
321 $groups = array_merge( $implicitGroups, explode(
'|', $row->groups ) );
323 $groups = $implicitGroups;
327 $data[
'groups'] = $groups;
328 ApiResult::setIndexedTagName( $data[
'groups'],
'g' );
329 ApiResult::setArrayType( $data[
'groups'],
'array' );
332 if ( $fld_implicitgroups ) {
333 $data[
'implicitgroups'] = $implicitGroups;
334 ApiResult::setIndexedTagName( $data[
'implicitgroups'],
'g' );
335 ApiResult::setArrayType( $data[
'implicitgroups'],
'array' );
339 $data[
'rights'] = $this->groupPermissionsLookup->getGroupPermissions( $groups );
340 ApiResult::setIndexedTagName( $data[
'rights'],
'r' );
341 ApiResult::setArrayType( $data[
'rights'],
'array' );
345 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $data );
352 $result->addIndexedTagName( [
'query', $this->
getModuleName() ],
'u' );
360 $userGroups = $this->userGroupManager->listAllGroups();
371 ParamValidator::PARAM_DEFAULT =>
'ascending',
372 ParamValidator::PARAM_TYPE => [
378 ParamValidator::PARAM_TYPE => $userGroups,
379 ParamValidator::PARAM_ISMULTI =>
true,
382 ParamValidator::PARAM_TYPE => $userGroups,
383 ParamValidator::PARAM_ISMULTI =>
true,
387 ParamValidator::PARAM_ISMULTI =>
true,
390 ParamValidator::PARAM_ISMULTI =>
true,
391 ParamValidator::PARAM_TYPE => [
403 ParamValidator::PARAM_DEFAULT => 10,
404 ParamValidator::PARAM_TYPE =>
'limit',
405 IntegerDef::PARAM_MIN => 1,
409 'witheditsonly' =>
false,
411 ParamValidator::PARAM_DEFAULT =>
false,
413 'apihelp-query+allusers-param-activeusers',
414 $this->
getConfig()->get( MainConfigNames::ActiveUserDays )
417 'attachedwiki' =>
null,