Completed
Pull Request — dev (#19)
by Arnaud
14:27 queued 06:29
created

ExtraConfigurationSubscriber   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 220
Duplicated Lines 12.73 %

Coupling/Cohesion

Components 1
Dependencies 12

Test Coverage

Coverage 58.1%

Importance

Changes 14
Bugs 4 Features 3
Metric Value
wmc 23
c 14
b 4
f 3
lcom 1
cbo 12
dl 28
loc 220
ccs 43
cts 74
cp 0.581
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getSubscribedEvents() 0 7 1
A __construct() 0 10 1
A adminCreate() 0 19 4
C actionCreate() 28 95 12
B addDefaultMenuConfiguration() 0 33 5

How to fix   Duplicated Code   

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:

1
<?php
2
3
namespace LAG\AdminBundle\Event\Subscriber;
4
5
use Doctrine\Bundle\DoctrineBundle\Registry;
6
use Doctrine\Common\Persistence\Mapping\MappingException;
7
use Doctrine\ORM\EntityManager;
8
use LAG\AdminBundle\Admin\Behaviors\TranslationKeyTrait;
9
use LAG\AdminBundle\Application\Configuration\ApplicationConfiguration;
10
use LAG\AdminBundle\Configuration\Factory\ConfigurationFactory;
11
use LAG\AdminBundle\Event\AdminEvent;
12
use LAG\AdminBundle\Utils\FieldTypeGuesser;
13
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
14
use Symfony\Component\OptionsResolver\OptionsResolver;
15
16
/**
17
 * Add extra default configuration for actions and fields. Bind to ADMIN_CREATE and ACTION_CREATE events
18
 */
19
class ExtraConfigurationSubscriber implements EventSubscriberInterface
20
{
21
    use TranslationKeyTrait;
22
23
    /**
24
     * If is true, the extra configuration will be added.
25
     *
26
     * @var bool
27
     */
28
    protected $extraConfigurationEnabled = false;
29
30
    /**
31
     * @var EntityManager
32
     */
33
    protected $entityManager;
34
35
    /**
36
     * @var ApplicationConfiguration
37
     */
38
    protected $applicationConfiguration;
39
40
    /**
41
     * @return array
42
     */
43 1
    public static function getSubscribedEvents()
44
    {
45
        return [
46 1
            AdminEvent::ADMIN_CREATE => 'adminCreate',
47
            AdminEvent::ACTION_CREATE => 'actionCreate',
48
        ];
49
    }
50
51
    /**
52
     * ExtraConfigurationSubscriber constructor.
53
     *
54
     * @param bool $extraConfigurationEnabled
55
     * @param Registry $doctrine
56
     * @param ConfigurationFactory $configurationFactory
57
     */
58 3
    public function __construct(
59
        $extraConfigurationEnabled = true,
60
        Registry $doctrine,
61
        ConfigurationFactory $configurationFactory
62
    ) {
63 3
        $this->extraConfigurationEnabled = $extraConfigurationEnabled;
64
        // entity manager can be closed, so its better to inject the Doctrine registry instead
65 3
        $this->entityManager = $doctrine->getManager();
66 3
        $this->applicationConfiguration = $configurationFactory->getApplicationConfiguration();
67 3
    }
68
69
    /**
70
     * Adding default CRUD if none is defined.
71
     *
72
     * @param AdminEvent $event
73
     */
74 2
    public function adminCreate(AdminEvent $event)
75
    {
76 2
        if (!$this->extraConfigurationEnabled) {
77 2
            return;
78
        }
79 1
        $configuration = $event->getConfiguration();
80
81
        // if no actions are defined, we set default CRUD action
82 1
        if (!array_key_exists('actions', $configuration) || !count($configuration['actions'])) {
83 1
            $configuration['actions'] = [
84
                'create' => [],
85
                'list' => [],
86
                'edit' => [],
87
                'delete' => [],
88
                'batch' => []
89
            ];
90 1
            $event->setConfiguration($configuration);
91
        }
92 1
    }
93
94
    /**
95
     * Add default linked actions and default menu actions.
96
     *
97
     * @param AdminEvent $event
98
     * @throws MappingException
99
     */
100 1
    public function actionCreate(AdminEvent $event)
101
    {
102
        // add configuration only if extra configuration is enabled
103 1
        if (!$this->extraConfigurationEnabled) {
104
            return;
105
        }
106
        // action configuration array
107 1
        $configuration = $event->getConfiguration();
108
        // current action admin
109 1
        $admin = $event->getAdmin();
110
        // allowed actions according to the admin
111
        $keys = $admin
112 1
            ->getConfiguration()
113 1
            ->getParameter('actions');
114 1
        $allowedActions = array_keys($keys);
115
116
        // add default menu configuration
117 1
        $configuration = $this->addDefaultMenuConfiguration(
118 1
            $admin->getName(),
119 1
            $event->getActionName(),
120
            $configuration,
121
            $allowedActions
122
        );
123
124
        // if no field was provided in configuration, we try to take fields from doctrine metadata
125 1
        if (empty($configuration['fields']) || !count($configuration['fields'])) {
126
            $fields = [];
127
            $guesser = new FieldTypeGuesser();
128
            $metadata = $this
129
                ->entityManager
130
                ->getMetadataFactory()
131
                ->getMetadataFor($admin->getConfiguration()->getParameter('entity'));
132
            $fieldsName = $metadata->getFieldNames();
133
134
            foreach ($fieldsName as $name) {
135
                $type = $metadata->getTypeOfField($name);
136
                // get field type from doctrine type
137
                $fieldConfiguration = $guesser->getTypeAndOptions($type);
138
139
                // if a field configuration was found, we take it
140
                if (count($fieldConfiguration)) {
141
                    $fields[$name] = $fieldConfiguration;
142
                }
143
            }
144
            if (count($fields)) {
145
                // adding new fields to action configuration
146
                $configuration['fields'] = $fields;
147
            }
148
        }
149
        // configured linked actions
150 1
        if (array_key_exists('_actions', $configuration['fields'])
151 1
            && $configuration['fields']['_actions'] === null
152
        ) {
153
            // in list view, we add by default and an edit and a delete button
154
            if ($event->getActionName() == 'list') {
155
156
                $translationPattern = $this
157
                    ->applicationConfiguration
158
                    ->getParameter('translation')['pattern']
159
                ;
160
                
161
                
162 View Code Duplication
                if (in_array('edit', $allowedActions)) {
163
                    $configuration['fields']['_actions']['type'] = 'collection';
164
                    $configuration['fields']['_actions']['options']['_edit'] = [
165
                        'type' => 'action',
166
                        'options' => [
167
                            'title' => $this->getTranslationKey($translationPattern, 'edit', $event->getAdmin()->getName()),
168
                            'route' => $admin->generateRouteName('edit'),
169
                            'parameters' => [
170
                                'id' => false
171
                            ],
172
                            'icon' => 'pencil'
173
                        ]
174
                    ];
175
                }
176 View Code Duplication
                if (in_array('delete', $allowedActions)) {
177
                    $configuration['fields']['_actions']['type'] = 'collection';
178
                    $configuration['fields']['_actions']['options']['_delete'] = [
179
                        'type' => 'action',
180
                        'options' => [
181
                            'title' => $this->getTranslationKey($translationPattern, 'delete', $event->getAdmin()->getName()),
182
                            'route' => $admin->generateRouteName('delete'),
183
                            'parameters' => [
184
                                'id' => false
185
                            ],
186
                            'icon' => 'remove'
187
                        ]
188
                    ];
189
                }
190
            }
191
        }
192
        // reset action configuration
193 1
        $event->setConfiguration($configuration);
194 1
    }
195
196
    /**
197
     * Add default menu configuration for an action.
198
     *
199
     * @param string $admiName
200
     * @param string $actionName
201
     * @param array $actionConfiguration
202
     * @param array $allowedActions
203
     * @return array The modified configuration
204
     */
205 1
    protected function addDefaultMenuConfiguration($admiName, $actionName, array $actionConfiguration, array $allowedActions)
206
    {
207
        // we add a default top menu item "create" only for list action
208 1
        if ($actionName === 'list') {
209
210
            // the create action should enabled
211 1
            if (in_array('create', $allowedActions)) {
212
213 1
                if (!array_key_exists('menus', $actionConfiguration)) {
214 1
                    $actionConfiguration['menus'] = [];
215
                }
216
                // if the menu is disabled we do not add the menu item
217 1
                if ($actionConfiguration['menus'] !== false) {
218 1
                    $resolver = new OptionsResolver();
219 1
                    $resolver->setDefaults([
220
                        'top' => [
221
                            'items' => [
222
                                'create' => [
223 1
                                    'admin' => $admiName,
224 1
                                    'action' => 'create',
225 1
                                    'icon' => 'fa fa-plus',
226
                                ]
227
                            ]
228
                        ]
229
                    ]);
230
                    // resolve default menu options
231 1
                    $actionConfiguration['menus'] = $resolver->resolve($actionConfiguration['menus']);
232
                }
233
            }
234
        }
235
236 1
        return $actionConfiguration;
237
    }
238
}
239