Passed
Push — master ( 58b566...3d7011 )
by Arnaud
05:04
created

Pagination   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Test Coverage

Coverage 95.56%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 82
c 1
b 0
f 0
dl 0
loc 125
ccs 86
cts 90
cp 0.9556
rs 10
wmc 20

1 Method

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