class ExecutableFinder

Same name and namespace in other branches
  1. 11.x core/modules/package_manager/src/ExecutableFinder.php \Drupal\package_manager\ExecutableFinder

An executable finder which looks for executable paths in configuration.

@internal This is an internal part of Package Manager and may be changed or removed at any time without warning. External code should not interact with this class.

Hierarchy

Expanded class hierarchy of ExecutableFinder

2 files declare their use of ExecutableFinder
ExecutableFinderTest.php in core/modules/package_manager/tests/src/Unit/ExecutableFinderTest.php
ServicesTest.php in core/modules/package_manager/tests/src/Kernel/ServicesTest.php

File

core/modules/package_manager/src/ExecutableFinder.php, line 24

Namespace

Drupal\package_manager
View source
final class ExecutableFinder implements ExecutableFinderInterface, LoggerAwareInterface {
  use LoggerAwareTrait;
  
  /**
   * The path where Composer is installed in the project, or FALSE if it's not.
   */
  private string|false|null $composerPackagePath = NULL;
  
  /**
   * The path of the Composer binary, or NULL if it can't be found.
   */
  private ?string $composerBinaryPath = NULL;
  public function __construct(private readonly ExecutableFinderInterface $decorated, private readonly FileSystemInterface $fileSystem, private readonly ConfigFactoryInterface $configFactory) {
    $this->composerPackagePath = InstalledVersions::isInstalled('composer/composer') ? InstalledVersions::getInstallPath('composer/composer') : FALSE;
  }
  
  /**
   * {@inheritdoc}
   */
  public function find(string $name) : string {
    if ($name === 'rsync') {
      return Settings::get('package_manager_rsync_path', $this->decorated
        ->find($name));
    }
    elseif ($name === 'composer') {
      $path = $this->getLocalComposerPath();
      if ($path && file_exists($path)) {
        return $path;
      }
      // Find the regular Composer executable overridden by a setting.
      return Settings::get('package_manager_composer_path', $this->decorated
        ->find($name));
    }
    return $this->decorated
      ->find($name);
  }
  
  /**
   * Tries to find the Composer binary installed in the project.
   *
   * @return string|null
   *   The path of the `composer` binary installed in the project's vendor
   *   dependencies, or NULL if it is not installed or cannot be found.
   */
  private function getLocalComposerPath() : ?string {
    // Composer is not installed in the project, so there's nothing to do.
    if ($this->composerPackagePath === FALSE) {
      return NULL;
    }
    // This is a bit expensive to compute, so statically cache it.
    if ($this->composerBinaryPath) {
      return $this->composerBinaryPath;
    }
    $composer_json = file_get_contents($this->composerPackagePath . '/composer.json');
    $composer_json = Json::decode($composer_json);
    foreach ($composer_json['bin'] ?? [] as $bin) {
      if (str_ends_with($bin, '/composer')) {
        $bin = $this->composerPackagePath . '/' . $bin;
        // For extra security, try to disable the binary's execute permission.
        // If that fails, it's worth warning about but is not an actual problem.
        if (is_executable($bin) && !$this->fileSystem
          ->chmod($bin, 0644)) {
          $this->logger?->warning('Composer was found at %path, but could not be made read-only.', [
            '%path' => $bin,
          ]);
        }
        return $this->composerBinaryPath = $bin;
      }
    }
    return NULL;
  }

}

Members

Title Sort descending Modifiers Object type Summary
ExecutableFinder::$composerBinaryPath private property The path of the Composer binary, or NULL if it can't be found.
ExecutableFinder::$composerPackagePath private property The path where Composer is installed in the project, or FALSE if it's not.
ExecutableFinder::find public function
ExecutableFinder::getLocalComposerPath private function Tries to find the Composer binary installed in the project.
ExecutableFinder::__construct public function

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