Completed
Push — master ( bd4cbc...df0c76 )
by Arnaud
9s
created

ExtraConfigurationSubscriber::actionCreate()   D

Complexity

Conditions 14
Paths 41

Size

Total Lines 100
Code Lines 59

Duplication

Lines 28
Ratio 28 %

Code Coverage

Tests 19
CRAP Score 80.768

Importance

Changes 11
Bugs 2 Features 2
Metric Value
c 11
b 2
f 2
dl 28
loc 100
ccs 19
cts 63
cp 0.3016
rs 4.9516
cc 14
eloc 59
nc 41
nop 1
crap 80.768

2 Methods

Rating   Name   Duplication   Size   Complexity  
B ExtraConfigurationSubscriber::beforeActionConfiguration() 0 41 2
B ExtraConfigurationSubscriber::addDefaultMenuConfiguration() 0 37 5

How to fix   Long Method    Complexity   

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