class RootComposer

Provides access to and manipulation of the root composer files.

@internal

Hierarchy

Expanded class hierarchy of RootComposer

File

composer/Plugin/RecipeUnpack/RootComposer.php, line 18

Namespace

Drupal\Composer\Plugin\RecipeUnpack
View source
final class RootComposer {
  
  /**
   * The JSON manipulator for the contents of the root composer.json.
   */
  private JsonManipulator $composerManipulator;
  
  /**
   * The locked root composer.json content.
   *
   * @var array<string, mixed>|null
   */
  private ?array $composerLockedContent = NULL;
  public function __construct(private readonly Composer $composer, private readonly IOInterface $io) {
  }
  
  /**
   * Retrieves the JSON manipulator for the contents of the root composer.json.
   *
   * @return \Composer\Json\JsonManipulator
   *   The JSON manipulator.
   */
  public function getComposerManipulator() : JsonManipulator {
    $this->composerManipulator ??= new JsonManipulator(file_get_contents(Factory::getComposerFile()));
    return $this->composerManipulator;
  }
  
  /**
   * Gets the locked root composer.json content.
   *
   * @return array<string, mixed>
   *   The locked root composer.json content.
   */
  public function getComposerLockedContent() : array {
    $this->composerLockedContent ??= $this->composer
      ->getLocker()
      ->getLockData();
    return $this->composerLockedContent;
  }
  
  /**
   * Removes an element from the composer lock.
   *
   * @param string $key
   *   The key of the element to remove.
   * @param string $index
   *   The index of the element to remove.
   */
  public function removeFromComposerLock(string $key, string $index) : void {
    unset($this->composerLockedContent[$key][$index]);
  }
  
  /**
   * Adds an element to the composer lock.
   *
   * @param string $key
   *   The key of the element to add.
   * @param array $data
   *   The data to add.
   */
  public function addToComposerLock(string $key, array $data) : void {
    $this->composerLockedContent[$key][] = $data;
  }
  
  /**
   * Writes the root composer files.
   *
   * The files written are:
   *   - composer.json
   *   - composer.lock
   *   - vendor/composer/installed.json
   *   - vendor/composer/installed.php
   *
   * @throws \RuntimeException
   *   If the root composer could not be updated.
   */
  public function writeFiles() : void {
    // Write composer.json.
    $composer_json = Factory::getComposerFile();
    $composer_content = $this->getComposerManipulator()
      ->getContents();
    if (!file_put_contents($composer_json, $composer_content)) {
      throw new \RuntimeException(sprintf('Could not update %s', $composer_json));
    }
    // Create package lists for lock file update.
    $local_repo = $this->composer
      ->getRepositoryManager()
      ->getLocalRepository();
    $packages = $dev_packages = [];
    $dev_package_names = $local_repo->getDevPackageNames();
    foreach ($local_repo->getPackages() as $package) {
      if (in_array($package->getName(), $dev_package_names, TRUE)) {
        $dev_packages[] = $package;
      }
      else {
        $packages[] = $package;
      }
    }
    $lock_file_path = Factory::getLockFile(Factory::getComposerFile());
    $lock_file = new JsonFile($lock_file_path, io: $this->io);
    $old_locker = $this->composer
      ->getLocker();
    $locker = new Locker($this->io, $lock_file, $this->composer
      ->getInstallationManager(), $composer_content);
    $composer_locker_content = $this->getComposerLockedContent();
    // Write the lock file.
    $locker->setLockData($packages, $dev_packages, $composer_locker_content['platform'], $composer_locker_content['platform-dev'], $composer_locker_content['aliases'], $old_locker->getMinimumStability(), $old_locker->getStabilityFlags(), $old_locker->getPreferStable(), $old_locker->getPreferLowest(), $old_locker->getPlatformOverrides());
    $this->composer
      ->setLocker($locker);
    // Update installed.json and installed.php.
    $local_repo->write($local_repo->getDevMode() ?? TRUE, $this->composer
      ->getInstallationManager());
    $this->io
      ->write("Unpacking has updated the root composer files.", verbosity: IOInterface::VERBOSE);
    assert(self::checkRootPackage($composer_content, $this->composer
      ->getPackage()), 'Composer root package and composer.json match');
  }
  
  /**
   * Checks that the composer content and root package match.
   *
   * @param string $composer_content
   *   The root composer content.
   * @param \Composer\Package\RootPackageInterface $root_package
   *   The root package.
   *
   * @return bool
   *   TRUE if the composer content and root package match, FALSE if not.
   */
  private static function checkRootPackage(string $composer_content, RootPackageInterface $root_package) : bool {
    $composer = JsonFile::parseJson($composer_content);
    return empty(array_diff_key($root_package->getRequires(), $composer['require'] ?? [])) && empty(array_diff_key($root_package->getDevRequires(), $composer['require-dev'] ?? []));
  }

}

Members

Title Sort descending Modifiers Object type Summary
RootComposer::$composerLockedContent private property The locked root composer.json content.
RootComposer::$composerManipulator private property The JSON manipulator for the contents of the root composer.json.
RootComposer::addToComposerLock public function Adds an element to the composer lock.
RootComposer::checkRootPackage private static function Checks that the composer content and root package match.
RootComposer::getComposerLockedContent public function Gets the locked root composer.json content.
RootComposer::getComposerManipulator public function Retrieves the JSON manipulator for the contents of the root composer.json.
RootComposer::removeFromComposerLock public function Removes an element from the composer lock.
RootComposer::writeFiles public function Writes the root composer files.
RootComposer::__construct public function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.