Passed
Pull Request — master (#1704)
by Arnaud
08:32 queued 03:26
created

Section::generate()   F

Complexity

Conditions 18
Paths 655

Size

Total Lines 78
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 45
CRAP Score 18.0033

Importance

Changes 5
Bugs 2 Features 0
Metric Value
cc 18
eloc 45
c 5
b 2
f 0
nc 655
nop 0
dl 0
loc 78
ccs 45
cts 46
cp 0.9783
crap 18.0033
rs 1.1791

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
                    $pages = new PagesCollection("section-$pageId", $pagesAsArray);
66
                    // cascade variables
67 1
                    if ($page->hasVariable('cascade')) {
68 1
                        $cascade = $page->getVariable('cascade');
69 1
                        $pages->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 = self::sortSubPages($page, $pages);
79
                    // adds navigation links (excludes taxonomy pages)
80 1
                    $sortby = $page->getVariable('sortby')['variable'] ?? (string) $page->getVariable('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'));
83
                    }
84
                    // creates page for each section
85 1
                    $page->setType(Type::SECTION)
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 $e) {
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(Page $page, PagesCollection $pages): PagesCollection
115
    {
116
        // sorts (by date by default)
117 1
        $pages = $pages->sortByDate();
118
        /*
119
         * sortby: date|updated|title|weight
120
         *
121
         * sortby:
122
         *   variable: date|updated
123
         *   desc_title: false|true
124
         *   reverse: false|true
125
         */
126 1
        if ($page->hasVariable('sortby')) {
127 1
            $sortby = (string) $page->getVariable('sortby');
128
            // options?
129 1
            $sortby = $page->getVariable('sortby')['variable'] ?? $sortby;
130 1
            $descTitle = $page->getVariable('sortby')['desc_title'] ?? false;
131 1
            $reverse = $page->getVariable('sortby')['reverse'] ?? false;
132
            // sortby: date, title or weight
133 1
            $sortMethod = sprintf('sortBy%s', ucfirst(str_replace('updated', 'date', $sortby)));
134 1
            if (!method_exists($pages, $sortMethod)) {
135
                throw new RuntimeException(sprintf('In "%s" "%s" is not a valid value for "sortby" variable.', $page->getId(), $sortby));
136
            }
137
138 1
            return $pages->$sortMethod(['variable' => $sortby, 'descTitle' => $descTitle, 'reverse' => $reverse]);
139
        }
140
141 1
        return $pages;
142
    }
143
144
    /**
145
     * Adds navigation (next and prev) to section subpages.
146
     */
147 1
    protected function addNavigationLinks(PagesCollection $pages, string $sort = null, $circular = false): void
148
    {
149 1
        $pagesAsArray = $pages->toArray();
150 1
        if ($sort === null || $sort == 'date' || $sort == 'updated') {
151
            $pagesAsArray = array_reverse($pagesAsArray);
152
        }
153 1
        $count = \count($pagesAsArray);
154 1
        if ($count > 1) {
155 1
            foreach ($pagesAsArray as $position => $page) {
156
                switch ($position) {
157 1
                    case 0: // first
158 1
                        if ($circular) {
159 1
                            $page->setVariables([
160 1
                                'prev' => $pagesAsArray[$count - 1],
161 1
                            ]);
162
                        }
163 1
                        $page->setVariables([
164 1
                            'next' => $pagesAsArray[$position + 1],
165 1
                        ]);
166 1
                        break;
167 1
                    case $count - 1: // last
168 1
                        $page->setVariables([
169 1
                            'prev' => $pagesAsArray[$position - 1],
170 1
                        ]);
171 1
                        if ($circular) {
172 1
                            $page->setVariables([
173 1
                                'next' => $pagesAsArray[0],
174 1
                            ]);
175
                        }
176 1
                        break;
177
                    default:
178 1
                        $page->setVariables([
179 1
                            'prev' => $pagesAsArray[$position - 1],
180 1
                            'next' => $pagesAsArray[$position + 1],
181 1
                        ]);
182 1
                        break;
183
                }
184 1
                $this->generatedPages->add($page);
185
            }
186
        }
187
    }
188
}
189