Issue #3618762: Let each entity type say what its rows belong to, instead of the engine holding the list

Two screens need to know what a row belongs to. A page title names the nearest one, so two identically named rows are told apart. A machine name is unique within the things it belongs to rather than across the site, so two halls may both name a section "vip".

Both were answered by a list of field names written in the engine: EntityTitle held venue, resource, slot, preset, pinning, configuration, the machine name widget held tenant, venue. Four of those seven are fields the engine does not own, and neither list could be kept honest by anything — a field renamed on the far side leaves a title saying nothing and a key unique site-wide, and neither fails.

They are the same question, so an entity type declares it once: parent_fields in its attribute, nearest first. A title takes the first of the chain that names an entity; a machine name is narrowed by every field in the chain the row has filled. Twenty-two types declare their own chain, each in the module that defines it, and EntityParents is the one reader so the property name is written once.

The tenant is last in every chain because it is the widest wall, and it is a plain string rather than a reference — which is why a title skips it and a machine name does not: "of default" tells a reader nothing, while a key free to collide across tenants is not unique at all.

The guard ships with it. An attribute's additional is an open bag: a misspelled property is silence, and so is a field name that no longer exists. Both are invisible at runtime — the same shape of failure as [#3618720] and [#3618731]. So a test asserts every yoyaku content entity type declares a chain, every field named in one exists on that type, and each chain ends at the tenant. Both failure modes were seen to fail before the change was trusted: once by removing a declaration, once by pointing one at a field that does not exist.

One deliberate change of behaviour. A resource also references a pinning and a configuration, and a slot a pinning; the old list treated those as scopes. They are policies attached to the row, not things it belongs to, so a resource with no hall used to be titled "of" its pinning and now names no parent.

Not in this change. BookingHooks keeps three lists naming other modules' fields and cannot use a declaration: they are read inside hook_entity_base_field_info_alter(), which answers by reading the very definitions that would carry it. Its own issue rather than this mechanism bent to fit.

ResourceFieldGroups stays as it is, and not because it was missed: it maps every module's resource fields to a heading on one form, the groups are core's own headings, an unknown field is left ungrouped rather than misplaced, and the map is in one place precisely because two screens were grouping the same fields differently. Handing each module its own group would leave the arrangement owned by nobody.

Verification. phpstan level 3 [OK], phpcs and cspell clean. Eight kernel classes green including the machine name and translation screens, plus a new test of the consequence at the surface: a hall that already has a "vip" section refuses a second, and another hall may name one of its own.

Merge request reports

Loading
Loading