Skip to content

Commit 5a5ec1a

Browse files
committed
Merge 3.4
2 parents 13b0c1e + 82474a9 commit 5a5ec1a

File tree

7 files changed

+113
-4
lines changed

7 files changed

+113
-4
lines changed

src/JsonSchema/DefinitionNameFactory.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ final class DefinitionNameFactory implements DefinitionNameFactoryInterface
2121
{
2222
use ResourceClassInfoTrait;
2323

24+
private const GLUE = '.';
25+
private array $prefixCache = [];
26+
2427
public function __construct(private ?array $distinctFormats)
2528
{
2629
}
@@ -32,18 +35,18 @@ public function create(string $className, string $format = 'json', ?string $inpu
3235
}
3336

3437
if (!isset($prefix)) {
35-
$prefix = (new \ReflectionClass($className))->getShortName();
38+
$prefix = $this->createPrefixFromClass($className);
3639
}
3740

3841
if (null !== $inputOrOutputClass && $className !== $inputOrOutputClass) {
3942
$parts = explode('\\', $inputOrOutputClass);
4043
$shortName = end($parts);
41-
$prefix .= '.'.$shortName;
44+
$prefix .= self::GLUE.$shortName;
4245
}
4346

4447
if ('json' !== $format && ($this->distinctFormats[$format] ?? false)) {
4548
// JSON is the default, and so isn't included in the definition name
46-
$prefix .= '.'.$format;
49+
$prefix .= self::GLUE.$format;
4750
}
4851

4952
$definitionName = $serializerContext[SchemaFactory::OPENAPI_DEFINITION_NAME] ?? null;
@@ -61,4 +64,22 @@ private function encodeDefinitionName(string $name): string
6164
{
6265
return preg_replace('/[^a-zA-Z0-9.\-_]/', '.', $name);
6366
}
67+
68+
private function createPrefixFromClass(string $fullyQualifiedClassName, int $namespaceParts = 1): string
69+
{
70+
$parts = explode('\\', $fullyQualifiedClassName);
71+
$name = implode(self::GLUE, \array_slice($parts, -$namespaceParts));
72+
73+
if (!isset($this->prefixCache[$name])) {
74+
$this->prefixCache[$name] = $fullyQualifiedClassName;
75+
76+
return $name;
77+
}
78+
79+
if ($this->prefixCache[$name] !== $fullyQualifiedClassName) {
80+
$name = $this->createPrefixFromClass($fullyQualifiedClassName, ++$namespaceParts);
81+
}
82+
83+
return $name;
84+
}
6485
}

src/State/Provider/ParameterProvider.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
5252
$context = ['operation' => $operation] + $context;
5353
$parameters = $operation->getParameters();
5454
foreach ($parameters ?? [] as $parameter) {
55+
$extraProperties = $parameter->getExtraProperties();
56+
unset($extraProperties['_api_values']);
57+
$parameters->add($parameter->getKey(), $parameter = $parameter->withExtraProperties($extraProperties));
58+
5559
$values = $this->getParameterValues($parameter, $request, $context);
5660
$value = $this->extractParameterValues($parameter, $values);
5761

src/State/Tests/ParameterProviderTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use ApiPlatform\Metadata\Parameter;
1919
use ApiPlatform\Metadata\Parameters;
2020
use ApiPlatform\Metadata\QueryParameter;
21+
use ApiPlatform\State\ParameterNotFound;
2122
use ApiPlatform\State\ParameterProviderInterface;
2223
use ApiPlatform\State\Provider\ParameterProvider;
2324
use PHPUnit\Framework\TestCase;
@@ -51,16 +52,20 @@ public function has(string $id): bool
5152
'order' => new QueryParameter(key: 'order', provider: 'test'),
5253
'search[:property]' => new QueryParameter(key: 'search[:property]', provider: [self::class, 'provide']),
5354
'foo' => new QueryParameter(key: 'foo', provider: [self::class, 'shouldNotBeCalled']),
55+
'baz' => (new QueryParameter(key: 'baz'))->withExtraProperties(['_api_values' => 'test1']),
56+
'fas' => (new QueryParameter(key: 'fas'))->withExtraProperties(['_api_values' => '42']),
5457
]));
5558
$parameterProvider = new ParameterProvider(null, $locator);
56-
$request = new Request(server: ['QUERY_STRING' => 'order[foo]=asc&search[a]=bar']);
59+
$request = new Request(server: ['QUERY_STRING' => 'order[foo]=asc&search[a]=bar&baz=t42']);
5760
$context = ['request' => $request, 'operation' => $operation];
5861
$parameterProvider->provide($operation, [], $context);
5962
$operation = $request->attributes->get('_api_operation');
6063

6164
$this->assertEquals('ok', $operation->getName());
6265
$this->assertEquals(['foo' => 'asc'], $operation->getParameters()->get('order', QueryParameter::class)->getValue());
6366
$this->assertEquals(['a' => 'bar'], $operation->getParameters()->get('search[:property]', QueryParameter::class)->getValue());
67+
$this->assertEquals('t42', $operation->getParameters()->get('baz', QueryParameter::class)->getValue());
68+
$this->assertEquals(new ParameterNotFound(), $operation->getParameters()->get('fas', QueryParameter::class)->getValue());
6469
}
6570

6671
public static function provide(): void

tests/JsonSchema/DefinitionNameFactoryTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,29 @@ public function testCreate(string $expected, string $className, string $format =
6969

7070
static::assertSame($expected, $definitionNameFactory->create($className, $format, $inputOrOutputClass, $operation, $serializerContext));
7171
}
72+
73+
public function testCreateDifferentPrefixesForClassesWithTheSameShortName(): void
74+
{
75+
$definitionNameFactory = new DefinitionNameFactory(['jsonapi' => true, 'jsonhal' => true]);
76+
77+
self::assertEquals(
78+
'DummyClass.jsonapi',
79+
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceA\Module\DummyClass::class, 'jsonapi')
80+
);
81+
82+
self::assertEquals(
83+
'Module.DummyClass.jsonapi',
84+
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceB\Module\DummyClass::class, 'jsonapi')
85+
);
86+
87+
self::assertEquals(
88+
'NamespaceC.Module.DummyClass.jsonapi',
89+
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceC\Module\DummyClass::class, 'jsonapi')
90+
);
91+
92+
self::assertEquals(
93+
'DummyClass.jsonhal',
94+
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceA\Module\DummyClass::class, 'jsonhal')
95+
);
96+
}
7297
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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\Tests\JsonSchema\Dummy\NamespaceA\Module;
15+
16+
class DummyClass
17+
{
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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\Tests\JsonSchema\Dummy\NamespaceB\Module;
15+
16+
class DummyClass
17+
{
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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\Tests\JsonSchema\Dummy\NamespaceC\Module;
15+
16+
class DummyClass
17+
{
18+
}

0 commit comments

Comments
 (0)