Passed
Pull Request — master (#175)
by Arnaud
08:30 queued 02:17
created

MenuSubscriber::configureDefaultChildren()   B

Complexity

Conditions 10
Paths 38

Size

Total Lines 34
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 0
Metric Value
cc 10
eloc 15
nc 38
nop 2
dl 0
loc 34
ccs 0
cts 0
cp 0
crap 110
rs 7.6666
c 0
b 0
f 0

How to fix   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
namespace LAG\AdminBundle\Event\Subscriber;
4
5
use LAG\AdminBundle\Admin\Helper\AdminHelperInterface;
6
use LAG\AdminBundle\Event\Events;
7
use LAG\AdminBundle\Event\Menu\MenuConfigurationEvent;
8
use LAG\AdminBundle\Exception\Exception;
9
use LAG\AdminBundle\Resource\Registry\ResourceRegistryInterface;
10
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
11
12
class MenuSubscriber implements EventSubscriberInterface
13
{
14
    /**
15
     * @var bool
16
     */
17
    private $menuEnabled;
18
19
    /**
20
     * @var ResourceRegistryInterface
21
     */
22
    private $registry;
23
24
    /**
25
     * @var array
26
     */
27
    private $menuConfigurations;
28
29
    /**
30
     * @var AdminHelperInterface
31 4
     */
32
    private $adminHelper;
33
34 4
    /**
35
     * @return array
36
     */
37
    public static function getSubscribedEvents()
38 8
    {
39
        return [
40 8
            Events::PRE_MENU_CONFIGURATION => 'defineMenuConfiguration',
41 8
        ];
42 8
    }
43 8
44
    public function __construct(
45 6
        bool $menuEnabled,
46
        ResourceRegistryInterface $registry,
47 6
        AdminHelperInterface $adminHelper,
48 2
        array $menuConfigurations = []
49
    ) {
50 4
        $this->menuEnabled = $menuEnabled;
51
        $this->registry = $registry;
52 4
        $this->adminHelper = $adminHelper;
53 2
        $this->menuConfigurations = $menuConfigurations;
54
    }
55 4
56 4
    public function defineMenuConfiguration(MenuConfigurationEvent $event): void
57
    {
58 4
        if (!$this->supports($event)) {
59 2
            return;
60
        }
61 2
        $menuName = $event->getMenuName();
62 2
        $menu = $this->menuConfigurations[$menuName];
63 2
64
        if (null === $menu) {
65
            $menu = [];
66
        }
67
68 4
        if ('left' === $menuName) {
69 4
            $menu = $this->addDefaultLeftMenu($menu);
70
        }
71
72
        if ('top' === $menuName) {
73
            $menu = $this->addDefaultTopMenu($menu);
74 4
        }
75 2
        $menu = $this->configureDefaultChildren($event->getMenuName(), $menu);
76
77 2
        // Set defaults menu configuration to be build
78
        $event->setMenuConfiguration($menu);
79
    }
80
81 2
    private function supports(MenuConfigurationEvent $event): bool
82 2
    {
83
        if (!$this->menuEnabled) {
84
            return false;
85
        }
86 2
87 2
        if (!key_exists($event->getMenuName(), $this->menuConfigurations)) {
88
            return false;
89
        }
90
        $menuConfiguration = $this->menuConfigurations[$event->getMenuName()];
91 2
92
        if (false === $menuConfiguration) {
93
            return false;
94 2
        }
95
96
        return true;
97
    }
98 4
99 4
    private function addDefaultLeftMenu(array $menu): array
100
    {
101
        if (!empty($menu['children'])) {
102
            return $menu;
103
        }
104
        $menu['children'] = [];
105
106
        // The default main menu is composed by links to the list action of each admin resource
107
        foreach ($this->registry->all() as $resourceName => $resource) {
108
            if (empty($resource->getConfiguration()['actions']) || !key_exists('list', $resource->getConfiguration()['actions'])) {
109
                continue;
110
            }
111
            $menu['children'][$resourceName] = [
112
                'admin' => $resourceName,
113
                'action' => 'list',
114
            ];
115
        }
116
117
        return $menu;
118
    }
119
120
    private function configureDefaultChildren(string $menuName, array $menu): array
121
    {
122
        if (empty($menu['children'])) {
123
            $menu['children'] = [];
124
        }
125
126
        foreach ($menu['children'] as $itemName => $itemConfiguration) {
127
            if (null === $itemConfiguration) {
128
                $itemConfiguration = [];
129
            }
130
131
            // When an url is set, nothing to add, the item menu can be build
132
            if (key_exists('url', $itemConfiguration)) {
133
                continue;
134
            }
135
136
            // If the key "admin' is missing, we try to find an admin resource with the same name
137
            if (!key_exists('admin', $itemConfiguration) && $this->registry->has($itemName)) {
138
                $itemConfiguration['admin'] = $itemName;
139
            }
140
141
            // The default admins action is list
142
            if (key_exists('admin', $itemConfiguration) && !key_exists('action', $itemConfiguration)) {
143
                $itemConfiguration['action'] = 'list';
144
            }
145
146
            // At this point, an pair admin/action or an url or an admin should be defined
147
            if (!key_exists('admin', $itemConfiguration)) {
148
                throw new Exception(sprintf('The configuration of the children "%s" in the menu "%s" is invalid : no admin/action nor url configured, and no admin with the name "%s" exists', $itemName, $menuName, $itemName));
149
            }
150
            $menu['children'][$itemName] = $itemConfiguration;
151
        }
152
153
        return $menu;
154
    }
155
156
    private function addDefaultTopMenu(array $menu): array
157
    {
158
        $admin = $this->adminHelper->getCurrent();
159
        $menu['attributes'] = [
160
            'class' => 'navbar-nav mr-auto admin-menu-top',
161
        ];
162
163
        // Auto return link is be optional. It is configured by default for the edit, create and delete actions
164
        if (null !== $admin && $admin->getAction()->getConfiguration()->get('add_return')) {
165
            $menu['children']['return'] = [
166
                'admin' => $admin->getName(),
167
                'action' => 'list',
168
                'text' => $admin->getConfiguration()->getTranslationKey('return'),
169
                'icon' => 'fas fa-arrow-left',
170
            ];
171
        }
172
173
        return $menu;
174
    }
175
}
176