Passed
Push — fix ( 2bd68f )
by Arnaud
03:48
created

MenusCreate::collectPages()   C

Complexity

Conditions 12
Paths 28

Size

Total Lines 88
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 12.627

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 12
eloc 49
c 3
b 1
f 0
nc 28
nop 0
dl 0
loc 88
ccs 41
cts 49
cp 0.8367
crap 12.627
rs 6.9666

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