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