From da859f5da7b817e395440ec9c7a1384fc5430dd8 Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Mon, 21 Mar 2022 18:12:42 +0000
Subject: [PATCH] Issue #3267632 by phenaproxima: Ensure new, changed or
 deleted routes are in the correct state after an update

---
 .../1.0.0/updated_module.module               | 12 ++++++++++
 .../1.0.0/updated_module.routing.yml          | 12 ++++++++++
 .../1.1.0/updated_module.module               | 12 ++++++++++
 .../1.1.0/updated_module.routing.yml          | 12 ++++++++++
 .../package_manager_test_api.services.yml     |  1 +
 .../src/SystemChangeRecorder.php              | 24 +++++++++++++++++--
 .../tests/src/Build/PackageUpdateTest.php     |  9 +++++++
 7 files changed, 80 insertions(+), 2 deletions(-)
 create mode 100644 package_manager/tests/fixtures/updated_module/1.0.0/updated_module.routing.yml
 create mode 100644 package_manager/tests/fixtures/updated_module/1.1.0/updated_module.routing.yml

diff --git a/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.module b/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.module
index eeed114789..6f61c45788 100644
--- a/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.module
+++ b/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.module
@@ -5,6 +5,18 @@
  * Contains global functions for testing updates to a .module file.
  */
 
+/**
+ * Page controller that says hello.
+ *
+ * @return array
+ *   A renderable array of the page content.
+ */
+function updated_module_hello(): array {
+  return [
+    '#markup' => 'Hello!',
+  ];
+}
+
 /**
  * A test function to test if global functions are reloaded during an update.
  *
diff --git a/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.routing.yml b/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.routing.yml
new file mode 100644
index 0000000000..03a269bb83
--- /dev/null
+++ b/package_manager/tests/fixtures/updated_module/1.0.0/updated_module.routing.yml
@@ -0,0 +1,12 @@
+updated_module.changed:
+  path: '/updated-module/changed/pre'
+  defaults:
+    _controller: 'updated_module_hello'
+  requirements:
+    _access: 'TRUE'
+updated_module.deleted:
+  path: '/updated-module/deleted'
+  defaults:
+    _controller: 'updated_module_hello'
+  requirements:
+    _access: 'TRUE'
diff --git a/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.module b/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.module
index 01baecbdc4..34d5dce9bb 100644
--- a/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.module
+++ b/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.module
@@ -5,6 +5,18 @@
  * Contains global functions for testing updates to a .module file.
  */
 
+/**
+ * Page controller that says hello.
+ *
+ * @return array
+ *   A renderable array of the page content.
+ */
+function updated_module_hello(): array {
+  return [
+    '#markup' => 'Hello!',
+  ];
+}
+
 /**
  * A test function to test if global functions are reloaded during an update.
  *
diff --git a/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.routing.yml b/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.routing.yml
new file mode 100644
index 0000000000..525acd210c
--- /dev/null
+++ b/package_manager/tests/fixtures/updated_module/1.1.0/updated_module.routing.yml
@@ -0,0 +1,12 @@
+updated_module.changed:
+  path: '/updated-module/changed/post'
+  defaults:
+    _controller: 'updated_module_hello'
+  requirements:
+    _access: 'TRUE'
+updated_module.added:
+  path: '/updated-module/added'
+  defaults:
+    _controller: 'updated_module_hello'
+  requirements:
+    _access: 'TRUE'
diff --git a/package_manager/tests/modules/package_manager_test_api/package_manager_test_api.services.yml b/package_manager/tests/modules/package_manager_test_api/package_manager_test_api.services.yml
index be98a5e707..76f8f38a8c 100644
--- a/package_manager/tests/modules/package_manager_test_api/package_manager_test_api.services.yml
+++ b/package_manager/tests/modules/package_manager_test_api/package_manager_test_api.services.yml
@@ -4,5 +4,6 @@ services:
     arguments:
       - '@package_manager.path_locator'
       - '@state'
+      - '@router.no_access_checks'
     tags:
       - { name: event_subscriber }
diff --git a/package_manager/tests/modules/package_manager_test_api/src/SystemChangeRecorder.php b/package_manager/tests/modules/package_manager_test_api/src/SystemChangeRecorder.php
index 852410358b..df1b7b0180 100644
--- a/package_manager/tests/modules/package_manager_test_api/src/SystemChangeRecorder.php
+++ b/package_manager/tests/modules/package_manager_test_api/src/SystemChangeRecorder.php
@@ -9,6 +9,7 @@ use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Event\StageEvent;
 use Drupal\package_manager\PathLocator;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\Routing\RouterInterface;
 
 /**
  * Defines a service for checking system changes during an update.
@@ -29,6 +30,13 @@ class SystemChangeRecorder implements EventSubscriberInterface {
    */
   private $state;
 
+  /**
+   * The router service.
+   *
+   * @var \Symfony\Component\Routing\RouterInterface
+   */
+  private $router;
+
   /**
    * Constructs a SystemChangeRecorder object.
    *
@@ -36,10 +44,13 @@ class SystemChangeRecorder implements EventSubscriberInterface {
    *   The path locator service.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state service.
+   * @param \Symfony\Component\Routing\RouterInterface $router
+   *   The router service.
    */
-  public function __construct(PathLocator $path_locator, StateInterface $state) {
+  public function __construct(PathLocator $path_locator, StateInterface $state, RouterInterface $router) {
     $this->pathLocator = $path_locator;
     $this->state = $state;
+    $this->router = $router;
   }
 
   /**
@@ -56,7 +67,16 @@ class SystemChangeRecorder implements EventSubscriberInterface {
     $results['return value of existing global function'] = _updated_module_global1();
 
     // Check if a new global function exists after changes are applied.
-    $results['new global function exists'] = function_exists('_update_module_global2') ? "exists" : "not exists";
+    $results['new global function exists'] = function_exists('_updated_module_global2') ? "exists" : "not exists";
+
+    $route_collection = $this->router->getRouteCollection();
+    // Check if changes to an existing route are picked up.
+    $results['path of changed route'] = $route_collection->get('updated_module.changed')
+      ->getPath();
+    // Check if a route removed from the updated module is no longer available.
+    $results['deleted route exists'] = $route_collection->get('updated_module.deleted') ? 'exists' : 'not exists';
+    // Check if a route added in the updated module is available.
+    $results['new route exists'] = $route_collection->get('updated_module.added') ? 'exists' : 'not exists';
 
     $phase = $event instanceof PreApplyEvent ? 'pre' : 'post';
     $this->state->set("system_changes:$phase", $results);
diff --git a/package_manager/tests/src/Build/PackageUpdateTest.php b/package_manager/tests/src/Build/PackageUpdateTest.php
index f75b83e961..4b17c01c93 100644
--- a/package_manager/tests/src/Build/PackageUpdateTest.php
+++ b/package_manager/tests/src/Build/PackageUpdateTest.php
@@ -71,6 +71,9 @@ class PackageUpdateTest extends TemplateProjectTestBase {
     $expected_pre_apply_results = [
       'return value of existing global function' => 'pre-update-value',
       'new global function exists' => 'not exists',
+      'path of changed route' => '/updated-module/changed/pre',
+      'deleted route exists' => 'exists',
+      'new route exists' => 'not exists',
     ];
     $this->assertSame($expected_pre_apply_results, $results['pre']);
 
@@ -79,6 +82,12 @@ class PackageUpdateTest extends TemplateProjectTestBase {
       'return value of existing global function' => 'pre-update-value',
       // New functions that were added in .module files will not be available.
       'new global function exists' => 'not exists',
+      // Definitions for existing routes should be updated.
+      'path of changed route' => '/updated-module/changed/post',
+      // Routes deleted from the updated module should not be available.
+      'deleted route exists' => 'not exists',
+      // Routes added to the updated module should be available.
+      'new route exists' => 'exists',
     ];
     $this->assertSame($expected_post_apply_results, $results['post']);
   }
-- 
GitLab