Passed
Push — menu ( 2d5a28...71d6bb )
by Arnaud
04:12
created

MenusCreate::process()   F

Complexity

Conditions 17
Paths 288

Size

Total Lines 93
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 17.1781

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 17
eloc 47
c 1
b 1
f 0
nc 288
nop 0
dl 0
loc 93
ccs 43
cts 47
cp 0.9149
crap 17.1781
rs 3.2833

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