Completed
Push — master ( 67d37c...483c69 )
by Ruud
06:47
created

Kunstmaan/NodeBundle/Helper/PageCloningHelper.php (1 issue)

Severity

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;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Kunstmaan\AdminBundle\Entity\BaseUser;
7
use Kunstmaan\AdminBundle\Helper\CloneHelper;
8
use Kunstmaan\AdminBundle\Helper\Security\Acl\Permission\PermissionMap;
9
use Kunstmaan\NodeBundle\Entity\DuplicateSubPageInterface;
10
use Kunstmaan\NodeBundle\Entity\HasNodeInterface;
11
use Kunstmaan\NodeBundle\Entity\Node;
12
use Kunstmaan\NodeBundle\Entity\PageInterface;
13
use Kunstmaan\NodeBundle\Event\Events;
14
use Kunstmaan\NodeBundle\Event\PreNodeDuplicateEvent;
15
use Kunstmaan\NodeBundle\Event\PostNodeDuplicateEvent;
16
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
17
use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity;
18
use Symfony\Component\Security\Acl\Model\AclProviderInterface;
19
use Symfony\Component\Security\Acl\Model\EntryInterface;
20
use Symfony\Component\Security\Acl\Model\ObjectIdentityRetrievalStrategyInterface;
21
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
22
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
23
24
class PageCloningHelper
25
{
26
    /** @var EntityManagerInterface */
27
    private $em;
28
29
    /** @var CloneHelper */
30
    private $cloneHelper;
31
32
    /** @var AclProviderInterface */
33
    private $aclProvider;
34
35
    /** @var ObjectIdentityRetrievalStrategyInterface */
36
    private $identityRetrievalStrategy;
37
38
    /** @var AuthorizationCheckerInterface */
39
    private $authorizationCheckerInterface;
40
41
    /** @var EventDispatcherInterface */
42
    private $eventDispatcherInterface;
43
44
    public function __construct(EntityManagerInterface $em, CloneHelper $cloneHelper, AclProviderInterface $aclProvider, ObjectIdentityRetrievalStrategyInterface $identityRetrivalStrategy, AuthorizationCheckerInterface $authorizationChecker, EventDispatcherInterface $eventDispatcher)
45
    {
46
        $this->em = $em;
47
        $this->cloneHelper = $cloneHelper;
48
        $this->aclProvider = $aclProvider;
49
        $this->identityRetrievalStrategy = $identityRetrivalStrategy;
50
        $this->authorizationCheckerInterface = $authorizationChecker;
51
        $this->eventDispatcherInterface = $eventDispatcher;
52
    }
53
54
    /**
55
     * @throws AccessDeniedException
56
     */
57
    public function duplicateWithChildren($id, string $locale, BaseUser $user, string $title = null): Node
58
    {
59
        /* @var Node $parentNode */
60
        $originalNode = $this->em->getRepository('KunstmaanNodeBundle:Node')->find($id);
61
62
        $this->denyAccessUnlessGranted(PermissionMap::PERMISSION_EDIT, $originalNode);
63
64
        $this->eventDispatcherInterface->dispatch(Events::PRE_DUPLICATE_WITH_CHILDREN, new PreNodeDuplicateEvent($originalNode));
65
66
        $newPage = $this->clonePage($originalNode, $locale, $title);
67
        $nodeNewPage = $this->createNodeStructureForNewPage($originalNode, $newPage, $user, $locale);
68
69
        $this->eventDispatcherInterface->dispatch(Events::POST_DUPLICATE_WITH_CHILDREN, new PostNodeDuplicateEvent($originalNode, $nodeNewPage, $newPage));
0 ignored issues
show
$originalNode is of type object|null, but the function expects a object<Kunstmaan\NodeBundle\Entity\Node>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
70
71
        $this->cloneChildren($originalNode, $newPage, $user, $locale);
72
73
        return $nodeNewPage;
74
    }
75
76
    private function denyAccessUnlessGranted($attributes, $subject = null, $message = 'Access Denied.')
77
    {
78
        if (!$this->authorizationCheckerInterface->isGranted($attributes, $subject)) {
79
            $exception = new AccessDeniedException();
80
            $exception->setAttributes($attributes);
81
            $exception->setSubject($subject);
82
83
            throw $exception;
84
        }
85
    }
86
87
    public function clonePage(Node $originalNode, $locale, $title = null)
88
    {
89
        $originalNodeTranslations = $originalNode->getNodeTranslation($locale, true);
90
        $originalRef = $originalNodeTranslations->getPublicNodeVersion()->getRef($this->em);
91
92
        $newPage = $this->cloneHelper->deepCloneAndSave($originalRef);
93
94
        if ($title !== null) {
95
            $newPage->setTitle($title);
96
        }
97
98
        //set the parent
99
        $parentNodeTranslation = $originalNode->getParent()->getNodeTranslation($locale, true);
100
        $parent = $parentNodeTranslation->getPublicNodeVersion()->getRef($this->em);
101
        $newPage->setParent($parent);
102
103
        $this->em->persist($newPage);
104
        $this->em->flush();
105
106
        return $newPage;
107
    }
108
109
    private function createNodeStructureForNewPage(Node $originalNode, HasNodeInterface $newPage, BaseUser $user, string $locale): Node
110
    {
111
        /* @var Node $nodeNewPage */
112
        $nodeNewPage = $this->em->getRepository('KunstmaanNodeBundle:Node')->createNodeFor($newPage, $locale, $user);
113
114
        if ($newPage->isStructureNode()) {
115
            $nodeTranslation = $nodeNewPage->getNodeTranslation($locale, true);
116
            $nodeTranslation->setSlug('');
117
            $this->em->persist($nodeTranslation);
118
        }
119
        $this->em->flush();
120
121
        $this->updateAcl($originalNode, $nodeNewPage);
122
123
        return $nodeNewPage;
124
    }
125
126 View Code Duplication
    private function updateAcl($originalNode, $nodeNewPage): void
127
    {
128
        $originalIdentity = $this->identityRetrievalStrategy->getObjectIdentity($originalNode);
129
        $originalAcl = $this->aclProvider->findAcl($originalIdentity);
130
131
        $newIdentity = $this->identityRetrievalStrategy->getObjectIdentity($nodeNewPage);
132
        $newAcl = $this->aclProvider->createAcl($newIdentity);
133
134
        $aces = $originalAcl->getObjectAces();
135
        /* @var EntryInterface $ace */
136
        foreach ($aces as $ace) {
137
            $securityIdentity = $ace->getSecurityIdentity();
138
            if ($securityIdentity instanceof RoleSecurityIdentity) {
139
                $newAcl->insertObjectAce($securityIdentity, $ace->getMask());
140
            }
141
        }
142
        $this->aclProvider->updateAcl($newAcl);
143
    }
144
145
    private function cloneChildren(Node $originalNode, PageInterface $newPage, BaseUser $user, string $locale): void
146
    {
147
        $nodeChildren = $originalNode->getChildren();
148
        foreach ($nodeChildren as $originalNodeChild) {
149
            $originalNodeTranslations = $originalNodeChild->getNodeTranslation($locale, true);
150
            $originalRef = $originalNodeTranslations->getPublicNodeVersion()->getRef($this->em);
151
152
            if (!$originalRef instanceof DuplicateSubPageInterface || !$originalRef->skipClone()) {
153
                $this->eventDispatcherInterface->dispatch(Events::PRE_DUPLICATE_WITH_CHILDREN, new PreNodeDuplicateEvent($originalNodeChild));
154
                $newChildPage = $this->clonePage($originalNodeChild, $locale);
155
                $newChildPage->setParent($newPage);
156
157
                $newChildNode = $this->createNodeStructureForNewPage($originalNodeChild, $newChildPage, $user, $locale);
158
                $this->eventDispatcherInterface->dispatch(Events::POST_DUPLICATE_WITH_CHILDREN, new PostNodeDuplicateEvent($originalNodeChild, $newChildNode, $newChildPage));
159
                $this->cloneChildren($originalNodeChild, $newChildPage, $user, $locale);
160
            }
161
        }
162
    }
163
}
164