60 parent::__construct( $query, $moduleName,
'au' );
61 $this->userFactory = $userFactory;
62 $this->userGroupManager = $userGroupManager;
63 $this->groupPermissionsLookup = $groupPermissionsLookup;
64 $this->contentLanguage = $contentLanguage;
73 private function getCanonicalUserName( $name ) {
74 $name = $this->contentLanguage->
ucfirst( $name );
75 return strtr( $name,
'_',
' ' );
80 $activeUserDays = $this->
getConfig()->get( MainConfigNames::ActiveUserDays );
84 $prop = $params[
'prop'];
85 if ( $prop !==
null ) {
86 $prop = array_fill_keys( $prop,
true );
87 $fld_blockinfo = isset( $prop[
'blockinfo'] );
88 $fld_editcount = isset( $prop[
'editcount'] );
89 $fld_groups = isset( $prop[
'groups'] );
90 $fld_rights = isset( $prop[
'rights'] );
91 $fld_registration = isset( $prop[
'registration'] );
92 $fld_implicitgroups = isset( $prop[
'implicitgroups'] );
93 $fld_centralids = isset( $prop[
'centralids'] );
95 $fld_blockinfo = $fld_editcount = $fld_groups = $fld_registration =
96 $fld_rights = $fld_implicitgroups = $fld_centralids =
false;
99 $limit = $params[
'limit'];
103 $dir = ( $params[
'dir'] ==
'descending' ?
'older' :
'newer' );
104 $from = $params[
'from'] ===
null ? null : $this->getCanonicalUserName( $params[
'from'] );
105 $to = $params[
'to'] ===
null ? null : $this->getCanonicalUserName( $params[
'to'] );
107 # MySQL can't figure out that 'user_name' and 'qcc_title' are the same
108 # despite the JOIN condition, so manually sort on the correct one.
109 $userFieldToSort = $params[
'activeusers'] ?
'qcc_title' :
'user_name';
111 # Some of these subtable joins are going to give us duplicate rows, so
112 # calculate the maximum number of duplicates we might see.
113 $maxDuplicateRows = 1;
117 if ( $params[
'prefix'] !==
null ) {
119 $db->buildLike( $this->getCanonicalUserName( $params[
'prefix'] ), $db->anyString() ) );
122 if ( $params[
'rights'] !==
null && count( $params[
'rights'] ) ) {
124 foreach ( $params[
'rights'] as $r ) {
125 $groups = array_merge( $groups, $this->groupPermissionsLookup->getGroupsWithPermission( $r ) );
129 if ( $groups === [] ) {
135 $groups = array_unique( $groups );
137 if ( $params[
'group'] ===
null ) {
138 $params[
'group'] = $groups;
140 $params[
'group'] = array_unique( array_merge( $params[
'group'], $groups ) );
146 if ( $params[
'group'] !==
null && count( $params[
'group'] ) ) {
149 $this->
addTables(
'user_groups',
'ug1' );
154 'ug1.ug_user=user_id',
155 'ug1.ug_group' => $params[
'group'],
156 'ug1.ug_expiry IS NULL OR ug1.ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
160 $maxDuplicateRows *= count( $params[
'group'] );
163 if ( $params[
'excludegroup'] !==
null && count( $params[
'excludegroup'] ) ) {
166 $this->
addTables(
'user_groups',
'ug1' );
168 if ( count( $params[
'excludegroup'] ) == 1 ) {
169 $exclude = [
'ug1.ug_group' => $params[
'excludegroup'][0] ];
171 $exclude = [ $db->makeList(
172 [
'ug1.ug_group' => $params[
'excludegroup'] ],
178 'ug1.ug_user=user_id',
179 'ug1.ug_expiry IS NULL OR ug1.ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
182 $this->
addWhere( [
'ug1.ug_user' =>
null ] );
185 if ( $params[
'witheditsonly'] ) {
186 $this->
addWhere(
'user_editcount > 0' );
189 $this->addBlockInfoToQuery( $fld_blockinfo );
191 if ( $fld_groups || $fld_rights ) {
193 $db->buildGroupConcatField(
'|',
'user_groups',
'ug_group', [
195 'ug_expiry IS NULL OR ug_expiry >= ' . $db->addQuotes( $db->timestamp() )
200 if ( $params[
'activeusers'] ) {
201 $activeUserSeconds = $activeUserDays * 86400;
208 'qcc_type' =>
'activeusers',
210 'qcc_title=user_name',
215 $timestamp = $db->timestamp( (
int)
wfTimestamp( TS_UNIX ) - $activeUserSeconds );
216 $subqueryBuilder = $db->newSelectQueryBuilder()
217 ->select(
'COUNT(*)' )
218 ->from(
'recentchanges' )
219 ->join(
'actor',
null,
'rc_actor = actor_id' )
221 'actor_user = user_id',
223 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes(
'newusers' ),
224 $db->buildComparison(
'>=', [
'rc_timestamp' => $timestamp ] ),
227 'recentactions' =>
'(' . $subqueryBuilder->caller( __METHOD__ )->getSQL() .
')'
231 $sqlLimit = $limit + $maxDuplicateRows;
238 $this->
addFieldsIf(
'user_editcount', $fld_editcount );
239 $this->
addFieldsIf(
'user_registration', $fld_registration );
241 $res = $this->
select( __METHOD__ );
243 $countDuplicates = 0;
246 foreach ( $res as $row ) {
249 if ( $lastUser === $row->user_name ) {
254 if ( $countDuplicates == $maxDuplicateRows ) {
260 $countDuplicates = 0;
261 $lastUser = $row->user_name;
263 if ( $count > $limit ) {
270 if ( $count == $sqlLimit ) {
277 if ( $params[
'activeusers'] && (
int)$row->recentactions === 0 ) {
283 'userid' => (int)$row->user_id,
284 'name' => $row->user_name,
287 if ( $fld_centralids ) {
289 $this->
getConfig(), $this->userFactory->newFromId( (
int)$row->user_id ), $params[
'attachedwiki']
293 if ( $fld_blockinfo && $row->ipb_id !==
null ) {
294 $data += $this->getBlockDetails( DatabaseBlock::newFromRow( $row ) );
296 if ( $row->ipb_deleted ) {
297 $data[
'hidden'] =
true;
299 if ( $fld_editcount ) {
300 $data[
'editcount'] = (int)$row->user_editcount;
302 if ( $params[
'activeusers'] ) {
303 $data[
'recentactions'] = (int)$row->recentactions;
305 if ( $fld_registration ) {
306 $data[
'registration'] = $row->user_registration ?
307 wfTimestamp( TS_ISO_8601, $row->user_registration ) :
'';
310 if ( $fld_implicitgroups || $fld_groups || $fld_rights ) {
311 $implicitGroups = $this->userGroupManager
312 ->getUserImplicitGroups( $this->userFactory->newFromId( (
int)$row->user_id ) );
313 if ( isset( $row->groups ) && $row->groups !==
'' ) {
314 $groups = array_merge( $implicitGroups, explode(
'|', $row->groups ) );
316 $groups = $implicitGroups;
320 $data[
'groups'] = $groups;
325 if ( $fld_implicitgroups ) {
326 $data[
'implicitgroups'] = $implicitGroups;
332 $data[
'rights'] = $this->groupPermissionsLookup->getGroupPermissions( $groups );
338 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $data );
345 $result->addIndexedTagName( [
'query', $this->
getModuleName() ],
'u' );
349 return 'anon-public-user-private';
353 $userGroups = $this->userGroupManager->listAllGroups();
364 ParamValidator::PARAM_DEFAULT =>
'ascending',
365 ParamValidator::PARAM_TYPE => [
371 ParamValidator::PARAM_TYPE => $userGroups,
372 ParamValidator::PARAM_ISMULTI =>
true,
375 ParamValidator::PARAM_TYPE => $userGroups,
376 ParamValidator::PARAM_ISMULTI =>
true,
380 ParamValidator::PARAM_ISMULTI =>
true,
383 ParamValidator::PARAM_ISMULTI =>
true,
384 ParamValidator::PARAM_TYPE => [
396 ParamValidator::PARAM_DEFAULT => 10,
397 ParamValidator::PARAM_TYPE =>
'limit',
398 IntegerDef::PARAM_MIN => 1,
402 'witheditsonly' =>
false,
404 ParamValidator::PARAM_DEFAULT =>
false,
406 'apihelp-query+allusers-param-activeusers',
407 $this->
getConfig()->get( MainConfigNames::ActiveUserDays )
410 'attachedwiki' =>
null,
416 'action=query&list=allusers&aufrom=Y'
417 =>
'apihelp-query+allusers-example-y',
422 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Allusers';
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
if(!defined('MW_SETUP_CALLBACK'))
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, or 'string' with PARAM_ISMULTI,...
const LIMIT_BIG1
Fast query, standard limit.
requireMaxOneParameter( $params,... $required)
Dies if more than one parameter from a certain set of parameters are set and not false.
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When this is set, the result could take longer to generate,...
const LIMIT_BIG2
Fast query, apihighlimits limit.
getModuleName()
Get the name of the module being executed by this instance.
Query module to enumerate all registered users.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
__construct(ApiQuery $query, $moduleName, UserFactory $userFactory, UserGroupManager $userGroupManager, GroupPermissionsLookup $groupPermissionsLookup, Language $contentLanguage)
getExamplesMessages()
Returns usage examples for this module.
getAllowedParams( $flags=0)
getCacheMode( $params)
Get the cache mode for the data generated by this module.
getHelpUrls()
Return links to more detailed help pages about the module.
This is a base class for all Query modules.
setContinueEnumParameter( $paramName, $paramValue)
Set a query-continue value.
addWhereRange( $field, $dir, $start, $end, $sort=true)
Add a WHERE clause corresponding to a range, and an ORDER BY clause to sort in the right direction.
addFields( $value)
Add a set of fields to select to the internal array.
addOption( $name, $value=null)
Add an option such as LIMIT or USE INDEX.
addTables( $tables, $alias=null)
Add a set of tables to the internal array.
getDB()
Get the Query database connection (read-only)
select( $method, $extraQuery=[], array &$hookData=null)
Execute a SELECT query based on the values in the internal arrays.
addFieldsIf( $value, $condition)
Same as addFields(), but add the fields only if a condition is met.
addJoinConds( $join_conds)
Add a set of JOIN conditions to the internal array.
addWhere( $value)
Add a set of WHERE clauses to the internal array.
static getCentralUserInfo(Config $config, UserIdentity $user, $attachedWiki=UserIdentity::LOCAL)
Get central user info.
This is the main query class.
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Base class for language-specific code.
A class containing constants representing the names of configuration variables.
trait ApiQueryBlockInfoTrait