Passed
Push — master ( 250650...eb8721 )
by MusikAnimal
10:40
created

Pages::__construct()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 8
nc 8
nop 8
dl 0
loc 18
rs 9.2222
c 0
b 0
f 0
ccs 9
cts 9
cp 1
crap 6

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 Pages class.
4
 */
5
6
declare(strict_types = 1);
7
8
namespace AppBundle\Model;
9
10
use DateTime;
11
12
/**
13
 * A Pages provides statistics about the pages created by a given User.
14
 */
15
class Pages extends Model
16
{
17
    private const RESULTS_LIMIT_SINGLE_NAMESPACE = 1000;
18
    private const RESULTS_LIMIT_ALL_NAMESPACES = 50;
19
20
    /** @var string One of 'noredirects', 'onlyredirects' or 'all' for both. */
21
    protected $redirects;
22
23
    /** @var string One of 'live', 'deleted' or 'all' for both. */
24
    protected $deleted;
25
26
    /** @var int Pagination offset. */
27
    protected $offset;
28
29
    /** @var mixed[] The list of pages including various statistics, keyed by namespace. */
30
    protected $pages;
31
32
    /** @var mixed[] Number of redirects/pages that were created/deleted, broken down by namespace. */
33
    protected $countsByNamespace;
34
35
    /**
36
     * Pages constructor.
37
     * @param Project $project
38
     * @param User $user
39
     * @param string|int $namespace Namespace ID or 'all'.
40
     * @param string $redirects One of 'noredirects', 'onlyredirects' or 'all' for both.
41
     * @param string $deleted One of 'live', 'deleted' or 'all' for both.
42
     * @param int|false $start Start date in a format accepted by strtotime()
43
     * @param int|false $end End date in a format accepted by strtotime()
44
     * @param int $offset Pagination offset.
45
     */
46 2
    public function __construct(
47
        Project $project,
48
        User $user,
49
        $namespace = 0,
50
        $redirects = 'noredirects',
51
        $deleted = 'all',
52
        $start = false,
53
        $end = false,
54
        $offset = 0
55
    ) {
56 2
        $this->project = $project;
57 2
        $this->user = $user;
58 2
        $this->namespace = 'all' === $namespace ? 'all' : (string)$namespace;
59 2
        $this->start = false === $start ? '' : date('Y-m-d', $start);
60 2
        $this->end = false === $end ? '' : date('Y-m-d', $end);
61 2
        $this->redirects = $redirects ?: 'noredirects';
62 2
        $this->deleted = $deleted ?: 'all';
63 2
        $this->offset = $offset;
64 2
    }
65
66
    /**
67
     * The redirects option associated with this Pages instance.
68
     * @return string
69
     */
70 1
    public function getRedirects(): string
71
    {
72 1
        return $this->redirects;
73
    }
74
75
    /**
76
     * The deleted pages option associated with this Page instance.
77
     * @return string
78
     */
79
    public function getDeleted(): string
80
    {
81
        return $this->deleted;
82
    }
83
84
    /**
85
     * Fetch and prepare the pages created by the user.
86
     * @param bool $all Whether to get *all* results. This should only be used for
87
     *     export options. HTTP and JSON should paginate.
88
     * @return array
89
     * @codeCoverageIgnore
90
     */
91
    public function prepareData(bool $all = false): array
92
    {
93
        $this->pages = [];
94
95
        foreach ($this->getNamespaces() as $ns) {
96
            $data = $this->fetchPagesCreated($ns, $all);
97
            $this->pages[$ns] = count($data) > 0
98
                ? $this->formatPages($data)[$ns]
99
                : [];
100
        }
101
102
        return $this->pages;
103
    }
104
105
    /**
106
     * The public function to get the list of all pages created by the user,
107
     * up to self::resultsPerPage(), across all namespaces.
108
     * @param bool $all Whether to get *all* results. This should only be used for
109
     *     export options. HTTP and JSON should paginate.
110
     * @return array
111
     */
112 1
    public function getResults(bool $all = false): array
113
    {
114 1
        if (null === $this->pages) {
115
            $this->prepareData($all);
116
        }
117 1
        return $this->pages;
118
    }
119
120
    /**
121
     * Get the total number of pages the user has created.
122
     * @return int
123
     */
124
    public function getNumPages(): int
125
    {
126
        $total = 0;
127
        foreach (array_values($this->getCounts()) as $values) {
128
            $total += $values['count'];
129
        }
130
        return $total;
131
    }
132
133
    /**
134
     * Get the total number of pages we're showing data for.
135
     * @return int
136
     */
137 1
    public function getNumResults(): int
138
    {
139 1
        $total = 0;
140 1
        foreach (array_values($this->getResults()) as $pages) {
141 1
            $total += count($pages);
142
        }
143 1
        return $total;
144
    }
145
146
    /**
147
     * Get the total number of pages that are currently deleted.
148
     * @return int
149
     */
150 1
    public function getNumDeleted(): int
151
    {
152 1
        $total = 0;
153 1
        foreach (array_values($this->getCounts()) as $values) {
154 1
            $total += $values['deleted'];
155
        }
156 1
        return $total;
157
    }
158
159
    /**
160
     * Get the total number of pages that are currently redirects.
161
     * @return int
162
     */
163 1
    public function getNumRedirects(): int
164
    {
165 1
        $total = 0;
166 1
        foreach (array_values($this->getCounts()) as $values) {
167 1
            $total += $values['redirects'];
168
        }
169 1
        return $total;
170
    }
171
172
    /**
173
     * Get the namespaces in which this user has created pages.
174
     * @return string[] The IDs.
175
     */
176 1
    public function getNamespaces(): array
177
    {
178 1
        return array_keys($this->getCounts());
179
    }
180
181
    /**
182
     * Number of namespaces being reported.
183
     * @return int
184
     */
185 1
    public function getNumNamespaces(): int
186
    {
187 1
        return count(array_keys($this->getCounts()));
188
    }
189
190
    /**
191
     * Are there more than one namespace in the results?
192
     * @return bool
193
     */
194 1
    public function isMultiNamespace(): bool
195
    {
196 1
        return $this->getNumNamespaces() > 1;
197
    }
198
199
    /**
200
     * Number of redirects/pages that were created/deleted, broken down by namespace.
201
     * @return array Namespace IDs as the keys, with values 'count', 'deleted' and 'redirects'.
202
     */
203 1
    public function getCounts(): array
204
    {
205 1
        if (null !== $this->countsByNamespace) {
206 1
            return $this->countsByNamespace;
207
        }
208
209 1
        $counts = [];
210
211 1
        foreach ($this->countPagesCreated() as $row) {
212 1
            $counts[$row['namespace']] = [
213 1
                'count' => (int)$row['count'],
214
            ];
215 1
            if ('live' !== $this->deleted) {
216 1
                $counts[$row['namespace']]['deleted'] = (int)$row['deleted'];
217
            }
218 1
            if ('noredirects' !== $this->redirects) {
219 1
                $counts[$row['namespace']]['redirects'] = (int)$row['redirects'];
220
            }
221
        }
222
223 1
        $this->countsByNamespace = $counts;
224 1
        return $this->countsByNamespace;
225
    }
226
227
    /**
228
     * Get the number of pages the user created by assessment.
229
     * @return array Keys are the assessment class, values are the counts.
230
     */
231
    public function getAssessmentCounts(): array
232
    {
233
        if ($this->getNumPages() > $this->resultsPerPage()) {
234
            $counts = $this->getRepository()->getAssessmentCounts(
0 ignored issues
show
Bug introduced by
The method getAssessmentCounts() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\PagesRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

234
            $counts = $this->getRepository()->/** @scrutinizer ignore-call */ getAssessmentCounts(
Loading history...
235
                $this->project,
236
                $this->user,
237
                $this->namespace,
238
                $this->redirects
239
            );
240
        } else {
241
            $counts = [];
242
            foreach ($this->pages as $nsPages) {
243
                foreach ($nsPages as $page) {
244
                    if (!isset($counts[$page['pa_class']])) {
245
                        $counts[$page['pa_class']] = 1;
246
                    } else {
247
                        $counts[$page['pa_class']]++;
248
                    }
249
                }
250
            }
251
        }
252
253
        arsort($counts);
254
255
        return $counts;
256
    }
257
258
    /**
259
     * Number of results to show, depending on the namespace.
260
     * @param bool $all Whether to get *all* results. This should only be used for
261
     *     export options. HTTP and JSON should paginate.
262
     * @return int|false
263
     */
264 1
    public function resultsPerPage(bool $all = false)
265
    {
266 1
        if (true === $all) {
267
            return false;
268
        }
269 1
        if ('all' === $this->namespace) {
270
            return self::RESULTS_LIMIT_ALL_NAMESPACES;
271
        }
272 1
        return self::RESULTS_LIMIT_SINGLE_NAMESPACE;
273
    }
274
275
    /**
276
     * Run the query to get pages created by the user with options.
277
     * This is ran independently for each namespace if $this->namespace is 'all'.
278
     * @param int $namespace Namespace ID.
279
     * @param bool $all Whether to get *all* results. This should only be used for
280
     *     export options. HTTP and JSON should paginate.
281
     * @return array
282
     */
283 1
    private function fetchPagesCreated(int $namespace, bool $all = false): array
284
    {
285 1
        return $this->getRepository()->getPagesCreated(
0 ignored issues
show
Bug introduced by
The method getPagesCreated() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\PagesRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

285
        return $this->getRepository()->/** @scrutinizer ignore-call */ getPagesCreated(
Loading history...
286 1
            $this->project,
287 1
            $this->user,
288 1
            $namespace,
289 1
            $this->redirects,
290 1
            $this->deleted,
291 1
            $this->start,
292 1
            $this->end,
293 1
            $this->resultsPerPage($all),
294 1
            $this->offset * $this->resultsPerPage()
295
        );
296
    }
297
298
    /**
299
     * Run the query to get the number of pages created by the user with given options.
300
     * @return array
301
     */
302 1
    private function countPagesCreated(): array
303
    {
304 1
        return $this->getRepository()->countPagesCreated(
0 ignored issues
show
Bug introduced by
The method countPagesCreated() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\PagesRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

304
        return $this->getRepository()->/** @scrutinizer ignore-call */ countPagesCreated(
Loading history...
305 1
            $this->project,
306 1
            $this->user,
307 1
            $this->namespace,
308 1
            $this->redirects,
309 1
            $this->deleted,
310 1
            $this->start,
311 1
            $this->end
312
        );
313
    }
314
315
    /**
316
     * Format the data, adding humanized timestamps, page titles, assessment badges,
317
     * and sorting by namespace and then timestamp.
318
     * @param array $pages As returned by self::fetchPagesCreated()
319
     * @return array
320
     */
321 1
    private function formatPages(array $pages): array
322
    {
323 1
        $results = [];
324
325 1
        foreach ($pages as $row) {
326 1
            $datetime = DateTime::createFromFormat('YmdHis', $row['rev_timestamp']);
327 1
            $datetimeHuman = $datetime->format('Y-m-d H:i');
328
329 1
            $pageData = array_merge($row, [
330 1
                'raw_time' => $row['rev_timestamp'],
331 1
                'human_time' => $datetimeHuman,
332 1
                'page_title' => str_replace('_', ' ', $row['page_title']),
333
            ]);
334
335 1
            if ($this->project->hasPageAssessments()) {
336
                $pageData['badge'] = $this->project
337
                    ->getPageAssessments()
338
                    ->getBadgeURL($pageData['pa_class']);
339
                $pageData['badge_file'] = $this->project
340
                    ->getPageAssessments()
341
                    ->getBadgeURL($pageData['pa_class'], true);
342
            }
343
344 1
            $results[$row['namespace']][] = $pageData;
345
        }
346
347 1
        return $results;
348
    }
349
}
350