Skip to content
Snippets Groups Projects
Commit 3b0dacd9 authored by Theresa Grannum's avatar Theresa Grannum Committed by Ted Bowman
Browse files

Issue #3312669 by phenaproxima, Theresa.Grannum: Add help text explaining how...

Issue #3312669 by phenaproxima, Theresa.Grannum: Add help text explaining how to set an alternate port for cron
parent 3474fb9c
No related branches found
No related tags found
No related merge requests found
...@@ -30,6 +30,11 @@ function automatic_updates_help($route_name, RouteMatchInterface $route_match) { ...@@ -30,6 +30,11 @@ function automatic_updates_help($route_name, RouteMatchInterface $route_match) {
$output .= '<h3>' . t('Requirements') . '</h3>'; $output .= '<h3>' . t('Requirements') . '</h3>';
$output .= '<p>' . t('Automatic Updates requires a Composer executable whose version satisfies <code>@version</code>, 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_CONSTRAINT]) . '</p>'; $output .= '<p>' . t('Automatic Updates requires a Composer executable whose version satisfies <code>@version</code>, 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_CONSTRAINT]) . '</p>';
$output .= '<p>' . t('For more information, see the <a href=":automatic-updates-documentation">online documentation for the Automatic Updates module</a>.', [':automatic-updates-documentation' => 'https://www.drupal.org/docs/8/update/automatic-updates']) . '</p>'; $output .= '<p>' . t('For more information, see the <a href=":automatic-updates-documentation">online documentation for the Automatic Updates module</a>.', [':automatic-updates-documentation' => 'https://www.drupal.org/docs/8/update/automatic-updates']) . '</p>';
$output .= '<p id="cron-alternate-port">' . t('If your site is running on the built-in PHP web server, unattended (i.e., cron) updates may not work without one of the following workarounds:') . '</p>';
$output .= '<ul>';
$output .= '<li>' . t('Use a multithreaded web server, such as Apache, NGINX, or on Windows, IIS.') . '</li>';
$output .= '<li>' . t('Run another instance of the built-in PHP web server on a different port and configure automatic updates accordingly: <code>$config["automatic_updates.settings"]["cron_port"] = $alternate_port_number;</code>') . '</li>';
$output .= '</ul>';
return $output; return $output;
} }
} }
......
...@@ -166,6 +166,7 @@ services: ...@@ -166,6 +166,7 @@ services:
arguments: arguments:
- '@request_stack' - '@request_stack'
- '@config.factory' - '@config.factory'
- '@module_handler'
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
logger.channel.automatic_updates: logger.channel.automatic_updates:
......
...@@ -5,8 +5,10 @@ namespace Drupal\automatic_updates\Validator; ...@@ -5,8 +5,10 @@ namespace Drupal\automatic_updates\Validator;
use Drupal\automatic_updates\CronUpdater; use Drupal\automatic_updates\CronUpdater;
use Drupal\automatic_updates\Event\ReadinessCheckEvent; use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Http\RequestStack; use Drupal\Core\Http\RequestStack;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
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 Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
...@@ -37,6 +39,13 @@ final class CronServerValidator implements EventSubscriberInterface { ...@@ -37,6 +39,13 @@ final class CronServerValidator implements EventSubscriberInterface {
*/ */
protected $configFactory; protected $configFactory;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/** /**
* The type of interface between the web server and the PHP runtime. * The type of interface between the web server and the PHP runtime.
* *
...@@ -54,10 +63,13 @@ final class CronServerValidator implements EventSubscriberInterface { ...@@ -54,10 +63,13 @@ final class CronServerValidator implements EventSubscriberInterface {
* The request stack service. * The request stack service.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory service. * The config factory service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler service.
*/ */
public function __construct(RequestStack $request_stack, ConfigFactoryInterface $config_factory) { public function __construct(RequestStack $request_stack, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler) {
$this->request = $request_stack->getCurrentRequest(); $this->request = $request_stack->getCurrentRequest();
$this->configFactory = $config_factory; $this->configFactory = $config_factory;
$this->moduleHandler = $module_handler;
} }
/** /**
...@@ -79,13 +91,22 @@ final class CronServerValidator implements EventSubscriberInterface { ...@@ -79,13 +91,22 @@ final class CronServerValidator implements EventSubscriberInterface {
$alternate_port = intval($alternate_port) ?: $current_port; $alternate_port = intval($alternate_port) ?: $current_port;
if (static::$serverApi === 'cli-server' && $current_port === $alternate_port) { if (static::$serverApi === 'cli-server' && $current_port === $alternate_port) {
// @todo Explain how to fix this problem on our help page, and link to it, $message = $this->t('Your site appears to be running on the built-in PHP web server on port @port. Drupal cannot be automatically updated with this configuration unless the site can also be reached on an alternate port.', [
// in https://drupal.org/i/3312669. '@port' => $current_port,
$event->addError([
$this->t('Your site appears to be running on the built-in PHP web server on port @port. Drupal cannot be automatically updated with this configuration unless the site can also be reached on an alternate port.', [
'@port' => $current_port,
]),
]); ]);
if ($this->moduleHandler->moduleExists('help')) {
$url = Url::fromRoute('help.page')
->setRouteParameter('name', 'automatic_updates')
->setOption('fragment', 'cron-alternate-port')
->toString();
$message = $this->t('@message See <a href=":url">the Automatic Updates help page</a> for more information on how to resolve this.', [
'@message' => $message,
':url' => $url,
]);
}
$event->addError([$message]);
} }
} }
......
...@@ -5,6 +5,7 @@ namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation; ...@@ -5,6 +5,7 @@ namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation;
use Drupal\automatic_updates\CronUpdater; use Drupal\automatic_updates\CronUpdater;
use Drupal\automatic_updates\Validator\CronServerValidator; use Drupal\automatic_updates\Validator\CronServerValidator;
use Drupal\Core\Logger\RfcLogLevel; use Drupal\Core\Logger\RfcLogLevel;
use Drupal\Core\Url;
use Drupal\package_manager\Exception\StageValidationException; use Drupal\package_manager\Exception\StageValidationException;
use Drupal\package_manager\ValidationResult; use Drupal\package_manager\ValidationResult;
use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase; use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase;
...@@ -68,7 +69,7 @@ class CronServerValidatorTest extends AutomaticUpdatesKernelTestBase { ...@@ -68,7 +69,7 @@ class CronServerValidatorTest extends AutomaticUpdatesKernelTestBase {
} }
/** /**
* Tests server configuration validation for unattended updates. * Tests server validation for unattended updates.
* *
* @param bool $alternate_port * @param bool $alternate_port
* Whether or not an alternate port should be set. * Whether or not an alternate port should be set.
...@@ -118,4 +119,39 @@ class CronServerValidatorTest extends AutomaticUpdatesKernelTestBase { ...@@ -118,4 +119,39 @@ class CronServerValidatorTest extends AutomaticUpdatesKernelTestBase {
} }
} }
/**
* Tests server validation for unattended updates with Help enabled.
*
* @param bool $alternate_port
* Whether or not an alternate port should be set.
* @param string $server_api
* The value of the PHP_SAPI constant, as known to the validator.
* @param string[] $cron_modes
* The cron modes to test with. Can contain any of
* \Drupal\automatic_updates\CronUpdater::DISABLED,
* \Drupal\automatic_updates\CronUpdater::SECURITY, and
* \Drupal\automatic_updates\CronUpdater::ALL.
* @param \Drupal\package_manager\ValidationResult[] $expected_results
* The expected validation results.
*
* @dataProvider providerCronServerValidation
*/
public function testHelpLink(bool $alternate_port, string $server_api, array $cron_modes, array $expected_results): void {
$this->enableModules(['help']);
$url = Url::fromRoute('help.page')
->setRouteParameter('name', 'automatic_updates')
->setOption('fragment', 'cron-alternate-port')
->toString();
foreach ($expected_results as $i => $result) {
$messages = [];
foreach ($result->getMessages() as $message) {
$messages[] = "$message See <a href=\"$url\">the Automatic Updates help page</a> for more information on how to resolve this.";
}
$expected_results[$i] = ValidationResult::createError($messages);
}
$this->testCronServerValidation($alternate_port, $server_api, $cron_modes, $expected_results);
}
} }
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