Field [storage] config have incomplete settings until they are saved

Created on 26 August 2014, almost 10 years ago
Updated 19 June 2024, 4 days ago

From #2320253-10: FIC/FSC::preSave() do not call the parent implementation :

not sure why we initialize default settings in preSave(), this leaves freshly created entities broken for runtime use (incomplete settings) until they are actually saved. We should do this as early as postCreate().

Similarly, FieldStorageConfig::$module is currently only populated in preSave(), meaning the entity is not reliable until that point. This should be done also in postCreate().

How did we end up with the current approach after several rounds of back and forth?

Entity reference fields -- that is, any field type based on \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem -- need special handling. They have a setting called handler, which normally has a value of default that needs to be changed to something like default:taxonomy_term, depending on what kind of entities are being referenced, just before the field is saved. In HEAD, this is done on pre-save by the field module (field_field_config_presave()). This is also necessary for certain Entity Reference-based contrib modules, like Dynamic Entity Reference, to work properly.

BUT! If we want to make sure the settings are always complete and coherent, then we need to be able to do this normalization continuously, whenever field settings change, regardless of whether the field's been saved or not.

So, how to do that? A few approaches were tried, and it was a twisty, turny road:

  • Initially, we thought it should be a special method of \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem, which the field config entity calls whenever settings are changed.
  • But that seemed icky and poorly encapsulated, so we moved it to a new method of \Drupal\Core\Field\FieldItemInterface, thinking that the API addition was justified.
  • But then we thought we could just repurpose that interface's existing fieldSettingsToConfigData() method for this purpose, but it turned out that was mismatched to our needs.
  • So we decided we'd add a new method to FieldItemInterface after all.
  • But then it was pointed out that we don't really need new API -- we could just do the normalization in field_field_config_create(), since field entities are now created with complete, coherent settings.
  • After all of this, it was pointed out that none of the runtime config entities are actually valid because you would need to run \Drupal\Core\Config\Entity\ConfigEntityStorage::mapToStorageRecord before they become valid. This is currently only run on save.

So that's where we ended up: when an entity reference field is created (with complete settings, now), those settings get normalized. Then they get normalized again when the field is saved. No new API surface! At least, not now.

We still may need new API to ensure that the settings are always normalized even if they undergo multiple changes (before saving). But, if that's necessary, let's do it in 📌 Combine field storage and field instance forms Fixed and/or 📌 Save FieldStorageConfig at the same time as FieldConfig Fixed , in which we'll be figuring out just how, where, and when a field's settings can be changed as it gets built in the UI by a site builder.

What about base field overrides, I hear you asking? Well...those already don't get normalized in HEAD, because field_field_config_presave() (which, remember, normalizes the field's settings) only acts on...field_config entities. Not base_field_override entities. So sure, it should be fixed, but it's not in scope here.

But...but...doing special normalization only for particular field type plugin classes sucks and is restrictive, you say. Yup, that's true. It should probably be applied to particular kinds of field types (for example, perhaps it could be done for anything in the reference category). But that's also not in scope here.

Basically: this thing we're doing, where we're implementing entity hooks for field_config entities, is a temporary measure. It gets us past the current, specific problem of having incomplete settings, and puts us in a position to add a well-designed, properly scoped API in place for continuous settings normalization in other issues, where it will become more relevant. Hook implementations aren't API, so we can easily remove them.

🐛 Bug report
Status

Fixed

Version

11.0 🔥

Component
Field 

Last updated about 18 hours ago

Created by

🇫🇷France yched

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.

Production build 0.69.0 2024