Completed
Pull Request — master (#90)
by Arnaud
17:45
created

beforeActionConfiguration()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 43
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 43
ccs 23
cts 23
cp 1
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 23
nc 2
nop 1
crap 2
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 boolean
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
        ];
51
    }
52
53
    /**
54
     * ExtraConfigurationSubscriber constructor.
55
     *
56
     * @param boolean $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 2
    public function adminCreate(AdminCreateEvent $event)
77
    {
78 2
        if (!$this->extraConfigurationEnabled) {
79 1
            return;
80
        }
81 1
        $configuration = $event->getAdminConfiguration();
82
83
        // if no actions are defined, we set default CRUD action
84 1
        if (!array_key_exists('actions', $configuration) || !count($configuration['actions'])) {
85 1
            $configuration['actions'] = [
86
                'create' => [],
87
                'list' => [],
88
                'edit' => [],
89
                'delete' => [],
90
            ];
91 1
            $event->setAdminConfiguration($configuration);
92
        }
93 1
    }
94
95
    /**
96
     * Add default linked actions and default menu actions.
97
     *
98
     * @param BeforeConfigurationEvent $event
99
     */
100 4
    public function beforeActionConfiguration(BeforeConfigurationEvent $event)
101
    {
102
        // add configuration only if extra configuration is enabled
103 4
        if (!$this->extraConfigurationEnabled) {
104 1
            return;
105
        }
106
        // Action configuration array
107 3
        $configuration = $event->getActionConfiguration();
108
        
109
        // current Admin
110 3
        $admin = $event->getAdmin();
111
        
112
        // allowed Actions according to the admin
113
        $keys = $admin
114 3
            ->getConfiguration()
115 3
            ->getParameter('actions');
116 3
        $allowedActions = array_keys($keys);
117
118
        // add default menu configuration
119 3
        $configuration = $this->addDefaultMenuConfiguration(
120 3
            $admin->getName(),
121 3
            $event->getActionName(),
122 3
            $configuration,
123 3
            $allowedActions
124
        );
125
126
        // guess field configuration if required
127 3
        $this->guessFieldConfiguration(
128 3
            $configuration,
129 3
            $event->getActionName(),
130 3
            $admin->getConfiguration()->getParameter('entity')
131
        );
132
133
        // guess linked actions for list actions
134 3
        $this->guessLinkedActionsConfiguration(
135 3
            $configuration,
136 3
            $allowedActions,
137 3
            $event
138
        );
139
140
        // reset action configuration
141 3
        $event->setActionConfiguration($configuration);
142 3
    }
143
144
    /**
145
     * Add default menu configuration for an action.
146
     *
147
     * @param string $adminName
148
     * @param string $actionName
149
     * @param array $actionConfiguration
150
     * @param array $allowedActions
151
     * @return array The modified configuration
152
     */
153 3
    protected function addDefaultMenuConfiguration(
154
        $adminName,
155
        $actionName,
156
        array $actionConfiguration,
157
        array $allowedActions
158
    ) {
159
        // we add a default top menu item "create" only for list action
160 3
        if ($actionName === 'list') {
161
162
            // the create action should enabled
163 2
            if (in_array('create', $allowedActions)) {
164
165 2
                if (!array_key_exists('menus', $actionConfiguration)) {
166 2
                    $actionConfiguration['menus'] = [];
167
                }
168
                // if the menu is disabled we do not add the menu item
169 2
                if ($actionConfiguration['menus'] !== false) {
170 2
                    $resolver = new OptionsResolver();
171 2
                    $resolver->setDefaults([
172
                        'top' => [
173
                            'items' => [
174
                                'create' => [
175 2
                                    'admin' => $adminName,
176 2
                                    'action' => 'create',
177 2
                                    'icon' => 'fa fa-plus',
178
                                ]
179
                            ]
180
                        ]
181
                    ]);
182
                    // resolve default menu options
183 2
                    $actionConfiguration['menus'] = $resolver->resolve($actionConfiguration['menus']);
184
                }
185
            }
186
        }
187
188 3
        return $actionConfiguration;
189
    }
190
191
    /**
192
     * If no field was provided, try to guess field
193
     *
194
     * @param array $configuration
195
     * @param $actionName
196
     * @param $entityClass
197
     */
198 3
    protected function guessFieldConfiguration(array &$configuration, $actionName, $entityClass)
199
    {
200
        // if no field was provided in configuration, we try to take fields from doctrine metadata
201 3
        if (empty($configuration['fields']) || !count($configuration['fields'])) {
202 2
            $fields = [];
203 2
            $guesser = new FieldTypeGuesser();
204
            $metadata = $this
205 2
                ->entityManager
206 2
                ->getMetadataFactory()
207 2
                ->getMetadataFor($entityClass);
208 2
            $fieldsName = $metadata->getFieldNames();
209
210 2
            foreach ($fieldsName as $name) {
211 2
                $type = $metadata->getTypeOfField($name);
212
                // get field type from doctrine type
213 2
                $fieldConfiguration = $guesser->getTypeAndOptions($type);
214
215
                // if a field configuration was found, we take it
216 2
                if (count($fieldConfiguration)) {
217 2
                    $fields[$name] = $fieldConfiguration;
218
                }
219
            }
220 2
            if (count($fields)) {
221
                // adding new fields to action configuration
222 1
                $configuration['fields'] = $fields;
223
224 1
                if ($actionName == 'list') {
225 1
                    $configuration['fields']['_actions'] = null;
226
                }
227
            }
228
        }
229 3
    }
230
231
    /**
232
     * Add fake link fields to edit and delete action for the list view.
233
     *
234
     * @param array $configuration
235
     * @param array $allowedActions
236
     * @param BeforeConfigurationEvent $event
237
     */
238 3
    protected function guessLinkedActionsConfiguration(
239
        array &$configuration,
240
        array $allowedActions,
241
        BeforeConfigurationEvent $event
242
    ) {
243 3
        if (!array_key_exists('fields', $configuration)) {
244 1
            return;
245
        }
246
247
        // configured linked actions :
248
        // _action key should exists and be null
249 2
        $_actionExists = array_key_exists('_actions', $configuration['fields']);
250 2
        $_actionIsNull = $_actionExists && $configuration['fields']['_actions'] === null;
251
252
        // _action is added extra configuration only for the "list" action
253 2
        $isListAction = $event->getActionName() == 'list';
254
    
255
        //dump($_actionExists, $_actionIsNull, $isListAction);
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
256
        
257
258 2
        if ($_actionExists && $_actionIsNull && $isListAction) {
259
            // in list view, we add by default and an edit and a delete button
260
            $translationPattern = $this
261 1
                ->applicationConfiguration
262 1
                ->getParameter('translation')['pattern'];
263
264
            // add a link to the "edit" action, if it is allowed
265 1
            if (in_array('edit', $allowedActions)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
266
//                $configuration['fields']['_actions']['type'] = 'collection';
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
267
//                $configuration['fields']['_actions']['options']['_edit'] = [
268
//                    'type' => 'action',
269
//                    'options' => [
270
//                        'title' => $this->getTranslationKey($translationPattern, 'edit', $event->getAdmin()->getName()),
271
//                        'route' => $event->getAdmin()->generateRouteName('edit'),
272
//                        'parameters' => [
273
//                            'id' => false
274
//                        ],
275
//                        'icon' => 'pencil'
276
//                    ]
277
//                ];
278
            }
279
            
280
            // add a link to the "delete" action, if it is allowed
281 1
            if (in_array('delete', $allowedActions)) {
282 1
                $configuration['fields']['_actions'] = [
283 1
                    'type'=> 'action',
284
                    'options' => [
285 1
                        'title' => $this->getTranslationKey($translationPattern, 'delete', $event->getAdmin()->getName()),
286 1
                        'route' => $event->getAdmin()->generateRouteName('delete'),
287
                        'parameters' => [
288
                            'id' => false
289
                        ],
290 1
                        'icon' => 'remove'
291
                    ]
292
                ];
293
            }
294
        }
295 2
    }
296
}
297