function Problem::getMissingPackageReason
@internal
Return value
array{0: string, 1: string}
2 calls to Problem::getMissingPackageReason()
- Problem::getPrettyString in vendor/
composer/ composer/ src/ Composer/ DependencyResolver/ Problem.php - A human readable textual representation of the problem's reasons
- Rule::getPrettyString in vendor/
composer/ composer/ src/ Composer/ DependencyResolver/ Rule.php
File
-
vendor/
composer/ composer/ src/ Composer/ DependencyResolver/ Problem.php, line 246
Class
- Problem
- Represents a problem detected while solving dependencies
Namespace
Composer\DependencyResolverCode
public static function getMissingPackageReason(RepositorySet $repositorySet, Request $request, Pool $pool, bool $isVerbose, string $packageName, ?ConstraintInterface $constraint = null) : array {
if (PlatformRepository::isPlatformPackage($packageName)) {
// handle php/php-*/hhvm
if (0 === stripos($packageName, 'php') || $packageName === 'hhvm') {
$version = self::getPlatformPackageVersion($pool, $packageName, phpversion());
$msg = "- Root composer.json requires " . $packageName . self::constraintToText($constraint) . ' but ';
if (defined('HHVM_VERSION') || $packageName === 'hhvm' && count($pool->whatProvides($packageName)) > 0) {
return [
$msg,
'your HHVM version does not satisfy that requirement.',
];
}
if ($packageName === 'hhvm') {
return [
$msg,
'HHVM was not detected on this machine, make sure it is in your PATH.',
];
}
if (null === $version) {
return [
$msg,
'the ' . $packageName . ' package is disabled by your platform config. Enable it again with "composer config platform.' . $packageName . ' --unset".',
];
}
return [
$msg,
'your ' . $packageName . ' version (' . $version . ') does not satisfy that requirement.',
];
}
// handle php extensions
if (0 === stripos($packageName, 'ext-')) {
if (false !== strpos($packageName, ' ')) {
return [
'- ',
"PHP extension " . $packageName . ' should be required as ' . str_replace(' ', '-', $packageName) . '.',
];
}
$ext = substr($packageName, 4);
$msg = "- Root composer.json requires PHP extension " . $packageName . self::constraintToText($constraint) . ' but ';
$version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) === false ? '0' : phpversion($ext));
if (null === $version) {
$providersStr = self::getProvidersList($repositorySet, $packageName, 5);
if ($providersStr !== null) {
$providersStr = "\n\n Alternatively you can require one of these packages that provide the extension (or parts of it):\n{$providersStr}";
}
if (extension_loaded($ext)) {
return [
$msg,
'the ' . $packageName . ' package is disabled by your platform config. Enable it again with "composer config platform.' . $packageName . ' --unset".' . $providersStr,
];
}
return [
$msg,
'it is missing from your system. Install or enable PHP\'s ' . $ext . ' extension.' . $providersStr,
];
}
return [
$msg,
'it has the wrong version installed (' . $version . ').',
];
}
// handle linked libs
if (0 === stripos($packageName, 'lib-')) {
if (strtolower($packageName) === 'lib-icu') {
$error = extension_loaded('intl') ? 'it has the wrong version installed, try upgrading the intl extension.' : 'it is missing from your system, make sure the intl extension is loaded.';
return [
"- Root composer.json requires linked library " . $packageName . self::constraintToText($constraint) . ' but ',
$error,
];
}
$providersStr = self::getProvidersList($repositorySet, $packageName, 5);
if ($providersStr !== null) {
$providersStr = "\n\n Alternatively you can require one of these packages that provide the library (or parts of it):\n{$providersStr}";
}
return [
"- Root composer.json requires linked library " . $packageName . self::constraintToText($constraint) . ' but ',
'it has the wrong version installed or is missing from your system, make sure to load the extension providing it.' . $providersStr,
];
}
}
$lockedPackage = null;
foreach ($request->getLockedPackages() as $package) {
if ($package->getName() === $packageName) {
$lockedPackage = $package;
if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
return [
"- ",
$package->getPrettyName() . ' is fixed to ' . $package->getPrettyVersion() . ' (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you list it as an argument for the update command.',
];
}
break;
}
}
if ($constraint instanceof Constraint && $constraint->getOperator() === Constraint::STR_OP_EQ && Preg::isMatch('{^dev-.*#.*}', $constraint->getPrettyString())) {
$newConstraint = Preg::replace('{ +as +([^,\\s|]+)$}', '', $constraint->getPrettyString());
$packages = $repositorySet->findPackages($packageName, new MultiConstraint([
new Constraint(Constraint::STR_OP_EQ, $newConstraint),
new Constraint(Constraint::STR_OP_EQ, str_replace('#', '+', $newConstraint)),
], false));
if (\count($packages) > 0) {
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . '. The # character in branch names is replaced by a + character. Make sure to require it as "' . str_replace('#', '+', $constraint->getPrettyString()) . '".',
];
}
}
// first check if the actual requested package is found in normal conditions
// if so it must mean it is rejected by another constraint than the one given here
$packages = $repositorySet->findPackages($packageName, $constraint);
if (\count($packages) > 0) {
$rootReqs = $repositorySet->getRootRequires();
if (isset($rootReqs[$packageName])) {
$filtered = array_filter($packages, static function ($p) use ($rootReqs, $packageName) : bool {
return $rootReqs[$packageName]->matches(new Constraint('==', $p->getVersion()));
});
if (0 === count($filtered)) {
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts') . ' with your root composer.json require (' . $rootReqs[$packageName]->getPrettyString() . ').',
];
}
}
$tempReqs = $repositorySet->getTemporaryConstraints();
if (isset($tempReqs[$packageName])) {
$filtered = array_filter($packages, static function ($p) use ($tempReqs, $packageName) : bool {
return $tempReqs[$packageName]->matches(new Constraint('==', $p->getVersion()));
});
if (0 === count($filtered)) {
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these conflict' : 'it conflicts') . ' with your temporary update constraint (' . $packageName . ':' . $tempReqs[$packageName]->getPrettyString() . ').',
];
}
}
if ($lockedPackage !== null) {
$fixedConstraint = new Constraint('==', $lockedPackage->getVersion());
$filtered = array_filter($packages, static function ($p) use ($fixedConstraint) : bool {
return $fixedConstraint->matches(new Constraint('==', $p->getVersion()));
});
if (0 === count($filtered)) {
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but the package is fixed to ' . $lockedPackage->getPrettyVersion() . ' (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.',
];
}
}
$nonLockedPackages = array_filter($packages, static function ($p) : bool {
return !$p->getRepository() instanceof LockArrayRepository;
});
if (0 === \count($nonLockedPackages)) {
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.',
];
}
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but these were not loaded, likely because ' . (self::hasMultipleNames($packages) ? 'they conflict' : 'it conflicts') . ' with another require.',
];
}
// check if the package is found when bypassing stability checks
$packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES);
if (\count($packages) > 0) {
// we must first verify if a valid package would be found in a lower priority repository
$allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
if (\count($allReposPackages) > 0) {
return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'minimum-stability', $constraint);
}
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these do' : 'it does') . ' not match your minimum-stability.',
];
}
// check if the package is found when bypassing the constraint and stability checks
$packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES);
if (\count($packages) > 0) {
// we must first verify if a valid package would be found in a lower priority repository
$allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES);
if (\count($allReposPackages) > 0) {
return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'constraint', $constraint);
}
$suffix = '';
if ($constraint instanceof Constraint && $constraint->getVersion() === 'dev-master') {
foreach ($packages as $candidate) {
if (in_array($candidate->getVersion(), [
'dev-default',
'dev-main',
], true)) {
$suffix = ' Perhaps dev-master was renamed to ' . $candidate->getPrettyVersion() . '?';
break;
}
}
}
// check if the root package is a name match and hint the dependencies on root troubleshooting article
$allReposPackages = $packages;
$topPackage = reset($allReposPackages);
if ($topPackage instanceof RootPackageInterface) {
$suffix = ' See https://getcomposer.org/dep-on-root for details and assistance.';
}
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ', ',
'found ' . self::getPackageList($packages, $isVerbose, $pool, $constraint) . ' but ' . (self::hasMultipleNames($packages) ? 'these do' : 'it does') . ' not match the constraint.' . $suffix,
];
}
if (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $packageName)) {
$illegalChars = Preg::replace('{[A-Za-z0-9_./-]+}', '', $packageName);
return [
"- Root composer.json requires {$packageName}, it ",
'could not be found, it looks like its name is invalid, "' . $illegalChars . '" is not allowed in package names.',
];
}
$providersStr = self::getProvidersList($repositorySet, $packageName, 15);
if ($providersStr !== null) {
return [
"- Root composer.json requires {$packageName}" . self::constraintToText($constraint) . ", it ",
"could not be found in any version, but the following packages provide it:\n" . $providersStr . " Consider requiring one of these to satisfy the {$packageName} requirement.",
];
}
return [
"- Root composer.json requires {$packageName}, it ",
"could not be found in any version, there may be a typo in the package name.",
];
}