Skip to content
Snippets Groups Projects
Commit 6c262c68 authored by Kunal Sachdev's avatar Kunal Sachdev Committed by Ted Bowman
Browse files

Issue #3273369 by kunal.sachdev, tedbow: Create a validator to ensure...

Issue #3273369 by kunal.sachdev, tedbow: Create a validator to ensure ExtensionUpdater only updates Drupal modules or Drupal themes
parent d8c9435d
No related branches found
No related tags found
1 merge request!342Issue #3273369: Create a validator to ensure ExtensionUpdater only updates Drupal modules or Drupal themes
......@@ -17,6 +17,14 @@ services:
- '@string_translation'
tags:
- { name: event_subscriber }
automatic_updates_extensions.validator.packages_type:
class: Drupal\automatic_updates_extensions\Validator\UpdatePackagesTypeValidator
arguments:
- '@string_translation'
- '@extension.list.module'
- '@extension.list.theme'
tags:
- { name: event_subscriber }
automatic_updates_extensions.validator.target_release:
class: Drupal\automatic_updates_extensions\Validator\UpdateReleaseValidator
tags:
......
<?php
namespace Drupal\automatic_updates_extensions\Validator;
use Drupal\automatic_updates_extensions\ExtensionUpdater;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ThemeExtensionList;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Utility\ProjectInfo;
use Drupal\package_manager\Event\PreCreateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Validates the type of updated packages.
*/
class UpdatePackagesTypeValidator implements EventSubscriberInterface {
use StringTranslationTrait;
/**
* The module list service.
*
* @var \Drupal\Core\Extension\ModuleExtensionList
*/
protected $moduleList;
/**
* The theme list service.
*
* @var \Drupal\Core\Extension\ThemeExtensionList
*/
protected $themeList;
/**
* Constructs a UpdatePackagesTypeValidator object.
*
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation
* The translation service.
* @param \Drupal\Core\Extension\ModuleExtensionList $module_list
* The module list service.
* @param \Drupal\Core\Extension\ThemeExtensionList $theme_list
* The theme list service.
*/
public function __construct(TranslationInterface $translation, ModuleExtensionList $module_list, ThemeExtensionList $theme_list) {
$this->setStringTranslation($translation);
$this->moduleList = $module_list;
$this->themeList = $theme_list;
}
/**
* Validates that updated packages are only modules or themes.
*
* @param \Drupal\package_manager\Event\PreCreateEvent $event
* The event object.
*/
public function checkPackagesAreOnlyThemesOrModules(PreCreateEvent $event): void {
$stage = $event->getStage();
if ($stage instanceof ExtensionUpdater) {
$package_versions = $stage->getPackageVersions();
$invalid_projects = [];
$extension_list = array_merge($this->themeList->getList(), $this->moduleList->getList());
$project_info = new ProjectInfo();
$all_projects = array_map(
function (Extension $extension) use ($project_info): string {
return $project_info->getProjectName($extension);
},
$extension_list
);
foreach (['production', 'dev'] as $package_type) {
foreach ($package_versions[$package_type] as $package => $version) {
$update_project = str_replace('drupal/', '', $package);
if ($update_project === 'drupal' || !in_array($update_project, $all_projects)) {
$invalid_projects[] = $update_project;
}
}
}
if ($invalid_projects) {
$event->addError($invalid_projects, $this->t('Only Drupal Modules or Drupal Themes can be updated, therefore the following projects cannot be updated:'));
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
PreCreateEvent::class => 'checkPackagesAreOnlyThemesOrModules',
];
}
}
......@@ -28,7 +28,11 @@ class ExtensionUpdaterTest extends AutomaticUpdatesKernelTestBase {
* {@inheritdoc}
*/
protected function setUp(): void {
// This test doesn't need to validate that the test projects used are in the
// codebase. Therefore, we need to disable the following validators that
// require real Drupal projects.
$this->disableValidators[] = 'automatic_updates_extensions.validator.target_release';
$this->disableValidators[] = 'automatic_updates_extensions.validator.packages_type';
parent::setUp();
$this->installEntitySchema('user');
}
......
......@@ -31,6 +31,10 @@ class PackagesInstalledWithComposerValidatorTest extends AutomaticUpdatesExtensi
// secure and supported. Therefore, we need to disable the update release
// validator that validates updated projects are secure and supported.
$this->disableValidators[] = 'automatic_updates_extensions.validator.target_release';
// In this test, we don't focus on validating that the updated projects are
// only themes or modules. Therefore, we need to disable the update packages
// type validator.
$this->disableValidators[] = 'automatic_updates_extensions.validator.packages_type';
parent::setUp();
$this->createTestProject();
$this->activeDir = $this->container->get('package_manager.path_locator')
......
<?php
namespace Drupal\Tests\automatic_updates_extensions\Kernel\Validator;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\ValidationResult;
use Drupal\Tests\automatic_updates_extensions\Kernel\AutomaticUpdatesExtensionsKernelTestBase;
/**
* Validates the type of updated packages.
*
* @coversDefaultClass \Drupal\automatic_updates_extensions\Validator\UpdatePackagesTypeValidator
*
* @group automatic_updates_extensions
*/
class UpdatePackagesTypeValidatorTest extends AutomaticUpdatesExtensionsKernelTestBase {
/**
* {@inheritdoc}
*/
protected function setUp(): void {
// In this test, we don't focus on validating that the updated projects are
// secure and supported. Therefore, we need to disable the update release
// validator that validates updated projects are secure and supported.
$this->disableValidators[] = 'automatic_updates_extensions.validator.target_release';
$this->disableValidators[] = 'automatic_updates_extensions.validator.packages_installed_with_composer';
parent::setUp();
$this->createTestProject();
}
/**
* Data provider for testUpdatePackagesAreOnlyThemesOrModules().
*
* @return array
* Test cases for testUpdatePackagesAreOnlyThemesOrModules().
*/
public function providerUpdatePackagesAreOnlyThemesOrModules(): array {
return [
'non existing project updated' => [
[
'non_existing_project' => '9.8.1',
],
[ValidationResult::createError(['non_existing_project'], t('Only Drupal Modules or Drupal Themes can be updated, therefore the following projects cannot be updated:'))],
],
'non existing project, test module and test theme updated' => [
[
'non_existing_project' => '9.8.1',
'test_module_project' => '9.8.1',
'test_theme_project' => '9.8.1',
],
[ValidationResult::createError(['non_existing_project'], t('Only Drupal Modules or Drupal Themes can be updated, therefore the following projects cannot be updated:'))],
],
'drupal updated' => [
[
'drupal' => '9.8.1',
],
[ValidationResult::createError(['drupal'], t('Only Drupal Modules or Drupal Themes can be updated, therefore the following projects cannot be updated:'))],
],
];
}
/**
* Tests the packages installed with composer during pre-create.
*
* @param array $projects
* The projects to install.
* @param array $expected_results
* The expected validation results.
*
* @dataProvider providerUpdatePackagesAreOnlyThemesOrModules
*/
public function testUpdatePackagesAreOnlyThemesOrModules(array $projects, array $expected_results): void {
$module_info = ['project' => 'test_module_project'];
$this->config('update_test.settings')
->set("system_info.aaa_automatic_updates_test", $module_info)
->save();
$theme_info = ['project' => 'test_theme_project'];
$this->config('update_test.settings')
->set("system_info.automatic_updates_theme", $theme_info)
->save();
$this->assertUpdateResults($projects, $expected_results, PreCreateEvent::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