Skip to content
Snippets Groups Projects
Commit 15b871ae authored by Kunal Sachdev's avatar Kunal Sachdev Committed by Adam G-H
Browse files

Issue #3253858 by kunal.sachdev, phenaproxima, tedbow: In...

Issue #3253858 by kunal.sachdev, phenaproxima, tedbow: In ComposerExecutableValidator provide in explanation about how you can set the path to the Composer executable
parent bf9874f6
No related branches found
No related tags found
1 merge request!209Issue #3253858: In ComposerExecutableValidator provide in explanation about how you can set the path to the Composer executable
...@@ -17,7 +17,7 @@ function package_manager_help($route_name, RouteMatchInterface $route_match) { ...@@ -17,7 +17,7 @@ function package_manager_help($route_name, RouteMatchInterface $route_match) {
$output = '<h3>' . t('About') . '</h3>'; $output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Package Manager is a framework for updating Drupal core and installing contributed modules and themes via Composer. It has no user interface, but it provides an API for creating a temporary copy of the current site, making changes to the copy, and then syncing those changes back into the live site.') . '</p>'; $output .= '<p>' . t('Package Manager is a framework for updating Drupal core and installing contributed modules and themes via Composer. It has no user interface, but it provides an API for creating a temporary copy of the current site, making changes to the copy, and then syncing those changes back into the live site.') . '</p>';
$output .= '<p>' . t('Package Manager dispatches events before and after various operations, and external code can integrate with it by subscribing to those events. For more information, see <code>package_manager.api.php</code>.') . '</p>'; $output .= '<p>' . t('Package Manager dispatches events before and after various operations, and external code can integrate with it by subscribing to those events. For more information, see <code>package_manager.api.php</code>.') . '</p>';
$output .= '<h3>' . t('Requirements') . '</h3>'; $output .= '<h3 id="package-manager-requirements">' . t('Requirements') . '</h3>';
$output .= '<p>' . t('Package Manager requires Composer @version or later available as an executable, and PHP must have permission to run it. The path to the executable may be set in the <code>package_manager.settings:executables.composer</code> config setting, or it will be automatically detected.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION]) . '</p>'; $output .= '<p>' . t('Package Manager requires Composer @version or later available as an executable, and PHP must have permission to run it. The path to the executable may be set in the <code>package_manager.settings:executables.composer</code> config setting, or it will be automatically detected.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION]) . '</p>';
$output .= '<h3>' . t('Limitations') . '</h3>'; $output .= '<h3>' . t('Limitations') . '</h3>';
$output .= '<p>' . t("Because Package Manager modifies the current site's code base, it is intentionally limited in certain ways to prevent unexpected changes from being made to the live site:") . '</p>'; $output .= '<p>' . t("Because Package Manager modifies the current site's code base, it is intentionally limited in certain ways to prevent unexpected changes from being made to the live site:") . '</p>';
......
...@@ -80,6 +80,7 @@ services: ...@@ -80,6 +80,7 @@ services:
class: Drupal\package_manager\Validator\ComposerExecutableValidator class: Drupal\package_manager\Validator\ComposerExecutableValidator
arguments: arguments:
- '@package_manager.composer_runner' - '@package_manager.composer_runner'
- '@module_handler'
- '@string_translation' - '@string_translation'
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
namespace Drupal\package_manager\Validator; namespace Drupal\package_manager\Validator;
use Composer\Semver\Comparator; use Composer\Semver\Comparator;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Url;
use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\Event\PreOperationStageEvent; use Drupal\package_manager\Event\PreOperationStageEvent;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
...@@ -32,6 +34,13 @@ class ComposerExecutableValidator implements PreOperationStageValidatorInterface ...@@ -32,6 +34,13 @@ class ComposerExecutableValidator implements PreOperationStageValidatorInterface
*/ */
protected $composer; protected $composer;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/** /**
* The detected version of Composer. * The detected version of Composer.
* *
...@@ -44,11 +53,14 @@ class ComposerExecutableValidator implements PreOperationStageValidatorInterface ...@@ -44,11 +53,14 @@ class ComposerExecutableValidator implements PreOperationStageValidatorInterface
* *
* @param \PhpTuf\ComposerStager\Domain\Process\Runner\ComposerRunnerInterface $composer * @param \PhpTuf\ComposerStager\Domain\Process\Runner\ComposerRunnerInterface $composer
* The Composer runner. * The Composer runner.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
* The translation service. * The translation service.
*/ */
public function __construct(ComposerRunnerInterface $composer, TranslationInterface $translation) { public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation) {
$this->composer = $composer; $this->composer = $composer;
$this->moduleHandler = $module_handler;
$this->setStringTranslation($translation); $this->setStringTranslation($translation);
} }
...@@ -60,27 +72,47 @@ class ComposerExecutableValidator implements PreOperationStageValidatorInterface ...@@ -60,27 +72,47 @@ class ComposerExecutableValidator implements PreOperationStageValidatorInterface
$this->composer->run(['--version'], $this); $this->composer->run(['--version'], $this);
} }
catch (ExceptionInterface $e) { catch (ExceptionInterface $e) {
$event->addError([ $this->setError($e->getMessage(), $event);
$e->getMessage(),
]);
return; return;
} }
if ($this->version) { if ($this->version) {
if (Comparator::lessThan($this->version, static::MINIMUM_COMPOSER_VERSION)) { if (Comparator::lessThan($this->version, static::MINIMUM_COMPOSER_VERSION)) {
$event->addError([ $message = $this->t('Composer @minimum_version or later is required, but version @detected_version was detected.', [
$this->t('Composer @minimum_version or later is required, but version @detected_version was detected.', [ '@minimum_version' => static::MINIMUM_COMPOSER_VERSION,
'@minimum_version' => static::MINIMUM_COMPOSER_VERSION, '@detected_version' => $this->version,
'@detected_version' => $this->version,
]),
]); ]);
$this->setError($message, $event);
} }
} }
else { else {
$event->addError([ $this->setError($this->t('The Composer version could not be detected.'), $event);
$this->t('The Composer version could not be detected.'), }
}
/**
* Flags a validation error.
*
* @param string $message
* The error message. If the Help module is enabled, a link to Package
* Manager's online documentation will be appended.
* @param \Drupal\package_manager\Event\PreOperationStageEvent $event
* The event object.
*
* @see package_manager_help()
*/
protected function setError(string $message, PreOperationStageEvent $event): void {
if ($this->moduleHandler->moduleExists('help')) {
$url = Url::fromRoute('help.page', ['name' => 'package_manager'])
->setOption('fragment', 'package-manager-requirements')
->toString();
$message .= ' ';
$message .= $this->t('See <a href=":package-manager-help">the help page</a> for information on how to configure the path to Composer.', [
':package-manager-help' => $url,
]); ]);
} }
$event->addError([$message]);
} }
/** /**
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Drupal\Tests\package_manager\Kernel; namespace Drupal\Tests\package_manager\Kernel;
use Drupal\Core\Url;
use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\Validator\ComposerExecutableValidator; use Drupal\package_manager\Validator\ComposerExecutableValidator;
use Drupal\package_manager\ValidationResult; use Drupal\package_manager\ValidationResult;
...@@ -35,6 +36,10 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { ...@@ -35,6 +36,10 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
$exception->getMessage(), $exception->getMessage(),
]); ]);
$this->assertResults([$error], PreCreateEvent::class); $this->assertResults([$error], PreCreateEvent::class);
$this->enableModules(['help']);
$this->container->set('package_manager.executable_finder', $exec_finder->reveal());
$this->assertResultsWithHelp([$error], PreCreateEvent::class);
} }
/** /**
...@@ -137,6 +142,36 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase { ...@@ -137,6 +142,36 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
// If the validator can't find a recognized, supported version of Composer, // If the validator can't find a recognized, supported version of Composer,
// it should produce errors. // it should produce errors.
$this->assertResults($expected_results, PreCreateEvent::class); $this->assertResults($expected_results, PreCreateEvent::class);
$this->enableModules(['help']);
$this->container->set('package_manager.composer_runner', $runner->reveal());
$this->assertResultsWithHelp($expected_results, PreCreateEvent::class);
}
/**
* Asserts that a set of validation results link to the Package Manager help.
*
* @param \Drupal\package_manager\ValidationResult[] $expected_results
* The expected validation results.
* @param string|null $event_class
* (optional) The class of the event which should return the results. Must
* be passed if $expected_results is not empty.
*/
private function assertResultsWithHelp(array $expected_results, string $event_class = NULL): void {
$url = Url::fromRoute('help.page', ['name' => 'package_manager'])
->setOption('fragment', 'package-manager-requirements')
->toString();
// Reformat the provided results so that they all have the link to the
// online documentation appended to them.
$map = function (string $message) use ($url): string {
return $message . ' See <a href="' . $url . '">the help page</a> for information on how to configure the path to Composer.';
};
foreach ($expected_results as $index => $result) {
$messages = array_map($map, $result->getMessages());
$expected_results[$index] = ValidationResult::createError($messages);
}
$this->assertResults($expected_results, $event_class);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment