diff --git a/core/lib/Drupal/Core/Composer/ExtensionDependencyChecker.php b/core/lib/Drupal/Core/Composer/ExtensionDependencyChecker.php index f26d40b..d3813ef 100644 --- a/core/lib/Drupal/Core/Composer/ExtensionDependencyChecker.php +++ b/core/lib/Drupal/Core/Composer/ExtensionDependencyChecker.php @@ -9,15 +9,12 @@ use Composer\Semver\Semver; use Drupal\Core\Extension\Extension; -use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Performs a naive check for Composer-based module dependencies. */ class ExtensionDependencyChecker { - use StringTranslationTrait; - /** * The path to the Drupal root directory. * @@ -28,13 +25,14 @@ class ExtensionDependencyChecker { /** * The Composer packages that are currently installed. * - * We store this so the object is re-usable without re-parsing the file. + * @see self::getInstalledPackages() * - * @var string[] - * Keys are package names and values are package versions. Example: - * ['crell/api-problem' => '1.7.0'.\]. + * @var null|string[] + * Either NULL when the installed packages have not been computed yet, or an + * array of which keys are package names and values are package versions. + * Example: ['crell/api-problem' => '1.7.0']. */ - protected $composerInstalled = []; + protected $installedPackages; /** * Creates a new instance. @@ -56,30 +54,35 @@ public function __construct($drupal_root) { * TRUE if this extension's Composer dependencies are met, FALSE otherwise. */ public function dependenciesAreMet(Extension $extension) { - // Does the extension have a composer.json file? $composer_file_path = $this->drupalRoot . '/' . $extension->getPath() . '/composer.json'; - if (is_readable($composer_file_path)) { - $composer_dependencies = json_decode(file_get_contents($composer_file_path)); - $installed_packages = $this->getInstalledPackages(); - - // Gather all the requirements. - $require = []; - if (!empty($composer_dependencies->require)) { - $require = (array) $composer_dependencies->require; + + // If the extension has on Composer file, it has no unmet dependencies. + if (!file_exists($composer_file_path)) { + return TRUE; + } + + $composer_file = json_decode(file_get_contents($composer_file_path)); + + // If the extension has no Composer dependencies at all, it has no unmet + // dependencies. + if (empty($composer_file->require)) { + return TRUE; + } + + $requirements = (array) $composer_file->require; + $installed_packages = $this->getInstalledPackages(); + $semver = new Semver(); + + // Check each required package against the list of installed packages. + foreach ($requirements as $package_name => $constraint) { + // If a dependency is not installed at all, it is unmet. + if (empty($installed_packages[$package_name])) { + return FALSE; } - if (!empty($require)) { - // Check each required package against the list of installed packages. - $semver = new Semver(); - foreach ($require as $package_name => $constraint) { - if (empty($installed_packages[$package_name])) { - return FALSE; - } - if (!$semver->satisfies($installed_packages[$package_name], $constraint)) { - return FALSE; - } - } + // If the wrong version of a dependency is installed, it is unmet. + elseif (!$semver->satisfies($installed_packages[$package_name], $constraint)) { + return FALSE; } - return TRUE; } return TRUE; } @@ -89,22 +92,31 @@ public function dependenciesAreMet(Extension $extension) { * * @return string[] * Keys are package names and values are package versions. Example: - * ['crell/api-problem' => '1.7.0'.\]. + * ['crell/api-problem' => '1.7.0']. */ protected function getInstalledPackages() { - // Find the installed packages once, and cache the data. - if (empty($this->composerInstalled)) { - $installed_json = $this->drupalRoot . '/vendor/composer/installed.json'; - if (file_exists($installed_json)) { - $json = file_get_contents($installed_json, FALSE); - foreach (json_decode($json) as $package) { - if (isset($package->name) && isset($package->version_normalized)) { - $this->composerInstalled[$package->name] = $package->version_normalized; - } - } + // Quickly return the cached list, if it exists. + if (is_array($this->installedPackages)) { + return $this->installedPackages; + } + + $installed_json_path = $this->drupalRoot . '/vendor/composer/installed.json'; + + // If installed.json does not exist, no packages are installed. + if (!file_exists($installed_json_path)) { + $this->installedPackages = []; + return $this->installedPackages; + } + + // Parse the list once and then cache it. + $json = file_get_contents($installed_json_path, FALSE); + $this->installedPackages = []; + foreach (json_decode($json) as $package) { + if (isset($package->name) && isset($package->version_normalized)) { + $this->installedPackages[$package->name] = $package->version_normalized; } } - return $this->composerInstalled; + return $this->installedPackages; } }