Completed
Push — refonte ( 758c88...ee8395 )
by Arnaud
02:27
created

ExtraConfigurationSubscriber   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 301
Duplicated Lines 16.28 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 44
lcom 1
cbo 9
dl 49
loc 301
rs 8.8798
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 11 11 1
A getSubscribedEvents() 0 7 1
A enrichAdminConfiguration() 0 28 2
A enrichMenuConfiguration() 0 19 6
A addDefaultActions() 0 16 4
A addDefaultLeftMenu() 0 16 5
B addDefaultRightMenu() 0 20 6
C addDefaultTopMenu() 38 69 11
A addDefaultFilters() 0 30 5
A getOperatorFromFieldType() 0 13 2
A isExtraConfigurationEnabled() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ExtraConfigurationSubscriber often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ExtraConfigurationSubscriber, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace LAG\AdminBundle\Event\Subscriber;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use LAG\AdminBundle\Bridge\Doctrine\ORM\Helper\MetadataTrait;
7
use LAG\AdminBundle\Configuration\ApplicationConfiguration;
8
use LAG\AdminBundle\Configuration\ApplicationConfigurationStorage;
9
use LAG\AdminBundle\Event\Events;
10
use LAG\AdminBundle\Event\ConfigurationEvent;
11
use LAG\AdminBundle\Event\Menu\MenuConfigurationEvent;
12
use LAG\AdminBundle\Factory\ConfigurationFactory;
13
use LAG\AdminBundle\Field\Helper\FieldConfigurationHelper;
14
use LAG\AdminBundle\Resource\ResourceCollection;
15
use LAG\AdminBundle\Utils\StringUtils;
16
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17
18
/**
19
 * Add extra default configuration for actions and fields.
20
 */
21
class ExtraConfigurationSubscriber implements EventSubscriberInterface
22
{
23
    use MetadataTrait;
24
25
    /**
26
     * @var ApplicationConfiguration
27
     */
28
    private $applicationConfiguration;
29
30
    /**
31
     * @var ResourceCollection
32
     */
33
    private $resourceCollection;
34
35
    /**
36
     * @var ConfigurationFactory
37
     */
38
    private $configurationFactory;
39
40
    /**
41
     * @return array
42
     */
43
    public static function getSubscribedEvents()
44
    {
45
        return [
46
            Events::ADMIN_CONFIGURATION => 'enrichAdminConfiguration',
47
            Events::MENU_CONFIGURATION => 'enrichMenuConfiguration',
48
        ];
49
    }
50
51
    /**
52
     * ExtraConfigurationSubscriber constructor.
53
     *
54
     * @param ApplicationConfigurationStorage $applicationConfigurationStorage
55
     * @param EntityManagerInterface          $entityManager
56
     * @param ResourceCollection              $resourceCollection
57
     * @param ConfigurationFactory            $configurationFactory
58
     */
59 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
60
        ApplicationConfigurationStorage $applicationConfigurationStorage,
61
        EntityManagerInterface $entityManager,
62
        ResourceCollection $resourceCollection,
63
        ConfigurationFactory $configurationFactory
64
    ) {
65
        $this->applicationConfiguration = $applicationConfigurationStorage->getConfiguration();
66
        $this->entityManager = $entityManager;
67
        $this->resourceCollection = $resourceCollection;
68
        $this->configurationFactory = $configurationFactory;
69
    }
70
71
    public function enrichAdminConfiguration(ConfigurationEvent $event)
72
    {
73
        if (!$this->isExtraConfigurationEnabled()) {
74
            return;
75
        }
76
        $configuration = $event->getConfiguration();
77
78
        // Actions
79
        $this->addDefaultActions($configuration);
80
81
        // Add default field configuration: it provides a type, a form type, and a view according to the found metadata
82
        $helper = new FieldConfigurationHelper($this->entityManager, $this->applicationConfiguration);
83
        $helper->addDefaultFields($configuration, $event->getEntityClass(), $event->getAdminName());
84
        $helper->addDefaultStrategy($configuration);
85
        $helper->addDefaultRouteParameters($configuration);
86
        $helper->addDefaultFormUse($configuration);
87
        $helper->provideActionsFieldConfiguration($configuration, $event->getAdminName());
88
89
        // Menus
90
        $this->addDefaultRightMenu($configuration);
91
        $this->addDefaultLeftMenu($configuration);
92
        $this->addDefaultTopMenu($configuration, $event->getAdminName());
93
94
        // Filters
95
        $this->addDefaultFilters($configuration);
96
97
        $event->setConfiguration($configuration);
98
    }
99
100
    public function enrichMenuConfiguration(MenuConfigurationEvent $event)
101
    {
102
        if (!$this->isExtraConfigurationEnabled()) {
103
            return;
104
        }
105
        $configuration = $event->getMenuConfigurations();
106
107
        if (!key_exists('top', $configuration) || [] === $configuration['top']) {
108
            $configuration['top'] = [
109
                'brand' => $this->applicationConfiguration->getParameter('title'),
110
            ];
111
        }
112
113
        if (!key_exists('left', $configuration) || [] === $configuration['left']) {
114
            $configuration['left'] = $this->configurationFactory->createResourceMenuConfiguration();
115
        }
116
117
        $event->setMenuConfigurations($configuration);
118
    }
119
120
    /**
121
     * Defines the default CRUD actions if no action was configured.
122
     *
123
     * @param array $configuration
124
     */
125
    private function addDefaultActions(array &$configuration)
126
    {
127
        if (!key_exists('actions', $configuration) || !is_array($configuration['actions'])) {
128
            $configuration['actions'] = [];
129
        }
130
131
        if (0 !== count($configuration['actions'])) {
132
            return;
133
        }
134
        $configuration['actions'] = [
135
            'create' => [],
136
            'list' => [],
137
            'edit' => [],
138
            'delete' => [],
139
        ];
140
    }
141
142
    /**
143
     * Add the default left menu configuration. One item for each Admin.
144
     *
145
     * @param array $configuration
146
     */
147
    private function addDefaultLeftMenu(array &$configuration)
148
    {
149
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
150
            return;
151
        }
152
        $menus = $this->configurationFactory->createResourceMenuConfiguration();
153
154
        // Add the resources menu for each action of the admin
155
        foreach ($configuration['actions'] as $name => $action) {
156
            if (key_exists('menus', $action) && key_exists('left', $action)) {
157
                continue;
158
            }
159
160
            $configuration['actions'][$name]['menus']['left'] = $menus;
161
        }
162
    }
163
164
    /**
165
     * Add the default right menu.
166
     *
167
     * @param array  $configuration
168
     */
169
    private function addDefaultRightMenu(array &$configuration)
170
    {
171
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
172
            return;
173
        }
174
175
        if (!key_exists('list', $configuration['actions'])) {
176
            return;
177
        }
178
179
        if (
180
            key_exists('menus', $configuration['actions']['list']) &&
181
            is_array($configuration['actions']['list']['menus']) &&
182
            key_exists('right', $configuration['actions']['list']['menus'])
183
        ) {
184
            return;
185
        }
186
187
        $configuration['actions']['list']['menus']['right'] = [];
188
    }
189
190
    private function addDefaultTopMenu(array &$configuration, string $adminName)
191
    {
192
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
193
            return;
194
        }
195
196 View Code Duplication
        if (key_exists('list', $configuration['actions'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
197
            // Add a "Create" link in the top bar if the create action is allowed
198
            if (!key_exists('create', $configuration['actions'])) {
199
                return;
200
            }
201
            $configuration['actions']['list']['menus']['top']['items'][] = [
202
                'admin' => $adminName,
203
                'action' => 'create',
204
                'text' => StringUtils::getTranslationKey(
205
                    $this->applicationConfiguration->getParameter('translation_pattern'),
206
                    $adminName,
207
                    'create'
208
                ),
209
                'icon' => 'plus',
210
            ];
211
        }
212
213 View Code Duplication
        if (key_exists('create', $configuration['actions'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
            // Add a "Return" link in the top bar if the list action is allowed
215
            if (!key_exists('list', $configuration['actions'])) {
216
                return;
217
            }
218
            $configuration['actions']['create']['menus']['top']['items'][] = [
219
                'admin' => $adminName,
220
                'action' => 'list',
221
                'text' => StringUtils::getTranslationKey(
222
                    $this->applicationConfiguration->getParameter('translation_pattern'),
223
                    $adminName,
224
                    'return'
225
                ),
226
                'icon' => 'arrow-left',
227
            ];
228
        }
229
230
        if (key_exists('edit', $configuration['actions'])) {
231
            // Add a "Return" link in the top bar if the list action is allowed
232
            if (!key_exists('list', $configuration['actions'])) {
233
                return;
234
            }
235
236
            if (!key_exists('menus', $configuration['actions']['edit'])) {
237
                $configuration['actions']['edit']['menus'] = [];
238
            }
239
240 View Code Duplication
            if (!key_exists('top', $configuration['actions']['edit']['menus'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
                $configuration['actions']['edit']['menus']['top'] = [];
242
            }
243
244 View Code Duplication
            if (!key_exists('items', $configuration['actions']['edit']['menus']['top'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
                $configuration['actions']['edit']['menus']['top']['items'] = [];
246
            }
247
            array_unshift($configuration['actions']['edit']['menus']['top']['items'], [
248
                'admin' => $adminName,
249
                'action' => 'list',
250
                'text' => StringUtils::getTranslationKey(
251
                    $this->applicationConfiguration->getParameter('translation_pattern'),
252
                    $adminName,
253
                    'return'
254
                ),
255
                'icon' => 'arrow-left',
256
            ]);
257
        }
258
    }
259
260
261
262
    /**
263
     * Add default filters for the list actions, guessed using the entity metadata.
264
     *
265
     * @param array $configuration
266
     */
267
    private function addDefaultFilters(array &$configuration)
268
    {
269
        // Add the filters only for the "list" action
270
        if (!key_exists('list', $configuration['actions'])) {
271
            return;
272
        }
273
274
        // If some filters are already configured, we do not add the default filters
275
        if (key_exists('filter', $configuration['actions']['list'])) {
276
            return;
277
        }
278
        $metadata = $this->findMetadata($configuration['entity']);
279
280
        if (null === $metadata) {
281
            return;
282
        }
283
        $filters = [];
284
285
        foreach ($metadata->getFieldNames() as $fieldName) {
286
            $type = $metadata->getTypeOfField($fieldName);
287
            $operator = $this->getOperatorFromFieldType($type);
288
289
            $filters[$fieldName] = [
290
                'type' => $type,
291
                'options' => [],
292
                'comparator' => $operator,
293
            ];
294
        }
295
        $configuration['actions']['list']['filters'] = $filters;
296
    }
297
298
299
300
    private function getOperatorFromFieldType($type)
301
    {
302
        $mapping = [
303
            'string' => 'like',
304
            'text' => 'like',
305
        ];
306
307
        if (key_exists($type, $mapping)) {
308
            return $mapping[$type];
309
        }
310
311
        return '=';
312
    }
313
314
    /**
315
     * @return bool
316
     */
317
    private function isExtraConfigurationEnabled(): bool
318
    {
319
        return $this->applicationConfiguration->getParameter('enable_extra_configuration');
320
    }
321
}
322