Completed
Pull Request — master (#131)
by Arnaud
35:53
created

ExtraConfigurationSubscriber::addDefaultActions()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
cc 4
eloc 9
c 3
b 0
f 1
nc 4
nop 1
dl 0
loc 14
rs 9.9666
1
<?php
2
3
namespace LAG\AdminBundle\Event\Subscriber;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use LAG\AdminBundle\Bridge\Doctrine\ORM\Metadata\MetadataHelperInterface;
7
use LAG\AdminBundle\Configuration\ApplicationConfiguration;
8
use LAG\AdminBundle\Configuration\ApplicationConfigurationStorage;
9
use LAG\AdminBundle\Event\Events;
10
use LAG\AdminBundle\Event\Events\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\TranslationUtils;
16
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17
use Symfony\Contracts\Translation\TranslatorInterface;
18
19
/**
20
 * Add extra default configuration for actions and fields.
21
 */
22
class ExtraConfigurationSubscriber implements EventSubscriberInterface
23
{
24
    /**
25
     * @var ApplicationConfiguration
26
     */
27
    private $applicationConfiguration;
28
29
    /**
30
     * @var ResourceCollection
31
     */
32
    private $resourceCollection;
33
34
    /**
35
     * @var ConfigurationFactory
36
     */
37
    private $configurationFactory;
38
39
    /**
40
     * @var MetadataHelperInterface
41
     */
42
    private $metadataHelper;
43
44
    /**
45
     * @var EntityManagerInterface
46
     */
47
    private $entityManager;
48
49
    /**
50
     * @var TranslatorInterface
51
     */
52
    private $translator;
53
54
    /**
55
     * @return array
56
     */
57
    public static function getSubscribedEvents()
58
    {
59
        return [
60
            Events::CONFIGURATION_ADMIN => 'enrichAdminConfiguration',
61
            Events::MENU_CONFIGURATION => 'enrichMenuConfiguration',
62
        ];
63
    }
64
65
    /**
66
     * ExtraConfigurationSubscriber constructor.
67
     *
68
     * @param ApplicationConfigurationStorage $applicationConfigurationStorage
69
     * @param EntityManagerInterface          $entityManager
70
     * @param ResourceCollection              $resourceCollection
71
     * @param ConfigurationFactory            $configurationFactory
72
     * @param MetadataHelperInterface         $metadataHelper
73
     * @param TranslatorInterface             $translator
74
     */
75
    public function __construct(
76
        ApplicationConfigurationStorage $applicationConfigurationStorage,
77
        EntityManagerInterface $entityManager,
78
        ResourceCollection $resourceCollection,
79
        ConfigurationFactory $configurationFactory,
80
        MetadataHelperInterface $metadataHelper,
81
        TranslatorInterface $translator
82
    ) {
83
        $this->applicationConfiguration = $applicationConfigurationStorage->getConfiguration();
84
        $this->resourceCollection = $resourceCollection;
85
        $this->configurationFactory = $configurationFactory;
86
        $this->metadataHelper = $metadataHelper;
87
        $this->entityManager = $entityManager;
88
        $this->translator = $translator;
89
    }
90
91
    public function enrichAdminConfiguration(ConfigurationEvent $event)
92
    {
93
        if (!$this->isExtraConfigurationEnabled()) {
94
            return;
95
        }
96
        $configuration = $event->getConfiguration();
97
98
        // Actions
99
        $this->addDefaultActions($configuration);
100
101
        // Add default field configuration: it provides a type, a form type, and a view according to the found metadata
102
        $helper = new FieldConfigurationHelper(
103
            $this->entityManager,
104
            $this->translator,
105
            $this->applicationConfiguration,
106
            $this->metadataHelper
107
        );
108
        $helper->addDefaultFields($configuration, $event->getEntityClass(), $event->getAdminName());
109
        $helper->addDefaultStrategy($configuration);
110
        $helper->addDefaultRouteParameters($configuration);
111
        $helper->addDefaultFormUse($configuration);
112
        $helper->provideActionsFieldConfiguration($configuration, $event->getAdminName());
113
114
        // Menus
115
        $this->addDefaultRightMenu($configuration);
116
        $this->addDefaultLeftMenu($configuration);
117
        $this->addDefaultTopMenu($configuration, $event->getAdminName());
118
119
        // Filters
120
        $this->addDefaultFilters($configuration);
121
122
        $event->setConfiguration($configuration);
123
    }
124
125
    public function enrichMenuConfiguration(MenuConfigurationEvent $event)
126
    {
127
        if (!$this->isExtraConfigurationEnabled()) {
128
            return;
129
        }
130
        $configuration = $event->getMenuConfigurations();
131
132
        if (!key_exists('top', $configuration) || [] === $configuration['top']) {
133
            $configuration['top'] = [
134
                'brand' => $this->applicationConfiguration->getParameter('title'),
135
            ];
136
        }
137
138
        if (!key_exists('left', $configuration) || [] === $configuration['left']) {
139
            $configuration['left'] = $this->configurationFactory->createResourceMenuConfiguration();
140
        }
141
142
        $event->setMenuConfigurations($configuration);
143
    }
144
145
    /**
146
     * Defines the default CRUD actions if no action was configured.
147
     *
148
     * @param array $configuration
149
     */
150
    private function addDefaultActions(array &$configuration)
151
    {
152
        if (!key_exists('actions', $configuration) || !is_array($configuration['actions'])) {
153
            $configuration['actions'] = [];
154
        }
155
156
        if (0 !== count($configuration['actions'])) {
157
            return;
158
        }
159
        $configuration['actions'] = [
160
            'create' => [],
161
            'list' => [],
162
            'edit' => [],
163
            'delete' => [],
164
        ];
165
    }
166
167
    /**
168
     * Add the default left menu configuration. One item for each Admin.
169
     *
170
     * @param array $configuration
171
     */
172
    private function addDefaultLeftMenu(array &$configuration)
173
    {
174
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
175
            return;
176
        }
177
        $menus = $this->configurationFactory->createResourceMenuConfiguration();
178
179
        // Add the resources menu for each action of the admin
180
        foreach ($configuration['actions'] as $name => $action) {
181
            if (null === $action) {
182
                $action = [];
183
            }
184
185
            if (key_exists('menus', $action) && key_exists('left', $action)) {
186
                continue;
187
            }
188
189
            $configuration['actions'][$name]['menus']['left'] = $menus;
190
        }
191
    }
192
193
    /**
194
     * Add the default right menu.
195
     *
196
     * @param array  $configuration
197
     */
198
    private function addDefaultRightMenu(array &$configuration)
199
    {
200
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
201
            return;
202
        }
203
204
        if (!key_exists('list', $configuration['actions']) || null === $configuration['actions']['list']) {
205
            return;
206
        }
207
208
        if (
209
            key_exists('menus', $configuration['actions']['list']) &&
210
            is_array($configuration['actions']['list']['menus']) &&
211
            key_exists('right', $configuration['actions']['list']['menus'])
212
        ) {
213
            return;
214
        }
215
216
        $configuration['actions']['list']['menus']['right'] = [];
217
    }
218
219
    private function addDefaultTopMenu(array &$configuration, string $adminName)
220
    {
221
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
222
            return;
223
        }
224
225
        if (key_exists('list', $configuration['actions'])) {
226
            // Add a "Create" link in the top bar if the create action is allowed
227
            if (!key_exists('create', $configuration['actions'])) {
228
                return;
229
            }
230
            $configuration['actions']['list']['menus']['top']['items'][] = [
231
                'admin' => $adminName,
232
                'action' => 'create',
233
                'text' => TranslationUtils::getTranslationKey(
234
                    $this->applicationConfiguration->getParameter('translation_pattern'),
235
                    $adminName,
236
                    'create'
237
                ),
238
                'icon' => 'plus',
239
            ];
240
        }
241
242
        if (key_exists('create', $configuration['actions'])) {
243
            // Add a "Return" link in the top bar if the list action is allowed
244
            if (!key_exists('list', $configuration['actions'])) {
245
                return;
246
            }
247
            $configuration['actions']['create']['menus']['top']['items'][] = [
248
                'admin' => $adminName,
249
                'action' => 'list',
250
                'text' => TranslationUtils::getTranslationKey(
251
                    $this->applicationConfiguration->getParameter('translation_pattern'),
252
                    $adminName,
253
                    'return'
254
                ),
255
                'icon' => 'arrow-left',
256
            ];
257
        }
258
259
        if (key_exists('edit', $configuration['actions'])) {
260
            // Add a "Return" link in the top bar if the list action is allowed
261
            if (!key_exists('list', $configuration['actions'])) {
262
                return;
263
            }
264
265
            if (!key_exists('menus', $configuration['actions']['edit'])) {
266
                $configuration['actions']['edit']['menus'] = [];
267
            }
268
269
            if (!key_exists('top', $configuration['actions']['edit']['menus'])) {
270
                $configuration['actions']['edit']['menus']['top'] = [];
271
            }
272
273
            if (!key_exists('items', $configuration['actions']['edit']['menus']['top'])) {
274
                $configuration['actions']['edit']['menus']['top']['items'] = [];
275
            }
276
            array_unshift($configuration['actions']['edit']['menus']['top']['items'], [
277
                'admin' => $adminName,
278
                'action' => 'list',
279
                'text' => TranslationUtils::getTranslationKey(
280
                    $this->applicationConfiguration->getParameter('translation_pattern'),
281
                    $adminName,
282
                    'return'
283
                ),
284
                'icon' => 'arrow-left',
285
            ]);
286
        }
287
    }
288
289
    /**
290
     * Add default filters for the list actions, guessed using the entity metadata.
291
     *
292
     * @param array $configuration
293
     */
294
    private function addDefaultFilters(array &$configuration)
295
    {
296
        // Add the filters only for the "list" action
297
        if (!key_exists('list', $configuration['actions'])) {
298
            return;
299
        }
300
301
        // If some filters are already configured, we do not add the default filters
302
        if (key_exists('filter', $configuration['actions']['list'])) {
303
            return;
304
        }
305
        // TODO add a default unified filter
306
        $metadata = $this->metadataHelper->findMetadata($configuration['entity']);
307
308
        if (null === $metadata) {
309
            return;
310
        }
311
        $filters = [];
312
313
        foreach ($metadata->getFieldNames() as $fieldName) {
314
            $type = $metadata->getTypeOfField($fieldName);
315
            $operator = $this->getOperatorFromFieldType($type);
316
317
            $filters[$fieldName] = [
318
                'type' => $type,
319
                'options' => [],
320
                'comparator' => $operator,
321
            ];
322
        }
323
        $configuration['actions']['list']['filters'] = $filters;
324
    }
325
326
    private function getOperatorFromFieldType($type)
327
    {
328
        $mapping = [
329
            'string' => 'like',
330
            'text' => 'like',
331
        ];
332
333
        if (key_exists($type, $mapping)) {
334
            return $mapping[$type];
335
        }
336
337
        return '=';
338
    }
339
340
    /**
341
     * @return bool
342
     */
343
    private function isExtraConfigurationEnabled(): bool
344
    {
345
        return $this->applicationConfiguration->getParameter('enable_extra_configuration');
346
    }
347
}
348