Completed
Pull Request — master (#90)
by Arnaud
02:26
created

MenuFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 4
crap 2
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\Registry\Registry;
10
use LAG\AdminBundle\Configuration\Factory\ConfigurationFactory;
11
use LAG\AdminBundle\Menu\Configuration\MenuConfiguration;
12
use LAG\AdminBundle\Menu\Configuration\MenuItemConfiguration;
13
use LAG\AdminBundle\Routing\RouteNameGenerator;
14
use Symfony\Component\OptionsResolver\OptionsResolver;
15
use Symfony\Component\PropertyAccess\PropertyAccess;
16
use Symfony\Component\Translation\TranslatorInterface;
17
18
/**
19
 * Create KNP menus from given options.
20
 */
21
class MenuFactory
22
{
23
    use TranslationKeyTrait;
24
25
    /**
26
     * @var Registry
27
     */
28
    protected $registry;
29
30
    /**
31
     * @var FactoryInterface
32
     */
33
    protected $menuFactory;
34
35
    /**
36
     * @var ConfigurationFactory
37
     */
38
    protected $configurationFactory;
39
40
    /**
41
     * @var TranslatorInterface
42
     */
43
    protected $translator;
44
45
    /**
46
     * MenuBuilder constructor.
47
     *
48
     * @param FactoryInterface $menuFactory
49
     * @param Registry $registry
50
     * @param ConfigurationFactory $configurationFactory
51
     * @param TranslatorInterface $translator
52
     */
53
    public function __construct(
54
        FactoryInterface $menuFactory,
55
        Registry $registry,
56
        ConfigurationFactory $configurationFactory,
57
        TranslatorInterface $translator
58
    ) {
59
        $this->registry = $registry;
60
        $this->menuFactory = $menuFactory;
61
        $this->configurationFactory = $configurationFactory;
62
        $this->translator = $translator;
63
    }
64
65
    /**
66
     * Create a menu according to the given configuration.
67
     *
68
     * @param string $name
69
     * @param array $configuration
70
     * @param null $entity
71
     * @return ItemInterface
72
     */
73
    public function create($name, array $configuration, $entity = null)
74
    {
75
        // resolve menu configuration. It will return a MenuConfiguration with MenuItemConfiguration object
76
        $resolver = new OptionsResolver();
77
        $menuConfiguration = new MenuConfiguration();
78
        $menuConfiguration->configureOptions($resolver);
79
        $menuConfiguration->setParameters($resolver->resolve($configuration));
80
81
        // create knp menu
82
        $menu = $this
83
            ->menuFactory
84
            ->createItem($name, [
85
                'childrenAttributes' => $menuConfiguration->getParameter('attr')
86
            ])
87
        ;
88
        
89
        /**
90
         * @var string $itemName
91
         * @var MenuItemConfiguration $itemConfiguration
92
         */
93
        foreach ($menuConfiguration->getParameter('items') as $itemName => $itemConfiguration) {
94
            // guess item text from configuration
95
            $text = $this->guessItemText($itemName, $itemConfiguration);
96
97
            // item children
98
            $subItems = $itemConfiguration->getParameter('items');
99
            $hasChildren = count($subItems);
100
101
            // create menu item configuration (link attributes, icon, route...)
102
            $menuItemConfiguration = $this->createMenuItemConfiguration($itemConfiguration, $entity);
103
104
            if ($hasChildren) {
105
                $menuItemConfiguration['childrenAttributes']['class'] = 'nav nav-second-level collapse';
106
            }
107
108
            // add to knp menu
109
            $menu->addChild($text, $menuItemConfiguration);
110
111
            if ($hasChildren) {
112
                foreach ($subItems as $subItemName => $subItemConfiguration) {
113
                    $subMenuItemConfiguration = $this->createMenuItemConfiguration($subItemConfiguration);
114
                    $menu[$text]->addChild(
115
                        $this->guessItemText($subItemName, $subItemConfiguration),
116
                        $subMenuItemConfiguration
117
                    );
118
                }
119
            }
120
        }
121
122
        return $menu;
123
    }
124
125
    /**
126
     * Guess an item text according to the configuration.
127
     *
128
     * @param string $name
129
     * @param MenuItemConfiguration $itemConfiguration
130
     * @return string
131
     */
132
    protected function guessItemText($name, MenuItemConfiguration $itemConfiguration)
133
    {
134
        $text = $itemConfiguration->getParameter('text');
135
136
        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
0 ignored issues
show
Deprecated Code introduced by
The method LAG\AdminBundle\Configur...licationConfiguration() has been deprecated with message: Return the Application configuration.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
143
                ->configurationFactory
144
                ->getApplicationConfiguration()
145
                ->getParameter('translation')['pattern'];
146
            $action = $itemConfiguration->getParameter('action');
147
148
            $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
     *
160
     * @param MenuItemConfiguration $itemConfiguration
161
     * @param null $entity
162
     * @return array
163
     * @throws Exception
164
     */
165
    protected function createMenuItemConfiguration(MenuItemConfiguration $itemConfiguration, $entity = null)
166
    {
167
        $menuItemConfiguration = [
168
            // configured <a> tag attributes
169
            'linkAttributes' => $itemConfiguration->getParameter('attr'),
170
            'routeParameters' => $itemConfiguration->getParameter('parameters'),
171
            'attributes' => [
172
                'icon' => $itemConfiguration->getParameter('icon'),
173
            ]
174
        ];
175
        
176
        // add parameters value from entity
177
        if ($entity && count($menuItemConfiguration['routeParameters'])) {
178
            $routeParameters = [];
179
180
            foreach ($menuItemConfiguration['routeParameters'] as $name => $value) {
181
182
                if ($value === null) {
183
                    // get value from current entity
184
                    $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
                ->registry
197
                ->get($adminName)
198
            ;
199
            $generator = new RouteNameGenerator();
200
            $menuItemConfiguration['route'] = $generator->generate(
201
                $itemConfiguration->getParameter('action'),
202
                $admin->getName(),
203
                $admin->getConfiguration()
204
            );
205
            
206
        } else if ($route = $itemConfiguration->getParameter('route')) {
207
            // route is provided so we take it
208
            $menuItemConfiguration['route'] = $route;
209
        } else {
210
            // if no admin and no route is provided, we take the url. In knp configuration, the url parameter is uri
211
            $menuItemConfiguration['uri'] = $itemConfiguration->getParameter('url');
212
        }
213
214
        return $menuItemConfiguration;
215
    }
216
}
217