-
-
Notifications
You must be signed in to change notification settings - Fork 868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix relations denormalization with plain ids #1855
Conversation
try { | ||
return $this->serializer->denormalize($value, $className, $format, $context); | ||
} catch (InvalidArgumentException $e) { | ||
if ('Invalid value provided (invalid IRI?).' !== $e->getMessage()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it could be better to introduce a new Exception extending the InvalidArgumentException
.
That said, we wouldn't have to the check the message, WDYT ?
https://github.com/api-platform/core/blob/master/src/Serializer/AbstractItemNormalizer.php#L164
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, added a comment on that on my description, but IMO this is not really the scope of this PR, right ? Or should I change it anyway ?
|
||
namespace ApiPlatform\Core\Exception; | ||
|
||
class InvalidValueException extends InvalidArgumentException |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about reusing InvalideIdentifierException
(backport it from master)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem to extend / implement the invalid argument exception, Wouldn't that be a BC Break ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think so. Anyway I'd be fine with a new exception just trying to avoid multiplying them :p. Maybe we can call this one InvalidIRIException
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not against multiplying exceptions. It's just that in 2.2.4 (and 2.2.5), we should expect a InvalidArgumentException
(or a child of it), not something else, e.g Exception
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless you meant copying / pasting the code from the InvalidIdentifierException
? Which is not clean too (not saying that testing a reason
is better though :P)
try { | ||
return $this->serializer->denormalize($value, $className, $format, $context); | ||
} catch (InvalidValueException $e) { | ||
if ('invalid IRI?' !== $e->getReason()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait what? Shouldn't we have 1 exception per case to avoid this comparison?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, wasn't sure if we should have an invalid value exception for the invalid iri, but I could alter that to use one instead ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I got that. This exception is only thrown when IRI is invalid right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but the part between parentheses looked variable, that's why I added a reason. I can merge it if needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I really don't follow I think I'm missing something, has been a long day haha
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we had Invalid value (Invalid IRI?).
, so I thought that we could have multiple Invalid Value (reason)
, and it could sometimes be Invalid Value (Invalid IRI?)
. That's all, but then, I can make a InvalidIriException
and be done with it :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes please :D
bdfe70f
to
aae76af
Compare
Updated @soyuka but not satisfied with the tests, looks like something is wrong, as the result is |
|
||
public function __construct(int $code = 0, \Throwable $previous = null) | ||
{ | ||
parent::__construct("Invalid value provided (Invalid IRI?).", $code, $previous); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just remove everything in this class and call the exception with a message?
@@ -161,7 +162,7 @@ protected function getAllowedAttributes($classOrObject, array $context, $attribu | |||
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []) | |||
{ | |||
if (!\is_string($attribute)) { | |||
throw new InvalidArgumentException('Invalid value provided (invalid IRI?).'); | |||
throw new InvalidIriException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new InvalidIriException('Invalid value provided (invalid IRI?).');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would be the point of the exception if the message is not always the same one ? It's like using a generic exception... look at the exceptions from symfony, they each have somehting customisable but a defined (and thus customizable) message (even though the message is also quite pointless and not used)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we can have different reasons for an invalid IRI exception:
- bad format
- route not found
- data not found
for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's why I had the (invalid IRI?)
variable, so we would always have Invalid value provider (REASON)
. But ¯\_(ツ)_/¯
because it's the same thing actually. :}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @soyuka (and every other exception we have for now work like this). You can also add the message as the default value of the $message
parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, changed and removed the constructor altogether, as @soyuka suggested #1855 (comment)
c197b46
to
83cbb7a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh tests don't pass though
Indeed, I have some problems with the feature actually. Need some help looking into that, why it doesn't seem to take the plain id into account... |
@@ -161,7 +162,7 @@ protected function getAllowedAttributes($classOrObject, array $context, $attribu | |||
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []) | |||
{ | |||
if (!\is_string($attribute)) { | |||
throw new InvalidArgumentException('Invalid value provided (invalid IRI?).'); | |||
throw new InvalidValueException('Invalid value provided (Invalid IRI?).'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the message should be reverted (why an upper case I)?
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.
83cbb7a
to
b80916b
Compare
b80916b
to
cd0dd88
Compare
Looks like I managed to fix the tests 🎉 |
Thanks @Taluu |
#1547 introduced an
is_array
check to prevent the normalize to act on writable relations so that we could use plain identifiers, and was reverted by #1762 because not all relations are arrays, and can be iris.But this revert triggered also the fact that we cannot use plain ids anymore on writable relations. This PR aims to fix that ; if we encounter the invalid argument exception while trying to denormalize the relation, and that we allowed plain identifiers and we have an item provider, we should try the next block if it's not an array. Now that I think about it, I should probably add a
!is_array
check or something ?The tests passes, but I'm not sure how I can add a test to reflect this, so any hint would be welcomed...
BTW, shouldn't we add a more specific exception for the invalid iri ? Testing the message isn't specially clean IMO... and as it's not the scope of this PR, I had to make do with this.