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

NodeBundle/Controller/NodeAdminController.php (2 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\Controller;
4
5
use DateTime;
6
use Doctrine\Common\Collections\ArrayCollection;
7
use Doctrine\ORM\EntityManager;
8
use InvalidArgumentException;
9
use Kunstmaan\AdminBundle\Entity\BaseUser;
10
use Kunstmaan\AdminBundle\Entity\EntityInterface;
11
use Kunstmaan\AdminBundle\FlashMessages\FlashTypes;
12
use Kunstmaan\AdminBundle\Helper\FormWidgets\FormWidget;
13
use Kunstmaan\AdminBundle\Helper\FormWidgets\Tabs\Tab;
14
use Kunstmaan\AdminBundle\Helper\FormWidgets\Tabs\TabPane;
15
use Kunstmaan\AdminBundle\Helper\Security\Acl\AclHelper;
16
use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionMap;
17
use Kunstmaan\AdminBundle\Service\AclManager;
18
use Kunstmaan\AdminListBundle\AdminList\AdminList;
19
use Kunstmaan\NodeBundle\AdminList\NodeAdminListConfigurator;
20
use Kunstmaan\NodeBundle\Entity\HasNodeInterface;
21
use Kunstmaan\NodeBundle\Entity\Node;
22
use Kunstmaan\NodeBundle\Entity\NodeTranslation;
23
use Kunstmaan\NodeBundle\Entity\NodeVersion;
24
use Kunstmaan\NodeBundle\Entity\QueuedNodeTranslationAction;
25
use Kunstmaan\NodeBundle\Event\AdaptFormEvent;
26
use Kunstmaan\NodeBundle\Event\CopyPageTranslationNodeEvent;
27
use Kunstmaan\NodeBundle\Event\Events;
28
use Kunstmaan\NodeBundle\Event\NodeEvent;
29
use Kunstmaan\NodeBundle\Event\RecopyPageTranslationNodeEvent;
30
use Kunstmaan\NodeBundle\Event\RevertNodeAction;
31
use Kunstmaan\NodeBundle\Form\NodeMenuTabAdminType;
32
use Kunstmaan\NodeBundle\Form\NodeMenuTabTranslationAdminType;
33
use Kunstmaan\NodeBundle\Helper\NodeAdmin\NodeAdminPublisher;
34
use Kunstmaan\NodeBundle\Helper\NodeAdmin\NodeVersionLockHelper;
35
use Kunstmaan\NodeBundle\Helper\PageCloningHelper;
36
use Kunstmaan\NodeBundle\Repository\NodeVersionRepository;
37
use Kunstmaan\UtilitiesBundle\Helper\ClassLookup;
38
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
39
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
40
use Symfony\Component\HttpFoundation\JsonResponse;
41
use Symfony\Component\HttpFoundation\RedirectResponse;
42
use Symfony\Component\HttpFoundation\Request;
43
use Symfony\Component\Routing\Annotation\Route;
44
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
45
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
46
use Symfony\Component\Translation\TranslatorInterface;
47
48
/**
49
 * NodeAdminController
50
 */
51
class NodeAdminController extends Controller
52
{
53
    /**
54
     * @var EntityManager
55
     */
56
    protected $em;
57
58
    /**
59
     * @var string
60
     */
61
    protected $locale;
62
63
    /**
64
     * @var AuthorizationCheckerInterface
65
     */
66
    protected $authorizationChecker;
67
68
    /**
69
     * @var BaseUser
70
     */
71
    protected $user;
72
73
    /**
74
     * @var AclHelper
75
     */
76
    protected $aclHelper;
77
78
    /**
79
     * @var AclManager
80
     */
81
    protected $aclManager;
82
83
    /**
84
     * @var NodeAdminPublisher
85
     */
86
    protected $nodePublisher;
87
88
    /**
89
     * @var TranslatorInterface
90
     */
91
    protected $translator;
92
93
    /** @var PageCloningHelper */
94
    private $pageCloningHelper;
95
96
    /**
97
     * init
98
     */
99
    protected function init(Request $request)
100
    {
101
        $this->em = $this->getDoctrine()->getManager();
102
        $this->locale = $request->getLocale();
103
        $this->authorizationChecker = $this->container->get('security.authorization_checker');
104
        $this->user = $this->getUser();
105
        $this->aclHelper = $this->container->get('kunstmaan_admin.acl.helper');
106
        $this->aclManager = $this->container->get('kunstmaan_admin.acl.manager');
107
        $this->nodePublisher = $this->container->get('kunstmaan_node.admin_node.publisher');
108
        $this->translator = $this->container->get('translator');
109
        $this->pageCloningHelper = $this->container->get(PageCloningHelper::class);
110
    }
111
112
    /**
113
     * @Route("/", name="KunstmaanNodeBundle_nodes")
114
     * @Template("@KunstmaanNode/Admin/list.html.twig")
115
     *
116
     * @return array
117
     */
118
    public function indexAction(Request $request)
119
    {
120
        $this->init($request);
121
122
        $nodeAdminListConfigurator = new NodeAdminListConfigurator(
123
            $this->em,
124
            $this->aclHelper,
125
            $this->locale,
126
            PermissionMap::PERMISSION_VIEW,
127
            $this->authorizationChecker
128
        );
129
130
        $locale = $this->locale;
131
        $acl = $this->authorizationChecker;
132
        $itemRoute = function (EntityInterface $item) use ($locale, $acl) {
133
            if ($acl->isGranted(PermissionMap::PERMISSION_VIEW, $item->getNode())) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Kunstmaan\AdminBundle\Entity\EntityInterface as the method getNode() does only exist in the following implementations of said interface: Kunstmaan\FormBundle\Entity\FormSubmission, Kunstmaan\FormBundle\Tes...List\FakeFormSubmission, Kunstmaan\NodeBundle\Entity\NodeTranslation, Kunstmaan\NodeSearchBundle\Entity\NodeSearch.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
134
                return [
135
                    'path' => '_slug_preview',
136
                    'params' => ['_locale' => $locale, 'url' => $item->getUrl()],
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Kunstmaan\AdminBundle\Entity\EntityInterface as the method getUrl() does only exist in the following implementations of said interface: Kunstmaan\AdminBundle\Entity\Exception, Kunstmaan\MediaBundle\Entity\Media, Kunstmaan\MenuBundle\Entity\BaseMenuItem, Kunstmaan\MenuBundle\Entity\MenuItem, Kunstmaan\NodeBundle\Entity\NodeTranslation, Kunstmaan\PagePartBundle\Entity\LinkPagePart.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
137
                ];
138
            }
139
        };
140
        $nodeAdminListConfigurator->addSimpleItemAction('action.preview', $itemRoute, 'eye');
141
        $nodeAdminListConfigurator->setDomainConfiguration($this->get('kunstmaan_admin.domain_configuration'));
142
        $nodeAdminListConfigurator->setShowAddHomepage($this->getParameter('kunstmaan_node.show_add_homepage') && $this->isGranted('ROLE_SUPER_ADMIN'));
143
144
        /** @var AdminList $adminlist */
145
        $adminlist = $this->get('kunstmaan_adminlist.factory')->createList($nodeAdminListConfigurator);
146
        $adminlist->bindRequest($request);
147
148
        return [
149
            'adminlist' => $adminlist,
150
        ];
151
    }
152
153
    /**
154
     * @Route(
155
     *      "/{id}/copyfromotherlanguage",
156
     *      requirements={"id" = "\d+"},
157
     *      name="KunstmaanNodeBundle_nodes_copyfromotherlanguage",
158
     *      methods={"GET"}
159
     * )
160
     *
161
     * @param int $id The node id
162
     *
163
     * @return RedirectResponse
164
     *
165
     * @throws AccessDeniedException
166
     */
167
    public function copyFromOtherLanguageAction(Request $request, $id)
168
    {
169
        $this->init($request);
170
        /* @var Node $node */
171
        $node = $this->em->getRepository(Node::class)->find($id);
172
173
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $node);
174
175
        $originalLanguage = $request->get('originallanguage');
176
        $otherLanguageNodeTranslation = $node->getNodeTranslation($originalLanguage, true);
177
        $otherLanguageNodeNodeVersion = $otherLanguageNodeTranslation->getPublicNodeVersion();
178
        $otherLanguagePage = $otherLanguageNodeNodeVersion->getRef($this->em);
179
        $myLanguagePage = $this->get('kunstmaan_admin.clone.helper')
180
            ->deepCloneAndSave($otherLanguagePage);
181
182
        /* @var NodeTranslation $nodeTranslation */
183
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)
184
            ->createNodeTranslationFor($myLanguagePage, $this->locale, $node, $this->user);
185
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
186
187
        $this->get('event_dispatcher')->dispatch(
188
            Events::COPY_PAGE_TRANSLATION,
189
            new CopyPageTranslationNodeEvent(
190
                $node,
191
                $nodeTranslation,
192
                $nodeVersion,
193
                $myLanguagePage,
194
                $otherLanguageNodeTranslation,
195
                $otherLanguageNodeNodeVersion,
196
                $otherLanguagePage,
197
                $originalLanguage
198
            )
199
        );
200
201
        return $this->redirect($this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $id]));
202
    }
203
204
    /**
205
     * @Route(
206
     *      "/{id}/recopyfromotherlanguage",
207
     *      requirements={"id" = "\d+"},
208
     *      name="KunstmaanNodeBundle_nodes_recopyfromotherlanguage",
209
     *      methods={"POST"}
210
     * )
211
     *
212
     * @param int $id The node id
213
     *
214
     * @return RedirectResponse
215
     *
216
     * @throws AccessDeniedException
217
     */
218
    public function recopyFromOtherLanguageAction(Request $request, $id)
219
    {
220
        $this->init($request);
221
        /* @var Node $node */
222
        $node = $this->em->getRepository(Node::class)->find($id);
223
224
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $node);
225
226
        $otherLanguageNodeTranslation = $this->em->getRepository(NodeTranslation::class)->find($request->get('source'));
227
        $otherLanguageNodeNodeVersion = $otherLanguageNodeTranslation->getPublicNodeVersion();
228
        $otherLanguagePage = $otherLanguageNodeNodeVersion->getRef($this->em);
229
        $myLanguagePage = $this->get('kunstmaan_admin.clone.helper')
230
            ->deepCloneAndSave($otherLanguagePage);
231
232
        /* @var NodeTranslation $nodeTranslation */
233
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)
234
            ->addDraftNodeVersionFor($myLanguagePage, $this->locale, $node, $this->user);
235
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
236
237
        $this->get('event_dispatcher')->dispatch(
238
            Events::RECOPY_PAGE_TRANSLATION,
239
            new RecopyPageTranslationNodeEvent(
240
                $node,
241
                $nodeTranslation,
242
                $nodeVersion,
243
                $myLanguagePage,
244
                $otherLanguageNodeTranslation,
245
                $otherLanguageNodeNodeVersion,
246
                $otherLanguagePage,
247
                $otherLanguageNodeTranslation->getLang()
248
            )
249
        );
250
251
        return $this->redirect($this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $id, 'subaction' => NodeVersion::DRAFT_VERSION]));
252
    }
253
254
    /**
255
     * @Route(
256
     *      "/{id}/createemptypage",
257
     *      requirements={"id" = "\d+"},
258
     *      name="KunstmaanNodeBundle_nodes_createemptypage",
259
     *      methods={"GET"}
260
     * )
261
     *
262
     * @param int $id
263
     *
264
     * @return RedirectResponse
265
     *
266
     * @throws AccessDeniedException
267
     */
268
    public function createEmptyPageAction(Request $request, $id)
269
    {
270
        $this->init($request);
271
        /* @var Node $node */
272
        $node = $this->em->getRepository(Node::class)->find($id);
273
274
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $node);
275
276
        $entityName = $node->getRefEntityName();
277
        /* @var HasNodeInterface $myLanguagePage */
278
        $myLanguagePage = new $entityName();
279
        $myLanguagePage->setTitle('New page');
280
281
        $this->em->persist($myLanguagePage);
282
        $this->em->flush();
283
        /* @var NodeTranslation $nodeTranslation */
284
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)
285
            ->createNodeTranslationFor($myLanguagePage, $this->locale, $node, $this->user);
286
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
287
288
        $this->get('event_dispatcher')->dispatch(
289
            Events::ADD_EMPTY_PAGE_TRANSLATION,
290
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $myLanguagePage)
291
        );
292
293
        return $this->redirect($this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $id]));
294
    }
295
296
    /**
297
     * @Route("/{id}/publish", requirements={"id" =
298
     *                         "\d+"},
299
     *                         name="KunstmaanNodeBundle_nodes_publish", methods={"GET", "POST"})
300
     *
301
     * @param int $id
302
     *
303
     * @return RedirectResponse
304
     *
305
     * @throws AccessDeniedException
306
     */
307 View Code Duplication
    public function publishAction(Request $request, $id)
308
    {
309
        $this->init($request);
310
        /* @var Node $node */
311
        $node = $this->em->getRepository(Node::class)->find($id);
312
313
        $nodeTranslation = $node->getNodeTranslation($this->locale, true);
314
        $request = $this->get('request_stack')->getCurrentRequest();
315
        $this->nodePublisher->chooseHowToPublish($request, $nodeTranslation, $this->translator);
316
317
        return $this->redirect($this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $node->getId()]));
318
    }
319
320
    /**
321
     * @Route(
322
     *      "/{id}/unpublish",
323
     *      requirements={"id" = "\d+"},
324
     *      name="KunstmaanNodeBundle_nodes_unpublish",
325
     *      methods={"GET", "POST"}
326
     * )
327
     *
328
     * @param int $id
329
     *
330
     * @return RedirectResponse
331
     *
332
     * @throws AccessDeniedException
333
     */
334 View Code Duplication
    public function unPublishAction(Request $request, $id)
335
    {
336
        $this->init($request);
337
        /* @var Node $node */
338
        $node = $this->em->getRepository(Node::class)->find($id);
339
340
        $nodeTranslation = $node->getNodeTranslation($this->locale, true);
341
        $request = $this->get('request_stack')->getCurrentRequest();
342
        $this->nodePublisher->chooseHowToUnpublish($request, $nodeTranslation, $this->translator);
343
344
        return $this->redirect($this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $node->getId()]));
345
    }
346
347
    /**
348
     * @Route(
349
     *      "/{id}/unschedulepublish",
350
     *      requirements={"id" = "\d+"},
351
     *      name="KunstmaanNodeBundle_nodes_unschedule_publish",
352
     *      methods={"GET", "POST"}
353
     * )
354
     *
355
     * @param int $id
356
     *
357
     * @return RedirectResponse
358
     *
359
     * @throws AccessDeniedException
360
     */
361 View Code Duplication
    public function unSchedulePublishAction(Request $request, $id)
362
    {
363
        $this->init($request);
364
365
        /* @var Node $node */
366
        $node = $this->em->getRepository(Node::class)->find($id);
367
368
        $nodeTranslation = $node->getNodeTranslation($this->locale, true);
369
        $this->nodePublisher->unSchedulePublish($nodeTranslation);
370
371
        $this->addFlash(
372
            FlashTypes::SUCCESS,
373
            $this->get('translator')->trans('kuma_node.admin.unschedule.flash.success')
374
        );
375
376
        return $this->redirect($this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $id]));
377
    }
378
379
    /**
380
     * @Route(
381
     *      "/{id}/delete",
382
     *      requirements={"id" = "\d+"},
383
     *      name="KunstmaanNodeBundle_nodes_delete",
384
     *      methods={"POST"}
385
     * )
386
     *
387
     * @param int $id
388
     *
389
     * @return RedirectResponse
390
     *
391
     * @throws AccessDeniedException
392
     */
393
    public function deleteAction(Request $request, $id)
394
    {
395
        $this->init($request);
396
        /* @var Node $node */
397
        $node = $this->em->getRepository(Node::class)->find($id);
398
399
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_DELETE, $node);
400
401
        $nodeTranslation = $node->getNodeTranslation($this->locale, true);
402
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
403
        $page = $nodeVersion->getRef($this->em);
404
405
        $this->get('event_dispatcher')->dispatch(
406
            Events::PRE_DELETE,
407
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
408
        );
409
410
        $node->setDeleted(true);
411
        $this->em->persist($node);
412
413
        $children = $node->getChildren();
414
        $this->deleteNodeChildren($this->em, $this->user, $this->locale, $children);
415
        $this->em->flush();
416
417
        $event = new NodeEvent($node, $nodeTranslation, $nodeVersion, $page);
418
        $this->get('event_dispatcher')->dispatch(Events::POST_DELETE, $event);
419
        if (null === $response = $event->getResponse()) {
420
            $nodeParent = $node->getParent();
421
            // Check if we have a parent. Otherwise redirect to pages overview.
422
            if ($nodeParent) {
423
                $url = $this->get('router')->generate(
424
                    'KunstmaanNodeBundle_nodes_edit',
425
                    ['id' => $nodeParent->getId()]
426
                );
427
            } else {
428
                $url = $this->get('router')->generate(
429
                    'KunstmaanNodeBundle_nodes'
430
                );
431
            }
432
            $response = new RedirectResponse($url);
433
        }
434
435
        $this->addFlash(
436
            FlashTypes::SUCCESS,
437
            $this->get('translator')->trans('kuma_node.admin.delete.flash.success')
438
        );
439
440
        return $response;
441
    }
442
443
    /**
444
     * @Route(
445
     *      "/{id}/duplicate",
446
     *      requirements={"id" = "\d+"},
447
     *      name="KunstmaanNodeBundle_nodes_duplicate",
448
     *      methods={"POST"}
449
     * )
450
     *
451
     * @param int $id
452
     *
453
     * @return RedirectResponse
454
     *
455
     * @throws AccessDeniedException
456
     */
457
    public function duplicateAction(Request $request, $id)
458
    {
459
        $this->init($request);
460
        /* @var Node $parentNode */
461
        $originalNode = $this->em->getRepository(Node::class)
462
            ->find($id);
463
464
        // Check with Acl
465
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $originalNode);
466
467
        $request = $this->get('request_stack')->getCurrentRequest();
468
469
        $originalNodeTranslations = $originalNode->getNodeTranslation($this->locale, true);
470
        $originalRef = $originalNodeTranslations->getPublicNodeVersion()->getRef($this->em);
471
        $newPage = $this->get('kunstmaan_admin.clone.helper')
472
            ->deepCloneAndSave($originalRef);
473
474
        //set the title
475
        $title = $request->get('title');
476
        if (\is_string($title) && !empty($title)) {
477
            $newPage->setTitle($title);
478
        } else {
479
            $newPage->setTitle('New page');
480
        }
481
482
        //set the parent
483
        $parentNodeTranslation = $originalNode->getParent()->getNodeTranslation($this->locale, true);
484
        $parent = $parentNodeTranslation->getPublicNodeVersion()->getRef($this->em);
485
        $newPage->setParent($parent);
486
        $this->em->persist($newPage);
487
        $this->em->flush();
488
489
        /* @var Node $nodeNewPage */
490
        $nodeNewPage = $this->em->getRepository(Node::class)->createNodeFor(
491
            $newPage,
492
            $this->locale,
493
            $this->user
494
        );
495
496
        $nodeTranslation = $nodeNewPage->getNodeTranslation($this->locale, true);
497
        if ($newPage->isStructureNode()) {
498
            $nodeTranslation->setSlug('');
499
            $this->em->persist($nodeTranslation);
500
        }
501
        $this->em->flush();
502
503
        $this->aclManager->updateNodeAcl($originalNode, $nodeNewPage);
504
505
        $this->addFlash(
506
            FlashTypes::SUCCESS,
507
            $this->get('translator')->trans('kuma_node.admin.duplicate.flash.success')
508
        );
509
510
        return $this->redirect(
511
            $this->generateUrl('KunstmaanNodeBundle_nodes_edit', ['id' => $nodeNewPage->getId()])
512
        );
513
    }
514
515
    /**
516
     * @Route(
517
     *      "/{id}/duplicate-with-children",
518
     *      requirements={"id" = "\d+"},
519
     *      name="KunstmaanNodeBundle_nodes_duplicate_with_children",
520
     *      methods={"POST"}
521
     * )
522
     *
523
     * @throws AccessDeniedException
524
     */
525
    public function duplicateWithChildrenAction(Request $request, $id)
526
    {
527
        if (!$this->getParameter('kunstmaan_node.show_duplicate_with_children')) {
528
            return $this->redirectToRoute('KunstmaanNodeBundle_nodes_edit', ['id' => $id]);
529
        }
530
531
        $this->init($request);
532
        $title = $request->get('title', null);
533
534
        $nodeNewPage = $this->pageCloningHelper->duplicateWithChildren($id, $this->locale, $this->user, $title);
535
536
        $this->addFlash(FlashTypes::SUCCESS, $this->get('translator')->trans('kuma_node.admin.duplicate.flash.success'));
537
538
        return $this->redirectToRoute('KunstmaanNodeBundle_nodes_edit', ['id' => $nodeNewPage->getId()]);
539
    }
540
541
    /**
542
     * @Route(
543
     *      "/{id}/revert",
544
     *      requirements={"id" = "\d+"},
545
     *      defaults={"subaction" = "public"},
546
     *      name="KunstmaanNodeBundle_nodes_revert",
547
     *      methods={"GET"}
548
     * )
549
     *
550
     * @param int $id The node id
551
     *
552
     * @return RedirectResponse
553
     *
554
     * @throws AccessDeniedException
555
     * @throws InvalidArgumentException
556
     */
557
    public function revertAction(Request $request, $id)
558
    {
559
        $this->init($request);
560
        /* @var Node $node */
561
        $node = $this->em->getRepository(Node::class)->find($id);
562
563
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $node);
564
565
        $version = $request->get('version');
566
567
        if (empty($version) || !is_numeric($version)) {
568
            throw new InvalidArgumentException('No version was specified');
569
        }
570
571
        /* @var NodeVersionRepository $nodeVersionRepo */
572
        $nodeVersionRepo = $this->em->getRepository(NodeVersion::class);
573
        /* @var NodeVersion $nodeVersion */
574
        $nodeVersion = $nodeVersionRepo->find($version);
575
576
        if (\is_null($nodeVersion)) {
577
            throw new InvalidArgumentException('Version does not exist');
578
        }
579
580
        /* @var NodeTranslation $nodeTranslation */
581
        $nodeTranslation = $node->getNodeTranslation($this->locale, true);
582
        $page = $nodeVersion->getRef($this->em);
583
        /* @var HasNodeInterface $clonedPage */
584
        $clonedPage = $this->get('kunstmaan_admin.clone.helper')
585
            ->deepCloneAndSave($page);
586
        $newNodeVersion = $nodeVersionRepo->createNodeVersionFor(
587
            $clonedPage,
588
            $nodeTranslation,
589
            $this->user,
590
            $nodeVersion,
591
            'draft'
592
        );
593
594
        $nodeTranslation->setTitle($clonedPage->getTitle());
595
        $this->em->persist($nodeTranslation);
596
        $this->em->flush();
597
598
        $this->get('event_dispatcher')->dispatch(
599
            Events::REVERT,
600
            new RevertNodeAction(
601
                $node,
602
                $nodeTranslation,
603
                $newNodeVersion,
604
                $clonedPage,
605
                $nodeVersion,
606
                $page
607
            )
608
        );
609
610
        $this->addFlash(
611
            FlashTypes::SUCCESS,
612
            $this->get('translator')->trans('kuma_node.admin.revert.flash.success')
613
        );
614
615
        return $this->redirect(
616
            $this->generateUrl(
617
                'KunstmaanNodeBundle_nodes_edit',
618
                [
619
                    'id' => $id,
620
                    'subaction' => 'draft',
621
                ]
622
            )
623
        );
624
    }
625
626
    /**
627
     * @Route(
628
     *      "/{id}/add",
629
     *      requirements={"id" = "\d+"},
630
     *      name="KunstmaanNodeBundle_nodes_add",
631
     *      methods={"POST"}
632
     * )
633
     *
634
     * @param int $id
635
     *
636
     * @return RedirectResponse
637
     *
638
     * @throws AccessDeniedException
639
     * @throws InvalidArgumentException
640
     */
641
    public function addAction(Request $request, $id)
642
    {
643
        $this->init($request);
644
        /* @var Node $parentNode */
645
        $parentNode = $this->em->getRepository(Node::class)->find($id);
646
647
        // Check with Acl
648
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $parentNode);
649
650
        $parentNodeTranslation = $parentNode->getNodeTranslation($this->locale, true);
651
        $parentNodeVersion = $parentNodeTranslation->getPublicNodeVersion();
652
        $parentPage = $parentNodeVersion->getRef($this->em);
653
654
        $type = $this->validatePageType($request);
655
        $newPage = $this->createNewPage($request, $type);
656
        $newPage->setParent($parentPage);
657
658
        /* @var Node $nodeNewPage */
659
        $nodeNewPage = $this->em->getRepository(Node::class)
660
            ->createNodeFor($newPage, $this->locale, $this->user);
661
        $nodeTranslation = $nodeNewPage->getNodeTranslation(
662
            $this->locale,
663
            true
664
        );
665
        $weight = $this->em->getRepository(NodeTranslation::class)
666
                ->getMaxChildrenWeight($parentNode, $this->locale) + 1;
667
        $nodeTranslation->setWeight($weight);
668
669
        if ($newPage->isStructureNode()) {
670
            $nodeTranslation->setSlug('');
671
        }
672
673
        $this->em->persist($nodeTranslation);
674
        $this->em->flush();
675
676
        $this->aclManager->updateNodeAcl($parentNode, $nodeNewPage);
677
678
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
679
680
        $this->get('event_dispatcher')->dispatch(
681
            Events::ADD_NODE,
682
            new NodeEvent(
683
                $nodeNewPage, $nodeTranslation, $nodeVersion, $newPage
684
            )
685
        );
686
687
        return $this->redirect(
688
            $this->generateUrl(
689
                'KunstmaanNodeBundle_nodes_edit',
690
                ['id' => $nodeNewPage->getId()]
691
            )
692
        );
693
    }
694
695
    /**
696
     * @Route("/add-homepage", name="KunstmaanNodeBundle_nodes_add_homepage", methods={"POST"})
697
     *
698
     * @return RedirectResponse
699
     *
700
     * @throws AccessDeniedException
701
     * @throws InvalidArgumentException
702
     */
703
    public function addHomepageAction(Request $request)
704
    {
705
        $this->init($request);
706
707
        // Check with Acl
708
        $this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
709
710
        $type = $this->validatePageType($request);
711
712
        $newPage = $this->createNewPage($request, $type);
713
714
        /* @var Node $nodeNewPage */
715
        $nodeNewPage = $this->em->getRepository(Node::class)
716
            ->createNodeFor($newPage, $this->locale, $this->user);
717
        $nodeTranslation = $nodeNewPage->getNodeTranslation(
718
            $this->locale,
719
            true
720
        );
721
        $this->em->flush();
722
723
        // Set default permissions
724
        $this->container->get('kunstmaan_node.acl_permission_creator_service')
725
            ->createPermission($nodeNewPage);
726
727
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
728
729
        $this->get('event_dispatcher')->dispatch(
730
            Events::ADD_NODE,
731
            new NodeEvent(
732
                $nodeNewPage, $nodeTranslation, $nodeVersion, $newPage
733
            )
734
        );
735
736
        return $this->redirect(
737
            $this->generateUrl(
738
                'KunstmaanNodeBundle_nodes_edit',
739
                ['id' => $nodeNewPage->getId()]
740
            )
741
        );
742
    }
743
744
    /**
745
     * @Route("/reorder", name="KunstmaanNodeBundle_nodes_reorder", methods={"POST"})
746
     *
747
     * @return string
748
     *
749
     * @throws AccessDeniedException
750
     */
751
    public function reorderAction(Request $request)
752
    {
753
        $this->init($request);
754
        $nodes = [];
755
        $nodeIds = $request->get('nodes');
756
        $changeParents = $request->get('parent');
757
758
        foreach ($nodeIds as $id) {
759
            /* @var Node $node */
760
            $node = $this->em->getRepository(Node::class)->find($id);
761
            $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $node);
762
            $nodes[] = $node;
763
        }
764
765
        $weight = 1;
766
        foreach ($nodes as $node) {
767
            $newParentId = isset($changeParents[$node->getId()]) ? $changeParents[$node->getId()] : null;
768
            if ($newParentId) {
769
                $parent = $this->em->getRepository(Node::class)->find($newParentId);
770
                $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $parent);
771
                $node->setParent($parent);
772
                $this->em->persist($node);
773
                $this->em->flush($node);
774
            }
775
776
            /* @var NodeTranslation $nodeTranslation */
777
            $nodeTranslation = $node->getNodeTranslation($this->locale, true);
778
779
            if ($nodeTranslation) {
780
                $nodeVersion = $nodeTranslation->getPublicNodeVersion();
781
                $page = $nodeVersion->getRef($this->em);
782
783
                $this->get('event_dispatcher')->dispatch(
784
                    Events::PRE_PERSIST,
785
                    new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
786
                );
787
788
                $nodeTranslation->setWeight($weight);
789
                $this->em->persist($nodeTranslation);
790
                $this->em->flush($nodeTranslation);
791
792
                $this->get('event_dispatcher')->dispatch(
793
                    Events::POST_PERSIST,
794
                    new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
795
                );
796
797
                ++$weight;
798
            }
799
        }
800
801
        return new JsonResponse(
802
            [
803
                'Success' => 'The node-translations for [' . $this->locale . '] have got new weight values',
804
            ]
805
        );
806
    }
807
808
    /**
809
     * @Route(
810
     *      "/{id}/{subaction}",
811
     *      requirements={"id" = "\d+"},
812
     *      defaults={"subaction" = "public"},
813
     *      name="KunstmaanNodeBundle_nodes_edit",
814
     *      methods={"GET", "POST"}
815
     * )
816
     * @Template("@KunstmaanNode/NodeAdmin/edit.html.twig")
817
     *
818
     * @param int    $id        The node id
819
     * @param string $subaction The subaction (draft|public)
820
     *
821
     * @return RedirectResponse|array
822
     *
823
     * @throws AccessDeniedException
824
     */
825
    public function editAction(Request $request, $id, $subaction)
826
    {
827
        $this->init($request);
828
        /* @var Node $node */
829
        $node = $this->em->getRepository(Node::class)->find($id);
830
831
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $node);
832
833
        $tabPane = new TabPane(
834
            'todo',
835
            $request,
836
            $this->container->get('form.factory')
837
        );
838
839
        $nodeTranslation = $node->getNodeTranslation($this->locale, true);
840
        if (!$nodeTranslation) {
841
            return $this->renderNodeNotTranslatedPage($node);
842
        }
843
844
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
845
        $draftNodeVersion = $nodeTranslation->getDraftNodeVersion();
846
        $nodeVersionIsLocked = false;
847
848
        /* @var HasNodeInterface $page */
849
        $page = null;
850
        $draft = ($subaction == 'draft');
851
        $saveAsDraft = $request->get('saveasdraft');
852
        if ((!$draft && !empty($saveAsDraft)) || ($draft && \is_null($draftNodeVersion))) {
853
            // Create a new draft version
854
            $draft = true;
855
            $subaction = 'draft';
856
            $page = $nodeVersion->getRef($this->em);
857
            $nodeVersion = $this->createDraftVersion(
858
                $page,
859
                $nodeTranslation,
860
                $nodeVersion
861
            );
862
            $draftNodeVersion = $nodeVersion;
863
        } elseif ($draft) {
864
            $nodeVersion = $draftNodeVersion;
865
            $page = $nodeVersion->getRef($this->em);
866
        } else {
867
            if ($request->getMethod() == 'POST') {
868
                $nodeVersionIsLocked = $this->isNodeVersionLocked($nodeTranslation, true);
869
870
                //Check the version timeout and make a new nodeversion if the timeout is passed
871
                $thresholdDate = date(
872
                    'Y-m-d H:i:s',
873
                    time() - $this->getParameter(
874
                        'kunstmaan_node.version_timeout'
875
                    )
876
                );
877
                $updatedDate = date(
878
                    'Y-m-d H:i:s',
879
                    strtotime($nodeVersion->getUpdated()->format('Y-m-d H:i:s'))
880
                );
881 View Code Duplication
                if ($thresholdDate >= $updatedDate || $nodeVersionIsLocked) {
882
                    $page = $nodeVersion->getRef($this->em);
883
                    if ($nodeVersion === $nodeTranslation->getPublicNodeVersion()) {
884
                        $this->nodePublisher
885
                            ->createPublicVersion(
886
                                $page,
887
                                $nodeTranslation,
888
                                $nodeVersion,
889
                                $this->user
890
                            );
891
                    } else {
892
                        $this->createDraftVersion(
893
                            $page,
894
                            $nodeTranslation,
895
                            $nodeVersion
896
                        );
897
                    }
898
                }
899
            }
900
            $page = $nodeVersion->getRef($this->em);
901
        }
902
        $isStructureNode = $page->isStructureNode();
903
904
        $menubuilder = $this->get('kunstmaan_node.actions_menu_builder');
905
        $menubuilder->setActiveNodeVersion($nodeVersion);
906
        $menubuilder->setEditableNode(!$isStructureNode);
907
908
        // Building the form
909
        $propertiesWidget = new FormWidget();
910
        $propertiesWidget->addType('main', $page->getDefaultAdminType(), $page);
911
        $propertiesWidget->addType('node', $node->getDefaultAdminType(), $node);
912
        $tabPane->addTab(new Tab('kuma_node.tab.properties.title', $propertiesWidget));
913
914
        // Menu tab
915
        $menuWidget = new FormWidget();
916
        $menuWidget->addType(
917
            'menunodetranslation',
918
            NodeMenuTabTranslationAdminType::class,
919
            $nodeTranslation,
920
            ['slugable' => !$isStructureNode]
921
        );
922
        $menuWidget->addType('menunode', NodeMenuTabAdminType::class, $node, ['available_in_nav' => !$isStructureNode]);
923
        $tabPane->addTab(new Tab('kuma_node.tab.menu.title', $menuWidget));
924
925
        $this->get('event_dispatcher')->dispatch(
926
            Events::ADAPT_FORM,
927
            new AdaptFormEvent(
928
                $request,
929
                $tabPane,
930
                $page,
931
                $node,
932
                $nodeTranslation,
933
                $nodeVersion
934
            )
935
        );
936
937
        $tabPane->buildForm();
938
939
        if ($request->getMethod() == 'POST') {
940
            $tabPane->bindRequest($request);
941
942
            // Don't redirect to listing when coming from ajax request, needed for url chooser.
943
            if ($tabPane->isValid() && !$request->isXmlHttpRequest()) {
944
                $this->get('event_dispatcher')->dispatch(
945
                    Events::PRE_PERSIST,
946
                    new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
947
                );
948
949
                $nodeTranslation->setTitle($page->getTitle());
950
                if ($isStructureNode) {
951
                    $nodeTranslation->setSlug('');
952
                }
953
                $nodeVersion->setUpdated(new DateTime());
954
                if ($nodeVersion->getType() == 'public') {
955
                    $nodeTranslation->setUpdated($nodeVersion->getUpdated());
956
                }
957
                $this->em->persist($nodeTranslation);
958
                $this->em->persist($nodeVersion);
959
                $tabPane->persist($this->em);
960
                $this->em->flush();
961
962
                $this->get('event_dispatcher')->dispatch(
963
                    Events::POST_PERSIST,
964
                    new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
965
                );
966
967
                if ($nodeVersionIsLocked) {
968
                    $this->addFlash(
969
                        FlashTypes::SUCCESS,
970
                        $this->get('translator')->trans('kuma_node.admin.edit.flash.locked_success')
971
                    );
972
                } elseif ($request->request->has('publishing') || $request->request->has('publish_later')) {
973
                    $this->nodePublisher->chooseHowToPublish($request, $nodeTranslation, $this->translator);
974
                } elseif ($request->request->has('unpublishing') || $request->request->has('unpublish_later')) {
975
                    $this->nodePublisher->chooseHowToUnpublish($request, $nodeTranslation, $this->translator);
976
                } else {
977
                    $this->addFlash(
978
                        FlashTypes::SUCCESS,
979
                        $this->get('translator')->trans('kuma_node.admin.edit.flash.success')
980
                    );
981
                }
982
983
                $params = [
984
                    'id' => $node->getId(),
985
                    'subaction' => $subaction,
986
                    'currenttab' => $tabPane->getActiveTab(),
987
                ];
988
                $params = array_merge(
989
                    $params,
990
                    $tabPane->getExtraParams($request)
991
                );
992
993
                if ($subaction === 'draft' && ($request->request->has('publishing') || $request->request->has('publish_later'))) {
994
                    unset($params['subaction']);
995
                }
996
997
                return $this->redirect(
998
                    $this->generateUrl(
999
                        'KunstmaanNodeBundle_nodes_edit',
1000
                        $params
1001
                    )
1002
                );
1003
            }
1004
        }
1005
1006
        $nodeVersions = $this->em->getRepository(NodeVersion::class)->findBy(
1007
            ['nodeTranslation' => $nodeTranslation],
1008
            ['updated' => 'ASC']
1009
        );
1010
        $queuedNodeTranslationAction = $this->em->getRepository(QueuedNodeTranslationAction::class)->findOneBy(['nodeTranslation' => $nodeTranslation]);
1011
1012
        return [
1013
            'page' => $page,
1014
            'entityname' => ClassLookup::getClass($page),
1015
            'nodeVersions' => $nodeVersions,
1016
            'node' => $node,
1017
            'nodeTranslation' => $nodeTranslation,
1018
            'draft' => $draft,
1019
            'draftNodeVersion' => $draftNodeVersion,
1020
            'showDuplicateWithChildren' => $this->getParameter('kunstmaan_node.show_duplicate_with_children'),
1021
            'nodeVersion' => $nodeVersion,
1022
            'subaction' => $subaction,
1023
            'tabPane' => $tabPane,
1024
            'editmode' => true,
1025
            'childCount' => $this->em->getRepository('KunstmaanNodeBundle:Node')->getChildCount($node),
1026
            'queuedNodeTranslationAction' => $queuedNodeTranslationAction,
1027
            'nodeVersionLockCheck' => $this->container->getParameter('kunstmaan_node.lock_enabled'),
1028
            'nodeVersionLockInterval' => $this->container->getParameter('kunstmaan_node.lock_check_interval'),
1029
        ];
1030
    }
1031
1032
    /**
1033
     * @Route(
1034
     *      "checkNodeVersionLock/{id}/{public}",
1035
     *      requirements={"id" = "\d+", "public" = "(0|1)"},
1036
     *      name="KunstmaanNodeBundle_nodes_versionlock_check"
1037
     * )
1038
     *
1039
     * @param $id
1040
     *
1041
     * @return JsonResponse
1042
     */
1043
    public function checkNodeVersionLockAction(Request $request, $id, $public)
1044
    {
1045
        $nodeVersionIsLocked = false;
1046
        $message = '';
1047
        $this->init($request);
1048
1049
        /* @var Node $node */
1050
        $node = $this->em->getRepository(Node::class)->find($id);
1051
1052
        try {
1053
            $this->checkPermission($node, PermissionMap::PERMISSION_EDIT);
1054
1055
            /** @var NodeVersionLockHelper $nodeVersionLockHelper */
1056
            $nodeVersionLockHelper = $this->get('kunstmaan_node.admin_node.node_version_lock_helper');
1057
            $nodeTranslation = $node->getNodeTranslation($this->locale, true);
1058
1059
            if ($nodeTranslation) {
1060
                $nodeVersionIsLocked = $nodeVersionLockHelper->isNodeVersionLocked($this->getUser(), $nodeTranslation, $public);
1061
1062
                if ($nodeVersionIsLocked) {
1063
                    $users = $nodeVersionLockHelper->getUsersWithNodeVersionLock($nodeTranslation, $public, $this->getUser());
1064
                    $message = $this->get('translator')->trans('kuma_node.admin.edit.flash.locked', ['%users%' => implode(', ', $users)]);
1065
                }
1066
            }
1067
        } catch (AccessDeniedException $ade) {
1068
        }
1069
1070
        return new JsonResponse(['lock' => $nodeVersionIsLocked, 'message' => $message]);
1071
    }
1072
1073
    /**
1074
     * @param bool $isPublic
1075
     *
1076
     * @return bool
1077
     */
1078
    private function isNodeVersionLocked(NodeTranslation $nodeTranslation, $isPublic)
1079
    {
1080
        if ($this->container->getParameter('kunstmaan_node.lock_enabled')) {
1081
            /** @var NodeVersionLockHelper $nodeVersionLockHelper */
1082
            $nodeVersionLockHelper = $this->get('kunstmaan_node.admin_node.node_version_lock_helper');
1083
            $nodeVersionIsLocked = $nodeVersionLockHelper->isNodeVersionLocked($this->getUser(), $nodeTranslation, $isPublic);
1084
1085
            return $nodeVersionIsLocked;
1086
        }
1087
1088
        return false;
1089
    }
1090
1091
    /**
1092
     * @param HasNodeInterface $page            The page
1093
     * @param NodeTranslation  $nodeTranslation The node translation
1094
     * @param NodeVersion      $nodeVersion     The node version
1095
     *
1096
     * @return NodeVersion
1097
     */
1098
    private function createDraftVersion(
1099
        HasNodeInterface $page,
1100
        NodeTranslation $nodeTranslation,
1101
        NodeVersion $nodeVersion
1102
    ) {
1103
        $publicPage = $this->get('kunstmaan_admin.clone.helper')
1104
            ->deepCloneAndSave($page);
1105
        /* @var NodeVersion $publicNodeVersion */
1106
1107
        $publicNodeVersion = $this->em->getRepository(
1108
            NodeVersion::class
1109
        )->createNodeVersionFor(
1110
            $publicPage,
1111
            $nodeTranslation,
1112
            $this->user,
1113
            $nodeVersion->getOrigin(),
1114
            'public',
1115
            $nodeVersion->getCreated()
1116
        );
1117
1118
        $nodeTranslation->setPublicNodeVersion($publicNodeVersion);
1119
        $nodeVersion->setType('draft');
1120
        $nodeVersion->setOrigin($publicNodeVersion);
1121
        $nodeVersion->setCreated(new DateTime());
1122
1123
        $this->em->persist($nodeTranslation);
1124
        $this->em->persist($nodeVersion);
1125
        $this->em->flush();
1126
1127
        $this->get('event_dispatcher')->dispatch(
1128
            Events::CREATE_DRAFT_VERSION,
1129
            new NodeEvent(
1130
                $nodeTranslation->getNode(),
1131
                $nodeTranslation,
1132
                $nodeVersion,
1133
                $page
1134
            )
1135
        );
1136
1137
        return $nodeVersion;
1138
    }
1139
1140
    /**
1141
     * @param Node   $node       The node
1142
     * @param string $permission The permission to check for
1143
     *
1144
     * @throws AccessDeniedException
1145
     */
1146
    private function checkPermission(Node $node, $permission)
1147
    {
1148
        if (false === $this->authorizationChecker->isGranted($permission, $node)) {
1149
            throw new AccessDeniedException();
1150
        }
1151
    }
1152
1153
    /**
1154
     * @param EntityManager   $em       The Entity Manager
1155
     * @param BaseUser        $user     The user who deletes the children
1156
     * @param string          $locale   The locale that was used
1157
     * @param ArrayCollection $children The children array
1158
     */
1159
    private function deleteNodeChildren(
1160
        EntityManager $em,
1161
        BaseUser $user,
1162
        $locale,
1163
        ArrayCollection $children
1164
    ) {
1165
        /* @var Node $childNode */
1166
        foreach ($children as $childNode) {
1167
            $childNodeTranslation = $childNode->getNodeTranslation(
1168
                $this->locale,
1169
                true
1170
            );
1171
1172
            $childNodeVersion = $childNodeTranslation->getPublicNodeVersion();
1173
            $childNodePage = $childNodeVersion->getRef($this->em);
1174
1175
            $this->get('event_dispatcher')->dispatch(
1176
                Events::PRE_DELETE,
1177
                new NodeEvent(
1178
                    $childNode,
1179
                    $childNodeTranslation,
1180
                    $childNodeVersion,
1181
                    $childNodePage
1182
                )
1183
            );
1184
1185
            $childNode->setDeleted(true);
1186
            $this->em->persist($childNode);
1187
1188
            $children2 = $childNode->getChildren();
1189
            $this->deleteNodeChildren($em, $user, $locale, $children2);
1190
1191
            $this->get('event_dispatcher')->dispatch(
1192
                Events::POST_DELETE,
1193
                new NodeEvent(
1194
                    $childNode,
1195
                    $childNodeTranslation,
1196
                    $childNodeVersion,
1197
                    $childNodePage
1198
                )
1199
            );
1200
        }
1201
    }
1202
1203
    /**
1204
     * @param string $type
1205
     *
1206
     * @return HasNodeInterface
1207
     */
1208
    private function createNewPage(Request $request, $type)
1209
    {
1210
        /* @var HasNodeInterface $newPage */
1211
        $newPage = new $type();
1212
1213
        $title = $request->get('title');
1214
        if (\is_string($title) && !empty($title)) {
1215
            $newPage->setTitle($title);
1216
        } else {
1217
            $newPage->setTitle($this->get('translator')->trans('kuma_node.admin.new_page.title.default'));
1218
        }
1219
        $this->em->persist($newPage);
1220
        $this->em->flush();
1221
1222
        return $newPage;
1223
    }
1224
1225
    /**
1226
     * @param Request $request
1227
     *
1228
     * @return string
1229
     * @throw InvalidArgumentException
1230
     */
1231
    private function validatePageType($request)
1232
    {
1233
        $type = $request->get('type');
1234
1235
        if (empty($type)) {
1236
            throw new InvalidArgumentException('Please specify a type of page you want to create');
1237
        }
1238
1239
        return $type;
1240
    }
1241
1242
    /**
1243
     * @return \Symfony\Component\HttpFoundation\Response
1244
     */
1245
    private function renderNodeNotTranslatedPage(Node $node)
1246
    {
1247
        //try to find a parent node with the correct translation, if there is none allow copy.
1248
        //if there is a parent but it doesn't have the language to copy to don't allow it
1249
        $parentNode = $node->getParent();
1250
        if ($parentNode) {
1251
            $parentNodeTranslation = $parentNode->getNodeTranslation(
1252
                $this->locale,
1253
                true
1254
            );
1255
            $parentsAreOk = false;
1256
1257
            if ($parentNodeTranslation) {
1258
                $parentsAreOk = $this->em->getRepository(
1259
                    NodeTranslation::class
1260
                )->hasParentNodeTranslationsForLanguage(
1261
                    $node->getParent()->getNodeTranslation(
1262
                        $this->locale,
1263
                        true
1264
                    ),
1265
                    $this->locale
1266
                );
1267
            }
1268
        } else {
1269
            $parentsAreOk = true;
1270
        }
1271
1272
        return $this->render(
1273
            '@KunstmaanNode/NodeAdmin/pagenottranslated.html.twig',
1274
            [
1275
                'node' => $node,
1276
                'nodeTranslations' => $node->getNodeTranslations(
1277
                    true
1278
                ),
1279
                'copyfromotherlanguages' => $parentsAreOk,
1280
            ]
1281
        );
1282
    }
1283
}
1284