Completed
Push — master ( 2c9995...0e68f4 )
by Dawid
02:01
created

DataCollector::responseWasChecked()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiechu\SymfonyCommonsBundle\Service;
6
7
use Doctrine\Common\Annotations\Reader;
8
use Spiechu\SymfonyCommonsBundle\Annotation\Controller\ResponseSchemaValidator;
9
use Spiechu\SymfonyCommonsBundle\Event\ApiVersion\ApiVersionSetEvent;
10
use Spiechu\SymfonyCommonsBundle\Event\ResponseSchemaCheck\CheckResult;
11
use Spiechu\SymfonyCommonsBundle\Event\ResponseSchemaCheck\Events as ResponseSchemaCheckEvents;
12
use Spiechu\SymfonyCommonsBundle\Event\ApiVersion\Events as ApiVersionEvents;
13
use Spiechu\SymfonyCommonsBundle\EventListener\RequestSchemaValidatorListener;
14
use Symfony\Component\DependencyInjection\Container;
15
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpFoundation\Response;
18
use Symfony\Component\HttpKernel\DataCollector\DataCollector as BaseDataCollector;
19
use Symfony\Component\Routing\RouterInterface;
20
21
class DataCollector extends BaseDataCollector implements EventSubscriberInterface
22
{
23
    const COLLECTOR_NAME = 'spiechu_symfony_commons.data_collector';
24
25
    /**
26
     * @var RouterInterface
27
     */
28
    protected $router;
29
30
    /**
31
     * @var Reader
32
     */
33
    protected $reader;
34
35
    /**
36
     * @var Container
37
     */
38
    protected $container;
39
40
    /**
41
     * @param RouterInterface $router
42
     * @param Reader $reader
43
     * @param Container $container
44
     */
45 2
    public function __construct(RouterInterface $router, Reader $reader, Container $container)
46
    {
47 2
        $this->router = $router;
48 2
        $this->reader = $reader;
49 2
        $this->container = $container;
50 2
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 2
    public function collect(Request $request, Response $response, \Exception $exception = null): void
56
    {
57 2
        $this->data['known_response_schemas'] = $request->attributes->has(RequestSchemaValidatorListener::ATTRIBUTE_RESPONSE_SCHEMAS)
58 1
            ? $request->attributes->get(RequestSchemaValidatorListener::ATTRIBUTE_RESPONSE_SCHEMAS)
59 1
            : null;
60
61 2
        $this->extractRoutesData();
62 2
    }
63
64
    /**
65
     * {@inheritdoc}
66
     */
67 2
    public function getName(): string
68
    {
69 2
        return static::COLLECTOR_NAME;
70
    }
71
72
    /**
73
     * @return array
74
     */
75
    public function getGlobalResponseSchemas(): array
76
    {
77
        return $this->data['global_response_schemas'];
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83 3
    public static function getSubscribedEvents(): array
84
    {
85
        return [
86 3
            ResponseSchemaCheckEvents::CHECK_RESULT => ['onCheckResult', 100],
87 3
            ApiVersionEvents::API_VERSION_SET => ['onApiVersionSet', 100],
88
        ];
89
    }
90
91
    /**
92
     * @param CheckResult $checkResult
93
     */
94 1
    public function onCheckResult(CheckResult $checkResult): void
95
    {
96 1
        $this->data['validation_result'] = $checkResult->getValidationResult();
97 1
    }
98
99
    /**
100
     * @param ApiVersionSetEvent $apiVersionSetEvent
101
     */
102 1
    public function onApiVersionSet(ApiVersionSetEvent $apiVersionSetEvent): void
103
    {
104 1
        $this->data['api_version_set'] = $apiVersionSetEvent->getApiVersion();
105 1
    }
106
107
    /**
108
     * @return array
109
     */
110
    public function getKnownResponseSchemas(): array
111
    {
112
        return empty($this->data['known_response_schemas']) ? [] : $this->data['known_response_schemas'];
113
    }
114
115
    /**
116
     * @return int
117
     */
118
    public function getKnownResponseSchemaNumber(): int
119
    {
120
        $counter = 0;
121
122
        foreach ($this->getKnownResponseSchemas() as $format) {
123
            $counter += count($format);
124
        }
125
126
        return $counter;
127
    }
128
129
    /**
130
     * @return bool
131
     */
132 1
    public function responseWasChecked(): bool
133
    {
134 1
        return array_key_exists('validation_result', $this->data);
135
    }
136
137
    /**
138
     * @return bool
139
     */
140 1
    public function apiVersionWasSet(): bool
141
    {
142 1
        return array_key_exists('api_version_set', $this->data);
143
    }
144
145
    /**
146
     * @return string|null
147
     */
148
    public function getApiVersion(): ?string
149
    {
150
        return $this->apiVersionWasSet() ? $this->data['api_version_set'] : null;
151
    }
152
153
    /**
154
     * @return ValidationViolation[]
155
     */
156
    public function getValidationErrors(): array
157
    {
158
        if (!$this->responseWasChecked()) {
159
            return [];
160
        }
161
162
        return $this->data['validation_result']->getViolations();
163
    }
164
165 2
    protected function extractRoutesData(): void
166
    {
167 2
        $this->data['global_response_schemas'] = [];
168
169 2
        foreach ($this->router->getRouteCollection() as $name => $route) {
170 2
            $defaults = $route->getDefaults();
171
172 2
            if (empty($defaults['_controller'])) {
173
                continue;
174
            }
175
176 2
            $methodAnnotation = $this->extractControllerResponseValidator($defaults['_controller']);
177
178 2
            if (!$methodAnnotation instanceof ResponseSchemaValidator) {
179 2
                continue;
180
            }
181
182 2
            $this->data['global_response_schemas'][] = [
183 2
                'path' => $route->getPath(),
184 2
                'name' => $name,
185 2
                'controller' => $defaults['_controller'],
186 2
                'response_schemas' => $methodAnnotation->getSchemas(),
187
            ];
188
        }
189 2
    }
190
191
    /**
192
     * @param string $controllerDefinition
193
     *
194
     * @throws \Exception
195
     *
196
     * @return null|ResponseSchemaValidator
197
     */
198 2
    protected function extractControllerResponseValidator(string $controllerDefinition): ?ResponseSchemaValidator
199
    {
200 2
        [$controllerDefinition, $controllerMethod] = explode(':', $controllerDefinition, 2);
0 ignored issues
show
Bug introduced by
The variable $controllerMethod does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
201
202 2
        $controllerClass = $this->container->has($controllerDefinition)
203
            ? $this->container->get($controllerDefinition)
204 2
            : $controllerDefinition;
205
206 2
        $reflectedMethod = new \ReflectionMethod($controllerClass, ltrim($controllerMethod, ':'));
207
208 2
        return $this->reader->getMethodAnnotation($reflectedMethod, ResponseSchemaValidator::class);
209
    }
210
}
211