Passed
Pull Request — master (#1704)
by Arnaud
12:40 queued 05:14
created

Section::sortSubPages()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.2098

Importance

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