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\VersionCode
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;
}