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