Remove orphan components in EntityDisplay* config entity on save?

Created on 22 August 2017, over 7 years ago
Updated 24 April 2024, 8 months ago

Problem/Motivation

I found that components from e.g. hook_entity_extra_field_info() are not removed after the extra field is gone.

(part of this issue text is copied from https://drupal.stackexchange.com/questions/244305/how-to-clean-up-leftov...)

Technical observations

The entries, for both regular fields and extra fields, are stored in EntityDisplayBase::$content.

In the schema, defined in core.entity.schema.yml, we find

core.entity_view_display.*.*.*:
  ..
  mapping:
    ..
    content:
      type: sequence

Once an entry is saved there, it stays until something calls $display->removeComponent($name), and saves the display afterwards.
For this, the caller needs to know the name to remove.
I did not find any operation that would remove all unknown components.

Steps to reproduce

(This is the easiest to reproduce, but a bit artificial)

  1. (Install Drupal with standard profile, export configuration to `./config/sync/`.)
  2. Edit `config/sync/core.entity_view_display.node.article.default.yml`. Insert a new field display entry, name it 'zzz', and copy the display settings from 'body'.
  3. Import the modified config (drush cim)
  4. Visit `/admin/structure/types/manage/article/form-display`. Optionally change display settings for some fields. Save the form.
  5. Export the config (drush cex)

Expected behavior: The entry for 'zzz' gets removed.
Actual behavior: The entry for 'zzz' stays in the display.

  1. Download https://drupal.org/project/extra_field (I tried 8.x-1.0-alpha2). (The question is not about this module, it is just a useful example)
  2. Enable extra_field and extra_field_example modules.
  3. Visit admin/structure/types/manage/article/display, position the extra fields from the module, and click "Save".
  4. Uninstall extra_field and extra_field_example modules.
  5. Visit again admin/structure/types/manage/article/display, click "Save".
  6. Implement hook_node_view() in a custom module somewhere, and dpm($display->getComponents()) (using devel, obviously). Rebuild the cache to discover the hook. Visit a page where an article node is displayed.

Expected behavior: The components from the extra fields from extra_field_example should be gone now.

Actual behavior: The components still contain the keys from extra_field_example. E.g. "extra_field_all_nodes".

  1. Declare base fields for an entity type. Either by using a hook, or by changing the entity type definition directly.
  2. Place the base fields in a view or form display. Save.
  3. Remove the base fields, by removing the respective code.
  4. Open the display form, and save it.
  5. Use `drush cex`, or core config module, or the devel `dpm($display->getComponents())` as above, to inspect the configuration.

Expected behavior: The display components from the removed base fields are gone.

Actual behavior: The display components from the removed base fields are still present in the display configuration.

Proposed resolution

One opportunity to remove the orphan entries would be in EntityDisplayFormBase::submitForm().
More specifically, in EntityDisplayFormBase::copyFormValuesToEntity().

Maybe there could be a message and a checkbox in the field_ui form:
"Orphan entries were detected. Remove orphan entries on form submit?"

Another opportunity would be during cron, perhaps.

If not, there should at least be documentation for a module developer how to clean those entries.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

🐛 Bug report
Status

Active

Version

11.0 🔥

Component
Entity 

Last updated about 16 hours ago

Created by

🇩🇪Germany donquixote

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

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.
  • 🇩🇪Germany donquixote

    I notice this also happens with entity base fields.

    I had the following scenario:
    - I worked on a feature that adds a new custom entity type.
    - I add base fields.
    - I exported the view and form display.
    - Now I add entity bundles and replace the base fields with field UI fields.
    - I export the view and form display again.

    Expected: Base fields are removed from form and view display.
    Actual: Base fields remain in the form and view display, even after re-saving the form or view config.

  • 🇩🇪Germany donquixote

    Adding two more scenarios:
    - One that is very easy to reproduce.
    - One that is explicitly about base fields.

  • 🇩🇪Germany donquixote

    I think we should do housekeeping in the following situations:
    - When the entity view or form display form is submitted.
    - As a separate command (e.g. drush) or on a dedicated page to do this kind of clean-up.

    I don't think we can rely only on specific events.
    E.g. when we change the code of a custom module, no event will fire. Especially if we start with an older database dump that knows nothing about fields that were previously added.

Production build 0.71.5 2024