1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Kunstmaan\NodeBundle\EventListener; |
4
|
|
|
|
5
|
|
|
use Doctrine\ORM\EntityManager; |
6
|
|
|
use Kunstmaan\NodeBundle\Controller\SlugActionInterface; |
7
|
|
|
use Kunstmaan\NodeBundle\Entity\NodeTranslation; |
8
|
|
|
use Kunstmaan\NodeBundle\Event\Events; |
9
|
|
|
use Kunstmaan\NodeBundle\Event\SlugSecurityEvent; |
10
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
11
|
|
|
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; |
12
|
|
|
use Symfony\Component\HttpKernel\Event\ControllerEvent; |
13
|
|
|
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; |
14
|
|
|
|
15
|
|
|
class SlugListener |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* @var EntityManager |
19
|
|
|
*/ |
20
|
|
|
protected $em; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var ControllerResolverInterface |
24
|
|
|
*/ |
25
|
|
|
protected $resolver; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var EventDispatcherInterface |
29
|
|
|
*/ |
30
|
|
|
protected $eventDispatcher; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* SlugListener constructor. |
34
|
|
|
* |
35
|
|
|
* @param EntityManager $em |
36
|
|
|
* @param ControllerResolverInterface $resolver |
37
|
|
|
* @param EventDispatcherInterface $eventDispatcher |
38
|
|
|
*/ |
39
|
|
|
public function __construct(EntityManager $em, ControllerResolverInterface $resolver, EventDispatcherInterface $eventDispatcher) |
|
|
|
|
40
|
|
|
{ |
41
|
|
|
$this->em = $em; |
42
|
|
|
$this->resolver = $resolver; |
43
|
|
|
$this->eventDispatcher = $eventDispatcher; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @param FilterControllerEvent|ControllerEvent $event |
48
|
|
|
* |
49
|
|
|
* @throws \Exception |
50
|
|
|
*/ |
51
|
|
|
public function onKernelController($event) |
52
|
|
|
{ |
53
|
|
View Code Duplication |
if (!$event instanceof FilterControllerEvent && !$event instanceof ControllerEvent) { |
|
|
|
|
54
|
|
|
throw new \InvalidArgumentException(\sprintf('Expected instance of type %s, %s given', \class_exists(ControllerEvent::class) ? ControllerEvent::class : FilterControllerEvent::class, \is_object($event) ? \get_class($event) : \gettype($event))); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
$request = $event->getRequest(); |
58
|
|
|
|
59
|
|
|
// Check if the event has a nodeTranslation, if not this method can be skipped |
60
|
|
|
if (!$request->attributes->has('_nodeTranslation')) { |
61
|
|
|
return; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
$nodeTranslation = $request->attributes->get('_nodeTranslation'); |
65
|
|
|
if (!($nodeTranslation instanceof NodeTranslation)) { |
66
|
|
|
throw new \Exception('Invalid _nodeTranslation value found in request attributes'); |
67
|
|
|
} |
68
|
|
|
$entity = $nodeTranslation->getRef($this->em); |
69
|
|
|
|
70
|
|
|
// If the entity is an instance of the SlugActionInterface, change the controller |
71
|
|
|
if ($entity instanceof SlugActionInterface) { |
72
|
|
|
$request->attributes->set('_entity', $entity); |
73
|
|
|
|
74
|
|
|
// Do security check by firing an event that gets handled by the SlugSecurityListener |
75
|
|
|
$securityEvent = new SlugSecurityEvent(); |
76
|
|
|
$securityEvent |
77
|
|
|
->setNode($nodeTranslation->getNode()) |
78
|
|
|
->setEntity($entity) |
79
|
|
|
->setRequest($request) |
80
|
|
|
->setNodeTranslation($nodeTranslation); |
81
|
|
|
|
82
|
|
|
$this->eventDispatcher->dispatch(Events::SLUG_SECURITY, $securityEvent); |
83
|
|
|
|
84
|
|
|
// Set the right controller |
85
|
|
|
$request->attributes->set('_controller', $entity->getControllerAction()); |
86
|
|
|
$event->setController($this->resolver->getController($request)); |
|
|
|
|
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
The
EntityManager
might become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManager
is closed. Any other code which depends on the same instance of theEntityManager
during this request will fail.On the other hand, if you instead inject the
ManagerRegistry
, thegetManager()
method guarantees that you will always get a usable manager instance.