Completed
Pull Request — master (#90)
by Arnaud
16:42
created

MenuFactory::guessItemText()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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