diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml index b54402216e39b0b6aa5cc100442959fbde1b900f..d648287bc94e68e4e7659f7a87628ebc137d18b3 100644 --- a/automatic_updates.services.yml +++ b/automatic_updates.services.yml @@ -30,6 +30,12 @@ services: - '@string_translation' tags: - { name: event_subscriber } + automatic_updates.validator.settings: + class: Drupal\automatic_updates\Validator\SettingsValidator + arguments: + - '@string_translation' + tags: + - { name: event_subscriber } automatic_updates.update_version_validator: class: Drupal\automatic_updates\Validator\UpdateVersionValidator arguments: diff --git a/src/Validator/SettingsValidator.php b/src/Validator/SettingsValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..4d09e58df725e2123f7eb302900e6f0fcab43a79 --- /dev/null +++ b/src/Validator/SettingsValidator.php @@ -0,0 +1,52 @@ +<?php + +namespace Drupal\automatic_updates\Validator; + +use Drupal\automatic_updates\Event\ReadinessCheckEvent; +use Drupal\automatic_updates\Updater; +use Drupal\Core\Site\Settings; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\StringTranslation\TranslationInterface; +use Drupal\package_manager\Event\PreCreateEvent; +use Drupal\package_manager\Event\PreOperationStageEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +class SettingsValidator implements EventSubscriberInterface { + + use StringTranslationTrait; + + /** + * Constructs a SettingsValidator object. + * + * @param \Drupal\Core\StringTranslation\TranslationInterface $translation + * The string translation service. + */ + public function __construct(TranslationInterface $translation) { + $this->setStringTranslation($translation); + } + + /** + * Validates site settings before an update starts. + * + * @param \Drupal\package_manager\Event\PreOperationStageEvent $event + * The event object. + */ + public function checkSettings(PreOperationStageEvent $event): void { + if ($event->getStage() instanceof Updater && Settings::get('update_fetch_with_http_fallback')) { + $event->addError([ + $this->t('The <code>update_fetch_with_http_fallback</code> setting must be disabled for automatic updates.'), + ]); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + return [ + ReadinessCheckEvent::class => 'checkSettings', + PreCreateEvent::class => 'checkSettings', + ]; + } + +} diff --git a/tests/src/Kernel/ReadinessValidation/SettingsValidatorTest.php b/tests/src/Kernel/ReadinessValidation/SettingsValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..90612a6b8b77f753132226334d2a059222efebd9 --- /dev/null +++ b/tests/src/Kernel/ReadinessValidation/SettingsValidatorTest.php @@ -0,0 +1,68 @@ +<?php + +namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation; + +use Drupal\package_manager\Exception\StageValidationException; +use Drupal\package_manager\ValidationResult; +use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase; + +/** + * @covers \Drupal\Tests\automatic_updates\Kernel\ReadinessValidation\SettingsValidatorTest + * + * @group automatic_updates + */ +class SettingsValidatorTest extends AutomaticUpdatesKernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'automatic_updates', + 'package_manager', + 'package_manager_bypass', + ]; + + /** + * Data provider for ::testSettingsValidation(). + * + * @return array[] + * Sets of arguments to pass to the test method. + */ + public function providerSettingsValidation(): array { + $result = ValidationResult::createError([ + 'The <code>update_fetch_with_http_fallback</code> setting must be disabled for automatic updates.', + ]); + + return [ + [TRUE, [$result]], + [FALSE, []], + ]; + } + + /** + * Tests settings validation before starting an update. + * + * @param bool $setting + * The value of the update_fetch_with_http_fallback setting. + * @param \Drupal\package_manager\ValidationResult[] $expected_results + * The expected validation results. + * + * @dataProvider providerSettingsValidation + */ + public function testSettingsValidation(bool $setting, array $expected_results): void { + $this->setSetting('update_fetch_with_http_fallback', $setting); + + $this->assertCheckerResultsFromManager($expected_results, TRUE); + try { + $this->container->get('automatic_updates.updater')->begin([ + 'drupal' => '9.8.1', + ]); + // If there was no exception, ensure we're not expecting any errors. + $this->assertSame([], $expected_results); + } + catch (StageValidationException $e) { + $this->assertValidationResultsEqual($expected_results, $e->getResults()); + } + } + +}