Problem/Motivation
It is valid for an entity type not to specify a canonical link. If you call $entity->toUrl() on an entity of that type, it will fail with a
No link template 'canonical' found for the '...' entity type
exception.
If you explicitly dealing with an entity type of that type, just calling $entity->toUrl() like that might be considered a bug, as you should instead do $entity->toUrl('edit-form') (assuming there is an edit-form link) or whatever other link you want to link to, but there is a lot of code in core that generically deals with entities of any type and just wants to output "a link" to an entity. Code like that currently breaks with entities without a canonical link.
See #3367475: [meta] Improve support for entity types without a canonical link for more context, but I think the moist poignant example is the cancel URL of entity delete forms (see Drupal/Core/Entity/EntityDeleteFormTrait::getCancelUrl():
// Otherwise fall back to the default link template.
return $entity->toUrl();
The comment notes that it does not really care, whether the canonical link template is used or not, but it needs to link somewhere. It seems unfortunate to require EntityDeleteFormTrait to explicitly check the availability of various link templates. Since we have chosen to make $rel optional, I think we should try to actually make that work also for entities without a canonical link.
Steps to reproduce
1. Create an entity type without a canonical link and provide the default delete form used in core.
2. Expect the delete form to work.
3. Frown, because the delete form throws an exception.
Proposed resolution
In Entity::toUrl(), if no $rel is passed explicitly, check if no canonical link exists, but edit-form does and in that case fall back to edit-form.
Remaining tasks
Review the change record
User interface changes
-
API changes
EntityBase::toUrl() works without specifying $rel for entities without a canonical link.
Data model changes
-
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #7 | 3371753-7.patch | 5.91 KB | tstoeckler |
| #7 | 3371753-5-7-interdiff.txt | 2.18 KB | tstoeckler |
Issue fork drupal-3371753
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:
- 3371753-fall-back-to
changes, plain diff MR !4299
Comments
Comment #2
tstoecklerThis is the least intrusive version possible. It still fails in the same way for entities with neither a canonical nor an edit-form link.
I think it would be slightly better to in that case throw a more helpful exception in that case and possibly we could also consider other link templates than edit-form as fallback, but I wanted to make the smallest possible change first.
As an additional improvement we could remove the override of
ConfigEntityBase::toUrl()which defaults$relto edit-form directly, but didn't do that yet, either.Comment #5
tstoecklerThis implements the additional things noted in #2.
The additional exception being thrown, while technically a behavioral change, shouldn't really affect anyone as it's the same exception class, so in effect there is not really a change, just a (slightly) more meaningful message.
The default value change in
ConfigEntityBaseis somewhat of a behavior change for config entities that do provide a canonical link. Those are rare, but Search API indexes, for example, provide a status overview of the index in addition to the edit-form. Search API already provides a custom delete form where the cancel link links to the canonical URL, but a similar contrib or custom module would notice a change if it were using core's default entity delete form. This is an improvement, however, as it does make sense to link to the canonical URL in that case. The only reason the override was there in the first-place was to allow the "default URL" case for config entities at all, which is still possible with this.Comment #6
smustgrave commentedRemoving credit from sonam_sharma for the empty MR.
Change makes sense but think we will need a change record for the new behavior please
Thanks!
Comment #7
tstoecklerGood point, added a change notice.
Also fixed some stray characters in the exception message. I thought about how to test this properly and looked into actually adding a functional test for the delete form cancel URL, but our test entity types override the cancel URL of the delete form for some reason (see
\Drupal\entity_test\EntityTestDeleteForm::getCancelUrl()). We do haveEntityUrlTest, however, so that seemed reasonable enough to add a small test to.Comment #8
smustgrave commentedChange looks good. Think ready for committer review.
Comment #10
smustgrave commentedSeems random
Comment #11
lauriiiIn my opinion adding the 'edit-form' as a fallback to entities without canonical URL seems reasonable, but I'd love to hear what the subsystem maintainers or framework managers think about this.
Comment #13
tstoecklerRandom failure
Comment #14
quietone commentedI'm triaging RTBC issues.
The IS is up to date and the proposed resolution matches the change. All questions have been answered. I read the CR and made changes for readability. I have added an item to the remaining tasks to review the change record.
Other than that the only thing is review by a subsystem maintainer review or framework manager as stated in #11.
Comment #16
lauriiiLooks like a random fail: #3383230: TestSiteApplicationTest::testInstallWithNonExistingFile() fails when another test creates database tables during the test run.
Comment #18
catchUntagging for subystem maintainer review since I am one. I think it makes sense to prioritise the canonical URL if one exists instead of always defaulting to edit, and for me the change record is enough for the small behaviour change.
Committed 9c4bc86 and pushed to 11.x. Thanks!
Comment #20
acbramley commentedThis caused an edge case regression #3409895: [regression] toUrl can incorrectly return edit-form url when another link template shares the canonical url
Comment #21
larowlanThis also caused a fatal in aggregator module #3414579: Blocks cause WSOD; Cannot generate default URL
Comment #22
tstoecklerI was wondering how this could have broken BC, as I thought I/we had been careful about that, but I completely missed that
Entity::toUrl()does in fact handle entities with auri_callbackand that those entities do not necessarily define any link templates.Sorry about that! Opened #3421114: [regression] Entity::toUrl() without argument is broken for entity types with a URI callback as a (hopefully) quick follow-up to revert the unintended API change.
Comment #23
jenlamptonWe have one site using translation that is unable to delete files at all, and on all our others we able to reproduce the same problem when we remove the `destination` parameter in the URL.
edit: Oops, I should have read the issue linked in THE PREVIOUS COMMENT more closely. Will try that patch first :)
Comment #24
jenlamptonThat issue appears unrelated to our problems with files. We're now working over here: https://www.drupal.org/project/drupal/issues/3424701