Completed
Push — refonte ( fceb40...2ff6c8 )
by Arnaud
20:25 queued 18:21
created

MenuFactory::addExtraMenuItemConfiguration()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 9.2088
c 0
b 0
f 0
cc 5
nc 9
nop 1
1
<?php
2
3
namespace LAG\AdminBundle\Factory;
4
5
use LAG\AdminBundle\Configuration\ApplicationConfigurationStorage;
6
use LAG\AdminBundle\Configuration\MenuConfiguration;
7
use LAG\AdminBundle\Configuration\MenuItemConfiguration;
8
use LAG\AdminBundle\Exception\Exception;
9
use LAG\AdminBundle\Menu\Menu;
10
use LAG\AdminBundle\Menu\MenuItem;
11
use LAG\AdminBundle\Routing\RoutingLoader;
12
use Symfony\Component\HttpFoundation\RequestStack;
13
use Symfony\Component\OptionsResolver\OptionsResolver;
14
15
class MenuFactory
16
{
17
    /**
18
     * @var Menu[]
19
     */
20
    private $menus = [];
21
22
    /**
23
     * @var RequestStack
24
     */
25
    private $requestStack;
26
27
    /**
28
     * @var \LAG\AdminBundle\Configuration\ApplicationConfiguration
29
     */
30
    private $applicationConfiguration;
31
32
    public function __construct(
33
        RequestStack $requestStack,
34
        ApplicationConfigurationStorage $applicationConfigurationStorage
35
    ){
36
        $this->requestStack = $requestStack;
37
        $this->applicationConfiguration = $applicationConfigurationStorage->getConfiguration();
38
    }
39
40
    /**
41
     * Create a menu item from a configuration array.
42
     *
43
     * @param string $name
44
     * @param array  $configuration
45
     *
46
     * @return Menu
47
     */
48
    public function create(string $name, array $configuration)
49
    {
50
        $resolver = new OptionsResolver();
51
        $menuConfiguration = new MenuConfiguration($name, $this->applicationConfiguration->getParameter('title'));
52
        $menuConfiguration->configureOptions($resolver);
53
54
        $menuConfiguration->setParameters($resolver->resolve($configuration));
55
        $menu = new Menu($name, $menuConfiguration);
56
57
        foreach ($menuConfiguration->getParameter('items') as $itemName => $item) {
58
            $menu->addItem($this->createMenuItem($itemName, $item, $menuConfiguration));
59
        }
60
        $this->menus[$name] = $menu;
61
62
        return $menu;
63
    }
64
65
    /**
66
     * Create a menu item according to the given configuration.
67
     *
68
     * @param string            $name
69
     * @param array             $configuration
70
     * @param MenuConfiguration $parentConfiguration
71
     *
72
     * @return MenuItem
73
     */
74
    public function createMenuItem(string $name, array $configuration, MenuConfiguration $parentConfiguration): MenuItem
75
    {
76
        // Resolve configuration for the current item
77
        $resolver = new OptionsResolver();
78
        $menuItemConfiguration = new MenuItemConfiguration($name, $parentConfiguration->getParameter('position'));
79
        $menuItemConfiguration->configureOptions($resolver);
80
        $resolvedConfiguration = $resolver->resolve($configuration);
81
82
        if ($this->applicationConfiguration->getParameter('enable_extra_configuration')) {
83
            $this->addExtraMenuItemConfiguration($resolvedConfiguration);
84
        }
85
        $menuItemConfiguration->setParameters($resolvedConfiguration);
86
87
        return new MenuItem($menuItemConfiguration);
88
    }
89
90
    /**
91
     * Return true if the menu exists.
92
     *
93
     * @param string $name
94
     *
95
     * @return bool
96
     */
97
    public function hasMenu(string $name): bool
98
    {
99
        return array_key_exists($name, $this->menus);
100
    }
101
102
    /**
103
     * Return a menu with the given name.
104
     *
105
     * @param string $name
106
     *
107
     * @return Menu
108
     *
109
     * @throws Exception
110
     */
111
    public function getMenu(string $name): Menu
112
    {
113
        if (!$this->hasMenu($name)) {
114
            throw new Exception('Invalid menu name "'.$name.'"');
115
        }
116
117
        return $this->menus[$name];
118
    }
119
120
    /**
121
     * Return all the menus.
122
     *
123
     * @return Menu[]
124
     */
125
    public function getMenus(): array
126
    {
127
        return $this->menus;
128
    }
129
130
    private function addExtraMenuItemConfiguration(&$resolvedConfiguration)
131
    {
132
        // Determine the current route to add an active css class if the current item route is the current route
133
        $route = $this->requestStack->getCurrentRequest()->attributes->get('_route');
134
        $itemRoute = null;
135
136
        // A route string is not required, an admin and an action can also be provided
137
        if ($resolvedConfiguration['route']) {
138
            $itemRoute = $resolvedConfiguration['route'];
139
        } else if (key_exists('admin', $resolvedConfiguration)) {
140
            $itemRoute = RoutingLoader::generateRouteName(
141
                $resolvedConfiguration['admin'],
142
                $resolvedConfiguration['action'],
143
                $this->applicationConfiguration->getParameter('routing_name_pattern')
144
            );
145
        }
146
147
        // Add an "active" css class dor the current route
148
        if ($route === $itemRoute) {
149
            if (!key_exists('class', $resolvedConfiguration['attr'])) {
150
                $resolvedConfiguration['attr']['class'] = '';
151
            }
152
            $resolvedConfiguration['attr']['class'] .= ' active';
153
        }
154
    }
155
}
156