This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | declare(strict_types = 1); |
||
3 | |||
4 | namespace Mikemirten\Bundle\JsonApiBundle\DependencyInjection; |
||
5 | |||
6 | use Symfony\Component\Config\FileLocator; |
||
7 | use Symfony\Component\Config\Loader\LoaderInterface; |
||
8 | use Symfony\Component\DependencyInjection\ChildDefinition; |
||
9 | use Symfony\Component\DependencyInjection\Definition; |
||
10 | use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; |
||
11 | use Symfony\Component\DependencyInjection\Reference; |
||
12 | use Symfony\Component\HttpKernel\DependencyInjection\Extension; |
||
13 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
||
14 | |||
15 | class JsonApiExtension extends Extension |
||
16 | { |
||
17 | const ALIAS = 'mrtn_json_api'; |
||
18 | |||
19 | /** |
||
20 | * Configuration loader |
||
21 | * |
||
22 | * @var LoaderInterface |
||
23 | */ |
||
24 | protected $loader; |
||
25 | |||
26 | /** |
||
27 | * JsonApiExtension constructor. |
||
28 | * |
||
29 | * @param LoaderInterface $loader |
||
30 | */ |
||
31 | 7 | public function __construct(LoaderInterface $loader = null) |
|
32 | { |
||
33 | 7 | $this->loader = $loader; |
|
34 | 7 | } |
|
35 | |||
36 | /** |
||
37 | * {@inheritdoc} |
||
38 | */ |
||
39 | 7 | public function load(array $configs, ContainerBuilder $container) |
|
40 | { |
||
41 | 7 | $configuration = new JsonApiConfiguration(); |
|
42 | 7 | $config = $this->processConfiguration($configuration, $configs); |
|
43 | |||
44 | 7 | $loader = $this->loader ?? new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); |
|
45 | |||
46 | 7 | $loader->load('services.yml'); |
|
47 | 7 | $loader->load('hydrator.yml'); |
|
48 | 7 | $loader->load('mapper.yml'); |
|
49 | 7 | $loader->load('http_client.yml'); |
|
50 | |||
51 | 7 | $this->handleMappingDefinitionProvider($container); |
|
52 | |||
53 | 7 | if (! empty($config['mappers'])) { |
|
54 | 6 | $this->createMappers($config['mappers'], $container); |
|
55 | } |
||
56 | |||
57 | 7 | if (! empty($config['resource_clients'])) { |
|
58 | 5 | $this->createResourceClients($config['resource_clients'], $container); |
|
59 | } |
||
60 | |||
61 | 7 | if (! empty($config['http_client'])) { |
|
62 | 1 | $this->processHttpClient($config['http_client'], $container); |
|
63 | } |
||
64 | 7 | } |
|
65 | |||
66 | /** |
||
67 | * Process http client |
||
68 | * |
||
69 | * @param array $config |
||
70 | * @param ContainerBuilder $container |
||
71 | */ |
||
72 | 1 | protected function processHttpClient(array $config, ContainerBuilder $container) |
|
73 | { |
||
74 | 1 | if (empty($config['guzzle_service'])) { |
|
75 | return; |
||
76 | } |
||
77 | |||
78 | 1 | if ($container->hasDefinition($config['guzzle_service'])) { |
|
79 | throw new \LogicException(sprintf('Service "%s" has not been defined.')); |
||
80 | } |
||
81 | |||
82 | 1 | $container->getDefinition('mrtn_json_api.http_client.adapter.guzzle') |
|
83 | 1 | ->setArguments([ |
|
84 | 1 | new Reference($config['guzzle_service']) |
|
85 | ]); |
||
86 | 1 | } |
|
87 | |||
88 | /** |
||
89 | * Handle mapping definition provider depends on environment |
||
90 | * |
||
91 | * @param ContainerBuilder $container |
||
92 | */ |
||
93 | 7 | protected function handleMappingDefinitionProvider(ContainerBuilder $container) |
|
94 | { |
||
95 | 7 | $env = $container->getParameter('kernel.environment'); |
|
96 | |||
97 | 7 | if ($env === 'prod') { |
|
98 | 4 | $container->setAlias( |
|
99 | 4 | 'mrtn_json_api.object_mapper.definition_provider', |
|
100 | 4 | 'mrtn_json_api.object_mapper.definition_provider.cached' |
|
101 | ); |
||
102 | |||
103 | 4 | return; |
|
104 | } |
||
105 | |||
106 | 3 | $container->setAlias( |
|
107 | 3 | 'mrtn_json_api.object_mapper.definition_provider', |
|
108 | 3 | 'mrtn_json_api.object_mapper.definition_provider.annotation' |
|
109 | ); |
||
110 | 3 | } |
|
111 | |||
112 | /** |
||
113 | * Create mappers |
||
114 | * |
||
115 | * @param array $config |
||
116 | * @param ContainerBuilder $container |
||
117 | */ |
||
118 | 6 | protected function createMappers(array $config, ContainerBuilder $container) |
|
119 | { |
||
120 | 6 | $handlers = $this->findMappingHandlers($container); |
|
121 | |||
122 | 6 | foreach ($config as $name => $mapperDefinition) |
|
123 | { |
||
124 | 6 | $mapper = new ChildDefinition('mrtn_json_api.object_mapper.abstract'); |
|
125 | 6 | $mapper->addTag('mrtn_json_api.object_mapper', ['alias' => $name]); |
|
126 | |||
127 | 6 | View Code Duplication | foreach ($mapperDefinition['handlers'] as $handlerName) |
0 ignored issues
–
show
|
|||
128 | { |
||
129 | 6 | if (! isset($handlers[$handlerName])) { |
|
130 | throw new \LogicException(sprintf('Mapping handler with name "%s" has not been registered as a service.', $handlerName)); |
||
131 | } |
||
132 | |||
133 | 6 | $mapper->addMethodCall('addHandler', [ |
|
134 | 6 | new Reference($handlers[$handlerName]) |
|
135 | ]); |
||
136 | } |
||
137 | |||
138 | 6 | $container->setDefinition('mrtn_json_api.object_mapper.' . $name, $mapper); |
|
139 | } |
||
140 | 6 | } |
|
141 | |||
142 | /** |
||
143 | * Find mapping handler registered in container |
||
144 | * |
||
145 | * @param ContainerBuilder $container |
||
146 | * @return array |
||
147 | */ |
||
148 | 6 | protected function findMappingHandlers(ContainerBuilder $container): array |
|
149 | { |
||
150 | 6 | $handlers = $container->findTaggedServiceIds('mrtn_json_api.object_mapper.handler'); |
|
151 | |||
152 | 6 | $found = []; |
|
153 | |||
154 | 6 | foreach ($handlers as $id => $tags) |
|
155 | { |
||
156 | 6 | foreach ($tags as $tag) |
|
157 | { |
||
158 | 6 | if (! isset($tag['alias'])) { |
|
159 | continue; |
||
160 | } |
||
161 | |||
162 | 6 | $found[$tag['alias']] = $id; |
|
163 | } |
||
164 | } |
||
165 | |||
166 | 6 | return $found; |
|
167 | } |
||
168 | |||
169 | /** |
||
170 | * Create resources-based clients |
||
171 | * |
||
172 | * @param array $config |
||
173 | * @param ContainerBuilder $container |
||
174 | */ |
||
175 | 5 | protected function createResourceClients(array $config, ContainerBuilder $container) |
|
176 | { |
||
177 | 5 | $repositoryClass = $container->getParameter('mrtn_json_api.route_repository.class'); |
|
178 | 5 | $clientClass = $container->getParameter('mrtn_json_api.resource_client.class'); |
|
179 | |||
180 | 5 | foreach ($config as $name => $definition) |
|
181 | { |
||
182 | 5 | $this->createEventDispatcherDecorator($container, $name); |
|
183 | |||
184 | 5 | $routes = $this->createRoutesDefinition($definition['resources']); |
|
185 | |||
186 | 5 | $repository = new Definition($repositoryClass, [$definition['base_url'], $routes]); |
|
187 | 5 | $repository->setPublic(false); |
|
188 | |||
189 | 5 | $client = new Definition($clientClass, [ |
|
190 | 5 | new Reference('mrtn_json_api.http_client.decorator.event_dispatcher.' . $name), |
|
191 | 5 | new Reference('mrtn_json_api.route_repository.' . $name) |
|
192 | ]); |
||
193 | |||
194 | 5 | $container->setDefinition('mrtn_json_api.route_repository.' . $name, $repository); |
|
195 | 5 | $container->setDefinition('mrtn_json_api.resource_client.' . $name, $client); |
|
196 | } |
||
197 | 5 | } |
|
198 | |||
199 | /** |
||
200 | * Create event dispatcher decorator for resource-based http-client |
||
201 | * |
||
202 | * @param ContainerBuilder $container |
||
203 | * @param string $name |
||
204 | */ |
||
205 | 5 | protected function createEventDispatcherDecorator(ContainerBuilder $container, string $name) |
|
206 | { |
||
207 | 5 | $class = $container->getParameter('mrtn_json_api.http_client.decorator.event_dispatcher.class'); |
|
208 | |||
209 | 5 | $decorator = new Definition($class, [ |
|
210 | 5 | new Reference('mrtn_json_api.http_client'), |
|
211 | 5 | new Reference('event_dispatcher'), |
|
212 | 5 | sprintf('mrtn_json_api.resource_client.%s.request', $name), |
|
213 | 5 | sprintf('mrtn_json_api.resource_client.%s.response', $name), |
|
214 | 5 | sprintf('mrtn_json_api.resource_client.%s.exception', $name) |
|
215 | ]); |
||
216 | |||
217 | 5 | $decorator->setPublic(false); |
|
218 | |||
219 | 5 | $container->setDefinition('mrtn_json_api.http_client.decorator.event_dispatcher.' . $name, $decorator); |
|
220 | 5 | } |
|
221 | |||
222 | /** |
||
223 | * Create definition of routes for a route repository by a collection of endpoints |
||
224 | * |
||
225 | * @param array $resources |
||
226 | * @return array |
||
227 | */ |
||
228 | 5 | protected function createRoutesDefinition(array $resources): array |
|
229 | { |
||
230 | 5 | $definition = []; |
|
231 | |||
232 | 5 | foreach ($resources as $name => $resource) |
|
233 | { |
||
234 | 5 | $methods = array_keys($resource['methods']); |
|
235 | 5 | $methods = array_map('strtoupper', $methods); |
|
236 | |||
237 | 5 | $definition[$name] = [ |
|
238 | 5 | 'path' => trim($resource['path']), |
|
239 | 5 | 'methods' => array_map('trim', $methods) |
|
240 | ]; |
||
241 | } |
||
242 | |||
243 | 5 | return $definition; |
|
244 | } |
||
245 | |||
246 | /** |
||
247 | * {@inheritdoc} |
||
248 | */ |
||
249 | 5 | public function getAlias() |
|
250 | { |
||
251 | 5 | return self::ALIAS; |
|
252 | } |
||
253 | } |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.