Passed
Pull Request — master (#2506)
by Alan
04:15
created

EventDispatcher   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 50
dl 0
loc 81
rs 10
c 0
b 0
f 0
wmc 9

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getSubscribedEvents() 0 5 1
A __construct() 0 3 1
B dispatch() 0 29 7
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\EventSubscriber;
15
16
use ApiPlatform\Core\Event\DeserializeEvent;
17
use ApiPlatform\Core\Event\Event as ApiPlatformEvent;
18
use ApiPlatform\Core\Event\FormatAddEvent;
19
use ApiPlatform\Core\Event\PostDeserializeEvent;
20
use ApiPlatform\Core\Event\PostReadEvent;
21
use ApiPlatform\Core\Event\PostRespondEvent;
22
use ApiPlatform\Core\Event\PostSerializeEvent;
23
use ApiPlatform\Core\Event\PostValidateEvent;
24
use ApiPlatform\Core\Event\PostWriteEvent;
25
use ApiPlatform\Core\Event\PreDeserializeEvent;
26
use ApiPlatform\Core\Event\PreReadEvent;
27
use ApiPlatform\Core\Event\PreRespondEvent;
28
use ApiPlatform\Core\Event\PreSerializeEvent;
29
use ApiPlatform\Core\Event\PreValidateEvent;
30
use ApiPlatform\Core\Event\PreWriteEvent;
31
use ApiPlatform\Core\Event\QueryParameterValidateEvent;
32
use ApiPlatform\Core\Event\ReadEvent;
33
use ApiPlatform\Core\Event\RespondEvent;
34
use ApiPlatform\Core\Event\SerializeEvent;
35
use ApiPlatform\Core\Event\ValidateEvent;
36
use ApiPlatform\Core\Event\ValidationExceptionEvent;
37
use ApiPlatform\Core\Event\WriteEvent;
38
use ApiPlatform\Core\Events;
39
use Symfony\Component\EventDispatcher\Event;
40
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
41
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
42
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
43
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
44
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
45
use Symfony\Component\HttpKernel\KernelEvents;
46
47
/**
48
 * @internal
49
 *
50
 * @author Alan Poulain <[email protected]>
51
 */
52
final class EventDispatcher implements EventSubscriberInterface
53
{
54
    private const INTERNAL_EVENTS_CONFIGURATION = [
55
        KernelEvents::REQUEST => [
56
            QueryParameterValidateEvent::class => Events::QUERY_PARAMETER_VALIDATE,
57
            FormatAddEvent::class => Events::FORMAT_ADD,
58
59
            PreReadEvent::class => Events::PRE_READ,
60
            ReadEvent::class => Events::READ,
61
            PostReadEvent::class => Events::POST_READ,
62
63
            PreDeserializeEvent::class => Events::PRE_DESERIALIZE,
64
            DeserializeEvent::class => Events::DESERIALIZE,
65
            PostDeserializeEvent::class => Events::POST_DESERIALIZE,
66
        ],
67
        KernelEvents::VIEW => [
68
            PreValidateEvent::class => Events::PRE_VALIDATE,
69
            ValidateEvent::class => Events::VALIDATE,
70
            PostValidateEvent::class => Events::POST_VALIDATE,
71
72
            PreWriteEvent::class => Events::PRE_WRITE,
73
            WriteEvent::class => Events::WRITE,
74
            PostWriteEvent::class => Events::POST_WRITE,
75
76
            PreSerializeEvent::class => Events::PRE_SERIALIZE,
77
            SerializeEvent::class => Events::SERIALIZE,
78
            PostSerializeEvent::class => Events::POST_SERIALIZE,
79
80
            PreRespondEvent::class => Events::PRE_RESPOND,
81
            RespondEvent::class => Events::RESPOND,
82
            PostRespondEvent::class => Events::POST_RESPOND, // @todo kernel.response
83
        ],
84
        KernelEvents::EXCEPTION => [
85
            ValidationExceptionEvent::class => Events::VALIDATE_EXCEPTION,
86
        ],
87
    ];
88
89
    private $dispatcher;
90
91
    public function __construct(EventDispatcherInterface $dispatcher)
92
    {
93
        $this->dispatcher = $dispatcher;
94
    }
95
96
    public static function getSubscribedEvents(): array
97
    {
98
        return [
99
            KernelEvents::REQUEST => 'dispatch',
100
            KernelEvents::VIEW => 'dispatch',
101
        ];
102
    }
103
104
    public function dispatch(Event $event, string $eventName): void
105
    {
106
        $internalEventData = null;
107
        $internalEventContext = [];
108
109
        // case order is important because of Symfony events inheritance
110
        switch (true) {
111
            case $event instanceof GetResponseForControllerResultEvent:
112
                $internalEventData = $event->getControllerResult();
113
                $internalEventContext = ['request' => $event->getRequest()];
114
                break;
115
            case $event instanceof GetResponseForExceptionEvent:
116
                $internalEventContext = ['request' => $event->getRequest(), 'exception' => $event->getException()];
117
                break;
118
            case $event instanceof GetResponseEvent:
119
                $internalEventContext = ['request' => $event->getRequest()];
120
                break;
121
        }
122
123
        foreach (self::INTERNAL_EVENTS_CONFIGURATION[$eventName] as $internalEventClass => $internalEventName) {
124
            /** @var ApiPlatformEvent $internalEvent */
125
            $internalEvent = new $internalEventClass($internalEventData, $internalEventContext);
126
127
            $this->dispatcher->dispatch($internalEventName, $internalEvent);
128
129
            $internalEventData = $internalEvent->getData();
130
            // @todo set controller result?
131
            if ($event instanceof GetResponseEvent && $response = $internalEvent->getContext()['response'] ?? null) {
132
                $event->setResponse($response);
133
            }
134
        }
135
    }
136
}
137