Skip to content

Commit

Permalink
fix(jsonapi): fixed definition name to allow using the same class nam…
Browse files Browse the repository at this point in the history
…es in different namespaces
  • Loading branch information
Robert committed Sep 26, 2024
1 parent 0273d23 commit 1302834
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 3 deletions.
27 changes: 24 additions & 3 deletions src/JsonSchema/DefinitionNameFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ final class DefinitionNameFactory implements DefinitionNameFactoryInterface
{
use ResourceClassInfoTrait;

private const GLUE = '.';
private array $prefixCache = [];

public function __construct(private ?array $distinctFormats)
{
}
Expand All @@ -32,18 +35,18 @@ public function create(string $className, string $format = 'json', ?string $inpu
}

if (!isset($prefix)) {
$prefix = (new \ReflectionClass($className))->getShortName();
$prefix = $this->createPrefixFromClass($className);
}

if (null !== $inputOrOutputClass && $className !== $inputOrOutputClass) {
$parts = explode('\\', $inputOrOutputClass);
$shortName = end($parts);
$prefix .= '.'.$shortName;
$prefix .= self::GLUE.$shortName;
}

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

$definitionName = $serializerContext[SchemaFactory::OPENAPI_DEFINITION_NAME] ?? null;
Expand All @@ -61,4 +64,22 @@ private function encodeDefinitionName(string $name): string
{
return preg_replace('/[^a-zA-Z0-9.\-_]/', '.', $name);
}

private function createPrefixFromClass(string $fullyQualifiedClassName, int $namespaceParts = 1): string
{
$parts = explode('\\', $fullyQualifiedClassName);
$name = implode(self::GLUE, \array_slice($parts, -$namespaceParts));

if (!isset($this->prefixCache[$name])) {
$this->prefixCache[$name] = $fullyQualifiedClassName;

return $name;
}

if ($this->prefixCache[$name] !== $fullyQualifiedClassName) {
$name = $this->createPrefixFromClass($fullyQualifiedClassName, ++$namespaceParts);
}

return $name;
}
}
25 changes: 25 additions & 0 deletions tests/JsonSchema/DefinitionNameFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,29 @@ public function testCreate(string $expected, string $className, string $format =

static::assertSame($expected, $definitionNameFactory->create($className, $format, $inputOrOutputClass, $operation, $serializerContext));
}

public function testCreateDifferentPrefixesForClassesWithTheSameShortName(): void
{
$definitionNameFactory = new DefinitionNameFactory(['jsonapi' => true, 'jsonhal' => true]);

self::assertEquals(
'DummyClass.jsonapi',
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceA\Module\DummyClass::class, 'jsonapi')
);

self::assertEquals(
'Module.DummyClass.jsonapi',
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceB\Module\DummyClass::class, 'jsonapi')
);

self::assertEquals(
'NamespaceC.Module.DummyClass.jsonapi',
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceC\Module\DummyClass::class, 'jsonapi')
);

self::assertEquals(
'DummyClass.jsonhal',
$definitionNameFactory->create(\ApiPlatform\Tests\JsonSchema\Dummy\NamespaceA\Module\DummyClass::class, 'jsonhal')
);
}
}
18 changes: 18 additions & 0 deletions tests/JsonSchema/Dummy/NamespaceA/Module/DummyClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\JsonSchema\Dummy\NamespaceA\Module;

class DummyClass
{
}
18 changes: 18 additions & 0 deletions tests/JsonSchema/Dummy/NamespaceB/Module/DummyClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\JsonSchema\Dummy\NamespaceB\Module;

class DummyClass
{
}
18 changes: 18 additions & 0 deletions tests/JsonSchema/Dummy/NamespaceC/Module/DummyClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Tests\JsonSchema\Dummy\NamespaceC\Module;

class DummyClass
{
}

0 comments on commit 1302834

Please sign in to comment.