Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
GlobalUserSelectQueryBuilder
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 10
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 init
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 whereGlobalUserIds
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 whereUserNames
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 whereLocked
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 whereRegisteredTimestamp
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 named
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 temp
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 fetchCentralAuthUsers
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 fetchLocalUserIdentitites
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace MediaWiki\Extension\CentralAuth\User;
4
5use EmptyIterator;
6use Iterator;
7use MediaWiki\User\ActorStore;
8use MediaWiki\User\TempUser\TempUserConfig;
9use MediaWiki\User\UserIdentity;
10use MediaWiki\User\UserNameUtils;
11use Wikimedia\Assert\Assert;
12use Wikimedia\Rdbms\IExpression;
13use Wikimedia\Rdbms\IReadableDatabase;
14use Wikimedia\Rdbms\SelectQueryBuilder;
15
16/**
17 * @stable
18 */
19class GlobalUserSelectQueryBuilder extends SelectQueryBuilder {
20
21    /** @var ActorStore for the local wiki */
22    private ActorStore $actorStore;
23
24    private UserNameUtils $userNameUtils;
25    private TempUserConfig $tempUserConfig;
26
27    /** @var bool */
28    private bool $initRan = false;
29
30    /**
31     * @param IReadableDatabase $db
32     * @param ActorStore $actorStore
33     * @param UserNameUtils $userNameUtils
34     * @param TempUserConfig $tempUserConfig
35     */
36    public function __construct(
37        IReadableDatabase $db,
38        ActorStore $actorStore,
39        UserNameUtils $userNameUtils,
40        TempUserConfig $tempUserConfig
41    ) {
42        parent::__construct( $db );
43        $this->actorStore = $actorStore;
44        $this->userNameUtils = $userNameUtils;
45        $this->tempUserConfig = $tempUserConfig;
46    }
47
48    /**
49     * Init the SelectQueryBuilder
50     *
51     * Should be called by ::fetch* methods.
52     */
53    private function init(): void {
54        if ( $this->initRan ) {
55            return;
56        }
57
58        $this->queryInfo( CentralAuthUser::selectQueryInfo() );
59
60        $this->initRan = true;
61    }
62
63    /**
64     * Find by provided global user IDs
65     *
66     * @param int|int[] $globalUserIds
67     * @return $this
68     */
69    public function whereGlobalUserIds( $globalUserIds ): self {
70        Assert::parameterType( 'integer|array', $globalUserIds, '$globalUserIds' );
71
72        $this->conds( [ 'gu_id' => $globalUserIds ] );
73        return $this;
74    }
75
76    /**
77     * Find by provided usernames
78     *
79     * @param string|string[] $userNames
80     * @return $this
81     */
82    public function whereUserNames( $userNames ): self {
83        Assert::parameterType( 'string|array', $userNames, '$userIds' );
84
85        $userNames = array_map( function ( $name ) {
86            return $this->userNameUtils->getCanonical( (string)$name );
87        }, (array)$userNames );
88
89        $this->conds( [ 'gu_name' => $userNames ] );
90        return $this;
91    }
92
93    /**
94     * @param bool $isLocked
95     * @return $this
96     */
97    public function whereLocked( bool $isLocked ): self {
98        $this->conds( [ 'gu_locked' => $isLocked ] );
99        return $this;
100    }
101
102    /**
103     * Return users registered before/after $timestamp
104     *
105     * @param string $timestamp
106     * @param bool $before Direction flag (if true, user_registration must be before $timestamp)
107     * @return self
108     */
109    public function whereRegisteredTimestamp( string $timestamp, bool $before ): self {
110        $this->conds(
111            $this->db->expr( 'gu_registration', $before ? '<' : '>',
112                $this->db->timestamp( $timestamp ) )
113        );
114        return $this;
115    }
116
117    /**
118     * Only return named accounts
119     *
120     * @return $this
121     */
122    public function named(): self {
123        if ( !$this->tempUserConfig->isKnown() ) {
124            // nothing to do: getMatchCondition throws if temp accounts aren't known
125            return $this;
126        }
127        $this->conds( $this->tempUserConfig->getMatchCondition( $this->db, 'gu_name', IExpression::NOT_LIKE ) );
128        return $this;
129    }
130
131    /**
132     * Only return temporary accounts
133     *
134     * @return $this
135     */
136    public function temp(): self {
137        if ( !$this->tempUserConfig->isKnown() ) {
138            $this->conds( '1=0' );
139            return $this;
140        }
141        $this->conds( $this->tempUserConfig->getMatchCondition( $this->db, 'gu_name', IExpression::LIKE ) );
142        return $this;
143    }
144
145    /**
146     * Fetch CentralAuthUsers for the specified query
147     *
148     * @return Iterator<CentralAuthUser>
149     */
150    public function fetchCentralAuthUsers(): Iterator {
151        $this->init();
152
153        $result = $this->fetchResultSet();
154        foreach ( $result as $row ) {
155            yield CentralAuthUser::newFromRow( $row, [] );
156        }
157        $result->free();
158    }
159
160    /**
161     * Fetch UserIdentities for the current wiki
162     *
163     * @return Iterator<UserIdentity>
164     */
165    public function fetchLocalUserIdentitites(): Iterator {
166        $this->init();
167        $this->field( 'lu_local_id' );
168
169        $result = $this->fetchResultSet();
170        $localUserIds = [];
171        foreach ( $result as $row ) {
172            $localUserIds[] = $row->lu_local_id;
173        }
174
175        if ( $localUserIds === [] ) {
176            return new EmptyIterator();
177        }
178
179        return $this->actorStore->newSelectQueryBuilder()
180            ->whereUserIds( $localUserIds )
181            ->caller( $this->getCaller() )
182            ->fetchUserIdentities();
183    }
184}