Test Failed
Push — master ( 860dbc...7f6d09 )
by MusikAnimal
07:34
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
     * Get the sum of all page sizes, across all specified namespaces.
201
     * @return int
202
     */
203 1
    public function getTotalPageSize(): int
204
    {
205 1
        return array_sum(array_column($this->getCounts(), 'total_length'));
206 1
    }
207
208
    /**
209 1
     * Get average size across all pages.
210
     * @return float
211 1
     */
212 1
    public function averagePageSize(): float
213 1
    {
214
        return $this->getTotalPageSize() / $this->getNumPages();
215 1
    }
216 1
217
    /**
218 1
     * Number of redirects/pages that were created/deleted, broken down by namespace.
219 1
     * @return array Namespace IDs as the keys, with values 'count', 'deleted' and 'redirects'.
220
     */
221
    public function getCounts(): array
222
    {
223 1
        if (null !== $this->countsByNamespace) {
224 1
            return $this->countsByNamespace;
225
        }
226
227
        $counts = [];
228
229
        foreach ($this->countPagesCreated() as $row) {
230
            $count = (int)$row['count'];
231
            $totalLength = (int)$row['total_length'];
232
            $counts[$row['namespace']] = [
233
                'count' => $count,
234
                'total_length' => $totalLength,
235
                'avg_length' => $count > 0 ? $totalLength / $count : 0,
236
            ];
237
            if ('live' !== $this->deleted) {
238
                $counts[$row['namespace']]['deleted'] = (int)$row['deleted'];
239
            }
240
            if ('noredirects' !== $this->redirects) {
241
                $counts[$row['namespace']]['redirects'] = (int)$row['redirects'];
242
            }
243
        }
244
245
        $this->countsByNamespace = $counts;
246
        return $this->countsByNamespace;
247
    }
248
249
    /**
250
     * Get the number of pages the user created by assessment.
251
     * @return array Keys are the assessment class, values are the counts.
252
     */
253
    public function getAssessmentCounts(): array
254
    {
255
        if ($this->getNumPages() > $this->resultsPerPage()) {
256
            $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

256
            $counts = $this->getRepository()->/** @scrutinizer ignore-call */ getAssessmentCounts(
Loading history...
257
                $this->project,
258
                $this->user,
259
                $this->namespace,
260
                $this->redirects
261
            );
262
        } else {
263
            $counts = [];
264 1
            foreach ($this->pages as $nsPages) {
265
                foreach ($nsPages as $page) {
266 1
                    if (!isset($counts[$page['pa_class']])) {
267
                        $counts[$page['pa_class']] = 1;
268
                    } else {
269 1
                        $counts[$page['pa_class']]++;
270
                    }
271
                }
272 1
            }
273
        }
274
275
        arsort($counts);
276
277
        return $counts;
278
    }
279
280
    /**
281
     * Number of results to show, depending on the namespace.
282
     * @param bool $all Whether to get *all* results. This should only be used for
283 1
     *     export options. HTTP and JSON should paginate.
284
     * @return int|false
285 1
     */
286 1
    public function resultsPerPage(bool $all = false)
287 1
    {
288 1
        if (true === $all) {
289 1
            return false;
290 1
        }
291 1
        if ('all' === $this->namespace) {
292 1
            return self::RESULTS_LIMIT_ALL_NAMESPACES;
293 1
        }
294 1
        return self::RESULTS_LIMIT_SINGLE_NAMESPACE;
295
    }
296
297
    /**
298
     * Run the query to get pages created by the user with options.
299
     * This is ran independently for each namespace if $this->namespace is 'all'.
300
     * @param int $namespace Namespace ID.
301
     * @param bool $all Whether to get *all* results. This should only be used for
302 1
     *     export options. HTTP and JSON should paginate.
303
     * @return array
304 1
     */
305 1
    private function fetchPagesCreated(int $namespace, bool $all = false): array
306 1
    {
307 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

307
        return $this->getRepository()->/** @scrutinizer ignore-call */ getPagesCreated(
Loading history...
308 1
            $this->project,
309 1
            $this->user,
310 1
            $namespace,
311 1
            $this->redirects,
312
            $this->deleted,
313
            $this->start,
314
            $this->end,
315
            $this->resultsPerPage($all),
316
            $this->offset * $this->resultsPerPage()
317
        );
318
    }
319
320
    /**
321 1
     * Run the query to get the number of pages created by the user with given options.
322
     * @return array
323 1
     */
324
    private function countPagesCreated(): array
325 1
    {
326 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

326
        return $this->getRepository()->/** @scrutinizer ignore-call */ countPagesCreated(
Loading history...
327 1
            $this->project,
328
            $this->user,
329 1
            $this->namespace,
330 1
            $this->redirects,
331 1
            $this->deleted,
332 1
            $this->start,
333
            $this->end
334
        );
335 1
    }
336
337
    /**
338
     * Format the data, adding humanized timestamps, page titles, assessment badges,
339
     * and sorting by namespace and then timestamp.
340
     * @param array $pages As returned by self::fetchPagesCreated()
341
     * @return array
342
     */
343
    private function formatPages(array $pages): array
344 1
    {
345
        $results = [];
346
347 1
        foreach ($pages as $row) {
348
            $datetime = DateTime::createFromFormat('YmdHis', $row['rev_timestamp']);
349
            $datetimeHuman = $datetime->format('Y-m-d H:i');
350
351
            $pageData = array_merge($row, [
352
                'raw_time' => $row['rev_timestamp'],
353
                'human_time' => $datetimeHuman,
354
                'page_title' => str_replace('_', ' ', $row['page_title']),
355
            ]);
356
357
            if ($this->project->hasPageAssessments()) {
358
                $pageData['badge'] = $this->project
359
                    ->getPageAssessments()
360
                    ->getBadgeURL($pageData['pa_class']);
361
                $pageData['badge_file'] = $this->project
362
                    ->getPageAssessments()
363
                    ->getBadgeURL($pageData['pa_class'], true);
364
            }
365
366
            $results[$row['namespace']][] = $pageData;
367
        }
368
369
        return $results;
370
    }
371
}
372