Problem/Motivation

I am using entity share module with Media entity and crop API.
Adding crops to media image attached to node in source are not created on client site.

Steps to reproduce

  1. Add crops to media image
  2. Attach media created in step 1 to any node.
  3. Try to import node created in step 2 from any client site.
  4. Node and media will imported successfully on client but not the crops in media image.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Bunty Badgujar created an issue. See original summary.

grimreaper’s picture

Title: Crop derivatives of file image not importing. » Support Crop API
Version: 8.x-3.0-beta4 » 8.x-3.x-dev
Category: Bug report » Feature request

The list of supported field types is on https://www.drupal.org/docs/8/modules/entity-share/supported-field-types.

Currently Entity Share does not explicitly support Crop API, so it is a feature request and not a bug.

maxpah’s picture

Hello Grimreaper,

I have a website who also need this feature. As you must be more comfortable with JSONAPI and entity_share, would it be possible to have the steps to make an entity compatible like Crop and FocalPoint.

I think about these steps :

  1. Create a Normalizer to add the relationship in the endpoint jsonapi/file/file (crop side and focal_point module side ?)
  2. Make an EntityShareCropFocalPointFieldEnhancer if it does not work directly
  3. Any other steps that I don't have in mind at all?

Then I can propose a patch, thanks for your help.

Jsonapi output for crop types

{
   "jsonapi":{
      "version":"1.0",
      "meta":{
         "links":{
            "self":{
               "href":"http://jsonapi.org/format/1.0/"
            }
         }
      }
   },
   "data":[
      {
         "type":"crop_type--crop_type",
         "id":"21e84545-f17a-4020-8c99-99a5d7f87fa5",
         "links":{
            "self":{
               "href":"http://mywebsite.localhost/en/jsonapi/crop_type/crop_type/21e84545-f17a-4020-8c99-99a5d7f87fa5"
            }
         },
         "attributes":{
            "langcode":"en",
            "status":true,
            "dependencies":[
               
            ],
            "drupal_internal__id":"focal_point",
            "label":"Focal point",
            "description":"Crop type used by Focal point module.",
            "aspect_ratio":"",
            "soft_limit_width":null,
            "soft_limit_height":null,
            "hard_limit_width":null,
            "hard_limit_height":null
         }
      }
   ],
   "links":{
      "self":{
         "href":"http://mywebsite.localhost/en/jsonapi/crop_type/crop_type"
      }
   }
}

Jsonapi output for crop focal-point

{
   "jsonapi":{
      "version":"1.0",
      "meta":{
         "links":{
            "self":{
               "href":"http://jsonapi.org/format/1.0/"
            }
         }
      }
   },
   "data":[
      {
         "type":"crop--focal_point",
         "id":"8fe51b61-d86a-4d87-a048-ed3ea9916b77",
         "links":{
            "self":{
               "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point/8fe51b61-d86a-4d87-a048-ed3ea9916b77"
            }
         },
         "attributes":{
            "drupal_internal__cid":1,
            "drupal_internal__vid":1,
            "langcode":"en",
            "entity_id":1,
            "entity_type":"file",
            "uri":"public://2022-04/image-TEST.jpg",
            "height":null,
            "width":null,
            "x":320,
            "y":160,
            "revision_timestamp":"2021-01-07T15:34:09+00:00",
            "revision_log":null,
            "default_langcode":true,
            "revision_translation_affected":true
         },
         "relationships":{
            "crop_type":{
               "data":{
                  "type":"crop_type--crop_type",
                  "id":"21e84545-f17a-4020-8c99-99a5d7f87fa5",
                  "meta":{
                     "drupal_internal__target_id":"focal_point"
                  }
               },
               "links":{
                  "related":{
                     "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point/8fe51b61-d86a-4d87-a048-ed3ea9916b77/crop_type"
                  },
                  "self":{
                     "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point/8fe51b61-d86a-4d87-a048-ed3ea9916b77/relationships/crop_type"
                  }
               }
            },
            "revision_uid":{
               "data":{
                  "type":"user--user",
                  "id":"3244b490-e011-441c-a2ce-8dab0bb63f5b",
                  "meta":{
                     "drupal_internal__target_id":1
                  }
               },
               "links":{
                  "related":{
                     "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point/8fe51b61-d86a-4d87-a048-ed3ea9916b77/revision_uid"
                  },
                  "self":{
                     "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point/8fe51b61-d86a-4d87-a048-ed3ea9916b77/relationships/revision_uid"
                  }
               }
            }
         }
      }
   ],
   "links":{
      "next":{
         "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point?page%5Boffset%5D=1&page%5Blimit%5D=1"
      },
      "self":{
         "href":"http://mywebsite.localhost/en/jsonapi/crop/focal_point?page%5Blimit%5D=1"
      }
   }
}
maxpah’s picture

Hello @Grimreaper,

Is it possible to have input for this feature ?

grimreaper’s picture

Component: Entity share client » Code
Assigned: Unassigned » grimreaper

assigning

grimreaper’s picture

Assigned: grimreaper » Unassigned
Related issues: +#2890651: JSON API integration

Hi,

I finally got time to give a look at this issue.

I confirm this is not a problem related to Entity Share but the Crop API module:

#2890651: JSON API integration

So solution will both work for Focal Point and Manual crop or any kind of crop.

As crop type is a config entity, it should be the same between your client and server website.

As you mentioned the problem is that there is no proper relationship between a crop content entity and the image file entity it is applied on.

And there is also that in the attributes of this content entity, there is "entity_id":1, which is an ID and not an UUID.

I think what could be done as a workaround to automatically import the crop:
1. in the image field output add information of the (or the multiples) crop content entity JSON:API URLs. How?
- With a normalizer like you proposed?
- or maybe like in comment #2890651-14: JSON API integration

I think the place for this is in the Crop API module.

2. add an event subscriber on RelationshipFieldValueEvent or an import plugin processor that will read this or these URLs to import automatically the crop content entity.

But the crop content entity would need to be prepared:
3. create a field enhancer to transform the "entity_id" attributes into a UUID and the opposite in doTransform().

This field enhancer could reside either in Entity Share or in the Crop API module. Maybe better in Crop API.

4. should the uri attributes on crop content entity be ignored or will require special treatment too? will the physical file be regenerated automatically?

I will also ping in the other issue to ask for feedbacks.

pbabin’s picture

We're looking at needing something like this as well. Has anyone been able to successfully do this and can share their code? We're just using crop api with image widget crop. I see in the database all the points that @maxpah and @grimreaper are making so I think we should be able to pass the crop information along; however, I am at a loss of where to start. It doesn't look like there is any traction on the crop api side. So is it advisable to add these modifications into our own module and try the import?

Any guidance to point me in the right direction is greatly appreciated. Entity share is such an amazing tool and our organization is extremely grateful for all that it does!

Thank you in advance.

rishabjasrotia’s picture

Hello @pbabin,
In one of our project we faced similar problem.
The solution was implemented using custom module to bind another extra field which stores the crop positions data.
Once the data is synced we wrote code to use those field value and apply crop to image.

pbabin’s picture

Thank you @grimreaper for linking this issue to #2890651: Crop API - JSON API integration!

I've applied the MR !9 patch from #2890651 and the crops are being brought over with Entity Share! Please note that my setup included a locked policy. With the policy turned on, the crops did not come over. Meaning that entity share registered that there was a crop to bring over, it brought over, however, the values for the crop were not applied. I've converted the policy to create only and the crops come over and are applied correctly.

So much gratitude for this package! Thank you.

prudloff’s picture

I tried the patch from #2890651: JSON API integration and it correctly adds a crop computed field on file API responses.
But it does not seem to be enough. I get this notice and the crop is not imported:

[notice] Error during import. The field crop does not exist.

I suppose entity_share does not know what to do with a computed field?
I guess an enhancer could handle this.

Also the "changed" property of files is not updated when the crop changes, so entity_share_cron will not try to reimport the file when its crop has changed.

blacksnipe’s picture

Status: Active » Reviewed & tested by the community

Hi

I've applied the MR for #2890651: JSON API integration via composer.
After some debugging, the data for focal point and cropping came through.

The patch needs to be applied to both server and client(s) for it to work.
Tested and approved for our case.

Thanks for the contribution everyone!

joachim’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

This is RTBC but I don't see an MR or a patch here.

maxpah’s picture

Hello,

I can confirm, it's works well with patch from #2890651 (crop module)

So, no patch needed in entity_share module.

joachim’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)

Thanks for reporting back!

In that case, I'll close this.

prudloff’s picture

At least part of my problem in #10 was related to this so in case anyone else has the problem : the "administer crop" permission is need to get crop entities from the JSON API.

quentin massez’s picture

Status: Closed (works as designed) » Active

Hello everyone,

I encountered a problem while trying to import my crop "focal_point" using Entity Share and the MR in #2890651.
The crops are imported, but they have the entity_id of the source file ID.

Example:
I have a file (let's say ID = 10) on my source website with a crop at x=100, y=200.
After import, the file is correctly imported on my destination website (with ID = 20), and I get a row in the crop_field_data table that contains: entity_id=10, x=100, y=200.

I believe this issue relates to point 3) in https://www.drupal.org/project/entity_share/issues/3220320#comment-14981040?
I'm not sure how we should handle this.
One workaround could be to update the entity_id of the crop in hook_file_update : this works, but it doesn’t seem like the best solution.

Maybe there's something specific in my setup, since it looks like you're not encountering this issue?

joachim’s picture

> the "administer crop" permission is need to get crop entities from the JSON API.

That's pretty bad for security! User accounts which are used by APIs should have permissions which are as limited as possible.

If there's a patch for adding a 'view' permission for crop entities, we can recommend it in the README here, as we already do for some other entity types.

pbabin’s picture

I've submitted a related merge request to the Crop API module that should help address part of the problem discussed here.

🔗 JSON API integration

The patch introduces a “view only” permission, an access controller, and updates to expose certain Crop entity fields to JSON:API.

It also updates the parent entity timestamp whenever a crop changes — this allows tools like Entity Share to detect and re-import those updates. In testing, this timestamp change was the only reliable way to ensure re-syncing of modified crops.

This behavior and and an additional required hook are further detailed in a related inquiry here: Crop API - Crop Updates and Entity Share.

I’m continuing to refine the approach and welcome any feedback from maintainers or others working on Entity Share integration.