From d1acf5cada24f511d6e17cb9bba2710545a9362f Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Mon, 8 Apr 2024 08:28:37 +0100
Subject: [PATCH] Issue #2862702 by larowlan, hswong3i, mohit_aghera,
 perfectcu.be, markhalliwell, mxr576, dscl, alexpott, smustgrave:
 PrepareModulesEntityUninstallForm::formTitle does not exist

(cherry picked from commit f1601a487e1640f854235778b17d95eb30d8ae5b)
---
 .../PrepareModulesEntityUninstallForm.php     | 32 ++++++++++++
 core/modules/system/system.routing.yml        |  1 +
 .../Module/PrepareUninstallTest.php           |  2 +-
 .../PrepareModulesEntityUninstallFormTest.php | 49 +++++++++++++++++++
 4 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 core/modules/system/tests/src/Kernel/Module/PrepareModulesEntityUninstallFormTest.php

diff --git a/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php b/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php
index bc061bfbd0f4..75ee379654a0 100644
--- a/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php
+++ b/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\system\Form;
 
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Access\AccessResultInterface;
 use Drupal\Core\Batch\BatchBuilder;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
@@ -91,6 +93,36 @@ public function getCancelUrl() {
     return Url::fromRoute('system.modules_uninstall');
   }
 
+  /**
+   * Gets the form title.
+   *
+   * @param string $entity_type_id
+   *   The entity type ID.
+   *
+   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
+   *   The form title.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+   *   Thrown when the entity-type does not exist.
+   */
+  public function formTitle(string $entity_type_id): TranslatableMarkup {
+    $this->entityTypeId = $entity_type_id;
+    return $this->getQuestion();
+  }
+
+  /**
+   * Checks access based on the validity of the entity type ID.
+   *
+   * @param string $entity_type_id
+   *   Entity type ID.
+   *
+   * @return \Drupal\Core\Access\AccessResultInterface
+   *   The access result.
+   */
+  public static function checkAccess(string $entity_type_id): AccessResultInterface {
+    return AccessResult::allowedIf(\Drupal::entityTypeManager()->hasDefinition($entity_type_id));
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index dee60fb189cb..d6b10e81914c 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -456,6 +456,7 @@ system.prepare_modules_entity_uninstall:
     _title_callback: '\Drupal\system\Form\PrepareModulesEntityUninstallForm::formTitle'
   requirements:
     _permission: 'administer modules'
+    _custom_access: '\Drupal\system\Form\PrepareModulesEntityUninstallForm::checkAccess'
 
 system.timezone:
   path: '/system/timezone/{abbreviation}/{offset}/{is_daylight_saving_time}'
diff --git a/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php b/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php
index 82f2f9c81924..ac24f9b9421d 100644
--- a/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php
+++ b/core/modules/system/tests/src/Functional/Module/PrepareUninstallTest.php
@@ -176,7 +176,7 @@ public function testUninstall() {
 
     // Ensure a 404 is returned when accessing a non-existent entity type.
     $this->drupalGet('admin/modules/uninstall/entity/node');
-    $this->assertSession()->statusCodeEquals(404);
+    $this->assertSession()->statusCodeEquals(403);
 
     // Test an entity type which does not have any existing entities.
     $this->drupalGet('admin/modules/uninstall/entity/entity_test_no_label');
diff --git a/core/modules/system/tests/src/Kernel/Module/PrepareModulesEntityUninstallFormTest.php b/core/modules/system/tests/src/Kernel/Module/PrepareModulesEntityUninstallFormTest.php
new file mode 100644
index 000000000000..4bac0474e6d4
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/Module/PrepareModulesEntityUninstallFormTest.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\system\Kernel\Module;
+
+use Drupal\Component\Plugin\Exception\PluginNotFoundException;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\user\Traits\UserCreationTrait;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Tests PrepareModulesEntityUninstallForm.
+ *
+ * @group Module
+ */
+class PrepareModulesEntityUninstallFormTest extends KernelTestBase {
+
+  use UserCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['user', 'system'];
+
+  /**
+   * Tests PrepareModulesEntityUninstallForm::formTitle.
+   */
+  public function testModuleEntityUninstallTitle(): void {
+    $this->setUpCurrentUser(permissions: ['administer modules']);
+    /** @var \Drupal\Core\Controller\TitleResolverInterface $title_resolver */
+    $title_resolver = \Drupal::service('title_resolver');
+    \Drupal::service('router.builder')->rebuild();
+    $request = Request::create('/admin/modules/uninstall/entity/user');
+    // Simulate matching.
+    $request->attributes->set('entity_type_id', 'user');
+    $route = \Drupal::service('router.route_provider')->getRouteByName('system.prepare_modules_entity_uninstall');
+    $title = (string) $title_resolver->getTitle($request, $route);
+    $this->assertEquals('Are you sure you want to delete all users?', $title);
+
+    $not_an_entity_type = $this->randomMachineName();
+    $request = Request::create('/admin/modules/uninstall/entity/' . $not_an_entity_type);
+    // Simulate matching.
+    $request->attributes->set('entity_type_id', $not_an_entity_type);
+    $this->expectException(PluginNotFoundException::class);
+    (string) $title_resolver->getTitle($request, $route);
+  }
+
+}
-- 
GitLab