diff --git a/automatic_updates_extensions/automatic_updates_extensions.services.yml b/automatic_updates_extensions/automatic_updates_extensions.services.yml index d2c2a1305bb1e76d2e8b5a4901e89032d0f26212..8e22f97c5691cc7916e2120b0476e42c7e242b2e 100644 --- a/automatic_updates_extensions/automatic_updates_extensions.services.yml +++ b/automatic_updates_extensions/automatic_updates_extensions.services.yml @@ -18,14 +18,6 @@ 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: diff --git a/automatic_updates_extensions/src/ExtensionUpdater.php b/automatic_updates_extensions/src/ExtensionUpdater.php index 6314ea7d00dbd98a949d35ff239e71e13347e2e8..91109fa788d9229b8436a16f2e49ee6051e09ab9 100644 --- a/automatic_updates_extensions/src/ExtensionUpdater.php +++ b/automatic_updates_extensions/src/ExtensionUpdater.php @@ -43,7 +43,10 @@ class ExtensionUpdater extends Stage { ->getPackage() ->getDevRequires(); foreach ($project_versions as $project_name => $version) { - $package = "drupal/$project_name"; + $package = $composer->getPackageForProject($project_name); + if (empty($package)) { + throw new \InvalidArgumentException("The project $project_name is not a Drupal project known to Composer and cannot be updated."); + } $group = array_key_exists($package, $require_dev) ? 'dev' : 'production'; $package_versions[$group][$package] = LegacyVersionUtility::convertToSemanticVersion($version); } diff --git a/automatic_updates_extensions/src/Validator/PackagesInstalledWithComposerValidator.php b/automatic_updates_extensions/src/Validator/PackagesInstalledWithComposerValidator.php index 54af7e4dc49fc49fdb3576f1346e57a76846fc66..487b46a64ff8c997a70e43e3b0685887650a216f 100644 --- a/automatic_updates_extensions/src/Validator/PackagesInstalledWithComposerValidator.php +++ b/automatic_updates_extensions/src/Validator/PackagesInstalledWithComposerValidator.php @@ -7,12 +7,12 @@ use Drupal\automatic_updates_extensions\ExtensionUpdater; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\package_manager\Event\PreApplyEvent; -use Drupal\package_manager\Event\PreCreateEvent; -use Drupal\package_manager\Event\PreOperationStageEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Validates packages are installed via Composer. + * + * @todo Remove this validator completely in https://www.drupal.org/i/3303900. */ class PackagesInstalledWithComposerValidator implements EventSubscriberInterface { @@ -31,10 +31,10 @@ class PackagesInstalledWithComposerValidator implements EventSubscriberInterface /** * Validates that packages are installed with composer or not. * - * @param \Drupal\package_manager\Event\PreOperationStageEvent $event + * @param \Drupal\package_manager\Event\PreApplyEvent $event * The event object. */ - public function checkPackagesInstalledWithComposer(PreOperationStageEvent $event): void { + public function checkPackagesInstalledWithComposer(PreApplyEvent $event): void { $stage = $event->getStage(); if (!$stage instanceof ExtensionUpdater) { @@ -54,7 +54,6 @@ class PackagesInstalledWithComposerValidator implements EventSubscriberInterface */ public static function getSubscribedEvents() { return [ - PreCreateEvent::class => 'checkPackagesInstalledWithComposer', PreApplyEvent::class => 'checkPackagesInstalledWithComposer', ]; } @@ -62,51 +61,37 @@ class PackagesInstalledWithComposerValidator implements EventSubscriberInterface /** * Gets the packages which aren't installed via composer. * - * @param \Drupal\package_manager\Event\PreOperationStageEvent $event + * @param \Drupal\package_manager\Event\PreApplyEvent $event * The event object. * * @return \Composer\Package\PackageInterface[] * Packages not installed via composer. */ - protected function getPackagesNotInstalledWithComposer(PreOperationStageEvent $event): array { + protected function getPackagesNotInstalledWithComposer(PreApplyEvent $event): array { $stage = $event->getStage(); $active_composer = $stage->getActiveComposer(); - $installed_packages = $active_composer->getInstalledPackages(); - $missing_packages = []; - // During pre-create there is no stage directory, so missing packages can be - // found using package versions that will be required during the update, - // while during pre-apply there is stage directory which will be used to - // find missing packages. - if ($event instanceof PreCreateEvent) { - $package_versions = $stage->getPackageVersions(); - foreach (['production', 'dev'] as $package_group) { - $missing_packages = array_merge($missing_packages, array_diff_key($package_versions[$package_group], $installed_packages)); - } - } - else { - $missing_packages = $stage->getStageComposer()->getPackagesNotIn($active_composer); + $missing_packages = $stage->getStageComposer()->getPackagesNotIn($active_composer); - // The core update system can only fetch release information for modules, - // themes, or profiles that are in the active code base (whether they're - // installed or not). If a package is not one of those types, ignore it - // even if its vendor namespace is `drupal`. - $types = [ - 'drupal-module', - 'drupal-theme', - 'drupal-profile', - ]; - $filter = function (PackageInterface $package) use ($types): bool { - return in_array($package->getType(), $types, TRUE); - }; - $missing_packages = array_filter($missing_packages, $filter); + // The core update system can only fetch release information for modules, + // themes, or profiles that are in the active code base (whether they're + // installed or not). If a package is not one of those types, ignore it + // even if its vendor namespace is `drupal`. + $types = [ + 'drupal-module', + 'drupal-theme', + 'drupal-profile', + ]; + $filter = function (PackageInterface $package) use ($types): bool { + return in_array($package->getType(), $types, TRUE); + }; + $missing_packages = array_filter($missing_packages, $filter); - // The core update system can only fetch release information for drupal - // projects, so saving only the packages whose name starts with drupal/. - $missing_packages = array_filter($missing_packages, function (string $key) { - return str_starts_with($key, 'drupal/'); - }, ARRAY_FILTER_USE_KEY); - } + // The core update system can only fetch release information for drupal + // projects, so saving only the packages whose name starts with drupal/. + $missing_packages = array_filter($missing_packages, function (string $key) { + return str_starts_with($key, 'drupal/'); + }, ARRAY_FILTER_USE_KEY); return $missing_packages; } diff --git a/automatic_updates_extensions/src/Validator/UpdatePackagesTypeValidator.php b/automatic_updates_extensions/src/Validator/UpdatePackagesTypeValidator.php deleted file mode 100644 index 9fc41b9b35cd02fcccda123d83692a2d8720719b..0000000000000000000000000000000000000000 --- a/automatic_updates_extensions/src/Validator/UpdatePackagesTypeValidator.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -namespace Drupal\automatic_updates_extensions\Validator; - -use Drupal\automatic_updates_extensions\ExtensionUpdater; -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) { - return; - } - - $invalid_projects = []; - $all_projects = $this->getInstalledProjectNames(); - - foreach ($stage->getPackageVersions() as $group) { - foreach (array_keys($group) as $package) { - // @todo Use - // \Drupal\package_manager\ComposerUtility::getProjectForPackage() to - // determine the project name in https://www.drupal.org/i/3304142. - $update_project = str_replace('drupal/', '', $package); - if ($update_project === 'drupal' || !in_array($update_project, $all_projects, TRUE)) { - $invalid_projects[] = $update_project; - } - } - } - if ($invalid_projects) { - $event->addError($invalid_projects, $this->t('The following projects cannot be updated because they are not Drupal modules or themes:')); - } - } - - /** - * Returns a list of all available modules and themes' project names. - * - * @return string[] - * The project names of all available modules and themes. - */ - private function getInstalledProjectNames(): array { - $extension_list = array_merge($this->themeList->getList(), $this->moduleList->getList()); - $map = \Closure::fromCallable([new ProjectInfo(), 'getProjectName']); - return array_map($map, $extension_list); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() { - return [ - PreCreateEvent::class => 'checkPackagesAreOnlyThemesOrModules', - ]; - } - -} diff --git a/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php b/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php index 945d89b5a79b894cddfa0a641c4601ecdfd426c6..e6a832537889e05be7c8b9c4641074ee9c3258dc 100644 --- a/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php +++ b/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php @@ -16,6 +16,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; * @internal * This class is an internal part of the module's update handling and * should not be used by external code. + * + * @todo Remove this validator completely in https://www.drupal.org/i/3307369. */ final class UpdateReleaseValidator implements EventSubscriberInterface { @@ -79,7 +81,7 @@ final class UpdateReleaseValidator implements EventSubscriberInterface { ['drupal-module', 'drupal-theme'], TRUE)) { continue; } - [, $project_name] = explode('/', $staged_package->getName()); + $project_name = $staged->getProjectForPackage($staged_package->getName()); $semantic_version = $staged_package->getPrettyVersion(); if (!$this->isSupportedRelease($project_name, $semantic_version)) { $messages[] = $this->t('Project @project_name to version @version', [ @@ -115,8 +117,7 @@ final class UpdateReleaseValidator implements EventSubscriberInterface { $messages = []; foreach (['production', 'dev'] as $package_type) { foreach ($all_versions[$package_type] as $package_name => $sematic_version) { - $package_parts = explode('/', $package_name); - $project_name = $package_parts[1]; + $project_name = $stage->getActiveComposer()->getProjectForPackage($package_name); // If the version isn't in the list of installable releases, then it // isn't secure and supported and the user should receive an error. if (!$this->isSupportedRelease($project_name, $sematic_version)) { diff --git a/automatic_updates_extensions/tests/fixtures/fake-site/vendor/composer/installed.php b/automatic_updates_extensions/tests/fixtures/fake-site/vendor/composer/installed.php new file mode 100644 index 0000000000000000000000000000000000000000..4f90e04078283b7bc2113891f6b518dff5a87279 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/fake-site/vendor/composer/installed.php @@ -0,0 +1,31 @@ +<?php + +/** + * @file + */ + +$projects_dir = __DIR__ . '/../../web/projects'; +return [ + 'versions' => [ + 'drupal/my_module' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/my_module', + ], + 'drupal/my_dev_module' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/my_dev_module', + ], + 'drupal/semver_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/semver_test', + ], + 'drupal/aaa_update_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/aaa_update_test', + ], + 'drupal/aaa_automatic_updates_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/aaa_automatic_updates_test', + ], + ], +]; diff --git a/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/aaa_automatic_updates_test/aaa_automatic_updates_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/aaa_automatic_updates_test/aaa_automatic_updates_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..8215de0b462a258714e2ebb3b9624da096742794 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/aaa_automatic_updates_test/aaa_automatic_updates_test.info.yml.hide @@ -0,0 +1 @@ +project: aaa_automatic_updates_test diff --git a/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/aaa_update_test/aaa_update_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/aaa_update_test/aaa_update_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..b2d1f884d4a007ebd07dc00b3e46a8c5d098918d --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/aaa_update_test/aaa_update_test.info.yml.hide @@ -0,0 +1 @@ +project: aaa_update_test diff --git a/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/my_dev_module/my_dev_module.info.yml.hide b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/my_dev_module/my_dev_module.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..038e544660c96601ccc767d75d191d1ed132abc3 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/my_dev_module/my_dev_module.info.yml.hide @@ -0,0 +1 @@ +project: my_dev_module diff --git a/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/my_module/my_module.info.yml.hide b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/my_module/my_module.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..eb1bc0fda720c2989242046e42db1097f2f8f631 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/my_module/my_module.info.yml.hide @@ -0,0 +1 @@ +project: my_module diff --git a/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/semver_test/semver_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/semver_test/semver_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..6175b81a041a98520a59f20ff0e1bce7b659cacd --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/fake-site/web/projects/semver_test/semver_test.info.yml.hide @@ -0,0 +1 @@ +project: semver_test diff --git a/automatic_updates_extensions/tests/fixtures/new_module/1.0.0/new_module.info.yml b/automatic_updates_extensions/tests/fixtures/new_module/1.0.0/new_module.info.yml.hide similarity index 75% rename from automatic_updates_extensions/tests/fixtures/new_module/1.0.0/new_module.info.yml rename to automatic_updates_extensions/tests/fixtures/new_module/1.0.0/new_module.info.yml.hide index 8ffd0cce5c6bd85945d961b8246cddc9bb77c92c..24cbeec14e6d1b8966cf9bfdeccdbee49e8c069b 100644 --- a/automatic_updates_extensions/tests/fixtures/new_module/1.0.0/new_module.info.yml +++ b/automatic_updates_extensions/tests/fixtures/new_module/1.0.0/new_module.info.yml.hide @@ -1,3 +1,4 @@ name: 'New module' type: module core_version_requirement: ^9 +project: new_module diff --git a/automatic_updates_extensions/tests/fixtures/new_module/1.1.0/new_module.info.yml b/automatic_updates_extensions/tests/fixtures/new_module/1.1.0/new_module.info.yml.hide similarity index 75% rename from automatic_updates_extensions/tests/fixtures/new_module/1.1.0/new_module.info.yml rename to automatic_updates_extensions/tests/fixtures/new_module/1.1.0/new_module.info.yml.hide index 8ffd0cce5c6bd85945d961b8246cddc9bb77c92c..24cbeec14e6d1b8966cf9bfdeccdbee49e8c069b 100644 --- a/automatic_updates_extensions/tests/fixtures/new_module/1.1.0/new_module.info.yml +++ b/automatic_updates_extensions/tests/fixtures/new_module/1.1.0/new_module.info.yml.hide @@ -1,3 +1,4 @@ name: 'New module' type: module core_version_requirement: ^9 +project: new_module diff --git a/automatic_updates_extensions/tests/fixtures/stage_composer/aaa_update_test/vendor/composer/installed.php b/automatic_updates_extensions/tests/fixtures/stage_composer/aaa_update_test/vendor/composer/installed.php new file mode 100644 index 0000000000000000000000000000000000000000..db86abf49f27d864aca21eb9bcef1bd8b92b17ff --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/stage_composer/aaa_update_test/vendor/composer/installed.php @@ -0,0 +1,23 @@ +<?php + +/** + * @file + */ + +$projects_dir = __DIR__ . '/../../web/projects'; +return [ + 'versions' => [ + 'drupal/test_theme' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/test_theme', + ], + 'drupal/semver_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/semver_test', + ], + 'drupal/aaa_update_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/aaa_update_test', + ], + ], +]; diff --git a/automatic_updates_extensions/tests/fixtures/stage_composer/aaa_update_test/web/projects/aaa_update_test/aaa_update_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/stage_composer/aaa_update_test/web/projects/aaa_update_test/aaa_update_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..b2d1f884d4a007ebd07dc00b3e46a8c5d098918d --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/stage_composer/aaa_update_test/web/projects/aaa_update_test/aaa_update_test.info.yml.hide @@ -0,0 +1 @@ +project: aaa_update_test diff --git a/automatic_updates_extensions/tests/fixtures/stage_composer/semver_test/vendor/composer/installed.php b/automatic_updates_extensions/tests/fixtures/stage_composer/semver_test/vendor/composer/installed.php new file mode 100644 index 0000000000000000000000000000000000000000..db86abf49f27d864aca21eb9bcef1bd8b92b17ff --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/stage_composer/semver_test/vendor/composer/installed.php @@ -0,0 +1,23 @@ +<?php + +/** + * @file + */ + +$projects_dir = __DIR__ . '/../../web/projects'; +return [ + 'versions' => [ + 'drupal/test_theme' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/test_theme', + ], + 'drupal/semver_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/semver_test', + ], + 'drupal/aaa_update_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/aaa_update_test', + ], + ], +]; diff --git a/automatic_updates_extensions/tests/fixtures/stage_composer/semver_test/web/projects/semver_test/semver_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/stage_composer/semver_test/web/projects/semver_test/semver_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..6175b81a041a98520a59f20ff0e1bce7b659cacd --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/stage_composer/semver_test/web/projects/semver_test/semver_test.info.yml.hide @@ -0,0 +1 @@ +project: semver_test diff --git a/automatic_updates_extensions/tests/fixtures/stage_composer/test_theme/vendor/composer/installed.php b/automatic_updates_extensions/tests/fixtures/stage_composer/test_theme/vendor/composer/installed.php new file mode 100644 index 0000000000000000000000000000000000000000..db86abf49f27d864aca21eb9bcef1bd8b92b17ff --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/stage_composer/test_theme/vendor/composer/installed.php @@ -0,0 +1,23 @@ +<?php + +/** + * @file + */ + +$projects_dir = __DIR__ . '/../../web/projects'; +return [ + 'versions' => [ + 'drupal/test_theme' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/test_theme', + ], + 'drupal/semver_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/semver_test', + ], + 'drupal/aaa_update_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/aaa_update_test', + ], + ], +]; diff --git a/automatic_updates_extensions/tests/fixtures/stage_composer/test_theme/web/projects/test_theme/test_theme.info.yml.hide b/automatic_updates_extensions/tests/fixtures/stage_composer/test_theme/web/projects/test_theme/test_theme.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..95e64c8affec1370b89e6f78a7a2f7d32076afe1 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/stage_composer/test_theme/web/projects/test_theme/test_theme.info.yml.hide @@ -0,0 +1 @@ +project: test_theme diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/vendor/composer/installed.php b/automatic_updates_extensions/tests/fixtures/two_projects/vendor/composer/installed.php new file mode 100644 index 0000000000000000000000000000000000000000..db86abf49f27d864aca21eb9bcef1bd8b92b17ff --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/vendor/composer/installed.php @@ -0,0 +1,23 @@ +<?php + +/** + * @file + */ + +$projects_dir = __DIR__ . '/../../web/projects'; +return [ + 'versions' => [ + 'drupal/test_theme' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/test_theme', + ], + 'drupal/semver_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/semver_test', + ], + 'drupal/aaa_update_test' => [ + 'type' => 'drupal-module', + 'install_path' => $projects_dir . '/aaa_update_test', + ], + ], +]; diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/aaa_automatic_updates_test/aaa_automatic_updates_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/aaa_automatic_updates_test/aaa_automatic_updates_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..8215de0b462a258714e2ebb3b9624da096742794 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/aaa_automatic_updates_test/aaa_automatic_updates_test.info.yml.hide @@ -0,0 +1 @@ +project: aaa_automatic_updates_test diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/aaa_update_test/aaa_update_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/aaa_update_test/aaa_update_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..b2d1f884d4a007ebd07dc00b3e46a8c5d098918d --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/aaa_update_test/aaa_update_test.info.yml.hide @@ -0,0 +1 @@ +project: aaa_update_test diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/my_dev_module/my_dev_module.info.yml.hide b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/my_dev_module/my_dev_module.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..038e544660c96601ccc767d75d191d1ed132abc3 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/my_dev_module/my_dev_module.info.yml.hide @@ -0,0 +1 @@ +project: my_dev_module diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/my_module/my_module.info.yml.hide b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/my_module/my_module.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..eb1bc0fda720c2989242046e42db1097f2f8f631 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/my_module/my_module.info.yml.hide @@ -0,0 +1 @@ +project: my_module diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/semver_test/semver_test.info.yml.hide b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/semver_test/semver_test.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..6175b81a041a98520a59f20ff0e1bce7b659cacd --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/semver_test/semver_test.info.yml.hide @@ -0,0 +1 @@ +project: semver_test diff --git a/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/test_theme/test_theme.info.yml.hide b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/test_theme/test_theme.info.yml.hide new file mode 100644 index 0000000000000000000000000000000000000000..95e64c8affec1370b89e6f78a7a2f7d32076afe1 --- /dev/null +++ b/automatic_updates_extensions/tests/fixtures/two_projects/web/projects/test_theme/test_theme.info.yml.hide @@ -0,0 +1 @@ +project: test_theme diff --git a/automatic_updates_extensions/tests/src/Build/ModuleUpdateTest.php b/automatic_updates_extensions/tests/src/Build/ModuleUpdateTest.php index 55e122bb50011dbea91b4598fad3fa61be8488ea..b674eeb03aab9b7aca8113e468a1911e9fd6f2c5 100644 --- a/automatic_updates_extensions/tests/src/Build/ModuleUpdateTest.php +++ b/automatic_updates_extensions/tests/src/Build/ModuleUpdateTest.php @@ -37,12 +37,11 @@ class ModuleUpdateTest extends UpdateTestBase { \$config['update_test.settings']['system_info'] = $system_info; END; $this->writeSettings($code); - - $this->addRepository('alpha', __DIR__ . '/../../../../package_manager/tests/fixtures/alpha/1.0.0'); + $this->addRepository('alpha', $this->copyFixtureToTempDirectory(__DIR__ . '/../../../../package_manager/tests/fixtures/alpha/1.0.0')); $this->runComposer('COMPOSER_MIRROR_PATH_REPOS=1 composer require drupal/alpha --update-with-all-dependencies', 'project'); $this->assertModuleVersion('alpha', '1.0.0'); $fs = new SymfonyFilesystem(); - $fs->mirror(__DIR__ . '/../../fixtures/new_module', $this->getWorkspaceDirectory() . '/project/web/modules'); + $fs->mirror($this->copyFixtureToTempDirectory(__DIR__ . '/../../fixtures/new_module'), $this->getWorkspaceDirectory() . '/project/web/modules'); $this->installModules([ 'automatic_updates_extensions_test_api', 'alpha', @@ -50,7 +49,7 @@ END; ]); // Change both modules' upstream version. - $this->addRepository('alpha', __DIR__ . '/../../../../package_manager/tests/fixtures/alpha/1.1.0'); + $this->addRepository('alpha', $this->copyFixtureToTempDirectory(__DIR__ . '/../../../../package_manager/tests/fixtures/alpha/1.1.0')); } /** @@ -72,7 +71,7 @@ END; $mink = $this->getMink(); $mink->assertSession()->statusCodeEquals(500); $page_text = $mink->getSession()->getPage()->getText(); - $this->assertStringContainsString('Automatic Updates can only update projects that were installed via Composer. The following packages are not installed through composer:', $page_text); + $this->assertStringContainsString('The project new_module is not a Drupal project known to Composer and cannot be updated.', $page_text); $this->assertStringContainsString('new_module', $page_text); // Use the API endpoint to create a stage and update the 'alpha' module to // 1.1.0. We ask the API to return the contents of the module's diff --git a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php index a7df5b7e14fb19a0a3f4c3ebf12ba6aa83be9261..d8c3a98bd7e77ee921efecf7738633ad1af37f3d 100644 --- a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php +++ b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php @@ -153,11 +153,11 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { */ public function testSuccessfulUpdate(bool $maintenance_mode_on, string $project_name, string $project_title, string $installed_version, string $target_version): void { $this->container->get('theme_installer')->install(['automatic_updates_theme_with_updates']); - // By default, the Update module only checks for updates of installed modules - // and themes. The two modules we're testing here (semver_test and aaa_update_test) - // are already installed by static::$modules. + // By default, the Update module only checks for updates of installed + // modules and themes. The two modules we're testing here (semver_test and + // aaa_update_test) are already installed by static::$modules. $this->container->get('theme_installer')->install(['test_theme']); - Stager::setFixturePath(__DIR__ . '/../../fixtures/stage_composer/' . $project_name); + $this->useFixtureDirectoryAsStaged(__DIR__ . '/../../fixtures/stage_composer/' . $project_name); $this->setReleaseMetadata(__DIR__ . '/../../../../tests/fixtures/release-history/drupal.9.8.2.xml'); $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/' . $project_name . '.1.1.xml'); $this->setProjectInstalledVersion([$project_name => $installed_version]); @@ -202,7 +202,6 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { $page->pressButton('Continue'); $this->checkForMetaRefresh(); - $assert_session->addressEquals('/admin/reports/updates'); // Confirm that the site was in maintenance before the update was applied. // @see \Drupal\package_manager_test_validation\EventSubscriber\TestSubscriber::handleEvent() diff --git a/automatic_updates_extensions/tests/src/Kernel/AutomaticUpdatesExtensionsKernelTestBase.php b/automatic_updates_extensions/tests/src/Kernel/AutomaticUpdatesExtensionsKernelTestBase.php index f7a4b01a2467b79d4b39186465bff05008f7817c..a6357c9c77c96b512d501d919ecee10cb080e0f5 100644 --- a/automatic_updates_extensions/tests/src/Kernel/AutomaticUpdatesExtensionsKernelTestBase.php +++ b/automatic_updates_extensions/tests/src/Kernel/AutomaticUpdatesExtensionsKernelTestBase.php @@ -3,18 +3,20 @@ namespace Drupal\Tests\automatic_updates_extensions\Kernel; use Drupal\automatic_updates_extensions\ExtensionUpdater; - use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\package_manager\Exception\StageValidationException; use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase; use Drupal\Tests\package_manager\Kernel\TestPathFactory; use Drupal\Tests\package_manager\Kernel\TestStageTrait; +use Drupal\Tests\package_manager\Traits\InfoYmlConverterTrait; /** * Base class for kernel tests of the Automatic Updates Extensions module. */ abstract class AutomaticUpdatesExtensionsKernelTestBase extends AutomaticUpdatesKernelTestBase { + use InfoYmlConverterTrait; + /** * {@inheritdoc} */ @@ -36,6 +38,18 @@ abstract class AutomaticUpdatesExtensionsKernelTestBase extends AutomaticUpdates parent::setUp(); } + /** + * Create Virtual Project. + * + * @param string|null $source_dir + * Source directory. + */ + protected function createVirtualProject(?string $source_dir = NULL): void { + $source_dir = $source_dir ?? __DIR__ . '/../../fixtures/fake-site'; + parent::createVirtualProject($source_dir); + $this->renameVfsInfoYmlFiles(); + } + /** * {@inheritdoc} */ diff --git a/automatic_updates_extensions/tests/src/Kernel/ExtensionUpdaterTest.php b/automatic_updates_extensions/tests/src/Kernel/ExtensionUpdaterTest.php index 61f0845de0a71a1ac46465c857a608781990d116..b05262708476bcfd2b48e362de5a55f1e73d9644 100644 --- a/automatic_updates_extensions/tests/src/Kernel/ExtensionUpdaterTest.php +++ b/automatic_updates_extensions/tests/src/Kernel/ExtensionUpdaterTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\automatic_updates_extensions\Kernel; use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase; +use Drupal\Tests\package_manager\Traits\InfoYmlConverterTrait; use Drupal\Tests\user\Traits\UserCreationTrait; /** @@ -13,6 +14,7 @@ use Drupal\Tests\user\Traits\UserCreationTrait; class ExtensionUpdaterTest extends AutomaticUpdatesKernelTestBase { use UserCreationTrait; + use InfoYmlConverterTrait; /** * {@inheritdoc} @@ -32,28 +34,28 @@ class ExtensionUpdaterTest extends AutomaticUpdatesKernelTestBase { // 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'); - } - - /** - * Tests that correct versions are staged after calling ::begin(). - */ - public function testCorrectVersionsStaged(): void { // Create a user who will own the stage even after the container is rebuilt. $user = $this->createUser([], NULL, TRUE, ['uid' => 2]); $this->setCurrentUser($user); $this->createVirtualProject(__DIR__ . '/../../fixtures/fake-site'); + $this->renameVfsInfoYmlFiles(); + } + /** + * Tests that correct versions are staged after calling ::begin(). + */ + public function testCorrectVersionsStaged(): void { $id = $this->container->get('automatic_updates_extensions.updater')->begin([ 'my_module' => '9.8.1', // Use a legacy version number to ensure they are converted to semantic // version numbers which will work with the drupal.org Composer facade. 'my_dev_module' => '8.x-1.2-alpha1', ]); + $user = $this->container->get('current_user')->getAccount(); // Rebuild the container to ensure the package versions are persisted. /** @var \Drupal\Core\DrupalKernel $kernel */ $kernel = $this->container->get('kernel'); @@ -123,4 +125,15 @@ class ExtensionUpdaterTest extends AutomaticUpdatesKernelTestBase { $this->container->get('automatic_updates_extensions.updater')->begin([]); } + /** + * Tests exception if a Drupal project unknown to composer sent to ::begin(). + */ + public function testUnknownDrupalProject(): void { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage("The project my_module_unknown is not a Drupal project known to Composer and cannot be updated."); + $this->container->get('automatic_updates_extensions.updater')->begin([ + 'my_module_unknown' => '9.8.1', + ]); + } + } diff --git a/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php b/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php index 9d1dfa8b4256ec7449a68113e03fd31cc1faffe3..1ed0f011163a48d24d307efd006ce88b82ab92ac 100644 --- a/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php +++ b/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\automatic_updates_extensions\Kernel\Validator; use Drupal\package_manager\Event\PreApplyEvent; -use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\ValidationResult; use Drupal\Tests\automatic_updates_extensions\Kernel\AutomaticUpdatesExtensionsKernelTestBase; @@ -23,91 +22,9 @@ class PackagesInstalledWithComposerValidatorTest extends AutomaticUpdatesExtensi // In this test, we don't care whether the updated projects are secure and // supported. $this->disableValidators[] = 'automatic_updates_extensions.validator.target_release'; - // We also don't care if the updated projects are themes and modules only. - $this->disableValidators[] = 'automatic_updates_extensions.validator.packages_type'; parent::setUp(); } - /** - * Data provider for testPreCreateException(). - * - * @return mixed[][] - * The test cases. - */ - public function providerPreCreateException(): array { - $summary = t('Automatic Updates can only update projects that were installed via Composer. The following packages are not installed through composer:'); - - return [ - 'module not installed via Composer' => [ - [ - 'new_module' => '9.8.0', - ], - [ - ValidationResult::createError(['new_module'], $summary), - ], - ], - 'theme not installed via Composer' => [ - [ - 'new_theme' => '9.8.0', - ], - [ - ValidationResult::createError(['new_theme'], $summary), - ], - ], - 'profile not installed via Composer' => [ - [ - 'new_profile' => '9.8.0', - ], - [ - ValidationResult::createError(['new_profile'], $summary), - ], - ], - 'module, theme, profile, and library not installed via Composer' => [ - [ - 'new_module' => '9.8.0', - 'new_theme' => '9.8.0', - 'new_profile' => '9.8.0', - 'new_dependency' => '9.8.0', - ], - [ - ValidationResult::createError(['new_module', 'new_theme', 'new_profile', 'new_dependency'], $summary), - ], - ], - 'module, theme, and profile installed via Composer' => [ - [ - 'existing_module' => '9.8.1', - 'existing_theme' => '9.8.1', - 'existing_profile' => '9.8.1', - ], - [], - ], - 'existing module installed and new module not installed via Composer' => [ - [ - 'existing_module' => '9.8.1', - 'new_module' => '9.8.0', - ], - [ - ValidationResult::createError(['new_module'], $summary), - ], - ], - ]; - } - - /** - * 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 providerPreCreateException - */ - public function testPreCreateException(array $projects, array $expected_results): void { - $this->useComposerFixturesFiles(__DIR__ . '/../../../fixtures/packages_installed_with_composer_validator/active'); - $this->assertUpdateResults($projects, $expected_results, PreCreateEvent::class); - } - /** * Data provider for testPreApplyException(). * @@ -146,7 +63,10 @@ class PackagesInstalledWithComposerValidatorTest extends AutomaticUpdatesExtensi 'module, theme, and profile not installed via Composer' => [ "$fixtures_folder/module_theme_profile_dependency_not_installed_stage", [ - ValidationResult::createError(['new_module', 'new_theme', 'new_profile'], $summary), + ValidationResult::createError( + ['new_module', 'new_theme', 'new_profile'], + $summary + ), ], ], ]; diff --git a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php deleted file mode 100644 index 43284d23796a91460b33f0ac905d5f1de73569ad..0000000000000000000000000000000000000000 --- a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php +++ /dev/null @@ -1,91 +0,0 @@ -<?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(); - } - - /** - * Data provider for testUpdatePackagesAreOnlyThemesOrModules(). - * - * @return mixed[][] - * The test cases. - */ - public function providerUpdatePackagesAreOnlyThemesOrModules(): array { - $summary = t('The following projects cannot be updated because they are not Drupal modules or themes:'); - - return [ - 'non existing project updated' => [ - [ - 'non_existing_project' => '9.8.1', - ], - [ - ValidationResult::createError(['non_existing_project'], $summary), - ], - ], - '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'], $summary), - ], - ], - 'drupal updated' => [ - [ - 'drupal' => '9.8.1', - ], - [ - ValidationResult::createError(['drupal'], $summary), - ], - ], - ]; - } - - /** - * 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 { - $this->config('update_test.settings') - ->set("system_info.aaa_automatic_updates_test", [ - 'project' => 'test_module_project', - ]) - ->set("system_info.automatic_updates_theme", [ - 'project' => 'test_theme_project', - ]) - ->save(); - $this->assertUpdateResults($projects, $expected_results, PreCreateEvent::class); - } - -} diff --git a/package_manager/tests/fixtures/alpha/1.0.0/alpha.info.yml b/package_manager/tests/fixtures/alpha/1.0.0/alpha.info.yml.hide similarity index 78% rename from package_manager/tests/fixtures/alpha/1.0.0/alpha.info.yml rename to package_manager/tests/fixtures/alpha/1.0.0/alpha.info.yml.hide index 565d3142d8d816bc2f401ef4a6974c7a4c1c6208..4b12c91c911ffd8506961b4e1aff65baedf28c9b 100644 --- a/package_manager/tests/fixtures/alpha/1.0.0/alpha.info.yml +++ b/package_manager/tests/fixtures/alpha/1.0.0/alpha.info.yml.hide @@ -1,3 +1,4 @@ name: Alpha type: module core_version_requirement: ^9 +project: alpha diff --git a/package_manager/tests/fixtures/alpha/1.1.0/alpha.info.yml b/package_manager/tests/fixtures/alpha/1.1.0/alpha.info.yml.hide similarity index 78% rename from package_manager/tests/fixtures/alpha/1.1.0/alpha.info.yml rename to package_manager/tests/fixtures/alpha/1.1.0/alpha.info.yml.hide index 565d3142d8d816bc2f401ef4a6974c7a4c1c6208..4b12c91c911ffd8506961b4e1aff65baedf28c9b 100644 --- a/package_manager/tests/fixtures/alpha/1.1.0/alpha.info.yml +++ b/package_manager/tests/fixtures/alpha/1.1.0/alpha.info.yml.hide @@ -1,3 +1,4 @@ name: Alpha type: module core_version_requirement: ^9 +project: alpha diff --git a/package_manager/tests/src/Kernel/ComposerUtilityTest.php b/package_manager/tests/src/Kernel/ComposerUtilityTest.php index f80331b01dc407f482d05f0c95dd3562f50671ce..29023f1d4575b56aa9d6d61618e4724a3338adb6 100644 --- a/package_manager/tests/src/Kernel/ComposerUtilityTest.php +++ b/package_manager/tests/src/Kernel/ComposerUtilityTest.php @@ -4,10 +4,8 @@ namespace Drupal\Tests\package_manager\Kernel; use Drupal\KernelTests\KernelTestBase; use Drupal\package_manager\ComposerUtility; +use Drupal\Tests\package_manager\Traits\InfoYmlConverterTrait; use org\bovigo\vfs\vfsStream; -use org\bovigo\vfs\vfsStreamDirectory; -use org\bovigo\vfs\vfsStreamFile; -use org\bovigo\vfs\visitor\vfsStreamAbstractVisitor; /** * @coversDefaultClass \Drupal\package_manager\ComposerUtility @@ -16,6 +14,8 @@ use org\bovigo\vfs\visitor\vfsStreamAbstractVisitor; */ class ComposerUtilityTest extends KernelTestBase { + use InfoYmlConverterTrait; + /** * {@inheritdoc} */ @@ -30,34 +30,7 @@ class ComposerUtilityTest extends KernelTestBase { $fixture = vfsStream::newDirectory('fixture'); vfsStream::copyFromFileSystem(__DIR__ . '/../../fixtures/project_package_conversion', $fixture); $this->vfsRoot->addChild($fixture); - - // Strip the `.hide` suffix from all `.info.yml.hide` files. Drupal's coding - // standards don't allow info files to have the `project` key, but we need - // it to be present for testing. - vfsStream::inspect(new class () extends vfsStreamAbstractVisitor { - - /** - * {@inheritdoc} - */ - public function visitFile(vfsStreamFile $file) { - $name = $file->getName(); - - if (str_ends_with($name, '.info.yml.hide')) { - $new_name = basename($name, '.hide'); - $file->rename($new_name); - } - } - - /** - * {@inheritdoc} - */ - public function visitDirectory(vfsStreamDirectory $dir) { - foreach ($dir->getChildren() as $child) { - $this->visit($child); - } - } - - }); + $this->renameVfsInfoYmlFiles(); } /** diff --git a/package_manager/tests/src/Traits/InfoYmlConverterTrait.php b/package_manager/tests/src/Traits/InfoYmlConverterTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..4f186a53faf69540926627dae11ba5a70cd5518c --- /dev/null +++ b/package_manager/tests/src/Traits/InfoYmlConverterTrait.php @@ -0,0 +1,48 @@ +<?php + +namespace Drupal\Tests\package_manager\Traits; + +use org\bovigo\vfs\vfsStream; +use org\bovigo\vfs\vfsStreamDirectory; +use org\bovigo\vfs\vfsStreamFile; +use org\bovigo\vfs\visitor\vfsStreamAbstractVisitor; + +/** + * Common methods to convert info.yml file that will pass core coding standards. + */ +trait InfoYmlConverterTrait { + + /** + * Renames all files that end with .info.yml.hide. + */ + protected function renameVfsInfoYmlFiles(): void { + // Strip the `.hide` suffix from all `.info.yml.hide` files. Drupal's coding + // standards don't allow info files to have the `project` key, but we need + // it to be present for testing. + vfsStream::inspect(new class () extends vfsStreamAbstractVisitor { + + /** + * {@inheritdoc} + */ + public function visitFile(vfsStreamFile $file) { + $name = $file->getName(); + + if (str_ends_with($name, '.info.yml.hide')) { + $new_name = basename($name, '.hide'); + $file->rename($new_name); + } + } + + /** + * {@inheritdoc} + */ + public function visitDirectory(vfsStreamDirectory $dir) { + foreach ($dir->getChildren() as $child) { + $this->visit($child); + } + } + + }); + } + +} diff --git a/tests/src/Build/UpdateTestBase.php b/tests/src/Build/UpdateTestBase.php index c2ef131588fa746c24c2b047fe76aada0f94d8d1..32d754d758fef90fa281eeba770eda29362a96ef 100644 --- a/tests/src/Build/UpdateTestBase.php +++ b/tests/src/Build/UpdateTestBase.php @@ -4,12 +4,17 @@ namespace Drupal\Tests\automatic_updates\Build; use Drupal\Component\Utility\Html; use Drupal\Tests\package_manager\Build\TemplateProjectTestBase; +use Drupal\Tests\RandomGeneratorTrait; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator; /** * Base class for tests that perform in-place updates. */ abstract class UpdateTestBase extends TemplateProjectTestBase { + use RandomGeneratorTrait; + /** * A secondary server instance, to serve XML metadata about available updates. * @@ -101,4 +106,40 @@ END; } } + /** + * Copies a fixture directory to a temporary directory and returns its path. + * + * @param string $fixture_directory + * The fixture directory. + * + * @return string + * The temporary directory. + */ + protected function copyFixtureToTempDirectory(string $fixture_directory): string { + $temp_directory = $this->getWorkspaceDirectory() . '/fixtures_temp_' . $this->randomMachineName(20); + (new Filesystem())->mirror($fixture_directory, $temp_directory); + $this->assertDirectoryIsWritable($temp_directory); + $this->renameInfoYmlFiles($temp_directory); + return $temp_directory; + } + + /** + * Renames all files that end with .info.yml.hide. + * + * @param string $dir + * The directory to be iterated through. + */ + protected function renameInfoYmlFiles(string $dir) { + // Construct the iterator. + $it = new RecursiveDirectoryIterator($dir, \RecursiveIteratorIterator::SELF_FIRST); + + // Loop through files and rename them. + foreach (new \RecursiveIteratorIterator($it) as $file) { + if ($file->getExtension() == 'hide') { + rename($file->getPathname(), $dir . DIRECTORY_SEPARATOR . + $file->getRelativePath() . DIRECTORY_SEPARATOR . str_replace(".hide", "", $file->getFilename())); + } + } + } + } diff --git a/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php b/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php index df4b249ab952552da937b4a512cebd9aea43d875..7b2cc2216c9e49b44932434dc771bb5398743c56 100644 --- a/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php +++ b/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php @@ -4,9 +4,11 @@ namespace Drupal\Tests\automatic_updates\Functional; use Drupal\Core\Site\Settings; use Drupal\package_manager_bypass\Beginner; +use Drupal\package_manager_bypass\Stager; use Drupal\Tests\BrowserTestBase; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator; /** * Base class for functional tests of the Automatic Updates module. @@ -191,6 +193,43 @@ abstract class AutomaticUpdatesFunctionalTestBase extends BrowserTestBase { Beginner::setFixturePath($active_dir); $this->container->get('package_manager.path_locator') ->setPaths($active_dir, $active_dir . '/vendor', '', NULL); + + $this->renameInfoYmlFiles($active_dir); + } + + /** + * Sets a fixture directory to use as the staged directory. + * + * @param string $fixture_directory + * The fixture directory. + */ + protected function useFixtureDirectoryAsStaged(string $fixture_directory): void { + // Create a temporary directory from our fixture directory that will be + // unique for each test run. This will enable changing files in the + // directory and not affect other tests. + $staged_dir = $this->copyFixtureToTempDirectory($fixture_directory); + Stager::setFixturePath($staged_dir); + + $this->renameInfoYmlFiles($staged_dir); + } + + /** + * Renames all files that end with .info.yml.hide. + * + * @param string $dir + * The directory to be iterated through. + */ + protected function renameInfoYmlFiles(string $dir) { + // Construct the iterator. + $it = new RecursiveDirectoryIterator($dir, \RecursiveIteratorIterator::SELF_FIRST); + + // Loop through files and rename them. + foreach (new \RecursiveIteratorIterator($it) as $file) { + if ($file->getExtension() == 'hide') { + rename($file->getPathname(), $dir . DIRECTORY_SEPARATOR . $file->getRelativePath() . DIRECTORY_SEPARATOR . str_replace(".hide", "", $file->getFilename())); + } + } + } }