Passed
Push — master ( 78fac6...512cd1 )
by Arnaud
05:16
created

Pagination::generate()   F

Complexity

Conditions 20
Paths 184

Size

Total Lines 135
Code Lines 88

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 92
CRAP Score 20.029

Importance

Changes 5
Bugs 1 Features 0
Metric Value
cc 20
eloc 88
c 5
b 1
f 0
nc 184
nop 0
dl 0
loc 135
ccs 92
cts 96
cp 0.9583
crap 20.029
rs 3.4666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Cecil.
7
 *
8
 * Copyright (c) Arnaud Ligny <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Cecil\Generator;
15
16
use Cecil\Collection\Page\Collection as PagesCollection;
17
use Cecil\Collection\Page\Page;
18
use Cecil\Collection\Page\Type;
19
use Cecil\Exception\RuntimeException;
20
21
/**
22
 * Class Generator\Pagination.
23
 */
24
class Pagination extends AbstractGenerator implements GeneratorInterface
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29 1
    public function generate(): void
30
    {
31 1
        if ($this->config->get('pagination.enabled') === false) {
32
            return;
33
        }
34
35
        // filters list pages (home, sections and terms)
36 1
        $filteredPages = $this->builder->getPages()->filter(function (Page $page) {
37 1
            return \in_array($page->getType(), [Type::HOMEPAGE, Type::SECTION, Type::TERM]);
38 1
        });
39
        /** @var Page $page */
40 1
        foreach ($filteredPages as $page) {
41 1
            $pages = $page->getPages()->filter(function (Page $page) {
42 1
                return $page->getVariable('published');
43 1
            });
44
            // if no sub-pages: by-pass
45 1
            if ($pages === null) {
46
                continue;
47
            }
48 1
            $path = $page->getPath();
49
            // site pagination configuration
50 1
            $paginationPerPage = \intval($this->config->get('pagination.max') ?? 5);
51 1
            $paginationPath = (string) $this->config->get('pagination.path') ?? 'page';
52
            // page pagination configuration
53 1
            $pagePagination = $page->getVariable('pagination');
54 1
            if ($pagePagination) {
55 1
                if (isset($pagePagination['enabled']) && $pagePagination['enabled'] === false) {
56
                    continue;
57
                }
58 1
                if (isset($pagePagination['max'])) {
59 1
                    $paginationPerPage = \intval($pagePagination['max']);
60
                }
61 1
                if (isset($pagePagination['path'])) {
62 1
                    $paginationPath = (string) $pagePagination['path'];
63
                }
64
            }
65 1
            $pagesTotal = \count($pages);
66
            // is pagination not necessary?
67 1
            if ($pagesTotal <= $paginationPerPage) {
68 1
                continue;
69
            }
70
            // sorts (by date by default)
71 1
            $pages = $pages->sortByDate();
72
            /*
73
             * sortby: date|updated|title|weight
74
             *
75
             * sortby:
76
             *   variable: date|updated
77
             *   desc_title: false|true
78
             *   reverse: false|true
79
             */
80 1
            if ($page->hasVariable('sortby')) {
81 1
                $sortby = (string) $page->getVariable('sortby');
82
                // options?
83 1
                $sortby = $page->getVariable('sortby')['variable'] ?? $sortby;
84 1
                $descTitle = $page->getVariable('sortby')['desc_title'] ?? false;
85 1
                $reverse = $page->getVariable('sortby')['reverse'] ?? false;
86
                // sortby: date, title or weight
87 1
                $sortMethod = sprintf('sortBy%s', ucfirst(str_replace('updated', 'date', $sortby)));
88 1
                if (!method_exists($pages, $sortMethod)) {
89
                    throw new RuntimeException(sprintf('In "%s" section "%s" is not a valid value for "sortby" variable.', $page->getId(), $sortby));
90
                }
91 1
                $pages = $pages->$sortMethod(['variable' => $sortby, 'descTitle' => $descTitle, 'reverse' => $reverse]);
92
            }
93
            // builds paginator
94 1
            $paginatorPagesCount = \intval(ceil($pagesTotal / $paginationPerPage));
95 1
            for ($i = 0; $i < $paginatorPagesCount; $i++) {
96 1
                $itPagesInPagination = new \LimitIterator($pages->getIterator(), ($i * $paginationPerPage), $paginationPerPage);
97 1
                $pagesInPagination = new PagesCollection(
98 1
                    $page->getId() . '-page-' . ($i + 1),
99 1
                    iterator_to_array($itPagesInPagination)
100 1
                );
101 1
                $alteredPage = clone $page;
102 1
                if ($i == 0) { // first page (ie: blog/page/1 -> blog)
103 1
                    $pageId = $page->getId();
104 1
                    $alteredPage
105 1
                        ->setVariable('alias', [
106 1
                            sprintf('%s/%s/%s', $path, $paginationPath, 1),
107 1
                        ]);
108
                } else { // others pages (ie: blog/page/X)
109 1
                    $pageId = Page::slugify(sprintf('%s/%s/%s', $page->getId(), $paginationPath, $i + 1));
110 1
                    $alteredPage
111 1
                        ->setId($pageId)
112 1
                        ->setVirtual(true)
113 1
                        ->setPath(Page::slugify(sprintf('%s/%s/%s', $path, $paginationPath, $i + 1)))
114 1
                        ->unVariable('menu')
115 1
                        ->unVariable('alias')
116 1
                        ->unVariable('aliases') // backward compatibility
117 1
                        ->unVariable('langref')
118 1
                        ->setVariable('paginated', true);
119
                }
120
                // set paginator values
121 1
                $paginator = [
122 1
                    'pages'       => $pagesInPagination,
123 1
                    'pages_total' => $pagesTotal,
124 1
                    'totalpages'  => $pagesTotal, // backward compatibility
125 1
                    'count'       => $paginatorPagesCount,
126 1
                    'current'     => $i + 1,
127 1
                ];
128
                // adds links
129 1
                $paginator['links'] = ['first' => $page->getId() ?: 'index'];
130 1
                if ($i == 1) {
131 1
                    $paginator['links'] += ['prev' => $page->getId() ?: 'index'];
132
                }
133 1
                if ($i > 1) {
134 1
                    $paginator['links'] += ['prev' => Page::slugify(sprintf(
135 1
                        '%s/%s/%s',
136 1
                        $page->getId(),
137 1
                        $paginationPath,
138 1
                        $i
139 1
                    ))];
140
                }
141 1
                $paginator['links'] += ['self' => $pageId ?: 'index'];
142 1
                if ($i < $paginatorPagesCount - 1) {
143 1
                    $paginator['links'] += ['next' => Page::slugify(sprintf(
144 1
                        '%s/%s/%s',
145 1
                        $page->getId(),
146 1
                        $paginationPath,
147 1
                        $i + 2
148 1
                    ))];
149
                }
150 1
                $paginator['links'] += ['last' => Page::slugify(sprintf(
151 1
                    '%s/%s/%s',
152 1
                    $page->getId(),
153 1
                    $paginationPath,
154 1
                    $paginatorPagesCount
155 1
                ))];
156 1
                $paginator['links'] += ['path' => Page::slugify(sprintf('%s/%s', $page->getId(), $paginationPath))];
157
                // set paginator to cloned page
158 1
                $alteredPage->setPaginator($paginator);
159 1
                $alteredPage->setVariable('pagination', $paginator); // backward compatibility
160
                // updates date with the first element of the collection
161 1
                $alteredPage->setVariable('date', $pagesInPagination->first()->getVariable('date'));
162
163 1
                $this->generatedPages->add($alteredPage);
164
            }
165
        }
166
    }
167
}
168