• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Cecilapp / Cecil / 21672766165

04 Feb 2026 01:11PM UTC coverage: 82.577% (-0.005%) from 82.582%
21672766165

push

github

ArnaudLigny
refactor: simplify pagination logic

Support disabling pagination per-page by treating page.pagination === false as a skip, and preserve existing enabled flag behavior. Flattened and simplified the pagination conditional flow, extracted page-level max/path overrides without nesting, and adjusted comments (including a note about global pagination disable). This refactor reduces complexity and makes per-page pagination toggling clearer.

5 of 6 new or added lines in 1 file covered. (83.33%)

3313 of 4012 relevant lines covered (82.58%)

0.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/src/Generator/Pagination.php
1
<?php
2

3
/**
4
 * This file is part of Cecil.
5
 *
6
 * (c) Arnaud Ligny <arnaud@ligny.fr>
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
    public function generate(): void
33
    {
34
        // disable pagination globally
35
        if (!$this->config->isEnabled('pages.pagination')) {
1✔
36
            return;
×
37
        }
38

39
        // filters list pages (home, sections and terms)
40
        $listPages = $this->builder->getPages()->filter(function (Page $page) {
1✔
41
            return \in_array($page->getType(), [Type::HOMEPAGE->value, Type::SECTION->value, Type::TERM->value]);
1✔
42
        });
1✔
43
        /** @var Page $page */
44
        foreach ($listPages as $page) {
1✔
45
            // if no pages: continue
46
            if ($page->getPages() === null) {
1✔
47
                continue;
×
48
            }
49
            $pages = $page->getPages()->filter(function (Page $page) {
1✔
50
                return $page->getType() == Type::PAGE->value && $page->getVariable('published');
1✔
51
            });
1✔
52
            // if no published pages: continue
53
            if ($pages === null) {
1✔
54
                continue;
×
55
            }
56
            $path = $page->getPath();
1✔
57
            // site configuration
58
            $paginationPerPage = \intval($this->config->get('pages.pagination.max') ?? 5);
1✔
59
            $paginationPath = $this->config->get('pages.pagination.path') ?? 'page';
1✔
60
            // page configuration
61
            $pagePagination = $page->getVariable('pagination');
1✔
62
            if ($pagePagination === false || (isset($pagePagination['enabled']) && $pagePagination['enabled'] === false)) {
1✔
NEW
63
                continue;
×
64
            }
65
            if (isset($pagePagination['max'])) {
1✔
66
                $paginationPerPage = \intval($pagePagination['max']);
1✔
67
            }
68
            if (isset($pagePagination['path'])) {
1✔
69
                $paginationPath = (string) $pagePagination['path'];
1✔
70
            }
71
            // total pages
72
            $pagesTotal = \count($pages);
1✔
73
            // is pagination not necessary?
74
            if ($pagesTotal <= $paginationPerPage) {
1✔
75
                continue;
1✔
76
            }
77
            // sorts pages
78
            $sortBy = $page->getVariable('sortby') ?? $this->config->get('pages.sortby');
1✔
79
            $pages = $pages->sortBy($sortBy);
1✔
80
            // builds paginator
81
            $paginatorPagesCount = \intval(ceil($pagesTotal / $paginationPerPage));
1✔
82
            for ($i = 0; $i < $paginatorPagesCount; $i++) {
1✔
83
                $itPagesInPagination = new \LimitIterator($pages->getIterator(), $i * $paginationPerPage, $paginationPerPage);
1✔
84
                $pagesInPagination = new PagesCollection(
1✔
85
                    $page->getId() . '-page-' . ($i + 1),
1✔
86
                    iterator_to_array($itPagesInPagination)
1✔
87
                );
1✔
88
                $alteredPage = clone $page;
1✔
89
                // first page (ie: blog/page/1 -> blog)
90
                $pageId = $page->getId();
1✔
91
                $alteredPage
1✔
92
                    ->setVariable('alias', [
1✔
93
                        \sprintf('%s/%s/%s', $path, $paginationPath, 1),
1✔
94
                    ]);
1✔
95
                // others pages (ie: blog/page/X)
96
                if ($i > 0) {
1✔
97
                    $pageId = Page::slugify(\sprintf('%s/%s/%s', $page->getId(), $paginationPath, $i + 1));
1✔
98
                    $alteredPage
1✔
99
                        ->setId($pageId)
1✔
100
                        ->setVirtual(true)
1✔
101
                        ->setPath(Page::slugify(\sprintf('%s/%s/%s', $path, $paginationPath, $i + 1)))
1✔
102
                        ->unVariable('menu')
1✔
103
                        ->unVariable('alias')
1✔
104
                        ->unVariable('aliases') // backward compatibility
1✔
105
                        ->unVariable('langref')
1✔
106
                        ->setVariable('paginated', true);
1✔
107
                }
108
                // set paginator values
109
                $paginator = [
1✔
110
                    'pages'       => $pagesInPagination,
1✔
111
                    'pages_total' => $pagesTotal,
1✔
112
                    'totalpages'  => $pagesTotal, // backward compatibility
1✔
113
                    'count'       => $paginatorPagesCount,
1✔
114
                    'current'     => $i + 1,
1✔
115
                ];
1✔
116
                // adds links
117
                $paginator['links'] = ['first' => $page->getId() ?: 'index'];
1✔
118
                if ($i == 1) {
1✔
119
                    $paginator['links'] += ['prev' => $page->getId() ?: 'index'];
1✔
120
                }
121
                if ($i > 1) {
1✔
122
                    $paginator['links'] += ['prev' => Page::slugify(\sprintf(
1✔
123
                        '%s/%s/%s',
1✔
124
                        $page->getId(),
1✔
125
                        $paginationPath,
1✔
126
                        $i
1✔
127
                    ))];
1✔
128
                }
129
                $paginator['links'] += ['self' => $pageId ?: 'index'];
1✔
130
                if ($i < $paginatorPagesCount - 1) {
1✔
131
                    $paginator['links'] += ['next' => Page::slugify(\sprintf(
1✔
132
                        '%s/%s/%s',
1✔
133
                        $page->getId(),
1✔
134
                        $paginationPath,
1✔
135
                        $i + 2
1✔
136
                    ))];
1✔
137
                }
138
                $paginator['links'] += ['last' => Page::slugify(\sprintf(
1✔
139
                    '%s/%s/%s',
1✔
140
                    $page->getId(),
1✔
141
                    $paginationPath,
1✔
142
                    $paginatorPagesCount
1✔
143
                ))];
1✔
144
                $paginator['links'] += ['path' => Page::slugify(\sprintf('%s/%s', $page->getId(), $paginationPath))];
1✔
145
                // set paginator to cloned page
146
                $alteredPage->setPaginator($paginator);
1✔
147
                $alteredPage->setVariable('pagination', $paginator); // backward compatibility
1✔
148
                // updates date with the first element of the collection
149
                $alteredPage->setVariable('date', $pagesInPagination->first()->getVariable('date'));
1✔
150

151
                $this->generatedPages->add($alteredPage);
1✔
152
            }
153
        }
154
    }
155
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc