Entity Reference custom fields: Configurable delete behavior
Overview
Currently, when entities referenced in a custom field of the type Entity Reference are deleted, the entity reference field gets cleared (set to NULL
). This is easy and prevents us from database inconsistencies. But this can lead to problems:
- inconsistencies when the entity reference field is set to be required
- stale/orphaned entities the entity reference field is attached to
-
civicrm_value_*
records with all-empty columns (or are they being taken care of already)
Example use-case
Imagine a custom entity named Qualification with (among others) an entity reference custom field referencing a Contact entity, which is set to be required; read: A Contact has multiple Qualifications.
Current behaviour
When deleting the contact, the Qualification entity will not be deleted until done so manually. The reference is just being set to NULL
instead. Those entities will be meaningless without a referenced contact, the required entity reference custom field will be empty, which breaks the semantic contract.
Question: Is the SET NULL
behavior a FK constraint on the DB table or part of some logic in Core code?
Proposed behaviour
When deleting the contact, the Qualification entity should be deleted. This is what we'd have configured the entity reference field to behave, as in other scenarios, the current behavior will be totally fine.
So, we'll need a configuration option for Entity Reference custom fields for selecting what should happen upon deletion of the referenced entity. Available options could be (basically MySQL foreign key constraints):
- Remove Reference (
SET NULL
) - current behavior, maybe also the default option - Cascade Delete (
CASCADE
) - removes thecivicrm_value_*
record and the entity the custom group is attached to - Restrict Delete (
RESTRICT
) - just as you can't e. g. delete contacts with financial transactions - Set Default (
SET DEFAULT
) - to be configured on the custom field -
Keep Reference (- might not be a good ideaNO ACTION
)
Comments
@colemanw and @michaelmcandrew might be interested.
Currently, this can be partly achieved by implementing a preDelete
event for retrieving and deleting referencing entities.