Skip to content

Commit

Permalink
Merge pull request #3425 from remoteclient/patch-3
Browse files Browse the repository at this point in the history
Pass $options to PropertyInfoMetadataFactory
  • Loading branch information
teohhanhui committed Mar 5, 2020
2 parents 6578c8b + d26a503 commit 7e1e5ba
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 224 deletions.
32 changes: 30 additions & 2 deletions src/JsonSchema/SchemaFactory.php
Expand Up @@ -131,9 +131,9 @@ public function buildSchema(string $className, string $format = 'json', string $
$definition['externalDocs'] = ['url' => $iri];
}

$options = isset($serializerContext[AbstractNormalizer::GROUPS]) ? ['serializer_groups' => (array) $serializerContext[AbstractNormalizer::GROUPS]] : [];
$options = $this->getFactoryOptions($serializerContext, $operationType, $operationName);
foreach ($this->propertyNameCollectionFactory->create($inputOrOutputClass, $options) as $propertyName) {
$propertyMetadata = $this->propertyMetadataFactory->create($inputOrOutputClass, $propertyName);
$propertyMetadata = $this->propertyMetadataFactory->create($inputOrOutputClass, $propertyName, $options);
if (!$propertyMetadata->isReadable() && !$propertyMetadata->isWritable()) {
continue;
}
Expand Down Expand Up @@ -273,4 +273,32 @@ private function getSerializerContext(ResourceMetadata $resourceMetadata, string

return $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, $attribute, [], true);
}

/**
* Gets the options for the property name collection / property metadata factories.
*/
private function getFactoryOptions(array $serializerContext, ?string $operationType, ?string $operationName): array
{
$options = [];

if (isset($serializerContext[AbstractNormalizer::GROUPS])) {
/* @see https://github.com/symfony/symfony/blob/v4.2.6/src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php */
$options['serializer_groups'] = (array) $serializerContext[AbstractNormalizer::GROUPS];
}

if (null !== $operationType && null !== $operationName) {
switch ($operationType) {
case OperationType::COLLECTION:
$options['collection_operation_name'] = $operationName;
break;
case OperationType::ITEM:
$options['item_operation_name'] = $operationName;
break;
default:
break;
}
}

return $options;
}
}
67 changes: 67 additions & 0 deletions tests/JsonSchema/SchemaFactoryTest.php
Expand Up @@ -13,15 +13,19 @@

namespace ApiPlatform\Core\Tests\JsonSchema;

use ApiPlatform\Core\Api\OperationType;
use ApiPlatform\Core\Api\ResourceClassResolverInterface;
use ApiPlatform\Core\JsonSchema\Schema;
use ApiPlatform\Core\JsonSchema\SchemaFactory;
use ApiPlatform\Core\JsonSchema\TypeFactoryInterface;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
use ApiPlatform\Core\Metadata\Property\PropertyNameCollection;
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
use ApiPlatform\Core\Tests\Fixtures\NotAResource;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\OverriddenOperationDummy;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Symfony\Component\PropertyInfo\Type;
Expand Down Expand Up @@ -74,4 +78,67 @@ public function testBuildSchemaForNonResourceClass(): void
$this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['bar']);
$this->assertSame('integer', $definitions[$rootDefinitionKey]['properties']['bar']['type']);
}

public function testBuildSchemaForOperationWithOverriddenSerializerGroups(): void
{
$typeFactoryProphecy = $this->prophesize(TypeFactoryInterface::class);
$typeFactoryProphecy->getType(Argument::allOf(
Argument::type(Type::class),
Argument::which('getBuiltinType', Type::BUILTIN_TYPE_STRING)
), Argument::cetera())->willReturn([
'type' => 'string',
]);

$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
$resourceMetadataFactoryProphecy->create(OverriddenOperationDummy::class)->willReturn(new ResourceMetadata((new \ReflectionClass(OverriddenOperationDummy::class))->getShortName(), null, null, [
'put' => [
'normalization_context' => [
'groups' => 'overridden_operation_dummy_put',
],
],
], [], [
'normalization_context' => [
'groups' => 'overridden_operation_dummy_read',
],
]));

$serializerGroup = 'overridden_operation_dummy_put';

$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
$propertyNameCollectionFactoryProphecy->create(OverriddenOperationDummy::class, Argument::allOf(
Argument::type('array'),
Argument::withEntry('serializer_groups', [$serializerGroup])
))->willReturn(new PropertyNameCollection(['alias', 'description']));

$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
$propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'alias', Argument::allOf(
Argument::type('array'),
Argument::withEntry('serializer_groups', [$serializerGroup])
))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true));
$propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'description', Argument::allOf(
Argument::type('array'),
Argument::withEntry('serializer_groups', [$serializerGroup])
))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true));

$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
$resourceClassResolverProphecy->isResourceClass(OverriddenOperationDummy::class)->willReturn(true);

$schemaFactory = new SchemaFactory($typeFactoryProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), null, $resourceClassResolverProphecy->reveal());
$resultSchema = $schemaFactory->buildSchema(OverriddenOperationDummy::class, 'json', Schema::TYPE_OUTPUT, OperationType::ITEM, 'put');

$rootDefinitionKey = $resultSchema->getRootDefinitionKey();
$definitions = $resultSchema->getDefinitions();

$this->assertSame((new \ReflectionClass(OverriddenOperationDummy::class))->getShortName().'-'.$serializerGroup, $rootDefinitionKey);
$this->assertArrayHasKey($rootDefinitionKey, $definitions);
$this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]);
$this->assertSame('object', $definitions[$rootDefinitionKey]['type']);
$this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
$this->assertArrayHasKey('alias', $definitions[$rootDefinitionKey]['properties']);
$this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['alias']);
$this->assertSame('string', $definitions[$rootDefinitionKey]['properties']['alias']['type']);
$this->assertArrayHasKey('description', $definitions[$rootDefinitionKey]['properties']);
$this->assertArrayHasKey('type', $definitions[$rootDefinitionKey]['properties']['description']);
$this->assertSame('string', $definitions[$rootDefinitionKey]['properties']['description']['type']);
}
}

0 comments on commit 7e1e5ba

Please sign in to comment.