Section   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Test Coverage

Coverage 95.24%

Importance

Changes 0
Metric Value
eloc 81
dl 0
loc 146
ccs 80
cts 84
cp 0.9524
rs 9.84
c 0
b 0
f 0
wmc 32

3 Methods

Rating   Name   Duplication   Size   Complexity  
F generate() 0 79 19
A sortSubPages() 0 12 3
B addNavigationLinks() 0 38 10
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
use Cecil\Exception\RuntimeException;
20
21
/**
22
 * Section generator class.
23
 *
24
 * This class is responsible for generating sections from the pages in the builder.
25
 * It identifies sections based on the 'section' variable in each page, and
26
 * creates a new page for each section. The generated pages are added to the
27
 * collection of generated pages. It also handles sorting of subpages and
28
 * adding navigation links (next and previous) to the section pages.
29
 */
30
class Section extends AbstractGenerator implements GeneratorInterface
31
{
32
    /**
33
     * {@inheritdoc}
34
     */
35 1
    public function generate(): void
36
    {
37 1
        $sections = [];
38
39
        // identifying sections from all pages
40
        /** @var Page $page */
41 1
        foreach ($this->builder->getPages() ?? [] as $page) {
42
            // top level (root) sections
43 1
            if ($page->getSection()) {
44
                // do not add "not published" and "not excluded" pages to its section
45
                if (
46 1
                    $page->getVariable('published') !== true
47 1
                    || ($page->getVariable('excluded') || $page->getVariable('exclude'))
48
                ) {
49 1
                    continue;
50
                }
51 1
                $sections[$page->getSection()][$page->getVariable('language', $this->config->getLanguageDefault())][] = $page;
52
            }
53
        }
54
55
        // adds each section to pages collection
56 1
        if (\count($sections) > 0) {
57 1
            $menuWeight = 100;
58
59 1
            foreach ($sections as $section => $languages) {
60 1
                foreach ($languages as $language => $pagesAsArray) {
61 1
                    $pageId = $path = Page::slugify($section);
62 1
                    if ($language != $this->config->getLanguageDefault()) {
63 1
                        $pageId = "$language/$pageId";
64
                    }
65 1
                    $page = (new Page($pageId))->setVariable('title', ucfirst($section))
66 1
                        ->setPath($path);
67 1
                    if ($this->builder->getPages()->has($pageId)) {
68 1
                        $page = clone $this->builder->getPages()->get($pageId);
69
                    }
70 1
                    $subPages = new PagesCollection("section-$pageId", $pagesAsArray);
71
                    // cascade variables
72 1
                    if ($page->hasVariable('cascade')) {
73 1
                        $cascade = $page->getVariable('cascade');
74 1
                        if (\is_array($cascade)) {
75 1
                            $subPages->map(function (Page $page) use ($cascade) {
76 1
                                foreach ($cascade as $key => $value) {
77 1
                                    if (!$page->hasVariable($key)) {
78 1
                                        $page->setVariable($key, $value);
79
                                    }
80
                                }
81 1
                            });
82
                        }
83
                    }
84
                    // sorts pages
85 1
                    $pages = Section::sortSubPages($this->config, $page, $subPages);
86
                    // adds navigation links (excludes taxonomy pages)
87 1
                    $sortBy = $page->getVariable('sortby')['variable'] ?? $page->getVariable('sortby') ?? $this->config->get('pages.sortby')['variable'] ?? $this->config->get('pages.sortby') ?? 'date';
88 1
                    if (!\in_array($page->getId(), array_keys((array) $this->config->get('taxonomies')))) {
89 1
                        $this->addNavigationLinks($pages, $sortBy, $page->getVariable('circular') ?? false);
90
                    }
91
                    // creates page for each section
92 1
                    $page->setType(Type::SECTION->value)
93 1
                        ->setSection($path)
94 1
                        ->setPages($pages)
95 1
                        ->setVariable('language', $language)
96 1
                        ->setVariable('date', $pages->first()->getVariable('date'))
97 1
                        ->setVariable('langref', $path);
98
                    // human readable title
99 1
                    if ($page->getVariable('title') == 'index') {
100 1
                        $page->setVariable('title', $section);
101
                    }
102
                    // default menu
103 1
                    if (!$page->getVariable('menu')) {
104 1
                        $page->setVariable('menu', ['main' => ['weight' => $menuWeight]]);
105
                    }
106
107
                    try {
108 1
                        $this->generatedPages->add($page);
109
                    } catch (\DomainException) {
110
                        $this->generatedPages->replace($page->getId(), $page);
111
                    }
112
                }
113 1
                $menuWeight += 10;
114
            }
115
        }
116
    }
117
118
    /**
119
     * Sorts subpages.
120
     */
121 1
    public static function sortSubPages(\Cecil\Config $config, Page $page, PagesCollection $subPages): PagesCollection
122
    {
123 1
        $subPages = $subPages->sortBy($config->get('pages.sortby'));
124 1
        if ($page->hasVariable('sortby')) {
125
            try {
126 1
                $subPages = $subPages->sortBy($page->getVariable('sortby'));
127
            } catch (RuntimeException $e) {
128
                throw new RuntimeException(\sprintf('In page "%s", %s', $page->getId(), $e->getMessage()));
129
            }
130
        }
131
132 1
        return $subPages;
133
    }
134
135
    /**
136
     * Adds navigation (next and prev) to section subpages.
137
     */
138 1
    protected function addNavigationLinks(PagesCollection $pages, string|null $sortBy = null, bool $circular = false): void
139
    {
140 1
        $pagesAsArray = $pages->toArray();
141 1
        if ($sortBy === null || $sortBy == 'date' || $sortBy == 'updated') {
142 1
            $pagesAsArray = array_reverse($pagesAsArray);
143
        }
144 1
        $count = \count($pagesAsArray);
145 1
        if ($count > 1) {
146 1
            foreach ($pagesAsArray as $position => $page) {
147
                switch ($position) {
148 1
                    case 0: // first
149 1
                        if ($circular) {
150 1
                            $page->setVariables([
151 1
                                'prev' => $pagesAsArray[$count - 1],
152 1
                            ]);
153
                        }
154 1
                        $page->setVariables([
155 1
                            'next' => $pagesAsArray[$position + 1],
156 1
                        ]);
157 1
                        break;
158 1
                    case $count - 1: // last
159 1
                        $page->setVariables([
160 1
                            'prev' => $pagesAsArray[$position - 1],
161 1
                        ]);
162 1
                        if ($circular) {
163 1
                            $page->setVariables([
164 1
                                'next' => $pagesAsArray[0],
165 1
                            ]);
166
                        }
167 1
                        break;
168
                    default:
169 1
                        $page->setVariables([
170 1
                            'prev' => $pagesAsArray[$position - 1],
171 1
                            'next' => $pagesAsArray[$position + 1],
172 1
                        ]);
173 1
                        break;
174
                }
175 1
                $this->generatedPages->add($page);
176
            }
177
        }
178
    }
179
}
180