Completed
Pull Request — 5.6 (#2830)
by Jeroen
14:14
created

NodeBundle/Helper/Menu/ActionsMenuBuilder.php (4 issues)

Upgrade to new PHP Analysis Engine

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
You have injected the EntityManager via parameter $em. This is generally not recommended as it might get closed and become unusable. Instead, it is recommended to inject the ManagerRegistry and retrieve the EntityManager via getManager() each time you need it.

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:

function someFunction(ManagerRegistry $registry) {
    $em = $registry->getManager();
    $em->getConnection()->beginTransaction();
    try {
        // Do something.
        $em->getConnection()->commit();
    } catch (\Exception $ex) {
        $em->getConnection()->rollback();
        $em->close();

        throw $ex;
    }
}

If that code throws an exception and the EntityManager is closed. Any other code which depends on the same instance of the EntityManager during this request will fail.

On the other hand, if you instead inject the ManagerRegistry, the getManager() method guarantees that you will always get a usable manager instance.

Loading history...
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