These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\NodeBundle\Helper\Menu; |
||
4 | |||
5 | use Doctrine\ORM\EntityManager; |
||
6 | use FOS\UserBundle\Model\UserInterface; |
||
7 | use Knp\Menu\FactoryInterface; |
||
8 | use Knp\Menu\ItemInterface; |
||
9 | use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionMap; |
||
10 | use Kunstmaan\NodeBundle\Entity\NodeVersion; |
||
11 | use Kunstmaan\NodeBundle\Entity\QueuedNodeTranslationAction; |
||
12 | use Kunstmaan\NodeBundle\Event\ConfigureActionMenuEvent; |
||
13 | use Kunstmaan\NodeBundle\Event\Events; |
||
14 | use Kunstmaan\NodeBundle\Helper\PagesConfiguration; |
||
15 | use Kunstmaan\PagePartBundle\Helper\HasPageTemplateInterface; |
||
16 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
||
17 | use Symfony\Component\Routing\RouterInterface; |
||
18 | use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; |
||
19 | |||
20 | class ActionsMenuBuilder |
||
21 | { |
||
22 | /** |
||
23 | * @var FactoryInterface |
||
24 | */ |
||
25 | private $factory; |
||
26 | |||
27 | /** |
||
28 | * @var NodeVersion |
||
29 | */ |
||
30 | private $activeNodeVersion; |
||
31 | |||
32 | /** |
||
33 | * @var EntityManager |
||
34 | */ |
||
35 | private $em; |
||
36 | |||
37 | /** |
||
38 | * @var RouterInterface |
||
39 | */ |
||
40 | private $router; |
||
41 | |||
42 | /** |
||
43 | * @var EventDispatcherInterface |
||
44 | */ |
||
45 | private $dispatcher; |
||
46 | |||
47 | /** |
||
48 | * @var AuthorizationCheckerInterface |
||
49 | */ |
||
50 | private $authorizationChecker; |
||
51 | |||
52 | /** |
||
53 | * @var PagesConfiguration |
||
54 | */ |
||
55 | private $pagesConfiguration; |
||
56 | |||
57 | /** |
||
58 | * @var bool |
||
59 | */ |
||
60 | private $isEditableNode = true; |
||
61 | |||
62 | /** |
||
63 | * @var bool |
||
64 | */ |
||
65 | private $enableExportPageTemplate; |
||
66 | |||
67 | /** @var bool */ |
||
68 | private $showDuplicateWithChildren; |
||
69 | |||
70 | /** |
||
71 | * @param bool $enableExportPageTemplate |
||
72 | */ |
||
73 | 8 | public function __construct( |
|
74 | FactoryInterface $factory, |
||
75 | EntityManager $em, |
||
0 ignored issues
–
show
|
|||
76 | RouterInterface $router, |
||
77 | EventDispatcherInterface $dispatcher, |
||
78 | AuthorizationCheckerInterface $authorizationChecker, |
||
79 | PagesConfiguration $pagesConfiguration, |
||
80 | $enableExportPageTemplate = true, |
||
81 | bool $showDuplicateWithChildren = false |
||
82 | ) { |
||
83 | 8 | $this->factory = $factory; |
|
84 | 8 | $this->em = $em; |
|
85 | 8 | $this->router = $router; |
|
86 | 8 | $this->dispatcher = $dispatcher; |
|
87 | 8 | $this->authorizationChecker = $authorizationChecker; |
|
88 | 8 | $this->pagesConfiguration = $pagesConfiguration; |
|
89 | 8 | $this->enableExportPageTemplate = $enableExportPageTemplate; |
|
90 | 8 | $this->showDuplicateWithChildren = $showDuplicateWithChildren; |
|
91 | 8 | } |
|
92 | |||
93 | /** |
||
94 | * @return ItemInterface |
||
95 | */ |
||
96 | 1 | public function createSubActionsMenu() |
|
97 | { |
||
98 | 1 | $activeNodeVersion = $this->getActiveNodeVersion(); |
|
99 | 1 | $menu = $this->factory->createItem('root'); |
|
100 | 1 | $menu->setChildrenAttribute('class', 'page-sub-actions'); |
|
101 | |||
102 | 1 | if (null !== $activeNodeVersion && $this->isEditableNode) { |
|
103 | 1 | $menu->addChild( |
|
104 | 1 | 'subaction.versions', |
|
105 | [ |
||
106 | 'linkAttributes' => [ |
||
107 | 1 | 'data-toggle' => 'modal', |
|
108 | 'data-keyboard' => 'true', |
||
109 | 'data-target' => '#versions', |
||
110 | ], |
||
111 | ] |
||
112 | ); |
||
113 | } |
||
114 | |||
115 | 1 | $this->dispatcher->dispatch( |
|
116 | 1 | Events::CONFIGURE_SUB_ACTION_MENU, |
|
117 | 1 | new ConfigureActionMenuEvent( |
|
118 | 1 | $this->factory, |
|
119 | $menu, |
||
120 | $activeNodeVersion |
||
121 | ) |
||
122 | ); |
||
123 | |||
124 | 1 | return $menu; |
|
125 | } |
||
126 | |||
127 | /** |
||
128 | * @return ItemInterface |
||
129 | */ |
||
130 | 6 | public function createActionsMenu() |
|
131 | { |
||
132 | 6 | $activeNodeVersion = $this->getActiveNodeVersion(); |
|
133 | |||
134 | 6 | $translations = $activeNodeVersion->getNodeTranslation()->getNode()->getNodeTranslations(true); |
|
135 | 6 | $canRecopy = false; |
|
136 | 6 | foreach ($translations as $translation) { |
|
137 | 1 | if ($translation->getLang() != $activeNodeVersion->getNodeTranslation()->getLang()) { |
|
138 | 1 | $canRecopy = true; |
|
139 | } |
||
140 | } |
||
141 | |||
142 | 6 | $menu = $this->factory->createItem('root'); |
|
143 | 6 | $menu->setChildrenAttribute( |
|
144 | 6 | 'class', |
|
145 | 6 | 'page-main-actions js-auto-collapse-buttons' |
|
146 | ); |
||
147 | 6 | $menu->setChildrenAttribute( |
|
148 | 6 | 'data-visible-buttons', |
|
149 | 6 | '3' |
|
150 | ); |
||
151 | |||
152 | 6 | if (null === $activeNodeVersion) { |
|
153 | $this->dispatcher->dispatch( |
||
154 | Events::CONFIGURE_ACTION_MENU, |
||
155 | new ConfigureActionMenuEvent( |
||
156 | $this->factory, |
||
157 | $menu, |
||
158 | $activeNodeVersion |
||
159 | ) |
||
160 | ); |
||
161 | |||
162 | return $menu; |
||
163 | } |
||
164 | |||
165 | 6 | $activeNodeTranslation = $activeNodeVersion->getNodeTranslation(); |
|
166 | 6 | $node = $activeNodeTranslation->getNode(); |
|
167 | 6 | $queuedNodeTranslationAction = $this->em->getRepository(QueuedNodeTranslationAction::class)->findOneBy(['nodeTranslation' => $activeNodeTranslation]); |
|
168 | |||
169 | 6 | $isFirst = true; |
|
170 | 6 | $canEdit = $this->authorizationChecker->isGranted(PermissionMap::PERMISSION_EDIT, $node); |
|
171 | 6 | $canPublish = $this->authorizationChecker->isGranted(PermissionMap::PERMISSION_PUBLISH, $node); |
|
172 | 6 | $isSuperAdmin = $this->authorizationChecker->isGranted(UserInterface::ROLE_SUPER_ADMIN); |
|
173 | |||
174 | 6 | if ($activeNodeVersion->isDraft() && $this->isEditableNode) { |
|
175 | 1 | View Code Duplication | if ($canEdit) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
176 | 1 | $menu->addChild( |
|
177 | 1 | 'action.saveasdraft', |
|
178 | [ |
||
179 | 'linkAttributes' => [ |
||
180 | 1 | 'type' => 'submit', |
|
181 | 'class' => 'js-save-btn btn btn--raise-on-hover btn-primary', |
||
182 | 'value' => 'save', |
||
183 | 'name' => 'save', |
||
184 | ], |
||
185 | 'extras' => ['renderType' => 'button'], |
||
186 | ] |
||
187 | ); |
||
188 | 1 | if ($this->enableExportPageTemplate && $isSuperAdmin && is_subclass_of($node->getRefEntityName(), HasPageTemplateInterface::class)) { |
|
189 | $menu->addChild( |
||
190 | 'action.exportpagetemplate', |
||
191 | [ |
||
192 | 'linkAttributes' => [ |
||
193 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
194 | 'data-toggle' => 'modal', |
||
195 | 'data-keyboard' => 'true', |
||
196 | 'data-target' => '#exportPagetemplate', |
||
197 | ], |
||
198 | ] |
||
199 | ); |
||
200 | } |
||
201 | 1 | if ($canRecopy) { |
|
202 | $menu->addChild( |
||
203 | 'action.recopyfromlanguage', |
||
204 | [ |
||
205 | 'linkAttributes' => [ |
||
206 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
207 | 'data-toggle' => 'modal', |
||
208 | 'data-keyboard' => 'true', |
||
209 | 'data-target' => '#recopy', |
||
210 | ], |
||
211 | ] |
||
212 | ); |
||
213 | } |
||
214 | 1 | $isFirst = false; |
|
215 | } |
||
216 | |||
217 | 1 | $menu->addChild( |
|
218 | 1 | 'action.preview', |
|
219 | [ |
||
220 | 1 | 'uri' => $this->router->generate( |
|
221 | 1 | '_slug_preview', |
|
222 | [ |
||
223 | 1 | 'url' => $activeNodeTranslation->getUrl(), |
|
224 | 1 | 'version' => $activeNodeVersion->getId(), |
|
225 | ] |
||
226 | ), |
||
227 | 'linkAttributes' => [ |
||
228 | 'target' => '_blank', |
||
229 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
230 | ], |
||
231 | ] |
||
232 | ); |
||
233 | |||
234 | 1 | View Code Duplication | if (empty($queuedNodeTranslationAction) && $canPublish) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
235 | 1 | $menu->addChild( |
|
236 | 1 | 'action.publish', |
|
237 | [ |
||
238 | 'linkAttributes' => [ |
||
239 | 1 | 'data-toggle' => 'modal', |
|
240 | 1 | 'data-target' => '#pub', |
|
241 | 1 | 'class' => 'btn btn--raise-on-hover' . ($isFirst ? ' btn-primary btn-save' : ' btn-default'), |
|
242 | ], |
||
243 | ] |
||
244 | ); |
||
245 | } |
||
246 | } else { |
||
247 | 5 | if ($canEdit && $canPublish) { |
|
248 | 5 | $menu->addChild( |
|
249 | 5 | 'action.save', |
|
250 | [ |
||
251 | 'linkAttributes' => [ |
||
252 | 5 | 'type' => 'submit', |
|
253 | 'class' => 'js-save-btn btn btn--raise-on-hover btn-primary', |
||
254 | 'value' => 'save', |
||
255 | 'name' => 'save', |
||
256 | ], |
||
257 | 'extras' => ['renderType' => 'button'], |
||
258 | ] |
||
259 | ); |
||
260 | 5 | $isFirst = false; |
|
261 | } |
||
262 | |||
263 | 5 | if ($this->isEditableNode) { |
|
264 | 4 | $menu->addChild( |
|
265 | 4 | 'action.preview', |
|
266 | [ |
||
267 | 4 | 'uri' => $this->router->generate( |
|
268 | 4 | '_slug_preview', |
|
269 | 4 | ['url' => $activeNodeTranslation->getUrl()] |
|
270 | ), |
||
271 | 'linkAttributes' => [ |
||
272 | 'target' => '_blank', |
||
273 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
274 | ], |
||
275 | ] |
||
276 | ); |
||
277 | |||
278 | 4 | if (empty($queuedNodeTranslationAction) |
|
279 | 4 | && $activeNodeTranslation->isOnline() |
|
280 | 1 | && $this->authorizationChecker->isGranted( |
|
281 | 4 | PermissionMap::PERMISSION_UNPUBLISH, |
|
282 | $node |
||
283 | ) |
||
284 | ) { |
||
285 | 1 | $menu->addChild( |
|
286 | 1 | 'action.unpublish', |
|
287 | [ |
||
288 | 'linkAttributes' => [ |
||
289 | 1 | 'class' => 'btn btn-default btn--raise-on-hover', |
|
290 | 'data-toggle' => 'modal', |
||
291 | 'data-keyboard' => 'true', |
||
292 | 'data-target' => '#unpub', |
||
293 | ], |
||
294 | ] |
||
295 | ); |
||
296 | 4 | View Code Duplication | } elseif (empty($queuedNodeTranslationAction) |
297 | 4 | && !$activeNodeTranslation->isOnline() |
|
298 | 4 | && $canPublish |
|
299 | ) { |
||
300 | 4 | $menu->addChild( |
|
301 | 4 | 'action.publish', |
|
302 | [ |
||
303 | 'linkAttributes' => [ |
||
304 | 4 | 'class' => 'btn btn-default btn--raise-on-hover', |
|
305 | 'data-toggle' => 'modal', |
||
306 | 'data-keyboard' => 'true', |
||
307 | 'data-target' => '#pub', |
||
308 | ], |
||
309 | ] |
||
310 | ); |
||
311 | } |
||
312 | |||
313 | 4 | View Code Duplication | if ($canEdit) { |
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
314 | 4 | $menu->addChild( |
|
315 | 4 | 'action.saveasdraft', |
|
316 | [ |
||
317 | 'linkAttributes' => [ |
||
318 | 4 | 'type' => 'submit', |
|
319 | 4 | 'class' => 'btn btn--raise-on-hover' . ($isFirst ? ' btn-primary btn-save' : ' btn-default'), |
|
320 | 4 | 'value' => 'saveasdraft', |
|
321 | 4 | 'name' => 'saveasdraft', |
|
322 | ], |
||
323 | 'extras' => ['renderType' => 'button'], |
||
324 | ] |
||
325 | ); |
||
326 | 4 | if ($this->enableExportPageTemplate && $isSuperAdmin && is_subclass_of($node->getRefEntityName(), HasPageTemplateInterface::class)) { |
|
327 | $menu->addChild( |
||
328 | 'action.exportpagetemplate', |
||
329 | [ |
||
330 | 'linkAttributes' => [ |
||
331 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
332 | 'data-toggle' => 'modal', |
||
333 | 'data-keyboard' => 'true', |
||
334 | 'data-target' => '#exportPagetemplate', |
||
335 | ], |
||
336 | ] |
||
337 | ); |
||
338 | } |
||
339 | 4 | if ($canRecopy) { |
|
340 | 1 | $menu->addChild( |
|
341 | 1 | 'action.recopyfromlanguage', |
|
342 | [ |
||
343 | 'linkAttributes' => [ |
||
344 | 1 | 'class' => 'btn btn-default btn--raise-on-hover', |
|
345 | 'data-toggle' => 'modal', |
||
346 | 'data-keyboard' => 'true', |
||
347 | 'data-target' => '#recopy', |
||
348 | ], |
||
349 | ] |
||
350 | ); |
||
351 | } |
||
352 | } |
||
353 | } |
||
354 | } |
||
355 | |||
356 | 6 | View Code Duplication | if ($this->pagesConfiguration->getPossibleChildTypes( |
357 | 6 | $node->getRefEntityName() |
|
358 | ) |
||
359 | ) { |
||
360 | $menu->addChild( |
||
361 | 'action.addsubpage', |
||
362 | [ |
||
363 | 'linkAttributes' => [ |
||
364 | 'type' => 'button', |
||
365 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
366 | 'data-toggle' => 'modal', |
||
367 | 'data-keyboard' => 'true', |
||
368 | 'data-target' => '#add-subpage-modal', |
||
369 | ], |
||
370 | 'extras' => ['renderType' => 'button'], |
||
371 | ] |
||
372 | ); |
||
373 | } |
||
374 | |||
375 | 6 | if (null !== $node->getParent() && $canEdit) { |
|
376 | 1 | $menu->addChild( |
|
377 | 1 | 'action.duplicate', |
|
378 | [ |
||
379 | 'linkAttributes' => [ |
||
380 | 1 | 'type' => 'button', |
|
381 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
382 | 'data-toggle' => 'modal', |
||
383 | 'data-keyboard' => 'true', |
||
384 | 'data-target' => '#duplicate-page-modal', |
||
385 | ], |
||
386 | 'extras' => ['renderType' => 'button'], |
||
387 | ] |
||
388 | ); |
||
389 | |||
390 | 1 | View Code Duplication | if ($this->showDuplicateWithChildren) { |
391 | $menu->addChild( |
||
392 | 'action.duplicate_with_children', |
||
393 | [ |
||
394 | 'linkAttributes' => [ |
||
395 | 'type' => 'button', |
||
396 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
397 | 'data-toggle' => 'modal', |
||
398 | 'data-keyboard' => 'true', |
||
399 | 'data-target' => '#duplicate-with-children-page-modal', |
||
400 | ], |
||
401 | 'extras' => ['renderType' => 'button'], |
||
402 | ] |
||
403 | ); |
||
404 | } |
||
405 | } |
||
406 | |||
407 | 6 | if ((null !== $node->getParent() || $node->getChildren()->isEmpty()) |
|
408 | 6 | && $this->authorizationChecker->isGranted( |
|
409 | 6 | PermissionMap::PERMISSION_DELETE, |
|
410 | $node |
||
411 | ) |
||
412 | ) { |
||
413 | 6 | $menu->addChild( |
|
414 | 6 | 'action.delete', |
|
415 | [ |
||
416 | 'linkAttributes' => [ |
||
417 | 6 | 'type' => 'button', |
|
418 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
419 | 'onClick' => 'oldEdited = isEdited; isEdited=false', |
||
420 | 'data-toggle' => 'modal', |
||
421 | 'data-keyboard' => 'true', |
||
422 | 'data-target' => '#delete-page-modal', |
||
423 | ], |
||
424 | 'extras' => ['renderType' => 'button'], |
||
425 | ] |
||
426 | ); |
||
427 | } |
||
428 | |||
429 | 6 | $this->dispatcher->dispatch( |
|
430 | 6 | Events::CONFIGURE_ACTION_MENU, |
|
431 | 6 | new ConfigureActionMenuEvent( |
|
432 | 6 | $this->factory, |
|
433 | $menu, |
||
434 | $activeNodeVersion |
||
435 | ) |
||
436 | ); |
||
437 | |||
438 | 6 | return $menu; |
|
439 | } |
||
440 | |||
441 | /** |
||
442 | * @return ItemInterface |
||
443 | */ |
||
444 | 1 | public function createTopActionsMenu() |
|
445 | { |
||
446 | 1 | $menu = $this->createActionsMenu(); |
|
447 | 1 | $menu->setChildrenAttribute('id', 'page-main-actions-top'); |
|
448 | 1 | $menu->setChildrenAttribute( |
|
449 | 1 | 'class', |
|
450 | 1 | 'page-main-actions page-main-actions--top' |
|
451 | ); |
||
452 | |||
453 | 1 | return $menu; |
|
454 | } |
||
455 | |||
456 | /** |
||
457 | * @return ItemInterface |
||
458 | */ |
||
459 | public function createHomeActionsMenu() |
||
460 | { |
||
461 | $menu = $this->factory->createItem('root'); |
||
462 | $menu->setChildrenAttribute( |
||
463 | 'class', |
||
464 | 'page-main-actions js-auto-collapse-buttons' |
||
465 | ); |
||
466 | $menu->addChild( |
||
467 | 'action.addhomepage', |
||
468 | [ |
||
469 | 'linkAttributes' => [ |
||
470 | 'type' => 'button', |
||
471 | 'class' => 'btn btn-default btn--raise-on-hover', |
||
472 | 'data-toggle' => 'modal', |
||
473 | 'data-keyboard' => 'true', |
||
474 | 'data-target' => '#add-homepage-modal', |
||
475 | ], |
||
476 | 'extras' => ['renderType' => 'button'], |
||
477 | ] |
||
478 | ); |
||
479 | |||
480 | return $menu; |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * @return ItemInterface |
||
485 | */ |
||
486 | public function createTopHomeActionsMenu() |
||
487 | { |
||
488 | $menu = $this->createHomeActionsMenu(); |
||
489 | $menu->setChildrenAttribute('id', 'page-main-actions-top'); |
||
490 | $menu->setChildrenAttribute( |
||
491 | 'class', |
||
492 | 'page-main-actions page-main-actions--top' |
||
493 | ); |
||
494 | |||
495 | return $menu; |
||
496 | } |
||
497 | |||
498 | /** |
||
499 | * Set activeNodeVersion |
||
500 | * |
||
501 | * @return ActionsMenuBuilder |
||
502 | */ |
||
503 | 8 | public function setActiveNodeVersion(NodeVersion $activeNodeVersion) |
|
504 | { |
||
505 | 8 | $this->activeNodeVersion = $activeNodeVersion; |
|
506 | |||
507 | 8 | return $this; |
|
508 | } |
||
509 | |||
510 | /** |
||
511 | * Get activeNodeVersion |
||
512 | * |
||
513 | * @return NodeVersion |
||
514 | */ |
||
515 | 8 | public function getActiveNodeVersion() |
|
516 | { |
||
517 | 8 | return $this->activeNodeVersion; |
|
518 | } |
||
519 | |||
520 | /** |
||
521 | * @param bool $value |
||
522 | */ |
||
523 | 1 | public function setEditableNode($value) |
|
524 | { |
||
525 | 1 | $this->isEditableNode = $value; |
|
526 | 1 | } |
|
527 | } |
||
528 |
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.