Passed
Pull Request — 6 (#1291)
by Arnaud
08:00 queued 11s
created

Create::collectPages()   B

Complexity

Conditions 11
Paths 14

Size

Total Lines 83
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 11.5965

Importance

Changes 0
Metric Value
cc 11
eloc 47
c 0
b 0
f 0
nc 14
nop 0
dl 0
loc 83
ccs 39
cts 47
cp 0.8298
crap 11.5965
rs 7.3166

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