Skip to content

Commit 2aeafd6

Browse files
committed
Merge 3.4
2 parents e063b80 + b3d7c07 commit 2aeafd6

File tree

12 files changed

+89
-21
lines changed

12 files changed

+89
-21
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ jobs:
945945
- '8.3'
946946
fail-fast: false
947947
env:
948+
SYMFONY_PHPUNIT_VERSION: '9.5'
948949
APP_ENV: sqlite
949950
DATABASE_URL: sqlite:///%kernel.project_dir%/var/data.db
950951
steps:
@@ -996,6 +997,7 @@ jobs:
996997
- '8.3'
997998
fail-fast: false
998999
env:
1000+
SYMFONY_PHPUNIT_VERSION: '9.5'
9991001
APP_ENV: sqlite
10001002
DATABASE_URL: sqlite:///%kernel.project_dir%/var/data.db
10011003
steps:

src/Exception/FilterValidationException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*
2121
* @author Julien DENIAU <[email protected]>
2222
*
23-
* @deprecated use \ApiPlatform\Metadata\Exception\ValidationException instead
23+
* @deprecated use \ApiPlatform\ParameterValidator\Exception\ValidationException instead
2424
*/
2525
final class FilterValidationException extends \Exception implements ValidationExceptionInterface, ExceptionInterface, \Stringable
2626
{

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: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515

1616
use ApiPlatform\Api\IriConverterInterface as LegacyIriConverterInterface;
1717
use ApiPlatform\Api\ResourceClassResolverInterface as LegacyResourceClassResolverInterface;
18-
use ApiPlatform\Exception\InvalidArgumentException;
18+
use ApiPlatform\Exception\InvalidArgumentException as LegacyInvalidArgumentException;
1919
use ApiPlatform\Exception\ItemNotFoundException;
2020
use ApiPlatform\Metadata\ApiProperty;
2121
use ApiPlatform\Metadata\CollectionOperationInterface;
22+
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
2223
use ApiPlatform\Metadata\IriConverterInterface;
2324
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2425
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
@@ -244,7 +245,7 @@ public function denormalize(mixed $data, string $class, ?string $format = null,
244245
return $this->iriConverter->getResourceFromIri($data, $context + ['fetch_data' => true]);
245246
} catch (ItemNotFoundException $e) {
246247
throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e);
247-
} catch (InvalidArgumentException $e) {
248+
} catch (LegacyInvalidArgumentException|InvalidArgumentException $e) {
248249
throw new UnexpectedValueException(\sprintf('Invalid IRI "%s".', $data), $e->getCode(), $e);
249250
}
250251
}
@@ -541,9 +542,14 @@ protected function denormalizeCollection(string $attribute, ApiProperty $propert
541542
$childContext = $this->createChildContext($this->createOperationContext($context, $className), $attribute, $format);
542543
$collectionKeyTypes = $type->getCollectionKeyTypes();
543544
foreach ($value as $index => $obj) {
545+
$currentChildContext = $childContext;
546+
if (isset($childContext['deserialization_path'])) {
547+
$currentChildContext['deserialization_path'] = "{$childContext['deserialization_path']}[{$index}]";
548+
}
549+
544550
// no typehint provided on collection key
545551
if (!$collectionKeyTypes) {
546-
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $childContext);
552+
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $currentChildContext);
547553
continue;
548554
}
549555

@@ -554,7 +560,7 @@ protected function denormalizeCollection(string $attribute, ApiProperty $propert
554560
continue;
555561
}
556562

557-
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $childContext);
563+
$values[$index] = $this->denormalizeRelation($attribute, $propertyMetadata, $className, $obj, $format, $currentChildContext);
558564
continue 2;
559565
}
560566
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);
@@ -590,7 +596,7 @@ protected function denormalizeRelation(string $attributeName, ApiProperty $prope
590596
);
591597

592598
return null;
593-
} catch (InvalidArgumentException $e) {
599+
} catch (LegacyInvalidArgumentException|InvalidArgumentException $e) {
594600
if (!isset($context['not_normalizable_value_exceptions'])) {
595601
throw new UnexpectedValueException(\sprintf('Invalid IRI "%s".', $value), $e->getCode(), $e);
596602
}

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;
@@ -1034,6 +1035,56 @@ public function testBadRelationTypeWithExceptionToValidationErrors(): void
10341035
$this->assertNull($actual->relatedDummy);
10351036
}
10361037

1038+
public function testDeserializationPathForNotDenormalizableRelations(): void
1039+
{
1040+
$data = [
1041+
'relatedDummies' => ['wrong'],
1042+
];
1043+
1044+
$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
1045+
$propertyNameCollectionFactoryProphecy->create(Dummy::class, [])->willReturn(new PropertyNameCollection(['relatedDummies']));
1046+
1047+
$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
1048+
$propertyMetadataFactoryProphecy->create(Dummy::class, 'relatedDummies', [])->willReturn(
1049+
(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)
1050+
);
1051+
1052+
$iriConverterProphecy = $this->prophesize(IriConverterInterface::class);
1053+
$iriConverterProphecy->getResourceFromIri(Argument::cetera())->willThrow(new InvalidArgumentException('Invalid IRI'));
1054+
1055+
$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
1056+
$resourceClassResolverProphecy->getResourceClass(null, Dummy::class)->willReturn(Dummy::class);
1057+
$resourceClassResolverProphecy->getResourceClass(null, RelatedDummy::class)->willReturn(RelatedDummy::class);
1058+
$resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
1059+
$resourceClassResolverProphecy->isResourceClass(RelatedDummy::class)->willReturn(true);
1060+
1061+
$propertyAccessorProphecy = $this->prophesize(PropertyAccessorInterface::class);
1062+
1063+
$serializerProphecy = $this->prophesize(SerializerInterface::class);
1064+
$serializerProphecy->willImplement(DenormalizerInterface::class);
1065+
1066+
$normalizer = $this->getMockForAbstractClass(AbstractItemNormalizer::class, [
1067+
$propertyNameCollectionFactoryProphecy->reveal(),
1068+
$propertyMetadataFactoryProphecy->reveal(),
1069+
$iriConverterProphecy->reveal(),
1070+
$resourceClassResolverProphecy->reveal(),
1071+
$propertyAccessorProphecy->reveal(),
1072+
null,
1073+
null,
1074+
[],
1075+
null,
1076+
null,
1077+
]);
1078+
$normalizer->setSerializer($serializerProphecy->reveal());
1079+
1080+
$errors = [];
1081+
$actual = $normalizer->denormalize($data, Dummy::class, null, ['not_normalizable_value_exceptions' => &$errors]);
1082+
$this->assertEmpty($actual->relatedDummies);
1083+
$this->assertCount(1, $errors); // @phpstan-ignore-line method.impossibleType (false positive)
1084+
$this->assertInstanceOf(NotNormalizableValueException::class, $errors[0]);
1085+
$this->assertSame('relatedDummies[0]', $errors[0]->getPath());
1086+
}
1087+
10371088
public function testInnerDocumentNotAllowed(): void
10381089
{
10391090
$this->expectException(UnexpectedValueException::class);

src/State/Util/ParameterParserTrait.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,8 @@ private function extractParameterValues(Parameter $parameter, array $values): st
5151
$key = $parsedKey[0];
5252
} elseif (str_contains($key, '[')) {
5353
preg_match_all('/[^\[\]]+/', $key, $matches);
54-
if (isset($matches[0])) {
55-
$key = array_shift($matches[0]);
56-
$accessors = $matches[0];
57-
}
54+
$key = array_shift($matches[0]);
55+
$accessors = $matches[0];
5856
}
5957

6058
$value = $values[$key] ?? new ParameterNotFound();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@
154154
<service id="api_platform.uri_variables.converter" class="ApiPlatform\Api\UriVariablesConverter" public="false">
155155
<argument type="service" id="api_platform.metadata.property.metadata_factory" />
156156
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
157-
<argument type="tagged" tag="api_platform.uri_variables.transformer" />
157+
<argument type="tagged_iterator" tag="api_platform.uri_variables.transformer" />
158158
</service>
159159

160160
<service id="api_platform.uri_variables.transformer.integer" class="ApiPlatform\Api\UriVariableTransformer\IntegerUriVariableTransformer" public="false">

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@
154154
<service id="api_platform.doctrine.orm.state.collection_provider" class="ApiPlatform\Doctrine\Orm\State\CollectionProvider" public="false">
155155
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
156156
<argument type="service" id="doctrine" />
157-
<argument type="tagged" tag="api_platform.doctrine.orm.query_extension.collection" />
157+
<argument type="tagged_iterator" tag="api_platform.doctrine.orm.query_extension.collection" />
158158
<argument type="tagged_locator" tag="api_platform.doctrine.orm.links_handler" index-by="key" />
159159

160160
<tag name="api_platform.state_provider" priority="-100" key="ApiPlatform\Doctrine\Orm\State\CollectionProvider" />
@@ -165,7 +165,7 @@
165165
<service id="api_platform.doctrine.orm.state.item_provider" class="ApiPlatform\Doctrine\Orm\State\ItemProvider" public="false">
166166
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
167167
<argument type="service" id="doctrine" />
168-
<argument type="tagged" tag="api_platform.doctrine.orm.query_extension.item" />
168+
<argument type="tagged_iterator" tag="api_platform.doctrine.orm.query_extension.item" />
169169
<argument type="tagged_locator" tag="api_platform.doctrine.orm.links_handler" index-by="key" />
170170

171171
<tag name="api_platform.state_provider" priority="-100" key="ApiPlatform\Doctrine\Orm\State\ItemProvider" />

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
<services>
88
<service id="api_platform.http_cache.purger.varnish" alias="api_platform.http_cache.purger.varnish.ban" public="false" />
99
<service id="api_platform.http_cache.purger.varnish.ban" class="ApiPlatform\HttpCache\VarnishPurger" public="false">
10-
<argument type="tagged" tag="api_platform.http_cache.http_client" />
10+
<argument type="tagged_iterator" tag="api_platform.http_cache.http_client" />
1111
</service>
1212
<service id="api_platform.http_cache.purger.varnish.xkey" class="ApiPlatform\HttpCache\VarnishXKeyPurger" public="false">
13-
<argument type="tagged" tag="api_platform.http_cache.http_client" />
13+
<argument type="tagged_iterator" tag="api_platform.http_cache.http_client" />
1414
<argument>%api_platform.http_cache.invalidation.max_header_length%</argument>
1515
<argument>%api_platform.http_cache.invalidation.xkey.glue%</argument>
1616
</service>
1717
<service id="api_platform.http_cache.purger.souin" class="ApiPlatform\HttpCache\SouinPurger" public="false">
18-
<argument type="tagged" tag="api_platform.http_cache.http_client" />
18+
<argument type="tagged_iterator" tag="api_platform.http_cache.http_client" />
1919
<argument>%api_platform.http_cache.invalidation.max_header_length%</argument>
2020
</service>
2121
</services>

src/Symfony/Bundle/Resources/config/metadata/validator.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
<service id="api_platform.metadata.property.metadata_factory.validator" class="ApiPlatform\Symfony\Validator\Metadata\Property\ValidatorPropertyMetadataFactory" decorates="api_platform.metadata.property.metadata_factory" decoration-priority="20" public="false">
77
<argument type="service" id="validator" />
88
<argument type="service" id="api_platform.metadata.property.metadata_factory.validator.inner" />
9-
<argument type="tagged" tag="api_platform.metadata.property_schema_restriction" />
9+
<argument type="tagged_iterator" tag="api_platform.metadata.property_schema_restriction" />
1010
</service>
1111

1212
<service id="api_platform.metadata.property_schema.choice_restriction" class="ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaChoiceRestriction" public="false">
1313
<tag name="api_platform.metadata.property_schema_restriction"/>
1414
</service>
1515

1616
<service id="api_platform.metadata.property_schema.collection_restriction" class="ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaCollectionRestriction" public="false">
17-
<argument type="tagged" tag="api_platform.metadata.property_schema_restriction" />
17+
<argument type="tagged_iterator" tag="api_platform.metadata.property_schema_restriction" />
1818
<tag name="api_platform.metadata.property_schema_restriction"/>
1919
</service>
2020

@@ -43,7 +43,7 @@
4343
</service>
4444

4545
<service id="api_platform.metadata.property_schema.one_of_restriction" class="ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaOneOfRestriction" public="false">
46-
<argument type="tagged" tag="api_platform.metadata.property_schema_restriction" />
46+
<argument type="tagged_iterator" tag="api_platform.metadata.property_schema_restriction" />
4747
<tag name="api_platform.metadata.property_schema_restriction"/>
4848
</service>
4949

0 commit comments

Comments
 (0)