22use Wikimedia\Timestamp\TimestampFormat as TS;
67 parent::__construct( $query, $moduleName,
'us' );
75 if ( $params[
'prop'] !==
null ) {
76 $this->prop = array_fill_keys( $params[
'prop'],
true );
80 $useNames = $params[
'users'] !==
null;
82 $users = (array)$params[
'users'];
83 $userids = (array)$params[
'userids'];
85 $goodNames = $done = [];
88 foreach ( $users as $u ) {
89 $n = $this->userNameUtils->getCanonical( $u );
90 if ( $n ===
false || $n ===
'' ) {
91 $vals = [
'name' => $u,
'invalid' => true ];
92 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
96 implode(
'|', array_diff( $users, $done ) ) );
107 $parameters = &$goodNames;
109 $parameters = &$userids;
114 if ( count( $parameters ) ) {
122 $this->addDeletedUserFilter();
125 $res = $this->
select( __METHOD__ );
129 if ( isset( $this->prop[
'groups'] ) || isset( $this->prop[
'rights'] ) ) {
140 $this->
addJoinConds( [
'user_groups' => [
'JOIN',
'ug_user=user_id' ] ] );
142 $this->
addFields( [
'ug_user',
'ug_group',
'ug_expiry' ] );
144 $db->expr(
'ug_expiry',
'=',
null )->or(
'ug_expiry',
'>=', $db->timestamp() )
146 $userGroupsRes = $this->
select( __METHOD__ );
148 foreach ( $userGroupsRes as $row ) {
149 $userGroups[$row->user_name][] = $row;
152 if ( isset( $this->prop[
'gender'] ) ) {
154 foreach ( $res as $row ) {
155 $userNames[] = $row->user_name;
157 $this->genderCache->doQuery( $userNames, __METHOD__ );
160 if ( isset( $this->prop[
'blockinfo'] ) ) {
161 $blockInfos = $this->getBlockDetailsForRows( $res );
166 if ( isset( $this->prop[
'tempexpired'] ) ) {
168 foreach ( $res as $row ) {
169 if ( $this->tempUserConfig->isTempName( $row->user_name ) ) {
170 $tempUsers[] = UserIdentityValue::newRegistered( $row->user_id, $row->user_name );
173 $this->tempUserDetailsLookup->preloadExpirationStatus( $tempUsers );
176 foreach ( $res as $row ) {
179 if ( !isset( $userGroups ) ) {
180 $user = $this->userFactory->newFromRow( $row );
182 if ( !isset( $userGroups[$row->user_name] ) || !is_array( $userGroups[$row->user_name] ) ) {
183 $userGroups[$row->user_name] = [];
185 $user = $this->userFactory->newFromRow( $row, [
'user_groups' => $userGroups[$row->user_name] ] );
188 $key = $user->getName();
190 $key = $user->getId();
192 $data[$key][
'userid'] = $user->getId();
193 $data[$key][
'name'] = $user->getName();
195 if ( $user->isSystemUser() ) {
196 $data[$key][
'systemuser'] =
true;
199 if ( isset( $this->prop[
'editcount'] ) ) {
200 $data[$key][
'editcount'] = $user->getEditCount();
203 if ( isset( $this->prop[
'registration'] ) ) {
204 $data[$key][
'registration'] =
wfTimestampOrNull( TS::ISO_8601, $user->getRegistration() );
207 if ( isset( $this->prop[
'groups'] ) ) {
208 $data[$key][
'groups'] = $this->userGroupManager->getUserEffectiveGroups(
209 $user, IDBAccessObject::READ_NORMAL,
false,
false );
212 if ( isset( $this->prop[
'groupmemberships'] ) ) {
213 $data[$key][
'groupmemberships'] = array_map(
static function ( $ugm ) {
215 'group' => $ugm->getGroup(),
218 }, $this->userGroupManager->getUserGroupMemberships( $user ) );
221 if ( isset( $this->prop[
'implicitgroups'] ) ) {
222 $data[$key][
'implicitgroups'] = $this->userGroupManager->getUserImplicitGroups( $user );
225 if ( isset( $this->prop[
'rights'] ) ) {
227 ->getUserPermissions( $user,
false );
229 if ( $row->hu_deleted ) {
230 $data[$key][
'hidden'] =
true;
232 if ( isset( $this->prop[
'blockinfo'] ) && isset( $blockInfos[$row->user_id] ) ) {
233 $data[$key] += $blockInfos[$row->user_id];
236 if ( isset( $this->prop[
'emailable'] ) ) {
237 $data[$key][
'emailable'] = $user->canReceiveEmail();
240 if ( isset( $this->prop[
'gender'] ) ) {
241 $data[$key][
'gender'] = $this->genderCache->getGenderOf( $user, __METHOD__ );
244 if ( isset( $this->prop[
'centralids'] ) ) {
246 $this->
getConfig(), $user, $params[
'attachedwiki']
250 if ( isset( $this->prop[
'tempexpired'] ) ) {
251 if ( $this->tempUserConfig->isTempName( $row->user_name ) ) {
252 $data[$key][
'tempexpired'] = $this->tempUserDetailsLookup->isExpired( $user );
254 $data[$key][
'tempexpired'] =
null;
261 foreach ( $parameters as $u ) {
262 if ( !isset( $data[$u] ) ) {
264 $data[$u] = [
'name' => $u,
'missing' => true ];
265 if ( isset( $this->prop[
'cancreate'] ) ) {
266 $status = $this->authManager->canCreateAccount( $u );
267 $data[$u][
'cancreate'] = $status->isGood();
268 if ( !$status->isGood() ) {
269 $data[$u][
'cancreateerror'] = $this->
getErrorFormatter()->arrayFromStatus( $status );
273 $data[$u] = [
'userid' => $u,
'missing' => true ];
277 if ( isset( $this->prop[
'groups'] ) && isset( $data[$u][
'groups'] ) ) {
281 if ( isset( $this->prop[
'groupmemberships'] ) && isset( $data[$u][
'groupmemberships'] ) ) {
285 if ( isset( $this->prop[
'implicitgroups'] ) && isset( $data[$u][
'implicitgroups'] ) ) {
289 if ( isset( $this->prop[
'rights'] ) && isset( $data[$u][
'rights'] ) ) {
295 $fit = $result->addValue( [
'query', $this->
getModuleName() ],
null, $data[$u] );
299 implode(
'|', array_diff( $users, $done ) ) );
302 implode(
'|', array_diff( $userids, $done ) ) );
308 $result->addIndexedTagName( [
'query', $this->
getModuleName() ],
'user' );
313 if ( array_diff( (array)$params[
'prop'], static::$publicProps ) ) {
314 return 'anon-public-user-private';
324 ParamValidator::PARAM_ISMULTI =>
true,
325 ParamValidator::PARAM_TYPE => [
343 'attachedwiki' =>
null,
345 ParamValidator::PARAM_ISMULTI => true
348 ParamValidator::PARAM_ISMULTI =>
true,
349 ParamValidator::PARAM_TYPE =>
'integer'
357 'action=query&list=users&ususers=Example&usprop=groups|editcount|gender'
358 =>
'apihelp-query+users-example-simple',
364 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Users';
369class_alias( ApiQueryUsers::class,
'ApiQueryUsers' );
wfTimestampOrNull( $outputtype=TS::UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
trait ApiQueryBlockInfoTrait