1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Spiechu\SymfonyCommonsBundle\Service\SchemaValidator; |
6
|
|
|
|
7
|
|
|
use Doctrine\Common\Annotations\Reader; |
8
|
|
|
use Spiechu\SymfonyCommonsBundle\Annotation\Controller\ControllerAnnotationExtractorTrait; |
9
|
|
|
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; |
10
|
|
|
use Symfony\Component\Config\FileLocatorInterface; |
11
|
|
|
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; |
12
|
|
|
use Symfony\Component\Routing\RouterInterface; |
13
|
|
|
use Spiechu\SymfonyCommonsBundle\Annotation\Controller\ResponseSchemaValidator; |
14
|
|
|
use Symfony\Component\HttpFoundation\Request; |
15
|
|
|
|
16
|
|
|
class SchemaFilesExistenceChecker |
17
|
|
|
{ |
18
|
|
|
use ControllerAnnotationExtractorTrait; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @var Reader |
22
|
|
|
*/ |
23
|
|
|
protected $reader; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var RouterInterface |
27
|
|
|
*/ |
28
|
|
|
protected $router; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var ControllerResolverInterface |
32
|
|
|
*/ |
33
|
|
|
protected $controllerResolver; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var FileLocatorInterface |
37
|
|
|
*/ |
38
|
|
|
protected $fileLocator; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @param Reader $reader |
42
|
|
|
* @param RouterInterface $router |
43
|
|
|
* @param ControllerResolverInterface $controllerResolver |
44
|
|
|
* @param FileLocatorInterface $fileLocator |
45
|
|
|
*/ |
46
|
6 |
|
public function __construct( |
47
|
|
|
Reader $reader, |
48
|
|
|
RouterInterface $router, |
49
|
|
|
ControllerResolverInterface $controllerResolver, |
50
|
|
|
FileLocatorInterface $fileLocator |
51
|
|
|
) { |
52
|
6 |
|
$this->reader = $reader; |
53
|
6 |
|
$this->router = $router; |
54
|
6 |
|
$this->controllerResolver = $controllerResolver; |
55
|
6 |
|
$this->fileLocator = $fileLocator; |
56
|
6 |
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @throws \LogicException If any of controllers can't be found by controller resolver |
60
|
|
|
* @throws \RuntimeException When any of defined schema files in ResponseSchemaValidator not exist |
61
|
|
|
*/ |
62
|
6 |
|
public function checkControllerResponseSchemaValidatorFiles(): void |
63
|
|
|
{ |
64
|
6 |
|
$corruptedFiles = []; |
65
|
|
|
|
66
|
6 |
|
foreach ($this->router->getRouteCollection()->all() as $route) { |
67
|
5 |
|
$controllerAttribute = $route->getDefault('_controller'); |
68
|
5 |
|
$resolvedController = $this->controllerResolver->getController(new Request( |
69
|
5 |
|
[], |
70
|
5 |
|
[], |
71
|
|
|
[ |
72
|
5 |
|
'_controller' => $controllerAttribute, |
73
|
|
|
] |
74
|
|
|
)); |
75
|
|
|
|
76
|
5 |
|
if (!\is_callable($resolvedController)) { |
77
|
|
|
continue; |
78
|
|
|
} |
79
|
|
|
|
80
|
5 |
|
$annotation = $this->getMethodAnnotationFromController($resolvedController, ResponseSchemaValidator::class); |
81
|
5 |
|
if (!$annotation instanceof ResponseSchemaValidator) { |
82
|
5 |
|
continue; |
83
|
|
|
} |
84
|
|
|
|
85
|
4 |
|
if ($checkError = $this->checkResponseSchema($annotation->getSchemas())) { |
86
|
|
|
if (!array_key_exists($routePath = $route->getPath(), $corruptedFiles)) { |
87
|
|
|
$corruptedFiles[$routePath] = []; |
88
|
|
|
} |
89
|
4 |
|
$corruptedFiles[$routePath][] = $checkError; |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
|
93
|
6 |
|
if ($corruptedFiles) { |
|
|
|
|
94
|
|
|
throw $this->createExceptionFromCorruptedFiles($corruptedFiles); |
95
|
|
|
} |
96
|
6 |
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @param array $schemas |
100
|
|
|
* @return null|string |
101
|
|
|
*/ |
102
|
4 |
|
protected function checkResponseSchema(array $schemas): ?string |
103
|
|
|
{ |
104
|
4 |
|
foreach ($schemas as $schema) { |
105
|
4 |
|
foreach ($schema as $schemaLocation) { |
106
|
|
|
try { |
107
|
4 |
|
$this->fileLocator->locate($schemaLocation); |
108
|
|
|
} catch (FileLocatorFileNotFoundException $e) { |
109
|
4 |
|
return $schemaLocation; |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
4 |
|
return null; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @param array $corruptedFiles |
119
|
|
|
* @return \RuntimeException |
120
|
|
|
*/ |
121
|
|
|
protected function createExceptionFromCorruptedFiles(array $corruptedFiles): \RuntimeException |
122
|
|
|
{ |
123
|
|
|
$routePaths = []; |
124
|
|
|
|
125
|
|
|
foreach ($corruptedFiles as $routePath => $files) { |
126
|
|
|
$routePaths[] = sprintf('%s[%s]', $routePath, implode(', ', $files)); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
return new \RuntimeException(sprintf('Non existing response schema files set: "%s"', implode(', ', $routePaths))); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* {@inheritdoc} |
134
|
|
|
*/ |
135
|
5 |
|
protected function getAnnotationReader(): Reader |
136
|
|
|
{ |
137
|
5 |
|
return $this->reader; |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.