resolveEntityUri() hardcodes entity:node/, so link props can never target any other entity type
Problem/motivation
A link_default-backed prop (any SDC prop with format: uri or format: uri-reference)
autocompletes against node entities only. This is hardcoded in two places:
-
Drupal core's
LinkWidget::formElement()sets$element['uri']['#target_type'] = 'node'unconditionally — tracked as core issue #2423093, open since 2013. -
Canvas's
resolveEntityUri()assumes any autocomplete selection is a node and rewrites it toentity:node/${id}:// ui/src/utils/transforms.ts export const resolveEntityUri = (uri: string): string => { const id = parseSingleEntityAutocompleteSelection(uri); // LinkWidget with autocomplete support only supports matching on node // entities. // @todo Add support for other entity types once core does - // https://www.drupal.org/i/2423093 return id !== null ? `entity:node/${id}` : uri; };
Canvas's own canvas_page entity type — a first-class content entity with its own
canonical route — can never be a link prop's target because of this. It affects any site
author trying to link to a Canvas-built page from a component prop.
This is the reverse of an already-fixed bug: #3588884 (closed) (fixed in 1.4.0) was the same node assumption breaking non-link entity autocompletes, such as the Webform block picker. That fix scoped the assumption correctly there; this issue is the matching half for link props.
A related, distinct gap: Linkit's own autocomplete also excludes Canvas pages (linkit#3552659).
Steps to reproduce
- On a site with Canvas pages (
canvas_pageentities) and a custom entity-reference autocomplete wired up for a non-node target type on auri/uri-referenceprop. - Select any non-node entity from that autocomplete inside a component instance form.
- Observe the stored value is always rewritten to
entity:node/<id>, which is wrong unless the selected entity happens to be a node — for acanvas_page, the id collides with an unrelated node and the link silently targets the wrong page.
Proposed resolution
A uri/uri-reference prop often needs more than one valid target type at once — a
Canvas-built page and a legacy node are both valid destinations on the same field, and
other content entity types apply as a site's content model grows. Making the hardcoded
type configurable to a single alternative (e.g. a hook_canvas_storable_prop_shape_alter()
override that swaps in canvas_page) doesn't cover this; it only relocates the assumption,
and is rejected for that reason.
Closing the gap requires per-selection type resolution:
- The autocomplete endpoint must report which entity type it matched for each suggestion,
not just return a bare
{value, label}pair.resolveEntityUri()can then buildentity:<type>/<id>per selection instead of assumingnode. LinkWidget's own matching needs to query more than one target type in a single autocomplete request to produce those suggestions in the first place. Core issue #2423093 as filed only covers making the target type configurable to one alternative, not several at once, so it wouldn't close this gap even if it landed.
Remaining tasks
- Agree on how a suggestion payload carries its entity type (new field vs. an encoded
value) without breaking existing{value, label}consumers. - Decide whether multi-type matching belongs in core's
EntityAutocompleteMatcher/LinkWidget, or is a Canvas-specific concern layered on top. - Prototype
resolveEntityUri()buildingentity:<type>/<id>from a type-aware suggestion. - Design how mixed-type suggestion rows are labeled so authors can tell entity types apart (see this module's two-line suggestion rows for one approach).
User interface changes
None today. Once resolved, a link prop's autocomplete could return suggestions spanning multiple entity types in one dropdown instead of node-only. The suggestion list would need a way to show each row's entity type so authors aren't guessing (e.g. a secondary line with content type and path, as implemented in this contrib module).
API changes
- Core:
LinkWidget::formElement()'s$element['uri']['#target_type']would need to accept more than a single scalar entity type ID, affectinggetUriAsDisplayableString()andgetUserEnteredStringAsUri(), which currently assume'node'. - Canvas:
resolveEntityUri()inui/src/utils/transforms.tswould need a target entity type per selection instead of a hardcoded'node'. - Any custom autocomplete route backing an
entity_autocompleteelement would need to add the matched entity type to its JSON response. Additive change — existing{value, label}consumers are unaffected.
Data model changes
None. No new fields, storage, or schema; this is a widget/matching-logic and autocomplete response-shape change only.