Skip to content

Commit e6cea1f

Browse files
committed
test defaults parameters
1 parent 6edee72 commit e6cea1f

2 files changed

Lines changed: 244 additions & 0 deletions

File tree

src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
use ApiPlatform\Metadata\McpTool;
4848
use ApiPlatform\Metadata\NotExposed;
4949
use ApiPlatform\Metadata\OperationMutatorInterface;
50+
use ApiPlatform\Metadata\Parameter;
51+
use ApiPlatform\Metadata\Parameters;
5052
use ApiPlatform\Metadata\Patch;
5153
use ApiPlatform\Metadata\Post;
5254
use ApiPlatform\Metadata\Put;
@@ -439,9 +441,66 @@ private function normalizeDefaults(array $defaults): array
439441
$normalizedDefaults['extra_properties'][$option] = $value;
440442
}
441443

444+
if (isset($normalizedDefaults['parameters']) && \is_array($normalizedDefaults['parameters'])) {
445+
$normalizedDefaults['parameters'] = $this->normalizeParametersConfig($normalizedDefaults['parameters']);
446+
}
447+
442448
return $normalizedDefaults;
443449
}
444450

451+
private function normalizeParametersConfig(array $parametersConfig): Parameters|array
452+
{
453+
$parameters = [];
454+
$hasClassNames = false;
455+
456+
foreach ($parametersConfig as $key => $config) {
457+
if (class_exists($key) && is_subclass_of($key, Parameter::class)) {
458+
$hasClassNames = true;
459+
$parameterClass = $key;
460+
$parameterConfig = \is_array($config) ? $config : [];
461+
462+
try {
463+
$reflection = new \ReflectionClass($parameterClass);
464+
$constructor = $reflection->getConstructor();
465+
466+
if (null === $constructor) {
467+
continue;
468+
}
469+
470+
$args = [];
471+
foreach ($constructor->getParameters() as $param) {
472+
$paramName = $param->getName();
473+
if (isset($parameterConfig[$paramName])) {
474+
$args[$paramName] = $parameterConfig[$paramName];
475+
} elseif ($param->isDefaultValueAvailable()) {
476+
$args[$paramName] = $param->getDefaultValue();
477+
}
478+
}
479+
480+
$instance = $reflection->newInstance(...$args);
481+
482+
if (null !== $instance->getKey()) {
483+
$parameters[$instance->getKey()] = $instance;
484+
}
485+
} catch (\ReflectionException|\TypeError $e) {
486+
continue;
487+
}
488+
} else {
489+
$parameters[$key] = $config;
490+
}
491+
}
492+
493+
if ($hasClassNames || !empty($parameters)) {
494+
try {
495+
return new Parameters($parameters);
496+
} catch (\Throwable $e) {
497+
return $parameters;
498+
}
499+
}
500+
501+
return $parameters;
502+
}
503+
445504
private function registerMetadataConfiguration(ContainerBuilder $container, array $config, PhpFileLoader $loader): void
446505
{
447506
[$xmlResources, $yamlResources, $phpResources] = $this->getResourcesToWatch($container, $config);
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <dunglas@gmail.com>
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\Symfony\Tests\Bundle\DependencyInjection;
15+
16+
use ApiPlatform\Metadata\HeaderParameter;
17+
use ApiPlatform\Metadata\Parameters;
18+
// use ApiPlatform\Metadata\QueryParameter;
19+
use ApiPlatform\Symfony\Bundle\DependencyInjection\ApiPlatformExtension;
20+
use ApiPlatform\Tests\Fixtures\TestBundle\TestBundle;
21+
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
22+
use PHPUnit\Framework\TestCase;
23+
use Symfony\Bundle\SecurityBundle\SecurityBundle;
24+
use Symfony\Bundle\TwigBundle\TwigBundle;
25+
use Symfony\Component\DependencyInjection\ContainerBuilder;
26+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
27+
28+
/**
29+
* Test that parameters can be defined using Parameter class names as keys.
30+
*
31+
* Example:
32+
* ```yaml
33+
* defaults:
34+
* parameters:
35+
* 'ApiPlatform\Metadata\HeaderParameter':
36+
* key: 'X-Api-Version'
37+
* required: true
38+
* ```
39+
*/
40+
class ApiPlatformExtensionParameterClassNameTest extends TestCase
41+
{
42+
private ContainerBuilder $container;
43+
44+
protected function setUp(): void
45+
{
46+
$containerParameterBag = new ParameterBag([
47+
'kernel.bundles' => [
48+
'DoctrineBundle' => DoctrineBundle::class,
49+
'SecurityBundle' => SecurityBundle::class,
50+
'TwigBundle' => TwigBundle::class,
51+
],
52+
'kernel.bundles_metadata' => [
53+
'TestBundle' => [
54+
'parent' => null,
55+
'path' => realpath(__DIR__.'/../../../Fixtures/TestBundle'),
56+
'namespace' => TestBundle::class,
57+
],
58+
],
59+
'kernel.project_dir' => __DIR__.'/../../../Fixtures/app',
60+
'kernel.debug' => false,
61+
'kernel.environment' => 'test',
62+
]);
63+
64+
$this->container = new ContainerBuilder($containerParameterBag);
65+
}
66+
67+
public function testParametersWithClassNameAsKey(): void
68+
{
69+
$config = [
70+
'api_platform' => [
71+
'title' => 'Test API',
72+
'description' => 'Test Description',
73+
'version' => '1.0.0',
74+
'formats' => ['json' => ['mime_types' => ['application/json']]],
75+
'error_formats' => [],
76+
'patch_formats' => [],
77+
'defaults' => [
78+
'parameters' => [
79+
'ApiPlatform\Metadata\HeaderParameter' => [
80+
'key' => 'X-Api-Version',
81+
'required' => true,
82+
'description' => 'API Version',
83+
],
84+
// 'ApiPlatform\Metadata\QueryParameter' => [
85+
// 'key' => 'q',
86+
// 'description' => 'Search query',
87+
// ],
88+
],
89+
],
90+
],
91+
];
92+
93+
(new ApiPlatformExtension())->load($config, $this->container);
94+
95+
$defaults = $this->container->getParameter('api_platform.defaults');
96+
$this->assertArrayHasKey('parameters', $defaults);
97+
98+
/** @var Parameters $parameters */
99+
$parameters = $defaults['parameters'];
100+
$this->assertInstanceOf(Parameters::class, $parameters);
101+
102+
$paramArray = iterator_to_array($parameters);
103+
$this->assertNotEmpty($paramArray);
104+
105+
$this->assertArrayHasKey('X-Api-Version', $paramArray);
106+
$headerParam = $paramArray['X-Api-Version'];
107+
$this->assertInstanceOf(HeaderParameter::class, $headerParam);
108+
$this->assertTrue($headerParam->getRequired());
109+
110+
// $this->assertArrayHasKey('q', $paramArray);
111+
// $queryParam = $paramArray['q'];
112+
// $this->assertInstanceOf(QueryParameter::class, $queryParam);
113+
}
114+
115+
public function testMixedParameterDefinitions(): void
116+
{
117+
$config = [
118+
'api_platform' => [
119+
'title' => 'Test API',
120+
'description' => 'Test Description',
121+
'version' => '1.0.0',
122+
'formats' => ['json' => ['mime_types' => ['application/json']]],
123+
'error_formats' => [],
124+
'patch_formats' => [],
125+
'defaults' => [
126+
'parameters' => [
127+
'ApiPlatform\Metadata\HeaderParameter' => [
128+
'key' => 'X-Api-Version',
129+
'required' => true,
130+
],
131+
// 'ApiPlatform\Metadata\QueryParameter' => [
132+
// 'key' => 'q',
133+
// 'description' => 'Search query',
134+
// ],
135+
],
136+
],
137+
],
138+
];
139+
140+
(new ApiPlatformExtension())->load($config, $this->container);
141+
142+
$defaults = $this->container->getParameter('api_platform.defaults');
143+
/** @var Parameters $parameters */
144+
$parameters = $defaults['parameters'];
145+
146+
$paramArray = iterator_to_array($parameters);
147+
148+
$this->assertArrayHasKey('X-Api-Version', $paramArray);
149+
$this->assertInstanceOf(HeaderParameter::class, $paramArray['X-Api-Version']);
150+
151+
// $this->assertArrayHasKey('q', $paramArray);
152+
// $this->assertInstanceOf(QueryParameter::class, $paramArray['q']);
153+
}
154+
155+
public function testMultipleHeaderParameters(): void
156+
{
157+
$config = [
158+
'api_platform' => [
159+
'title' => 'Test API',
160+
'description' => 'Test Description',
161+
'version' => '1.0.0',
162+
'formats' => ['json' => ['mime_types' => ['application/json']]],
163+
'error_formats' => [],
164+
'patch_formats' => [],
165+
'defaults' => [
166+
'parameters' => [
167+
'ApiPlatform\Metadata\HeaderParameter' => [
168+
'key' => 'X-Api-Version',
169+
'required' => true,
170+
],
171+
],
172+
],
173+
],
174+
];
175+
176+
(new ApiPlatformExtension())->load($config, $this->container);
177+
178+
$defaults = $this->container->getParameter('api_platform.defaults');
179+
/** @var Parameters $parameters */
180+
$parameters = $defaults['parameters'];
181+
182+
$paramArray = iterator_to_array($parameters);
183+
$this->assertNotEmpty($paramArray);
184+
}
185+
}

0 commit comments

Comments
 (0)