Support embedded paragraphs

Created on 6 February 2025, 16 days ago

Problem/Motivation

Paragraphs added to text fields using the Paragraphs Entity Embed module are considered orphans because the tag is ignored. Need a tracking mechanism to connect the paragraphs to the embedded paragraphs entity and that entity to it's source.

Steps to reproduce

Install module, config text editor to use it, add an embedded paragraph with something like a media item. Then look at the media item usage. Will only indicate it was used by an unlinked paragraph.

Proposed resolution

  • Add an entity tracker based on the embedded entities tracker to handle the drupal-paragraphs tag.
  • Modify usage code to handle finding and displaying the first 'linkable' source in the source hierarchy

Remaining tasks

Patch attached

User interface changes

New tracker plugin listed. Better usage info for items used in paragraph structures. E.G., page has embedded paragraph uses an accordion paragraph which uses an accordion item paragraph that has an image. Image usage shows the page with link to it.

API changes

None

Data model changes

None

✨ Feature request
Status

Active

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States cgmonroe

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @cgmonroe
  • πŸ‡ΊπŸ‡ΈUnited States cgmonroe

    Patch for issue

  • πŸ‡ΊπŸ‡ΈUnited States cgmonroe
  • πŸ‡¬πŸ‡§United Kingdom alexpott πŸ‡ͺπŸ‡ΊπŸŒ
    1. +++ b/src/Plugin/EntityUsage/Track/ParagraphsEntityEmbed.php
      @@ -0,0 +1,63 @@
      +  public function parseEntitiesFromText($text) {
      +    $dom = Html::load($text);
      

      Before you do any parsing here you should check that embedded_paragraphs are in the target entity types.

    2. +++ b/src/Plugin/EntityUsage/Track/ParagraphsEntityEmbed.php
      @@ -0,0 +1,63 @@
      +      $embeddedPara = $this->entityTypeManager
      +        ->getStorage('embedded_paragraphs')
      +        ->loadByProperties(['uuid' => $node->getAttribute('data-paragraph-id')]);
      +      if (empty($embeddedPara)) {
      +        return [];
      +      }
      +      /** @var \Drupal\paragraphs_entity_embed\Entity\EmbeddedParagraphs $embeddedPara */
      +      $embeddedPara = reset($embeddedPara);
      +      $para = $embeddedPara->getParagraph();
      +      if (empty($para)) {
      +        return [];
      +      }
      

      It'd be great if we can do this without loading entities. Perhaps we can use an aggregate entity query here to get the embedded paragraph ID. For an example aggregate query see \Drupal\content_moderation\ModeratedNodeListBuilder::getEntityRevisionIds

    3. +++ b/src/Plugin/EntityUsage/Track/ParagraphsEntityEmbed.php
      @@ -0,0 +1,63 @@
      +      // Add tracking for internal paragraph target being used by the embedded paragraph.
      +      $this->usageService->registerUsage($para->id(), 'paragraph', $embeddedPara->getId(), 'embedded_paragraphs', $embeddedPara->language()->getId(), $embeddedPara->getRevisionId(), $this->pluginId, 'paragraph_target_id');
      

      Here we need to check if embedded_paragraphs are in the source types I think

  • πŸ‡ΊπŸ‡ΈUnited States cgmonroe

    Here's a version that solves these concerns:

    1. & 3. - The tracker now checks that embedded_paragraphs can be used as sources and that paragraphs can be targets. If not true, no tracking occurs and a logger message is output once per instance.

    In addition, the settings form now has a validation that will not let this tracker be selected unless emebedded_paras is an allowed source and paras are an allowed target. Message also suggests they should be target/sources too.

    Also, the tracker plugin is disabled unless the paragraphs_entity_embed provider module is enabled. (provider annotation)

    2. - The required info is retrieved via 2 queries now instead of loading entities.

  • πŸ‡ΊπŸ‡ΈUnited States cgmonroe

    Changing title to reflect that the attached patch also improves tracking paragraphs back to the 'linkable' source (e.g. node, etc.) and not just the parent item. This is independent of if embedded paragraphs are used.

  • πŸ‡ͺπŸ‡ΈSpain marcoscano Barcelona, Spain

    Thank you for filing this and for contributing.
    I am very reluctant to add more code and special-cases to the list controller, which is already somewhat messy code special-casing paragraphs and blocks.
    I'd rather we can wait until ✨ Issue Event for Row Rendering Active lands, then other modules can alter the list in any way they want.
    Along these lines, I also believe the new plugin and settings form validation code should be part of the "Paragraphs entity embed" contrib module, how about we move this ticket into their issue queue?

Production build 0.71.5 2024