From 3778dde0fb82d221342d3d3d3ecd64738e4c54c1 Mon Sep 17 00:00:00 2001
From: omkar podey <58183-omkar.podey@users.noreply.drupalcode.org>
Date: Fri, 5 Apr 2024 01:42:05 +0000
Subject: [PATCH] Issue #3304142 by omkar.podey, tedbow, Wim Leers,
 TravisCarden, phenaproxima: Do not assume that Composer package names will
 exactly match Drupal projects names

---
 .../src/Form/UpdateReady.php                  | 19 ++++++++++++-------
 .../src/Form/UpdaterForm.php                  |  5 ++---
 .../ComposerStagerOperationFailureTest.php    |  4 ++--
 .../src/Functional/DisplayUpdatesTest.php     |  2 +-
 .../tests/src/Functional/PreUpdateTest.php    |  2 +-
 .../StatusCheckerRunAfterUpdateTest.php       |  2 +-
 .../src/Functional/SuccessfulUpdateTest.php   | 12 +++++++-----
 .../src/Functional/UnsuccessfulUpdateTest.php |  2 +-
 .../tests/src/Functional/UpdateErrorTest.php  |  2 +-
 .../src/Functional/UpdaterFormTestBase.php    | 18 +++++++++++++-----
 10 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/automatic_updates_extensions/src/Form/UpdateReady.php b/automatic_updates_extensions/src/Form/UpdateReady.php
index d6b8c6bb14..3190aeaad7 100644
--- a/automatic_updates_extensions/src/Form/UpdateReady.php
+++ b/automatic_updates_extensions/src/Form/UpdateReady.php
@@ -7,6 +7,7 @@ namespace Drupal\automatic_updates_extensions\Form;
 use Drupal\automatic_updates\Form\UpdateFormBase;
 use Drupal\package_manager\ComposerInspector;
 use Drupal\package_manager\Exception\StageFailureMarkerException;
+use Drupal\package_manager\InstalledPackage;
 use Drupal\package_manager\PathLocator;
 use Drupal\package_manager\ProjectInfo;
 use Drupal\package_manager\ValidationResult;
@@ -230,7 +231,7 @@ final class UpdateReady extends UpdateFormBase {
         continue;
       }
       $updated_project_info[$name] = [
-        'title' => $this->getProjectTitle($updated_package->name),
+        'title' => $this->getProjectTitleFromPackage($updated_package),
         'installed_version' => $installed_packages[$updated_package->name]->version,
         'updated_version' => $updated_package->version,
       ];
@@ -262,21 +263,25 @@ final class UpdateReady extends UpdateFormBase {
   /**
    * Gets the human-readable project title for a Composer package.
    *
-   * @param string $package_name
-   *   Package name.
+   * @param \Drupal\package_manager\InstalledPackage $package
+   *   The installed package.
    *
    * @return string
-   *   The human-readable title of the project.
+   *   The human-readable title of the project. If no project information is
+   *   available, the package name is returned.
    */
-  private function getProjectTitle(string $package_name): string {
-    $project_name = str_replace('drupal/', '', $package_name);
+  private function getProjectTitleFromPackage(InstalledPackage $package): string {
+    $project_name = $package->getProjectName();
+    if (!$project_name) {
+      return $package->name;
+    }
     $project_info = new ProjectInfo($project_name);
     $project_data = $project_info->getProjectInfo();
     if ($project_data) {
       return $project_data['title'];
     }
     else {
-      return $project_name;
+      return $package->name;
     }
   }
 
diff --git a/automatic_updates_extensions/src/Form/UpdaterForm.php b/automatic_updates_extensions/src/Form/UpdaterForm.php
index a7bd4921a3..1ab632ca10 100644
--- a/automatic_updates_extensions/src/Form/UpdaterForm.php
+++ b/automatic_updates_extensions/src/Form/UpdaterForm.php
@@ -243,13 +243,12 @@ final class UpdaterForm extends UpdateFormBase {
 
     $all_projects_data = update_calculate_project_data($available_updates);
     $outdated_modules = [];
-    $installed_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot())
-      ->getArrayCopy();
+    $installed_packages = $this->composerInspector->getInstalledPackagesList($this->pathLocator->getProjectRoot());
     $non_supported_update_statuses = [];
     foreach ($all_projects_data as $project_name => $project_data) {
       if (in_array($project_data['project_type'], $supported_project_types, TRUE)) {
         if ($project_data['status'] !== UpdateManagerInterface::CURRENT) {
-          if (!array_key_exists("drupal/$project_name", $installed_packages)) {
+          if ($installed_packages->getPackageByDrupalProjectName($project_name) === NULL) {
             $non_supported_update_statuses[] = $project_data['status'];
             continue;
           }
diff --git a/automatic_updates_extensions/tests/src/Functional/ComposerStagerOperationFailureTest.php b/automatic_updates_extensions/tests/src/Functional/ComposerStagerOperationFailureTest.php
index a102056089..46803b1793 100644
--- a/automatic_updates_extensions/tests/src/Functional/ComposerStagerOperationFailureTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/ComposerStagerOperationFailureTest.php
@@ -42,7 +42,7 @@ class ComposerStagerOperationFailureTest extends UpdaterFormTestBase {
       '8.1.0',
       '8.1.1',
     );
-    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test', '8.1.1');
+    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
     $this->assertUpdatesCount(1);
     $page->checkField('projects[semver_test]');
 
@@ -74,7 +74,7 @@ class ComposerStagerOperationFailureTest extends UpdaterFormTestBase {
     // This ensures that we can still update after the exception no longer
     // exists.
     $page->checkField('projects[semver_test]');
-    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test', '8.1.1');
+    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
     $page->pressButton('Update');
     $this->checkForMetaRefresh();
     $page->pressButton('Continue');
diff --git a/automatic_updates_extensions/tests/src/Functional/DisplayUpdatesTest.php b/automatic_updates_extensions/tests/src/Functional/DisplayUpdatesTest.php
index c4d214a5bf..7e1624eee0 100644
--- a/automatic_updates_extensions/tests/src/Functional/DisplayUpdatesTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/DisplayUpdatesTest.php
@@ -67,7 +67,7 @@ class DisplayUpdatesTest extends UpdaterFormTestBase {
     $page->checkField('projects[semver_test]');
     $this->getStageFixtureManipulator()
       ->setVersion('drupal/aaa_update_test', '2.1.0')
-      ->setVersion('drupal/semver_test', '8.1.1');
+      ->setVersion('drupal/semver_test_package_name', '8.1.1');
     $page->pressButton('Update');
     $this->checkForMetaRefresh();
     $this->assertUpdateStagedTimes(1);
diff --git a/automatic_updates_extensions/tests/src/Functional/PreUpdateTest.php b/automatic_updates_extensions/tests/src/Functional/PreUpdateTest.php
index b36b3d220f..a44a12e704 100644
--- a/automatic_updates_extensions/tests/src/Functional/PreUpdateTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/PreUpdateTest.php
@@ -48,7 +48,7 @@ class PreUpdateTest extends UpdaterFormTestBase {
 
     // Both of the modules not installed through composer.
     (new ActiveFixtureManipulator())
-      ->removePackage('drupal/semver_test')
+      ->removePackage('drupal/semver_test_package_name')
       ->commitChanges();
     $this->getSession()->reload();
     $assert->pageTextContains('Updates were found, but they must be performed manually. See the list of available updates for more information.');
diff --git a/automatic_updates_extensions/tests/src/Functional/StatusCheckerRunAfterUpdateTest.php b/automatic_updates_extensions/tests/src/Functional/StatusCheckerRunAfterUpdateTest.php
index 35c6d023f3..8df651fe94 100644
--- a/automatic_updates_extensions/tests/src/Functional/StatusCheckerRunAfterUpdateTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/StatusCheckerRunAfterUpdateTest.php
@@ -48,7 +48,7 @@ class StatusCheckerRunAfterUpdateTest extends UpdaterFormTestBase {
     $assert_session->pageTextNotContains(static::$warningsExplanation);
 
     $this->assertTableShowsUpdates('Semver Test', '8.1.0', '8.1.1');
-    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test', '8.1.1');
+    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
     $this->assertUpdatesCount(1);
     $page->checkField('projects[semver_test]');
     $page->pressButton('Update');
diff --git a/automatic_updates_extensions/tests/src/Functional/SuccessfulUpdateTest.php b/automatic_updates_extensions/tests/src/Functional/SuccessfulUpdateTest.php
index 5b2e3f5a27..146c9bb47f 100644
--- a/automatic_updates_extensions/tests/src/Functional/SuccessfulUpdateTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/SuccessfulUpdateTest.php
@@ -24,13 +24,13 @@ class SuccessfulUpdateTest extends UpdaterFormTestBase {
   public function providerSuccessfulUpdate(): array {
     return [
       'maintenance mode on, semver module' => [
-        TRUE, 'semver_test', 'Semver Test', '8.1.0', '8.1.1',
+        TRUE, 'semver_test', 'drupal/semver_test_package_name', 'Semver Test', '8.1.0', '8.1.1',
       ],
       'maintenance mode off, legacy module' => [
-        FALSE, 'aaa_update_test', 'AAA Update test', '8.x-2.0', '8.x-2.1',
+        FALSE, 'aaa_update_test', 'drupal/aaa_update_test', 'AAA Update test', '8.x-2.0', '8.x-2.1',
       ],
       'maintenance mode off, legacy theme' => [
-        FALSE, 'automatic_updates_extensions_test_theme', 'Automatic Updates Extensions Test Theme', '8.x-2.0', '8.x-2.1',
+        FALSE, 'automatic_updates_extensions_test_theme', 'drupal/automatic_updates_extensions_test_theme', 'Automatic Updates Extensions Test Theme', '8.x-2.0', '8.x-2.1',
       ],
     ];
   }
@@ -42,6 +42,8 @@ class SuccessfulUpdateTest extends UpdaterFormTestBase {
    *   Whether maintenance should be on at the beginning of the update.
    * @param string $project_name
    *   The project name.
+   * @param string $package_name
+   *   The package name.
    * @param string $project_title
    *   The project title.
    * @param string $installed_version
@@ -51,7 +53,7 @@ class SuccessfulUpdateTest extends UpdaterFormTestBase {
    *
    * @dataProvider providerSuccessfulUpdate
    */
-  public function testSuccessfulUpdate(bool $maintenance_mode_on, string $project_name, string $project_title, string $installed_version, string $target_version): void {
+  public function testSuccessfulUpdate(bool $maintenance_mode_on, string $project_name, string $package_name, string $project_title, string $installed_version, string $target_version): void {
     $this->container->get('theme_installer')->install(['automatic_updates_theme_with_updates']);
     // By default, the Update module only checks for updates of installed
     // modules and themes. The two modules we're testing here (semver_test and
@@ -61,7 +63,7 @@ class SuccessfulUpdateTest extends UpdaterFormTestBase {
     $path_to_fixtures_folder = $project_name === 'aaa_update_test' ? '/../../../../package_manager/tests' : '/../..';
     $this->setReleaseMetadata(__DIR__ . $path_to_fixtures_folder . '/fixtures/release-history/' . $project_name . '.1.1.xml');
     $this->setProjectInstalledVersion([$project_name => $installed_version]);
-    $this->getStageFixtureManipulator()->setVersion('drupal/' . $project_name, LegacyVersionUtility::convertToSemanticVersion($target_version));
+    $this->getStageFixtureManipulator()->setVersion($package_name, LegacyVersionUtility::convertToSemanticVersion($target_version));
     $this->checkForUpdates();
     $state = $this->container->get('state');
     $state->set('system.maintenance_mode', $maintenance_mode_on);
diff --git a/automatic_updates_extensions/tests/src/Functional/UnsuccessfulUpdateTest.php b/automatic_updates_extensions/tests/src/Functional/UnsuccessfulUpdateTest.php
index 673c9561fc..73b2724848 100644
--- a/automatic_updates_extensions/tests/src/Functional/UnsuccessfulUpdateTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/UnsuccessfulUpdateTest.php
@@ -31,7 +31,7 @@ class UnsuccessfulUpdateTest extends UpdaterFormTestBase {
     $this->drupalGet('/admin/reports/updates');
     $this->clickLink('Update Extensions');
     $this->assertTableShowsUpdates('Semver Test', '8.1.0', '8.1.1');
-    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test', '8.1.1');
+    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
     $this->assertUpdatesCount(1);
     $this->checkForMetaRefresh();
     $assert->pageTextNotContains(static::$errorsExplanation);
diff --git a/automatic_updates_extensions/tests/src/Functional/UpdateErrorTest.php b/automatic_updates_extensions/tests/src/Functional/UpdateErrorTest.php
index 8acb822a15..e7df2dc78b 100644
--- a/automatic_updates_extensions/tests/src/Functional/UpdateErrorTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/UpdateErrorTest.php
@@ -32,7 +32,7 @@ class UpdateErrorTest extends UpdaterFormTestBase {
     $assert_session->pageTextNotContains(static::$warningsExplanation);
 
     $this->assertTableShowsUpdates('Semver Test', '8.1.0', '8.1.1');
-    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test', '8.1.1');
+    $this->getStageFixtureManipulator()->setVersion('drupal/semver_test_package_name', '8.1.1');
     $this->assertUpdatesCount(1);
     $page->checkField('projects[semver_test]');
     $page->pressButton('Update');
diff --git a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTestBase.php b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTestBase.php
index 56da072dae..dedd398aaa 100644
--- a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTestBase.php
+++ b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTestBase.php
@@ -48,11 +48,19 @@ abstract class UpdaterFormTestBase extends UpdaterFormFunctionalTestBase {
 
     $this->activeDir = $this->container->get(PathLocator::class)->getProjectRoot();
     (new ActiveFixtureManipulator())
-      ->addPackage([
-        'name' => 'drupal/semver_test',
-        'version' => '8.1.0',
-        'type' => 'drupal-module',
-      ])
+      // Add a package where the Composer package name,
+      // drupal/semver_test_package_name, does not match the project name,
+      // semver_test.
+      ->addPackage(
+        [
+          'name' => 'drupal/semver_test_package_name',
+          'version' => '8.1.0',
+          'type' => 'drupal-module',
+        ],
+        extra_files: [
+          'semver_test.info.yml' => '{name: "Semver Test", project: "semver_test", type: "module"}',
+        ]
+      )
       ->addPackage([
         'name' => 'drupal/aaa_update_test',
         'version' => '2.0.0',
-- 
GitLab