Skip to content

Commit 4c58b33

Browse files
nightioRobert
and
Robert
authored
fix(jsonapi): fixed definition name to allow using the same class names in different namespaces (#6676)
Co-authored-by: Robert <[email protected]>
1 parent 0273d23 commit 4c58b33

File tree

5 files changed

+103
-3
lines changed

5 files changed

+103
-3
lines changed

src/JsonSchema/DefinitionNameFactory.php

+24-3
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
}

tests/JsonSchema/DefinitionNameFactoryTest.php

+25
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
}
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+
}
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+
}
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)