Passed
Push — chore/code ( 0ac777...ef052a )
by Arnaud
03:15
created

Create::process()   D

Complexity

Conditions 16
Paths 192

Size

Total Lines 90
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 42
CRAP Score 16.1685

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 16
eloc 45
c 1
b 0
f 0
nc 192
nop 0
dl 0
loc 90
ccs 42
cts 46
cp 0.913
crap 16.1685
rs 4.8

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\Step\Menus;
15
16
use Cecil\Collection\Menu\Collection as MenusCollection;
17
use Cecil\Collection\Menu\Entry;
18
use Cecil\Collection\Menu\Menu;
19
use Cecil\Collection\Page\Page;
20
use Cecil\Exception\RuntimeException;
21
use Cecil\Logger\PrintLogger;
22
use Cecil\Renderer\Page as PageRenderer;
23
use Cecil\Step\AbstractStep;
24
25
/**
26
 * Creates menus collection.
27
 */
28
class Create extends AbstractStep
29
{
30
    /** @var array */
31
    protected $menus;
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 1
    public function getName(): string
37
    {
38 1
        return 'Creating menus';
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     *
44 1
     * @throws RuntimeException
45
     */
46 1
    public function process(): void
47 1
    {
48
        // creates a 'menus' collection for each language, with a default 'main' menu
49 1
        foreach ($this->config->getLanguages() as $language) {
50
            $this->menus[$language['code']] = new MenusCollection('menus');
51
            $this->menus[$language['code']]->add(new Menu('main'));
52
        }
53
54
        // collects 'menu' entries from pages
55
        $this->collectPages();
56 1
57
        /**
58
         * Removing/adding/replacing menus entries from config.
59 1
         * ie:
60 1
         *   menus:
61 1
         *     main:
62
         *       - id: example
63
         *         name: "Example"
64
         *         url: https://example.com
65 1
         *         weight: 999
66
         *       - id: about
67
         *         enabled: false.
68
         */
69
        foreach ($this->config->getLanguages() as $language) {
70
            if ($menusConfig = (array) $this->config->get('menus', $language['code'], false)) {
71
                $totalConfig = array_sum(array_map('count', $menusConfig));
72
                $countConfig = 0;
73
                $suffix = $language['code'] !== $this->config->getLanguageDefault() ? '.'.$language['code'] : '';
74
75
                foreach ($menusConfig as $menuConfig => $entry) {
76
                    // add Menu if not exists
77
                    if (!$this->menus[$language['code']]->has($menuConfig)) {
78
                        $this->menus[$language['code']]->add(new Menu($menuConfig));
79 1
                    }
80 1
                    /** @var \Cecil\Collection\Menu\Menu $menu */
81 1
                    $menu = $this->menus[$language['code']]->get($menuConfig);
82 1
                    foreach ($entry as $key => $property) {
83 1
                        $countConfig++;
84
                        $enabled = true;
85 1
                        $updated = false;
86
87 1
                        // ID is required
88
                        if (!isset($property['id'])) {
89
                            throw new RuntimeException(\sprintf('"id" is required for entry at position %s in "%s" menu', $key, $menu));
90
                        }
91 1
                        // enabled?
92 1
                        if (isset($property['enabled']) && false === $property['enabled']) {
93 1
                            $enabled = false;
94 1
                            if (!$menu->has($property['id'])) {
95 1
                                $message = \sprintf('Config menu entry "%s > %s%s" disabled', (string) $menu, $property['id'], $suffix);
96
                                $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
97
                            }
98 1
                        }
99
                        // is entry already exists?
100
                        if ($menu->has($property['id'])) {
101
                            // removes a disabled entry
102 1
                            if (!$enabled) {
103 1
                                $menu->remove($property['id']);
104 1
105
                                $message = \sprintf('Config menu entry "%s > %s%s" removed', (string) $menu, $property['id'], $suffix);
106
                                $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
107
                                continue;
108
                            }
109
                            // merges properties
110 1
                            $updated = true;
111
                            $current = $menu->get($property['id'])->toArray();
112 1
                            $property = array_merge($current, $property);
113 1
114
                            $message = \sprintf('Config menu entry "%s > %s%s" updated', (string) $menu, $property['id'], $suffix);
115 1
                            $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
116 1
                        }
117 1
                        // adds/replaces entry
118
                        if ($enabled) {
119
                            $item = (new Entry($property['id']))
120 1
                                ->setName($property['name'] ?? ucfirst($property['id']))
121 1
                                ->setUrl($property['url'] ?? '/404')
122 1
                                ->setWeight($property['weight'] ?? 0);
123
                            $menu->add($item);
124 1
125 1
                            if (!$updated) {
126
                                $message = \sprintf('Config menu entry "%s > %s%s" created', (string) $menu, $property['id'], $suffix);
127
                                $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
128 1
                            }
129 1
                        }
130 1
                    }
131 1
                }
132 1
            }
133 1
        }
134
135 1
        $this->builder->setMenus($this->menus);
136 1
    }
137 1
138
    /**
139
     * Collects pages with a menu variable.
140
     */
141
    protected function collectPages(): void
142
    {
143
        $filteredPages = $this->builder->getPages()->filter(function (Page $page) {
144
            return $page->hasVariable('menu')
145 1
                && $page->getVariable('published')
146 1
                && in_array($page->getVariable('language') ?? $this->config->getLanguageDefault(), array_column($this->config->getLanguages(), 'code'));
147
        });
148
149
        $total = count($filteredPages);
150
        $count = 0;
151 1
        /** @var \Cecil\Collection\Page\Page $page */
152
        foreach ($filteredPages as $page) {
153
            $count++;
154 1
            $language = $page->getVariable('language') ?? $this->config->getLanguageDefault();
155 1
            /**
156 1
             * Array case.
157 1
             *
158
             * ie 1:
159 1
             *   menu: [main, navigation]
160 1
             * ie 2:
161
             *   menu:
162 1
             *     main:
163 1
             *       weight: 999
164 1
             */
165
            if (is_array($page->getVariable('menu'))) {
166
                foreach ($page->getVariable('menu') as $key => $value) {
167
                    $menuName = $key;
168
                    $property = $value;
169
                    $weight = null;
170
                    if (is_int($key)) {
171
                        $menuName = $value;
172
                        $property = null;
173
                    }
174
                    if (!is_string($menuName)) {
175 1
                        $this->builder->getLogger()->error(
176 1
                            \sprintf(
177 1
                                'Menu\'s name of page "%s" must be a string, not "%s"',
178 1
                                $page->getId(),
179 1
                                PrintLogger::format($menuName)
180 1
                            ),
181 1
                            ['progress' => [$count, $total]]
182 1
                        );
183
                        continue;
184 1
                    }
185
                    $item = (new Entry($page->getIdWithoutLang()))
186
                        ->setName($page->getVariable('title'))
187
                        ->setUrl((new PageRenderer($this->config))->getUrl($page));
188
                    if (isset($property['weight'])) {
189
                        $weight = $property['weight'];
190
                        $item->setWeight($property['weight']);
191
                    }
192
                    // add Menu if not exists
193
                    if (!$this->menus[$language]->has($menuName)) {
194
                        $this->menus[$language]->add(new Menu($menuName));
195 1
                    }
196 1
                    /** @var \Cecil\Collection\Menu\Menu $menu */
197 1
                    $menu = $this->menus[$language]->get($menuName);
198 1
                    $menu->add($item);
199 1
200 1
                    $message = \sprintf('Page menu entry "%s > %s" created (weight: %s)', $menuName, $page->getId(), $weight ?? 'N/A');
201
                    $this->builder->getLogger()->info($message, ['progress' => [$count, $total]]);
202
                }
203 1
                continue;
204 1
            }
205
            /**
206
             * String case.
207 1
             *
208 1
             * ie:
209
             *   menu: main
210 1
             */
211 1
            $item = (new Entry($page->getIdWithoutLang()))
212
                ->setName($page->getVariable('title'))
213 1
                ->setUrl((new PageRenderer($this->config))->getUrl($page));
214
            // add Menu if not exists
215
            if (!$this->menus[$language]->has($page->getVariable('menu'))) {
216
                $this->menus[$language]->add(new Menu($page->getVariable('menu')));
217
            }
218
            /** @var \Cecil\Collection\Menu\Menu $menu */
219
            $menu = $this->menus[$language]->get($page->getVariable('menu'));
220
            $menu->add($item);
221 1
222 1
            $message = \sprintf('Page menu entry "%s > %s" created', $page->getVariable('menu'), $page->getId());
223 1
            $this->builder->getLogger()->info($message, ['progress' => [$count, $total]]);
224
        }
225 1
    }
226
}
227