Closed (fixed)
Project:
Drupal Canvas
Version:
1.x-dev
Component:
Shape matching
Priority:
Major
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
10 Sep 2025 at 01:16 UTC
Updated:
18 Nov 2025 at 20:29 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
phenaproximaMy stop-gap measure has been to create a computed
urlfield for nodes which returns the canonical URL of the node: https://git.drupalcode.org/project/drupal_cms/-/blob/2.x/drupal_cms_help... and https://git.drupalcode.org/project/drupal_cms/-/blob/2.x/drupal_cms_help....Comment #3
phenaproximaPer @effulgentsia's suggestion, the computed field should be ported into Canvas.
Comment #4
wim leersThis could've been avoided if we had #3543408. See #3543408-3: Allow content templates to contain adapted prop sources.
(Please help prevent issue sprawl of hard-to-connect issues! 🙏)
Comment #5
wim leersPer #3 😊 Looking forward to your MR!
Comment #7
phenaproximaComment #8
phenaproximaComment #9
phenaproximaComment #10
wim leersComment #12
tedbowI tried to manually tests this. I merged this with 1.x but I couldn't find a component that I could link a prop to this field. Is there an existing one? I enabled `sdc_test_all_props` but it didn't have a prop I could find either. Since this mainly for content templates it seems reasonable we should be able to manually test this before merging
Also is there a reason not to create an adapter instead of base field. Won't a base field have the side effect of it being able to used in other module UI's but an adapter won't?
Comment #13
phenaproximaI had originally implemented this as an adapter in Drupal CMS's shim module, but was emphatically told that we cannot use adapters because if they are present in any component's input in a content template, it will crash the UI.
I can't confirm or deny that, but it was a scary enough warning that (at @effulgentsia's suggestion), I changed the approach to use a computed field instead. That has worked for us, and is implemented in the shim module.
Having said that, the true solution is probably an adapter, but if Canvas doesn't support them right now, that leaves us in a tough spot.
Comment #15
wim leersChoices to evaluate
I was asked to check whether:
AdaptedPropSources into Canvas after all (see #3543408: Allow content templates to contain adapted prop sources)Evaluation
Of those:
canonical_urlproperty to the "ID" entity key's field, which would return the/node/1URL (without path processing), andcanonical_url_alias(with path processing). That reduces chances of disruption for contrib, because the set of fields on everyNodeobject remains exactly the same. (Contrib/custom modules are more likely to be iterating over all fields of an entity type+bundle than over the field properties on a particular field instance.)What if there's a 4th option?
What if … we added a new type of prop source, called
HostEntityUrlPropSource? BecauseDynamicPropSourceis about fetching fields/field properties (Typed Data, basically), whereas this is about calling$entity→toUrl('canonical')→setAbsolute(). There's prior art for generating special URLs dynamically, too:DefaultRelativeUrlPropSourceSee https://git.drupalcode.org/project/canvas/-/merge_requests/199. WDYT? 😊
Comment #16
phenaproximaI'll get to the IS update later.
Comment #17
phenaproximaComment #19
phenaproximaI can confirm that this does exactly what is intended; I tested it out in the context of Drupal CMS 2.x's
cardcontent template for blog posts, which is where we're currently using the computedurlfield as a shim.I did at least fix the linting issues. I'm not sure what else would be needed for this to be mergeable.
Comment #20
effulgentsia commentedCode looks great. Tests pass. #19 confirms it addresses what Drupal CMS needs.
Comment #22
phenaproximaThank you! This is a nice solution.
Comment #24
wim leersThanks for that test coverage! 😊
But … why was this merged?!?! It was clearly not ready. I spent a few mins hacking something together sprinkled with many
@todos, @phenaproxima added minimal test coverage, and … that's it.was merged as-is. 😅 Meaning no human can use it!
@todos beyond that.\Drupal\Tests\canvas\Kernel\Config\ContentTemplateValidationTest::setUp()should've been updated to use this, to prove it works end-to-end\Drupal\Tests\canvas\Kernel\Config\PatternValidationTest::testInvalidComponentTree()should've gotten a test case that tries to use it, to prove you can't use it inPatternPageRegionThis was rushed in. 👎
Comment #25
wim leersAh, I found now in private chat that #24.1 was skipped because:
Which surprises me, but I guess it does mean Drupal CMS is unblocked 🚀
That does mean this issue should definitely be open again though, for A) tests, B) docs, C) updating our shape matching logic.
I think A + B could largely be handled by @phenaproxima. I am probably the only one who can do C.
Comment #27
phenaproximaOkay, responding to the points in #24:
HostEntityUrlPropSource, and updated the@todos to refer to it. You are correct that what is in 1.x HEAD right now is enough to unblock Drupal CMS and remove any need for us to ship a computedurlfield as a shim -- for which we are very grateful!I'm assigning to you to handle the shape matching piece of it, which will presumably also need tests and documentation, so leaving those issue tags in place.
Comment #28
lauriiiWouldn't the benefit of a computed URL field be that the URL would be available in JSON:API response too? It's currently pretty difficult to get the URL for a given entity from JSON:API. IMO it would make sense to provide it as an API there too.
Comment #29
wim leersThat'd be a core issue. It's not Canvas' responsibility to do this on behalf of all entities in all of Drupal.
#27:
I'll get on reviewing this 👍
Comment #30
wim leersFieldForComponentSuggester(as the name implies) is only designed for suggesting field data (field properties in fields on the entity, or from a referenced entity). But due to the MR that was merged here, it needs to be reorganized significantly, to allow for not onlyDynamicPropSources but alsoHostEntityUrlPropSources.It doesn't help that all of #3551455: HostEntityUrlPropSource should be able to support absolute or relative URLs, URL options was deferred to a follow-up: that just makes it harder to get everything right, because currently
HostEntityUrlPropSourceis de facto a one-trick pony, whereas it clearly will need to accept configurability in the future (even if only to be able to generate a relative OR an absolute URL, whereas currently it ALWAYS generates an absolute URL).(Static|Dynamic)PropSource, and the same flaw also applies to this new prop source: it's failing to bubble cacheability (an absolute URL varies by theurl.sitecache context) → #3554184: Bubble cacheability of resolved props values and access results + `PropSourceBase::evaluate()` does not return cacheability at all should tackle it for all prop sources at onceI've got #1 WIP locally, but am currently constantly distracted by a very sick baby to take care of 😅 Still, progress is being made:

Comment #31
phenaproximaI think we should rename
host-entity-urltopermalink.That's a much clearer, more standard name for what it does...and it's also completely accurate, regardless of which link template(s) it ultimately supports. For example, this is so clear:
or:
The word "permalink" also implies that an absolute URL will be the default, which is true (and IMHO, the correct behavior). If we later wish to support relative URLs, we could make that explicit:
permalink:canonical:relative.Comment #32
phenaproximaDidn't find anything terribly wrong here but I do have some thoughts. And I personally think the time to rename is now, before this goes into RC and stable releases of Canvas.
Comment #33
phenaproximaWent over this with Wim over Zoom. We are broadly on the same page about making Canvas's internals more grokable, but that's not in the scope of this issue. So some of the doc comment nits and minor feedback can wait until later, when the whole PropSource system is more internally consistent.
Has tests. Has docs. Shippety-ship it.
Comment #34
wim leersMerging, given @phenaproxima's +1.
Three follow-ups:
ContentTemplateUI, but clicking it has no effect, due to a bug in the UI — the child issues of #3541000: [META] Content templates UI for 1.0: only nodes, no exposed slots, no replacement for the view mode/display UI that built the "select a suggestion from the server-side provided list of suggestions" specifically was designed to have the client side treat the suggested sources as opaque JSON objects (see#/components/schemas/StructuredDataForPropShapeHierarchicalSuggestionPathWithChoicein/openapi.yml). Apparently the/uicode does not do that. Follow-up bug report filed: #3555068: Linking a `HostEntityUrlPropSource` to populate a `type: string, format: uri|uri-reference` in a `ContentTemplate` has no effect — until that is fixed, the choice will appear in the UI but clicking it won't do a thing:Comment #35
wim leersFixing the title, because what the merged MR !199 landed is specifically not a permalink (because path processing is enabled by default, and path aliases are literally the opposite of permalinks — unless you install the contrib Redirect module) — see #3551455-3: HostEntityUrlPropSource should be able to support absolute or relative URLs, URL options.
Comment #37
wim leersComment #39
wim leersComment #40
wim leersComment #41
wim leersLooks like @lauriii thinks this MR didn't go far enough: #3555413: Allow linking to referenced entities: add `url` property to `EntityReferenceItem::propertyDefinitions()`. Which in turn may call into question the entire premise of the new prop source. As I wrote in #15 here: — which given @lauriii's latest remark over there actually is literally what he expects.
Which is totally reasonable, but it would mean that a new prop source makes less sense than adding a computed base field to every entity type — aka what this issue originally did 😅
IOW: why go through the pains of simulating the presence of entity URLs in the right place in the Typed Data tree (which is the path we're currently on) when we could much more simply just expose it as a computed field with multiple properties to offer multiple kinds of URLs?
Comment #42
wim leersComment #43
phenaproximaTo recap how we got here...
Now, if we actually do need to traverse a data tree to get to URLs at any point in the tree, a new computed base field does make sense. I assume we'd implement it on nodes to start with, then expand that to other entity types as necessary.
I can see us having use for something like this:
$node->url->canonical->setAbsolute()->setOption('query', ['foo' => 'bar'])->toString()I could also see (hopefully) core adopting that at some point in the future.
So...count me in, I guess.
Comment #44
wim leersExactly!
\Drupal\Core\Urlobject as a property directly. So the->setAbsolute()->setOption('query', ['foo' => 'bar'])->toString()part is not realistic I think, because how would we know to call those methods? ⇒ it should be available as a field property directly, with no choices available. So:+
(with
urlthe new base field on all entity types, added by Canvas, andcanonical_absoluteandcanonical_relativethe 2 field properties.static\Drupal\Core\Field\FieldItemInterface::propertyDefinitions(FieldStorageDefinitionInterface $field_definition)being able to determine the target entity type ID using the given field storage definition, it's possible to determine which link relations/templates exist for a given entity type, and hence expose alsoedit-form_absolute+<code>edit-form_relative, and so on. AKA what #3551455: HostEntityUrlPropSource should be able to support absolute or relative URLs, URL options was about.(Plus perhaps a special case for the canonical URL with + without path processing aka path aliases?)
Comment #45
wim leersComment #46
wim leersSimilar sentiment @phenaproxima here in #43 and from @penyaskito at #3555413-12: Allow linking to referenced entities: add `url` property to `EntityReferenceItem::propertyDefinitions()`.
⇒marking unfixed, and flagging the likely need for a revert
⚠️ Note that this will make any future update path towards adapters much more painful. Because anything that uses a Canvas-altered-in field property that SHOULD use an adapter would then need to be updated later.
A simpler, clearer example of that general problem is an SDC's need (e.g. #3547303: The hero-blog component's `date` prop needs to be a timestamp) for a
type: string, format: dateprop to be populated by aNode'screated</em> field. That field contains a UNIX timestamp, which is a <code>type: integer. That was intended to be solved by\Drupal\canvas\Plugin\Adapter\UnixTimestampToDateAdapter, but adapters are out of scope for 1.0.But @lauriii just told me in a meeting that he expects this to work in 1.0, despite that not being part of #3541000: [META] Content templates UI for 1.0: only nodes, no exposed slots, no replacement for the view mode/display UI. 😅😬
So we might just have to accept that such a painful update path will be necessary. Thanks to the
ComponentAuditservice, we'll know how to find affected component instances (per revision, even). But it'll mean we won't be able to drop whichever computed field properties (or fields) we add in Canvas 1.x until at least 2.x, and realistically until much later.Is that something we're willing to commit to? For content templates, the update path wouldn't be too painful (at most dozens of entities to update), but for content entities it'd be very complex.
Comment #47
wim leersTo give a sense of the complexity & scale of such an update path: essentially, we'd have to update potentially millions of rows (every component instance DB row that uses a computed field/field property added by Canvas) from something like:
(👆 stored for a single component instance in its
inputscolumn of the field table for a content entity)+
(👆 stored in the
Componentconfig entity)to:
+ a change to the per-component instance
inputscolumn for every revision that uses it, to convey that this uses a static prop source + adapter, so something like:Comment #48
wim leersDiscussed with @effulgentsia in detail.
I discussed with him the full range of possible implementation choices (they're listed in #3555413: Allow linking to referenced entities: add `url` property to `EntityReferenceItem::propertyDefinitions()`).
Alex independently proposed what I previously proposed at #3555413-5: Allow linking to referenced entities: add `url` property to `EntityReferenceItem::propertyDefinitions()`:
But he phrased it better than I did — this is our joint conclusion, which uses his phrasing:
HostEntityUrlPropSourcethis issue added, only for the host entity. There is indeed a likely future need for e.g. linking to theedit-form, or with/without path processing (path aliases), etc. → we have #3551455: HostEntityUrlPropSource should be able to support absolute or relative URLs, URL options for that.ContentTemplateis fine as-is (at the very top of the root level — only if the target prop shape istype: string, format: uri|uri-reference, of course).urlfield property to\Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::propertyDefinitions(), and make it only ever return the canonical URL. This would then simply reuse the existing Typed Data-basedDynamicPropSourcematching+suggesting logic — no changes needed.HostEntityUrlPropSourceand added a computed field instead) is far more likely than adding a computed field property. Any module could be altering base fields, but only one module can alter a field type's properties, which also exceedingly few modules do. This would mean it is feasible to bring this part into core. (Whereas making core auto-add a new (computed) base field to all (content) entity types would be fairly unlikely.)Comment #50
wim leersBuilt #48: #3545859-16: Add a `host-entity-url` prop source for linking to the host entity.