Track composite (e.g. paragraph) entities directly and only as their host

Created on 25 September 2018, over 6 years ago
Updated 16 April 2025, 11 days ago

Problem/Motivation

Tracking paragraphs is really hard, a big reason for that is the bad stale paragraph management of the ERR/paragraphs module (which is hard to get right).

The module currently tracks each paragraph entity on its own and then at runtime when building the usage list, tries to find the parent and display it as a hierarchy based on the fields.

Proposed resolution

This is just a rough idea right now, but might be worth to explore. Instead of tracking paragraphs that are being saved directly, the module would only track the entities that have those paragraphs attached, e.g. nodes and paragraph library items. It would detect ERR fields pointing to paragraphs and transparently include anything those paragraphs are using and attribute it to the host entity.

We currently are doing something like that simply to figure out all the media entities referenced by a node and it would be way simpler if we could just look for usages of that node directly.

We would lose the hierarchy information but I'd say that is not very useful anyway. In turn, if a paragraphs is no longer used on a node, it would simply no longer be counted as nothing would be saved that references it.

Remaining tasks

User interface changes

API changes

It might require some API changes as \Drupal\entity_usage\EntityUpdateManager::trackUpdateOnEdition() and so on would need a way to tell plugins on what the usage should be reported.

Looking at that, it does seem rather inefficient right now, each usage does its own merge query + event, that's pretty heavy. If you're building large sites with a lot of paragraphs, I imagine there can quickly be a considerable amount of target entities being involved.

Maybe there could be something like an EntityUsages value object where the plugins could add usages to, and then that could do an optimized bulk update similar to how field saving works (delete all rows for a specific source, then do a single multi-insert query) and also a single event on all those usages.

As a side effect of that, EntityUpdateManager would then have full control over what those usages are reported on and e.g. pass in N referenced paragraph entities and track everything on a single EntityUsages object.

Data model changes

📌 Task
Status

Active

Version

2.0

Component

Code

Created by

🇨🇭Switzerland berdir Switzerland

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

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • First commit to issue fork.
  • Merge request !136Resolve #3002332 "Track paragraphs on host" → (Open) created by rp7
  • Pipeline finished with Failed
    4 days ago
    Total: 351s
    #480051
  • Pipeline finished with Failed
    3 days ago
    Total: 259s
    #481073
  • Pipeline finished with Failed
    3 days ago
    Total: 344s
    #481105
  • Pipeline finished with Failed
    3 days ago
    Total: 230s
    #481112
  • Pipeline finished with Failed
    3 days ago
    Total: 267s
    #481123
  • Pipeline finished with Failed
    3 days ago
    Total: 212s
    #481125
  • 🇧🇪Belgium rp7

    I've been taking a stab at this, trying to stay within the constraints of the 2.x version of this module. Not the finished product yet (some tests are failing - not yet sure why), but this is my progress so far.

    The route I went is creating a new @EntityUsageTrack plugin (paragraph_inherited) that goes through all the paragraphs a (host) entity references and tracks those references on the host entity itself.

    We would lose the hierarchy information but I'd say that is not very useful anyway.

    Well, actually it is for the editors on the project that I'm working on. They have pages with quite a complex nested paragraph structure. It helps them tremendously to immediately see in which nested paragraph the entity is referenced. This is the reason I expanded the field_name column so that it contains all the fields of the paragraph chain. It adds quite some complexity though, I'll give you that.

    Not battle-tested just yet, but our initial internal tests look good. We have custom logic in various places that uses entity usage information, and no longer having to deal with intermediary paragraphs makes things less complex.

    Insights & help always welcome.

Production build 0.71.5 2024