Spin off from
#2015697: Convert field type to typed data plugin for file and image modules →
.
[disclaimer: I personally don't think that's a big issue, but opened this at the request of @claudiu.cristea :-)]
Context
FieldDefinitionInterface, introduced in
#1950632: Create a FieldDefinitionInterface and use it for formatters and widgets →
, merges the notion of field-level & instance-level settings into one single set of 'settings', because:
a) only "configurable fields" have a notion of 'instances', base fields have a single 'field" definition structure
b) 95% client code doesn't care where the setting comes from, they just need the setting value for the current field definition structure they work with.
c) this works transparently for code that only has a $field structure to work with and no $instance (i.e. code that works at a cross-bundles level, e.g. Views, some parts of Entity_ref).
Then there is the (rare) case where a field type uses a setting with the same name at both levels - Image fields currently build on this for their 'default_image' setting.
- It was decided in
#1950632: Create a FieldDefinitionInterface and use it for formatters and widgets →
that one level would take precedence over the other.
-
#2060003: Wrong precedence in Field::getFieldSetting[s]() when setting appears in both field and instance →
fixed FieldInstance::getFieldSetting[s]() so that the order is "instance wins over field" instead of the opposite - that's what image fields expect.
Problem
The issue is that whichever precedence we set for field-level vs instance-level settings within FieldInstance::getFieldSettings(), there is always code that needs the opposite.
"Instance wins over field" is the correct choice for most consuming code. But then there is ConfigFieldItem::settingsForm(), that is in charge of building the settings form for the *field* level settting. By definition, this code needs the field-level values of the settings, not covered by the instance level, to place in the form's #default_value.
The recommended way to access settings within a FieldItem class is $this->getFieldSettings(), which is a shortcut for $this->getFieldDefinition()->getFieldSettings(). But since $this->getFieldDefinition() is an $instance, $this->getFieldSettings() will give you "instance wins over field" values. See
#2015697-31: Convert field type to typed data plugin for file and image modules →
.
Currently ImageItem::settingsForm() works around this with:
$field = $this->getFieldDefinition()->getField();
$settings = $field->getFieldSettings();
This works because in practice $this->getFieldDefinition() is a FieldInstance, so getField() works. Our current runtime flow currently never calls settingsForm() if the field is a base field, base fields are not configurable.
But strictly speaking, $this->getFieldDefinition() returns a FieldDefinitionInterface, and getField() is not part of that interface.
Even if base fields stay non-configurable and we never display settings forms for them, we might come to a point where Field UI displays a non-editable summary of their settings (like for widgets & formatters). Then the method in charge of displaying this summary output would have the same issues.