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

Breadcrumb

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

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\DependencyResolver

Code

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.",
    ];
}
RSS feed
Powered by Drupal