Loading package_manager/package_manager.services.yml +2 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,8 @@ services: - '@PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface' - '@module_handler' - '@string_translation' - '@PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' tags: - { name: event_subscriber } package_manager.validator.disk_space: Loading package_manager/src/Validator/ComposerExecutableValidator.php +39 −1 Original line number Diff line number Diff line Loading @@ -13,8 +13,11 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\package_manager\Event\StatusCheckEvent; use PhpTuf\ComposerStager\Domain\Exception\ExceptionInterface; use PhpTuf\ComposerStager\Domain\Exception\PreconditionException; use PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface; use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface; use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface; use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** Loading Loading @@ -43,6 +46,13 @@ class ComposerExecutableValidator implements EventSubscriberInterface { */ protected $composer; /** * The "Composer is available" precondition service. * * @var \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface */ protected $composerIsAvailable; /** * The module handler service. * Loading @@ -50,6 +60,13 @@ class ComposerExecutableValidator implements EventSubscriberInterface { */ protected $moduleHandler; /** * The path factory service. * * @var \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface */ protected $pathFactory; /** * Constructs a ComposerExecutableValidator object. * Loading @@ -59,17 +76,38 @@ class ComposerExecutableValidator implements EventSubscriberInterface { * The module handler service. * @param \Drupal\Core\StringTranslation\TranslationInterface $translation * The translation service. * @param \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface $composer_is_available * The "Composer is available" precondition service. * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $path_factory * The path factory service. */ public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation) { public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation, ComposerIsAvailableInterface $composer_is_available, PathFactoryInterface $path_factory) { $this->composer = $composer; $this->moduleHandler = $module_handler; $this->setStringTranslation($translation); $this->composerIsAvailable = $composer_is_available; $this->pathFactory = $path_factory; } /** * {@inheritdoc} */ public function validateStagePreOperation(PreOperationStageEvent $event): void { // Return early if Composer is not available. try { // The "Composer is available" precondition requires active and staging // directories, but they don't actually matter to it, nor do path // exclusions, so dummies can be passed for simplicity. $active_dir = $this->pathFactory::create(__DIR__); $stage_dir = $active_dir; $this->composerIsAvailable->assertIsFulfilled($active_dir, $stage_dir); } catch (PreconditionException $e) { $event->addError([$e->getMessage()]); return; } try { $output = $this->runCommand(); } Loading package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php +39 −0 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\Validator\ComposerExecutableValidator; use Drupal\package_manager\ValidationResult; use PhpTuf\ComposerStager\Domain\Exception\IOException; use PhpTuf\ComposerStager\Domain\Exception\LogicException; use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface; use PHPUnit\Framework\Assert; use Symfony\Component\DependencyInjection\Reference; /** * @covers \Drupal\package_manager\Validator\ComposerExecutableValidator Loading @@ -27,6 +30,8 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { $container->getDefinition('package_manager.validator.composer_executable') ->setClass(TestComposerExecutableValidator::class); $container ->register('test.terrible_composer_finder', TestFailingComposerFinder::class); } /** Loading @@ -47,6 +52,26 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { $this->assertResultsWithHelp([$error], PreCreateEvent::class); } /** * Test RuntimeError is handled correctly. */ public function testComposerNotFound(): void { // @see \PhpTuf\ComposerStager\Infrastructure\Service\Precondition\ComposerIsAvailable::getUnfulfilledStatusMessage() $exception = new \Exception('Composer cannot be found.'); TestComposerExecutableValidator::setCommandOutput($exception); // Change ComposerRunnerInterface path to throw a LogicException. $definition = $this->container->getDefinition('PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface'); $definition->setArgument(0, new Reference('test.terrible_composer_finder')); // The validator should translate that exception into an error. $error = ValidationResult::createError([ $exception->getMessage(), ]); $this->assertStatusCheckResults([$error]); $this->assertResults([$error], PreCreateEvent::class); } /** * Data provider for testComposerVersionValidation(). * Loading Loading @@ -212,3 +237,17 @@ class TestComposerExecutableValidator extends ComposerExecutableValidator { } } /** * A test-only version of ExecutableFinderInterface that throws LogicException. */ class TestFailingComposerFinder implements ExecutableFinderInterface { /** * {@inheritdoc} */ public function find(string $name): string { throw new LogicException(); } } Loading
package_manager/package_manager.services.yml +2 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,8 @@ services: - '@PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface' - '@module_handler' - '@string_translation' - '@PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface' - '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface' tags: - { name: event_subscriber } package_manager.validator.disk_space: Loading
package_manager/src/Validator/ComposerExecutableValidator.php +39 −1 Original line number Diff line number Diff line Loading @@ -13,8 +13,11 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\package_manager\Event\StatusCheckEvent; use PhpTuf\ComposerStager\Domain\Exception\ExceptionInterface; use PhpTuf\ComposerStager\Domain\Exception\PreconditionException; use PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface; use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface; use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface; use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** Loading Loading @@ -43,6 +46,13 @@ class ComposerExecutableValidator implements EventSubscriberInterface { */ protected $composer; /** * The "Composer is available" precondition service. * * @var \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface */ protected $composerIsAvailable; /** * The module handler service. * Loading @@ -50,6 +60,13 @@ class ComposerExecutableValidator implements EventSubscriberInterface { */ protected $moduleHandler; /** * The path factory service. * * @var \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface */ protected $pathFactory; /** * Constructs a ComposerExecutableValidator object. * Loading @@ -59,17 +76,38 @@ class ComposerExecutableValidator implements EventSubscriberInterface { * The module handler service. * @param \Drupal\Core\StringTranslation\TranslationInterface $translation * The translation service. * @param \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface $composer_is_available * The "Composer is available" precondition service. * @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $path_factory * The path factory service. */ public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation) { public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation, ComposerIsAvailableInterface $composer_is_available, PathFactoryInterface $path_factory) { $this->composer = $composer; $this->moduleHandler = $module_handler; $this->setStringTranslation($translation); $this->composerIsAvailable = $composer_is_available; $this->pathFactory = $path_factory; } /** * {@inheritdoc} */ public function validateStagePreOperation(PreOperationStageEvent $event): void { // Return early if Composer is not available. try { // The "Composer is available" precondition requires active and staging // directories, but they don't actually matter to it, nor do path // exclusions, so dummies can be passed for simplicity. $active_dir = $this->pathFactory::create(__DIR__); $stage_dir = $active_dir; $this->composerIsAvailable->assertIsFulfilled($active_dir, $stage_dir); } catch (PreconditionException $e) { $event->addError([$e->getMessage()]); return; } try { $output = $this->runCommand(); } Loading
package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php +39 −0 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\Validator\ComposerExecutableValidator; use Drupal\package_manager\ValidationResult; use PhpTuf\ComposerStager\Domain\Exception\IOException; use PhpTuf\ComposerStager\Domain\Exception\LogicException; use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface; use PHPUnit\Framework\Assert; use Symfony\Component\DependencyInjection\Reference; /** * @covers \Drupal\package_manager\Validator\ComposerExecutableValidator Loading @@ -27,6 +30,8 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { $container->getDefinition('package_manager.validator.composer_executable') ->setClass(TestComposerExecutableValidator::class); $container ->register('test.terrible_composer_finder', TestFailingComposerFinder::class); } /** Loading @@ -47,6 +52,26 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { $this->assertResultsWithHelp([$error], PreCreateEvent::class); } /** * Test RuntimeError is handled correctly. */ public function testComposerNotFound(): void { // @see \PhpTuf\ComposerStager\Infrastructure\Service\Precondition\ComposerIsAvailable::getUnfulfilledStatusMessage() $exception = new \Exception('Composer cannot be found.'); TestComposerExecutableValidator::setCommandOutput($exception); // Change ComposerRunnerInterface path to throw a LogicException. $definition = $this->container->getDefinition('PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface'); $definition->setArgument(0, new Reference('test.terrible_composer_finder')); // The validator should translate that exception into an error. $error = ValidationResult::createError([ $exception->getMessage(), ]); $this->assertStatusCheckResults([$error]); $this->assertResults([$error], PreCreateEvent::class); } /** * Data provider for testComposerVersionValidation(). * Loading Loading @@ -212,3 +237,17 @@ class TestComposerExecutableValidator extends ComposerExecutableValidator { } } /** * A test-only version of ExecutableFinderInterface that throws LogicException. */ class TestFailingComposerFinder implements ExecutableFinderInterface { /** * {@inheritdoc} */ public function find(string $name): string { throw new LogicException(); } }