Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. CompletionTrait.php

trait CompletionTrait

Adds completion to arguments and options.

@internal

Hierarchy

  • trait \Composer\Command\CompletionTrait

File

vendor/composer/composer/src/Composer/Command/CompletionTrait.php, line 31

Namespace

Composer\Command
View source
trait CompletionTrait {
    
    /**
     * @see BaseCommand::requireComposer()
     */
    public abstract function requireComposer(?bool $disablePlugins = null, ?bool $disableScripts = null) : Composer;
    
    /**
     * Suggestion values for "prefer-install" option
     *
     * @return list<string>
     */
    private function suggestPreferInstall() : array {
        return [
            'dist',
            'source',
            'auto',
        ];
    }
    
    /**
     * Suggest package names from root requirements.
     */
    private function suggestRootRequirement() : \Closure {
        return function (CompletionInput $input) : array {
            $composer = $this->requireComposer();
            return array_merge(array_keys($composer->getPackage()
                ->getRequires()), array_keys($composer->getPackage()
                ->getDevRequires()));
        };
    }
    
    /**
     * Suggest package names from installed.
     */
    private function suggestInstalledPackage(bool $includeRootPackage = true, bool $includePlatformPackages = false) : \Closure {
        return function (CompletionInput $input) use ($includeRootPackage, $includePlatformPackages) : array {
            $composer = $this->requireComposer();
            $installedRepos = [];
            if ($includeRootPackage) {
                $installedRepos[] = new RootPackageRepository(clone $composer->getPackage());
            }
            $locker = $composer->getLocker();
            if ($locker->isLocked()) {
                $installedRepos[] = $locker->getLockedRepository(true);
            }
            else {
                $installedRepos[] = $composer->getRepositoryManager()
                    ->getLocalRepository();
            }
            $platformHint = [];
            if ($includePlatformPackages) {
                if ($locker->isLocked()) {
                    $platformRepo = new PlatformRepository([], $locker->getPlatformOverrides());
                }
                else {
                    $platformRepo = new PlatformRepository([], $composer->getConfig()
                        ->get('platform'));
                }
                if ($input->getCompletionValue() === '') {
                    // to reduce noise, when no text is yet entered we list only two entries for ext- and lib- prefixes
                    $hintsToFind = [
                        'ext-' => 0,
                        'lib-' => 0,
                        'php' => 99,
                        'composer' => 99,
                    ];
                    foreach ($platformRepo->getPackages() as $pkg) {
                        foreach ($hintsToFind as $hintPrefix => $hintCount) {
                            if (str_starts_with($pkg->getName(), $hintPrefix)) {
                                if ($hintCount === 0 || $hintCount >= 99) {
                                    $platformHint[] = $pkg->getName();
                                    $hintsToFind[$hintPrefix]++;
                                }
                                elseif ($hintCount === 1) {
                                    unset($hintsToFind[$hintPrefix]);
                                    $platformHint[] = substr($pkg->getName(), 0, max(strlen($pkg->getName()) - 3, strlen($hintPrefix) + 1)) . '...';
                                }
                                continue 2;
                            }
                        }
                    }
                }
                else {
                    $installedRepos[] = $platformRepo;
                }
            }
            $installedRepo = new InstalledRepository($installedRepos);
            return array_merge(array_map(static function (PackageInterface $package) {
                return $package->getName();
            }, $installedRepo->getPackages()), $platformHint);
        };
    }
    
    /**
     * Suggest package names from installed.
     */
    private function suggestInstalledPackageTypes(bool $includeRootPackage = true) : \Closure {
        return function (CompletionInput $input) use ($includeRootPackage) : array {
            $composer = $this->requireComposer();
            $installedRepos = [];
            if ($includeRootPackage) {
                $installedRepos[] = new RootPackageRepository(clone $composer->getPackage());
            }
            $locker = $composer->getLocker();
            if ($locker->isLocked()) {
                $installedRepos[] = $locker->getLockedRepository(true);
            }
            else {
                $installedRepos[] = $composer->getRepositoryManager()
                    ->getLocalRepository();
            }
            $installedRepo = new InstalledRepository($installedRepos);
            return array_values(array_unique(array_map(static function (PackageInterface $package) {
                return $package->getType();
            }, $installedRepo->getPackages())));
        };
    }
    
    /**
     * Suggest package names available on all configured repositories.
     */
    private function suggestAvailablePackage(int $max = 99) : \Closure {
        return function (CompletionInput $input) use ($max) : array {
            if ($max < 1) {
                return [];
            }
            $composer = $this->requireComposer();
            $repos = new CompositeRepository($composer->getRepositoryManager()
                ->getRepositories());
            $results = [];
            $showVendors = false;
            if (!str_contains($input->getCompletionValue(), '/')) {
                $results = $repos->search('^' . preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_VENDOR);
                $showVendors = true;
            }
            // if we get a single vendor, we expand it into its contents already
            if (\count($results) <= 1) {
                $results = $repos->search('^' . preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_NAME);
                $showVendors = false;
            }
            $results = array_column($results, 'name');
            if ($showVendors) {
                $results = array_map(static function (string $name) : string {
                    return $name . '/';
                }, $results);
                // sort shorter results first to avoid auto-expanding the completion to a longer string than needed
                usort($results, static function (string $a, string $b) {
                    $lenA = \strlen($a);
                    $lenB = \strlen($b);
                    if ($lenA === $lenB) {
                        return $a <=> $b;
                    }
                    return $lenA - $lenB;
                });
                $pinned = [];
                // ensure if the input is an exact match that it is always in the result set
                $completionInput = $input->getCompletionValue() . '/';
                if (false !== ($exactIndex = array_search($completionInput, $results, true))) {
                    $pinned[] = $completionInput;
                    array_splice($results, $exactIndex, 1);
                }
                return array_merge($pinned, array_slice($results, 0, $max - \count($pinned)));
            }
            return array_slice($results, 0, $max);
        };
    }
    
    /**
     * Suggest package names available on all configured repositories or
     * platform packages from the ones available on the currently-running PHP
     */
    private function suggestAvailablePackageInclPlatform() : \Closure {
        return function (CompletionInput $input) : array {
            if (Preg::isMatch('{^(ext|lib|php)(-|$)|^com}', $input->getCompletionValue())) {
                $matches = $this->suggestPlatformPackage()($input);
            }
            else {
                $matches = [];
            }
            return array_merge($matches, $this->suggestAvailablePackage(99 - \count($matches))($input));
        };
    }
    
    /**
     * Suggest platform packages from the ones available on the currently-running PHP
     */
    private function suggestPlatformPackage() : \Closure {
        return function (CompletionInput $input) : array {
            $repos = new PlatformRepository([], $this->requireComposer()
                ->getConfig()
                ->get('platform'));
            $pattern = BasePackage::packageNameToRegexp($input->getCompletionValue() . '*');
            return array_filter(array_map(static function (PackageInterface $package) {
                return $package->getName();
            }, $repos->getPackages()), static function (string $name) use ($pattern) : bool {
                return Preg::isMatch($pattern, $name);
            });
        };
    }

}

Members

Title Sort descending Modifiers Object type Summary
CompletionTrait::requireComposer abstract public function
CompletionTrait::suggestAvailablePackage private function Suggest package names available on all configured repositories.
CompletionTrait::suggestAvailablePackageInclPlatform private function Suggest package names available on all configured repositories or
platform packages from the ones available on the currently-running PHP
CompletionTrait::suggestInstalledPackage private function Suggest package names from installed.
CompletionTrait::suggestInstalledPackageTypes private function Suggest package names from installed.
CompletionTrait::suggestPlatformPackage private function Suggest platform packages from the ones available on the currently-running PHP
CompletionTrait::suggestPreferInstall private function Suggestion values for &quot;prefer-install&quot; option
CompletionTrait::suggestRootRequirement private function Suggest package names from root requirements.

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal