Problem/Motivation
There is no reusable mechanism in Drupal for overriding config entity settings on a per-content-entity basis. For example, a Commerce store may need to override payment gateway credentials without modifying the global configuration, or a node may need to override a date format or notification settings specific to that piece of content.
This pattern is needed by multiple projects but each one implements it ad-hoc. A generic, plugin-based solution built on top of plugin_configuration_field would allow any module to declare overridable config entity fields with minimal boilerplate.
Proposed resolution
Add a new submodule config_entity_override (shipped under modules/) that provides:
1. Plugin type and manager
- A
ConfigEntityOverridePHP attribute declaring the plugin's target config entity type and, optionally, which content entity types it applies to via theentity_typesparameter. - A
ConfigEntityOverrideManagerplugin manager with standard Drupal discovery. - Automatic registration as a
plugin_configuration_fieldtype via an event subscriber.
2. Base class and interface
ConfigEntityOverrideInterfaceexposesgetEntityTypes()andappliesTo()so widgets and other consumers can check whether a plugin is valid for a given entity type.ConfigEntityOverrideBaseimplementsappliesTo()and provides template methods (buildOverrideForm,validateOverrideForm,submitOverrideForm) that concrete plugins override to expose only the config entity fields that should be editable.
3. Custom widget
ConfigEntityOverrideWidgetextends the base plugin select widget.- Filters available plugins through
getApplicableDefinitions(), keeping only those whoseentity_typesinclude the host entity type. - Renders a config entity select element alongside the plugin override form.
4. Data model
The field stores target_plugin_id (the override plugin ID) and target_plugin_configuration containing:
[ 'config_entity_id' => 'my_entity_id', 'overrides' => ['setting' => 'overridden_value'], ]
No new database tables are needed; the submodule reuses the existing plugin_configuration_field schema.
5. Test coverage
- Unit test:
ConfigEntityOverrideBaseTest(appliesTo logic, entity type filtering). - Kernel tests:
ConfigEntityOverrideManagerTest(plugin discovery),DateFormatOverrideTest(end-to-end config override). - FunctionalJavascript test:
ConfigEntityOverrideWidgetTest(widget interaction, AJAX, form submission). - Test module
config_entity_override_testwith aDateFormatOverrideplugin as a realistic example.
Usage example
use Drupal\config_entity_override\Attribute\ConfigEntityOverride;
use Drupal\config_entity_override\Plugin\ConfigEntityOverrideBase;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
#[ConfigEntityOverride(
id: 'my_config_type',
label: new TranslatableMarkup('My config type'),
config_entity_type: 'my_config_entity',
entity_types: ['node'],
)]
class MyConfigOverride extends ConfigEntityOverrideBase {
protected function buildOverrideForm(
array $form,
FormStateInterface $form_state,
ConfigEntityInterface $config_entity,
): array {
$form['setting'] = [
'#type' => 'textfield',
'#title' => $this->t('Override value'),
'#default_value' => $this->configuration['overrides']['setting']
?? $config_entity->get('setting'),
];
return $form;
}
}
Remaining tasks
- Review and merge
User interface changes
- New
ConfigEntityOverrideWidgetadds a config entity select dropdown above the override form when editing aplugin_configuration_field:config_entity_overridefield.
API changes
- New plugin type:
config_entity_overridewith attribute-based discovery. - New plugin manager service:
plugin.manager.config_entity_override. - New interface:
ConfigEntityOverrideInterface. - New base class:
ConfigEntityOverrideBase. - New attribute:
ConfigEntityOverride. - New widget:
ConfigEntityOverrideWidget.
Data model changes
None. Reuses the existing plugin_configuration_field two-column schema (target_plugin_id + target_plugin_configuration).
Issue fork plugin_configuration_field-3579697
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
facine commented