Test Failed
Push — master ( 860dbc...7f6d09 )
by MusikAnimal
07:34
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 string $start Start date in a format accepted by strtotime()
29
     * @param string $end End date in a format accepted by strtotime()
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
        string $start = '',
39
        string $end = ''
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(CASE WHEN type = 'arc' THEN 1 ELSE 0 END) 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, $start, $end)->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 string $start Start date in a format accepted by strtotime()
82
     * @param string $end End date in a format accepted by strtotime()
83
     * @param int|null $limit Number of results to return, or blank to return all.
84
     * @param int $offset Number of results past the initial dataset. 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
        string $start = '',
94
        string $end = '',
95
        $limit = 1000,
96
        $offset = 0
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, $start, $end)->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 string $start Start date in a format accepted by strtotime()
176
     * @param string $end End date in a format accepted by strtotime()
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
        string $start = '',
185
        string $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
        [$revCondBegin, $revCondEnd] = $this->getRevTimestampConditions($start, $end);
201
        [$arCondBegin, $arCondEnd] = $this->getRevTimestampConditions($start, $end, '', true);
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
                $revCondBegin.
213
                $revCondEnd.
214
            $conditions['revPageGroupBy'];
215
216
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
217
        $arSelects = "ar_namespace AS `namespace`, 'arc' AS `type`, ar_title AS page_title, "
218
            . "'0' AS page_is_redirect, ar_len AS length";
219
        if (false === $count) {
220
            $arSelects .= ", NULL AS page_len, MIN(ar_timestamp) AS rev_timestamp, ".
221
                "ar_len AS rev_len, ar_rev_id AS rev_id, EXISTS(
222
                    SELECT 1 FROM $pageTable
223
                    WHERE page_namespace = ar_namespace
224
                    AND page_title = ar_title
225
                ) AS `recreated`";
226
        }
227
228
        $archiveSelect = "
229
            SELECT $arSelects ".$conditions['paSelectsArchive']."
230
            FROM $archiveTable
231
            LEFT JOIN $logTable ON log_namespace = ar_namespace AND log_title = ar_title
232
                AND log_actor = ar_actor AND (log_action = 'move' OR log_action = 'move_redir')
233
                AND log_type = 'move'
234
            WHERE ".$conditions['whereArc']."
235
                AND ar_parent_id = '0' ".
236
                $conditions['namespaceArc']."
237
                AND log_action IS NULL
238
                $arCondBegin
239
                $arCondEnd
240
            GROUP BY ar_namespace, ar_title";
241
242
        if ('live' == $deleted) {
243
            return $revisionsSelect;
244
        } elseif ('deleted' == $deleted) {
245
            return $archiveSelect;
246
        }
247
248
        return "($revisionsSelect) UNION ($archiveSelect)";
249
    }
250
251
    /**
252
     * Get the number of pages the user created by assessment.
253
     * @param Project $project
254
     * @param User $user
255
     * @param int|string $namespace
256
     * @param string $redirects
257
     * @param string $start Start date in a format accepted by strtotime()
258
     * @param string $end End date in a format accepted by strtotime()
259
     * @return array Keys are the assessment class, values are the counts.
260
     */
261
    public function getAssessmentCounts(
262
        Project $project,
263
        User $user,
264
        $namespace,
265
        string $redirects,
266
        string $start = '',
267
        string $end = ''
268
    ): array {
269
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_pages_created_assessments');
270
        if ($this->cache->hasItem($cacheKey)) {
271
            return $this->cache->getItem($cacheKey)->get();
272
        }
273
274
        $pageTable = $project->getTableName('page');
275
        $revisionTable = $project->getTableName('revision');
276
        $pageAssessmentsTable = $project->getTableName('page_assessments');
277
278
        $conditions = array_merge(
279
            $this->getNamespaceRedirectAndDeletedPagesConditions($namespace, $redirects),
280
            $this->getUserConditions('' !== $start.$end)
281
        );
282
        [$revCondBegin, $revCondEnd] = $this->getRevTimestampConditions($start, $end);
283
284
        $sql = "SELECT pa_class AS `class`, COUNT(pa_class) AS `count` FROM (
285
                    SELECT DISTINCT page_id, IFNULL(pa_class, '') AS pa_class
286
                    FROM $pageTable
287
                    JOIN $revisionTable ON page_id = rev_page
288
                    LEFT JOIN $pageAssessmentsTable ON rev_page = pa_page_id
289
                    WHERE ".$conditions['whereRev']."
290
                    AND rev_parent_id = '0'".
291
                    $conditions['namespaceRev'].
292
                    $conditions['redirects'].
293
                    $revCondBegin.
294
                    $revCondEnd."
295
                    GROUP BY page_id
296
                ) a
297
                GROUP BY pa_class";
298
299
        $resultQuery = $this->executeQuery($sql, $project, $user, $namespace, $start, $end);
300
301
        $assessments = [];
302
        while ($result = $resultQuery->fetch()) {
303
            $class = '' == $result['class'] ? '' : $result['class'];
304
            $assessments[$class] = $result['count'];
305
        }
306
307
        // Cache and return.
308
        return $this->setCache($cacheKey, $assessments);
309
    }
310
}
311