Add a validate() method to ComposerInspector to ensure that Composer is usable

Created on 23 February 2023, over 1 year ago
Updated 27 February 2023, over 1 year ago

Problem/Motivation

We have many validators that use the Composer inspector; misconfigured Composer setups could cause them to have problems. Right now, each validator has to catch and handle these errors. If they use \Drupal\package_manager\Event\PreOperationStageEvent::addErrorFromThrowable with the error directly from Composer, it is hard to read.

Also we have `ComposerJsonExistsValidator` and ComposerExecutableValidator, but we don't have validator specifically checking for the presence of composer.lock.

Proposed resolution

Add a new public method, ComposerInspector::validate(string $dir), which throws an exception of any of the following are true:

  • Composer's version is not correct (we can either copy the logic from ComposerExecutableValidator for this or use the existing getVersion() method, and cache the detected version in a private class property, since it's unlikely to change over the course of a single request)
  • composer.json is missing
  • composer.lock is missing

The other methods of ComposerInspector (getConfig(), getInstalledPackagesList(), etc.) should call this->validate() before they do anything else. That way it comes impossible to do Composer stuff with a broken set-up, no matter how you slice it.

Meanwhile, let's remove ComposerJsonExistsValidator and ComposerExecutableValidator, and fold them into a new validator: ComposerValidator, which simply calls ComposerInspector::validate() and bubbles any exception it raises up into a validation error. ComposerValidator should have a high priority (10000) so it runs first, and stops propagation if an error is detected. Something like:

 try {
      $this->composerInspector->validate($dir);
    }
    catch (\Throwable $e) {
      $event->addErrorFromThrowable($e, $this->t('Composer set-up is invalid'));
      $event->stopPropagation();
    }

Any other validators that need to directly use Composer (bypassing ComposerInspector's domain methods) can do this:

try {
      $this->composerInspector->validate($dir);
    }
    catch (\Throwable $e) {
      $event->addError([t('Unable to check X composer config because composer is invalid')]
      return;
    }

This means they don't have to repeat the basic failure messages that ComposerInspector::validate() produces.

πŸ“Œ Task
Status

Fixed

Version

3.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States tedbow Ithaca, NY, USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024