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

Breadcrumb

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

function VersionSelector::findBestCandidate

Given a package name and optional version, returns the latest PackageInterface that matches.

Parameters

string $targetPackageVersion:

PlatformRequirementFilterInterface|bool|string[] $platformRequirementFilter:

IOInterface|null $io If passed, warnings will be output there in case versions cannot be selected due to platform requirements:

callable(PackageInterface):bool|bool $showWarnings:

Return value

PackageInterface|false

File

vendor/composer/composer/src/Composer/Package/Version/VersionSelector.php, line 72

Class

VersionSelector
Selects the best possible version for a package

Namespace

Composer\Package\Version

Code

public function findBestCandidate(string $packageName, ?string $targetPackageVersion = null, string $preferredStability = 'stable', $platformRequirementFilter = null, int $repoSetFlags = 0, ?IOInterface $io = null, $showWarnings = true) {
    if (!isset(BasePackage::STABILITIES[$preferredStability])) {
        // If you get this, maybe you are still relying on the Composer 1.x signature where the 3rd arg was the php version
        throw new \UnexpectedValueException('Expected a valid stability name as 3rd argument, got ' . $preferredStability);
    }
    if (null === $platformRequirementFilter) {
        $platformRequirementFilter = PlatformRequirementFilterFactory::ignoreNothing();
    }
    elseif (!$platformRequirementFilter instanceof PlatformRequirementFilterInterface) {
        trigger_error('VersionSelector::findBestCandidate with ignored platform reqs as bool|array is deprecated since Composer 2.2, use an instance of PlatformRequirementFilterInterface instead.', E_USER_DEPRECATED);
        $platformRequirementFilter = PlatformRequirementFilterFactory::fromBoolOrList($platformRequirementFilter);
    }
    $constraint = $targetPackageVersion ? $this->getParser()
        ->parseConstraints($targetPackageVersion) : null;
    $candidates = $this->repositorySet
        ->findPackages(strtolower($packageName), $constraint, $repoSetFlags);
    $minPriority = BasePackage::STABILITIES[$preferredStability];
    usort($candidates, static function (PackageInterface $a, PackageInterface $b) use ($minPriority) {
        $aPriority = $a->getStabilityPriority();
        $bPriority = $b->getStabilityPriority();
        // A is less stable than our preferred stability,
        // and B is more stable than A, select B
        if ($minPriority < $aPriority && $bPriority < $aPriority) {
            return 1;
        }
        // A is less stable than our preferred stability,
        // and B is less stable than A, select A
        if ($minPriority < $aPriority && $aPriority < $bPriority) {
            return -1;
        }
        // A is more stable than our preferred stability,
        // and B is less stable than preferred stability, select A
        if ($minPriority >= $aPriority && $minPriority < $bPriority) {
            return -1;
        }
        // select highest version of the two
        return version_compare($b->getVersion(), $a->getVersion());
    });
    if (count($this->platformConstraints) > 0 && !$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter) {
        
        /** @var array<string, true> $alreadyWarnedNames */
        $alreadyWarnedNames = [];
        
        /** @var array<string, true> $alreadySeenNames */
        $alreadySeenNames = [];
        foreach ($candidates as $pkg) {
            $reqs = $pkg->getRequires();
            $skip = false;
            foreach ($reqs as $name => $link) {
                if (!PlatformRepository::isPlatformPackage($name) || $platformRequirementFilter->isIgnored($name)) {
                    continue;
                }
                if (isset($this->platformConstraints[$name])) {
                    foreach ($this->platformConstraints[$name] as $providedConstraint) {
                        if ($link->getConstraint()
                            ->matches($providedConstraint)) {
                            // constraint satisfied, go to next require
                            continue 2;
                        }
                        if ($platformRequirementFilter instanceof IgnoreListPlatformRequirementFilter && $platformRequirementFilter->isUpperBoundIgnored($name)) {
                            $filteredConstraint = $platformRequirementFilter->filterConstraint($name, $link->getConstraint());
                            if ($filteredConstraint->matches($providedConstraint)) {
                                // constraint satisfied with the upper bound ignored, go to next require
                                continue 2;
                            }
                        }
                    }
                    // constraint not satisfied
                    $reason = 'is not satisfied by your platform';
                }
                else {
                    // Package requires a platform package that is unknown on current platform.
                    // It means that current platform cannot validate this constraint and so package is not installable.
                    $reason = 'is missing from your platform';
                }
                $isLatestVersion = !isset($alreadySeenNames[$pkg->getName()]);
                $alreadySeenNames[$pkg->getName()] = true;
                if ($io !== null && ($showWarnings === true || is_callable($showWarnings) && $showWarnings($pkg))) {
                    $isFirstWarning = !isset($alreadyWarnedNames[$pkg->getName() . '/' . $link->getTarget()]);
                    $alreadyWarnedNames[$pkg->getName() . '/' . $link->getTarget()] = true;
                    $latest = $isLatestVersion ? "'s latest version" : '';
                    $io->writeError('<warning>Cannot use ' . $pkg->getPrettyName() . $latest . ' ' . $pkg->getPrettyVersion() . ' as it ' . $link->getDescription() . ' ' . $link->getTarget() . ' ' . $link->getPrettyConstraint() . ' which ' . $reason . '.</>', true, $isFirstWarning ? IOInterface::NORMAL : IOInterface::VERBOSE);
                }
                // skip candidate
                $skip = true;
            }
            if ($skip) {
                continue;
            }
            $package = $pkg;
            break;
        }
    }
    else {
        $package = count($candidates) > 0 ? $candidates[0] : null;
    }
    if (!isset($package)) {
        return false;
    }
    // if we end up with 9999999-dev as selected package, make sure we use the original version instead of the alias
    if ($package instanceof AliasPackage && $package->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
        $package = $package->getAliasOf();
    }
    return $package;
}

API Navigation

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