Test Failed
Pull Request — master (#378)
by MusikAnimal
20:23 queued 12:27
created

PagesRepository::getPagesCreated()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 50
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 26
nc 9
nop 9
dl 0
loc 50
rs 9.1928
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * This file contains only the PagesRepository class.
4
 */
5
6
declare(strict_types = 1);
7
8
namespace AppBundle\Repository;
9
10
use AppBundle\Model\Project;
11
use AppBundle\Model\User;
12
13
/**
14
 * An PagesRepository is responsible for retrieving information from the
15
 * databases for the Pages Created tool. It does not do any post-processing
16
 * of that data.
17
 * @codeCoverageIgnore
18
 */
19
class PagesRepository extends UserRepository
20
{
21
    /**
22
     * Count the number of pages created by a user.
23
     * @param Project $project
24
     * @param User $user
25
     * @param string|int $namespace Namespace ID or 'all'.
26
     * @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both.
27
     * @param string $deleted One of 'live', 'deleted' or blank for both.
28
     * @param int|false $start Start date as Unix timestamp.
29
     * @param int|false $end End date as Unix timestamp.
30
     * @return string[] Result of query, see below. Includes live and deleted pages.
31
     */
32
    public function countPagesCreated(
33
        Project $project,
34
        User $user,
35
        $namespace,
36
        string $redirects,
37
        string $deleted,
38
        $start = false,
39
        $end = false
40
    ): array {
41
        $cacheKey = $this->getCacheKey(func_get_args(), 'num_user_pages_created');
42
        if ($this->cache->hasItem($cacheKey)) {
43
            return $this->cache->getItem($cacheKey)->get();
44
        }
45
46
        $conditions = [
47
            'paSelects' => '',
48
            'paSelectsArchive' => '',
49
            'paJoin' => '',
50
            'revPageGroupBy' => '',
51
        ];
52
        $conditions = array_merge(
53
            $conditions,
54
            $this->getNamespaceRedirectAndDeletedPagesConditions($namespace, $redirects),
55
            $this->getUserConditions('' !== $start.$end)
56
        );
57
58
        $sql = "SELECT namespace,
59
                    COUNT(page_title) AS count,
60
                    SUM(IF(type = 'arc', 1, 0)) AS deleted,
61
                    SUM(page_is_redirect) AS redirects,
62
                    SUM(length) AS total_length
63
                FROM (" .
64
                    $this->getPagesCreatedInnerSql($project, $conditions, $deleted, $start, $end, true)."
65
                ) a ".
66
                "GROUP BY namespace";
67
68
        $result = $this->executeQuery($sql, $project, $user, $namespace)->fetchAll();
69
70
        // Cache and return.
71
        return $this->setCache($cacheKey, $result);
72
    }
73
74
    /**
75
     * Get pages created by a user.
76
     * @param Project $project
77
     * @param User $user
78
     * @param string|int $namespace Namespace ID or 'all'.
79
     * @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both.
80
     * @param string $deleted One of 'live', 'deleted' or blank for both.
81
     * @param int|false $start Start date as Unix timestamp.
82
     * @param int|false $end End date as Unix timestamp.
83
     * @param int|null $limit Number of results to return, or blank to return all.
84
     * @param false|int $offset Unix timestamp. Used for pagination.
85
     * @return string[] Result of query, see below. Includes live and deleted pages.
86
     */
87
    public function getPagesCreated(
88
        Project $project,
89
        User $user,
90
        $namespace,
91
        string $redirects,
92
        string $deleted,
93
        $start = false,
94
        $end = false,
95
        $limit = 1000,
96
        $offset = false
97
    ): array {
98
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_pages_created');
99
        if ($this->cache->hasItem($cacheKey)) {
100
            return $this->cache->getItem($cacheKey)->get();
101
        }
102
103
        $conditions = [
104
            'paSelects' => '',
105
            'paSelectsArchive' => '',
106
            'paJoin' => '',
107
            'revPageGroupBy' => '',
108
        ];
109
110
        $conditions = array_merge(
111
            $conditions,
112
            $this->getNamespaceRedirectAndDeletedPagesConditions($namespace, $redirects),
113
            $this->getUserConditions('' !== $start.$end)
114
        );
115
116
        $pageAssessmentsTable = $project->getTableName('page_assessments');
117
118
        $hasPageAssessments = $this->isLabs() && $project->hasPageAssessments();
119
        if ($hasPageAssessments) {
120
            $conditions['paSelects'] = ', pa_class, pa_importance, pa_page_revision';
121
            $conditions['paSelectsArchive'] = ', NULL AS pa_class, NULL AS pa_page_id, '.
122
                'NULL AS pa_page_revision';
123
            $conditions['paJoin'] = "LEFT JOIN $pageAssessmentsTable ON rev_page = pa_page_id";
124
            $conditions['revPageGroupBy'] = 'GROUP BY rev_page';
125
        }
126
127
        $sql = "SELECT * FROM (".
128
                    $this->getPagesCreatedInnerSql($project, $conditions, $deleted, $start, $end)."
129
                ) a ".
130
                "ORDER BY rev_timestamp DESC
131
                ".(!empty($limit) ? "LIMIT $limit OFFSET $offset" : '');
132
133
        $result = $this->executeQuery($sql, $project, $user, $namespace)->fetchAll();
134
135
        // Cache and return.
136
        return $this->setCache($cacheKey, $result);
137
    }
138
139
    /**
140
     * Get SQL fragments for the namespace and redirects,
141
     * to be used in self::getPagesCreatedInnerSql().
142
     * @param string|int $namespace Namespace ID or 'all'.
143
     * @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both.
144
     * @return string[] With keys 'namespaceRev', 'namespaceArc' and 'redirects'
145
     */
146
    private function getNamespaceRedirectAndDeletedPagesConditions($namespace, string $redirects): array
147
    {
148
        $conditions = [
149
            'namespaceArc' => '',
150
            'namespaceRev' => '',
151
            'redirects' => '',
152
        ];
153
154
        if ('all' !== $namespace) {
155
            $conditions['namespaceRev'] = " AND page_namespace = '".intval($namespace)."' ";
156
            $conditions['namespaceArc'] = " AND ar_namespace = '".intval($namespace)."' ";
157
        }
158
159
        if ('onlyredirects' == $redirects) {
160
            $conditions['redirects'] = " AND page_is_redirect = '1' ";
161
        } elseif ('noredirects' == $redirects) {
162
            $conditions['redirects'] = " AND page_is_redirect = '0' ";
163
        }
164
165
        return $conditions;
166
    }
167
168
    /**
169
     * Inner SQL for getting or counting pages created by the user.
170
     * @param Project $project
171
     * @param string[] $conditions Conditions for the SQL, must include 'paSelects',
172
     *     'paSelectsArchive', 'paJoin', 'whereRev', 'whereArc', 'namespaceRev', 'namespaceArc',
173
     *     'redirects' and 'revPageGroupBy'.
174
     * @param string $deleted One of 'live', 'deleted' or blank for both.
175
     * @param int|false $start Start date as Unix timestamp.
176
     * @param int|false $end End date as Unix timestamp.
177
     * @param bool $count Omit unneeded columns from the SELECT clause.
178
     * @return string Raw SQL.
179
     */
180
    private function getPagesCreatedInnerSql(
181
        Project $project,
182
        array $conditions,
183
        string $deleted,
184
        $start,
185
        $end,
186
        bool $count = false
187
    ): string {
188
        $pageTable = $project->getTableName('page');
189
        $revisionTable = $project->getTableName('revision');
190
        $archiveTable = $project->getTableName('archive');
191
        $logTable = $project->getTableName('logging', 'logindex');
192
193
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
194
        $revSelects = "DISTINCT page_namespace AS `namespace`, 'rev' AS `type`, page_title, "
195
            . "page_is_redirect, rev_len AS length";
196
        if (false === $count) {
197
            $revSelects .= ", page_len, rev_timestamp, rev_len, rev_id, NULL AS `recreated` ";
198
        }
199
200
        $revDateConditions = $this->getDateConditions($start, $end);
201
        $arDateConditions = $this->getDateConditions($start, $end, false, '', 'ar_timestamp');
202
203
        $revisionsSelect = "
204
            SELECT $revSelects ".$conditions['paSelects']."
205
            FROM $pageTable
206
            JOIN $revisionTable ON page_id = rev_page ".
207
            $conditions['paJoin']."
208
            WHERE ".$conditions['whereRev']."
209
                AND rev_parent_id = '0'".
210
                $conditions['namespaceRev'].
211
                $conditions['redirects'].
212
                $revDateConditions.
213
            $conditions['revPageGroupBy'];
214
215
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
216
        $arSelects = "ar_namespace AS `namespace`, 'arc' AS `type`, ar_title AS page_title, "
217
            . "'0' AS page_is_redirect, ar_len AS length";
218
        if (false === $count) {
219
            $arSelects .= ", NULL AS page_len, MIN(ar_timestamp) AS rev_timestamp, ".
220
                "ar_len AS rev_len, ar_rev_id AS rev_id, EXISTS(
221
                    SELECT 1 FROM $pageTable
222
                    WHERE page_namespace = ar_namespace
223
                    AND page_title = ar_title
224
                ) AS `recreated`";
225
        }
226
227
        $archiveSelect = "
228
            SELECT $arSelects ".$conditions['paSelectsArchive']."
229
            FROM $archiveTable
230
            LEFT JOIN $logTable ON log_namespace = ar_namespace AND log_title = ar_title
231
                AND log_actor = ar_actor AND (log_action = 'move' OR log_action = 'move_redir')
232
                AND log_type = 'move'
233
            WHERE ".$conditions['whereArc']."
234
                AND ar_parent_id = '0' ".
235
                $conditions['namespaceArc']."
236
                AND log_action IS NULL
237
                $arDateConditions
238
            GROUP BY ar_namespace, ar_title";
239
240
        if ('live' == $deleted) {
241
            return $revisionsSelect;
242
        } elseif ('deleted' == $deleted) {
243
            return $archiveSelect;
244
        }
245
246
        return "($revisionsSelect) UNION ($archiveSelect)";
247
    }
248
249
    /**
250
     * Get the number of pages the user created by assessment.
251
     * @param Project $project
252
     * @param User $user
253
     * @param int|string $namespace
254
     * @param string $redirects
255
     * @param int|false $start Start date as Unix timestamp.
256
     * @param int|false $end End date as Unix timestamp.
257
     * @return array Keys are the assessment class, values are the counts.
258
     */
259
    public function getAssessmentCounts(
260
        Project $project,
261
        User $user,
262
        $namespace,
263
        string $redirects,
264
        $start = false,
265
        $end = false
266
    ): array {
267
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_pages_created_assessments');
268
        if ($this->cache->hasItem($cacheKey)) {
269
            return $this->cache->getItem($cacheKey)->get();
270
        }
271
272
        $pageTable = $project->getTableName('page');
273
        $revisionTable = $project->getTableName('revision');
274
        $pageAssessmentsTable = $project->getTableName('page_assessments');
275
276
        $conditions = array_merge(
277
            $this->getNamespaceRedirectAndDeletedPagesConditions($namespace, $redirects),
278
            $this->getUserConditions('' !== $start.$end)
279
        );
280
        $revDateConditions = $this->getDateConditions($start, $end);
281
282
        $sql = "SELECT pa_class AS `class`, COUNT(pa_class) AS `count` FROM (
283
                    SELECT DISTINCT page_id, IFNULL(pa_class, '') AS pa_class
284
                    FROM $pageTable
285
                    JOIN $revisionTable ON page_id = rev_page
286
                    LEFT JOIN $pageAssessmentsTable ON rev_page = pa_page_id
287
                    WHERE ".$conditions['whereRev']."
288
                    AND rev_parent_id = '0'".
289
                    $conditions['namespaceRev'].
290
                    $conditions['redirects'].
291
                    $revDateConditions."
292
                    GROUP BY page_id
293
                ) a
294
                GROUP BY pa_class";
295
296
        $resultQuery = $this->executeQuery($sql, $project, $user, $namespace);
297
298
        $assessments = [];
299
        while ($result = $resultQuery->fetch()) {
300
            $class = '' == $result['class'] ? '' : $result['class'];
301
            $assessments[$class] = $result['count'];
302
        }
303
304
        // Cache and return.
305
        return $this->setCache($cacheKey, $assessments);
306
    }
307
}
308