Passed
Pull Request — master (#138)
by Arnaud
08:18 queued 05:22
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
    public function __construct(
69
        ApplicationConfigurationStorage $applicationConfigurationStorage,
70
        EntityManagerInterface $entityManager,
71
        ResourceCollection $resourceCollection,
72
        ConfigurationFactory $configurationFactory,
73
        MetadataHelperInterface $metadataHelper,
74
        TranslatorInterface $translator
75
    ) {
76
        $this->applicationConfiguration = $applicationConfigurationStorage->getConfiguration();
77
        $this->resourceCollection = $resourceCollection;
78
        $this->configurationFactory = $configurationFactory;
79
        $this->metadataHelper = $metadataHelper;
80
        $this->entityManager = $entityManager;
81
        $this->translator = $translator;
82
    }
83
84
    public function enrichAdminConfiguration(ConfigurationEvent $event)
85
    {
86
        if (!$this->isExtraConfigurationEnabled()) {
87
            return;
88
        }
89
        $configuration = $event->getConfiguration();
90
91
        // Actions
92
        $this->addDefaultActions($configuration);
93
94
        // Add default field configuration: it provides a type, a form type, and a view according to the found metadata
95
        $helper = new FieldConfigurationHelper(
96
            $this->entityManager,
97
            $this->translator,
98
            $this->applicationConfiguration,
99
            $this->metadataHelper
100
        );
101
        $helper->addDefaultFields($configuration, $event->getEntityClass(), $event->getAdminName());
102
        $helper->addDefaultStrategy($configuration);
103
        $helper->addDefaultRouteParameters($configuration);
104
        $helper->addDefaultFormUse($configuration);
105
        $helper->provideActionsFieldConfiguration($configuration, $event->getAdminName());
106
107
        // Menus
108
        $this->addDefaultRightMenu($configuration);
109
        $this->addDefaultLeftMenu($configuration);
110
        $this->addDefaultTopMenu($configuration, $event->getAdminName());
111
112
        // Filters
113
        $this->addDefaultFilters($configuration);
114
115
        $event->setConfiguration($configuration);
116
    }
117
118
    public function enrichMenuConfiguration(MenuConfigurationEvent $event)
119
    {
120
        if (!$this->isExtraConfigurationEnabled()) {
121
            return;
122
        }
123
        $configuration = $event->getMenuConfigurations();
124
125
        if (!key_exists('top', $configuration) || [] === $configuration['top']) {
126
            $configuration['top'] = [
127
                'brand' => $this->applicationConfiguration->getParameter('title'),
128
            ];
129
        }
130
131
        if (!key_exists('left', $configuration) || [] === $configuration['left']) {
132
            $configuration['left'] = $this->configurationFactory->createResourceMenuConfiguration();
133
        }
134
135
        $event->setMenuConfigurations($configuration);
136
    }
137
138
    /**
139
     * Defines the default CRUD actions if no action was configured.
140
     */
141
    private function addDefaultActions(array &$configuration)
142
    {
143
        if (!key_exists('actions', $configuration) || !is_array($configuration['actions'])) {
144
            $configuration['actions'] = [];
145
        }
146
147
        if (0 !== count($configuration['actions'])) {
148
            return;
149
        }
150
        $configuration['actions'] = [
151
            'create' => [],
152
            'list' => [],
153
            'edit' => [],
154
            'delete' => [],
155
        ];
156
    }
157
158
    /**
159
     * Add the default left menu configuration. One item for each Admin.
160
     */
161
    private function addDefaultLeftMenu(array &$configuration)
162
    {
163
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
164
            return;
165
        }
166
        $menus = $this->configurationFactory->createResourceMenuConfiguration();
167
168
        // Add the resources menu for each action of the admin
169
        foreach ($configuration['actions'] as $name => $action) {
170
            if (null === $action) {
171
                $action = [];
172
            }
173
174
            if (key_exists('menus', $action) && key_exists('left', $action)) {
175
                continue;
176
            }
177
178
            $configuration['actions'][$name]['menus']['left'] = $menus;
179
        }
180
    }
181
182
    /**
183
     * Add the default right menu.
184
     */
185
    private function addDefaultRightMenu(array &$configuration)
186
    {
187
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
188
            return;
189
        }
190
191
        if (!key_exists('list', $configuration['actions']) || null === $configuration['actions']['list']) {
192
            return;
193
        }
194
195
        if (
196
            key_exists('menus', $configuration['actions']['list']) &&
197
            is_array($configuration['actions']['list']['menus']) &&
198
            key_exists('right', $configuration['actions']['list']['menus'])
199
        ) {
200
            return;
201
        }
202
203
        $configuration['actions']['list']['menus']['right'] = [];
204
    }
205
206
    private function addDefaultTopMenu(array &$configuration, string $adminName)
207
    {
208
        if (!$this->applicationConfiguration->getParameter('enable_menus')) {
209
            return;
210
        }
211
212
        if (key_exists('list', $configuration['actions'])) {
213
            // Add a "Create" link in the top bar if the create action is allowed
214
            if (!key_exists('create', $configuration['actions'])) {
215
                return;
216
            }
217
            $configuration['actions']['list']['menus']['top']['items'][] = [
218
                'admin' => $adminName,
219
                'action' => 'create',
220
                'text' => $this->getText('create', $adminName),
221
                'icon' => 'plus',
222
            ];
223
        }
224
225
        if (key_exists('create', $configuration['actions'])) {
226
            // Add a "Return" link in the top bar if the list action is allowed
227
            if (!key_exists('list', $configuration['actions'])) {
228
                return;
229
            }
230
            $configuration['actions']['create']['menus']['top']['items'][] = [
231
                'admin' => $adminName,
232
                'action' => 'list',
233
                'text' => $this->getText('return', $adminName),
234
                'icon' => 'arrow-left',
235
            ];
236
        }
237
238
        if (key_exists('edit', $configuration['actions'])) {
239
            // Add a "Return" link in the top bar if the list action is allowed
240
            if (!key_exists('list', $configuration['actions'])) {
241
                return;
242
            }
243
244
            if (!key_exists('menus', $configuration['actions']['edit'])) {
245
                $configuration['actions']['edit']['menus'] = [];
246
            }
247
248
            if (!key_exists('top', $configuration['actions']['edit']['menus'])) {
249
                $configuration['actions']['edit']['menus']['top'] = [];
250
            }
251
252
            if (!key_exists('items', $configuration['actions']['edit']['menus']['top'])) {
253
                $configuration['actions']['edit']['menus']['top']['items'] = [];
254
            }
255
            array_unshift($configuration['actions']['edit']['menus']['top']['items'], [
256
                'admin' => $adminName,
257
                'action' => 'list',
258
                'text' => $this->getText('Return', $adminName),
259
                'icon' => 'arrow-left',
260
            ]);
261
        }
262
    }
263
264
    /**
265
     * Add default filters for the list actions, guessed using the entity metadata.
266
     */
267
    private function addDefaultFilters(array &$configuration): void
268
    {
269
        // Add the filters only for the "list" action
270
        if (!key_exists('list', $configuration['actions'])) {
271
            return;
272
        }
273
274
        // If some filters are already configured, we do not add the default filters
275
        if (key_exists('filter', $configuration['actions']['list'])) {
276
            return;
277
        }
278
        // TODO add a default unified filter
279
        $metadata = $this->metadataHelper->findMetadata($configuration['entity']);
280
281
        if (null === $metadata) {
282
            return;
283
        }
284
        $filters = [];
285
286
        foreach ($metadata->getFieldNames() as $fieldName) {
287
            $type = $metadata->getTypeOfField($fieldName);
288
            $operator = $this->getOperatorFromFieldType($type);
289
290
            $filters[$fieldName] = [
291
                'type' => $type,
292
                'options' => [],
293
                'comparator' => $operator,
294
            ];
295
        }
296
        $configuration['actions']['list']['filters'] = $filters;
297
    }
298
299
    private function getOperatorFromFieldType($type)
300
    {
301
        $mapping = [
302
            'string' => 'like',
303
            'text' => 'like',
304
        ];
305
306
        if (key_exists($type, $mapping)) {
307
            return $mapping[$type];
308
        }
309
310
        return '=';
311
    }
312
313
    private function isExtraConfigurationEnabled(): bool
314
    {
315
        return $this->applicationConfiguration->getParameter('enable_extra_configuration');
316
    }
317
318
    private function getText(string $text, $adminName = null): string
319
    {
320
        $text = ucfirst($text);
321
322
        if (!$this->applicationConfiguration->isTranslationEnabled()) {
323
            $text = TranslationUtils::getTranslationKey(
324
                $this->applicationConfiguration->getTranslationPattern(),
325
                $adminName,
326
                'create'
327
            );
328
        }
329
330
        return $text;
331
    }
332
}
333