Problem/Motivation
FieldValue::walk(), getHopOptions(), isDescendable(), hopFieldOptions() and traversalLabel() total about 500 lines implementing a labeled, cycle-guarded walk down entity reference chains: discovering what is descendable, what its target types are, and how each hop should be named.
This is a solved problem with well-known edge cases — multi-target reference fields, computed fields, recursive types — and every one of them has to be rediscovered here.
Proposed resolution
Use Typed Data API's DataFetcher and property-path handling for the traversal itself, keeping this module's presentation on top: the ›-joined labeled hops and the target-aware root. typed_data is API-only and already arrives transitively with ECA, which is a suggestion, so the added weight is small.
Remaining tasks
- Confirm typed_data's traversal covers what the current walk handles, notably multi-target reference fields and the descendable/not-descendable split.
- Map property paths back to the stored path format.
- Keep the stored condition format unchanged, or write the change up under Data model changes.
User interface changes
None intended. The hop selector should offer the same options with the same labels.
API changes
Internal to FieldValue. No change to SegmentPluginInterface or QueryableSegmentPluginInterface.
Data model changes
None intended. If typed_data's path syntax is adopted in storage rather than only internally, stored conditions change format and that must be called out here.
Issue fork entity_segment-3612426
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 #2
jdleonardComment #4
jdleonardWorked this in MR !6. The investigation changed the approach, so a few notes
for the record — including corrections to this issue's own summary.
typed_data (the proposed mechanism) was evaluated and set aside.
Two findings, verified against a real build:
released 3.x) requires
drupal/typed_data— it would be a genuinelynew dependency, not a transitive one.
DataFetcherdrills via
EntityDataDefinition::getPropertyDefinitions(), whichfalls back to
getBaseFieldDefinitions()unless the definition ispinned to exactly one bundle — and core builds every entity-reference hop target
bundle-less (
EntityReferenceItem::propertyDefinitions()). So everyhop would silently drop all configurable fields, which is most of what
the selector needs to offer. Core carries a standing
@todofor themulti-bundle case (#2169813).
What landed instead: the same idea — stand on the Typed Data
API instead of a bespoke walk — but on core Typed Data
interfaces, in the shape Search API's
FieldsHelperuses. ItsgetNestedProperties()is exactly the missing piece: it unionsgetFieldDefinitions()across a hop target's bundles, overComplexDataDefinitionInterface/DataReferenceDefinitionInterface/ListDataDefinitionInterface. Search API itself doesn't depend on thetyped_data module, and neither does this. Net result: the goal is met
with no new Composer dependency.
The traversal now lives in a new
property_traversalsubmoduleexposing a
property_traversal.fetcherservice(
PropertyTraversalInterface).FieldValueconsumes it andno longer walks references itself. Behaviour, hop-selector options/labels, and the
stored
<ref>.entity.<field>format are unchanged.Corrections to this issue's summary:
a public service and a new submodule boundary.
SegmentPluginInterfaceandQueryableSegmentPluginInterfaceare still untouched. The submoduleis deliberately unprefixed and depends only on core (dependency runs
entity_segment → property_traversal) so it can later move to itsown project.
<ref>.entity.<field>format; no migration.reference fields" — neither was accurate. There is no visited-set (traversal is
bounded by finite path length and one-level-per-interaction expansion), and
neither the old walk nor typed_data handles per-item target types (e.g.
dynamic_entity_reference). Those, plus back-references and custom-storage
filtering, are noted as out of scope for separate issues.
Testing:
phpcs,phpstan, and thefull PHPUnit suite are green locally (Unit + Kernel + Functional). The MR pipeline
is green; its three advisory (
allow_failure) jobs are handled — cspelland phpmd cleaned up, and
phpunit (next major)fails identically on1.0.x today, so it's a pre-existing moving-target job, not from this change.
Retitling this to "Use core Typed Data for FieldValue reference traversal (via
a property_traversal submodule)", since the old title names a module we ended up
not using.