Passed
Branch master (0917e1)
by MusikAnimal
11:12
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, false, 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, $offset)."
129
                ) a ".
130
                "ORDER BY rev_timestamp DESC
131
                ".(!empty($limit) ? "LIMIT $limit" : '');
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 int|false $offset Unix timestamp, used for pagination.
178
     * @param bool $count Omit unneeded columns from the SELECT clause.
179
     * @return string Raw SQL.
180
     */
181
    private function getPagesCreatedInnerSql(
182
        Project $project,
183
        array $conditions,
184
        string $deleted,
185
        $start,
186
        $end,
187
        $offset = false,
188
        bool $count = false
189
    ): string {
190
        $pageTable = $project->getTableName('page');
191
        $revisionTable = $project->getTableName('revision');
192
        $archiveTable = $project->getTableName('archive');
193
        $logTable = $project->getTableName('logging', 'logindex');
194
195
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
196
        $revSelects = "DISTINCT page_namespace AS `namespace`, 'rev' AS `type`, page_title, "
197
            . "page_is_redirect, rev_len AS length";
198
        if (!$count) {
199
            $revSelects .= ", page_len, rev_timestamp, rev_len, rev_id, NULL AS `recreated` ";
200
        }
201
202
        $revDateConditions = $this->getDateConditions($start, $end, $offset);
203
        $arDateConditions = $this->getDateConditions($start, $end, $offset, '', 'ar_timestamp');
204
205
        $revisionsSelect = "
206
            SELECT $revSelects ".$conditions['paSelects']."
207
            FROM $pageTable
208
            JOIN $revisionTable ON page_id = rev_page ".
209
            $conditions['paJoin']."
210
            WHERE ".$conditions['whereRev']."
211
                AND rev_parent_id = '0'".
212
                $conditions['namespaceRev'].
213
                $conditions['redirects'].
214
                $revDateConditions.
215
            $conditions['revPageGroupBy'];
216
217
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
218
        $arSelects = "ar_namespace AS `namespace`, 'arc' AS `type`, ar_title AS page_title, "
219
            . "'0' AS page_is_redirect, ar_len AS length";
220
        if (false === $count) {
221
            $arSelects .= ", NULL AS page_len, MIN(ar_timestamp) AS rev_timestamp, ".
222
                "ar_len AS rev_len, ar_rev_id AS rev_id, EXISTS(
223
                    SELECT 1 FROM $pageTable
224
                    WHERE page_namespace = ar_namespace
225
                    AND page_title = ar_title
226
                ) AS `recreated`";
227
        }
228
229
        $archiveSelect = "
230
            SELECT $arSelects ".$conditions['paSelectsArchive']."
231
            FROM $archiveTable
232
            LEFT JOIN $logTable ON log_namespace = ar_namespace AND log_title = ar_title
233
                AND log_actor = ar_actor AND (log_action = 'move' OR log_action = 'move_redir')
234
                AND log_type = 'move'
235
            WHERE ".$conditions['whereArc']."
236
                AND ar_parent_id = '0' ".
237
                $conditions['namespaceArc']."
238
                AND log_action IS NULL
239
                $arDateConditions
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 int|false $start Start date as Unix timestamp.
258
     * @param int|false $end End date as Unix timestamp.
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
        $start = false,
267
        $end = false
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
        $revDateConditions = $this->getDateConditions($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
                    $revDateConditions."
294
                    GROUP BY page_id
295
                ) a
296
                GROUP BY pa_class";
297
298
        $resultQuery = $this->executeQuery($sql, $project, $user, $namespace);
299
300
        $assessments = [];
301
        while ($result = $resultQuery->fetch()) {
302
            $class = '' == $result['class'] ? '' : $result['class'];
303
            $assessments[$class] = $result['count'];
304
        }
305
306
        // Cache and return.
307
        return $this->setCache($cacheKey, $assessments);
308
    }
309
}
310