1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace LAG\AdminBundle\Event\Subscriber; |
4
|
|
|
|
5
|
|
|
use Doctrine\Common\Persistence\Mapping\MappingException; |
6
|
|
|
use Doctrine\ORM\EntityManager; |
7
|
|
|
use LAG\AdminBundle\Admin\Configuration\ApplicationConfiguration; |
8
|
|
|
use LAG\AdminBundle\Event\AdminEvent; |
9
|
|
|
use LAG\AdminBundle\Utils\FieldTypeGuesser; |
10
|
|
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Add extra default configuration for actions and fields. Bind to ADMIN_CREATE and ACTION_CREATE events |
14
|
|
|
*/ |
15
|
|
|
class ExtraConfigurationSubscriber implements EventSubscriberInterface |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* @var bool |
19
|
|
|
*/ |
20
|
|
|
protected $enableExtraConfiguration; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var EntityManager |
24
|
|
|
*/ |
25
|
|
|
protected $entityManager; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var ApplicationConfiguration |
29
|
|
|
*/ |
30
|
|
|
protected $applicationConfiguration; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @return array |
34
|
|
|
*/ |
35
|
1 |
|
public static function getSubscribedEvents() |
36
|
|
|
{ |
37
|
|
|
return [ |
38
|
1 |
|
AdminEvent::ADMIN_CREATE => 'adminCreate', |
39
|
|
|
AdminEvent::ACTION_CREATE => 'actionCreate', |
40
|
|
|
]; |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* ExtraConfigurationSubscriber constructor |
45
|
|
|
* |
46
|
|
|
* @param bool $enableExtraConfiguration |
47
|
|
|
* @param EntityManager $entityManager |
48
|
|
|
* @param ApplicationConfiguration $applicationConfiguration |
49
|
|
|
*/ |
50
|
1 |
|
public function __construct( |
51
|
|
|
$enableExtraConfiguration = true, |
52
|
|
|
EntityManager $entityManager, |
|
|
|
|
53
|
|
|
ApplicationConfiguration $applicationConfiguration |
54
|
|
|
) |
55
|
|
|
{ |
56
|
1 |
|
$this->enableExtraConfiguration = $enableExtraConfiguration; |
57
|
1 |
|
$this->entityManager = $entityManager; |
58
|
1 |
|
$this->applicationConfiguration = $applicationConfiguration; |
59
|
1 |
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Adding default CRUD if none is defined |
63
|
|
|
* |
64
|
|
|
* @param AdminEvent $event |
65
|
|
|
*/ |
66
|
1 |
|
public function adminCreate(AdminEvent $event) |
67
|
|
|
{ |
68
|
1 |
|
if (!$this->enableExtraConfiguration) { |
69
|
1 |
|
return; |
70
|
|
|
} |
71
|
1 |
|
$configuration = $event->getConfiguration(); |
72
|
|
|
|
73
|
|
|
// if no actions are defined, we set default CRUD action |
74
|
1 |
|
if (!array_key_exists('actions', $configuration) || !count($configuration['actions'])) { |
75
|
1 |
|
$configuration['actions'] = [ |
76
|
1 |
|
'create' => [], |
77
|
|
|
'list' => [], |
78
|
|
|
'edit' => [], |
79
|
|
|
'delete' => [], |
80
|
|
|
'batch' => [] |
81
|
|
|
]; |
82
|
|
|
} else { |
83
|
1 |
|
$actions = $configuration['actions']; |
84
|
|
|
|
85
|
1 |
|
foreach ($actions as $name => $action) { |
86
|
1 |
|
if (!array_key_exists('batch', $action) || $action['batch'] !== false) { |
87
|
1 |
|
if ($name == 'list') { |
88
|
1 |
|
$configuration['actions']['batch'] = []; |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
} |
93
|
1 |
|
$event->setConfiguration($configuration); |
94
|
1 |
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Add default linked actions and default menu actions |
98
|
|
|
* |
99
|
|
|
* @param AdminEvent $event |
100
|
|
|
* @throws MappingException |
101
|
|
|
*/ |
102
|
|
|
public function actionCreate(AdminEvent $event) |
103
|
|
|
{ |
104
|
|
|
// add configuration only if extra configuration is enabled |
105
|
|
|
if (!$this->enableExtraConfiguration) { |
106
|
|
|
return; |
107
|
|
|
} |
108
|
|
|
// action configuration array |
109
|
|
|
$configuration = $event->getConfiguration(); |
110
|
|
|
// current action admin |
111
|
|
|
$admin = $event->getAdmin(); |
112
|
|
|
// allowed actions according to the admin |
113
|
|
|
$keys = $admin |
114
|
|
|
->getConfiguration() |
115
|
|
|
->getActions(); |
116
|
|
|
$allowedActions = array_keys($keys); |
117
|
|
|
|
118
|
|
|
// if no field was provided in configuration, we try to take fields from doctrine metadata |
119
|
|
|
if (empty($configuration['fields']) || !count($configuration['fields'])) { |
120
|
|
|
$fields = []; |
121
|
|
|
$guesser = new FieldTypeGuesser(); |
122
|
|
|
$metadata = $this |
123
|
|
|
->entityManager |
124
|
|
|
->getMetadataFactory() |
125
|
|
|
->getMetadataFor($admin->getConfiguration()->getEntityName()); |
126
|
|
|
$fieldsName = $metadata->getFieldNames(); |
127
|
|
|
|
128
|
|
|
foreach ($fieldsName as $name) { |
129
|
|
|
$type = $metadata->getTypeOfField($name); |
130
|
|
|
// get field type from doctrine type |
131
|
|
|
$fieldConfiguration = $guesser->getTypeAndOptions($type); |
132
|
|
|
|
133
|
|
|
// if a field configuration was found, we take it |
134
|
|
|
if (count($fieldConfiguration)) { |
135
|
|
|
$fields[$name] = $fieldConfiguration; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
if (count($fields)) { |
139
|
|
|
// adding new fields to action configuration |
140
|
|
|
$configuration['fields'] = $fields; |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
// configured linked actions |
144
|
|
|
if (array_key_exists('_actions', $configuration['fields']) |
145
|
|
|
&& !array_key_exists('type', $configuration['fields']['_actions']) |
146
|
|
|
) { |
147
|
|
|
// in list view, we add by default and an edit and a delete button |
148
|
|
|
if ($event->getActionName() == 'list') { |
149
|
|
View Code Duplication |
if (in_array('edit', $allowedActions)) { |
150
|
|
|
$configuration['fields']['_actions']['type'] = 'collection'; |
151
|
|
|
$configuration['fields']['_actions']['options']['_edit'] = [ |
152
|
|
|
'type' => 'action', |
153
|
|
|
'options' => [ |
154
|
|
|
'title' => $this->applicationConfiguration->getTranslationKey('edit', $event->getAdmin()->getName()), |
155
|
|
|
'route' => $admin->generateRouteName('edit'), |
156
|
|
|
'parameters' => [ |
157
|
|
|
'id' => false |
158
|
|
|
], |
159
|
|
|
'icon' => 'pencil' |
160
|
|
|
] |
161
|
|
|
]; |
162
|
|
|
} |
163
|
|
View Code Duplication |
if (in_array('delete', $allowedActions)) { |
164
|
|
|
$configuration['fields']['_actions']['type'] = 'collection'; |
165
|
|
|
$configuration['fields']['_actions']['options']['_delete'] = [ |
166
|
|
|
'type' => 'action', |
167
|
|
|
'options' => [ |
168
|
|
|
'title' => $this->applicationConfiguration->getTranslationKey('delete', $event->getAdmin()->getName()), |
169
|
|
|
'route' => $admin->generateRouteName('delete'), |
170
|
|
|
'parameters' => [ |
171
|
|
|
'id' => false |
172
|
|
|
], |
173
|
|
|
'icon' => 'remove' |
174
|
|
|
] |
175
|
|
|
]; |
176
|
|
|
} |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
// add default menu actions if none was provided |
180
|
|
|
if (empty($configuration['actions'])) { |
181
|
|
|
// by default, in list action we add a create linked action |
182
|
|
|
if ($event->getActionName() == 'list') { |
183
|
|
|
if (in_array('create', $allowedActions)) { |
184
|
|
|
$configuration['actions']['create'] = [ |
185
|
|
|
'title' => $this->applicationConfiguration->getTranslationKey('create', $event->getAdmin()->getName()), |
186
|
|
|
'route' => $admin->generateRouteName('create'), |
187
|
|
|
'icon' => 'pencil' |
188
|
|
|
]; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
// for list action, add the delete batch action by defaut |
193
|
|
|
if (empty($configuration['batch'])) { |
194
|
|
|
if ($event->getActionName() == 'list') { |
195
|
|
|
$configuration['batch'] = [ |
196
|
|
|
'delete' => null |
197
|
|
|
]; |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
// reset action configuration |
201
|
|
|
$event->setConfiguration($configuration); |
202
|
|
|
} |
203
|
|
|
} |
204
|
|
|
|
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.