Skip to content

Commit 86a7959

Browse files
committed
Merge 3.4
2 parents cd2dbd0 + 4c29bf8 commit 86a7959

15 files changed

+92
-35
lines changed

src/Laravel/ApiPlatformProvider.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,6 @@
9696
use ApiPlatform\Laravel\Metadata\CachePropertyMetadataFactory;
9797
use ApiPlatform\Laravel\Metadata\CachePropertyNameCollectionMetadataFactory;
9898
use ApiPlatform\Laravel\Metadata\CacheResourceCollectionMetadataFactory;
99-
use ApiPlatform\Laravel\Metadata\ConcernsPropertyNameCollectionMetadataFactory;
100-
use ApiPlatform\Laravel\Metadata\ConcernsResourceMetadataCollectionFactory;
101-
use ApiPlatform\Laravel\Metadata\ConcernsResourceNameCollectionFactory;
10299
use ApiPlatform\Laravel\Routing\IriConverter;
103100
use ApiPlatform\Laravel\Routing\Router as UrlGeneratorRouter;
104101
use ApiPlatform\Laravel\Routing\SkolemIriConverter;
@@ -108,7 +105,6 @@
108105
use ApiPlatform\Laravel\State\SwaggerUiProvider;
109106
use ApiPlatform\Laravel\State\ValidateProvider;
110107
use ApiPlatform\Metadata\Exception\NotExposedHttpException;
111-
use ApiPlatform\Metadata\Factory\Property\ClassLevelAttributePropertyNameCollectionFactory;
112108
use ApiPlatform\Metadata\FilterInterface;
113109
use ApiPlatform\Metadata\IdentifiersExtractor;
114110
use ApiPlatform\Metadata\IdentifiersExtractorInterface;
@@ -119,6 +115,8 @@
119115
use ApiPlatform\Metadata\Operation\PathSegmentNameGeneratorInterface;
120116
use ApiPlatform\Metadata\Operation\UnderscorePathSegmentNameGenerator;
121117
use ApiPlatform\Metadata\Property\Factory\AttributePropertyMetadataFactory;
118+
use ApiPlatform\Metadata\Property\Factory\ClassLevelAttributePropertyNameCollectionFactory;
119+
use ApiPlatform\Metadata\Property\Factory\ConcernsPropertyNameCollectionMetadataFactory;
122120
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyMetadataFactory;
123121
use ApiPlatform\Metadata\Property\Factory\PropertyInfoPropertyNameCollectionFactory;
124122
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
@@ -127,6 +125,8 @@
127125
use ApiPlatform\Metadata\Resource\Factory\AlternateUriResourceMetadataCollectionFactory;
128126
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory;
129127
use ApiPlatform\Metadata\Resource\Factory\AttributesResourceNameCollectionFactory;
128+
use ApiPlatform\Metadata\Resource\Factory\ConcernsResourceMetadataCollectionFactory;
129+
use ApiPlatform\Metadata\Resource\Factory\ConcernsResourceNameCollectionFactory;
130130
use ApiPlatform\Metadata\Resource\Factory\FiltersResourceMetadataCollectionFactory;
131131
use ApiPlatform\Metadata\Resource\Factory\FormatsResourceMetadataCollectionFactory;
132132
use ApiPlatform\Metadata\Resource\Factory\InputOutputResourceMetadataCollectionFactory;

src/Laravel/IsApiResource.php renamed to src/Metadata/IsApiResource.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111

1212
declare(strict_types=1);
1313

14-
namespace ApiPlatform\Laravel;
15-
16-
use ApiPlatform\Metadata\ApiResource;
14+
namespace ApiPlatform\Metadata;
1715

1816
/**
1917
* @author Kévin Dunglas <[email protected]>

src/Metadata/Factory/Property/ClassLevelAttributePropertyNameCollectionFactory.php renamed to src/Metadata/Property/Factory/ClassLevelAttributePropertyNameCollectionFactory.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111

1212
declare(strict_types=1);
1313

14-
namespace ApiPlatform\Metadata\Factory\Property;
14+
namespace ApiPlatform\Metadata\Property\Factory;
1515

1616
use ApiPlatform\Metadata\ApiProperty;
17-
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
1817
use ApiPlatform\Metadata\Property\PropertyNameCollection;
1918

2019
/**

src/Laravel/Metadata/ConcernsPropertyNameCollectionMetadataFactory.php renamed to src/Metadata/Property/Factory/ConcernsPropertyNameCollectionMetadataFactory.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111

1212
declare(strict_types=1);
1313

14-
namespace ApiPlatform\Laravel\Metadata;
14+
namespace ApiPlatform\Metadata\Property\Factory;
1515

16-
use ApiPlatform\Laravel\IsApiResource;
1716
use ApiPlatform\Metadata\ApiProperty;
18-
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
17+
use ApiPlatform\Metadata\IsApiResource;
1918
use ApiPlatform\Metadata\Property\PropertyNameCollection;
2019

2120
/**

src/Laravel/Metadata/ConcernsResourceMetadataCollectionFactory.php renamed to src/Metadata/Resource/Factory/ConcernsResourceMetadataCollectionFactory.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@
1111

1212
declare(strict_types=1);
1313

14-
namespace ApiPlatform\Laravel\Metadata;
14+
namespace ApiPlatform\Metadata\Resource\Factory;
1515

16-
use ApiPlatform\Laravel\IsApiResource;
17-
use ApiPlatform\Metadata\Resource\Factory\MetadataCollectionFactoryTrait;
18-
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
16+
use ApiPlatform\Metadata\IsApiResource;
1917
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
2018

2119
/**

src/Laravel/Metadata/ConcernsResourceNameCollectionFactory.php renamed to src/Metadata/Resource/Factory/ConcernsResourceNameCollectionFactory.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111

1212
declare(strict_types=1);
1313

14-
namespace ApiPlatform\Laravel\Metadata;
14+
namespace ApiPlatform\Metadata\Resource\Factory;
1515

16-
use ApiPlatform\Laravel\IsApiResource;
17-
use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
16+
use ApiPlatform\Metadata\IsApiResource;
1817
use ApiPlatform\Metadata\Resource\ResourceNameCollection;
1918
use ApiPlatform\Metadata\Util\ReflectionClassRecursiveIterator;
2019

src/OpenApi/Factory/OpenApiFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
304304
}
305305
}
306306

307-
if (!$operation instanceof CollectionOperationInterface && 'POST' !== $operation->getMethod()) {
307+
if (true === $overrideResponses && !$operation instanceof CollectionOperationInterface && 'POST' !== $operation->getMethod()) {
308308
if (!isset($existingResponses[404])) {
309309
$openapiOperation = $openapiOperation->withResponse(404, new Response('Resource not found'));
310310
}

src/OpenApi/Model/PathItem.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function getServers(): ?array
8383
return $this->servers;
8484
}
8585

86-
public function getParameters(): array
86+
public function getParameters(): ?array
8787
{
8888
return $this->parameters;
8989
}

src/Serializer/AbstractItemNormalizer.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public function denormalize(mixed $data, string $class, ?string $format = null,
225225
return $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]);
226226
} catch (ItemNotFoundException $e) {
227227
throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e);
228-
} catch (InvalidArgumentException $e) {
228+
} catch (LegacyInvalidArgumentException|InvalidArgumentException $e) {
229229
throw new UnexpectedValueException(\sprintf('Invalid IRI "%s".', $data), $e->getCode(), $e);
230230
}
231231
}
@@ -522,9 +522,14 @@ protected function denormalizeCollection(string $attribute, ApiProperty $propert
522522
$childContext = $this->createChildContext($this->createOperationContext($context, $className), $attribute, $format);
523523
$collectionKeyTypes = $type->getCollectionKeyTypes();
524524
foreach ($value as $index => $obj) {
525+
$currentChildContext = $childContext;
526+
if (isset($childContext['deserialization_path'])) {
527+
$currentChildContext['deserialization_path'] = "{$childContext['deserialization_path']}[{$index}]";
528+
}
529+
525530
// no typehint provided on collection key
526531
if (!$collectionKeyTypes) {
527-
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $childContext);
532+
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $currentChildContext);
528533
continue;
529534
}
530535

@@ -535,7 +540,7 @@ protected function denormalizeCollection(string $attribute, ApiProperty $propert
535540
continue;
536541
}
537542

538-
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $childContext);
543+
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $currentChildContext);
539544
continue 2;
540545
}
541546
throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type of the key "%s" must be "%s", "%s" given.', $index, $collectionKeyTypes[0]->getBuiltinType(), \gettype($index)), $index, [$collectionKeyTypes[0]->getBuiltinType()], ($context['deserialization_path'] ?? false) ? \sprintf('key(%s)', $context['deserialization_path']) : null, true);
@@ -571,7 +576,7 @@ protected function denormalizeRelation(string $attributeName, ApiProperty $prope
571576
);
572577

573578
return null;
574-
} catch (InvalidArgumentException $e) {
579+
} catch (LegacyInvalidArgumentException|InvalidArgumentException $e) {
575580
if (!isset($context['not_normalizable_value_exceptions'])) {
576581
throw new UnexpectedValueException(\sprintf('Invalid IRI "%s".', $value), $e->getCode(), $e);
577582
}

src/Serializer/Tests/AbstractItemNormalizerTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use ApiPlatform\Metadata\ApiProperty;
1717
use ApiPlatform\Metadata\ApiResource;
18+
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
1819
use ApiPlatform\Metadata\Get;
1920
use ApiPlatform\Metadata\GetCollection;
2021
use ApiPlatform\Metadata\IriConverterInterface;
@@ -862,6 +863,56 @@ public function testBadRelationTypeWithExceptionToValidationErrors(): void
862863
$this->assertNull($actual->relatedDummy);
863864
}
864865

866+
public function testDeserializationPathForNotDenormalizableRelations(): void
867+
{
868+
$data = [
869+
'relatedDummies' => ['wrong'],
870+
];
871+
872+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
873+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummies']));
874+
875+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
876+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn(
877+
(new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, null, true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, RelatedDummy::class))])->withReadable(false)->withWritable(true)->withReadableLink(false)->withWritableLink(true)
878+
);
879+
880+
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
881+
$iriConverterProphecy->getResourceFromIri(Argument::cetera())->willThrow(new InvalidArgumentException('Invalid IRI'));
882+
883+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
884+
$resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class);
885+
$resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class);
886+
$resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
887+
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true);
888+
889+
$propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class);
890+
891+
$serializerProphecy = $this->prophesize(SerializerInterface::class);
892+
$serializerProphecy->willImplement(DenormalizerInterface::class);
893+
894+
$normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [
895+
$propertyNameCollectionFactoryProphecy->reveal(),
896+
$propertyMetadataFactoryProphecy->reveal(),
897+
$iriConverterProphecy->reveal(),
898+
$resourceClassResolverProphecy->reveal(),
899+
$propertyAccessorProphecy->reveal(),
900+
null,
901+
null,
902+
[],
903+
null,
904+
null,
905+
]);
906+
$normalizer->setSerializer($serializerProphecy->reveal());
907+
908+
$errors = [];
909+
$actual = $normalizer->denormalize($data, Dummy::class, null, ['not_normalizable_value_exceptions' => &$errors]);
910+
$this->assertEmpty($actual->relatedDummies);
911+
$this->assertCount(1, $errors); // @phpstan-ignore-line method.impossibleType (false positive)
912+
$this->assertInstanceOf(NotNormalizableValueException::class, $errors[0]);
913+
$this->assertSame('relatedDummies[0]', $errors[0]->getPath());
914+
}
915+
865916
public function testInnerDocumentNotAllowed(): void
866917
{
867918
$this->expectException(UnexpectedValueException::class);

0 commit comments

Comments
 (0)