Skip to content

Commit 7a680f1

Browse files
Taluudunglas
authored andcommitted
Fix relations denormalization with plain ids (#1855)
* On invalid iri error with plain identifiers, use the data provider If a resource property is writable, we can't use plain identifiers, and end up with a iri error, while we explicit allowed plain identifiers. * Make an appropriare exception for invalid value on item normalizer * Add a behat test for plain id relations
1 parent 29aa053 commit 7a680f1

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

features/main/relation.feature

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,50 @@ Feature: Relations support
512512
}
513513
"""
514514

515+
Scenario: Passing a (valid) plain identifier on a relation
516+
When I add "Content-Type" header equal to "application/json"
517+
And I send a "POST" request to "/dummies" with body:
518+
"""
519+
{
520+
"relatedDummy": "1",
521+
"relatedDummies": ["1"],
522+
"name": "Dummy with plain relations"
523+
}
524+
"""
525+
Then the response status code should be 201
526+
And the response should be in JSON
527+
And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8"
528+
And the JSON should be equal to:
529+
"""
530+
{
531+
"@context":"/contexts/Dummy",
532+
"@id":"/dummies/2",
533+
"@type":"Dummy",
534+
"description":null,
535+
"dummy":null,
536+
"dummyBoolean":null,
537+
"dummyDate":null,
538+
"dummyFloat":null,
539+
"dummyPrice":null,
540+
"relatedDummy":"/related_dummies/1",
541+
"relatedDummies":["/related_dummies/1"],
542+
"jsonData":[],
543+
"arrayData":[],
544+
"name_converted":null,
545+
"id":2,
546+
"name":"Dummy with plain relations",
547+
"alias":null,
548+
"foo":null
549+
}
550+
"""
551+
515552
@dropSchema
516553
Scenario: Passing an invalid IRI to a relation
517554
When I add "Content-Type" header equal to "application/ld+json"
518555
And I send a "POST" request to "/relation_embedders" with body:
519556
"""
520557
{
521-
"related": "certainly not an iri"
558+
"related": "certainly not an iri and not a plain identifier"
522559
}
523560
"""
524561
Then the response status code should be 400
Lines changed: 18 additions & 0 deletions
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\Core\Exception;
15+
16+
class InvalidValueException extends InvalidArgumentException
17+
{
18+
}

src/Serializer/AbstractItemNormalizer.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use ApiPlatform\Core\Api\ResourceClassResolverInterface;
1919
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
2020
use ApiPlatform\Core\Exception\InvalidArgumentException;
21+
use ApiPlatform\Core\Exception\InvalidValueException;
2122
use ApiPlatform\Core\Exception\ItemNotFoundException;
2223
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2324
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
@@ -157,7 +158,7 @@ protected function getAllowedAttributes($classOrObject, array $context, $attribu
157158
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = [])
158159
{
159160
if (!\is_string($attribute)) {
160-
throw new InvalidArgumentException('Invalid value provided (invalid IRI?).');
161+
throw new InvalidValueException('Invalid value provided (invalid IRI?).');
161162
}
162163

163164
$propertyMetadata = $this->propertyMetadataFactory->create($context['resource_class'], $attribute, $this->getFactoryOptions($context));
@@ -304,7 +305,13 @@ protected function denormalizeRelation(string $attributeName, PropertyMetadata $
304305
$context['resource_class'] = $className;
305306
$context['api_allow_update'] = true;
306307

307-
return $this->serializer->denormalize($value, $className, $format, $context);
308+
try {
309+
return $this->serializer->denormalize($value, $className, $format, $context);
310+
} catch (InvalidValueException $e) {
311+
if (!$this->allowPlainIdentifiers || null === $this->itemDataProvider) {
312+
throw $e;
313+
}
314+
}
308315
}
309316

310317
if (!\is_array($value)) {

0 commit comments

Comments
 (0)