Passed
Push — master ( e61fe1...3dcafc )
by MusikAnimal
07:03
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($project, $user, '' !== $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
                FROM (".
63
                    $this->getPagesCreatedInnerSql($project, $conditions, $deleted, $start, $end, true)."
64
                ) a ".
65
                "GROUP BY namespace";
66
67
        $result = $this->executeQuery($sql, $project, $user, $namespace, $start, $end)->fetchAll();
68
69
        // Cache and return.
70
        return $this->setCache($cacheKey, $result);
71
    }
72
73
    /**
74
     * Get pages created by a user.
75
     * @param Project $project
76
     * @param User $user
77
     * @param string|int $namespace Namespace ID or 'all'.
78
     * @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both.
79
     * @param string $deleted One of 'live', 'deleted' or blank for both.
80
     * @param string $start Start date in a format accepted by strtotime()
81
     * @param string $end End date in a format accepted by strtotime()
82
     * @param int|null $limit Number of results to return, or blank to return all.
83
     * @param int $offset Number of results past the initial dataset. Used for pagination.
84
     * @return string[] Result of query, see below. Includes live and deleted pages.
85
     */
86
    public function getPagesCreated(
87
        Project $project,
88
        User $user,
89
        $namespace,
90
        string $redirects,
91
        string $deleted,
92
        string $start = '',
93
        string $end = '',
94
        $limit = 1000,
95
        $offset = 0
96
    ): array {
97
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_pages_created');
98
        if ($this->cache->hasItem($cacheKey)) {
99
            return $this->cache->getItem($cacheKey)->get();
100
        }
101
102
        $conditions = [
103
            'paSelects' => '',
104
            'paSelectsArchive' => '',
105
            'paJoin' => '',
106
            'revPageGroupBy' => '',
107
        ];
108
109
        $conditions = array_merge(
110
            $conditions,
111
            $this->getNamespaceRedirectAndDeletedPagesConditions($namespace, $redirects),
112
            $this->getUserConditions($project, $user, '' !== $start.$end)
113
        );
114
115
        $pageAssessmentsTable = $project->getTableName('page_assessments');
116
117
        $hasPageAssessments = $this->isLabs() && $project->hasPageAssessments();
118
        if ($hasPageAssessments) {
119
            $conditions['paSelects'] = ', pa_class, pa_importance, pa_page_revision';
120
            $conditions['paSelectsArchive'] = ', NULL AS pa_class, NULL AS pa_page_id, '.
121
                'NULL AS pa_page_revision';
122
            $conditions['paJoin'] = "LEFT JOIN $pageAssessmentsTable ON rev_page = pa_page_id";
123
            $conditions['revPageGroupBy'] = 'GROUP BY rev_page';
124
        }
125
126
        $sql = "SELECT * FROM (".
127
                    $this->getPagesCreatedInnerSql($project, $conditions, $deleted, $start, $end)."
128
                ) a ".
129
                "ORDER BY rev_timestamp DESC
130
                ".(!empty($limit) ? "LIMIT $limit OFFSET $offset" : '');
131
132
        $result = $this->executeQuery($sql, $project, $user, $namespace, $start, $end)->fetchAll();
133
134
        // Cache and return.
135
        return $this->setCache($cacheKey, $result);
136
    }
137
138
    /**
139
     * Get SQL fragments for the namespace and redirects,
140
     * to be used in self::getPagesCreatedInnerSql().
141
     * @param string|int $namespace Namespace ID or 'all'.
142
     * @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both.
143
     * @return string[] With keys 'namespaceRev', 'namespaceArc' and 'redirects'
144
     */
145
    private function getNamespaceRedirectAndDeletedPagesConditions($namespace, string $redirects): array
146
    {
147
        $conditions = [
148
            'namespaceArc' => '',
149
            'namespaceRev' => '',
150
            'redirects' => '',
151
        ];
152
153
        if ('all' !== $namespace) {
154
            $conditions['namespaceRev'] = " AND page_namespace = '".intval($namespace)."' ";
155
            $conditions['namespaceArc'] = " AND ar_namespace = '".intval($namespace)."' ";
156
        }
157
158
        if ('onlyredirects' == $redirects) {
159
            $conditions['redirects'] = " AND page_is_redirect = '1' ";
160
        } elseif ('noredirects' == $redirects) {
161
            $conditions['redirects'] = " AND page_is_redirect = '0' ";
162
        }
163
164
        return $conditions;
165
    }
166
167
    /**
168
     * Inner SQL for getting or counting pages created by the user.
169
     * @param Project $project
170
     * @param string[] $conditions Conditions for the SQL, must include 'paSelects',
171
     *     'paSelectsArchive', 'paJoin', 'whereRev', 'whereArc', 'namespaceRev', 'namespaceArc',
172
     *     'redirects' and 'revPageGroupBy'.
173
     * @param string $deleted One of 'live', 'deleted' or blank for both.
174
     * @param string $start Start date in a format accepted by strtotime()
175
     * @param string $end End date in a format accepted by strtotime()
176
     * @param bool $count Omit unneeded columns from the SELECT clause.
177
     * @return string Raw SQL.
178
     */
179
    private function getPagesCreatedInnerSql(
180
        Project $project,
181
        array $conditions,
182
        string $deleted,
183
        string $start = '',
184
        string $end = '',
185
        bool $count = false
186
    ): string {
187
        $pageTable = $project->getTableName('page');
188
        $revisionTable = $project->getTableName('revision');
189
        $archiveTable = $project->getTableName('archive');
190
        $logTable = $project->getTableName('logging', 'logindex');
191
192
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
193
        $revSelects = "DISTINCT page_namespace AS `namespace`, 'rev' AS `type`, page_title, page_is_redirect";
194
        if (false === $count) {
195
            $revSelects .= ", page_len, rev_timestamp, rev_len, rev_id, NULL AS `recreated` ";
196
        }
197
198
        [$revCondBegin, $revCondEnd] = $this->getRevTimestampConditions($start, $end);
199
        [$arCondBegin, $arCondEnd] = $this->getRevTimestampConditions($start, $end, '', true);
200
201
        $revisionsSelect = "
202
            SELECT $revSelects ".$conditions['paSelects']."
203
            FROM $pageTable
204
            JOIN $revisionTable ON page_id = rev_page ".
205
            $conditions['paJoin']."
206
            WHERE ".$conditions['whereRev']."
207
                AND rev_parent_id = '0'".
208
                $conditions['namespaceRev'].
209
                $conditions['redirects'].
210
                $revCondBegin.
211
                $revCondEnd.
212
            $conditions['revPageGroupBy'];
213
214
        // Only SELECT things that are needed, based on whether or not we're doing a COUNT.
215
        $arSelects = "ar_namespace AS `namespace`, 'arc' AS `type`, ar_title AS page_title, '0' AS page_is_redirect";
216
        if (false === $count) {
217
            $arSelects .= ", NULL AS page_len, MIN(ar_timestamp) AS rev_timestamp, ".
218
                "ar_len AS rev_len, ar_rev_id AS rev_id, EXISTS(
219
                    SELECT 1 FROM $pageTable
220
                    WHERE page_namespace = ar_namespace
221
                    AND page_title = ar_title
222
                ) AS `recreated`";
223
        }
224
225
        $archiveSelect = "
226
            SELECT $arSelects ".$conditions['paSelectsArchive']."
227
            FROM $archiveTable
228
            LEFT JOIN $logTable ON log_namespace = ar_namespace AND log_title = ar_title
229
                AND log_user = ar_user AND (log_action = 'move' OR log_action = 'move_redir')
230
                AND log_type = 'move'
231
            WHERE ".$conditions['whereArc']."
232
                AND ar_parent_id = '0' ".
233
                $conditions['namespaceArc']."
234
                AND log_action IS NULL
235
                $arCondBegin
236
                $arCondEnd
237
            GROUP BY ar_namespace, ar_title";
238
239
        if ('live' == $deleted) {
240
            return $revisionsSelect;
241
        } elseif ('deleted' == $deleted) {
242
            return $archiveSelect;
243
        }
244
245
        return "($revisionsSelect) UNION ($archiveSelect)";
246
    }
247
248
    /**
249
     * Get the number of pages the user created by assessment.
250
     * @param Project $project
251
     * @param User $user
252
     * @param int|string $namespace
253
     * @param string $redirects
254
     * @param string $start Start date in a format accepted by strtotime()
255
     * @param string $end End date in a format accepted by strtotime()
256
     * @return array Keys are the assessment class, values are the counts.
257
     */
258
    public function getAssessmentCounts(
259
        Project $project,
260
        User $user,
261
        $namespace,
262
        string $redirects,
263
        string $start = '',
264
        string $end = ''
265
    ): array {
266
        $cacheKey = $this->getCacheKey(func_get_args(), 'user_pages_created_assessments');
267
        if ($this->cache->hasItem($cacheKey)) {
268
            return $this->cache->getItem($cacheKey)->get();
269
        }
270
271
        $pageTable = $project->getTableName('page');
272
        $revisionTable = $project->getTableName('revision');
273
        $pageAssessmentsTable = $project->getTableName('page_assessments');
274
275
        $conditions = array_merge(
276
            $this->getNamespaceRedirectAndDeletedPagesConditions($namespace, $redirects),
277
            $this->getUserConditions($project, $user, '' !== $start.$end)
278
        );
279
        [$revCondBegin, $revCondEnd] = $this->getRevTimestampConditions($start, $end);
280
281
        $sql = "SELECT pa_class AS `class`, COUNT(pa_class) AS `count` FROM (
282
                    SELECT DISTINCT page_id, IFNULL(pa_class, '') AS pa_class
283
                    FROM $pageTable
284
                    JOIN $revisionTable ON page_id = rev_page
285
                    LEFT JOIN $pageAssessmentsTable ON rev_page = pa_page_id
286
                    WHERE ".$conditions['whereRev']."
287
                    AND rev_parent_id = '0'".
288
                    $conditions['namespaceRev'].
289
                    $conditions['redirects'].
290
                    $revCondBegin.
291
                    $revCondEnd."
292
                    GROUP BY page_id
293
                ) a
294
                GROUP BY pa_class";
295
296
        $resultQuery = $this->executeProjectsQuery($sql);
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