-
-
Notifications
You must be signed in to change notification settings - Fork 875
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
[RFC] Refactor population of object in serializer #1939
Conversation
$identifiers = $this->identifiersExtractor->getIdentifiersFromResourceClass($class); | ||
} | ||
|
||
if (0 !== count(array_intersect(array_keys($data), $identifiers))) { |
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 have no clue if this works, it was just a quick hack and needs to be covered by tests. The idea here is just to check if the data contains all identifiers.
private function updateObjectToPopulate(array $data, array &$context) | ||
{ | ||
try { | ||
$context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getItemFromIri((string) $data['id'], $context + ['fetch_data' => true]); |
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.
This whole method was nonsense imho. Looks like it was developed before there was the IdentifiersExtractor
.
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.
Looks like it was developed before there was the
IdentifiersExtractor
.
It's the case.
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.
You should add a deprecated error here saying this class is deprecated, and "unabstract" the AbstractItemNormalizer
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 don't think that's a good plan. I'd keep it as is because the AbstractItemNormalizer
is not used directly anywhere now and maybe there will be the day we have to add something to the ItemNormalizer
. It can still be refactored for 3.0 even if there's no deprecation message.
*/ | ||
protected function getIdentifiersForDenormalization(string $class): array | ||
{ | ||
return $this->identifiersExtractor->getIdentifiersFromResourceClass($class); |
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.
$identifierExtractor is nullable so you can't call a metod on it directly
@@ -65,6 +67,12 @@ public function __construct(PropertyNameCollectionFactoryInterface $propertyName | |||
$this->setCircularReferenceHandler(function ($object) { | |||
return $this->iriConverter->getIriFromItem($object); | |||
}); | |||
|
|||
if (null === $identifiersExtractor) { | |||
@trigger_error(sprintf('Not passing an instance of IdentifiersExtractorInterface in "%s" is deprecated and will be mandatory in version 3.0. Not passing it is deprecated since 2.2.', __METHOD__), E_USER_DEPRECATED); |
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.
2.3
nay ? Kinda strange to introduce a deprecated on > 2.2.0...
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 really, not being able to pass an id
in a POST request is a bug to me but I don't care as long as it's published soon it can also go into 2.3 😄 Deprecating in bugfix releases is fine.
|
||
$context[self::OBJECT_TO_POPULATE] = $object; | ||
} | ||
} |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
||
$identifiers = $this->getIdentifiersForDenormalization($class); | ||
|
||
if (0 !== count(array_intersect(array_keys($data), $identifiers))) { |
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 really not sure about this but maybe that performances would be better with a simple foreach test:
foreach ($identifiers as $identifier) { if (!isset($data[$identifier])) { return false; } }
return true;
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.
Also it should be \count
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 be simplified to if (\count(array_intersect(array_keys($data), $identifiers))
* @param array $context | ||
* @param array $identifiers | ||
*/ | ||
protected function populateObjectIfAllowed($data, $class, array $context = []) |
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 type the $class
as string
?
Hey guys, this PR is not ready to review at all 😄 I mean, I know there's loads of stuff to cleanup, null pointer exceptions etc. but all I wanted to know is if you think the general concept could work and it's worth continuing into this direction or if I'm completely wrong. What I'm e.g. missing is the use of the IriConverter. What's the idea there. Asking the IriConverter first if there's a result and if not, asking the ItemDataProvider so both is supported? |
The ItemDataProvider shouldn't be useful here. IMO IriConverter should be sufficient and we would need to merge #1837 before being able to fix this correctly. |
@soyuka do you mean like so? |
@Toflar yes this is really good! |
Okay, phpunit is fixed. Behat left 😓 |
Don't you run tests locally? |
Sure but as it‘s squashed anyway I keep my motivation high by making smaller nonsense commits🤔😂 |
Okay |
@soyuka will try to help with the behat tests. I've restored them to the initial state as per his request. |
@Toflar can you rebase on 2.2 and see how the tests look. I'm working on this and can PR to your branch. I'll raise some comments here. |
return; | ||
} | ||
|
||
$updateAllowed = isset($context['api_allow_update']) && true !== $context['api_allow_update']; |
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.
should be ===
not !==
or just:
$updateAllowed = $context['api_allow_update'] ?? false;
return; | ||
} | ||
|
||
if (null !== $object && $updateAllowed) { |
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.
should be !$updateAllowed
* @param array $context | ||
* @param array $identifiers | ||
*/ | ||
protected function setObjectToPopulate($data, $class, array $context = []) |
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.
you need to pass $context
by reference as you are modifying it.
|
||
$updateAllowed = isset($context['api_allow_update']) && true !== $context['api_allow_update']; | ||
$identifiers = $this->getIdentifiersForDenormalization($class); | ||
$writeableIdentifiers = []; |
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.
this logic is flawed unfortunately. You cannot validate the writability of identifiers here, as identifiers can be used to reference nested relations, to update them. example:
https://github.com/api-platform/core/blob/master/features/hal/max_depth.feature#L58
summary. having an identifier in the data does not mean it is trying to be updated.
$iri = implode(';', $identifiersData); // TODO: use $this->iriConverter->getIriFromPlainIdentifier() once https://github.com/api-platform/core/pull/1837 got merged. | ||
|
||
try { | ||
$object = $this->iriConverter->getItemFromIri($iri, $context + ['fetch_data' => true]); |
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.
exceptions thrown here should not be caught. the old code did not catch.
{ | ||
try { | ||
$context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getItemFromIri((string) $data['id'], $context + ['fetch_data' => true]); | ||
} catch (InvalidArgumentException $e) { |
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.
this has to be retained, it fixes #857
I have all the tests passing. I'll PR in the morning. |
Closing in favor of #2022. |
This is completely untested but I think it should be enough to outline the plan as described in #1937
Basically this would fix two things:
id
but using theIdentifiersExtractor
instead.Looking for feedback here :-)