Hello,

As the issue in core #2353611: Make it possible to link to an entity by UUID to allow the use of UUID for link field seems hard to move forward, I am trying to alter the JSON API behavior to have UUID in the output of link field.

My goal is to be able to share content across websites using https://www.drupal.org/project/entity_share, and link fields with internal link are not handled.

I am creating a field enhancer for that. I will upload a patch. Now the output of link fields has UUID.

But I just think that maybe it won't help me in the deserialization of the data...

In any case I will upload a patch to share my work.

And big thanks for this module. Looks awesome.

Members fund testing for the Drupal project. Drupal Association Learn more

Comments

Grimreaper created an issue. See original summary.

Grimreaper’s picture

Assigned: Grimreaper » Unassigned
Status: Active » Needs review
FileSize
4.03 KB

Here is the patch.

Thanks for the review.

Grimreaper’s picture

Here is an updated patch with the implementation of the prepareForInput method. I didn't get the meaning of this method in the first time. After reading #2874309: Apply enhancers for the data coming into the server I got it :).

So now with that if I have the field enhancer of both websites, I can share the value of internal links between sites using https://www.drupal.org/project/entity_share

That would be better to be able to store an UUID in the field value (with the core issue) because if a referenced entity has not been imported yet, I unset the value so the content would have to be reimported to update the field value.

But that's a workaround while the core issue is open.

e0ipso’s picture

Thanks for the patch @Grimreaper! This feels close. Just some minor thoughts.


  1. +++ b/src/Plugin/ResourceFieldEnhancerBase.php
    @@ -26,6 +26,13 @@ abstract class ResourceFieldEnhancerBase extends PluginBase implements ResourceF
    +  public function defaultConfiguration() {
    
    @@ -43,9 +50,30 @@ abstract class ResourceFieldEnhancerBase extends PluginBase implements ResourceF
    +  public function postProcess($value) {
    ...
    +  public function prepareForInput($value) {
    ...
    +  public function getSettingsForm(array $resource_field_info) {
    

    Let's leave these default implementations out of the patch. The base class is abstract so you are forced to implement them.

  2. +++ b/src/Plugin/jsonapi/FieldEnhancer/LinkFieldEnhancer.php
    @@ -0,0 +1,100 @@
    + *   id = "link_field",
    

    Maybe: uuid_link

  3. +++ b/src/Plugin/jsonapi/FieldEnhancer/LinkFieldEnhancer.php
    @@ -0,0 +1,100 @@
    + *   label = @Translation("Link field"),
    

    Maybe "Link by UUID"?

  4. +++ b/src/Plugin/jsonapi/FieldEnhancer/LinkFieldEnhancer.php
    @@ -0,0 +1,100 @@
    +        $value['uri'] = 'entity:' . $entity_type . '/' . $entity->uuid();
    

    What if we add the bundle here as well. We would have something like:

    entity://node/article/12345-1234-3456

  5. +++ b/src/Plugin/jsonapi/FieldEnhancer/LinkFieldEnhancer.php
    @@ -0,0 +1,100 @@
    +  public function getJsonSchema() {
    +    return [
    +      'type' => 'array',
    +    ];
    +  }
    

    Unless I'm missing something, the schema seems wrong.

e0ipso’s picture

Status: Needs review » Needs work
Grimreaper’s picture

Status: Needs work » Needs review
FileSize
4.44 KB

Hello @e0ipso,

Thanks for the review. Here is an updated patch.

  1. Agreed for "the postProcess" and the "prepareForInput" methods but for plugins that do not have configuration such as this one, I think it is not to those modules to have empty methods but to the base plugin.
  2. Done
  3. Done: UUID for link
  4. If you want, I wanted to follow the way Core stores data. But yeah, if we had the bundle it would be usable in JSON API, not only for data transfer as with my usage. So let's add that? If yes, do you want me to update the patch?
  5. I don't know how to check the schema for that and the two existing plugins return "string" bu a link field value is an array with uri, title,
    options. So I don't know what to put.
e0ipso’s picture

Status: Needs review » Needs work

Thanks for the patch!

  1. I'm OK with leaving default config in. No strong feelings either way.
  2. yay
  3. great
  4. Let's go the convenient route since this is an override anyways. Let's add the bundle in.
  5. Then you probably want 'object'.
Grimreaper’s picture

Status: Needs work » Needs review
FileSize
4.47 KB

Hello @e0ipso,

Here is an updated patch with the last review taken into account.

Thanks for the review.

e0ipso’s picture

Status: Needs review » Needs work

Sorry I missed this before.


+++ b/src/Plugin/jsonapi/FieldEnhancer/UuidLinkEnhancer.php
@@ -0,0 +1,100 @@
+        $entity = $this->entityTypeManager->getStorage($entity_type)->load($entity_id);

What happens if the linked entity has not been created yet, deleted or the current user doesn't have view permissions to it?

Should we return the initial link then? Maybe return NULL? If we return the initial link then the API contains links in different formats.

+++ b/src/Plugin/jsonapi/FieldEnhancer/UuidLinkEnhancer.php
@@ -0,0 +1,100 @@
+ *   description = @Translation("Use UUID for internal link field.")

Please add a note that this enhancer only be applied to Link fields.

Grimreaper’s picture

Good catch.

Hum, I think we should return the initial value for consistency with Core behavior. By default Core displays the link value even if it will lead to a 404.

And so in the "prepareForInput" method if the uri is like entity:[entity_type]/[id], it would be a "wrong" value and it would be unsetted.

I am not very happy with this solution but for my use case of sharing entities, if I do not unset a "wrong" value, there is a risk that a shared entity will reference an existing content which is not the content referenced by the original website.

The ideal world would be that the core issue would be fixed to avoid to have to do this workaround.

Are you ok with this proposition?

I will add " (link field only)" in the label of the plugin because the plugin's description does not seem to be used. Will do it on the next patch.

Grimreaper’s picture

Status: Needs work » Needs review
FileSize
4.71 KB
1.28 KB

Hello,

Sorry about the delay.

Here is an updated patch.

Thanks for the review.

e0ipso’s picture

Status: Needs review » Fixed

@Grimreaper I am embarrassed that this fell off my radar. I will commit this now.

  • e0ipso committed 6ba06da on 8.x-1.x authored by Grimreaper
    feat(FieldEnhancer): Transform link field value to use UUID (#2883437 by...
Grimreaper’s picture

@e0ipso no problem. Thanks for the commit :)

Status: Fixed » Closed (fixed)

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