From 373c3da216319eb2e486c6714dc54efabdb6086d Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Mon, 6 Feb 2023 21:20:16 +0000
Subject: [PATCH] Issue #2897251 by murilohp, Bhanu951, heddn, smustgrave:
 EntityController doesn't pass dynamic route parameters

---
 .../Entity/Controller/EntityController.php    | 21 +++++++++--
 .../src/Entity/EntityTestAddPage.php          | 35 +++++++++++++++++++
 .../src/Functional/Entity/EntityFormTest.php  | 20 +++++++++--
 3 files changed, 71 insertions(+), 5 deletions(-)
 create mode 100644 core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAddPage.php

diff --git a/core/lib/Drupal/Core/Entity/Controller/EntityController.php b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
index 17f6a36ea125..041fdc8480c3 100644
--- a/core/lib/Drupal/Core/Entity/Controller/EntityController.php
+++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php
@@ -67,6 +67,11 @@ class EntityController implements ContainerInjectionInterface {
    */
   protected UrlGeneratorInterface $urlGenerator;
 
+  /**
+   * The route match.
+   */
+  protected RouteMatchInterface $routeMatch;
+
   /**
    * Constructs a new EntityController.
    *
@@ -82,14 +87,21 @@ class EntityController implements ContainerInjectionInterface {
    *   The string translation.
    * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
    *   The URL generator.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityRepositoryInterface $entity_repository, RendererInterface $renderer, TranslationInterface $string_translation, UrlGeneratorInterface $url_generator) {
+  public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, EntityRepositoryInterface $entity_repository, RendererInterface $renderer, TranslationInterface $string_translation, UrlGeneratorInterface $url_generator, RouteMatchInterface $route_match = NULL) {
     $this->entityTypeManager = $entity_type_manager;
     $this->entityTypeBundleInfo = $entity_type_bundle_info;
     $this->entityRepository = $entity_repository;
     $this->renderer = $renderer;
     $this->stringTranslation = $string_translation;
     $this->urlGenerator = $url_generator;
+    if ($route_match === NULL) {
+      @trigger_error('Calling ' . __METHOD__ . '() without the $route_match argument is deprecated in drupal:10.1.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3337782', E_USER_DEPRECATED);
+      $route_match = \Drupal::service('current_route_match');
+    }
+    $this->routeMatch = $route_match;
   }
 
   /**
@@ -102,7 +114,8 @@ public static function create(ContainerInterface $container) {
       $container->get('entity.repository'),
       $container->get('renderer'),
       $container->get('string_translation'),
-      $container->get('url_generator')
+      $container->get('url_generator'),
+      $container->get('current_route_match')
     );
   }
 
@@ -182,7 +195,9 @@ public function addPage($entity_type_id) {
     if (count($bundles) == 1) {
       $bundle_names = array_keys($bundles);
       $bundle_name = reset($bundle_names);
-      return $this->redirect($form_route_name, [$bundle_argument => $bundle_name]);
+      $parameters = $this->routeMatch->getRawParameters()->all();
+      $parameters[$bundle_argument] = $bundle_name;
+      return $this->redirect($form_route_name, $parameters);
     }
     // Prepare the #bundles array for the template.
     foreach ($bundles as $bundle_name => $bundle_info) {
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAddPage.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAddPage.php
new file mode 100644
index 000000000000..e027b0dca5f1
--- /dev/null
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAddPage.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Drupal\entity_test\Entity;
+
+/**
+ * Test entity class routes.
+ *
+ * @ContentEntityType(
+ *   id = "entity_test_add_page",
+ *   label = @Translation("Entity test route add page"),
+ *   handlers = {
+ *     "form" = {
+ *       "default" = "Drupal\entity_test\EntityTestForm",
+ *     },
+ *     "route_provider" = {
+ *       "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
+ *     },
+ *   },
+ *   admin_permission = "administer entity_test content",
+ *   base_table = "entity_test_add_page",
+ *   render_cache = FALSE,
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "uuid" = "uuid",
+ *     "bundle" = "type",
+ *     "label" = "name",
+ *   },
+ *   links = {
+ *     "add-page" = "/entity_test_add_page/{user}/add",
+ *     "add-form" = "/entity_test_add_page/add/{user}/form",
+ *   },
+ * )
+ */
+class EntityTestAddPage extends EntityTest {
+}
diff --git a/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php b/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php
index 5c1b02c56c64..7b1b0995ed5f 100644
--- a/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php
+++ b/core/modules/system/tests/src/Functional/Entity/EntityFormTest.php
@@ -28,16 +28,23 @@ class EntityFormTest extends BrowserTestBase {
    */
   protected $defaultTheme = 'stark';
 
+  /**
+   * The current user of the test.
+   *
+   * @var \Drupal\user\Entity\User|false
+   */
+  protected $webUser;
+
   /**
    * {@inheritdoc}
    */
   protected function setUp(): void {
     parent::setUp();
-    $web_user = $this->drupalCreateUser([
+    $this->webUser = $this->drupalCreateUser([
       'administer entity_test content',
       'view test entity',
     ]);
-    $this->drupalLogin($web_user);
+    $this->drupalLogin($this->webUser);
 
     // Add a language.
     ConfigurableLanguage::createFromLangcode('ro')->save();
@@ -221,4 +228,13 @@ public function testValidationHandlers() {
     $this->assertEquals('Drupal\\Core\\Entity\\EntityStorageException: Entity validation was skipped.', $state->get('entity_test.form.save.exception'), 'Button-level validation handlers behave correctly.');
   }
 
+  /**
+   * Tests the route add-page with multiple parameters.
+   */
+  public function testAddPageWithMultipleParameters(): void {
+    $this->drupalGet('entity_test_add_page/' . $this->webUser->id() . '/add');
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertSession()->pageTextContains('Add entity test route add page');
+  }
+
 }
-- 
GitLab