Completed
Push — dev ( 5ca438...ffa11e )
by Arnaud
04:26
created

MenuFactory::createMenuItemConfiguration()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 45
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 11.3004

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 45
ccs 5
cts 9
cp 0.5556
rs 6.7272
cc 7
eloc 25
nc 6
nop 2
crap 11.3004
1
<?php
2
3
namespace LAG\AdminBundle\Menu\Factory;
4
5
use Exception;
6
use Knp\Menu\FactoryInterface;
7
use Knp\Menu\ItemInterface;
8
use LAG\AdminBundle\Admin\Behaviors\TranslationKeyTrait;
9
use LAG\AdminBundle\Admin\Factory\AdminFactory;
10
use LAG\AdminBundle\Configuration\Factory\ConfigurationFactory;
11
use LAG\AdminBundle\Menu\Configuration\MenuConfiguration;
12
use LAG\AdminBundle\Menu\Configuration\MenuItemConfiguration;
13
use Symfony\Component\OptionsResolver\OptionsResolver;
14
use Symfony\Component\PropertyAccess\PropertyAccess;
15
use Symfony\Component\Translation\TranslatorInterface;
16
17
/**
18
 * Create KNP menus from given options.
19
 */
20
class MenuFactory
21
{
22
    use TranslationKeyTrait;
23
24
    /**
25
     * @var AdminFactory
26
     */
27
    protected $adminFactory;
28
29
    /**
30
     * @var FactoryInterface
31
     */
32
    protected $menuFactory;
33
34
    /**
35
     * @var ConfigurationFactory
36
     */
37
    protected $configurationFactory;
38
39
    /**
40
     * @var TranslatorInterface
41
     */
42
    protected $translator;
43
44
    /**
45
     * MenuBuilder constructor.
46
     *
47
     * @param FactoryInterface $menuFactory
48
     * @param AdminFactory $adminFactory
49
     * @param ConfigurationFactory $configurationFactory
50
     * @param TranslatorInterface $translator
51 2
     */
52
    public function __construct(
53
        FactoryInterface $menuFactory,
54
        AdminFactory $adminFactory,
55
        ConfigurationFactory $configurationFactory,
56
        TranslatorInterface $translator
57 2
    ) {
58 2
        $this->adminFactory = $adminFactory;
59 2
        $this->menuFactory = $menuFactory;
60 2
        $this->configurationFactory = $configurationFactory;
61 2
        $this->translator = $translator;
62
    }
63
64
    /**
65
     * Create a menu according to the given configuration.
66
     *
67
     * @param string $name
68
     * @param array $configuration
69
     * @param null $entity
70 2
     * @return ItemInterface
71
     */
72 2
    public function create($name, array $configuration, $entity = null)
73 2
    {
74 2
        // resolve menu configuration. It will return a MenuConfiguration with MenuItemConfiguration object
75 2
        $resolver = new OptionsResolver();
76
        $menuConfiguration = new MenuConfiguration();
77
        $menuConfiguration->configureOptions($resolver);
78 2
        $menuConfiguration->setParameters($resolver->resolve($configuration));
79 2
80 2
        // create knp menu
81
        $menu = $this
82
            ->menuFactory
83
            ->createItem($name, [
84
                'childrenAttributes' => $menuConfiguration->getParameter('attr')
85
            ]);
86
87 2
        /**
88
         * @var string $itemName
89 1
         * @var MenuItemConfiguration $itemConfiguration
90
         */
91
        foreach ($menuConfiguration->getParameter('items') as $itemName => $itemConfiguration) {
92 1
            // guess item text from configuration
93 1
            $text = $this->guessItemText($itemName, $itemConfiguration);
94
95
            // item children
96 1
            $subItems = $itemConfiguration->getParameter('items');
97
            $hasChildren = count($subItems);
98 1
99 1
            // create menu item configuration (link attributes, icon, route...)
100
            $menuItemConfiguration = $this->createMenuItemConfiguration($itemConfiguration, $entity);
101
102 1
            if ($hasChildren) {
103
                $menuItemConfiguration['childrenAttributes']['class'] = 'nav nav-second-level collapse';
104 1
            }
105
106 1
            // add to knp menu
107 1
            $menu->addChild($text, $menuItemConfiguration);
108
109 1
            if ($hasChildren) {
110 1
111
                foreach ($subItems as $subItemName => $subItemConfiguration) {
112
                    $subMenuItemConfiguration = $this->createMenuItemConfiguration($subItemConfiguration);
113
114
                    $menu[$text]->addChild(
115
                        $this->guessItemText($subItemName, $subItemConfiguration),
116
                        $subMenuItemConfiguration
117 2
                    );
118
                }
119
            }
120
        }
121
122
        return $menu;
123
    }
124
125
    /**
126
     * Guess an item text according to the configuration.
127 1
     *
128
     * @param string $name
129 1
     * @param MenuItemConfiguration $itemConfiguration
130
     * @return string
131 1
     */
132
    protected function guessItemText($name, MenuItemConfiguration $itemConfiguration)
133
    {
134
        $text = $itemConfiguration->getParameter('text');
135
136 1
        if ($text) {
137
            return $text;
138
        }
139
140
        // if an admin is defined, we get the text using the translation pattern and the admin action's name
141
        if ($admin = $itemConfiguration->getParameter('admin')) {
142
            $translationPattern = $this
143
                ->configurationFactory
144
                ->getApplicationConfiguration()
145 1
                ->getParameter('translation')['pattern'];
146
            $action = $itemConfiguration->getParameter('action');
147
148 1
            $text = $this->getTranslationKey($translationPattern, $action, $admin);
149
        } else {
150
            $text = $name;
151
        }
152
153
        return $text;
154
    }
155
156
157
    /**
158
     * Create a knp menu item configuration from the configured options.
159 1
     *
160
     * @param MenuItemConfiguration $itemConfiguration
161
     * @param null $entity
162 1
     * @return array
163 1
     * @throws Exception
164
     */
165 1
    protected function createMenuItemConfiguration(MenuItemConfiguration $itemConfiguration, $entity = null)
166
    {
167
        $menuItemConfiguration = [
168
            // configured <a> tag attributes
169 1
            'linkAttributes' => $itemConfiguration->getParameter('attr'),
170
            'routeParameters' => $itemConfiguration->getParameter('parameters'),
171
            'attributes' => [
172
                'icon' => $itemConfiguration->getParameter('icon'),
173
            ]
174
        ];
175
176 1
        // add parameters value from entity
177
        if ($entity && count($menuItemConfiguration['routeParameters'])) {
178
            $routeParameters = [];
179
180
            foreach ($menuItemConfiguration['routeParameters'] as $name => $value) {
181 1
182
                if ($value === null) {
183
                    // get value from current entity
184 1
                    $propertyAccessor = PropertyAccess::createPropertyAccessor();
185
                    $routeParameters[$name] = $propertyAccessor->getValue($entity, $name);
186
                } else {
187
                    $routeParameters[$name] = $value;
188
                }
189
            }
190
            $menuItemConfiguration['routeParameters'] = $routeParameters;
191
        }
192
193
        if ($adminName = $itemConfiguration->getParameter('admin')) {
194
            // retrieve an existing admin
195
            $admin = $this
196
                ->adminFactory
197
                ->getAdmin($adminName);
198
199
            $menuItemConfiguration['route'] = $admin->generateRouteName($itemConfiguration->getParameter('action'));
200
        } else if ($route = $itemConfiguration->getParameter('route')) {
201
            // route is provided so we take it
202
            $menuItemConfiguration['route'] = $route;
203
        } else {
204
            // if no admin and no route is provided, we take the url. In knp configuration, the url parameter is uri
205
            $menuItemConfiguration['uri'] = $itemConfiguration->getParameter('url');
206
        }
207
208
        return $menuItemConfiguration;
209
    }
210
}
211