Completed
Branch master (01610a)
by Arnaud
06:29
created

MenuFactory::create()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 52
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 5

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 52
ccs 28
cts 28
cp 1
rs 8.6868
cc 5
eloc 24
nc 7
nop 3
crap 5

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
     */
52 2
    public function __construct(
53
        FactoryInterface $menuFactory,
54
        AdminFactory $adminFactory,
55
        ConfigurationFactory $configurationFactory,
56
        TranslatorInterface $translator
57
    ) {
58 2
        $this->adminFactory = $adminFactory;
59 2
        $this->menuFactory = $menuFactory;
60 2
        $this->configurationFactory = $configurationFactory;
61 2
        $this->translator = $translator;
62 2
    }
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
     * @return ItemInterface
71
     */
72 2
    public function create($name, array $configuration, $entity = null)
73
    {
74
        // resolve menu configuration. It will return a MenuConfiguration with MenuItemConfiguration object
75 2
        $resolver = new OptionsResolver();
76 2
        $menuConfiguration = new MenuConfiguration();
77 2
        $menuConfiguration->configureOptions($resolver);
78 2
        $menuConfiguration->setParameters($resolver->resolve($configuration));
79
80
        // create knp menu
81 2
        $menu = $this
82
            ->menuFactory
83 2
            ->createItem($name, [
84 2
                'childrenAttributes' => $menuConfiguration->getParameter('attr')
85 2
            ]);
86
87
        /**
88
         * @var string $itemName
89
         * @var MenuItemConfiguration $itemConfiguration
90
         */
91 2
        foreach ($menuConfiguration->getParameter('items') as $itemName => $itemConfiguration) {
92
            // guess item text from configuration
93 1
            $text = $this->guessItemText($itemName, $itemConfiguration);
94
95
            // item children
96 1
            $subItems = $itemConfiguration->getParameter('items');
97 1
            $hasChildren = count($subItems);
98
99
            // create menu item configuration (link attributes, icon, route...)
100 1
            $menuItemConfiguration = $this->createMenuItemConfiguration($itemConfiguration, $entity);
101
102 1
            if ($hasChildren) {
103 1
                $menuItemConfiguration['childrenAttributes']['class'] = 'nav nav-second-level collapse';
104 1
            }
105
106
            // add to knp menu
107 1
            $menu->addChild($text, $menuItemConfiguration);
108
109 1
            if ($hasChildren) {
110
111 1
                foreach ($subItems as $subItemName => $subItemConfiguration) {
112 1
                    $subMenuItemConfiguration = $this->createMenuItemConfiguration($subItemConfiguration);
113
114 1
                    $menu[$text]->addChild(
115 1
                        $this->guessItemText($subItemName, $subItemConfiguration),
116
                        $subMenuItemConfiguration
117 1
                    );
118 1
                }
119 1
            }
120 2
        }
121
122 2
        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 1
    protected function guessItemText($name, MenuItemConfiguration $itemConfiguration)
133
    {
134 1
        $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 1
        if ($admin = $itemConfiguration->getParameter('admin')) {
142
            $translationPattern = $this
143
                ->configurationFactory
144
                ->getApplicationConfiguration()
145
                ->getParameter('translation')['pattern'];
146
            $action = $itemConfiguration->getParameter('action');
147
148
            $text = $this->getTranslationKey($translationPattern, $action, $admin);
149
        } else {
150 1
            $text = $name;
151
        }
152
153 1
        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 1
    protected function createMenuItemConfiguration(MenuItemConfiguration $itemConfiguration, $entity = null)
166
    {
167
        $menuItemConfiguration = [
168
            // configured <a> tag attributes
169 1
            'linkAttributes' => $itemConfiguration->getParameter('attr'),
170 1
            'routeParameters' => $itemConfiguration->getParameter('parameters'),
171
            'attributes' => [
172 1
                'icon' => $itemConfiguration->getParameter('icon'),
173
            ]
174 1
        ];
175
176
        // add parameters value from entity
177 1
        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 1
        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 1
        } 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 1
            $menuItemConfiguration['uri'] = $itemConfiguration->getParameter('url');
206
        }
207
208 1
        return $menuItemConfiguration;
209
    }
210
}
211