Passed
Push — fix-menus ( 1bf5e9...2e9d99 )
by Arnaud
03:10
created

MenusCreate::collectPages()   B

Complexity

Conditions 10
Paths 24

Size

Total Lines 81
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 2 Features 0
Metric Value
cc 10
eloc 46
c 6
b 2
f 0
nc 24
nop 0
dl 0
loc 81
rs 7.3115

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