Passed
Push — i18n ( 25e72b...081ef1 )
by Arnaud
14:17 queued 10:36
created

MenusCreate::collectPages()   C

Complexity

Conditions 13
Paths 44

Size

Total Lines 94
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 14.5988

Importance

Changes 5
Bugs 3 Features 1
Metric Value
cc 13
eloc 51
c 5
b 3
f 1
nc 44
nop 0
dl 0
loc 94
ccs 41
cts 52
cp 0.7885
crap 14.5988
rs 6.6166

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
        // creates a 'menus' collection for each language, with a default 'main' menu
44 1
        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 1
            $this->menus[$lang]->add(new Menu('main'));
48
        }
49
50
        // collects 'menu' entries from pages
51 1
        $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
         */
65 1
        foreach ($this->config->getLanguages() as $language) {
66 1
            if ($menusConfig = $this->builder->getConfig()->get('menus', $language['code'], false)) {
67 1
                $this->builder->getLogger()->debug('Creating config menus');
68
69 1
                $totalConfig = array_sum(array_map('count', $menusConfig));
70 1
                $countConfig = 0;
71 1
                $lang = $language['code'] == $this->config->getLanguageDefault() ? null : $language['code'];
72
73 1
                foreach ($menusConfig as $menuConfig => $entry) {
74 1
                    if (!$this->menus[$lang]->has($menuConfig)) {
75
                        $this->menus[$lang]->add(new Menu($menuConfig));
76
                    }
77
                    /** @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 1
                        $enabled = true;
82 1
                        $updated = false;
83
84
                        // ID is required
85 1
                        if (!array_key_exists('id', $property)) {
86
                            throw new Exception(sprintf('"id" is required for menu entry "%s"', $key));
87
                        }
88
                        // enabled?
89 1
                        if (array_key_exists('enabled', $property) && false === $property['enabled']) {
90 1
                            $enabled = false;
91 1
                            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
                        }
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('%s > %s (removed)', $menu, $property['id']);
103 1
                                $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
104
105 1
                                continue;
106
                            }
107
                            // merges properties
108 1
                            $updated = true;
109 1
                            $current = $menu->get($property['id'])->toArray();
110 1
                            $property = array_merge($current, $property);
111
112 1
                            $message = sprintf('%s > %s (updated)', $menu, $property['id']);
113 1
                            $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
114
                        }
115
                        // 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 1
                                ->setWeight($property['weight'] ?? 0);
121 1
                            $menu->add($item);
122
123 1
                            if (!$updated) {
124 1
                                $message = sprintf('%s > %s', $menu, $property['id']);
125 1
                                $this->builder->getLogger()->info($message, ['progress' => [$countConfig, $totalConfig]]);
126
                            }
127
                        }
128
                    }
129
                }
130
            }
131
        }
132
133 1
        $this->builder->setMenus($this->menus);
134 1
    }
135
136
    /**
137
     * Collects pages with a menu variable.
138
     */
139 1
    protected function collectPages()
140
    {
141 1
        $count = 0;
142
143
        $filteredPages = $this->builder->getPages()->filter(function (Page $page) {
144 1
            return $page->hasVariable('menu') && $page->getVariable('published');
145 1
        });
146
147 1
        $total = count($filteredPages);
148
149 1
        if ($total > 0) {
150 1
            $this->builder->getLogger()->debug('Creating pages menus');
151
        }
152
153
        /** @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 1
            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
                    }
176 1
                    if (!is_string($menuName)) {
177
                        $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 1
                    $item = (new Entry($page->getIdWithoutLang()))
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
                    }
194
                    // checks if page's language exists
195 1
                    if (!array_key_exists($lang, $this->menus)) {
196
                        if ($lang === null) {
197
                            throw new Exception('The default language is not correctly defined in config.');
198
                        }
199
200
                        throw new Exception(sprintf('Language "%s" is not defined in config.', $lang));
201
                    }
202
                    // add Menu if not exists
203 1
                    if (!$this->menus[$lang]->has($menuName)) {
204 1
                        $this->menus[$lang]->add(new Menu($menuName));
205
                    }
206
                    /** @var \Cecil\Collection\Menu\Menu $menu */
207 1
                    $menu = $this->menus[$lang]->get($menuName);
208 1
                    $menu->add($item);
209
210 1
                    $message = sprintf('%s > %s (weight: %s)', $menuName, $page->getId(), $weight ?? 'N/A');
211 1
                    $this->builder->getLogger()->info($message, ['progress' => [$count, $total]]);
212
                }
213 1
                continue;
214
            }
215
            /**
216
             * String case.
217
             *
218
             * ie:
219
             *   menu: main
220
             */
221 1
            $item = (new Entry($page->getId()))
222 1
                ->setName($page->getVariable('title'))
223 1
                ->setUrl($page->getUrl());
224 1
            if (!$this->menus[$lang]->has($page->getVariable('menu'))) {
225
                $this->menus[$lang]->add(new Menu($page->getVariable('menu')));
226
            }
227
            /** @var \Cecil\Collection\Menu\Menu $menu */
228 1
            $menu = $this->menus[$lang]->get($page->getVariable('menu'));
229 1
            $menu->add($item);
230
231 1
            $message = sprintf('%s > %s', $page->getVariable('menu'), $page->getId());
232 1
            $this->builder->getLogger()->info($message, ['progress' => [$count, $total]]);
233
        }
234 1
    }
235
}
236