Completed
Pull Request — master (#244)
by Łukasz
11:47
created

MainMenuListener::populateMenu()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
cc 5
eloc 16
nc 7
nop 2
1
<?php
2
3
namespace FSi\Bundle\AdminBundle\EventListener;
4
5
use FSi\Bundle\AdminBundle\Admin\ManagerInterface;
6
use FSi\Bundle\AdminBundle\Event\MenuEvent;
7
use FSi\Bundle\AdminBundle\Menu\Builder\Exception\InvalidYamlStructureException;
8
use FSi\Bundle\AdminBundle\Menu\Item\ElementItem;
9
use FSi\Bundle\AdminBundle\Menu\Item\Item;
10
use Symfony\Component\Yaml\Yaml;
11
12
class MainMenuListener
13
{
14
    /**
15
     * @var string
16
     */
17
    private $configFilePath;
18
19
    /**
20
     * @var Yaml
21
     */
22
    private $yaml;
23
24
    /**
25
     * @var ManagerInterface
26
     */
27
    private $manager;
28
29
    /**
30
     * @param ManagerInterface $manager
31
     * @param string $configFilePath
32
     */
33
    public function __construct(ManagerInterface $manager, $configFilePath)
34
    {
35
        $this->configFilePath = $configFilePath;
36
        $this->yaml = new Yaml();
37
        $this->manager = $manager;
38
    }
39
40
    /**
41
     * @param MenuEvent $event
42
     * @return Item
43
     * @throws InvalidYamlStructureException
44
     */
45
    public function createMainMenu(MenuEvent $event)
46
    {
47
        $config = $this->yaml->parse(file_get_contents($this->configFilePath), true, true);
48
49
        if (!isset($config['menu'])) {
50
            throw new InvalidYamlStructureException(
51
                sprintf('File "%s" should contain top level "menu:" key', $this->configFilePath)
52
            );
53
        }
54
55
        $menu = $event->getMenu();
56
        $menu->setOptions(array(
57
            'attr' => array(
58
                'id' => 'top-menu',
59
                'class' => 'nav navbar-nav',
60
            )
61
        ));
62
63
        $this->populateMenu($menu, $config['menu']);
64
65
        return $menu;
66
    }
67
68
    private function populateMenu(Item $menu, array $configs)
69
    {
70
        foreach ($configs as $itemConfig) {
71
            $item = $this->buildSingleItem($itemConfig);
72
73
            if (null !== $item) {
74
                $options = array(
75
                    'attr' => array(
76
                        'class' => 'admin-element'
77
                    )
78
                );
79
                $options['elements'] = $this->buildItemElements($itemConfig);
80
                $item->setOptions($options);
81
            }
82
83
            if (null === $item) {
84
                if ($this->isSingleItem($itemConfig)) {
85
                    continue;
86
                }
87
                $item = new Item(key($itemConfig));
88
                $group = array_values($itemConfig);
89
                $this->populateMenu($item, $group[0]);
90
            }
91
92
            $menu->addChild($item);
93
        }
94
    }
95
96
    private function buildSingleItem($itemConfig)
97
    {
98
        if (is_string($itemConfig)) {
99
            if ($this->manager->hasElement($itemConfig)) {
100
                return new ElementItem($itemConfig, $this->manager->getElement($itemConfig));
101
            }
102
103
            return new Item($itemConfig);
104
        }
105
106
        if (!$this->isSingleItem($itemConfig) || !$this->manager->hasElement($itemConfig['id'])) {
107
            return null;
108
        }
109
110
        return new ElementItem(
111
            ($this->hasEntry($itemConfig, 'name')) ? $itemConfig['name'] : $itemConfig['id'],
112
            $this->manager->getElement($itemConfig['id'])
113
        );
114
    }
115
116
    private function isSingleItem($itemConfig)
117
    {
118
        return $this->hasEntry($itemConfig, 'id');
119
    }
120
121
    private function hasEntry($itemConfig, $keyName)
122
    {
123
        return is_array($itemConfig) && array_key_exists($keyName, $itemConfig);
124
    }
125
126
    /**
127
     * @param array $itemConfig
128
     * @return mixed
129
     */
130
    private function buildItemElements($itemConfig)
131
    {
132
        $elements = array();
133
134
        if ($this->hasEntry($itemConfig, 'elements')) {
135
            $elementIds = (array)$itemConfig['elements'];
136
            foreach ($elementIds as $elementId) {
137
                $elements[] = $this->manager->getElement($elementId);
138
            }
139
        }
140
141
        return $elements;
142
    }
143
}
144