diff --git a/core/modules/composer_dependency/composer_dependency.install b/core/modules/composer_dependency/composer_dependency.install index c4b7e39..ec140ff 100644 --- a/core/modules/composer_dependency/composer_dependency.install +++ b/core/modules/composer_dependency/composer_dependency.install @@ -32,6 +32,8 @@ function composer_dependency_requirements($phase) { } } if ($phase == 'runtime') { + // We have to check if the service throws an exception because the vendor/ + // directory could have changed since the last run. $drupal_dependencies = NULL; try { $drupal_dependencies = \Drupal::service('composer_dependency.drupal_respository'); @@ -46,22 +48,12 @@ function composer_dependency_requirements($phase) { } if ($drupal_dependencies) { // Composer is installed as a dependency. - // Discover all composer.json files. - $composer_paths = []; - $module_handler = \Drupal::moduleHandler(); - $module_list = $module_handler->getModuleList(); - foreach ($module_list as $name => $module) { - $path = $module->getPath() . '/composer.json'; - if (file_exists($path)) { - $composer_paths[$name] = $path; - } - } + $composer_paths = $drupal_dependencies->modulesWithComposerDependencies(); // Determine if our requirements are met. $unmet_dependencies = []; - foreach ($composer_paths as $name => $json_path) { - $json_file = new JsonFile($json_path); - if (!$drupal_dependencies->areDependenciesMet($json_file)) { - $unmet_dependencies[] = $name; + foreach (array_keys($composer_paths) as $module_name) { + if (!$drupal_dependencies->checkForModule($module_name)) { + $unmet_dependencies[] = $module_name; } } if (count($unmet_dependencies)) { diff --git a/core/modules/composer_dependency/composer_dependency.services.yml b/core/modules/composer_dependency/composer_dependency.services.yml index 64cbf57..5ab69a6 100644 --- a/core/modules/composer_dependency/composer_dependency.services.yml +++ b/core/modules/composer_dependency/composer_dependency.services.yml @@ -6,4 +6,4 @@ services: - { name: parameter_service } composer_dependency.drupal_respository.factory: class: Drupal\composer_dependency\DrupalRepositoryFactory - arguments: ['@app.root'] + arguments: ['@app.root', '@module_handler'] diff --git a/core/modules/composer_dependency/src/DrupalRepository.php b/core/modules/composer_dependency/src/DrupalRepository.php index 49fe707..66c07bf 100644 --- a/core/modules/composer_dependency/src/DrupalRepository.php +++ b/core/modules/composer_dependency/src/DrupalRepository.php @@ -17,16 +17,69 @@ */ class DrupalRepository extends InstalledFilesystemRepository { + protected $moduleHandler; + /** + * Constructor. * * @param string|SplString $app_root + * Injected app root service parameter. + * @param \Drupal\Core\Extension\ModuleHandlerInterface|null $module_handler + * Injected module handler service. We need to allow a NULL module handler + * because this class can be used without services available. */ - public function __construct($app_root) { + public function __construct($app_root, $module_handler = NULL) { + $this->moduleHandler = $module_handler; $installed_json = (string) $app_root . '/core/vendor/composer/installed.json'; parent::__construct(new JsonFile($installed_json)); } /** + * Gather a list of modules with Composer-based dependencies. + * + * @return array + * A keyed array, with the name of the module as the key, and the path to + * composer.json as the value. + * + * @throws \RuntimeException + */ + public function modulesWithComposerDependencies() { + if ($this->moduleHandler) { + $composer_paths = []; + $module_list = $this->moduleHandler->getModuleList(); + foreach ($module_list as $name => $module) { + $path = $module->getPath() . '/composer.json'; + if (file_exists($path)) { + $composer_paths[$name] = $path; + } + } + return $composer_paths; + } + throw new \RuntimeException('The module handler service is unavailable to the Composer repository service.'); + } + + /** + * Check whether a module's Composer-based dependencies are met. + * + * @param string $module_name + * The name of the module we're checking. + * + * @return bool + */ + public function checkForModule($module_name) { + if ($this->moduleHandler) { + $module = $this->moduleHandler->getModule($module_name); + $module_composer = $module->getPath() . '/composer.json'; + if (file_exists($module_composer)) { + return $this->areDependenciesMet(new JsonFile($module_composer)); + } + // If there's no composer.json file, then dependencies are met. + return TRUE; + } + throw new \RuntimeException('The module handler service is unavailable to the Composer repository service.'); + } + + /** * Determine whether a composer.json file depends on a package not present. * * Excludes require-dev (for now). diff --git a/core/modules/composer_dependency/src/DrupalRepositoryFactory.php b/core/modules/composer_dependency/src/DrupalRepositoryFactory.php index e4b6d374..e3203ce 100644 --- a/core/modules/composer_dependency/src/DrupalRepositoryFactory.php +++ b/core/modules/composer_dependency/src/DrupalRepositoryFactory.php @@ -12,9 +12,11 @@ class DrupalRepositoryFactory { protected $appRoot; + protected $moduleHandler; - public function __construct($app_root) { + public function __construct($app_root, $module_handler) { $this->appRoot = (string) $app_root; + $this->moduleHandler = $module_handler; } public function getDrupalRepository() { @@ -29,7 +31,7 @@ public function getDrupalRepository() { // InstalledFilesystemRepository is available. // @todo: Determine a better way to do this. require_once __DIR__ . '/DrupalRepository.php'; - return new DrupalRepository($this->appRoot); + return new DrupalRepository($this->appRoot, $this->moduleHandler); } }