From b7ff1c56899e744d1f268c6a47822978c16b0dd1 Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Thu, 2 Sep 2021 15:27:13 +0000
Subject: [PATCH] Issue #3230049 by phenaproxima, tedbow: Add validation
 subscriber to check that Composer can be found

---
 automatic_updates.services.yml                |  5 ++
 .../ComposerExecutableValidator.php           | 60 +++++++++++++++++++
 .../ComposerExecutableValidatorTest.php       | 49 +++++++++++++++
 3 files changed, 114 insertions(+)
 create mode 100644 src/Validation/ComposerExecutableValidator.php
 create mode 100644 tests/src/Kernel/ReadinessValidation/ComposerExecutableValidatorTest.php

diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml
index 834207fca3..d7b7982665 100644
--- a/automatic_updates.services.yml
+++ b/automatic_updates.services.yml
@@ -76,3 +76,8 @@ services:
     arguments: ['%app.root%', '%site.path%', '@file_system', '@stream_wrapper_manager']
     tags:
       - { name: event_subscriber }
+  automatic_updates.composer_executable_validator:
+    class: Drupal\automatic_updates\Validation\ComposerExecutableValidator
+    arguments: ['@automatic_updates.exec_finder']
+    tags:
+      - { name: event_subscriber }
diff --git a/src/Validation/ComposerExecutableValidator.php b/src/Validation/ComposerExecutableValidator.php
new file mode 100644
index 0000000000..6244e78fde
--- /dev/null
+++ b/src/Validation/ComposerExecutableValidator.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Drupal\automatic_updates\Validation;
+
+use Drupal\automatic_updates\AutomaticUpdatesEvents;
+use Drupal\automatic_updates\Event\UpdateEvent;
+use PhpTuf\ComposerStager\Exception\IOException;
+use PhpTuf\ComposerStager\Infrastructure\Process\ExecutableFinderInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Validates that the Composer executable can be found.
+ */
+class ComposerExecutableValidator implements EventSubscriberInterface {
+
+  /**
+   * The executable finder service.
+   *
+   * @var \PhpTuf\ComposerStager\Infrastructure\Process\ExecutableFinderInterface
+   */
+  protected $executableFinder;
+
+  /**
+   * Constructs a ComposerExecutableValidator object.
+   *
+   * @param \PhpTuf\ComposerStager\Infrastructure\Process\ExecutableFinderInterface $executable_finder
+   *   The executable finder service.
+   */
+  public function __construct(ExecutableFinderInterface $executable_finder) {
+    $this->executableFinder = $executable_finder;
+  }
+
+  /**
+   * Validates that the Composer executable can be found.
+   *
+   * @param \Drupal\automatic_updates\Event\UpdateEvent $event
+   *   The event object.
+   */
+  public function checkForComposerExecutable(UpdateEvent $event): void {
+    try {
+      $this->executableFinder->find('composer');
+    }
+    catch (IOException $e) {
+      $error = ValidationResult::createError([
+        $e->getMessage(),
+      ]);
+      $event->addValidationResult($error);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    return [
+      AutomaticUpdatesEvents::READINESS_CHECK => 'checkForComposerExecutable',
+    ];
+  }
+
+}
diff --git a/tests/src/Kernel/ReadinessValidation/ComposerExecutableValidatorTest.php b/tests/src/Kernel/ReadinessValidation/ComposerExecutableValidatorTest.php
new file mode 100644
index 0000000000..7426323fc4
--- /dev/null
+++ b/tests/src/Kernel/ReadinessValidation/ComposerExecutableValidatorTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation;
+
+use Drupal\automatic_updates\Validation\ValidationResult;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
+use PhpTuf\ComposerStager\Exception\IOException;
+use PhpTuf\ComposerStager\Infrastructure\Process\ExecutableFinderInterface;
+
+/**
+ * @covers \Drupal\automatic_updates\Validation\ComposerExecutableValidator
+ *
+ * @group automatic_updates
+ */
+class ComposerExecutableValidatorTest extends KernelTestBase {
+
+  use ValidationTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['automatic_updates'];
+
+  /**
+   * Tests that an error is raised if the Composer executable isn't found.
+   */
+  public function testErrorIfComposerNotFound(): void {
+    $exception = new IOException("This is your regularly scheduled error.");
+
+    // The executable finder throws an exception if it can't find the requested
+    // executable.
+    $exec_finder = $this->prophesize(ExecutableFinderInterface::class);
+    $exec_finder->find('composer')
+      ->willThrow($exception)
+      ->shouldBeCalled();
+    $this->container->set('automatic_updates.exec_finder', $exec_finder->reveal());
+
+    // The validator should translate that exception into an error.
+    $error = ValidationResult::createError([
+      $exception->getMessage(),
+    ]);
+    $results = $this->container->get('automatic_updates.readiness_validation_manager')
+      ->run()
+      ->getResults();
+    $this->assertValidationResultsEqual([$error], $results);
+  }
+
+}
-- 
GitLab