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