Skip to content

Commit c2824c1

Browse files
authored
fix(jsonschema): restore type factory usage (#5897)
fixes #5896
1 parent 3d0dfc1 commit c2824c1

File tree

10 files changed

+118
-5
lines changed

10 files changed

+118
-5
lines changed

phpstan.neon.dist

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ parameters:
2626
- src/Symfony/Bundle/DependencyInjection/Configuration.php
2727
# Templates for Maker
2828
- src/Symfony/Maker/Resources/skeleton
29-
- src/*/vendor
29+
- **vendor**
3030
earlyTerminatingMethodCalls:
3131
PHPUnit\Framework\Constraint\Constraint:
3232
- fail

src/JsonSchema/SchemaFactory.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ final class SchemaFactory implements SchemaFactoryInterface
3737
{
3838
use ResourceClassInfoTrait;
3939
private array $distinctFormats = [];
40-
40+
private ?TypeFactoryInterface $typeFactory = null;
4141
// Edge case where the related resource is not readable (for example: NotExposed) but we have groups to read the whole related object
4242
public const FORCE_SUBSCHEMA = '_api_subschema_force_readable_link';
4343
public const OPENAPI_DEFINITION_NAME = 'openapi_definition_name';
4444

4545
public function __construct(?TypeFactoryInterface $typeFactory, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly ?NameConverterInterface $nameConverter = null, ResourceClassResolverInterface $resourceClassResolver = null)
4646
{
4747
if ($typeFactory) {
48-
trigger_deprecation('api-platform/core', '3.2', sprintf('The "%s" is not needed anymore and will not be used anymore.', TypeFactoryInterface::class));
48+
$this->typeFactory = $typeFactory;
4949
}
5050

5151
$this->resourceMetadataFactory = $resourceMetadataFactory;
@@ -198,6 +198,12 @@ private function buildPropertySchema(Schema $schema, string $definitionName, str
198198
$subSchema->setDefinitions($schema->getDefinitions()); // Populate definitions of the main schema
199199

200200
foreach ($types as $type) {
201+
// TODO: in 3.3 add trigger_deprecation() as type factories are not used anymore, we moved this logic to SchemaPropertyMetadataFactory so that it gets cached
202+
if ($typeFromFactory = $this->typeFactory?->getType($type, 'jsonschema', $propertyMetadata->isReadableLink(), $serializerContext)) {
203+
$propertySchema = $typeFromFactory;
204+
break;
205+
}
206+
201207
$isCollection = $type->isCollection();
202208
if ($isCollection) {
203209
$valueType = $type->getCollectionValueTypes()[0] ?? null;

src/JsonSchema/TypeFactory.php

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
/**
2424
* {@inheritdoc}
2525
*
26+
* @deprecated since 3.3 https://github.com/api-platform/core/pull/5470
27+
*
2628
* @author Kévin Dunglas <[email protected]>
2729
*/
2830
final class TypeFactory implements TypeFactoryInterface
@@ -46,6 +48,11 @@ public function setSchemaFactory(SchemaFactoryInterface $schemaFactory): void
4648
*/
4749
public function getType(Type $type, string $format = 'json', bool $readableLink = null, array $serializerContext = null, Schema $schema = null): array
4850
{
51+
if ('jsonschema' === $format) {
52+
return [];
53+
}
54+
55+
// TODO: OpenApiFactory uses this to compute filter types
4956
if ($type->isCollection()) {
5057
$keyType = $type->getCollectionKeyTypes()[0] ?? null;
5158
$subType = ($type->getCollectionValueTypes()[0] ?? null) ?? new Type($type->getBuiltinType(), false, $type->getClassName(), false);

src/OpenApi/Factory/OpenApiFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ private function getFiltersParameters(CollectionOperationInterface|HttpOperation
573573
}
574574

575575
foreach ($filter->getDescription($entityClass) as $name => $data) {
576-
$schema = $data['schema'] ?? (\in_array($data['type'], Type::$builtinTypes, true) ? $this->jsonSchemaTypeFactory->getType(new Type($data['type'], false, null, $data['is_collection'] ?? false)) : ['type' => 'string']);
576+
$schema = $data['schema'] ?? (\in_array($data['type'], Type::$builtinTypes, true) ? $this->jsonSchemaTypeFactory->getType(new Type($data['type'], false, null, $data['is_collection'] ?? false), 'openapi') : ['type' => 'string']);
577577

578578
$parameters[] = new Parameter(
579579
$name,

src/Symfony/Bundle/Resources/config/json_schema.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<service id="ApiPlatform\JsonSchema\TypeFactoryInterface" alias="api_platform.json_schema.type_factory" />
1717

1818
<service id="api_platform.json_schema.schema_factory" class="ApiPlatform\JsonSchema\SchemaFactory">
19-
<argument>null</argument>
19+
<argument type="service" id="api_platform.json_schema.type_factory" on-invalid="ignore"></argument>
2020
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
2121
<argument type="service" id="api_platform.metadata.property.name_collection_factory" />
2222
<argument type="service" id="api_platform.metadata.property.metadata_factory" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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\Fixtures\TestBundle\ApiResource\Issue5896;
15+
16+
use ApiPlatform\Metadata\ApiProperty;
17+
use ApiPlatform\Metadata\Get;
18+
19+
#[Get]
20+
class Foo
21+
{
22+
#[ApiProperty(readable: false, writable: false, identifier: true)]
23+
public ?int $id = null;
24+
public ?LocalDate $expiration;
25+
}
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\Fixtures\TestBundle\ApiResource\Issue5896;
15+
16+
class LocalDate
17+
{
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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\Fixtures\TestBundle\ApiResource\Issue5896;
15+
16+
use ApiPlatform\JsonSchema\Schema;
17+
use ApiPlatform\JsonSchema\TypeFactoryInterface;
18+
use Symfony\Component\PropertyInfo\Type;
19+
20+
class TypeFactoryDecorator implements TypeFactoryInterface
21+
{
22+
public function __construct(
23+
private readonly TypeFactoryInterface $decorated,
24+
) {
25+
}
26+
27+
public function getType(Type $type, string $format = 'json', bool $readableLink = null, array $serializerContext = null, Schema $schema = null): array
28+
{
29+
if (is_a($type->getClassName(), LocalDate::class, true)) {
30+
return [
31+
'type' => 'string',
32+
'format' => 'date',
33+
];
34+
}
35+
36+
return $this->decorated->getType($type, $format, $readableLink, $serializerContext, $schema);
37+
}
38+
}

tests/Fixtures/app/config/config_common.yml

+5
Original file line numberDiff line numberDiff line change
@@ -457,3 +457,8 @@ services:
457457
ApiPlatform\Tests\Fixtures\TestBundle\State\ODMLinkHandledDummyLinksHandler:
458458
tags:
459459
- {name: 'api_platform.doctrine.odm.links_handler'}
460+
461+
ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5896\TypeFactoryDecorator:
462+
decorates: 'api_platform.json_schema.type_factory'
463+
arguments:
464+
$decorated: '@.inner'

tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php

+14
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,18 @@ public function testArraySchemaWithReference(): void
124124
'$ref' => '#/definitions/TestEntity.jsonld-write',
125125
]);
126126
}
127+
128+
/**
129+
* TODO: add deprecation (TypeFactory will be deprecated in api platform 3.3).
130+
*
131+
* @group legacy
132+
*/
133+
public function testArraySchemaWithTypeFactory(): void
134+
{
135+
$this->tester->run(['command' => 'api:json-schema:generate', 'resource' => 'ApiPlatform\Tests\Fixtures\TestBundle\ApiResource\Issue5896\Foo', '--type' => 'output']);
136+
$result = $this->tester->getDisplay();
137+
$json = json_decode($result, associative: true);
138+
139+
$this->assertEquals($json['definitions']['Foo.jsonld']['properties']['expiration'], ['type' => 'string', 'format' => 'date']);
140+
}
127141
}

0 commit comments

Comments
 (0)