Skip to content

Commit 8396bdf

Browse files
author
abluchet
committed
Merge remote-tracking branch 'upstream/2.2' into merge-2.2
2 parents c304b11 + c99a148 commit 8396bdf

File tree

18 files changed

+206
-69
lines changed

18 files changed

+206
-69
lines changed

src/Bridge/Symfony/Bundle/Resources/config/api.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@
5858
<argument type="service" id="api_platform.router" />
5959
<argument type="service" id="api_platform.property_accessor" />
6060
<argument type="service" id="api_platform.identifiers_extractor.cached" />
61-
<argument type="service" id="api_platform.identifier.denormalizer" />
62-
<argument type="service" id="api_platform.subresource_data_provider" />
61+
<argument type="service" id="api_platform.subresource_data_provider" on-invalid="ignore" />
62+
<argument type="service" id="api_platform.identifier.denormalizer" on-invalid="ignore" />
6363
</service>
6464
<service id="ApiPlatform\Core\Api\IriConverterInterface" alias="api_platform.iri_converter" />
6565

src/Bridge/Symfony/Bundle/Resources/config/hydra.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<argument type="service" id="api_platform.operation_method_resolver" />
1414
<argument type="service" id="api_platform.router" />
1515
<argument type="service" id="api_platform.subresource_operation_factory" />
16+
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
1617

1718
<tag name="serializer.normalizer" priority="32" />
1819
</service>

src/Bridge/Symfony/Routing/IriConverter.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ final class IriConverter implements IriConverterInterface
4949
private $router;
5050
private $identifiersExtractor;
5151

52-
public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ItemDataProviderInterface $itemDataProvider, RouteNameResolverInterface $routeNameResolver, RouterInterface $router, PropertyAccessorInterface $propertyAccessor = null, IdentifiersExtractorInterface $identifiersExtractor = null, ChainIdentifierDenormalizer $identifierDenormalizer = null, SubresourceDataProviderInterface $subresourceDataProvider = null)
52+
public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ItemDataProviderInterface $itemDataProvider, RouteNameResolverInterface $routeNameResolver, RouterInterface $router, PropertyAccessorInterface $propertyAccessor = null, IdentifiersExtractorInterface $identifiersExtractor = null, SubresourceDataProviderInterface $subresourceDataProvider = null, ChainIdentifierDenormalizer $identifierDenormalizer = null)
5353
{
5454
$this->itemDataProvider = $itemDataProvider;
5555
$this->routeNameResolver = $routeNameResolver;
5656
$this->router = $router;
5757
$this->identifiersExtractor = $identifiersExtractor;
58-
$this->identifierDenormalizer = $identifierDenormalizer;
5958
$this->subresourceDataProvider = $subresourceDataProvider;
59+
$this->identifierDenormalizer = $identifierDenormalizer;
6060

6161
if (null === $identifiersExtractor) {
6262
@trigger_error(sprintf('Not injecting "%s" is deprecated since API Platform 2.1 and will not be possible anymore in API Platform 3', IdentifiersExtractorInterface::class), E_USER_DEPRECATED);
@@ -81,16 +81,16 @@ public function getItemFromIri(string $iri, array $context = [])
8181

8282
$attributes = AttributesExtractor::extractAttributes($parameters);
8383

84+
if ($this->identifierDenormalizer) {
85+
$context[ChainIdentifierDenormalizer::HAS_IDENTIFIER_DENORMALIZER] = true;
86+
}
87+
8488
try {
8589
$identifiers = $this->extractIdentifiers($parameters, $attributes);
8690
} catch (InvalidIdentifierException $e) {
8791
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
8892
}
8993

90-
if ($this->identifierDenormalizer) {
91-
$context[ChainIdentifierDenormalizer::HAS_IDENTIFIER_DENORMALIZER] = true;
92-
}
93-
9494
if (isset($attributes['subresource_operation_name'])) {
9595
if ($item = $this->getSubresourceData($identifiers, $attributes, $context)) {
9696
return $item;

src/DataProvider/OperationDataProviderTrait.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace ApiPlatform\Core\DataProvider;
1515

1616
use ApiPlatform\Core\Exception\InvalidIdentifierException;
17+
use ApiPlatform\Core\Exception\PropertyNotFoundException;
1718
use ApiPlatform\Core\Exception\RuntimeException;
1819
use ApiPlatform\Core\Identifier\Normalizer\ChainIdentifierDenormalizer;
1920

@@ -61,7 +62,11 @@ private function getCollectionData(array $attributes, array $context)
6162
*/
6263
private function getItemData($identifiers, array $attributes, array $context)
6364
{
64-
return $this->itemDataProvider->getItem($attributes['resource_class'], $identifiers, $attributes['item_operation_name'], $context);
65+
try {
66+
return $this->itemDataProvider->getItem($attributes['resource_class'], $identifiers, $attributes['item_operation_name'], $context);
67+
} catch (PropertyNotFoundException $e) {
68+
return null;
69+
}
6570
}
6671

6772
/**

src/GraphQl/Serializer/ItemNormalizer.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
namespace ApiPlatform\Core\GraphQl\Serializer;
2323

2424
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
25-
use ApiPlatform\Core\Serializer\AbstractItemNormalizer;
2625
use ApiPlatform\Core\Serializer\ItemNormalizer as BaseItemNormalizer;
2726

2827
/**
@@ -48,7 +47,7 @@ public function supportsNormalization($data, $format = null)
4847
*/
4948
public function normalize($object, $format = null, array $context = [])
5049
{
51-
$data = AbstractItemNormalizer::normalize($object, $format, $context);
50+
$data = parent::normalize($object, $format, $context);
5251
$data[self::ITEM_KEY] = serialize($object); // calling serialize prevent weird normalization process done by Webonyx's GraphQL PHP
5352

5453
return $data;

src/Hal/Serializer/ItemNormalizer.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,24 +174,29 @@ private function populateRelation(array $data, $object, string $format = null, a
174174
continue;
175175
}
176176

177+
$relationName = $relation['name'];
178+
if ($this->nameConverter) {
179+
$relationName = $this->nameConverter->normalize($relationName);
180+
}
181+
177182
if ('one' === $relation['cardinality']) {
178183
if ('links' === $type) {
179-
$data[$key][$relation['name']]['href'] = $this->getRelationIri($attributeValue);
184+
$data[$key][$relationName]['href'] = $this->getRelationIri($attributeValue);
180185
continue;
181186
}
182187

183-
$data[$key][$relation['name']] = $attributeValue;
188+
$data[$key][$relationName] = $attributeValue;
184189
continue;
185190
}
186191

187192
// many
188-
$data[$key][$relation['name']] = [];
193+
$data[$key][$relationName] = [];
189194
foreach ($attributeValue as $rel) {
190195
if ('links' === $type) {
191196
$rel = ['href' => $this->getRelationIri($rel)];
192197
}
193198

194-
$data[$key][$relation['name']][] = $rel;
199+
$data[$key][$relationName][] = $rel;
195200
}
196201
}
197202

src/Hydra/Serializer/DocumentationNormalizer.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
2828
use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface;
2929
use Symfony\Component\PropertyInfo\Type;
30+
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
3031
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
3132
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
3233

@@ -46,8 +47,9 @@ final class DocumentationNormalizer implements NormalizerInterface
4647
private $operationMethodResolver;
4748
private $urlGenerator;
4849
private $subresourceOperationFactory;
50+
private $nameConverter;
4951

50-
public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver, UrlGeneratorInterface $urlGenerator, SubresourceOperationFactoryInterface $subresourceOperationFactory = null)
52+
public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver, UrlGeneratorInterface $urlGenerator, SubresourceOperationFactoryInterface $subresourceOperationFactory = null, NameConverterInterface $nameConverter = null)
5153
{
5254
$this->resourceMetadataFactory = $resourceMetadataFactory;
5355
$this->propertyNameCollectionFactory = $propertyNameCollectionFactory;
@@ -56,6 +58,7 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa
5658
$this->operationMethodResolver = $operationMethodResolver;
5759
$this->urlGenerator = $urlGenerator;
5860
$this->subresourceOperationFactory = $subresourceOperationFactory;
61+
$this->nameConverter = $nameConverter;
5962
}
6063

6164
/**
@@ -194,6 +197,10 @@ private function getHydraProperties(string $resourceClass, ResourceMetadata $res
194197
continue;
195198
}
196199

200+
if ($this->nameConverter) {
201+
$propertyName = $this->nameConverter->normalize($propertyName);
202+
}
203+
197204
$properties[] = $this->getProperty($propertyMetadata, $propertyName, $prefixedShortName, $shortName);
198205
}
199206

src/Serializer/AbstractItemNormalizer.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2323
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
2424
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
25+
use ApiPlatform\Core\Util\ClassInfoTrait;
2526
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
2627
use Symfony\Component\PropertyAccess\PropertyAccess;
2728
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
@@ -37,6 +38,7 @@
3738
*/
3839
abstract class AbstractItemNormalizer extends AbstractObjectNormalizer
3940
{
41+
use ClassInfoTrait;
4042
use ContextTrait;
4143

4244
protected $propertyNameCollectionFactory;
@@ -74,13 +76,7 @@ public function supportsNormalization($data, $format = null)
7476
return false;
7577
}
7678

77-
try {
78-
$this->resourceClassResolver->getResourceClass($data);
79-
} catch (InvalidArgumentException $e) {
80-
return false;
81-
}
82-
83-
return true;
79+
return $this->resourceClassResolver->isResourceClass($this->getObjectClass($data));
8480
}
8581

8682
/**

tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ private function getPartialContainerBuilderProphecy($test = false)
498498
'api_platform.filter_locator',
499499
'api_platform.filter_collection_factory',
500500
'api_platform.filters',
501+
'api_platform.identifiers_extractor',
502+
'api_platform.identifiers_extractor.cached',
501503
'api_platform.iri_converter',
502504
'api_platform.identifier.denormalizer',
503505
'api_platform.identifier.integer',

tests/Bridge/Symfony/Routing/IriConverterTest.php

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,30 @@ public function testGetItemFromIri()
101101
$this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item);
102102
}
103103

104+
public function testGetItemFromIriWithOperationName()
105+
{
106+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
107+
108+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
109+
110+
$itemDataProviderProphecy = $this->prophesize(ItemDataProviderInterface::class);
111+
$itemDataProviderProphecy->getItem('AppBundle\Entity\User', '3', 'operation_name', ['fetch_data' => true])
112+
->willReturn('foo')
113+
->shouldBeCalledTimes(1);
114+
115+
$routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class);
116+
117+
$routerProphecy = $this->prophesize(RouterInterface::class);
118+
$routerProphecy->match('/users/3')->willReturn([
119+
'_api_resource_class' => 'AppBundle\Entity\User',
120+
'_api_item_operation_name' => 'operation_name',
121+
'id' => 3,
122+
])->shouldBeCalledTimes(1);
123+
124+
$converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy);
125+
$this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), 'foo');
126+
}
127+
104128
public function testGetIriFromResourceClass()
105129
{
106130
$routeNameResolverProphecy = $this->prophesize(RouteNameResolverInterface::class);
@@ -199,7 +223,7 @@ public function testGetItemFromIriWithIdentifierDenormalizer()
199223
'id' => 3,
200224
])->shouldBeCalledTimes(1);
201225

202-
$converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy, $identifierDenormalizerProphecy);
226+
$converter = $this->getIriConverter($routerProphecy, null, $itemDataProviderProphecy, null, $identifierDenormalizerProphecy);
203227
$this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item);
204228
}
205229

@@ -216,11 +240,9 @@ public function testGetItemFromIriWithSubresourceDataProvider()
216240
'_api_subresource_operation_name' => 'get_subresource',
217241
'id' => 3,
218242
])->shouldBeCalledTimes(1);
219-
$identifierDenormalizerProphecy = $this->prophesize(ChainIdentifierDenormalizer::class);
220-
$identifierDenormalizerProphecy->denormalize('3', Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]);
221243
$subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class);
222-
$subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, ChainIdentifierDenormalizer::HAS_IDENTIFIER_DENORMALIZER => true], 'get_subresource')->shouldBeCalled()->willReturn($item);
223-
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $identifierDenormalizerProphecy, $subresourceDataProviderProphecy);
244+
$subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => 3], $subresourceContext + ['fetch_data' => true], 'get_subresource')->shouldBeCalled()->willReturn($item);
245+
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy);
224246
$this->assertEquals($converter->getItemFromIri('/users/3/adresses', ['fetch_data' => true]), $item);
225247
}
226248

@@ -244,7 +266,7 @@ public function testGetItemFromIriWithSubresourceDataProviderNotFound()
244266
$identifierDenormalizerProphecy->denormalize('3', Dummy::class)->shouldBeCalled()->willReturn(['id' => 3]);
245267
$subresourceDataProviderProphecy = $this->prophesize(SubresourceDataProviderInterface::class);
246268
$subresourceDataProviderProphecy->getSubresource(Dummy::class, ['id' => ['id' => 3]], $subresourceContext + ['fetch_data' => true, ChainIdentifierDenormalizer::HAS_IDENTIFIER_DENORMALIZER => true], 'get_subresource')->shouldBeCalled()->willReturn(null);
247-
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $identifierDenormalizerProphecy, $subresourceDataProviderProphecy);
269+
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $subresourceDataProviderProphecy, $identifierDenormalizerProphecy);
248270
$converter->getItemFromIri('/users/3/adresses', ['fetch_data' => true]);
249271
}
250272

@@ -265,7 +287,7 @@ public function testGetItemFromIriBadIdentifierException()
265287
])->shouldBeCalledTimes(1);
266288
$identifierDenormalizerProphecy = $this->prophesize(ChainIdentifierDenormalizer::class);
267289
$identifierDenormalizerProphecy->denormalize('3', Dummy::class)->shouldBeCalled()->willThrow(new InvalidIdentifierException('fail'));
268-
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, $identifierDenormalizerProphecy);
290+
$converter = $this->getIriConverter($routerProphecy, $routeNameResolverProphecy, null, null, $identifierDenormalizerProphecy);
269291
$this->assertEquals($converter->getItemFromIri('/users/3', ['fetch_data' => true]), $item);
270292
}
271293

@@ -302,7 +324,7 @@ private function getResourceClassResolver()
302324
return $resourceClassResolver->reveal();
303325
}
304326

305-
private function getIriConverter($routerProphecy = null, $routeNameResolverProphecy = null, $itemDataProviderProphecy = null, $identifierDenormalizerProphecy = null, $subresourceDataProviderProphecy = null)
327+
private function getIriConverter($routerProphecy = null, $routeNameResolverProphecy = null, $itemDataProviderProphecy = null, $subresourceDataProviderProphecy = null, $identifierDenormalizerProphecy = null)
306328
{
307329
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
308330
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
@@ -328,8 +350,8 @@ private function getIriConverter($routerProphecy = null, $routeNameResolverProph
328350
$routerProphecy->reveal(),
329351
null,
330352
new IdentifiersExtractor($propertyNameCollectionFactory, $propertyMetadataFactory, null, $this->getResourceClassResolver()),
331-
$identifierDenormalizerProphecy ? $identifierDenormalizerProphecy->reveal() : null,
332-
$subresourceDataProviderProphecy ? $subresourceDataProviderProphecy->reveal() : null
353+
$subresourceDataProviderProphecy ? $subresourceDataProviderProphecy->reveal() : null,
354+
$identifierDenormalizerProphecy ? $identifierDenormalizerProphecy->reveal() : null
333355
);
334356
}
335357
}

0 commit comments

Comments
 (0)