Passed
Push — master ( f3a10f...0cfa7d )
by MusikAnimal
06:25
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 = 100;
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
        // $this->recreatedPages = $this->fetchRecreatedPages();
103
104
        return $this->pages;
105
    }
106
107
    /**
108
     * The public function to get the list of all pages created by the user,
109
     * up to self::resultsPerPage(), across all namespaces.
110
     * @param bool $all Whether to get *all* results. This should only be used for
111
     *     export options. HTTP and JSON should paginate.
112
     * @return array
113
     */
114 1
    public function getResults(bool $all = false): array
115
    {
116 1
        if (null === $this->pages) {
117
            $this->prepareData($all);
118
        }
119 1
        return $this->pages;
120
    }
121
122
    /**
123
     * Get the total number of pages the user has created.
124
     * @return int
125
     */
126
    public function getNumPages(): int
127
    {
128
        $total = 0;
129
        foreach (array_values($this->getCounts()) as $values) {
130
            $total += $values['count'];
131
        }
132
        return $total;
133
    }
134
135
    /**
136
     * Get the total number of pages we're showing data for.
137
     * @return int
138
     */
139 1
    public function getNumResults(): int
140
    {
141 1
        $total = 0;
142 1
        foreach (array_values($this->getResults()) as $pages) {
143 1
            $total += count($pages);
144
        }
145 1
        return $total;
146
    }
147
148
    /**
149
     * Get the total number of pages that are currently deleted.
150
     * @return int
151
     */
152 1
    public function getNumDeleted(): int
153
    {
154 1
        $total = 0;
155 1
        foreach (array_values($this->getCounts()) as $values) {
156 1
            $total += $values['deleted'];
157
        }
158 1
        return $total;
159
    }
160
161
    /**
162
     * Get the total number of pages that are currently redirects.
163
     * @return int
164
     */
165 1
    public function getNumRedirects(): int
166
    {
167 1
        $total = 0;
168 1
        foreach (array_values($this->getCounts()) as $values) {
169 1
            $total += $values['redirects'];
170
        }
171 1
        return $total;
172
    }
173
174
    /**
175
     * Get the namespaces in which this user has created pages.
176
     * @return string[] The IDs.
177
     */
178 1
    public function getNamespaces(): array
179
    {
180 1
        return array_keys($this->getCounts());
181
    }
182
183
    /**
184
     * Number of namespaces being reported.
185
     * @return int
186
     */
187
    public function getNumNamespaces(): int
188
    {
189
        return count(array_keys($this->getCounts()));
190
    }
191
192
    /**
193
     * Number of redirects/pages that were created/deleted, broken down by namespace.
194
     * @return array Namespace IDs as the keys, with values 'count', 'deleted' and 'redirects'.
195
     */
196 1
    public function getCounts(): array
197
    {
198 1
        if (null !== $this->countsByNamespace) {
199 1
            return $this->countsByNamespace;
200
        }
201
202 1
        $counts = [];
203
204 1
        foreach ($this->countPagesCreated() as $row) {
205 1
            $counts[$row['namespace']] = [
206 1
                'count' => (int)$row['count'],
207
            ];
208 1
            if ('live' !== $this->deleted) {
209 1
                $counts[$row['namespace']]['deleted'] = (int)$row['deleted'];
210
            }
211 1
            if ('noredirects' !== $this->redirects) {
212 1
                $counts[$row['namespace']]['redirects'] = (int)$row['redirects'];
213
            }
214
        }
215
216 1
        $this->countsByNamespace = $counts;
217 1
        return $this->countsByNamespace;
218
    }
219
220
    /**
221
     * Get the number of pages the user created by assessment.
222
     * @return array Keys are the assessment class, values are the counts.
223
     */
224
    public function getAssessmentCounts(): array
225
    {
226
        if ($this->getNumPages() > $this->resultsPerPage()) {
227
            $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

227
            $counts = $this->getRepository()->/** @scrutinizer ignore-call */ getAssessmentCounts(
Loading history...
228
                $this->project,
229
                $this->user,
230
                $this->namespace,
231
                $this->redirects
232
            );
233
        } else {
234
            $counts = [];
235
            foreach ($this->pages as $nsPages) {
236
                foreach ($nsPages as $page) {
237
                    if (!isset($counts[$page['pa_class']])) {
238
                        $counts[$page['pa_class']] = 1;
239
                    } else {
240
                        $counts[$page['pa_class']]++;
241
                    }
242
                }
243
            }
244
        }
245
246
        arsort($counts);
247
248
        return $counts;
249
    }
250
251
    /**
252
     * Number of results to show, depending on the namespace.
253
     * @param bool $all Whether to get *all* results. This should only be used for
254
     *     export options. HTTP and JSON should paginate.
255
     * @return int|false
256
     */
257 1
    public function resultsPerPage(bool $all = false)
258
    {
259 1
        if (true === $all) {
260
            return false;
261
        }
262 1
        if ('all' === $this->namespace) {
263
            return self::RESULTS_LIMIT_ALL_NAMESPACES;
264
        }
265 1
        return self::RESULTS_LIMIT_SINGLE_NAMESPACE;
266
    }
267
268
    /**
269
     * Run the query to get pages created by the user with options.
270
     * This is ran independently for each namespace if $this->namespace is 'all'.
271
     * @param int $namespace Namespace ID.
272
     * @param bool $all Whether to get *all* results. This should only be used for
273
     *     export options. HTTP and JSON should paginate.
274
     * @return array
275
     */
276 1
    private function fetchPagesCreated(int $namespace, bool $all = false): array
277
    {
278 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

278
        return $this->getRepository()->/** @scrutinizer ignore-call */ getPagesCreated(
Loading history...
279 1
            $this->project,
280 1
            $this->user,
281 1
            $namespace,
282 1
            $this->redirects,
283 1
            $this->deleted,
284 1
            $this->start,
285 1
            $this->end,
286 1
            $this->resultsPerPage($all),
287 1
            $this->offset * $this->resultsPerPage()
288
        );
289
    }
290
291
    /**
292
     * Run the query to get the number of pages created by the user with given options.
293
     * @return array
294
     */
295 1
    private function countPagesCreated(): array
296
    {
297 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

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