We are building a "content_synchronisation" module that allows you to synchronise content entities between sites through a custom REST resource. On the content provider side we serialize a node, send it over to the content consumer website by REST POST/PATCH, where we deserialize the incoming data. Since each site can have different number of nodes, we can't rely on the node id being the same on both websites, thus we synchronise everything based on uuid.

This is working ok with the help of some custom code after we deserialise the data. Today I also patched core with this fix #2827164, which now allows me to add my own normalizer for file items. In the patch I saw that EntityReferenceFieldItemNormalizer now looks up the entity by uuid and sets the target_id.

So to get to my question, is this also something that could be done on the entity level deserialisation. So that when denormalizing an entity, the entity id is replaced by looking the entity up using the uuid. We now do this in custom code after we call deserialize on the create entity object, but would be nice if core already did this and seems more logical.

Willing to try this and create a patch, but wanted to check first if this might be a good idea, and second this code would go in EntityNormaliser right ?

Comments

kriboogh created an issue. See original summary.

Wim Leers’s picture

Status: Active » Fixed

I'm pretty certain this is a duplicate of #2827164: Entity reference field normalization has target_type and target_uuid, but not used in denormalization, which is RTBC :) Please test that patch and if it doesn't solve your problem, please reopen this issue!

kriboogh’s picture

Status: Fixed » Active

Thanks wim, yes i had that patch applied already.

What I wanted to ask, was if the object being created by the deserializer, if the nid can be updated to the nid of the receiving site. If a node on site A has nid=1, and uuid=xx, we serialise it to json, and push it over REST/POST to site B. In the receiver site B, we deserialise the incoming data array, but there the resulting node that is created, gets nid=1, which we reset to null, so we can save the node on site B. On site B the node has nid=100 and uuid=xx.
When we update the node with nid=1 on site A, we push it over REST/PATCH to site B. In this case it would be nice, when we deserialise the incoming data array, to have the created node object have the nid=100 and not nid=1.

I applied that patch, which doens't address the issue above. With that patch though, we saw another problem with reference fields. When a serialised entity from site A is being imported in site B, the user id being looked up by the reference field item denormalizer on B can't find the user using the uuid. This user doesn't exist on site B. So I get an error when $entity->id() is called, since $entity is null.

I'm trying to write my own normalizers that hook into this, so the id can be replaced with for example user 1. But can't seem to manage to replace the normalizer for this. We also needed a solution for importing files, which are transfered by url only. I saw that the HAL denormalizer deals with this by downloading the file from the url, but I want to avoid depending on HAL. Than about 10 min ago I also read something about JSONAPI being better since they plan on using uuid and not ids, so maybe this might help us or maybe make our solution to sync content between sites obsolete all together.

Wim Leers’s picture

Status: Active » Postponed (maintainer needs more info)

With that patch applied, as long as A and B have the same UUIDs for the same node, that should work. Of course, that patch only fixes it for referenced entities, you're talking about the sent entity itself. For that, you'll need https://www.drupal.org/project/relaxed.

You say it fails for user references because the user doesn't exist on site B. That's why you should also sync users, and they should be synced first.

Also see https://www.drupal.org/project/default_content and especially https://www.drupal.org/project/entity_pilot — that one solves exactly your use case.

Wim Leers’s picture

Status: Postponed (maintainer needs more info) » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.