Passed
Push — master ( 585e03...f7d4e3 )
by MusikAnimal
05:22
created

UserRepository::getIdAndRegistration()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 2
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the UserRepository class.
4
 */
5
6
namespace Xtools;
7
8
use Mediawiki\Api\SimpleRequest;
9
use Symfony\Component\DependencyInjection\Container;
10
use Symfony\Component\HttpFoundation\Session\Session;
11
12
/**
13
 * This class provides data for the User class.
14
 * @codeCoverageIgnore
15
 */
16
class UserRepository extends Repository
17
{
18
    /**
19
     * Convenience method to get a new User object.
20
     * @param string $username The username.
21
     * @param Container $container The DI container.
22
     * @return User
23
     */
24
    public static function getUser($username, Container $container)
25
    {
26
        $user = new User($username);
27
        $userRepo = new UserRepository();
28
        $userRepo->setContainer($container);
29
        $user->setRepository($userRepo);
30
        return $user;
31
    }
32
33
    /**
34
     * Get the user's ID and registration date.
35
     * @param string $databaseName The database to query.
36
     * @param string $username The username to find.
37
     * @return array [int ID, string|null registration date].
38
     */
39
    public function getIdAndRegistration($databaseName, $username)
40
    {
41
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_id_reg');
42
        if ($this->cache->hasItem($cacheKey)) {
43
            return $this->cache->getItem($cacheKey)->get();
44
        }
45
46
        $userTable = $this->getTableName($databaseName, 'user');
47
        $sql = "SELECT user_id AS userId, user_registration AS regDate
48
                FROM $userTable
49
                WHERE user_name = :username
50
                LIMIT 1";
51
        $resultQuery = $this->executeProjectsQuery($sql, ['username' => $username]);
52
53
        // Cache and return.
54
        return $this->setCache($cacheKey, $resultQuery->fetch());
55
    }
56
57
    /**
58
     * Get the user's registration date.
59
     * @param string $databaseName The database to query.
60
     * @param string $username The username to find.
61
     * @return string|null As returned by the database.
62
     */
63
    public function getRegistrationDate($databaseName, $username)
64
    {
65
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_registration');
66
        if ($this->cache->hasItem($cacheKey)) {
67
            return $this->cache->getItem($cacheKey)->get();
68
        }
69
70
        $userTable = $this->getTableName($databaseName, 'user');
71
        $sql = "SELECT user_registration FROM $userTable WHERE user_name = :username LIMIT 1";
72
        $resultQuery = $this->executeProjectsQuery($sql, ['username' => $username]);
73
        $registrationDate = $resultQuery->fetchColumn();
74
75
        // Cache and return.
76
        return $this->setCache($cacheKey, $registrationDate);
77
    }
78
79
    /**
80
     * Get the user's (system) edit count.
81
     * @param string $databaseName The database to query.
82
     * @param string $username The username to find.
83
     * @return int|null As returned by the database.
84
     */
85
    public function getEditCount($databaseName, $username)
86
    {
87
        // Quick cache of edit count, valid on for the same request.
88
        static $editCount = null;
89
        if ($editCount !== null) {
90
            return $editCount;
91
        }
92
93
        $userTable = $this->getTableName($databaseName, 'user');
94
        $sql = "SELECT user_editcount FROM $userTable WHERE user_name = :username LIMIT 1";
95
        $resultQuery = $this->executeProjectsQuery($sql, ['username' => $username]);
96
        $editCount = $resultQuery->fetchColumn();
97
        return $editCount;
98
    }
99
100
    /**
101
     * Get group names of the given user.
102
     * @param Project $project The project.
103
     * @param string $username The username.
104
     * @return string[]
105
     */
106
    public function getGroups(Project $project, $username)
107
    {
108
        // Use md5 to ensure the key does not contain reserved characters.
109
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_groups');
110
        if ($this->cache->hasItem($cacheKey)) {
111
            return $this->cache->getItem($cacheKey)->get();
112
        }
113
114
        $this->stopwatch->start($cacheKey, 'XTools');
115
        $api = $this->getMediawikiApi($project);
116
        $params = [
117
            'list' => 'users',
118
            'ususers' => $username,
119
            'usprop' => 'groups'
120
        ];
121
        $query = new SimpleRequest('query', $params);
122
        $result = [];
123
        $res = $api->getRequest($query);
124
        if (isset($res['batchcomplete']) && isset($res['query']['users'][0]['groups'])) {
125
            $result = $res['query']['users'][0]['groups'];
126
        }
127
128
        // Cache and return.
129
        $this->stopwatch->stop($cacheKey);
130
        return $this->setCache($cacheKey, $result);
131
    }
132
133
    /**
134
     * Get a user's global group membership (starting at XTools' default project if none is
135
     * provided). This requires the CentralAuth extension to be installed.
136
     * @link https://www.mediawiki.org/wiki/Extension:CentralAuth
137
     * @param string $username The username.
138
     * @param Project $project The project to query.
139
     * @return string[]
140
     */
141
    public function getGlobalGroups($username, Project $project = null)
142
    {
143
        // Get the default project if not provided.
144
        if (!$project instanceof Project) {
145
            $project = ProjectRepository::getDefaultProject($this->container);
146
        }
147
148
        // Create the API query.
149
        $api = $this->getMediawikiApi($project);
150
        $params = [
151
            'meta' => 'globaluserinfo',
152
            'guiuser' => $username,
153
            'guiprop' => 'groups'
154
        ];
155
        $query = new SimpleRequest('query', $params);
156
157
        // Get the result.
158
        $res = $api->getRequest($query);
159
        $result = [];
160
        if (isset($res['batchcomplete']) && isset($res['query']['globaluserinfo']['groups'])) {
161
            $result = $res['query']['globaluserinfo']['groups'];
162
        }
163
        return $result;
164
    }
165
166
    /**
167
     * Search the ipblocks table to see if the user is currently blocked
168
     * and return the expiry if they are.
169
     * @param $databaseName The database to query.
170
     * @param $username The username of the user to search for.
0 ignored issues
show
Bug introduced by
The type Xtools\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
171
     * @return bool|string Expiry of active block or false
172
     */
173
    public function getBlockExpiry($databaseName, $username)
174
    {
175
        $ipblocksTable = $this->getTableName($databaseName, 'ipblocks', 'ipindex');
176
        $sql = "SELECT ipb_expiry
177
                FROM $ipblocksTable
178
                WHERE ipb_address = :username
179
                LIMIT 1";
180
        $resultQuery = $this->executeProjectsQuery($sql, ['username' => $username]);
181
        return $resultQuery->fetchColumn();
182
    }
183
184
    /**
185
     * Get edit count within given timeframe and namespace.
186
     * @param Project $project
187
     * @param User $user
188
     * @param int|string $namespace Namespace ID or 'all' for all namespaces
189
     * @param string $start Start date in a format accepted by strtotime()
190
     * @param string $end End date in a format accepted by strtotime()
191
     */
192
    public function countEdits(Project $project, User $user, $namespace = 'all', $start = '', $end = '')
193
    {
194
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_editcount');
195
        if ($this->cache->hasItem($cacheKey)) {
196
            return $this->cache->getItem($cacheKey)->get();
197
        }
198
199
        list($condBegin, $condEnd) = $this->getRevTimestampConditions($start, $end);
200
        list($pageJoin, $condNamespace) = $this->getPageAndNamespaceSql($project, $namespace);
201
        $revisionTable = $project->getTableName('revision');
202
203
        $sql = "SELECT COUNT(rev_id)
204
                FROM $revisionTable
205
                $pageJoin
206
                WHERE rev_user_text = :username
207
                $condNamespace
208
                $condBegin
209
                $condEnd";
210
211
        $resultQuery = $this->executeQuery($sql, $user, $namespace, $start, $end);
212
        $result = $resultQuery->fetchColumn();
213
214
        // Cache and return.
215
        return $this->setCache($cacheKey, $result);
216
    }
217
218
    /**
219
     * Get information about the currently-logged in user.
220
     * @return array
221
     */
222
    public function getXtoolsUserInfo()
223
    {
224
        /** @var Session $session */
225
        $session = $this->container->get('session');
226
        return $session->get('logged_in_user');
227
    }
228
229
    /**
230
     * Maximum number of edits to process, based on configuration.
231
     * @return int
232
     */
233
    public function maxEdits()
234
    {
235
        return $this->container->getParameter('app.max_user_edits');
236
    }
237
238
    /**
239
     * Get SQL clauses for joining on `page` and restricting to a namespace.
240
     * @param  Project $project
241
     * @param  int|string $namespace Namespace ID or 'all' for all namespaces.
242
     * @return array [page join clause, page namespace clause]
243
     */
244
    protected function getPageAndNamespaceSql(Project $project, $namespace)
245
    {
246
        if ($namespace === 'all') {
247
            return [null, null];
248
        }
249
250
        $pageTable = $project->getTableName('page');
251
        $pageJoin = $namespace !== 'all' ? "LEFT JOIN $pageTable ON rev_page = page_id" : null;
252
        $condNamespace = 'AND page_namespace = :namespace';
253
254
        return [$pageJoin, $condNamespace];
255
    }
256
257
    /**
258
     * Get SQL clauses for rev_timestamp, based on whether values for
259
     * the given start and end parameters exist.
260
     * @param  string $start
261
     * @param  string $end
262
     * @param string $tableAlias Alias of table FOLLOWED BY DOT.
263
     * @todo FIXME: merge with Repository::getDateConditions
264
     * @return string[] Clauses for start and end timestamps.
265
     */
266
    protected function getRevTimestampConditions($start, $end, $tableAlias = '')
267
    {
268
        $condBegin = '';
269
        $condEnd = '';
270
271
        if (!empty($start)) {
272
            $condBegin = "AND {$tableAlias}rev_timestamp >= :start ";
273
        }
274
        if (!empty($end)) {
275
            $condEnd = "AND {$tableAlias}rev_timestamp <= :end ";
276
        }
277
278
        return [$condBegin, $condEnd];
279
    }
280
281
    /**
282
     * Prepare the given SQL, bind the given parameters, and execute the Doctrine Statement.
283
     * @param  string $sql
284
     * @param  User   $user
285
     * @param  string $namespace
286
     * @param  string $start
287
     * @param  string $end
288
     * @return \Doctrine\DBAL\Statement
289
     */
290
    protected function executeQuery($sql, User $user, $namespace = 'all', $start = '', $end = '')
291
    {
292
        $params = [
293
            'username' => $user->getUsername(),
294
        ];
295
296
        if (!empty($start)) {
297
            $params['start'] = date('Ymd000000', strtotime($start));
298
        }
299
        if (!empty($end)) {
300
            $params['end'] = date('Ymd235959', strtotime($end));
301
        }
302
        if ($namespace !== 'all') {
303
            $params['namespace'] = $namespace;
304
        }
305
306
        return $this->executeProjectsQuery($sql, $params);
307
    }
308
309
    /**
310
     * Get a user's local user rights on the given Project.
311
     * @param Project $project
312
     * @param User $user
313
     * @return string[]
314
     */
315
    public function getUserRights(Project $project, User $user)
316
    {
317
        $userGroupsTable = $project->getTableName('user_groups');
318
        $userTable = $project->getTableName('user');
319
320
        $sql = "SELECT ug_group
321
                FROM $userGroupsTable
322
                JOIN $userTable ON user_id = ug_user
323
                WHERE user_name = :username";
324
325
        $ret = $this->executeProjectsQuery($sql, [
326
            'username' => $user->getUsername(),
327
        ])->fetchAll(\PDO::FETCH_COLUMN);
328
        return $ret;
329
    }
330
}
331