Passed
Push — master ( 34ad8f...0934f5 )
by Arnaud
05:35
created

Pagination   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 95.88%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
eloc 90
dl 0
loc 141
ccs 93
cts 97
cp 0.9588
rs 10
c 4
b 1
f 0
wmc 20

1 Method

Rating   Name   Duplication   Size   Complexity  
F generate() 0 136 20
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 1
            $sortby = $page->getVariable('sortby');
0 ignored issues
show
Unused Code introduced by
The assignment to $sortby is dead and can be removed.
Loading history...
50
            // site pagination configuration
51 1
            $paginationPerPage = \intval($this->config->get('pagination.max') ?? 5);
52 1
            $paginationPath = (string) $this->config->get('pagination.path') ?? 'page';
53
            // page pagination configuration
54 1
            $pagePagination = $page->getVariable('pagination');
55 1
            if ($pagePagination) {
56 1
                if (isset($pagePagination['enabled']) && $pagePagination['enabled'] === false) {
57
                    continue;
58
                }
59 1
                if (isset($pagePagination['max'])) {
60 1
                    $paginationPerPage = \intval($pagePagination['max']);
61
                }
62 1
                if (isset($pagePagination['path'])) {
63 1
                    $paginationPath = (string) $pagePagination['path'];
64
                }
65
            }
66 1
            $pagesTotal = \count($pages);
67
            // is pagination not necessary?
68 1
            if ($pagesTotal <= $paginationPerPage) {
69 1
                continue;
70
            }
71
            // sorts (by date by default)
72 1
            $pages = $pages->sortByDate();
73
            /*
74
             * sortby: date|updated|title|weight
75
             *
76
             * sortby:
77
             *   variable: date|updated
78
             *   desc_title: false|true
79
             *   reverse: false|true
80
             */
81 1
            if ($page->hasVariable('sortby')) {
82 1
                $sortby = (string) $page->getVariable('sortby');
83
                // options?
84 1
                $sortby = $page->getVariable('sortby')['variable'] ?? $sortby;
85 1
                $descTitle = $page->getVariable('sortby')['desc_title'] ?? false;
86 1
                $reverse = $page->getVariable('sortby')['reverse'] ?? false;
87
                // sortby: date, title or weight
88 1
                $sortMethod = sprintf('sortBy%s', ucfirst(str_replace('updated', 'date', $sortby)));
89 1
                if (!method_exists($pages, $sortMethod)) {
90
                    throw new RuntimeException(sprintf('In "%s" section "%s" is not a valid value for "sortby" variable.', $page->getId(), $sortby));
91
                }
92 1
                $pages = $pages->$sortMethod(['variable' => $sortby, 'descTitle' => $descTitle, 'reverse' => $reverse]);
93
            }
94
            // builds paginator
95 1
            $paginatorPagesCount = \intval(ceil($pagesTotal / $paginationPerPage));
96 1
            for ($i = 0; $i < $paginatorPagesCount; $i++) {
97 1
                $itPagesInPagination = new \LimitIterator($pages->getIterator(), ($i * $paginationPerPage), $paginationPerPage);
98 1
                $pagesInPagination = new PagesCollection(
99 1
                    $page->getId() . '-page-' . ($i + 1),
100 1
                    iterator_to_array($itPagesInPagination)
101 1
                );
102 1
                $alteredPage = clone $page;
103 1
                if ($i == 0) { // first page (ie: blog/page/1 -> blog)
104 1
                    $pageId = $page->getId();
105 1
                    $alteredPage
106 1
                        ->setVariable('alias', [
107 1
                            sprintf('%s/%s/%s', $path, $paginationPath, 1),
108 1
                        ]);
109
                } else { // others pages (ie: blog/page/X)
110 1
                    $pageId = Page::slugify(sprintf('%s/%s/%s', $page->getId(), $paginationPath, $i + 1));
111 1
                    $alteredPage
112 1
                        ->setId($pageId)
113 1
                        ->setVirtual(true)
114 1
                        ->setPath(Page::slugify(sprintf('%s/%s/%s', $path, $paginationPath, $i + 1)))
115 1
                        ->unVariable('menu')
116 1
                        ->unVariable('alias')
117 1
                        ->unVariable('aliases') // backward compatibility
118 1
                        ->unVariable('langref')
119 1
                        ->setVariable('paginated', true);
120
                }
121
                // set paginator values
122 1
                $paginator = [
123 1
                    'pages'       => $pagesInPagination,
124 1
                    'pages_total' => $pagesTotal,
125 1
                    'totalpages'  => $pagesTotal, // backward compatibility
126 1
                    'count'       => $paginatorPagesCount,
127 1
                    'current'     => $i + 1,
128 1
                ];
129
                // adds links
130 1
                $paginator['links'] = ['first' => $page->getId() ?: 'index'];
131 1
                if ($i == 1) {
132 1
                    $paginator['links'] += ['prev' => $page->getId() ?: 'index'];
133
                }
134 1
                if ($i > 1) {
135 1
                    $paginator['links'] += ['prev' => Page::slugify(sprintf(
136 1
                        '%s/%s/%s',
137 1
                        $page->getId(),
138 1
                        $paginationPath,
139 1
                        $i
140 1
                    ))];
141
                }
142 1
                $paginator['links'] += ['self' => $pageId ?: 'index'];
143 1
                if ($i < $paginatorPagesCount - 1) {
144 1
                    $paginator['links'] += ['next' => Page::slugify(sprintf(
145 1
                        '%s/%s/%s',
146 1
                        $page->getId(),
147 1
                        $paginationPath,
148 1
                        $i + 2
149 1
                    ))];
150
                }
151 1
                $paginator['links'] += ['last' => Page::slugify(sprintf(
152 1
                    '%s/%s/%s',
153 1
                    $page->getId(),
154 1
                    $paginationPath,
155 1
                    $paginatorPagesCount
156 1
                ))];
157 1
                $paginator['links'] += ['path' => Page::slugify(sprintf('%s/%s', $page->getId(), $paginationPath))];
158
                // set paginator to cloned page
159 1
                $alteredPage->setPaginator($paginator);
160 1
                $alteredPage->setVariable('pagination', $paginator); // backward compatibility
161
                // updates date with the first element of the collection
162 1
                $alteredPage->setVariable('date', $pagesInPagination->first()->getVariable('date'));
163
164 1
                $this->generatedPages->add($alteredPage);
165
            }
166
        }
167
    }
168
}
169