Passed
Push — master ( 249321...cafa97 )
by MusikAnimal
05:17
created

UserRepository::executeQuery()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 8
nop 5
dl 0
loc 17
rs 9.2
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
97
        $editCount = $resultQuery->fetchColumn();
98
        return $editCount;
99
    }
100
101
    /**
102
     * Search the ipblocks table to see if the user is currently blocked
103
     * and return the expiry if they are.
104
     * @param $databaseName The database to query.
105
     * @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...
106
     * @return bool|string Expiry of active block or false
107
     */
108
    public function getBlockExpiry($databaseName, $username)
109
    {
110
        $ipblocksTable = $this->getTableName($databaseName, 'ipblocks', 'ipindex');
111
        $sql = "SELECT ipb_expiry
112
                FROM $ipblocksTable
113
                WHERE ipb_address = :username
114
                LIMIT 1";
115
        $resultQuery = $this->executeProjectsQuery($sql, ['username' => $username]);
116
        return $resultQuery->fetchColumn();
117
    }
118
119
    /**
120
     * Get edit count within given timeframe and namespace.
121
     * @param Project $project
122
     * @param User $user
123
     * @param int|string $namespace Namespace ID or 'all' for all namespaces
124
     * @param string $start Start date in a format accepted by strtotime()
125
     * @param string $end End date in a format accepted by strtotime()
126
     */
127
    public function countEdits(Project $project, User $user, $namespace = 'all', $start = '', $end = '')
128
    {
129
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_editcount');
130
        if ($this->cache->hasItem($cacheKey)) {
131
            return $this->cache->getItem($cacheKey)->get();
132
        }
133
134
        list($condBegin, $condEnd) = $this->getRevTimestampConditions($start, $end);
135
        list($pageJoin, $condNamespace) = $this->getPageAndNamespaceSql($project, $namespace);
136
        $revisionTable = $project->getTableName('revision');
137
138
        $sql = "SELECT COUNT(rev_id)
139
                FROM $revisionTable
140
                $pageJoin
141
                WHERE rev_user_text = :username
142
                $condNamespace
143
                $condBegin
144
                $condEnd";
145
146
        $resultQuery = $this->executeQuery($sql, $user, $namespace, $start, $end);
147
        $result = $resultQuery->fetchColumn();
148
149
        // Cache and return.
150
        return $this->setCache($cacheKey, $result);
151
    }
152
153
    /**
154
     * Get information about the currently-logged in user.
155
     * @return array
156
     */
157
    public function getXtoolsUserInfo()
158
    {
159
        /** @var Session $session */
160
        $session = $this->container->get('session');
161
        return $session->get('logged_in_user');
162
    }
163
164
    /**
165
     * Maximum number of edits to process, based on configuration.
166
     * @return int
167
     */
168
    public function maxEdits()
169
    {
170
        return $this->container->getParameter('app.max_user_edits');
171
    }
172
173
    /**
174
     * Get SQL clauses for joining on `page` and restricting to a namespace.
175
     * @param  Project $project
176
     * @param  int|string $namespace Namespace ID or 'all' for all namespaces.
177
     * @return array [page join clause, page namespace clause]
178
     */
179
    protected function getPageAndNamespaceSql(Project $project, $namespace)
180
    {
181
        if ($namespace === 'all') {
182
            return [null, null];
183
        }
184
185
        $pageTable = $project->getTableName('page');
186
        $pageJoin = $namespace !== 'all' ? "LEFT JOIN $pageTable ON rev_page = page_id" : null;
187
        $condNamespace = 'AND page_namespace = :namespace';
188
189
        return [$pageJoin, $condNamespace];
190
    }
191
192
    /**
193
     * Get SQL clauses for rev_timestamp, based on whether values for
194
     * the given start and end parameters exist.
195
     * @param  string $start
196
     * @param  string $end
197
     * @param string $tableAlias Alias of table FOLLOWED BY DOT.
198
     * @todo FIXME: merge with Repository::getDateConditions
199
     * @return string[] Clauses for start and end timestamps.
200
     */
201
    protected function getRevTimestampConditions($start, $end, $tableAlias = '')
202
    {
203
        $condBegin = '';
204
        $condEnd = '';
205
206
        if (!empty($start)) {
207
            $condBegin = "AND {$tableAlias}rev_timestamp >= :start ";
208
        }
209
        if (!empty($end)) {
210
            $condEnd = "AND {$tableAlias}rev_timestamp <= :end ";
211
        }
212
213
        return [$condBegin, $condEnd];
214
    }
215
216
    /**
217
     * Prepare the given SQL, bind the given parameters, and execute the Doctrine Statement.
218
     * @param  string $sql
219
     * @param  User   $user
220
     * @param  string $namespace
221
     * @param  string $start
222
     * @param  string $end
223
     * @return \Doctrine\DBAL\Statement
224
     */
225
    protected function executeQuery($sql, User $user, $namespace = 'all', $start = '', $end = '')
226
    {
227
        $params = [
228
            'username' => $user->getUsername(),
229
        ];
230
231
        if (!empty($start)) {
232
            $params['start'] = date('Ymd000000', strtotime($start));
233
        }
234
        if (!empty($end)) {
235
            $params['end'] = date('Ymd235959', strtotime($end));
236
        }
237
        if ($namespace !== 'all') {
238
            $params['namespace'] = $namespace;
239
        }
240
241
        return $this->executeProjectsQuery($sql, $params);
242
    }
243
244
    /**
245
     * Get a user's local user rights on the given Project.
246
     * @param Project $project
247
     * @param User $user
248
     * @return string[]
249
     */
250
    public function getUserRights(Project $project, User $user)
251
    {
252
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_rights');
253
        if ($this->cache->hasItem($cacheKey)) {
254
            return $this->cache->getItem($cacheKey)->get();
255
        }
256
257
        $userGroupsTable = $project->getTableName('user_groups');
258
        $userTable = $project->getTableName('user');
259
260
        $sql = "SELECT ug_group
261
                FROM $userGroupsTable
262
                JOIN $userTable ON user_id = ug_user
263
                WHERE user_name = :username";
264
265
        $ret = $this->executeProjectsQuery($sql, [
266
            'username' => $user->getUsername(),
267
        ])->fetchAll(\PDO::FETCH_COLUMN);
268
269
        // Cache and return.
270
        return $this->setCache($cacheKey, $ret);
271
    }
272
273
    /**
274
     * Get a user's global group membership (starting at XTools' default project if none is
275
     * provided). This requires the CentralAuth extension to be installed.
276
     * @link https://www.mediawiki.org/wiki/Extension:CentralAuth
277
     * @param string $username The username.
278
     * @param Project $project The project to query.
279
     * @return string[]
280
     */
281
    public function getGlobalUserRights($username, Project $project = null)
282
    {
283
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_global_groups');
284
        if ($this->cache->hasItem($cacheKey)) {
285
            return $this->cache->getItem($cacheKey)->get();
286
        }
287
288
        // Get the default project if not provided.
289
        if (!$project instanceof Project) {
290
            $project = ProjectRepository::getDefaultProject($this->container);
291
        }
292
293
        // Create the API query.
294
        $api = $this->getMediawikiApi($project);
295
        $params = [
296
            'meta' => 'globaluserinfo',
297
            'guiuser' => $username,
298
            'guiprop' => 'groups'
299
        ];
300
        $query = new SimpleRequest('query', $params);
301
302
        // Get the result.
303
        $res = $api->getRequest($query);
304
        $result = [];
305
        if (isset($res['batchcomplete']) && isset($res['query']['globaluserinfo']['groups'])) {
306
            $result = $res['query']['globaluserinfo']['groups'];
307
        }
308
309
        // Cache and return.
310
        return $this->setCache($cacheKey, $result);
311
    }
312
}
313