Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
When creating a new entity from jsonapi data the relationships are not handled:
public static function createFromPrimaryData(ResourceType $resource_type, array $primary_data) {
$id = $primary_data['id'] ?? \Drupal::service('uuid')->generate();
$fields = array_merge(
$primary_data['attributes'] ?? [],
// @todo: handle relationships.
[]
);
return new static(new CacheableMetadata(), $resource_type, $id, NULL, $fields, new LinkCollection([]));
}
Comment | File | Size | Author |
---|---|---|---|
#19 | 3096734-interdiff-14_19.txt | 7.42 KB | sam711 |
#19 | 3096734-handle_relationships-19.patch | 15.23 KB | sam711 |
#14 | 3096734-interdiff-6_14.txt | 6.9 KB | sam711 |
#14 | 3096734-handle_relationships-14.patch | 15.32 KB | sam711 |
#13 | 3096734-interdiff-6_13.txt | 6.91 KB | sam711 |
Comments
Comment #2
sam711 CreditAttribution: sam711 as a volunteer commentedHere's my first attempt to solve this which is roughly working for me.
I've basically stolen code from Drupal\jsonapi\Normalizer\JsonApiDocumentTopLevelNormalizer, which I think makes a lot of sense here.
I'm also using the
jsonapi.resource_type.repository
service, which probably shouldn't, but it was already used by this module :)One thing that is missing, is the access check on the referenced entities and attribute fields.
I assume the create access check for the primary entity is handled on the route.
Comment #3
sam711 CreditAttribution: sam711 as a volunteer commentedFixing coding standards.
Field access is checked in the
EntityValidationTrait
so ignore that part.Comment #4
sam711 CreditAttribution: sam711 as a volunteer commentedComment #5
sam711 CreditAttribution: sam711 as a volunteer commentedComment #6
sam711 CreditAttribution: sam711 as a volunteer commentedComment #7
Wim LeersNice work, @sam711!
The key thing that's missing here, is test coverage.
This is exactly like
\Drupal\jsonapi\Normalizer\JsonApiDocumentTopLevelNormalizer::denormalize()
!Therefore … this is also related to and would benefit from #3017295: Refactor/clean up JsonApiDocumentTopLevelNormalizer::denormalize() and EntityNormalizer::denormalize().
Pinging @gabesullice.
🥳
Comment #8
sam711 CreditAttribution: sam711 as a volunteer commentedThanks for the review @WimLeers.
I'll add tests for POST
and PATCH(forgot that PATCH is not supported).Comment #9
Wim LeersSuperb, thank you so much! 😃 🙏
Comment #10
sam711 CreditAttribution: sam711 as a volunteer commentedAddComment Resource Test added. 🤞🏻
Comment #11
sam711 CreditAttribution: sam711 as a volunteer commentedComment #12
sam711 CreditAttribution: sam711 as a volunteer commentedComment #13
sam711 CreditAttribution: sam711 as a volunteer commentedSorry about that. The patch should now have all the files.
Comment #14
sam711 CreditAttribution: sam711 as a volunteer commentedComment #15
sam711 CreditAttribution: sam711 as a volunteer commentedComment #16
mglamanWill review :) The changes in #3104972: Move extracting documents from request objects to a service would cause a lot of disruption on this patch (everything moves to a new file.) So it would be easier to review and get this landed first.
Comment #17
mglamanIt looks like we only ever use $data['data']. Perhaps we should only pass the document data? handleRelationships shouldn't need anything else from the top level document.
There's a lot of logic happening in this closure. Should we move to a regular foreach()?
What if another delta is malformed? Would this catch it?
I don't think we'd ever have a nil reference item value to require an array filter
Relationships should always be an array if it values is determined from an array map
Here's my initial review. Not enough to warrant "Needs work", but general thoughts.
Comment #18
sam711 CreditAttribution: sam711 as a volunteer commentedThanks @mglaman! I'll take a look a bit later today.
Comment #19
sam711 CreditAttribution: sam711 as a volunteer commentedInterdiff looks long just because I removed the surrounding
if (!empty($data['data']['relationships']))
and the indentation changed.1. Done as you suggest. We could even just pass the relationship...
2. Done.
3.
$relationship['data'][0]['type']
is used for all the deltas, so at least the ['id'] of this delta has to exist too. All the delta ids are validated later or ignored if the 'id' doesn't exist.I wonder if different delta types on the same field should be supported.
4.Done
5.That was there because
if (!empty($data['data']['relationships']))
could be false. But I've moved this check to the caller so the relationships is not always added to the primary_data.If
$data['data']['relationships']
is set but empty, the result will be an empty array.Comment #20
mglamanThanks @sam711! I'll eyeball it in full later today. But it looks great, we have tests written and I think anything else can be discovered in follow ups.
Comment #21
sam711 CreditAttribution: sam711 as a volunteer commentedComment #22
mglamanI totally missed this before, which is how we get all of the IDs for the relationships.
nit on commit, probably move to sprintf
Hm. Actually, if we don't need the entity manager for anything but this, we could just inject the entity_repository which has loadByUuid.
Comment #23
mglamanOh duh, we need to load multiple.
Comment #24
mglamanComment #25
mglamanMaking sure to credit @Wim Leers
Comment #26
mglamanWoo! Thank you @sam711!
Comment #28
sam711 CreditAttribution: sam711 as a volunteer commented🎉 Thank you both!
Comment #29
sam711 CreditAttribution: sam711 as a volunteer commentedComment #30
Wim LeersDon't the changes in #19 mean that #7.1 is no longer true, and hence #3017295: Refactor/clean up JsonApiDocumentTopLevelNormalizer::denormalize() and EntityNormalizer::denormalize() just became more difficult? 🤔
Comment #31
sam711 CreditAttribution: sam711 as a volunteer commentedWell, I initially thought so but the code is still pretty much the same (although not exactly the same).
I was hoping we can start implementing in JSON:API Resources at least some of the improvements implied in #3017295: Refactor/clean up JsonApiDocumentTopLevelNormalizer::denormalize() and EntityNormalizer::denormalize(). I'm assuming it'll be easier to do it in contrib and may be even convenient.
This code is going to the DocumentExtractor service #3104972: Move extracting documents from request objects to a service that could be considered as one of these improvements, and might need to be refactored there anyway.