Completed
Push — master ( 1af7e7...796d56 )
by Jeroen
16s
created

src/Kunstmaan/NodeBundle/Helper/NodeHelper.php (3 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\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
20
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
21
22
/**
23
 * Class NodeHelper
24
 */
25
class NodeHelper
26
{
27
    /** @var EntityManagerInterface */
28
    private $em;
29
30
    /** @var NodeAdminPublisher */
31
    private $nodeAdminPublisher;
32
33
    /** @var TokenStorageInterface */
34
    private $tokenStorage;
35
36
    /** @var CloneHelper */
37
    private $cloneHelper;
38
39
    /** @var EventDispatcherInterface */
40
    private $eventDispatcher;
41
42
    /**
43
     * NodeHelper constructor.
44
     *
45
     * @param EntityManagerInterface   $em
46
     * @param NodeAdminPublisher       $nodeAdminPublisher
47
     * @param TokenStorageInterface    $tokenStorage
48
     * @param CloneHelper              $cloneHelper
49
     * @param EventDispatcherInterface $eventDispatcher
50
     */
51 View Code Duplication
    public function __construct(
52
        EntityManagerInterface $em,
53
        NodeAdminPublisher $nodeAdminPublisher,
54
        TokenStorageInterface $tokenStorage,
55
        CloneHelper $cloneHelper,
56
        EventDispatcherInterface $eventDispatcher
57
    ) {
58
        $this->em = $em;
59
        $this->nodeAdminPublisher = $nodeAdminPublisher;
60
        $this->tokenStorage = $tokenStorage;
61
        $this->cloneHelper = $cloneHelper;
62
        $this->eventDispatcher = $eventDispatcher;
63
    }
64
65
    /**
66
     * @param HasNodeInterface $page            The page
67
     * @param NodeTranslation  $nodeTranslation The node translation
68
     * @param NodeVersion      $nodeVersion     The node version
69
     *
70
     * @return NodeVersion
71
     */
72
    public function createDraftVersion(
73
        HasNodeInterface $page,
74
        NodeTranslation $nodeTranslation,
75
        NodeVersion $nodeVersion
76
    ) {
77
        $user = $this->getAdminUser();
78
        $publicPage = $this->cloneHelper->deepCloneAndSave($page);
79
80
        /* @var NodeVersion $publicNodeVersion */
81
        $publicNodeVersion = $this->em->getRepository('KunstmaanNodeBundle:NodeVersion')
82
            ->createNodeVersionFor(
83
                $publicPage,
84
                $nodeTranslation,
85
                $user,
86
                $nodeVersion->getOrigin(),
87
                NodeVersion::PUBLIC_VERSION,
88
                $nodeVersion->getCreated()
89
            );
90
91
        $nodeTranslation->setPublicNodeVersion($publicNodeVersion);
92
        $nodeVersion->setType(NodeVersion::DRAFT_VERSION);
93
        $nodeVersion->setOrigin($publicNodeVersion);
94
        $nodeVersion->setCreated(new \DateTime());
95
96
        $this->em->persist($nodeTranslation);
97
        $this->em->persist($nodeVersion);
98
        $this->em->flush();
99
100
        $this->eventDispatcher->dispatch(
101
            Events::CREATE_DRAFT_VERSION,
102
            new NodeEvent(
103
                $nodeTranslation->getNode(),
104
                $nodeTranslation,
105
                $nodeVersion,
106
                $page
107
            )
108
        );
109
110
        return $nodeVersion;
111
    }
112
113
    /**
114
     * @param NodeVersion     $nodeVersion
115
     * @param NodeTranslation $nodeTranslation
116
     * @param int             $nodeVersionTimeout
117
     * @param bool            $nodeVersionIsLocked
118
     */
119
    public function prepareNodeVersion(NodeVersion $nodeVersion, NodeTranslation $nodeTranslation, $nodeVersionTimeout, $nodeVersionIsLocked)
120
    {
121
        $user = $this->getAdminUser();
122
        $thresholdDate = date('Y-m-d H:i:s', time() - $nodeVersionTimeout);
123
        $updatedDate = date('Y-m-d H:i:s', strtotime($nodeVersion->getUpdated()->format('Y-m-d H:i:s')));
124
125 View Code Duplication
        if ($thresholdDate >= $updatedDate || $nodeVersionIsLocked) {
126
            $page = $nodeVersion->getRef($this->em);
127
            if ($nodeVersion === $nodeTranslation->getPublicNodeVersion()) {
128
                $this->nodeAdminPublisher
129
                    ->createPublicVersion(
130
                        $page,
131
                        $nodeTranslation,
132
                        $nodeVersion,
133
                        $user
134
                    );
135
            } else {
136
                $this->createDraftVersion(
137
                    $page,
138
                    $nodeTranslation,
139
                    $nodeVersion
140
                );
141
            }
142
        }
143
    }
144
145
    /**
146
     * @param Node             $node
147
     * @param NodeTranslation  $nodeTranslation
148
     * @param NodeVersion      $nodeVersion
149
     * @param HasNodeInterface $page
150
     * @param bool             $isStructureNode
151
     * @param TabPane          $tabPane
0 ignored issues
show
Should the type for parameter $tabPane not be null|TabPane?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
152
     *
153
     * @return NodeTranslation
154
     */
155
    public function updatePage(
156
        Node $node,
157
        NodeTranslation $nodeTranslation,
158
        NodeVersion $nodeVersion,
159
        HasNodeInterface $page,
160
        $isStructureNode,
161
        TabPane $tabPane = null
162
    ) {
163
        $this->eventDispatcher->dispatch(
164
            Events::PRE_PERSIST,
165
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
166
        );
167
168
        $nodeTranslation->setTitle($page->getTitle());
169
        if ($isStructureNode) {
170
            $nodeTranslation->setSlug('');
171
        }
172
173
        $nodeVersion->setUpdated(new \DateTime());
174
        if ($nodeVersion->getType() == NodeVersion::PUBLIC_VERSION) {
175
            $nodeTranslation->setUpdated($nodeVersion->getUpdated());
176
        }
177
        $this->em->persist($nodeTranslation);
178
        $this->em->persist($nodeVersion);
179
        $this->em->persist($node);
180
        if (null !== $tabPane) {
181
            $tabPane->persist($this->em);
182
        }
183
        $this->em->flush();
184
185
        $this->eventDispatcher->dispatch(
186
            Events::POST_PERSIST,
187
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
188
        );
189
190
        return $nodeTranslation;
191
    }
192
193
    /**
194
     * @param string    $refEntityType
195
     * @param string    $pageTitle
196
     * @param string    $locale
197
     * @param Node|null $parentNode
198
     *
199
     * @return NodeTranslation
0 ignored issues
show
Should the return type not be NodeTranslation|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
200
     */
201
    public function createPage(
202
        $refEntityType,
203
        $pageTitle,
204
        $locale,
205
        Node $parentNode = null)
206
    {
207
        $user = $this->getAdminUser();
208
209
        $newPage = $this->createNewPage($refEntityType, $pageTitle);
210
        if (null !== $parentNode) {
211
            $parentNodeTranslation = $parentNode->getNodeTranslation($locale, true);
212
            $parentNodeVersion = $parentNodeTranslation->getPublicNodeVersion();
213
            $parentPage = $parentNodeVersion->getRef($this->em);
214
            $newPage->setParent($parentPage);
215
        }
216
217
        /* @var Node $nodeNewPage */
218
        $nodeNewPage = $this->em->getRepository('KunstmaanNodeBundle:Node')->createNodeFor($newPage, $locale, $user);
219
        $nodeTranslation = $nodeNewPage->getNodeTranslation($locale, true);
220
        if (null !== $parentNode) {
221
            $weight = $this->em->getRepository('KunstmaanNodeBundle:NodeTranslation')->getMaxChildrenWeight(
222
                    $parentNode,
223
                    $locale
224
                ) + 1;
225
            $nodeTranslation->setWeight($weight);
226
        }
227
228
        if ($newPage->isStructureNode()) {
229
            $nodeTranslation->setSlug('');
230
        }
231
232
        $this->em->persist($nodeTranslation);
233
        $this->em->flush();
234
235
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
236
237
        $this->eventDispatcher->dispatch(
238
            Events::ADD_NODE,
239
            new NodeEvent(
240
                $nodeNewPage, $nodeTranslation, $nodeVersion, $newPage
241
            )
242
        );
243
244
        return $nodeTranslation;
245
    }
246
247
    /**
248
     * @param Node   $node
249
     * @param string $locale
250
     *
251
     * @return NodeTranslation
0 ignored issues
show
Should the return type not be NodeTranslation|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
252
     */
253
    public function deletePage(Node $node, $locale)
254
    {
255
        $nodeTranslation = $node->getNodeTranslation($locale, true);
256
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
257
        $page = $nodeVersion->getRef($this->em);
258
259
        $this->eventDispatcher->dispatch(
260
            Events::PRE_DELETE,
261
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
262
        );
263
264
        $node->setDeleted(true);
265
        $this->em->persist($node);
266
267
        $this->deleteNodeChildren($node, $locale);
268
        $this->em->flush();
269
270
        $this->eventDispatcher->dispatch(
271
            Events::POST_DELETE,
272
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $page)
273
        );
274
275
        return $nodeTranslation;
276
    }
277
278
    /**
279
     * @param Node   $node
280
     * @param string $locale
281
     *
282
     * @return HasNodeInterface
283
     */
284
    public function getPageWithNodeInterface(Node $node, $locale)
285
    {
286
        $nodeTranslation = $node->getNodeTranslation($locale, true);
287
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
288
289
        return $nodeVersion->getRef($this->em);
290
    }
291
292
    /**
293
     * @param Node   $node
294
     * @param string $sourceLocale
295
     * @param string $locale
296
     *
297
     * @return NodeTranslation
298
     */
299 View Code Duplication
    public function copyPageFromOtherLanguage(Node $node, $sourceLocale, $locale)
300
    {
301
        $user = $this->getAdminUser();
302
303
        $sourceNodeTranslation = $node->getNodeTranslation($sourceLocale, true);
304
        $sourceNodeVersion = $sourceNodeTranslation->getPublicNodeVersion();
305
        $sourcePage = $sourceNodeVersion->getRef($this->em);
306
        $targetPage = $this->cloneHelper->deepCloneAndSave($sourcePage);
307
308
        /* @var NodeTranslation $nodeTranslation */
309
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)->createNodeTranslationFor($targetPage, $locale, $node, $user);
310
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
311
312
        $this->eventDispatcher->dispatch(
313
            Events::COPY_PAGE_TRANSLATION,
314
            new CopyPageTranslationNodeEvent(
315
                $node,
316
                $nodeTranslation,
317
                $nodeVersion,
318
                $targetPage,
319
                $sourceNodeTranslation,
320
                $sourceNodeVersion,
321
                $sourcePage,
322
                $sourceLocale
323
            )
324
        );
325
326
        return $nodeTranslation;
327
    }
328
329
    /**
330
     * @param Node   $node
331
     * @param string $locale
332
     * @param string $title
333
     *
334
     * @return NodeTranslation|null
335
     */
336
    public function duplicatePage(Node $node, $locale, $title = 'New page')
337
    {
338
        $user = $this->getAdminUser();
339
340
        $sourceNodeTranslations = $node->getNodeTranslation($locale, true);
341
        $sourcePage = $sourceNodeTranslations->getPublicNodeVersion()->getRef($this->em);
342
        $targetPage = $this->cloneHelper->deepCloneAndSave($sourcePage);
343
        $targetPage->setTitle($title);
344
345
        if ($node->getParent()) {
346
            $parentNodeTranslation = $node->getParent()->getNodeTranslation($locale, true);
347
            $parent = $parentNodeTranslation->getPublicNodeVersion()->getRef($this->em);
348
            $targetPage->setParent($parent);
349
        }
350
        $this->em->persist($targetPage);
351
        $this->em->flush();
352
353
        /* @var Node $nodeNewPage */
354
        $nodeNewPage = $this->em->getRepository(Node::class)->createNodeFor($targetPage, $locale, $user);
355
356
        $nodeTranslation = $nodeNewPage->getNodeTranslation($locale, true);
357
        if ($targetPage->isStructureNode()) {
358
            $nodeTranslation->setSlug('');
359
            $this->em->persist($nodeTranslation);
360
        }
361
        $this->em->flush();
362
363
        return $nodeTranslation;
364
    }
365
366
    /**
367
     * @param Node   $node
368
     * @param int    $sourceNodeTranslationId
369
     * @param string $locale
370
     *
371
     * @return NodeTranslation
372
     */
373 View Code Duplication
    public function createPageDraftFromOtherLanguage(Node $node, $sourceNodeTranslationId, $locale)
374
    {
375
        $user = $this->getAdminUser();
376
377
        $sourceNodeTranslation = $this->em->getRepository(NodeTranslation::class)->find($sourceNodeTranslationId);
378
        $sourceNodeVersion = $sourceNodeTranslation->getPublicNodeVersion();
379
        $sourcePage = $sourceNodeVersion->getRef($this->em);
380
        $targetPage = $this->cloneHelper->deepCloneAndSave($sourcePage);
381
382
        /* @var NodeTranslation $nodeTranslation */
383
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)->addDraftNodeVersionFor($targetPage, $locale, $node, $user);
384
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
385
386
        $this->eventDispatcher->dispatch(
387
            Events::RECOPY_PAGE_TRANSLATION,
388
            new RecopyPageTranslationNodeEvent(
389
                $node,
390
                $nodeTranslation,
391
                $nodeVersion,
392
                $targetPage,
393
                $sourceNodeTranslation,
394
                $sourceNodeVersion,
395
                $sourcePage,
396
                $sourceNodeTranslation->getLang()
397
            )
398
        );
399
400
        return $nodeTranslation;
401
    }
402
403
    /**
404
     * @param Node   $node
405
     * @param string $locale
406
     *
407
     * @return NodeTranslation
408
     */
409
    public function createEmptyPage(Node $node, $locale)
410
    {
411
        $user = $this->getAdminUser();
412
413
        $refEntityName = $node->getRefEntityName();
414
        $targetPage = $this->createNewPage($refEntityName);
415
416
        /* @var NodeTranslation $nodeTranslation */
417
        $nodeTranslation = $this->em->getRepository(NodeTranslation::class)->createNodeTranslationFor($targetPage, $locale, $node, $user);
418
        $nodeVersion = $nodeTranslation->getPublicNodeVersion();
419
420
        $this->eventDispatcher->dispatch(
421
            Events::ADD_EMPTY_PAGE_TRANSLATION,
422
            new NodeEvent($node, $nodeTranslation, $nodeVersion, $targetPage)
423
        );
424
425
        return $nodeTranslation;
426
    }
427
428
    /**
429
     * @param string $entityType
430
     * @param string $title
431
     *
432
     * @return HasNodeInterface
433
     */
434
    protected function createNewPage($entityType, $title = 'No title')
435
    {
436
        /* @var HasNodeInterface $newPage */
437
        $newPage = new $entityType();
438
        $newPage->setTitle($title);
439
440
        $this->em->persist($newPage);
441
        $this->em->flush();
442
443
        return $newPage;
444
    }
445
446
    /**
447
     * @param Node   $node
448
     * @param string $locale
449
     */
450
    protected function deleteNodeChildren(Node $node, $locale)
451
    {
452
        $children = $node->getChildren();
453
454
        /* @var Node $childNode */
455
        foreach ($children as $childNode) {
456
            $childNodeTranslation = $childNode->getNodeTranslation($locale, true);
457
            $childNodeVersion = $childNodeTranslation->getPublicNodeVersion();
458
            $childNodePage = $childNodeVersion->getRef($this->em);
459
460
            $this->eventDispatcher->dispatch(
461
                Events::PRE_DELETE,
462
                new NodeEvent(
463
                    $childNode,
464
                    $childNodeTranslation,
465
                    $childNodeVersion,
466
                    $childNodePage
467
                )
468
            );
469
470
            $childNode->setDeleted(true);
471
            $this->em->persist($childNode);
472
473
            $this->deleteNodeChildren($childNode, $locale);
474
475
            $this->eventDispatcher->dispatch(
476
                Events::POST_DELETE,
477
                new NodeEvent(
478
                    $childNode,
479
                    $childNodeTranslation,
480
                    $childNodeVersion,
481
                    $childNodePage
482
                )
483
            );
484
        }
485
    }
486
487
    /**
488
     * @return mixed|null
489
     */
490
    protected function getUser()
491
    {
492
        $token = $this->tokenStorage->getToken();
493
        if ($token) {
494
            $user = $token->getUser();
495
            if ($user && $user !== 'anon.' && $user instanceof User) {
496
                return $user;
497
            }
498
        }
499
500
        return null;
501
    }
502
503
    /**
504
     * @return mixed
505
     */
506
    protected function getAdminUser()
507
    {
508
        $user = $this->getUser();
509
        if (!$user) {
510
            throw new AccessDeniedException('Access denied: User should be an admin user');
511
        }
512
513
        return $user;
514
    }
515
}
516