1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Victoire\Bundle\WidgetMapBundle\Manager; |
4
|
|
|
|
5
|
|
|
use Doctrine\Orm\EntityManager; |
6
|
|
|
use Victoire\Bundle\CoreBundle\Entity\View; |
7
|
|
|
use Victoire\Bundle\WidgetBundle\Entity\Widget; |
8
|
|
|
use Victoire\Bundle\WidgetMapBundle\Builder\WidgetMapBuilder; |
9
|
|
|
use Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap; |
10
|
|
|
use Victoire\Bundle\WidgetMapBundle\Helper\WidgetMapHelper; |
11
|
|
|
|
12
|
|
|
class WidgetMapManager |
13
|
|
|
{ |
14
|
|
|
private $em; |
15
|
|
|
private $builder; |
16
|
|
|
|
17
|
|
|
public function __construct(EntityManager $em, WidgetMapBuilder $builder) |
|
|
|
|
18
|
|
|
{ |
19
|
|
|
$this->em = $em; |
20
|
|
|
$this->builder = $builder; |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Insert a WidgetMap in a view at given position. |
25
|
|
|
* |
26
|
|
|
* @param string $slotId |
27
|
|
|
*/ |
28
|
|
|
public function insert(Widget $widget, View $view, $slotId, $position, $widgetReference) |
29
|
|
|
{ |
30
|
|
|
$quantum = $this->em->getRepository('VictoireWidgetMapBundle:WidgetMap')->findOneBy([ |
31
|
|
|
'view' => $view, |
32
|
|
|
'slot' => $slotId, |
33
|
|
|
'position' => $position, |
34
|
|
|
'parent' => $widgetReference, |
35
|
|
|
'action' => [ |
36
|
|
|
WidgetMap::ACTION_CREATE, |
37
|
|
|
WidgetMap::ACTION_OVERWRITE |
38
|
|
|
] |
39
|
|
|
]); |
40
|
|
|
|
41
|
|
|
if ($quantum) { |
42
|
|
|
$widget->setWidgetMap($quantum); |
43
|
|
|
$view->addWidgetMap($quantum); |
44
|
|
|
} else { |
45
|
|
|
$parent = null; |
46
|
|
|
if ($widgetReference) { |
47
|
|
|
$parent = $this->em->getRepository('VictoireWidgetMapBundle:WidgetMap')->find($widgetReference); |
48
|
|
|
} |
49
|
|
|
//create the new widget map |
50
|
|
|
$widgetMapEntry = new WidgetMap(); |
51
|
|
|
$widgetMapEntry->setAction(WidgetMap::ACTION_CREATE); |
52
|
|
|
$widgetMapEntry->setSlot($slotId); |
53
|
|
|
$widgetMapEntry->setPosition($position); |
54
|
|
|
$widgetMapEntry->setParent($parent); |
|
|
|
|
55
|
|
|
$widget->setWidgetMap($widgetMapEntry); |
56
|
|
|
|
57
|
|
|
$view->addWidgetMap($widgetMapEntry); |
58
|
|
|
} |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* moves a widget in a view. |
63
|
|
|
* |
64
|
|
|
* @param View $view |
65
|
|
|
* @param array $sortedWidget |
66
|
|
|
* |
67
|
|
|
* @return void |
68
|
|
|
*/ |
69
|
|
|
public function move(View $view, $sortedWidget) |
70
|
|
|
{ |
71
|
|
|
/** @var WidgetMap $parentWidgetMap */ |
72
|
|
|
$parentWidgetMap = $this->em->getRepository('VictoireWidgetMapBundle:WidgetMap')->find((int) $sortedWidget['parentWidgetMap']); |
73
|
|
|
$position = $sortedWidget['position']; |
74
|
|
|
$slot = $sortedWidget['slot']; |
75
|
|
|
/** @var WidgetMap $widgetMap */ |
76
|
|
|
$widgetMap = $this->em->getRepository('VictoireWidgetMapBundle:WidgetMap')->find((int) $sortedWidget['widgetMap']); |
77
|
|
|
|
78
|
|
|
$originalParent = $widgetMap->getParent(); |
79
|
|
|
$originalPosition = $widgetMap->getPosition(); |
80
|
|
|
|
81
|
|
|
$children = $widgetMap->getChildren($view); |
82
|
|
|
$beforeChild = !empty($children[WidgetMap::POSITION_BEFORE]) ? $children[WidgetMap::POSITION_BEFORE] : null; |
83
|
|
|
$afterChild = !empty($children[WidgetMap::POSITION_AFTER]) ? $children[WidgetMap::POSITION_AFTER] : null; |
84
|
|
|
|
85
|
|
|
$parentWidgetMapChildren = $this->getChildrenByView($parentWidgetMap); |
86
|
|
|
|
87
|
|
|
$widgetMap = $this->moveWidgetMap($view, $widgetMap, $parentWidgetMap, $position, $slot); |
|
|
|
|
88
|
|
|
|
89
|
|
|
// If the moved widgetMap has someone at both his before and after, arbitrary move UP the before side |
90
|
|
|
// and find the first place after the before widgetMap hierarchy to place the after widgetMap. |
91
|
|
|
$this->moveChildren($view, $beforeChild, $afterChild, $originalParent, $originalPosition); |
92
|
|
|
|
93
|
|
|
foreach ($parentWidgetMapChildren['views'] as $_view) { |
94
|
|
|
if ($_view !== $view) { |
95
|
|
View Code Duplication |
if (isset($parentWidgetMapChildren['before'][$_view->getId()]) && $parentWidgetMapChildren['before'][$_view->getId()]->getPosition() == $widgetMap->getPosition()) { |
|
|
|
|
96
|
|
|
$parentWidgetMapChildren['before'][$_view->getId()]->setParent($widgetMap); |
97
|
|
|
} |
98
|
|
View Code Duplication |
if (isset($parentWidgetMapChildren['after'][$_view->getId()]) && $parentWidgetMapChildren['after'][$_view->getId()]->getPosition() == $widgetMap->getPosition()) { |
|
|
|
|
99
|
|
|
$parentWidgetMapChildren['after'][$_view->getId()]->setParent($widgetMap); |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Delete the widget from the view. |
107
|
|
|
* |
108
|
|
|
* @param View $view |
109
|
|
|
* @param Widget $widget |
110
|
|
|
* |
111
|
|
|
* @throws \Exception Widget map does not exists |
112
|
|
|
*/ |
113
|
|
|
public function delete(View $view, Widget $widget) |
114
|
|
|
{ |
115
|
|
|
$this->builder->build($view); |
116
|
|
|
|
117
|
|
|
$widgetMap = WidgetMapHelper::getWidgetMapByWidgetAndView($widget, $view); |
118
|
|
|
$slot = $widgetMap->getSlot(); |
|
|
|
|
119
|
|
|
|
120
|
|
|
$originalParent = $widgetMap->getParent(); |
|
|
|
|
121
|
|
|
$originalPosition = $widgetMap->getPosition(); |
|
|
|
|
122
|
|
|
|
123
|
|
|
$children = $widgetMap->getChildren($view); |
|
|
|
|
124
|
|
|
$beforeChild = !empty($children[WidgetMap::POSITION_BEFORE]) ? $children[WidgetMap::POSITION_BEFORE] : null; |
125
|
|
|
$afterChild = !empty($children[WidgetMap::POSITION_AFTER]) ? $children[WidgetMap::POSITION_AFTER] : null; |
126
|
|
|
|
127
|
|
|
//we remove the widget from the current view |
128
|
|
|
if ($widgetMap->getView() === $view) { |
|
|
|
|
129
|
|
|
// If the widgetMap has substitutes, delete them or transform them in create mode |
130
|
|
|
if (count($widgetMap->getSubstitutes()) > 0) { |
131
|
|
|
foreach ($widgetMap->getSubstitutes() as $substitute) { |
|
|
|
|
132
|
|
|
if ($substitute->getAction() === WidgetMap::ACTION_OVERWRITE) { |
133
|
|
|
$substitute->setAction(WidgetMap::ACTION_CREATE); |
134
|
|
|
$substitute->setReplaced(null); |
135
|
|
|
} else { |
136
|
|
|
$view->removeWidgetMap($widgetMap); |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
//remove the widget map from the slot |
141
|
|
|
$view->removeWidgetMap($widgetMap); |
142
|
|
|
} else { |
143
|
|
|
//the widget is owned by another view (a parent) |
144
|
|
|
//so we add a new widget map that indicates we delete this widget |
145
|
|
|
$replaceWidgetMap = new WidgetMap(); |
146
|
|
|
$replaceWidgetMap->setAction(WidgetMap::ACTION_DELETE); |
147
|
|
|
$replaceWidgetMap->setWidget($widget); |
|
|
|
|
148
|
|
|
$replaceWidgetMap->setSlot($slot); |
149
|
|
|
$replaceWidgetMap->setReplaced($widgetMap); |
150
|
|
|
|
151
|
|
|
$view->addWidgetMap($replaceWidgetMap); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
$this->moveChildren($view, $beforeChild, $afterChild, $originalParent, $originalPosition); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* the widget is owned by another view (a parent) |
159
|
|
|
* so we add a new widget map that indicates we delete this widget. |
160
|
|
|
* |
161
|
|
|
* @param View $view |
162
|
|
|
* @param WidgetMap $originalWidgetMap |
163
|
|
|
* @param Widget $widgetCopy |
164
|
|
|
* |
165
|
|
|
* @throws \Exception |
166
|
|
|
*/ |
167
|
|
|
public function overwrite(View $view, WidgetMap $originalWidgetMap, Widget $widgetCopy) |
168
|
|
|
{ |
169
|
|
|
$widgetMap = new WidgetMap(); |
170
|
|
|
$widgetMap->setAction(WidgetMap::ACTION_OVERWRITE); |
171
|
|
|
$widgetMap->setReplaced($originalWidgetMap); |
172
|
|
|
$widgetCopy->setWidgetMap($widgetMap); |
173
|
|
|
$widgetMap->setSlot($originalWidgetMap->getSlot()); |
174
|
|
|
$widgetMap->setPosition($originalWidgetMap->getPosition()); |
175
|
|
|
$widgetMap->setParent($originalWidgetMap->getParent()); |
176
|
|
|
|
177
|
|
|
$view->addWidgetMap($widgetMap); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* If the moved widgetMap has someone at both his before and after, arbitrary move UP the before side |
182
|
|
|
* and find the first place after the before widgetMap hierarchy to place the after widgetMap. |
183
|
|
|
* |
184
|
|
|
* @param View $view |
185
|
|
|
* @param $beforeChild |
186
|
|
|
* @param $afterChild |
187
|
|
|
* @param $originalParent |
188
|
|
|
* @param $originalPosition |
189
|
|
|
*/ |
190
|
|
|
public function moveChildren(View $view, $beforeChild, $afterChild, $originalParent, $originalPosition) |
191
|
|
|
{ |
192
|
|
|
if ($beforeChild && $afterChild) { |
193
|
|
|
$this->moveWidgetMap($view, $beforeChild, $originalParent, $originalPosition); |
194
|
|
|
|
195
|
|
|
$child = $beforeChild; |
196
|
|
|
while ($child->getChild(WidgetMap::POSITION_AFTER)) { |
197
|
|
|
$child = $child->getChild(WidgetMap::POSITION_AFTER); |
198
|
|
|
} |
199
|
|
|
if ($afterChild->getId() !== $child->getId()) { |
200
|
|
|
$this->moveWidgetMap($view, $afterChild, $child); |
201
|
|
|
} |
202
|
|
|
} elseif ($beforeChild) { |
203
|
|
|
$this->moveWidgetMap($view, $beforeChild, $originalParent, $originalPosition); |
204
|
|
|
} elseif ($afterChild) { |
205
|
|
|
$this->moveWidgetMap($view, $afterChild, $originalParent, $originalPosition); |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Create a copy of a WidgetMap in "overwrite" mode and insert it in the given view. |
211
|
|
|
* |
212
|
|
|
* @param WidgetMap $widgetMap |
213
|
|
|
* @param View $view |
214
|
|
|
* |
215
|
|
|
* @throws \Exception |
216
|
|
|
* |
217
|
|
|
* @return WidgetMap |
218
|
|
|
*/ |
219
|
|
|
protected function cloneWidgetMap(WidgetMap $widgetMap, View $view) |
220
|
|
|
{ |
221
|
|
|
$originalWidgetMap = $widgetMap; |
222
|
|
|
$widgetMap = clone $widgetMap; |
223
|
|
|
$widgetMap->setId(null); |
224
|
|
|
$widgetMap->setAction(WidgetMap::ACTION_OVERWRITE); |
225
|
|
|
$widgetMap->setReplaced($originalWidgetMap); |
226
|
|
|
$widgetMap->setView($view); |
227
|
|
|
$view->addWidgetMap($widgetMap); |
228
|
|
|
$this->em->persist($widgetMap); |
229
|
|
|
|
230
|
|
|
return $widgetMap; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Move given WidgetMap as a child of given parent at given position and slot. |
235
|
|
|
* |
236
|
|
|
* @param View $view |
237
|
|
|
* @param WidgetMap $widgetMap |
238
|
|
|
* @param bool $parent |
239
|
|
|
* @param bool $position |
240
|
|
|
* @param bool $slot |
241
|
|
|
* |
242
|
|
|
* @return WidgetMap |
243
|
|
|
*/ |
244
|
|
|
protected function moveWidgetMap(View $view, WidgetMap $widgetMap, $parent = false, $position = false, $slot = false) |
245
|
|
|
{ |
246
|
|
|
if ($widgetMap->getView() !== $view) { |
247
|
|
|
$widgetMap = $this->cloneWidgetMap($widgetMap, $view); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
if ($parent !== false) { |
251
|
|
|
if ($oldParent = $widgetMap->getParent()) { |
252
|
|
|
$oldParent->removeChild($widgetMap); |
253
|
|
|
} |
254
|
|
|
$widgetMap->setParent($parent); |
|
|
|
|
255
|
|
|
if ($parent) { |
256
|
|
|
$parent->addChild($widgetMap); |
|
|
|
|
257
|
|
|
} |
258
|
|
|
} |
259
|
|
|
if ($position !== false) { |
260
|
|
|
$widgetMap->setPosition($position); |
|
|
|
|
261
|
|
|
} |
262
|
|
|
if ($slot !== false) { |
263
|
|
|
$widgetMap->setSlot($slot); |
|
|
|
|
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
return $widgetMap; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Find return all the given WidgetMap children for each view where it's related. |
271
|
|
|
* |
272
|
|
|
* @param WidgetMap $widgetMap |
273
|
|
|
* |
274
|
|
|
* @return mixed |
275
|
|
|
*/ |
276
|
|
|
protected function getChildrenByView(WidgetMap $widgetMap) |
277
|
|
|
{ |
278
|
|
|
$beforeChilds = $widgetMap->getChilds(WidgetMap::POSITION_BEFORE); |
279
|
|
|
$afterChilds = $widgetMap->getChilds(WidgetMap::POSITION_AFTER); |
280
|
|
|
|
281
|
|
|
$childrenByView['views'] = []; |
|
|
|
|
282
|
|
|
$childrenByView['before'] = []; |
283
|
|
|
$childrenByView['after'] = []; |
284
|
|
|
foreach ($beforeChilds as $beforeChild) { |
285
|
|
|
$view = $beforeChild->getView(); |
286
|
|
|
$childrenByView['views'][] = $view; |
287
|
|
|
$childrenByView['before'][$view->getId()] = $beforeChild; |
288
|
|
|
} |
289
|
|
|
foreach ($afterChilds as $afterChild) { |
290
|
|
|
$view = $afterChild->getView(); |
291
|
|
|
$childrenByView['views'][] = $view; |
292
|
|
|
$childrenByView['after'][$view->getId()] = $afterChild; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
return $childrenByView; |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
|
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.