Follow-up to #2350503: Add route generation handlers for entities

Problem/Motivation

We now have support for route auto-generation for entities. Let's use it for all entities.

Proposed resolution

Implement any additional route generators we need, and remove all static routes in yml files.

Remaining tasks

Do it.

Also make sure the Entity topic is updated as part of this patch. (@defgroup entity_api in entity.api.php).

User interface changes

None.

API changes

None.

(This issue was approved by catch and alexpott in Amsterdam.)

CommentFileSizeAuthor
#195 interdiff.txt13.3 KBdawehner
#195 2350509-195.patch88.6 KBdawehner
#193 interdiff.txt1.49 KBdawehner
#193 2350509-193.patch84.65 KBdawehner
#190 interdiff.txt11.2 KBdawehner
#190 2350509-190.patch85.05 KBdawehner
#186 interdiff-2350509.txt20.53 KBCrell
#186 2350509-auto-route-generation.patch75.11 KBCrell
#168 interdiff.txt6.46 KBjhodgdon
#164 2350509-164.patch83.82 KBlokapujya
#164 2350509-164-interdiff.txt2.97 KBlokapujya
#164 2350509-142-158-interdiff.txt6.87 KBlokapujya
#164 2350509-158.patch83.58 KBlokapujya
#158 2350509-142-158-interdiff.txt6.87 KBlokapujya
#158 2350509-158.patch83.58 KBlokapujya
#153 2350509-153-entity-route-provider.patch89.72 KBtstoeckler
#153 2350509-142-153-interdiff.txt13.45 KBtstoeckler
#142 2350509-129-142-interdiff.txt4.25 KBlokapujya
#142 2350509-142.patch79.93 KBlokapujya
#139 interdiff-2350509-139.txt836 byteslokapujya
#139 2350509-139.patch81.7 KBlokapujya
#134 2350509-134-interdiff.txt691 byteslokapujya
#134 2350509-134.patch81.24 KBlokapujya
#132 2350509-132-interdiff.txt2.02 KBlokapujya
#132 2350509-132.patch80.86 KBlokapujya
#129 interdiff-2350509-129.txt1.25 KBlokapujya
#129 2350509-129.patch80.25 KBlokapujya
#127 jjf_test3.patch84.22 KBlokapujya
#123 2350509-123.patch80.02 KBkgoel
#121 2350509-121.patch80.02 KBkgoel
#118 interdiff.txt3.11 KBdawehner
#118 2350509-118.patch80.1 KBdawehner
#116 interdiff.txt1.27 KBdawehner
#116 2350509-116.patch79.75 KBdawehner
#112 interdiff.txt2.77 KBdawehner
#112 2350509-112.patch79.35 KBdawehner
#109 2350509-109.patch79.37 KBwillzyx
#98 2350509-98.patch79.4 KBwillzyx
#98 interdiff.txt2.89 KBwillzyx
#97 shortcut.jpg35.84 KBwillzyx
#96 interdiff.txt2.29 KBdawehner
#96 2350509-96.patch79.94 KBdawehner
#94 interdiff.txt2.53 KBdawehner
#94 2350509-94.patch79.86 KBdawehner
#92 interdiff.txt1.68 KBdawehner
#92 2350509-91.patch77.33 KBdawehner
#87 interdiff.txt1.04 KBdawehner
#87 2350509-87.patch77.33 KBdawehner
#86 interdiff.txt18.11 KBdawehner
#86 2350509-86.patch76.29 KBdawehner
#78 2350509-78.patch77.22 KBBerdir
#76 interdiff.txt4.23 KBdawehner
#76 2350509-76.patch77.1 KBdawehner
#74 interdiff.txt7.45 KBdawehner
#74 2350509-74.patch72.88 KBdawehner
#72 2350509-72.patch65.42 KBdawehner
#69 2350509-68.patch65.35 KBtstoeckler
#69 2350509-66-69-interdiff.txt942 byteststoeckler
#66 2350509-66.patch65.29 KBtstoeckler
#66 2350509-65-66-interdiff.txt8.22 KBtstoeckler
#65 2350509-64.patch67.51 KBtstoeckler
#65 2350509-54-64-interdiff.txt6.51 KBtstoeckler
#54 2350509-54.patch66.84 KBtstoeckler
#54 2350509-52-54-interdiff.txt4.64 KBtstoeckler
#52 2350509-52.patch63.04 KBdawehner
#50 interdiff.txt4.28 KBdawehner
#50 2350509-49.patch63.03 KBdawehner
#48 2350509-48.patch59.32 KBdawehner
#46 interdiff-46-42.txt518 bytesmglaman
#46 2350509-46.patch59.61 KBmglaman
#42 interdiff.txt631 bytesdawehner
#42 2350509-42.patch59.6 KBdawehner
#40 2350509-39.patch59.57 KBdawehner
#40 interdiff.txt21.18 KBdawehner
#35 interdiff.txt7.02 KBdawehner
#35 2350509-35.patch42.44 KBdawehner
#32 interdiff.txt3 KBdawehner
#32 2350509-32.patch42.87 KBdawehner
#30 interdiff.txt7.32 KBdawehner
#30 2350509-30.patch42.88 KBdawehner
#28 2350509-28.patch35.61 KBdawehner
#28 interdiff.txt25.86 KBdawehner
#25 interdiff.txt4.46 KBdawehner
#25 2350509-25.patch28.31 KBdawehner
#21 interdiff.txt2.21 KBdawehner
#21 2350509-21.patch24.85 KBdawehner
#19 interdiff.txt5 KBdawehner
#19 2350509-19.patch22.64 KBdawehner
#17 interdiff.txt14.11 KBdawehner
#17 2350509-17.patch18.74 KBdawehner
#11 interdiff.txt1.74 KBdawehner
#11 2350509-11.patch7.79 KBdawehner
#8 2350509-8.patch7.83 KBdawehner
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Crell’s picture

larowlan’s picture

We already had an issue with a patch, any reason for new one?

dawehner’s picture

I do agree that the other issue had valuable discussions already, but it is quite outdated especially in terms what we plan now.

Wim Leers’s picture

Status: Active » Postponed
Wim Leers’s picture

dawehner’s picture

Yes it is.

dawehner’s picture

Status: Postponed » Active

Update the status.

dawehner’s picture

Status: Active » Needs review
FileSize
7.83 KB

Here is a basic start.

Status: Needs review » Needs work

The last submitted patch, 8: 2350509-8.patch, failed testing.

Berdir’s picture

+++ b/core/lib/Drupal/Core/Entity/Routing/DefaultRouteProvider.php
@@ -0,0 +1,60 @@
+    $route = (new Route(sprintf("/%s/{%s}", $entity_type_id, $entity_type_id)));
...
+    $route = (new Route(sprintf("/%s/{%s}/delete", $entity_type_id, $entity_type_id)));
...
+    $route = (new Route(sprintf("/%s/{%s}/edit", $entity_type_id, $entity_type_id)));

Shouldn't this use the link templates now? And be conditional based on that, e.g. don't generate a canonical route if the entity has no link template

Also thinking about patterns/ways to make it easy to override/customize, I think we talked about having a method per route or so..

dawehner’s picture

Status: Needs work » Needs review
FileSize
7.79 KB
1.74 KB

Shouldn't this use the link templates now? And be conditional based on that, e.g. don't generate a canonical route if the entity has no link template

You are absolute right!

Also thinking about patterns/ways to make it easy to override/customize, I think we talked about having a method per route or so..

It would be indeed good to think about it. Do you think it makes it easier requiring a new method compared to altering the collection directly?

Status: Needs review » Needs work

The last submitted patch, 11: 2350509-11.patch, failed testing.

tstoeckler’s picture

I think at least having a getBasePath() - which defaults to return $entity_type; would be quite useful. Especially for config entities...

Berdir’s picture

@tstoeckler: #2281645: Make entity annotations use link templates instead of route names landed, so now the link templates need to have the URL anyway, there's not much point in having an admin path or base path then?

tstoeckler’s picture

Oh, yes, sorry that was stupid. I had seen the commit, but it hadn't quite sunk in. Ignore me.

Berdir’s picture

Just thinking out loud, what about looping over link templates and then have a method name pattern based on that?

foreach ($this->entityType()->getLinkTemplates() as $name => $url) {
  $method = 'build' . camelize($name) . 'Route';
  if (method_exists($this, $method) && $route = $this->$method($url)) {
    $collection->add("entity.{$entity_type_id}." . magic_conversion($name), $route);
  }
}

My idea for this is that we can easily standardize the route name pattern. Subclasses can then decide if they want to override a method (to e.g. build a specific route completely custom), or they can still override getRoutes() and do whatever they want there.

Also, EntityTestRoutes might be a good example to convert to this instead of a route provider. My goal is still to have most of the entity test stuff being able to rely on default code. No idea why we have a custom controller for add/edit there, for example..

@tsteockler: See also #2401505: Add an entity collection template for lists , that will come pretty close to the idea of a base path for many, but not all entity types. But some are quite different, e.g. the collection url for users is now /admin/people

dawehner’s picture

Status: Needs work » Needs review
FileSize
18.74 KB
14.11 KB
  • Fixed user edit forms
  • Ensured that routes are just created when the corresponding link template exists
  • Converted some of the TestRoutes over
  • While doing so, ensured that the parameter conversions are set up properly.

Status: Needs review » Needs work

The last submitted patch, 17: 2350509-17.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
22.64 KB
5 KB

Fixed some failures and converted taxonomy over.

Status: Needs review » Needs work

The last submitted patch, 19: 2350509-19.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
24.85 KB
2.21 KB

...

tim.plunkett’s picture

Priority: Normal » Major

Status: Needs review » Needs work

The last submitted patch, 21: 2350509-21.patch, failed testing.

dawehner’s picture

I would consider this a critical bug after #2281645: Make entity annotations use link templates instead of route names, but that's just me.

Can you clarify why this blocks the release? Do you talk about the CRY argument of requiring the paths in multiple places? I am
not sure wether this is such a valid argument, given that previously it has been two places where the route name had to be entered.

dawehner’s picture

Status: Needs work » Needs review
FileSize
28.31 KB
4.46 KB

Fixed some issues and converted the vocabulary entity type.

Status: Needs review » Needs work

The last submitted patch, 25: 2350509-25.patch, failed testing.

Berdir’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php
    @@ -98,4 +100,32 @@ public function view(EntityInterface $_entity, $view_mode = 'full', $langcode =
    +   * @return string The title.
    +   * The title.
    

    Not really correct :)

  2. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultRouteProvider.php
    @@ -0,0 +1,73 @@
    +    $route = (new Route($entity_type->getLinkTemplate('canonical')));
    +    $route
    +      ->addDefaults([
    +        '_entity_view' => "{$entity_type_id}.full",
    +        '_title_callback' => '\Drupal\Core\Entity\Controller\EntityViewController::title',
    +      ])
    +      ->setRequirement('_entity_access', "{$entity_type_id}.view")
    +      ->setOption('parameters', [
    +        $entity_type_id => ['type' => 'entity:' . $entity_type_id],
    +      ]);
    

    The canonical route needs to be optional as well, most config entities don't have one I think, they can't be viewed.

  3. +++ b/core/modules/node/src/Entity/NodeRouteProvider.php
    @@ -15,37 +16,24 @@
    +    $collection->get('entity.node.canonical')
    +      ->setDefault('_entity_view', NULL)
    +      ->setDefault('_controller', '\Drupal\node\Controller\NodeViewController::view')
    

    This is a bit weird that we have to set it to NULL. Can't we make the thing that converts those routes intelligent enough to not overwrite an existing _controller?

  4. +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
    @@ -28,10 +28,14 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultRouteProvider",
    + *     },
    

    Should we rename the route provider to something like DefaultHtmlRouteProvider?

    Also, in #2364157: Replace most existing _url calls with Url objects, I noticed that we have a canonical route in entity_test.routing.yml, but just for this entity type, not generic, no idea way. Anyway, you can remove that one too.

  5. +++ b/core/modules/taxonomy/src/Entity/TermRouteProvider.php
    @@ -0,0 +1,39 @@
    +    $collection->get('entity.taxonomy_term.canonical')
    +      ->setDefault('_title', 'Taxonomy term');
    

    I might have asked this before, but what's the point of this _title, we also have a _title callback.

  6. +++ b/core/modules/taxonomy/src/Entity/VocabularyRouteProvider.php
    @@ -0,0 +1,32 @@
    +    $collection->get('entity.taxonomy_vocabulary.edit_form')
    +      ->setDefault('_entity_form', 'taxonomy_vocabulary.default')
    +      ->setDefault('_title_callback', 'Drupal\Core\Entity\Controller\EntityViewController::title');
    

    view controller title callback on the edit form? Should we have a useful default for this as well?

dawehner’s picture

Status: Needs work » Needs review
FileSize
25.86 KB
35.61 KB

The canonical route needs to be optional as well, most config entities don't have one I think, they can't be viewed.

Total valid point.

This is a bit weird that we have to set it to NULL. Can't we make the thing that converts those routes intelligent enough to not overwrite an existing _controller?

Does that mean we should that uri relationships just one level up? I still don't understand why we have to special case node here at all.

Should we rename the route provider to something like DefaultHtmlRouteProvider?

Sold.

I might have asked this before, but what's the point of this _title, we also have a _title callback.

Given that the entity ID is required there is none.

view controller title callback on the edit form? Should we have a useful default for this as well?

I think the best we should do is to provide a editTitle method and set it by default? This is related to [#2403359]l

I might have asked this before, but what's the point of this _title, we also have a _title callback.

It might have been important in earlier times, but I don't think its helpful any longer.

view controller title callback on the edit form? Should we have a useful default for this as well?

Moved it to EntityController, as a more generic place.

Also converted views, and tried to increase the failure rate again.

Status: Needs review » Needs work

The last submitted patch, 28: 2350509-28.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
Issue tags: +DX (Developer Experience)
FileSize
42.88 KB
7.32 KB

Converted roles and comment_type as well, and maybe fixed some failures.

Status: Needs review » Needs work

The last submitted patch, 30: 2350509-30.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
42.87 KB
3 KB

What does the bot say?

Status: Needs review » Needs work

The last submitted patch, 32: 2350509-32.patch, failed testing.

Wim Leers’s picture

Bot says no :(

  1. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    +/**
    + * Provides generic entity controllers, especially for titles.
    + */
    +class EntityController implements ContainerInjectionInterface {
    

    This will then clash with #2403359: Use _title and _title_callback where possible, but that's fine :) It should remove a large, large portion of that patch. I bet many of the test fixes you will need to borrow from there.

  2. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    +   * {@inerhtdi
    

    .

  3. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    +   * @return string The title.
    +   * The title.
    

    .

  4. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    +  public function title(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    ...
    +  public function editTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    ...
    +  public function deleteTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    

    Why not also addTitle() or createTitle()?

    And perhaps renaming title() to viewTitle() would make sense, too?

  5. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    +   *   The edit entity label.
    ...
    +   *   The delete entity label.
    

    These look strange. What about The 'edit entity' title. or The entity editing route title.?

  6. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    +      return $this->t('Edit %label', $entity->label());
    

    Wouldn't Edit %entity_type %label be more appropriate?

  7. +++ b/core/lib/Drupal/Core/Entity/EntityController.php
    @@ -0,0 +1,135 @@
    \ No newline at end of file
    

    .

  8. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,83 @@
    + * Provides a default implementation of an empty route provider.
    

    s/empty/entity/? :D

  9. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,83 @@
    +        ]);
    +
    +      $collection->add("entity.{$entity_type_id}.canonical", $route);
    ...
    +        ]);
    +      $collection->add("entity.{$entity_type_id}.edit_form", $route);
    ...
    +        ]);
    +      $collection->add("entity.{$entity_type_id}.delete_form", $route);
    

    Inconsistent whitespace.

  10. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,83 @@
    +      // Use the "edit" form handler, otherwise default.
    +      $operation = 'default';
    

    I wonder if it'd be better to change those who are using default to using edit instead?

  11. +++ b/core/modules/comment/src/CommentHtmlRouteProvider.php
    @@ -0,0 +1,32 @@
    + * Provides html routes for the comment entity type.
    
    +++ b/core/modules/comment/src/CommentTypeHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    + * Provides routes for the comment_type entity type.
    
    +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -0,0 +1,39 @@
    + * Provides routes for nodes.
    
    +++ b/core/modules/user/src/Entity/UserHtmlRouteProvider.php
    @@ -0,0 +1,45 @@
    + * Provides routes for the user entity.
    
    +++ b/core/modules/views_ui/src/ViewHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    + * Provides routes for the view html routes.
    

    Should be made consistent. Should all mention "HTML routes".

  12. +++ b/core/modules/comment/src/CommentTypeHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    +    $collection->get('entity.comment_type.edit_form')
    +      ->setOption('_admin_route', TRUE);
    +    $collection->get('entity.comment_type.delete_form')
    +      ->setOption('_admin_route', TRUE);
    

    If we'd detect bundle entity types in DefaultHtmlRouteProvider, then we could set _admin_route: TRUE automatically.

  13. +++ b/core/modules/comment/src/CommentTypeHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    \ No newline at end of file
    

    .

  14. +++ b/core/modules/node/node.routing.yml
    @@ -34,7 +34,7 @@ entity.node.preview:
    -    _title_callback: '\Drupal\node\Controller\NodePreviewController::title'
    +    _title_callback: '\Drupal\node\Controller\NodePreviewController::previewTitle'
    

    Why not change it to use EntityController::title() instead? (And then delete the custom title callback.)

  15. +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -0,0 +1,39 @@
    +      ->setDefault('_entity_view', NULL)
    

    Why?

  16. +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -0,0 +1,39 @@
    +      ->setDefault('_controller', '\Drupal\node\Controller\NodeViewController::view')
    +    ;
    

    Dangling semi-colon.

    Also: the only value of the custom controller is to set a bunch of HTML <HEAD> links. Why not just do that for all entities automatically? Then the custom code for Nodes can go away. No harm in that.

  17. +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -0,0 +1,39 @@
    +    $collection->get('entity.node.delete_form')->setOption('_node_operation_route', TRUE);
    +
    +    $collection->get('entity.node.edit_form')->setOption('_node_operation_route', TRUE);
    

    Inconsistent code formatting, compared with the other route providers.

  18. +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestBaseFieldDisplay.php
    @@ -21,15 +21,24 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
    + *     },
    

    Hm, I thought this would automatically be the default? I.e. I thought it wouldn't be necessary to define it in the annotation if you wanted to use the default HTML routes?

  19. +++ b/core/modules/taxonomy/src/Entity/TermHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    +      ->setDefault('_title', 'Delete term')
    

    This line can be deleted; the default title is superior. We also don't use the hardcoded title for editing terms anymore; no need to do it for deleting then.

  20. +++ b/core/modules/user/src/Entity/UserHtmlRouteProvider.php
    @@ -0,0 +1,45 @@
    +    $collection->get('entity.user.canonical')->setDefault('_title_callback', 'Drupal\user\Controller\UserController::userTitle');
    

    Inconsistent code formatting.

  21. +++ b/core/modules/user/src/Entity/UserHtmlRouteProvider.php
    @@ -0,0 +1,45 @@
    +      ->setDefault('_title_callback', 'Drupal\user\Controller\UserController::userTitle')
    

    Why keep this?

  22. +++ b/core/modules/views_ui/src/ViewHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    +      ->setDefault('_entity_form', NULL)
    

    ?

  23. +++ b/core/modules/views_ui/views_ui.module
    @@ -61,6 +62,7 @@ function views_ui_entity_type_build(array &$entity_types) {
         ->setLinkTemplate('break-lock-form', '/admin/structure/views/view/{view}/break-lock');
    +
     }
    

    Accidental whitespace.

dawehner’s picture

Status: Needs work » Needs review
FileSize
42.44 KB
7.02 KB

Thank you for your long

Why not also addTitle() or createTitle()?

And perhaps renaming title() to viewTitle() would make sense, too?

Mh, IMHO we don't have that link template defined yet, so its a little bit pointless for this issue to add it.

These look strange. What about The 'edit entity' title. or The entity editing route title.?

Went with the first one.

Wouldn't Edit %entity_type %label be more appropriate?

Well, this one seemed to be the one which is used most of the time, so I went with it. As we make things more consistent here, we can adapt it later, if needed.

Inconsistent whitespace.

Fixed

I wonder if it'd be better to change those who are using default to using edit instead?

There is clearly no actual strategy for existing code, so I would vote to keep it like that an decide in an issue whether the concept of a default form makes sense. I guess it doesn, as
we need a form for the add case as well.

Should be made consistent. Should all mention "HTML routes".

fixed.

If we'd detect bundle entity types in DefaultHtmlRouteProvider, then we could set _admin_route: TRUE automatically.

I won't do that, because I don't get why we manually add it here. The AdminRouteSubscriber should take care of it, if possible. Not sure why its added here,
but there is probably a reason.

Why not change it to use EntityController::title() instead? (And then delete the custom title callback.)

Well, its tricky as the NodePreviewController uses a different param converter.

Why?

Well, we have a custom controller, which I wanna use here (maybe not anymore in the future, but for now the amount of changes should be limited, if the patch should keep reviewable).

Also: the only value of the custom controller is to set a bunch of HTML links. Why not just do that for all entities automatically? Then the custom code for Nodes can go away. No harm in that.

Well, I think if we want to change the behaviour, we should do that separate, as it requires test coverage and what not. Its not in scope of this issue IMHO, which is about improving DX
for defining routes.

Hm, I thought this would automatically be the default? I.e. I thought it wouldn't be necessary to define it in the annotation if you wanted to use the default HTML routes?

Well, if you look at ContentEntityType and EntityType you won't see many handlers added by default. I kinda prefer to opt IN the behaviour and not require a way, to opt out of that behaviour. I don't
see a strict requirement why every entity type would require it.

This line can be deleted; the default title is superior. We also don't use the hardcoded title for editing terms anymore; no need to do it for deleting then.

fixed

Why keep this?

Oh, I first they do something different, but they do the same, just way more complex.

Alright, let's also fix stuff.

Status: Needs review » Needs work

The last submitted patch, 35: 2350509-35.patch, failed testing.

dawehner’s picture

Issue tags: +WSCCI

Add tag

Wim Leers’s picture

From 2460 fails to 117! Nice! :)


Mh, IMHO we don't have that link template defined yet, so its a little bit pointless for this issue to add it.

Oh, ok, never mind then :)

As we make things more consistent here, we can adapt it later, if needed.

Fair!

so I would vote to keep it like that an decide in an issue whether the concept of a default form makes sense

I see that angle, but the code introduced here is made more complicated because of that concept. I think we want input from more people about that.

The AdminRouteSubscriber should take care of it, if possible. Not sure why its added here,
but there is probably a reason.

Because:

  protected function alterRoutes(RouteCollection $collection) {
    foreach ($collection->all() as $route) {
      if (strpos($route->getPath(), '/admin') === 0 && !$route->hasOption('_admin_route')) {
        $route->setOption('_admin_route', TRUE);
      }
    }
  }

and the routes in this patch with _admin_route set don't have paths that begin with /admin.

Well, we have a custom controller, which I wanna use here (maybe not anymore in the future, but for now the amount of changes should be limited, if the patch should keep reviewable).

Ok. Could you document this? It was very puzzling to me why you'd set something to NULL.

Well, I think if we want to change the behaviour, we should do that separate, as it requires test coverage and what not.

Hrm, ok. Because it's so tightly related it feels sufficiently in scope, but: fair.

I kinda prefer to opt IN the behaviour and not require a way, to opt out of that behaviour. I don't see a strict requirement why every entity type would require it.

Right; there could be content entities that don't have HTML routes. Makes sense; thanks!

cgalli’s picture

I have tested this on the Content Entity Example from the examples Module with https://www.drupal.org/node/2409195 applied. Removed view, edit and delete route from the annotation.

The View, Edit and Delete links work perfectly well.

dawehner’s picture

Status: Needs work » Needs review
FileSize
21.18 KB
59.57 KB

@cgalli
Thank you for the manual testing. Good to know that it actually works :P

and the routes in this patch with _admin_route set don't have paths that begin with /admin.

Right, but there are exceptions, for whatever reason( admin/structure/comment/*,admin/structure/block/* )

Ok. Could you document this? It was very puzzling to me why you'd set something to NULL.

Sure.

Fixed all failures and later converted all the other entity types.

Status: Needs review » Needs work

The last submitted patch, 40: 2350509-39.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
59.6 KB
631 bytes

Ha, annotations <3

dawehner’s picture

Issue tags: +SprintWeekend2015

.

Status: Needs review » Needs work

The last submitted patch, 42: 2350509-42.patch, failed testing.

fago’s picture

mglaman’s picture

Status: Needs work » Needs review
FileSize
59.61 KB
518 bytes

Looks likes tests failed had exceptions due to incorrect namespace for FeedHtmlRouteProvider in annotation.

Status: Needs review » Needs work

The last submitted patch, 46: 2350509-46.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
59.32 KB

Good catch @mglaman

For now just a reroll.

Status: Needs review » Needs work

The last submitted patch, 48: 2350509-48.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
63.03 KB
4.28 KB

Some more work, not really happy about some of the required changes.

Status: Needs review » Needs work

The last submitted patch, 50: 2350509-49.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
63.04 KB

Reroll.

Status: Needs review » Needs work

The last submitted patch, 52: 2350509-52.patch, failed testing.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
4.64 KB
66.84 KB

This fixes some fails, hopefully.

Status: Needs review » Needs work

The last submitted patch, 54: 2350509-54.patch, failed testing.

jhodgdon’s picture

Issue summary: View changes

So, I realize that this patch isn't done (tests don't pass), but I'm not convinced this is a step forward.

It looks like most entities covered in the patch are losing a few lines in the routing.yml file, at the expense of having to define their own route provider class and reference in in entity annotation, apparently just to override some defaults that would otherwise just be part of the route definitions. This doesn't seem like great DX. It's easier to provide the defaults in the routing file than to define a class, I think, and it's way more lines being added than lost.

There are a few entities (like Feed in Aggregator module) that also don't seem to have lost anything in the routing.yml file and have only added lines in the annotation and the new class. This may be a problem in the patch, but is definitely not great DX.

And the patch will eventually need to update the Entity topic docs, so that developers know about this. I added a note about this to the issue summary so it doesn't get forgotten.

tstoeckler’s picture

Re @jhodgdon: The overrides that these entity types are just to be consistent with the current behavior: They will not be necessary for the majority of use-cases. Also the fact that this patch is uncovering all sorts of inconsistencies and weirdnesses between the different entity type is proof IMO that some form of generic implementation is needed or at least very helpful. We can always improve the base implementation in follow-ups so that maybe in the future less follow-ups will be necessary, but this is certainly a big step forward. I've been using this patch on a site I'm developing for a while now and it's a *big* timesaver.

Wim Leers’s picture

I share some of jhodgdon's DX concerns. Let me repeat a few points that I made in #34:

  • 12.
    +++ b/core/modules/comment/src/CommentTypeHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    +    $collection->get('entity.comment_type.edit_form')
    +      ->setOption('_admin_route', TRUE);
    +    $collection->get('entity.comment_type.delete_form')
    +      ->setOption('_admin_route', TRUE);
    

    If we'd detect bundle entity types in DefaultHtmlRouteProvider, then we could set _admin_route: TRUE automatically.

    to which dawehner replied

    I won't do that, because I don't get why we manually add it here. The AdminRouteSubscriber should take care of it, if possible. Not sure why its added here,
    but there is probably a reason.

  • 18.

    +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestBaseFieldDisplay.php
    @@ -21,15 +21,24 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
    + *     },
    

    Hm, I thought this would automatically be the default? I.e. I thought it wouldn't be necessary to define it in the annotation if you wanted to use the default HTML routes?

    to which dawehner replied:

    Well, if you look at ContentEntityType and EntityType you won't see many handlers added by default. I kinda prefer to opt IN the behaviour and not require a way, to opt out of that behaviour. I don't
    see a strict requirement why every entity type would require it.

    Which is a pretty good reason.

Perhaps revisiting those things could help the DX?

dawehner’s picture

Which is a pretty good reason.

If you look at the entity API you will see that its an explicit API, you specify what is done, and don't rely on the default
instead of just one single place.

It looks like most entities covered in the patch are losing a few lines in the routing.yml file, at the expense of having to define their own route provider class and reference in in entity annotation, apparently just to override some defaults that would otherwise just be part of the route definitions. This doesn't seem like great DX. It's easier to provide the defaults in the routing file than to define a class, I think, and it's way more lines being added than lost.

If you would be extreme, you could say, let's skip whatever core its doing, but for custom entity types you REALLY want to use it, and have a consistent behaviour.

jhodgdon’s picture

OK, I'll bow to your greater wisdom and tstoeckler's experience on this being better DX for defining your own entity type.

Regarding the complaint about having to specify using the default route builder, I think that in most other areas of the Entity API, such as the Access controller, we've made it so if you're using the default class, you don't have to specify it. So I think that should be the default here too? But that is not a huge deal, as it's only one line in the annotation.

Also, one note about the "admin_route" designation of routes... It seems to me that the default controller should and could choose more sensible defaults. For instance, it could designate either all routes, or just edit/add/delete routes (omitting "canonical"), for Config entities as admin_route. Alternatively, Core could provide two default classes, the first as it is now, and the second having this admin_route default set, so that entities could choose one or the other as their route provider without the necessity of defining their own class, and we wouldn't have to have a bunch of little classes floating around whose sole purpose is to set the admin_route flag on their routes. That would cut the size of this patch down considerably -- there are at least 4 classes in there whose sole purpose is to set admin_route defaults I think.

Another reason entities in this patch seem to be overriding the default class is to specify the title, but I think these overrides can actually be omitted. Most controllers for these things override the title for the page anyway, so the title in the current routing files is rarely if ever even used.

Anyway... just a couple of thoughts on how to possibly improve the DX in this patch.

Wim Leers’s picture

That would cut the size of this patch down considerably -- there are at least 4 classes in there whose sole purpose is to set admin_route defaults I think.

+1

Another reason entities in this patch seem to be overriding the default class is to specify the title, but I think these overrides can actually be omitted.

+1

dawehner’s picture

OK, I'll bow to your greater wisdom and tstoeckler's experience on this being better DX for defining your own entity type.

Let's try to be friends :)

Also, one note about the "admin_route" designation of routes... It seems to me that the default controller should and could choose more sensible defaults. For instance, it could designate either all routes, or just edit/add/delete routes (omitting "canonical"), for Config entities as admin_route. Alternatively, Core could provide two default classes, the first as it is now, and the second having this admin_route default set, so that entities could choose one or the other as their route provider without the necessity of defining their own class, and we wouldn't have to have a bunch of little classes floating around whose sole purpose is to set the admin_route flag on their routes. That would cut the size of this patch down considerably -- there are at least 4 classes in there whose sole purpose is to set admin_route defaults I think.

That sounds like a good thing to experiment with!

Regarding the complaint about having to specify using the default route builder, I think that in most other areas of the Entity API, such as the Access controller, we've made it so if you're using the default class, you don't have to specify it. So I think that should be the default here too? But that is not a huge deal, as it's only one line in the annotation.

Well, we do it for 2 cases: a) the storage controller and b) the access control handler ... For everything else we are explicit. I think one of the entity subsystem group should
tell us their opinion, given that they actually know the intended behavior of those annotations.

Another reason entities in this patch seem to be overriding the default class is to specify the title, but I think these overrides can actually be omitted. Most controllers for these things override the title for the page anyway, so the title in the current routing files is rarely if ever even used.

Note: we need the title on the routes for breadcrumbs.

Anyway... just a couple of thoughts on how to possibly improve the DX in this patch.

Its good that you care about it?

jhodgdon’s picture

RE: friends, of course! I really was not trying to be snarky, and I apologize if it came across that way. I see the wisdom of what you said and agree with it.

RE: route titles and breadcrumbs -- oh interesting. I hadn't thought of that. I guess that is important only for routes that are the base for local task/action groups then?

Berdir’s picture

+1 for making it explicit, that you have to specify it. That was the condition that we agreed on in Amsterdam to allow introducing this so late, that it is an opt-in mechanism. Otherwise it is going to mess up existing modules.

As @dawehner mentioned, we only do it for just storage, which just works for all entities, and entity access, which doesn't do anything else but checking the admin permission as defined. This is too experimental to enable it by default, at least for a first version.

Also, as @dawehner and @tstoeckler mentioned, almost all our entity types have some special cases which is why the defaults don't work for them and they do need overrides.

  1. +++ b/core/modules/aggregator/src/FeedHtmlRouteProvider.php
    @@ -0,0 +1,31 @@
    +    $collection->get('entity.aggregator_feed.edit_form')
    +      ->setDefault('_title', 'Configure')
    +      ->setOption('_admin_route', TRUE);
    

    I'm not sure if Configure is really something that we need to keep, but I wouldn't be surprised if we do have a test for this somewhere?

    Agreed that we could consider to set _admin_route to TRUE by default for edit/delete, this for example does not set it for delete, which is very likely an oversight, possibly in HEAD as well. _admin_route TRUE for edit/delete seems like a good default. That said, that just means that node will have to override more, as that part is configurable there, because nodes like to be special.

  2. +++ b/core/modules/comment/src/CommentTypeHtmlRouteProvider.php
    @@ -0,0 +1,32 @@
    +    $collection->get('entity.comment_type.edit_form')
    +      ->setOption('_admin_route', TRUE);
    +    $collection->get('entity.comment_type.delete_form')
    +      ->setOption('_admin_route', TRUE);
    

    I don't really see why this should be necessary though, those are /admin paths anyway? All config entities should be But setting it by default won't hurt either.

  3. +++ b/core/modules/file/src/Tests/SaveUploadTest.php
    @@ -69,7 +69,7 @@ protected function setUp() {
    -  function testNormal() {
    +  function ptestNormal() {
    

    ups.

  4. +++ b/core/modules/menu_link_content/src/Plugin/Menu/MenuLinkContent.php
    @@ -187,14 +187,14 @@ public function getDeleteRoute() {
       public function getTranslateRoute() {
    -    return $this->getEntity()->urlInfo('content-translation-overview');
    +    return $this->getEntity()->urlInfo('drupal:content-translation-overview');
       }
    

    Looks like you found that problem here as well with the wrong prefix, that was afaik just fixed in HEAD.

  5. +++ b/core/modules/rest/src/Tests/AuthTest.php
    +++ b/core/modules/rest/src/Tests/AuthTest.php
    @@ -91,6 +91,7 @@ protected function basicAuthGet(Url $url, $username, $password) {
    
    @@ -91,6 +91,7 @@ protected function basicAuthGet(Url $url, $username, $password) {
             CURLOPT_URL => $url->setAbsolute()->toString(),
             CURLOPT_NOBODY => FALSE,
             CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
    +        CURLOPT_HTTPHEADER => array('Accept: ' . $this->defaultMimeType),
             CURLOPT_USERPWD => $username . ':' . $password,
           )
    

    Why is this suddenly necessary? entity_test route changes?

  6. +++ b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
    @@ -41,6 +41,9 @@ protected function setUp() {
    +    $account = $this->drupalCreateUser(['view test entity']);
    +    $account->save();
    

    save is not necessary, drupalCreateUser() saves the user already.

tstoeckler’s picture

FileSize
6.51 KB
67.51 KB

I noticed some more routes and other things that can be removed. Did not tackle the tests yet.

Because Wim Leers' happiness is of ample importance to me, I wondered if it would make sense to introduce a HtmlRouteProviderThatUsesTheAdminRouteOptionForEditAndDeleteFormRoutesByDefault in order to consolidate the different route providers that set _admin_route to TRUE. (I think that is along the lines of what you proposed above, right?) It turns out, though, that each of those (but for one) also does something special like setting a different title or something. So it wouldn't actually be a net reduction of code (although it might be helpful for contrib?).

Edit: The paragraph above is bollocks (except, of course, the first subclause <3 :-)), sorry. New patch coming up.

tstoeckler’s picture

FileSize
8.22 KB
65.29 KB

Ok, here we go.

I just now saw #64, so this includes the fixes for this as well. I did not fix 1., though. I think when this is green we can see what fails if we remove the FeedHtmlRouteProvider, and then evaluate.

So this one - I think - will make @Wim Leers happy :-)

It introduces an AdminHtmlRouteProvide which is used directly by BlockContent and Term and extended by Feed and User. I think that is more explicit than simply making it the default. Then we would have to disable it for e.g. comments as well.

Berdir was right and CommentType in fact does not need the override at all.

dawehner’s picture

Status: Needs work » Needs review

...

Status: Needs review » Needs work

The last submitted patch, 66: 2350509-66.patch, failed testing.

tstoeckler’s picture

Status: Needs work » Needs review
FileSize
942 bytes
65.35 KB

Well, that was not too smart.

This installs at least.

Status: Needs review » Needs work

The last submitted patch, 69: 2350509-68.patch, failed testing.

Wim Leers’s picture

dawehner’s picture

Status: Needs work » Needs review
FileSize
65.42 KB

Just a reroll for now.

Status: Needs review » Needs work

The last submitted patch, 72: 2350509-72.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
72.88 KB
7.45 KB

Some fixes here and there.

Status: Needs review » Needs work

The last submitted patch, 74: 2350509-74.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
77.1 KB
4.23 KB

More fixes.

Status: Needs review » Needs work

The last submitted patch, 76: 2350509-76.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review
FileSize
77.22 KB

Reroll.

Status: Needs review » Needs work

The last submitted patch, 78: 2350509-78.patch, failed testing.

Crell’s picture

Overall I like the direction this is going. Some comments:

  1. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,135 @@
    +  /**
    +   * Determines the entity.
    +   *
    +   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
    +   *   The route match.
    +   * @param \Drupal\Core\Entity\EntityInterface $_entity
    +   *   (optional) The entity.
    +   *
    +   * @return \Drupal\Core\Entity\EntityInterface|NULL
    +   *   Returns the entity, otherwise NULL.
    +   */
    +  protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    

    In what circumstances would the entity not already be loaded in the parameter bag and therefore available for the reflection-based parameter passing? That seems like a bug; if there's a legit non-bug reason for it, it should be documented.

  2. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,82 @@
    +    if ($entity_type->hasLinkTemplate('canonical')) {
    +      $route = (new Route($entity_type->getLinkTemplate('canonical')));
    +      $route
    +        ->addDefaults([
    +          '_entity_view' => "{$entity_type_id}.full",
    +          '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title',
    +        ])
    +        ->setRequirement('_entity_access', "{$entity_type_id}.view")
    +        ->setOption('parameters', [
    +          $entity_type_id => ['type' => 'entity:' . $entity_type_id],
    +        ]);
    +      $collection->add("entity.{$entity_type_id}.canonical", $route);
    +    }
    

    Let's take each of these blocks and turn it into a method call for better SRP. Ie:

    if ($entity_type->hasLinkTemplate('canonical') { 
      $route = $this->getCanonicalRoute();
      $collection->add('...', $route);
    }
    

    That way getRoutes() becomes easier to read, and each discrete task is in its own (reusable!) method.

    Additionally, if entity.entitytype.canonical is manually defined via YAML already we want to skip this entirely, IIRC. Is that check already happening somewhere else, and if not, how do we make it happen?

  3. +++ b/core/modules/comment/src/CommentHtmlRouteProvider.php
    @@ -0,0 +1,32 @@
    +        '_title_callback' => '\Drupal\comment\Controller\CommentController::commentPermalinkTitlek',
    

    I think there's an extra k here. :-)

  4. +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -0,0 +1,40 @@
    +    $collection->get('entity.node.canonical')
    +      ->setDefault('_entity_view', NULL)
    +      ->setDefault('_controller', '\Drupal\node\Controller\NodeViewController::view');
    

    Ideally in a follow-up we can eliminate this exception. It's just there for links, which ought to be automated anyway.

  5. +++ b/core/modules/rest/src/Tests/AuthTest.php
    +++ b/core/modules/rest/src/Tests/AuthTest.php
    @@ -91,6 +91,7 @@ protected function basicAuthGet(Url $url, $username, $password) {
    
    @@ -91,6 +91,7 @@ protected function basicAuthGet(Url $url, $username, $password) {
             CURLOPT_URL => $url->setAbsolute()->toString(),
             CURLOPT_NOBODY => FALSE,
             CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
    +        CURLOPT_HTTPHEADER => array('Accept: ' . $this->defaultMimeType),
             CURLOPT_USERPWD => $username . ':' . $password,
           )
         );
    

    This seems unrelated? (I'm not against it, jut just seems unrelated.)

  6. +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php
    @@ -25,12 +25,16 @@
    + *   admin_permission = "administer entity_test content",
    

    Can't this be automated? We automate most entity permissions already, I believe...

  7. +++ b/core/modules/user/src/Entity/UserHtmlRouteProvider.php
    @@ -0,0 +1,44 @@
    +    $collection->remove('entity.user.delete');
    +
    +    $route = (new Route('/user/{user}/cancel'))
    +      ->setDefaults([
    +        '_title' => 'Cancel account',
    +        '_entity_form' => 'user.cancel',
    +      ])
    +      ->setOption('_admin_route', TRUE)
    +      ->setRequirement('_entity_access', 'user.delete');
    +    $collection->add('entity.user.cancel_form', $route);
    

    This might be scope creep, but shouldn't we keep the route names/behavior as similar as possible? Account cancelation may involve deletion, so should it reuse the same route name for consistency, even if we change some of the parameters on it?

My bigger issue, though, is the heavy use of inheritance. Default->Admin->Specific seems like a bad way to do it, since there's no is-a relationship. What we actually want here is a way to mix and match common auto-routes.

Instead, perhaps we could have a CommonRoutesTrait and AdminRoutesTrait. Then a DefaultRouteHandler could use both of those, and its getRoutes method just calls the methods out of those traits and returns. (As noted above, that should be a lot of little methods rather than 1-2 big ones.) Then instead of extending and extending, each entity-specific implementation could use those same traits and call the methods it wants. If it doesn't have anything custom to do, it can just use Default which is fine. That allows, say, admin routes without the default routes. (Since "has admin routes" is not a strict special-case of "has the common routes", conceptually.)

It might be slightly more verbose, depending on the details, but I think it will be a clearer separation of concerns and give developers both more flexibility and better education about what's going on. Layers of base classes can be rather opaque in that regard.

Status: Needs work » Needs review

jibran queued 78: 2350509-78.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 78: 2350509-78.patch, failed testing.

Crell’s picture

Would it get this issue moving if we didn't do all the conversions at once? Just get the mechanism in place (and therefore available to contrib) and do the easy conversions. If some are tricky, we can punt on those or even leave them as manual; the way this is setup manual still works and will continue to work, by design, so we don't have to do it all at once.

But this is an important DX improvement for both entity devs and RESTful devs.

dawehner’s picture

I would have loved to do it that way, but I'm not sure who, but I remember there was a strong push forward to do them all ...

dawehner’s picture

Status: Needs work » Needs review
FileSize
76.29 KB
18.11 KB

In what circumstances would the entity not already be loaded in the parameter bag and therefore available for the reflection-based parameter passing? That seems like a bug; if there's a legit non-bug reason for it, it should be documented.

Yeah I don't remember at all, but it was kinda needed for some failures, this is what I remember.

That way getRoutes() becomes easier to read, and each discrete task is in its own (reusable!) method.

Solved that.

Additionally, if entity.entitytype.canonical is manually defined via YAML already we want to skip this entirely, IIRC. Is that check already happening somewhere else, and if not, how do we make it happen?

Do you mind adding this into a follow up? We aren't doing that yet.

This seems unrelated? (I'm not against it, jut just seems unrelated.)

Alright, let's try to drop and see what fails.

`Can't this be automated? We automate most entity permissions already, I believe...

OUT OF SCOPE, and no, this is like asking for automating the path for a canonical link template.

This might be scope creep, but shouldn't we keep the route names/behavior as similar as possible? Account cancelation may involve deletion, so should it reuse the same route name for consistency, even if we change some of the parameters on it?

No, user deletion is NOT user cancelation, see https://www.drupal.org/node/8

My bigger issue, though, is the heavy use of inheritance. Default->Admin->Specific seems like a bad way to do it, since there's no is-a relationship. What we actually want here is a way to mix and match common auto-routes.

Seriously, this is what you worry about? Seen worse things in my life and IMHO inheritance makes sense. Well, default should extend from a base, but then IMHO it totally makes sense

Instead, perhaps we could have a CommonRoutesTrait and AdminRoutesTrait. Then a DefaultRouteHandler could use both of those, and its getRoutes method just calls the methods out of those traits and returns. (As noted above, that should be a lot of little methods rather than 1-2 big ones.) Then instead of extending and extending, each entity-specific implementation could use those same traits and call the methods it wants. If it doesn't have anything custom to do, it can just use Default which is fine. That allows, say, admin routes without the default routes. (Since "has admin routes" is not a strict special-case of "has the common routes", conceptually.)

I think using traits would make it harder to read, because you'd still have a admin one, which calls out to the trait methods, which then do pretty much nothing. Feel free to rewrite the code though, but I think using traits would make it actually harder in terms of DX, which is IMHO the point of this issue.

dawehner’s picture

FileSize
77.33 KB
1.04 KB

Forgot to add one file.

The last submitted patch, 86: 2350509-86.patch, failed testing.

tim.plunkett’s picture

  1. +++ b/core/modules/block_content/src/Tests/PageEditTest.php
    @@ -62,7 +62,7 @@ public function testPageEdit() {
    -    $this->drupalGet("block/" . $revised_block->id());
    +    $this->drupalGet($block->urlInfo('edit-form'));
    

    $revised_block->urlInfo()

  2. +++ b/core/modules/user/src/Entity/UserHtmlRouteProvider.php
    @@ -0,0 +1,44 @@
    +  public function getRoutes(EntityTypeInterface $entity_type) {
    +    $collection = parent::getRoutes($entity_type);
    +
    +    $collection->get('entity.user.canonical')->setDefault('_title_callback', 'Drupal\user\Controller\UserController::userTitle');
    
    +++ b/core/modules/views_ui/src/ViewHtmlRouteProvider.php
    @@ -0,0 +1,34 @@
    +  protected function getEditFormRoute(EntityTypeInterface $entity_type) {
    +    $route = parent::getEditFormRoute($entity_type);
    +
    +    // Replace the _entity_form with a custom _controller.
    +    $route
    

    Why use this approach for some and the other for others?

Status: Needs review » Needs work

The last submitted patch, 87: 2350509-87.patch, failed testing.

lokapujya’s picture

+++ b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php
@@ -0,0 +1,37 @@
+/**
+ * Provides routes for the taxonomy_term entity.
+ */
+class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider {

What should this comment really say? Provides the default admin routes for config entities?

dawehner’s picture

Status: Needs work » Needs review
FileSize
77.33 KB
1.68 KB

$revised_block->urlInfo()

Good catch!!

Why use this approach for some and the other for others?

I went with a single overridden method on the user case, because its extending the list in multiple other ways at the same time.
Feel free to disagree.

What should this comment really say? Provides the default admin routes for config entities?

Ha, improved the comment.

Status: Needs review » Needs work

The last submitted patch, 92: 2350509-91.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
79.86 KB
2.53 KB

There we go.

Status: Needs review » Needs work

The last submitted patch, 94: 2350509-94.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
79.94 KB
2.29 KB

Maybe now ...

willzyx’s picture

Status: Needs review » Needs work
FileSize
35.84 KB

manually tested shortcuts after #96 and this is the result for canonical route (empty page)

patch in #96 passes because it simply bypass checks in ShortcutLinksTest

looking at shortcut.routing.yml

+++ b/core/modules/shortcut/shortcut.routing.yml
@@ -54,22 +54,6 @@ shortcut.link_add:
-entity.shortcut.canonical:
-  path: '/admin/config/user-interface/shortcut/link/{shortcut}'
-  defaults:
-    _entity_form: 'shortcut.default'
-    _title: 'Edit'
-  requirements:
-    _entity_access: 'shortcut.update'

entity.shortcut.canonical coincides with entity.shortcut.edit_form so probably we should create a dedicated class to handle it

willzyx’s picture

FileSize
2.89 KB
79.4 KB

reverted changes in ShortcutLinksTest and added a dedicated class for shortcut

willzyx’s picture

Status: Needs work » Needs review
dawehner’s picture

@willzyx
Well, I think shortcuts are pretty stupid, in the way how the configured routes look like,
so I'm not sure whether its really the best idea to let the canonical route point to the edit route as well, but sure, feel free to do this here.

So now we need some proper reviews ... its green!

Crell’s picture

+++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
@@ -0,0 +1,135 @@
+/**
+ * Provides generic entity controllers, especially for titles.
+ */
+class EntityController implements ContainerInjectionInterface {

I quite like this. However, in the past our "very standard" controllers were registered as services to make them a little cleaner. Should we do that here as well, rather than using ContainerInjectionInterface? (Basically no perf diff, but it means the route is a little simpler as it just needs a service name, not a full class name.)

(Need to come back and finish review later, sorry.)

dawehner’s picture

Assigned: Unassigned » Crell
Issue tags: +Stalking Crell

ping crell!

andypost’s picture

+1 rtbc, looks solid

NW for:
1) needs consistency in having of entity route providers - admin_route is not a default
2) change record (NodeRouteProvider renamed)
Probably follow-up for entity translation routes

Also we need to link here #2407505: [meta] Finalize the menu links (and other user-entered paths) system

+++ b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php
@@ -0,0 +1,37 @@
+class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider {

+++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
@@ -0,0 +1,130 @@
+class DefaultHtmlRouteProvider implements EntityRouteProviderInterface {

+++ b/core/modules/aggregator/src/Entity/Feed.php
@@ -30,7 +30,10 @@
+ *       "html" = "Drupal\aggregator\FeedHtmlRouteProvider",

+++ b/core/modules/aggregator/src/FeedHtmlRouteProvider.php
@@ -0,0 +1,29 @@
+class FeedHtmlRouteProvider extends AdminHtmlRouteProvider {

+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -34,7 +34,10 @@
+ *       "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",

+++ b/core/modules/comment/src/CommentHtmlRouteProvider.php
@@ -0,0 +1,31 @@
+class CommentHtmlRouteProvider extends DefaultHtmlRouteProvider {

+++ b/core/modules/comment/src/Entity/Comment.php
@@ -35,7 +35,10 @@
+ *       "html" = "Drupal\comment\CommentHtmlRouteProvider",

+++ b/core/modules/comment/src/Entity/CommentType.php
@@ -24,7 +24,10 @@
+ *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",

+++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
@@ -31,7 +31,10 @@
+ *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",

+++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
@@ -0,0 +1,40 @@
+class NodeHtmlRouteProvider extends DefaultHtmlRouteProvider {

+++ b/core/modules/taxonomy/src/Entity/Term.php
@@ -31,7 +31,10 @@
+ *       "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",

+++ b/core/modules/taxonomy/src/Entity/Vocabulary.php
@@ -24,7 +24,10 @@
+ *       "html" = "Drupal\taxonomy\Entity\VocabularyRouteProvider",

+++ b/core/modules/taxonomy/src/Entity/VocabularyRouteProvider.php
@@ -0,0 +1,31 @@
+class VocabularyRouteProvider extends DefaultHtmlRouteProvider {

+++ b/core/modules/taxonomy/taxonomy.routing.yml
@@ -14,26 +14,6 @@ entity.taxonomy_term.add_form:
-entity.taxonomy_term.edit_form:
...
-    _admin_route: TRUE
...
-entity.taxonomy_term.delete_form:
...
-    _admin_route: TRUE

CommentHtml should be inherited from Admin provider
Same for comment type, menu link, node - we have mostly all edit operations in "admin" so maybe add "_admin_route: TRUE" in default?

dawehner’s picture

CommentHtml should be inherited from Admin provider
Same for comment type, menu link, node - we have mostly all edit operations in "admin" so maybe add "_admin_route: TRUE" in default?

Good point!

2) change record (NodeRouteProvider renamed)

I'm sorry but I don't think that this is an API.

Crell’s picture

Assigned: Crell » dawehner
Issue tags: -Stalking Crell, -Needs change record

As andypost noted, it seems like everything ought to be extending from AdminHtmlRouteProvider now. Which suggests that we shouldn't even have it. Just fold the _admin_route logic into the DefaultHtmlRouteProvider. That would also nicely sidestep my concerns about too much inheritance, because... we won't be inheriting as much. Problem solved. :-)

Other than that, a few minor nitpicks as noted below. Once those are addressed and AdminHtmlRouteProvider is folded into the parent, I think this is RTBC. dawehner, if you'd do the honors I'll try to not take so long to get back to you this time. :-(

I also agree there's no change record here. These are not API classes.

  1. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,130 @@
    +      $route = (new Route($entity_type->getLinkTemplate('canonical')));
    

    The outer-most parentheses here seem extraneous. Left-over from trying to chain everything, maybe?

    (Same in other methods.)

  2. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,130 @@
    +      // Use the "edit" form handler, otherwise default.
    

    "Use the edit form handler *if available*, otherwise default."

  3. +++ b/core/modules/block_content/src/Entity/BlockContent.php
    @@ -34,7 +34,10 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
    + *     },
    

    Hm. Something else I just realized. "route provider" is already the name of a class, and a rather important one. Using this key here is self-descriptive, but also likely to be confusing. :-(

    Unfortunately, the key there and the class names are not introduced in this patch, so it may be too late to change it. Blast!

  4. +++ b/core/modules/taxonomy/src/Entity/VocabularyRouteProvider.php
    @@ -0,0 +1,31 @@
    +    // Vocabularies use the "$vocabulary->label()" instead of
    +    // "Edit $vocabulary->label()".
    

    "Vocabularies use the *title* ..."

  5. +++ b/core/modules/user/src/Entity/UserHtmlRouteProvider.php
    @@ -0,0 +1,44 @@
    +    $route = (new Route('/user/{user}/cancel'))
    +      ->setDefaults([
    +        '_title' => 'Cancel account',
    +        '_entity_form' => 'user.cancel',
    +      ])
    +      ->setOption('_admin_route', TRUE)
    +      ->setRequirement('_entity_access', 'user.delete');
    +    $collection->add('entity.user.cancel_form', $route);
    

    This ought to have a link defined in the annotation to piggy back off of, no? That would be consistent with all of the other routes. That we then generate the route for it custom here doesn't change that.

tstoeckler’s picture

I don't think it makes sense for the admin one to be the default as then we would have to undo the _admin_route option for a bunch of entity types. I think having to undo a previous implementation is a sign of over-generalization and bad design.

I am also not a fan of huge inheritance chain, but IMO it's not fair to complain about that here when we have enormous inheritance chains all over core (Typed Data, anyone?). If we want to avoid that, let's do the following: Let's add a getRouteOptions() (or similar) method which is returns an empty array by default and then let's add a trait which implements this method and returns ['_admin_route' => TRUE].

Crell’s picture

@tstoeckler: Don't get me started on TypedData's inheritance tree... But just because one subsystem abused the extends keyword doesn't mean we have carte blanche to do it elsewhere.

What bunch of entities do we not want the edit-et-al pages to be admin-marked? Do you disagree with andypost that most if not all of them are/should be?

I don't follow your trait suggestion. Can you provide a brief code snippet to show what you mean?

willzyx’s picture

Issue tags: +Needs reroll

the patch needs a reroll

willzyx’s picture

Issue tags: -Needs reroll
FileSize
79.37 KB
dawehner’s picture

What bunch of entities do we not want the edit-et-al pages to be admin-marked? Do you disagree with andypost that most if not all of them are/should be?

Let's stop talking BS and look at actual data:

The following ones aren't using the AdminHtmlRoutesProvider (for example extend the Html one because of other reasons):

  • comment
  • comment_type
  • menu_link_content
  • node
  • shortcut_html

The following are:

  • feed
  • block_content
  • taxonomy_term
  • user

I think given that the default should not be the admin one, node and comment aren't a special case, if you ask me.

Crell’s picture

Eh, let's move forward here with the admin routes as is. The other items from #105 still need to be addressed, though. (No interdiff on #109 so I am assuming it was a straight reroll.)

dawehner’s picture

FileSize
79.35 KB
2.77 KB

The outer-most parentheses here seem extraneous. Left-over from trying to chain everything, maybe?

(Same in other methods.)

OH yeah this is annoying.

Hm. Something else I just realized. "route provider" is already the name of a class, and a rather important one. Using this key here is self-descriptive, but also likely to be confusing. :-(

Unfortunately, the key there and the class names are not introduced in this patch, so it may be too late to change it. Blast!

Well, the FQCN for itself should describe things. We should have put the route provider into the namespace ...

This ought to have a link defined in the annotation to piggy back off of, no? That would be consistent with all of the other routes. That we then generate the route for it custom here doesn't change that.

Not sure what to respond, honestly.

Crell’s picture

For the last point, I mean that we should declare a "cancel" link relation on User, give it a URI in the annotation, and then use that data to generate the route just like we do for all of the other routes.

dawehner’s picture

For the last point, I mean that we should declare a "cancel" link relation on User, give it a URI in the annotation, and then use that data to generate the route just like we do for all of the other routes.

Sounds quite out of scope of this issue!

Crell’s picture

No it's not. Doing it right should never be out of scope.

dawehner’s picture

FileSize
79.75 KB
1.27 KB

Ha, I think given that we actually have a link relation already, not using it, is actually wrong :)

bojanz’s picture

As someone making a lot of entity types in contrib right now, I'm loving this patch :)
I'm also loving the consistency it adds to the core entity routes. The current _admin_path approach for edit/delete makes sense.

+  protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
+    if ($_entity) {
+      $entity = $_entity;
+    }

It's a bit weird that the $_entity parameter has an underscore in front, telling me it's somehow special, but no comment explaining why.

        // Let's look up in the route object for the name of upcasted values.
+      foreach ($route_match->getParameters() as $parameter) {
+        if ($parameter instanceof EntityInterface) {
+          $entity = $parameter;
+          break;
+        }
+      }

This will probably be triggered in Commerce, since we've opted out of the magical automatic entity upcasting.
Would it make more sense to take the last entity parameter instead of the first?
Sometimes you nest UIs, in which case taking the last parameter would cover more use cases.

+    $collection->get('entity.node.canonical')
+      ->setDefault('_entity_view', NULL)

Why do this? A comment might help.

Docs nitpicking:

+/**
+ * Provides generic entity controllers, especially for titles.
+ */

Odd comment for a single class. Perhaps simply "Provides a generic entity controller."? Not sure if we want to focus on the title aspect since the class might grow in the future.

+ * It provides:
+ * - A view route with title callback.
+ * - An edit route with title callback.
+ * - A delete route with title callback.

...with a title callback?

+          foreach ($routes as $route_name => $route) {
+            // Don't override static defined routes.
+            if (!$route_collection->get($route_name)) {

Don't override existing routes? Or already defined routes?

dawehner’s picture

FileSize
80.1 KB
3.11 KB

Thank you @bojanz!!

It's a bit weird that the $_entity parameter has an underscore in front, telling me it's somehow special, but no comment explaining why.

Nothing introduced in that patch, but sure, let's add some documentation

This will probably be triggered in Commerce, since we've opted out of the magical automatic entity upcasting.
Would it make more sense to take the last entity parameter instead of the first?
Sometimes you nest UIs, in which case taking the last parameter would cover more use cases.

Well, I think because IMHO its more likely to do so. But honestly, I don't give a shit that you are doing things the wrong way.
All you need is to add the entity interface onto your controller, its not that hard.

Perhaps simply "Provides a generic entity controller."?

...with a title callback?

Sure, let's do that.

Don't override existing routes? Or already defined routes?

Went with the first one.

Crell’s picture

Twi minor nitpicks, then we're done.

  1. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -16,7 +16,12 @@
    + * Provides a generic entity controllers.
    

    Remove the "a". Doesn't parse in English.

  2. +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -25,6 +25,7 @@ public function getRoutes(EntityTypeInterface $entity_type) {
    +      // Use a custom controller, sadly, there is no removeDefault method.
    

    The first comma should be a semi-colon or period.

jhodgdon’s picture

One other thing... I don't have time to look at this in more detail right now, but there is no update to a .api.php file in this patch. I think that some Entity topic on api.drupal.org most likely needs an update about this change, and this should be part of the patch?
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!entity.api...

It seems like probably several parts of this topic need to be updated.

kgoel’s picture

reroll first

kgoel’s picture

Ugh, I feel like an idiot and I don't understand why patch in #121has INSTALL.txt, MAINTAINERS.txt, composer and so on. Patch file itself look fine on my local and don't have the above files. I was going to continue work on addressing concerns from #119 and #120but I think I need to wait until I or someone else can figure out what's going on.

kgoel’s picture

another reroll. let see.....

Status: Needs review » Needs work

The last submitted patch, 123: 2350509-123.patch, failed testing.

Status: Needs work » Needs review

willzyx queued 123: 2350509-123.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 123: 2350509-123.patch, failed testing.

lokapujya’s picture

I was working on this issue, but didn't mean to post this here. Please ignore this patch.

lokapujya’s picture

Status: Needs work » Needs review
lokapujya’s picture

Here's a reroll of #118, with the #119 items. If #127 passes, it might be the solution to some remaining test fails.

The last submitted patch, 127: jjf_test3.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 129: 2350509-129.patch, failed testing.

lokapujya’s picture

Status: Needs work » Needs review
FileSize
80.86 KB
2.02 KB

Try this.

Status: Needs review » Needs work

The last submitted patch, 132: 2350509-132.patch, failed testing.

lokapujya’s picture

Status: Needs work » Needs review
FileSize
81.24 KB
691 bytes

Revert the route change.

Status: Needs review » Needs work

The last submitted patch, 134: 2350509-134.patch, failed testing.

The last submitted patch, 134: 2350509-134.patch, failed testing.

Crell’s picture

With no interdiff in #123 or #127 I'm not clear what is wrong here. All that was left is docfixes, right?

lokapujya’s picture

123 was a reroll.
127 can be ignored.

Some changes in head regarding caching caused some test fails. There were 3 in #129. Now there are 2.

Todo:
1.

+++ b/core/modules/menu_link_content/src/Tests/MenuLinkContentTranslationUITest.php
@@ -20,7 +20,7 @@ class MenuLinkContentTranslationUITest extends ContentTranslationUITestBase {
+  protected $defaultCacheContexts = ['languages:language_interface', 'theme'];

I think we need to add 'languages:language_content' here.

2. For some reason, the MenuLinkContentDeleteForm does not have "/edit" on the Cancel Link (which it should according to the test.)

lokapujya’s picture

Status: Needs work » Needs review
FileSize
81.7 KB
836 bytes

Try to get the cache contexts right.

Status: Needs review » Needs work

The last submitted patch, 139: 2350509-139.patch, failed testing.

jhodgdon’s picture

Issue tags: +Needs documentation

I looked through the latest patch and I have some comments:

  1. Still missing a docs update... Adding tag. Needs to have the Entity topic on api.drupal.org updated.
    https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!entity.api...

  2. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,142 @@
    + * It provides:
    + * - A view route together with a title callback.
    + * - An edit route together with a title callback.
    + * - A delete route together with a title callback.
    + */
    +class EntityController implements ContainerInjectionInterface {
    +
    

    Does this provide controllers or routes? I think it provides controllers, so don't document that it provides routes, right?

  3. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,142 @@
    +   * @return \Drupal\Core\Entity\EntityInterface|NULL
    +   *   Returns the entity, otherwise NULL.
    +   */
    +  protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    +    if ($_entity) {
    

    Looking at the code for this method, I think the @return could use some more documentation about what it is returning. It seems to be returning either the entity in $_entity, or any other entity object that is found anywhere in the route parameters. Right?

  4. +++ b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php
    @@ -0,0 +1,37 @@
    +/**
    + * Provides admin routes for entities.
    + */
    +class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider {
    +
    

    It might be helpful in this class's doc block to explain how this differs from its parent class, because I had to read the code to figure it out.

    I think I'd add a line saying something like:

    These routes are the ones provided by \Drupal\Core\entity\Routing\DefaultHtmlRouteProvider, but with the _admin_route route option set for the edit and delete routes.

  5. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,130 @@
    + * It provides:
    + * - A view route with title callback.
    + * - An edit route with title callback.
    + * - A delete route with title callback.
    + */
    +class DefaultHtmlRouteProvider implements EntityRouteProviderInterface {
    +
    

    This class is just providing routes, not title callbacks, right?

    Oh... I see. The route definition has a title callback.

    How about "including a" instead of "with" here? And it also provides an access callback...

    So maybe this could be changed to say:

    This class provides the following routes for entities, each with title and access callbacks defined:
    - canonical
    - edit_form
    - delete_form

    (I think it would be clearer to use the actual machine names of the routes, like canonical rather than 'view'.)

  6. +++ b/core/modules/aggregator/src/Entity/Feed.php
    @@ -30,7 +30,10 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\aggregator\FeedHtmlRouteProvider",
    + *     },
      *   },
    

    See, this definitely needs to be documented in the Entity topic.

  7. +++ b/core/modules/block_content/src/Entity/BlockContent.php
    @@ -42,7 +45,7 @@
      *     "canonical" = "/block/{block_content}",
      *     "delete-form" = "/block/{block_content}/delete",
    - *     "edit-form" = "/block/{block_content}",
    + *     "edit-form" = "/block/{block_content}/edit",
      *     "collection" = "/admin/structure/block/block-content",
    

    Is this introducing a new path for custom blocks? It looks like previously the canonical and edit routes both went to block/ID, and now "canonical" is some kind of a view route at that URL, while eidt is now at block/ID/edit? This doesn't seem correct to me.

  8. +++ b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
    @@ -75,13 +75,6 @@ protected function doTestBasicTranslation() {
    -    $this->drupalGet($entity->urlInfo());
    -    $this->assertResponse(200, 'Entity URL is valid.');
    -
    

    Why were these two lines removed from the test?

  9. +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
    @@ -45,7 +48,7 @@
    - *     "canonical" = "/admin/structure/menu/item/{menu_link_content}/edit",
    + *     "canonical" = "/admin/structure/menu/item/{menu_link_content}",
      *     "edit-form" = "/admin/structure/menu/item/{menu_link_content}/edit",
      *     "delete-form" = "/admin/structure/menu/item/{menu_link_content}/delete",
    

    Same question here as on the Block Content entity: you're introducing a new URL here? Seems wrong.

    As another note, the code for generating these routes seems to have logic in it that says "Generate canonical if it exists", so maybe you don't need "canonical" at all? In any case I don't think it makes sense to view a block or menu link entity on a page?

  10. +++ b/core/modules/menu_link_content/src/Tests/MenuLinkContentTranslationUITest.php
    @@ -95,7 +95,7 @@ function testTranslationLinkTheme() {
    -    $this->drupalGet('admin/structure/menu/item/' . $entityId . '/edit/translations');
    +    $this->drupalGet('admin/structure/menu/item/' . $entityId . '/translations');
         $this->assertRaw('core/themes/seven/css/base/elements.css', 'Translation uses admin theme as well.');
    

    This URL is also changing???

  11. +++ b/core/modules/node/src/Entity/NodeHtmlRouteProvider.php
    @@ -0,0 +1,41 @@
    +    $collection->get('entity.node.canonical')
    +      // Use a custom controller. Sadly, there is no removeDefault method.
    +      ->setDefault('_entity_view', NULL)
    +      ->setDefault('_controller', '\Drupal\node\Controller\NodeViewController::view');
    +
    

    Maybe you could just remove the entity.node.canonical entry from the collection instead of being so sad here? :)

  12. +++ b/core/modules/shortcut/src/Entity/Shortcut.php
    @@ -46,7 +49,7 @@
      *     "canonical" = "/admin/config/user-interface/shortcut/link/{shortcut}",
      *     "delete-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/delete",
    - *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}",
    + *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/edit",
      *   },
    

    Another introduction of a new URL here?

  13. +++ b/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php
    @@ -63,26 +63,6 @@ public function testAdd($entity_type_id) {
    -  public function testEdit(RouteMatchInterface $route_match, $entity_type_id) {
    

    So you've removed this test... are we not needing to test this functionality any more, or could you just not get it to pass?

  14. +++ b/core/modules/taxonomy/src/Entity/Vocabulary.php
    @@ -35,11 +38,12 @@
    + *     "canonical" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}",
      *     "add-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/add",
    + *     "edit-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}",
      *     "delete-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/delete",
    

    See, here you've set the canonical and edit-form routes to go to the same URL. If the canonical route is absolutely necessary to have defined (and that needs to be documented!), can't we also use the same URL as we had before in the block and menu link entity classes, rather than introducing new URLs?

  15. +++ b/core/modules/taxonomy/src/Tests/VocabularyLanguageTest.php
    @@ -55,8 +56,10 @@ function testVocabularyLanguage() {
    -    $this->drupalGet('admin/structure/taxonomy/manage/' . $vid);
    +    $this->drupalGet($vocabulary->urlInfo('edit-form'));
    

    It actually scares me that this kind of change might have been necessary to get the test to pass. Did the URL change or not? I would prefer the test to be testing that the URL is what is expected, rather than calling the urlInfo() function to get the URL, because probably as a regression test, something that introduces a change in URLs ought to be caught as a test failure, right?

    This was also done in some of the other tests above. Really I think it's better for the tests to have a hard-wired drupalGet() URL so that we verify the URL is what we think it is.

lokapujya’s picture

Status: Needs work » Needs review
FileSize
79.93 KB
4.25 KB

Reverting the cache context changes that I made. There is just something wrong with the MenuLinkContent conversion.

1. Got the documentation started.
2. We already know it's a controller by the class name, so how about just "provides: A title callback". Updated in patch.
3. How about: "The entity from the controller or the first entity found in the route." Although I'm not really sure "from the controller" is right; It's the entity passed to the route generator, but I'm not completely sure where the passed entity comes from.
4. Updated.
5. Agree that the rewording is more concise, but actually think view, edit, delete is more readable for a comment.
6. Duplicate of #1.
7, 9, 10, 11, 12,14: All related. I assumed that it was some standardization the the edit-form path should be /edit. But, now don't see any consistent pattern. Needs more discussion.
8. I assumed that it wasn't needed anymore. Adding that piece back (add the cachecontexts assert after it that I deleted in the reroll) to see what happen.
Results:
Get an error in the MenuLinkContent conversion:
Canonical route used to be: /admin/structure/menu/item/1/edit
With the patch it is: admin/structure/menu/item/1 (without the /edit) which gets Access Denied.
13. This isn't a test, but just code in a test module that isn't needed after the conversion to use the routeProvider.
15. Maybe also part of a conversion.

Status: Needs review » Needs work

The last submitted patch, 142: 2350509-142.patch, failed testing.

jhodgdon’s picture

Looks like the tests do not pass... will wait to review most of the patch until they do.

Regarding the docs, This is the only change I'm seeing to an api.php file:

+++ b/core/lib/Drupal/Core/Entity/entity.api.php
@@ -385,6 +385,12 @@
  *     "form" = {
  *       "default" = "Drupal\block\BlockForm",
  *   @endcode
+ * - Optionally, utilize an auto-route generator that provides typical routes:
+ *   @code
+ *   handlers = {
+ *     "route_provider" = {
+ *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
+ *   @endcode

Some questions/comments:

a) Is this auto-route generation really optional?

b) This topic needs more updates:
- In the "Defining" section, it talks about needing to define routes, which needs some modification.
- The "Entity Routes" section also needs some modification
I think both of these should mention that in place of defining your own routes, you can use a route provider.

c) If this auto-route generation *isn't* optional... or even if it is optional... I am failing to see why someone would want to do this (define a class) in place of just defining the routes in a routing.yml file? The routing.yml file seems much easier. ??!?

dawehner’s picture

Looks like the tests do not pass... will wait to review most of the patch until they do.

IMHO you really don't have to.

a) Is this auto-route generation really optional?

Yes its opt in, as most every other handler in there, like the views data.

. I am failing to see why someone would want to do this (define a class) in place of just defining the routes in a routing.yml file? The routing.yml file seems much easier. ??!?

Well, the point of this issue is in the title. You want to not have to care about it ... It is quite an effort to get view + edit + delete + access + etc. right, the automation is an advantage.

jhodgdon’s picture

OK, fair enough. So #144(b) still applies - we need to mention this in two other places in the docs in the entity.api.php file.

Anyway, I took a look at the code as well, and it looks like my previous review comments were not addressed. They still exist. Here are a few; I gave up about half way through the patch because I think there are some real problems that have been overlooked.

  1. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,142 @@
    +/**
    + * Provides generic entity controllers.
    + *
    + * It provides:
    + * - A view title callback.
    + * - An edit title callback.
    + * - A delete title callback.
    + */
    +class EntityController implements ContainerInjectionInterface {
    +
    

    This isn't really a generic entity controller and I'm a bit confused about the name... it really is just something you could use to get these title callbacks, but it doesn't do any route controller stuff by itself.

    Maybe it should be called EntityTitleController and the first line should say something like:

    Provides title callbacks for entity routes.

    or something like that?

  2. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,142 @@
    +   * @return \Drupal\Core\Entity\EntityInterface|NULL
    +   *   Returns the entity, otherwise NULL.
    +   */
    +  protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    +    if ($_entity) {
    

    This method could use a bit more detail... maybe something like:

    Returns the entity if it is either passed in directly in $_entity, or if there is an entity that is one of the parameters of the route.

    or something like this? I had to read the code to figure out what this does.

  3. +++ b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php
    @@ -0,0 +1,39 @@
    +/**
    + * Provides admin routes for entities.
    + *
    + * Use this class if the default routes should use the admin theme.
    + */
    +class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider {
    +
    

    Um... it's only the delete and edit routes that will use admin, not canonical/view routes, right? So please fix the docs.

  4. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,130 @@
    + * It provides:
    + * - A view route with title callback.
    + * - An edit route with title callback.
    + * - A delete route with title callback.
    + */
    +class DefaultHtmlRouteProvider implements EntityRouteProviderInterface {
    +
    

    Can we please call these what they are?

    canonical
    edit_form or edit-form
    delete_form or delete-form

    There is no such thing as a "view" route...

  5. +++ b/core/lib/Drupal/Core/Entity/entity.api.php
    @@ -385,6 +385,12 @@
    + * - Optionally, utilize an auto-route generator that provides typical routes:
    + *   @code
    + *   handlers = {
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
    + *   @endcode
      *
    

    Actually here I think I wouldn't have just said "provides typical routes" because you can always define your own route handler to define your own, and I'd also mention the admin class.

    This just needs a bit more detail.

  6. +++ b/core/modules/block_content/src/Entity/BlockContent.php
    @@ -42,7 +45,7 @@
      *     "canonical" = "/block/{block_content}",
      *     "delete-form" = "/block/{block_content}/delete",
    - *     "edit-form" = "/block/{block_content}",
    + *     "edit-form" = "/block/{block_content}/edit",
      *     "collection" = "/admin/structure/block/block-content",
    

    I mentioned this in a previous review, but I don't think it's OK really to have a new URL here that didn't exist before. Previously, canonical and edit-form were the same URL path. Now you have two, but really there shouldn't be a "view" path for BlockContent entities. This is just wrong.

  7. +++ b/core/modules/block_content/src/Entity/BlockContent.php
    --- a/core/modules/block_content/src/Tests/PageEditTest.php
    +++ b/core/modules/block_content/src/Tests/PageEditTest.php
    
    +++ b/core/modules/block_content/src/Tests/PageEditTest.php
    +++ b/core/modules/block_content/src/Tests/PageEditTest.php
    @@ -37,7 +37,7 @@ public function testPageEdit() {
    
    @@ -37,7 +37,7 @@ public function testPageEdit() {
         $this->assertTrue($block, 'Custom block found in database.');
     
         // Load the edit page.
    -    $this->drupalGet('block/' . $block->id());
    +    $this->drupalGet($block->urlInfo('edit-form'));
         $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
    

    Again, in tests I think calling the urlInfo() method is wrong.

    You want to verify in a test like this that if you go to a particular URL that is defined in the test as a literal string that it will work.

    If you write the test like this you are not testing for regressions like what is introduced by the problem above, where the URL changed and it shouldn't have.

  8. +++ b/core/modules/comment/src/Entity/CommentType.php
    @@ -24,7 +24,10 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
    + *     },
      *   },
    

    Really, when editing CommentType entities, you don't want to be on Admin?

  9. +++ b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
    @@ -235,7 +235,7 @@ public function testTaxonomyVocabularyUpdate() {
    -    $this->drupalPostForm('admin/structure/taxonomy/manage/country', $edit, t('Save'));
    +    $this->drupalPostForm($vocabulary->urlInfo('edit-form'), $edit, t('Save'));
     
    

    Again I would avoid using urlInfo() in tests like this. Probably the URL changed here and the test failed and it would have uncovered a problem in the code, so instead someone changed the test. The test failure was real...

  10. +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
    @@ -31,7 +31,10 @@
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
    + *     },
      *   },
    

    Again shouldn't this be using the admin route provider?

  11. +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
    @@ -45,7 +48,7 @@
    - *     "canonical" = "/admin/structure/menu/item/{menu_link_content}/edit",
    + *     "canonical" = "/admin/structure/menu/item/{menu_link_content}",
      *     "edit-form" = "/admin/structure/menu/item/{menu_link_content}/edit",
      *     "delete-form" = "/admin/structure/menu/item/{menu_link_content}/delete",
    

    Again you've introduced a new URL path that should not exist. There should not be a way to view menu links on their own URL.

lokapujya’s picture

#146.11. This also leads to the following failure with the code that jhodgdon mentioned was removed in #141.8:

+++ b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
@@ -75,13 +75,6 @@ protected function doTestBasicTranslation() {
-    $this->drupalGet($entity->urlInfo());
-    $this->assertResponse(200, 'Entity URL is valid.');
-

The base test for translations is testing to see if the canonical link (default argument for urlinfo() ) is valid. But, MenuLinkContent doesn't have a view controller.

tstoeckler’s picture

Re #146 8. and 10.: Those entities (and others) are completely managed on URLs under /admin, so they automatically get the admin theme. But we should not set _admin_route explicitly, that's why the default route provider is used

jhodgdon’s picture

Ah, OK. Maybe we should add a comment to the Admin route provider class that says this is only needed for entities whose paths are outside of /admin then?

dawehner’s picture

Assigned: dawehner » Unassigned

I don't get why this was assigned to me all the time.

tstoeckler’s picture

Assigned: Unassigned » tstoeckler

Will take a stab at fixing the test fails. Not yet addressing any comments since #142.

dawehner’s picture

tstoeckler++

tstoeckler’s picture

So the test fails were again related to the problem of content entities without a canonical link relation. I think I've found a fairly generic solution, which should work in most cases. In ContentTranslationUiTestBase we had an explicit reference to canonical, so I implemented a little workaround for that.

Let's see what I broke with this.

andypost’s picture

Yep, looks this "missing canonical link" becomes noisy

Status: Needs review » Needs work

The last submitted patch, 153: 2350509-153-entity-route-provider.patch, failed testing.

tstoeckler’s picture

Assigned: tstoeckler » Unassigned

Hmmm.. actually now that I think of it, it should be possible to put the EntityEditUrlTrait stuff in a followup. That should make the tests pass.

Will try to tackle that but not working on it right now so unassigning.

lokapujya’s picture

So, if we do the EntityEditUrlTrait as a follow up: For now, we could extend DefaultHtmlRouteProvider for MenuLinkContent and copy the editroute code from DefaultHtmlRouteProvider into the canonical route or just not convert it yet?

lokapujya’s picture

Status: Needs work » Needs review
FileSize
83.58 KB
6.87 KB

Start on #146 1-5.

Assumes that we are doing the EntityEditUrlTrait as a followup. Extended DefaultHtmlRouteProvider for MenuLinkContent to try to fix remaining failures.

Crell’s picture

Yay, back to green!

Mostly this looks good to me, with a few caveats noted below:

  1. +++ b/core/modules/block_content/block_content.links.task.yml
    @@ -12,14 +12,14 @@ entity.block_content_type.collection:
     
    -entity.block_content.canonical:
    +entity.block_content.edit_form:
       title: Edit
    -  route_name: entity.block_content.canonical
    -  base_route: entity.block_content.canonical
    +  route_name: entity.block_content.edit_form
    +  base_route: entity.block_content.edit_form
    

    Does changing the machine name of the link have any upgrade path implications? I honestly don't know, but we should verify.

  2. +++ b/core/modules/block_content/src/Tests/PageEditTest.php
    @@ -37,7 +37,7 @@ public function testPageEdit() {
    -    $this->drupalGet('block/' . $block->id());
    +    $this->drupalGet($block->urlInfo('edit-form'));
    

    As I believe jhodgdon mentioned, it's debatable if using urlInfo() in a test is ideal. That means we lose the ability of the test to catch if the URL changes without us knowing. (This affects a large number of tests.)

jhodgdon’s picture

Status: Needs review » Needs work

+1000 for fixing #159 item 2 in all the tests. Remove all those changes from the patch and leave the URLs hard-wired as they were. That way, if we change URLs, we will consciously have to change the test and it's way more obvious. After release, changing URLs is bad, and our regression tests should detect this. It's part of why we have tests.

Regarding #159 item 1, changing route names does definitely have contrib code implications, because contrib modules might have defined local tasks/actions or route alters etc. based on route names. I don't think they require a hook_update_N(), because none of these things is config, but they do probably require a change notice.

And the issues I identified before are STILL there. This patch is not OK. We cannot be adding and changing URLs, and if this patch for some reason requires it, then it's not an OK way to fix things.

I read through about half the patch and gave up as in the last time because this stuff is still broken... Some comments:

  1. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,143 @@
    + * Provides generic entity controllers.
    + *
    + * It provides:
    + * - A view title callback.
    + * - An edit title callback.
    + * - A delete title callback.
    + */
    +class EntityController implements ContainerInjectionInterface {
    +
    

    I still do not understand why "generic entity controllers" and "EntityController" are good documentation/name for this class.

    It's only providing title callbacks. How is this a "controller" or moreover a "generic entity controller"?

  2. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,143 @@
    +  public function deleteTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) {
    +    if ($entity = $this->doGetEntity($route_match, $_entity)) {
    +      return $this->t('Delete %entity_type_label', ['@entity_type_label' => $entity->getEntityType()->getLabel()]);
    +    }
    +  }
    

    The edit page title is "Edit (label of entity)".

    Why is the delete title "Delete (label of entity type)" and not "Delete (entity)" also?

  3. +++ b/core/lib/Drupal/Core/Entity/entity.api.php
    @@ -335,6 +335,8 @@
    + *   Optionally, instead of defining routes, routes can be auto generated by
    + *   providing a route handler.
      * - If your content entity is fieldable, provide 'field_ui_base_route'
    

    This is good. I think it should go several lines up though, right after where it talks about the routing, not after it gives the names of the links:

     *   the path of this link template as the value. The corresponding route
     *   requires the following route name:
     *   "entity.$entity_type_id.$link_template_type". See @ref sec_routes below for
     *   some routing notes. Typical link types are:
    
  4. +++ b/core/lib/Drupal/Core/Entity/entity.api.php
    @@ -385,6 +388,16 @@
    + * - Optionally, utilize an auto-route generator that provides default routes. The
    

    nitpick: goes over 80 characters

  5. +++ b/core/lib/Drupal/Core/Entity/entity.api.php
    @@ -385,6 +388,16 @@
    + * - Optionally, utilize an auto-route generator that provides default routes. The
    + *   route providers intend to follow REST best practices.
    + *   DefaultHtmlRouteProvider provides canonical, edit-form, and delete-form.
    + *   Use AdminHtmlRouteProvider to provide the same with edit-form and
    + *   delete-form using the admin theme.
    + *   @code
    + *   handlers = {
    + *     "route_provider" = {
    + *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
    + *   @endcode
      *
    

    I would reword this as:

    Instead of putting the routes for your entity in a *.routing.yml file, you can instead use a route provider class. [sentence about Default and Admin ones]. You can also create your own class. To use a route provider, add the following to your entity annotation:

  6. +++ b/core/modules/block_content/src/Entity/BlockContent.php
    @@ -42,7 +45,7 @@
    - *     "edit-form" = "/block/{block_content}",
    + *     "edit-form" = "/block/{block_content}/edit",
      *     "collection" = "/admin/structure/block/block-content",
    

    Again, this change looks wrong. The URLs should NOT BE CHANGING in this patch. Right?

  7. +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
    @@ -45,7 +48,7 @@
    - *     "canonical" = "/admin/structure/menu/item/{menu_link_content}/edit",
    + *     "canonical" = "/admin/structure/menu/item/{menu_link_content}",
      *     "edit-form" = "/admin/structure/menu/item/{menu_link_content}/edit",
    

    This route/path for canonical is also wrong. Still. It should not exist.

  8. +++ b/core/modules/shortcut/src/Entity/Shortcut.php
    @@ -46,7 +49,7 @@
    - *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}",
    + *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/edit",
    

    This change also needs to go away. Still. Wrong.

  9. +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php
    @@ -38,7 +42,7 @@
    - *     "canonical" = "/entity_test_mul/manage/{entity_test_mul}",
    + *     "canonical" = "/entity_test_mul/{entity_test_mul}",
      *     "edit-form" = "/entity_test_mul/manage/{entity_test_mul}",
    

    I don't get why the links in the test entity classes need to change either. I would be MUCH more confident in this patch if nothing had to change in links. The fact that things are changing and that the tests are changing to use urlInfo() makes me distrust this whole effort.

Crell’s picture

I agree with switching the tests back to using hard-coded URLs for the reasons mentioned. However, I don't think that the fact a URL changes is itself a problem if the UI isn't changing. It means that the annotation and the existing routes were out of sync; moving the annotation to line up with the YAML routes, and then removing the YAML routes, is exactly what we should be doing, IMO.

Re comment 2: I agree, let's change that.

Re comment 7: Why shouldn't a canonical route exist?

dawehner’s picture

Again, this change looks wrong. The URLs should NOT BE CHANGING in this patch. Right?

I'm sorry but I strongly disagree with this. It is a bug if you use the same URL for both the canonical representation and the edit form, so IMHO changing them is the absolute right thing to do!

jhodgdon’s picture

Um, so what is the "canonical" URL for a menu UI item? They don't have a page where you can view them by themselves -- they shouldn't. There should only be edit/delete pages.

lokapujya’s picture

#160

  1. My understanding is that the controller might eventually do more.
  2. I'm not sure which it should be, but they should probably be the same. Updated.
  3. Moved it to the beginning so that the following lines still make sense.
  4. done.
  5. done.

Hard coded URLS: It's easier to develop with the tests with the dynamic urlinfo() while things are in flux. It's convenient to not have to know the path. That should be the last thing to change after figuring out if the changed paths (#160-6,8,9) are correct. Although, I don't think it adds much to convert the urlinfo()s back: you could just as easily have the hardcoded url wrong.

#160.7 Why ARE we adding the canonical link? Is it for REST?

lokapujya’s picture

Oops, somehow the old patch got attached.

lokapujya’s picture

jhodgdon’s picture

Status: Needs review » Needs work

OK. So looking at the latest patch... let's take a look at the URLs that are changing or being added. And a few documentation things....

  1. +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
    @@ -0,0 +1,143 @@
    + * Provides generic entity controllers.
    + *
    + * It provides:
    + * - A view title callback.
    + * - An edit title callback.
    + * - A delete title callback.
    + */
    +class EntityController implements ContainerInjectionInterface {
    +
    

    I know I've put this in about 5 reviews already...

    But can the first line docs and probably the name of this class change? It is not a "generic entity controller". To me when I read "generic entity controller" I would think it would be a controller class (i.e. something ready to respond to routes by providing pages). But it isn't -- it is just a class that provides title callbacks for entity routes.

    Let's make sure the documentation and the class name are appropriate for that.

  2. +++ b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php
    @@ -0,0 +1,40 @@
    +/**
    + * Provides admin routes for entities.
    + *
    + * Use this class if the default edit and delete routes should use the admin
    + * theme.
    + */
    +class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider {
    +
    

    This is nice! :)

  3. +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php
    @@ -0,0 +1,131 @@
    +/**
    + * Provides a default implementation of an HTML route provider.
    + *
    + * This class provides the following routes for entities with title and access
    + * callbacks:
    + * - canonical
    + * - edit-form
    + * - delete-form
    + */
    +class DefaultHtmlRouteProvider implements EntityRouteProviderInterface {
    +
    

    This is good too.

  4. +++ b/core/lib/Drupal/Core/Entity/entity.api.php
    @@ -324,7 +324,9 @@
    - * - Define routes and links for the various URLs associated with the entity.
    + * - Optionally, instead of defining routes, routes can be auto generated by
    + *   providing a route handler. See @ref sec_routes. Otherwise, define routes
    + *   and links for the various URLs associated with the entity.
      *   These go into the 'links' annotation, with the link type as the key, and
    

    I'm going to attach a suggested different patch for this documentation in entity.api.php. In a new comment though. This documentation needs some work.

  5. +++ b/core/modules/block_content/src/Entity/BlockContent.php
    @@ -42,7 +45,7 @@
      *   links = {
      *     "canonical" = "/block/{block_content}",
      *     "delete-form" = "/block/{block_content}/delete",
    - *     "edit-form" = "/block/{block_content}",
    + *     "edit-form" = "/block/{block_content}/edit",
      *     "collection" = "/admin/structure/block/block-content",
      *   },
      *   translatable = TRUE,
    

    Here's an entity whose URLs changed: BlockContent (custom block entities).

    Previously, there were URLs:
    - block/ID -- which was the canonical and edit route
    - block/ID/delete

    Now there are these URLs:
    - block/ID - canonical
    - block/ID/edit - edit

    What happens if you actually go to the "canonical" route? I don't think there is a view controller for viewing a block on its own page. It doesn't make sense to have one. And there shouldn't be two URLs that both do the same thing either, if both block/ID and block/ID/edit are used for editing. There should just be one URL for editing and one for deleting, and nothing else. Right?

    So if we cannot have two different links (canonical and edit-form) having the same URL template any more (why not? it apparently was OK before), then ... we probably need to get rid of one of them.

    It just doesn't make sense for block-content items to have a full-page view and as far as I know there is no controller set up to view them on their own page.

    So this change needs a review.

  6. +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
    @@ -45,7 +48,7 @@
      *   links = {
    - *     "canonical" = "/admin/structure/menu/item/{menu_link_content}/edit",
    + *     "canonical" = "/admin/structure/menu/item/{menu_link_content}",
      *     "edit-form" = "/admin/structure/menu/item/{menu_link_content}/edit",
      *     "delete-form" = "/admin/structure/menu/item/{menu_link_content}/delete",
      *   }
    

    The menu link entity is another case exactly like the block content case. See above.

  7. +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContentHtmlRouteProvider.php
    @@ -0,0 +1,44 @@
    +/**
    + * Provides HTML routes for the shortcut entity type.
    + */
    +class MenuLinkContentHtmlRouteProvider extends DefaultHtmlRouteProvider {
    +
    

    This documentation seems to have been copy/pasted from the Shortcut entity? Needs a quick edit.

  8. +++ b/core/modules/shortcut/src/Entity/Shortcut.php
    @@ -46,7 +49,7 @@
      *   links = {
      *     "canonical" = "/admin/config/user-interface/shortcut/link/{shortcut}",
      *     "delete-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/delete",
    - *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}",
    + *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/edit",
      *   },
    

    Shortcut entity is a 3rd case like the other two above.

  9. +++ b/core/modules/taxonomy/src/Entity/Vocabulary.php
    @@ -35,11 +38,12 @@
      *   links = {
    + *     "canonical" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}",
      *     "add-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/add",
    + *     "edit-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}",
      *     "delete-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/delete",
      *     "reset-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/reset",
      *     "overview-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/overview",
    - *     "edit-form" = "/admin/structure/taxonomy/manage/{taxonomy_vocabulary}",
      *     "collection" = "/admin/structure/taxonomy",
      *   },
      *   config_export = {
    

    So here's a different case, the Taxonomy Vocabulary.

    In this case, canonical has been added, but it uses the same URL as edit-form. Somehow this has been made to work.

    My suggestion is that the same thing should be made to work for the other 3 cases above, as they were before -- they all before had canonical at the same URL as edit, and they all still should I believe?

jhodgdon’s picture

FileSize
6.46 KB

Here is my suggested edit to the entity.api.php documentation, in the form of an interdiff from the latest patch.

dawehner’s picture

My suggestion is that the same thing should be made to work for the other 3 cases above, as they were before -- they all before had canonical at the same URL as edit, and they all still should I believe

Its just so wrong. If you ever want to expose them via REST the canonical URl should be different from the HTML edit one.

jhodgdon’s picture

Hm. So you think that the following entities *should* have "view" URLs?
- Custom blocks
- Menu links
- Shortcuts
- Vocabularies
rather than just edit/link URLs?

I guess that is OK, ... Let's look at what happens with custom blocks with the current patch, in the admin UI. I tried this out on simplytest.me with a standard profile install:

- Went to the custom block library page (admin/structure/block/block-content)
- Clicked on Add a block (block/add ). Created. Saved. Back to library page.
- Clicked on the Edit link in the custom block library page. This takes me to block/1/edit
- Tried out the block/1 link (without the edit suffix). This takes me to a page where the text of the block is the main body of the page.

Without this patch, if you do the same things in the UI:
- The Edit link is just block/1
- block/1/edit gives me a 404

So I guess the question is whether this is what is desired or not. I guess you could say that the patch is OK, although I am not sure it makes a lot of sense to view a block at a page URL. But, not horrible. At least it seems to work.

However, the same does NOT work with menu links. Although this patch defines a "canonical" link, the URL gives me a Not Found. The patch has:

  *   links = {
- *     "canonical" = "/admin/structure/menu/item/{menu_link_content}/edit",
+ *     "canonical" = "/admin/structure/menu/item/{menu_link_content}",
  *     "edit-form" = "/admin/structure/menu/item/{menu_link_content}/edit",
  *     "delete-form" = "/admin/structure/menu/item/{menu_link_content}/delete",
  *   }

But with this patch, only the URL
admin/structure/menu/item/1/edit
works. The URL
admin/structure/menu/item/1
gives me a 404.

I also tested shortcuts. The patch has:

  *   links = {
  *     "canonical" = "/admin/config/user-interface/shortcut/link/{shortcut}",
  *     "delete-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/delete",
- *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}",
+ *     "edit-form" = "/admin/config/user-interface/shortcut/link/{shortcut}/edit",
  *   },

In the UI, if you click edit you get:
admin/config/user-interface/shortcut/link/1
This works kind of -- has no page title, but it takes you to an Edit page. The URL
admin/config/user-interface/shortcut/link/1/edit
works better, and has a page title.

So, this patch still needs some work. I'm still not sure whether it makes sense or not to have "view this in a page" URLs for these things. But if it does, they need to actually work.

tstoeckler’s picture

I personally think we should not provide canonical routes at all for these entity types, which is what I tried to achieve in my patch above. We simply don't have a canonical route in any sensible meaning of that word for e.g. menu links or blocks, so it makes no sense to declare a path.

dawehner’s picture

I personally think we should not provide canonical routes at all for these entity types, which is what I tried to achieve in my patch above. We simply don't have a canonical route in any sensible meaning of that word for e.g. menu links or blocks, so it makes no sense to declare a path.

Well, I think from a REST request point of view, I think it would be fine to have a canonical path for them, but I agree with you, don't we should not have a canonical route,
which is done, when there is no view builder available.
In general though we cannot drop just canonical link templates, as core/modules/content_translation/content_translation.module:139 relies on it.

jhodgdon’s picture

Yeah, for translation I think we not only need a canonical link template, I think it also assumes that the canonical route exists and works, as well as a local task group based on it, right?

Anyway, given my manual testing in #170, I don't think that the current patch is OK -- and I didn't test it with translation either.... It seems to be a mix of having and not having various link templates and URLs work correctly (for instance, the Edit shortcut link from the Shortcuts page doesn't work right).

So. We still need to figure out what to do. If we need a canonical route for translation, but a canonical route doesn't make sense, then we have a problem that we need to figure out how to solve.

Crell’s picture

It sounds like the only remaining issue here is which links/routes we define, right? Otherwise we're good now?

Proposal for the links:

1) Keep the addition of /edit to any edit-form links, for consistency and to allow for the following points.
2) Omit the canonical links for now.
3) If any of those entities need a canonical link for translation purposes, create a follow-up issue to discuss/add those. That way it doesn't block this issue with creepy scope.

Does that sound reasonable?

Wim Leers’s picture

Sounds good.

I'm no expert on this, but wouldn't it be sensible to have content_translation fall back to the edit-form link if no canonical link is available? All content must surely be editable, so that is a safe fallback?

jhodgdon’s picture

RE the plan in #174, I do not think it is OK for this patch to break translation of blocks, menu items, vocabularies, or shortcuts. So I do not think that is the right plan.

One option for the present patch, in order to get it in and move on, would be to omit the 4 entities in question from the patch and make it "Implement auto-route generation for most core entities" instead of all, and then open a follow-up to deal with block content, menu link, shortcut, and vocabulary.

One other remaining issue we need to deal with before the patch is committed, is that all of the tests need to be restored to having their links hard-coded so that they remain being regression tests for URLs staying the same, and we can clearly see which URLs have changed.

tstoeckler’s picture

Re #175: Con*fig* translation completely uses the edit-form link only from the get-go, I think that is a much saner assumption. Especially because for con*tent* translation the translation form actually *is* (a variant of) the edit form, so we *do* rely on an edit form being available while having a canonical route is an often true, yet completely unnecessary assumption. That is of course, not for this issue.

jhodgdon’s picture

Ah. OK then. Well.

So the entities MenuLinkContent, Shortcut, and BlockContent are content entities. They will need to have a canonical link still. IMO if we are going to have this link defined, then we should also make sure it does something sensible. BlockContent seems to have that based on my manual testing in #170; MenuLinkContent and Shortcut do not.

Vocabulary on the other hand is a ConfigEntity. Patch #164 is adding a canonical link to it and setting it to the same path as the edit link. It seems that it shouldn't need a canonical link until such time as we decide there is a need for one, and at that time we should create one, give it its own unique path, and make it do something sensible. But defining one now at the same path as edit, given all the above discussion, is probably not the right thing to do, right?

tstoeckler’s picture

Tried out the block/1 link (without the edit suffix). This takes me to a page where the text of the block is the main body of the page.

IMO if we are going to have this link defined, then we should also make sure it does something sensible. BlockContent seems to have that based on my manual testing in #170;

I don't think that is very sensible IMO. The effect that that page exists is just a weird side effect of the combination of various parts of the entity system together with this page.

1. Content entities have a view builder by default (@see ContentEntityType::__construct())
2. This patch generates a route if a canonical link and a view builder exist

Thus, with this patch such a "full-page block" route gets creates automatically even though it doesn't exist in HEAD and even though we don't explicitly do anything to make it appear. One more reason to kill off the canonical route. I guess for now, we can just explicitly set the view builder to NULL, to circumvent this temporarily.

jhodgdon’s picture

@tstoeckler I am inclined to agree with you except that @dawehner points out that for REST it may make sense to have a route that returns the block text (not so much for full-page HTML requests but makes more sense if it's requesting just that block).

tstoeckler’s picture

Yes, I agree that it might be useful in the future. In fact, I thought that REST was the reason we had that route in HEAD in the first place .... until I went and checked, that we in fact don't (but that this patch "creates" the route). So regardless of REST or not, I don't think *this issue* should be introducing a canonical route for blocks?!

jhodgdon’s picture

That is what I've been saying for quite a while so I will not disagree with you. ;)

However, actually what this patch does is take the canonical link templates (which already existed for the 3 Content entities in question, block content, menu link, and shortcut), and change their URLs from being previously the same as the edit URLs to having new different URls. The canonical link templates had to exist previously for translation, it's just that they were rigged to be the same as edit and for some reason now they are not.

So. Once again. What we need to do is decide whether (given that these are content entities and currently need the edit and canonical link templates both to be defined in order for content_translation.module to work) we want to:
a) Make new URLs for canonical and make them actually do something somewhat sensible.
b) Make new URLs for canonical and have them not actually do anything sensible.
c) Keep the URLs for canonical and edit be the same, as they were prior to this issue.

I do not think (b) is OK, and that is what the current patch does.

I'm not sure what "sensible" means in (a) for these entities, but if someone can define what it should mean and make it work, that would probably be OK... but I don't understand why doing (a) is not out of scope for this patch since all it's supposed to do is convert existing entity routes to use an auto-generator, not change or add URLs that never existed before. Or so I would think.

tstoeckler’s picture

Well for c) we would have to find a way to not generate 'canonical' routes for these entity types. The only way I can see that working is if we explicitly set the view builder to NULL for these entity types.

Crell’s picture

kgoel and I discussed this issue at the MWDS sprint. Using MenuLinkContent as an example:

Current status:
1) We define links for both canonical and edit-form, that point to the same place.
2) We define a route for only edit-form. There is no canonical route.

If we switch to auto-routing (this issue), and keep both routes equal, then we would get 2 routes defined with identical paths. That's going to confuse the routing system.

If we split the URLs, we need to figure out what to do with the newly-created canonical route.

So, let's punt. Proposed solution:

1) Add the /edit suffix, as discussed above, for consistency.
2) Keep both canonical and edit-form pointing to the same place (now with /edit).
3) For those entities that want to double-up their relationships like that, they use a custom provider and unset the canonical route so that it does not get generated. This is fairly simple code. (Just subclass and add an unset() statement.)
4) Net result: Aside from the path changing (in a logical fashion) nothing changes from the current status quo. However, if we ever figure out a meaningful use for those canonical routes later we can move them to the non-/edit path and put that meaningful code there. And that can be done case-by-case and, IMO, is an 8.x safe thing to do.

jhodgdon, does that work for you?

jhodgdon’s picture

My concern is just that we should not have routes or paths that don't work, and the latest patch has several that do not work.

The proposal in #184 seems to be basically "Make an auto-route generator that maintains the status quo of no canonical route" for these entities. I'm OK with that; it seems that others are not though, given the lengthy series of patches and discussions here.

And whatever happens... Please also see #159 item 2 -- fix the tests so that we can explicitly see what URLs are changing, and so that our tests are regression tests for the URLs changing in the future. It *may* be OK to change the URLs at this point in Drupal 8 development (although I don't see why that is even necessary), but I doubt it would be cool to change them later on after 8.0.0 releases, and worse yet to change them and not even notice that it had happened.

Crell’s picture

Status: Needs work » Needs review
Issue tags: -Needs documentation
FileSize
75.11 KB
20.53 KB

Turns out, it makes sense to centralize the special handling of canonical/edit-form double handling. So I did and, I think, converted the tests back to raw URLs. Testbot will find all the places I got that wrong.

Status: Needs review » Needs work

The last submitted patch, 186: 2350509-auto-route-generation.patch, failed testing.

jhodgdon’s picture

We're running into the "content entities must have canonical routes" problem in some of the tests, it looks like?

dawehner’s picture

Assigned: Unassigned » dawehner

Working on it

dawehner’s picture

It SIMPLE does not work to just have one of the two route.s There is no way that this works, seriously. You need the canonical route for URls,
and the edit one for translation support. Here is some intermediate work.

andyceo’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 190: 2350509-190.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
84.65 KB
1.49 KB

Let's try something out.

Status: Needs review » Needs work

The last submitted patch, 193: 2350509-193.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
88.6 KB
13.3 KB

After looking into it for a while I realized that moving duplicated routes to /edit has one major flaw: The passed based breadcrumbs break with that.

Previously you could resolve on admin/structure/taxonomy/{example}/translate to admin/structure/taxonomy/{example} which is no longer possible.

Status: Needs review » Needs work

The last submitted patch, 195: 2350509-195.patch, failed testing.

dawehner’s picture

Title: Implement auto-route generation for all core entities » Implement auto-route generation for all core entities and convert all of the core entities.

This is sadly what this issue tries to achieve

dawehner’s picture

Splitted up issue into an issue which deals with just providing such a tool, see #2578955: Implement auto route generation but DON'T use it for all core entities
We don't need to provide tools for broken core entity types, IMHO

Wim Leers’s picture

Focused scopes FTW.

Wim Leers’s picture

#2578955: Implement auto route generation but DON'T use it for all core entities landed (hurray!), this now needs to be rerolled on top of that.

Crell’s picture

Since it's mainly the config entities that are problematic here, should we split this issue again and auto-generate just the content entities (node, user, term, etc. all seem fairly safe and un-controversial), which should be fairly straightforward, and then keep discussing how to figure out the config entities?

dawehner’s picture

Since it's mainly the config entities that are problematic here, should we split this issue again and auto-generate just the content entities (node, user, term, etc. all seem fairly safe and un-controversial), which should be fairly straightforward, and then keep discussing how to figure out the config entities?

Yeah I think this would totally make sense to extract the entity types which are easy to do.

Here is another subissues we could do base upon the experience in https://github.com/Jaesin/content_entity_base/blob/master/src/Entity/Rou...
see #2596095: Provide a route provider for add-form of entities

bojanz’s picture

How about we close this 200-comment issue, and continue with the conversions (which are probably 8.2 material at this point) elsewhere?

We now have add-form, edit-form, delete-form, and add-page is RTBC.

dawehner’s picture

+1

Crell’s picture

Yep. Spin up some new issues, link 'em, then close this beast. :-)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tstoeckler’s picture

Here's a list of all entities that could get the route provider treatment, as far as I see. I grouped them by their respective base class.

ConfigEntityBase
- Action
- Block
- ConfigurableLanguage
- DateFormat
- EntityFormMode
- EntityViewMode
- FilterFormat
- ImageStyle
- Menu
- ResponsiveImageStyle
- Role
- SearchPage
- View

ConfigEntityBundleBase
- BlockContentType
- CommentType
- ContactForm
- NodeType
- ShortcutSet
- Vocabulary

ContentEntityBase
- Block
- Comment
- MenuLinkContent
- Shortcut
- Term

Will open an issue for the content entity ones, to get started with that, but opened #2723579: [PP-1] NodeRouteProvider should extend DefaultHtmlRouteProvider as a first step.

dawehner’s picture

Assigned: dawehner » Unassigned

No reason for that being assigned to me.

tstoeckler’s picture

Category: Task » Plan
Status: Needs work » Active

Opened #2723615: [PP-1] Use entity route providers for all content entity types and #2760653: Use an entity route provider for taxonomy terms.

I think it's fine to keep this open as a tracking issue for now, so made this the parent of the three sub-issues for now.

If people want to mark this closed/fixed, that's also fine of course.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

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

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should 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.

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

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should 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.

apaderno’s picture

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

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.

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

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.