Entity::toUrl() currently uses a hardcoded special case to fill the revision_id parameter only on one route ("revision").

    if ($rel === 'revision' && $this instanceof RevisionableInterface) {
      $uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId();
    }

However, entity annotations can provide other revision-specific routes, such as "revision_revert" or "revision_delete". Maybe we could expand this and add it to all routes that match /^revision\b.*/ rather than only /^revision$/.

(Ideally, it should be set on all routes that accept a {$type}_revision parameter, but the actual parameters accepted by a route don't seem to be available to the code as it is, and if we set it on routes that don't have one, we'll likely break something. The expanded revision-* or revision_* match would be easier to implement.)

Comments

cburschka created an issue. See original summary.

cburschka’s picture

Title: $entity->toUrl('...') should fill revision parameter on all applicable routes. » $entity->toUrl('revision-*') should fill revision parameter on all applicable routes.

.

cburschka’s picture

Issue summary: View changes

.

cburschka’s picture

Status: Active » Needs review

This expands the logic from revision to all relationship types that start with revision.

I'm still not so happy about attaching special behavior to link template names, tbh. It's already undocumented magic as it is, and this patch adds even more magic.

The original code was added in #2456599: Field node_field_revision.title needs to use an entity-aware formatter in Views, maybe we could revisit the problem and find a more robust way?

cburschka’s picture

StatusFileSize
new736 bytes

Actual patch attached.

sam152’s picture

I wonder if there is a reason the param isn't just added for all link templates? If the param doesn't exist in the URL, it would just be ignored right?

cburschka’s picture

I don't think it would lead to outright errors when the Url is rendered, but there are places in core which make assumptions about the parameters in the unrendered object.

Just as an example, menu_link_content.module does this:

  foreach ($entity->uriRelationships() as $rel) {
    $url = $entity->toUrl($rel);
    // Delete all MenuLinkContent links that point to this entity route.
    $result = $menu_link_manager->loadLinksByRoute($url->getRouteName(), $url->getRouteParameters());

This wouldn't work correctly anymore, as loadLinksByRoute('entity.node.canonical', ['node' => 1, 'node_revision' => 1]) would not pick up the menu link for /node/1.

I suspect the only robust workaround would be to actually render and then parse the Url object, which seems like a big overhead.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jibran’s picture

Issue tags: +Needs tests

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jibran’s picture

StatusFileSize
new736 bytes

Reroll for 8.7.x

hchonov’s picture

Re #6:

I wonder if there is a reason the param isn't just added for all link templates? If the param doesn't exist in the URL, it would just be ignored right?

I think this would be the best option.

Re #7

Just as an example, menu_link_content.module does this:

 foreach ($entity->uriRelationships() as $rel) {
    $url = $entity->toUrl($rel);
    // Delete all MenuLinkContent links that point to this entity route.
    $result = $menu_link_manager->loadLinksByRoute($url->getRouteName(), $url->getRouteParameters());

This wouldn't work correctly anymore, as loadLinksByRoute('entity.node.canonical', ['node' => 1, 'node_revision' => 1]) would not pick up the menu link for /node/1.

Unfortunately this is correct.

But what we can do is to return the parameter in \Drupal\Core\Entity\Entity::urlRouteParameters() and in \Drupal\Core\Entity\Entity::toUrl() pass it to the URL object only in case this parameter is present on the route. What about something like this:

Make \Drupal\Core\Routing\RouteMatch::getParameterNames() somehow accessible -

  1. make it static public and add a parameter for the route object
  2. make it public
  3. copy-paste its logic here

An approach based on the 3rd option:

$route = \Drupal::service('router.route_provider')->getRouteByName($route_name);
// Variables defined in path and host patterns are route parameters.
$variables = $route->compile()->getVariables();
$names = array_combine($variables, $variables);
// Route defaults that do not start with a leading "_" are also
// parameters, even if they are not included in path or host patterns.
foreach ($route->getDefaults() as $name => $value) {
  if (!isset($names[$name]) && substr($name, 0, 1) !== '_') {
    $names[$name] = $name;
  }
}

Now that we know the necessary parameters we can remove the unnecessary ones:

$route_parameters = $this->urlRouteParameters($rel);
$route_parameters = array_intersect_key($route_parameters, $names);
hchonov’s picture

Status: Needs review » Needs work

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dpi’s picture

yogeshmpawar’s picture

Status: Needs work » Needs review

Setting back to Needs Review & Triggering bots.

aaronmchale’s picture

Manually tested #15 while working on #2350939-77: Implement a generic revision UI today, and it works as expxcted, tested using the link template revision-revert-form on the version_history route, using the block_content Entity Type.

This is now an additional blocker for the issue I just linked.

tstoeckler’s picture

Status: Needs review » Needs work

To be honest I think #12 is too complex if we can fix the actual issue with a patch as simple as #5 / #11 / #15. I agree with everyone here that the current API around this is super weird but it is the API we have. And #12 for example wouldn't work with "extra" route parameters which do not belong to variables, such as the entity type ID on the collection route. So I think #15 (or something like it is the way to go).

This is rightly marked "Needs tests", however, so marking "needs work" for that.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

cburschka’s picture

Status: Needs work » Needs review
StatusFileSize
new2.5 KB
new2.03 KB

Here we can extend EntityUrlTest::testToUrlLinkTemplateRevision() to test a link template that starts with "revision". Interdiff = testonly patch.

Status: Needs review » Needs work

The last submitted patch, 21: 2927077-21-testonly.patch, failed testing. View results

cburschka’s picture

Status: Needs work » Needs review

Testonly patch is designed to fail.

hchonov’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php
@@ -176,11 +176,11 @@ public function testToUrlLinkTemplateRevision($is_default_revision, $link_templa
+    $url = $entity->toUrl($link_template !== 'canonical' ? $link_template : 'revision');

I think this would be more understandable if we move $link_template out of the method call and reassign it:
$link_template = $link_template === 'canonical' ? 'revision' : $link_template;

Feel free to set to RTBC when done :).

cburschka’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new2.54 KB
new1.2 KB

Thanks! :)

Yeah, that didn't look right to me either.

aaronmchale’s picture

--- a/core/lib/Drupal/Core/Entity/EntityBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityBase.php
@@ -271,7 +271,7 @@ protected function urlRouteParameters($rel) {
       $parameter_name = $this->getEntityType()->getBundleEntityType() ?: $this->getEntityType()->getKey('bundle');
       $uri_route_parameters[$parameter_name] = $this->bundle();
     }
-    if ($rel === 'revision' && $this instanceof RevisionableInterface) {
+    if ($this instanceof RevisionableInterface && strpos($rel, 'revision') === 0) {
       $uri_route_parameters[$this->getEntityTypeId() . '_revision'] = $this->getRevisionId();
     }

Perhaps adding an inline comment here would be beneficial so that it's easy to see what the impact of this is. I'm also sort of split on whether strpos is fine or whether substr would be more readable here.

hchonov’s picture

I think that the code is self explanatory and does not need any additional documentation. Even if we add it I do not see the added value of documenting a simple condition.

larowlan’s picture

Adding review credit for @AaronMcHale for manual testing and @hchonov for subsystem-maintainer review

  • larowlan committed 8350f68 on 9.1.x
    Issue #2927077 by cburschka, jibran, dpi, hchonov, AaronMcHale: $entity...
larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed 8350f68 and pushed to 9.1.x. Thanks!

Updating some items this blocks

aaronmchale’s picture

Thanks @larowlan, great to see this small yet important patch land, well done everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

nono95230’s picture

StatusFileSize
new2.53 KB

I add to this issue the same patch, compatible with version 8.9.7 of the Drupal core.

kim.pepper’s picture

Issue tags: +#pnx-sprint