Completed
Pull Request — master (#90)
by Arnaud
16:42
created

ExtraConfigurationSubscriber::adminCreate()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

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