UUID does not support translating the local IDs of entities embedded in filtered text fields. E.g., files embedded via the Media module, nodes embedded via node_embed, etc.

The UUID Link module provides a method for linking to content, but it does not replicate the functionality of Media module and other projects that embed content in filtered text fields.

To facilitate the deployment of filtered text fields with embedded entity tokens, I propose implementing hook_field_uuid_load() and hook_field_uuid_presave() for the core "text" field module in uuid.core.inc. i.e.,

  text_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items)
  text_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items)

On their own, these hook implementations can not translate the embedded local entity IDs, because they don't know enough about the filtered text tokens of the projects that created them. Therefore, I propose two new hooks to allow projects to translate their embedded entity tokens from local ID to UUID. e.g.,

  hook_filtered_text_uuid_load_alter(&$text)
  hook_filtered_text_uuid_presave_alter(&$text)


If this approach and the following pseudo-code looks reasonable to the community/maintainers, I'll move forward with a patch.


PRE-DEPLOY: Replace filtered texts' entity token local IDs with UUIDs.
text_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items)
  if instance is filtered text,
  then foreach $items
    drupal_alter "hook_filtered_text_uuid_load_alter(&$text)"
    hook implementation by input filter modules (media, node_embed, custom, etc.):
    - regex to find their token in $text
    - filter-specific logic to parse local ID from token
    - lookup UUID from local ID
    - make new token with UUID instead of local ID
    - str_replace old token with new token



POST-DEPLOY: Replace filtered texts' entity token UUIDs with local IDs.
text_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items)
  if instance is filtered text,
  then foreach $items
    drupal_alter "hook_filtered_text_uuid_presave_alter(&$text)"
    hook implementation by input filter modules (media, node_embed, custom, etc.):
    - regex to find their token in $text
    - filter-specific logic to parse local ID from token
    - lookup local ID from UUID
    - make new token with local ID instead of UUID
    - str_replace old token with new token
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

hawkeye.twolf’s picture

Issue summary: View changes
hawkeye.twolf’s picture

dixon_’s picture

This is very interesting and something I'd be willing to commit.

Do you mean that the text implementation would fire hook_filtered_text_uuid_load_alter() inside text_field_uuid_load() and hook_filtered_text_uuid_presave_alter inside text_field_uuid_load()?
That sounds reasonable to me. Do I understand you correct if the use case for this is that ones custom project then can implement these and translate stuff embedded in the text?

I think though that the hook name should be hook_text_field_uuid_load/presave() since it's coming from the text field module.

hawkeye.twolf’s picture

Hiya, dixon! Yes, that's it exactly: text_field_uuid_load() and _presave() will call the new hooks to let each implementing module (media, node_embed, custom, etc.) modify the filtered text as needed.

Good idea on the hook name; hook_text_field_uuid_load_alter() and _presave_alter() is a better choice.

I have some client work depending on this, so I'll probably have a patch for review by the end of the week.

skwashd’s picture

I've already commented on #2137811: Add support for core field module "text". We solved this problem with the embed_asset_field module.

hawkeye.twolf’s picture

Hiya, skwashd! Wow, I had no idea about embed_assets_field. Thanks for pointing it out!

I think I mostly understand how it works, but I have two questions about it:

  1. What's the reason for the separate field to hold the embedded assets? Is it to prevent the delay of reverse-lookups in the filter processor?
  2. I ran into one problem with the Media implementation: It worked when the assets field is of the same bundle as the embedded asset, but if I tried embedding an image when my asset field was a file, the db columns didn't match up. I guess I'd have to extend your Media implementation to add support per bundle?

I'm wondering if my proposed solution would still be a good contribution to UUID and Entity Dependency modules as a somewhat simpler method for handling the issue. The benefits I see are:

  • Doesn't require adding container fields.
  • Doesn't affect the token as it lives in the local system - only during UUID load and presave (pre-/post-deploy).
  • Doesn't require additional input filters (performance).
  • Follows the UUID/Entity Dependency paradigm for implementing support of core field modules.

Since you've obviously dived into this problem before, do you see any inherent flaws in my solution?

Thanks, I appreciate your feedback!

hawkeye.twolf’s picture

Added related issue from the Media module.

hawkeye.twolf’s picture

hawkeye.twolf’s picture

Status: Active » Needs review
hawkeye.twolf’s picture

*bump* Does anyone have some time to review this work? It's work out very elegantly for me and will be in the wild soon.

skwashd’s picture

Status: Needs review » Needs work

@derek.deraps,

Overall this looks good. I like that it is configurable. We need to alter the field configuration form to include the option. I think that $instance['settings']['text_processing'] should be 'uuid_text_processing' to indicate where it comes from. We should also make it clear in the help text that this needs to enabled on both sides.

hawkeye.twolf’s picture

Is there any momentum behind and/or need for this approach? If other folks dig it / want it, I'm happy to fix up the patch as @skwashd asked. Otherwise, I think we can just put this issue to bed ;)