Issues (3099)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Kunstmaan/NodeBundle/Helper/NodeHelper.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\Helper;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Kunstmaan\AdminBundle\Entity\User;
7
use Kunstmaan\AdminBundle\Helper\CloneHelper;
8
use Kunstmaan\AdminBundle\Helper\FormWidgets\Tabs\TabPane;
9
use Kunstmaan\NodeBundle\Entity\HasNodeInterface;
10
use Kunstmaan\NodeBundle\Entity\Node;
11
use Kunstmaan\NodeBundle\Entity\NodeTranslation;
12
use Kunstmaan\NodeBundle\Entity\NodeVersion;
13
use Kunstmaan\NodeBundle\Event\CopyPageTranslationNodeEvent;
14
use Kunstmaan\NodeBundle\Event\Events;
15
use Kunstmaan\NodeBundle\Event\NodeEvent;
16
use Kunstmaan\NodeBundle\Event\RecopyPageTranslationNodeEvent;
17
use Kunstmaan\NodeBundle\Helper\NodeAdmin\NodeAdminPublisher;
18
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
19
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
20
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
21
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
22
23
/**
24
 * Class NodeHelper
25
 */
26
class NodeHelper
27
{
28
    /** @var EntityManagerInterface */
29
    private $em;
30
31
    /** @var NodeAdminPublisher */
32
    private $nodeAdminPublisher;
33
34
    /** @var TokenStorageInterface */
35
    private $tokenStorage;
36
37
    /** @var CloneHelper */
38
    private $cloneHelper;
39
40
    /** @var EventDispatcherInterface */
41
    private $eventDispatcher;
42
43
    /**
44
     * NodeHelper constructor.
45
     *
46
     * @param EntityManagerInterface   $em
47
     * @param NodeAdminPublisher       $nodeAdminPublisher
48
     * @param TokenStorageInterface    $tokenStorage
49
     * @param CloneHelper              $cloneHelper
50
     * @param EventDispatcherInterface $eventDispatcher
51
     */
52 12 View Code Duplication
    public function __construct(
53
        EntityManagerInterface $em,
54
        NodeAdminPublisher $nodeAdminPublisher,
55
        TokenStorageInterface $tokenStorage,
56
        CloneHelper $cloneHelper,
57
        EventDispatcherInterface $eventDispatcher
58
    ) {
59 12
        $this->em = $em;
60 12
        $this->nodeAdminPublisher = $nodeAdminPublisher;
61 12
        $this->tokenStorage = $tokenStorage;
62 12
        $this->cloneHelper = $cloneHelper;
63 12
        $this->eventDispatcher = $eventDispatcher;
64 12
    }
65
66
    /**
67
     * @param HasNodeInterface $page            The page
68
     * @param NodeTranslation  $nodeTranslation The node translation
69
     * @param NodeVersion      $nodeVersion     The node version
70
     *
71
     * @return NodeVersion
72
     */
73 1
    public function createDraftVersion(
74
        HasNodeInterface $page,
75
        NodeTranslation $nodeTranslation,
76
        NodeVersion $nodeVersion
77
    ) {
78 1
        $user = $this->getAdminUser();
79 1
        $publicPage = $this->cloneHelper->deepCloneAndSave($page);
80
81
        /* @var NodeVersion $publicNodeVersion */
82 1
        $publicNodeVersion = $this->em->getRepository(NodeVersion::class)
83 1
            ->createNodeVersionFor(
84 1
                $publicPage,
85
                $nodeTranslation,
86
                $user,
87 1
                $nodeVersion->getOrigin(),
88 1
                NodeVersion::PUBLIC_VERSION,
89 1
                $nodeVersion->getCreated()
90
            );
91
92 1
        $nodeTranslation->setPublicNodeVersion($publicNodeVersion);
93 1
        $nodeVersion->setType(NodeVersion::DRAFT_VERSION);
94 1
        $nodeVersion->setOrigin($publicNodeVersion);
95 1
        $nodeVersion->setCreated(new \DateTime());
96
97 1
        $this->em->persist($nodeTranslation);
98 1
        $this->em->persist($nodeVersion);
99 1
        $this->em->flush();
100
101 1
        $this->dispatch(
102 1
            new NodeEvent(
103 1
                $nodeTranslation->getNode(),
104
                $nodeTranslation,
105
                $nodeVersion,
106
                $page
107
            ),
108 1
            Events::CREATE_DRAFT_VERSION
109
        );
110
111 1
        return $nodeVersion;
112
    }
113
114
    /**
115
     * @param NodeVersion     $nodeVersion
116
     * @param NodeTranslation $nodeTranslation
117
     * @param int             $nodeVersionTimeout
118
     * @param bool            $nodeVersionIsLocked
119
     */
120 2
    public function prepareNodeVersion(NodeVersion $nodeVersion, NodeTranslation $nodeTranslation, $nodeVersionTimeout, $nodeVersionIsLocked)
121
    {
122 2
        $user = $this->getAdminUser();
123 2
        $thresholdDate = date('Y-m-d H:i:s', time() - $nodeVersionTimeout);
124 2
        $updatedDate = date('Y-m-d H:i:s', strtotime($nodeVersion->getUpdated()->format('Y-m-d H:i:s')));
125
126 2 View Code Duplication
        if ($thresholdDate >= $updatedDate || $nodeVersionIsLocked) {
127 2
            $page = $nodeVersion->getRef($this->em);
0 ignored issues
show
$this->em of type object<Doctrine\ORM\EntityManagerInterface> is not a sub-type of object<Doctrine\ORM\EntityManager>. It seems like you assume a concrete implementation of the interface Doctrine\ORM\EntityManagerInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
128 2
            if ($nodeVersion === $nodeTranslation->getPublicNodeVersion()) {
129 1
                $this->nodeAdminPublisher
130 1
                    ->createPublicVersion(
131 1
                        $page,
132
                        $nodeTranslation,
133
                        $nodeVersion,
134
                        $user
135
                    );
136
            } else {
137 1
                $this->createDraftVersion(
138 1
                    $page,
139
                    $nodeTranslation,
140
                    $nodeVersion
141
                );
142
            }
143
        }
144 2
    }
145
146
    /**
147
     * @param Node             $node
148
     * @param NodeTranslation  $nodeTranslation
149
     * @param NodeVersion      $nodeVersion
150
     * @param HasNodeInterface $page
151
     * @param bool             $isStructureNode
152
     * @param TabPane          $tabPane
153
     *
154
     * @return NodeTranslation
155
     */
156 1
    public function updatePage(
157
        Node $node,
158
        NodeTranslation $nodeTranslation,
159
        NodeVersion $nodeVersion,
160
        HasNodeInterface $page,
161
        $isStructureNode,
162
        TabPane $tabPane = null
163
    ) {
164 1
        $this->dispatch(
165 1
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page),
166 1
            Events::PRE_PERSIST
167
        );
168
169 1
        $nodeTranslation->setTitle($page->getTitle());
170 1
        if ($isStructureNode) {
171
            $nodeTranslation->setSlug('');
172
        }
173
174 1
        $nodeVersion->setUpdated(new \DateTime());
175 1
        if ($nodeVersion->getType() == NodeVersion::PUBLIC_VERSION) {
176 1
            $nodeTranslation->setUpdated($nodeVersion->getUpdated());
177
        }
178 1
        $this->em->persist($nodeTranslation);
179 1
        $this->em->persist($nodeVersion);
180 1
        $this->em->persist($node);
181 1
        if (null !== $tabPane) {
182
            $tabPane->persist($this->em);
0 ignored issues
show
$this->em of type object<Doctrine\ORM\EntityManagerInterface> is not a sub-type of object<Doctrine\ORM\EntityManager>. It seems like you assume a concrete implementation of the interface Doctrine\ORM\EntityManagerInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
183
        }
184 1
        $this->em->flush();
185
186 1
        $this->dispatch(
187 1
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page),
188 1
            Events::POST_PERSIST
189
        );
190
191 1
        return $nodeTranslation;
192
    }
193
194
    /**
195
     * @param string    $refEntityType
196
     * @param string    $pageTitle
197
     * @param string    $locale
198
     * @param Node|null $parentNode
199
     *
200
     * @return NodeTranslation
201
     */
202 1
    public function createPage(
203
        $refEntityType,
204
        $pageTitle,
205
        $locale,
206
        Node $parentNode = null)
207
    {
208 1
        $user = $this->getAdminUser();
209
210 1
        $newPage = $this->createNewPage($refEntityType, $pageTitle);
211 1
        if (null !== $parentNode) {
212 1
            $parentNodeTranslation = $parentNode->getNodeTranslation($locale, true);
213 1
            $parentNodeVersion = $parentNodeTranslation->getPublicNodeVersion();
214 1
            $parentPage = $parentNodeVersion->getRef($this->em);
215 1
            $newPage->setParent($parentPage);
216
        }
217
218
        /* @var Node $nodeNewPage */
219 1
        $nodeNewPage = $this->em->getRepository(Node::class)->createNodeFor($newPage, $locale, $user);
220 1
        $nodeTranslation = $nodeNewPage->getNodeTranslation($locale, true);
221 1
        if (null !== $parentNode) {
222 1
            $weight = $this->em->getRepository(NodeTranslation::class)->getMaxChildrenWeight(
223 1
                    $parentNode,
224
                    $locale
225 1
                ) + 1;
226 1
            $nodeTranslation->setWeight($weight);
227
        }
228
229 1
        if ($newPage->isStructureNode()) {
230
            $nodeTranslation->setSlug('');
231
        }
232
233 1
        $this->em->persist($nodeTranslation);
234 1
        $this->em->flush();
235
236 1
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
237
238 1
        $this->dispatch(
239 1
            new NodeEvent($nodeNewPage, $nodeTranslation, $nodeVersion, $newPage),
240 1
            Events::ADD_NODE
241
        );
242
243 1
        return $nodeTranslation;
244
    }
245
246
    /**
247
     * @param Node   $node
248
     * @param string $locale
249
     *
250
     * @return NodeTranslation
251
     */
252 1
    public function deletePage(Node $node, $locale)
253
    {
254 1
        $nodeTranslation = $node->getNodeTranslation($locale, true);
255 1
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
256 1
        $page = $nodeVersion->getRef($this->em);
257
258 1
        $this->dispatch(
259 1
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page),
260 1
            Events::PRE_DELETE
261
        );
262
263 1
        $node->setDeleted(true);
264 1
        $this->em->persist($node);
265
266 1
        $this->deleteNodeChildren($node, $locale);
267 1
        $this->em->flush();
268
269 1
        $this->dispatch(
270 1
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page),
271 1
            Events::POST_DELETE
272
        );
273
274 1
        return $nodeTranslation;
275
    }
276
277
    /**
278
     * @param Node   $node
279
     * @param string $locale
280
     *
281
     * @return HasNodeInterface
282
     */
283 1
    public function getPageWithNodeInterface(Node $node, $locale)
284
    {
285 1
        $nodeTranslation = $node->getNodeTranslation($locale, true);
286 1
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
287
288 1
        return $nodeVersion->getRef($this->em);
289
    }
290
291
    /**
292
     * @param Node   $node
293
     * @param string $sourceLocale
294
     * @param string $locale
295
     *
296
     * @return NodeTranslation
297
     */
298 1 View Code Duplication
    public function copyPageFromOtherLanguage(Node $node, $sourceLocale, $locale)
299
    {
300 1
        $user = $this->getAdminUser();
301
302 1
        $sourceNodeTranslation = $node->getNodeTranslation($sourceLocale, true);
303 1
        $sourceNodeVersion = $sourceNodeTranslation->getPublicNodeVersion();
304 1
        $sourcePage = $sourceNodeVersion->getRef($this->em);
305 1
        $targetPage = $this->cloneHelper->deepCloneAndSave($sourcePage);
306
307
        /* @var NodeTranslation $nodeTranslation */
308 1
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)->createNodeTranslationFor($targetPage, $locale, $node, $user);
309 1
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
310
311 1
        $this->dispatch(
312 1
            new CopyPageTranslationNodeEvent(
313 1
                $node,
314
                $nodeTranslation,
315
                $nodeVersion,
316
                $targetPage,
317
                $sourceNodeTranslation,
318
                $sourceNodeVersion,
319
                $sourcePage,
320
                $sourceLocale
321
            ),
322 1
            Events::COPY_PAGE_TRANSLATION
323
        );
324
325 1
        return $nodeTranslation;
326
    }
327
328
    /**
329
     * @param Node   $node
330
     * @param string $locale
331
     * @param string $title
332
     *
333
     * @return NodeTranslation|null
334
     */
335 1
    public function duplicatePage(Node $node, $locale, $title = 'New page')
336
    {
337 1
        $user = $this->getAdminUser();
338
339 1
        $sourceNodeTranslations = $node->getNodeTranslation($locale, true);
340 1
        $sourcePage = $sourceNodeTranslations->getPublicNodeVersion()->getRef($this->em);
341 1
        $targetPage = $this->cloneHelper->deepCloneAndSave($sourcePage);
342 1
        $targetPage->setTitle($title);
343
344 1
        if ($node->getParent()) {
345 1
            $parentNodeTranslation = $node->getParent()->getNodeTranslation($locale, true);
346 1
            $parent = $parentNodeTranslation->getPublicNodeVersion()->getRef($this->em);
347 1
            $targetPage->setParent($parent);
348
        }
349 1
        $this->em->persist($targetPage);
350 1
        $this->em->flush();
351
352
        /* @var Node $nodeNewPage */
353 1
        $nodeNewPage = $this->em->getRepository(Node::class)->createNodeFor($targetPage, $locale, $user);
354
355 1
        $nodeTranslation = $nodeNewPage->getNodeTranslation($locale, true);
356 1
        if ($targetPage->isStructureNode()) {
357
            $nodeTranslation->setSlug('');
358
            $this->em->persist($nodeTranslation);
359
        }
360 1
        $this->em->flush();
361
362 1
        return $nodeTranslation;
363
    }
364
365
    /**
366
     * @param Node   $node
367
     * @param int    $sourceNodeTranslationId
368
     * @param string $locale
369
     *
370
     * @return NodeTranslation
371
     */
372 1 View Code Duplication
    public function createPageDraftFromOtherLanguage(Node $node, $sourceNodeTranslationId, $locale)
373
    {
374 1
        $user = $this->getAdminUser();
375
376 1
        $sourceNodeTranslation = $this->em->getRepository(NodeTranslation::class)->find($sourceNodeTranslationId);
377 1
        $sourceNodeVersion = $sourceNodeTranslation->getPublicNodeVersion();
378 1
        $sourcePage = $sourceNodeVersion->getRef($this->em);
379 1
        $targetPage = $this->cloneHelper->deepCloneAndSave($sourcePage);
380
381
        /* @var NodeTranslation $nodeTranslation */
382 1
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)->addDraftNodeVersionFor($targetPage, $locale, $node, $user);
383 1
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
384
385 1
        $this->dispatch(
386 1
            new RecopyPageTranslationNodeEvent(
387 1
                $node,
388
                $nodeTranslation,
389
                $nodeVersion,
390
                $targetPage,
391
                $sourceNodeTranslation,
392
                $sourceNodeVersion,
393
                $sourcePage,
394 1
                $sourceNodeTranslation->getLang()
395
            ),
396 1
            Events::RECOPY_PAGE_TRANSLATION
397
        );
398
399 1
        return $nodeTranslation;
400
    }
401
402
    /**
403
     * @param Node   $node
404
     * @param string $locale
405
     *
406
     * @return NodeTranslation
407
     */
408 1
    public function createEmptyPage(Node $node, $locale)
409
    {
410 1
        $user = $this->getAdminUser();
411
412 1
        $refEntityName = $node->getRefEntityName();
413 1
        $targetPage = $this->createNewPage($refEntityName);
414
415
        /* @var NodeTranslation $nodeTranslation */
416 1
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)->createNodeTranslationFor($targetPage, $locale, $node, $user);
417 1
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
418
419 1
        $this->dispatch(
420 1
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $targetPage),
421 1
            Events::ADD_EMPTY_PAGE_TRANSLATION
422
        );
423
424 1
        return $nodeTranslation;
425
    }
426
427
    /**
428
     * @param string $entityType
429
     * @param string $title
430
     *
431
     * @return HasNodeInterface
432
     */
433 2
    protected function createNewPage($entityType, $title = 'No title')
434
    {
435
        /* @var HasNodeInterface $newPage */
436 2
        $newPage = new $entityType();
437 2
        $newPage->setTitle($title);
438
439 2
        $this->em->persist($newPage);
440 2
        $this->em->flush();
441
442 2
        return $newPage;
443
    }
444
445
    /**
446
     * @param Node   $node
447
     * @param string $locale
448
     */
449 1 View Code Duplication
    protected function deleteNodeChildren(Node $node, $locale)
450
    {
451 1
        $children = $node->getChildren();
452
453
        /* @var Node $childNode */
454 1
        foreach ($children as $childNode) {
455 1
            $childNodeTranslation = $childNode->getNodeTranslation($locale, true);
456 1
            $childNodeVersion = $childNodeTranslation->getPublicNodeVersion();
457 1
            $childNodePage = $childNodeVersion->getRef($this->em);
458
459 1
            $this->dispatch(
460 1
                new NodeEvent(
461 1
                    $childNode,
462
                    $childNodeTranslation,
463
                    $childNodeVersion,
464
                    $childNodePage
465
                ),
466 1
                Events::PRE_DELETE
467
            );
468
469 1
            $childNode->setDeleted(true);
470 1
            $this->em->persist($childNode);
471
472 1
            $this->deleteNodeChildren($childNode, $locale);
473
474 1
            $this->dispatch(
475 1
                new NodeEvent(
476 1
                    $childNode,
477
                    $childNodeTranslation,
478
                    $childNodeVersion,
479
                    $childNodePage
480
                ),
481 1
                Events::POST_DELETE
482
            );
483
        }
484 1
    }
485
486
    /**
487
     * @return mixed|null
488
     */
489 8
    protected function getUser()
490
    {
491 8
        $token = $this->tokenStorage->getToken();
492 8
        if ($token) {
493 8
            $user = $token->getUser();
494 8
            if ($user && $user !== 'anon.' && $user instanceof User) {
495 8
                return $user;
496
            }
497
        }
498
499
        return null;
500
    }
501
502
    /**
503
     * @return mixed
504
     */
505 8
    protected function getAdminUser()
506
    {
507 8
        $user = $this->getUser();
508 8
        if (!$user) {
509
            throw new AccessDeniedException('Access denied: User should be an admin user');
510
        }
511
512 8
        return $user;
513
    }
514
515
    /**
516
     * @param object $event
517
     * @param string $eventName
518
     *
519
     * @return object
520
     */
521 7 View Code Duplication
    private function dispatch($event, string $eventName)
522
    {
523 7
        if (class_exists(LegacyEventDispatcherProxy::class)) {
524 7
            $eventDispatcher = LegacyEventDispatcherProxy::decorate($this->eventDispatcher);
525
526 7
            return $eventDispatcher->dispatch($event, $eventName);
527
        }
528
529
        return $this->eventDispatcher->dispatch($eventName, $event);
530
    }
531
}
532