class RootPackageLoader
ArrayLoader built for the sole purpose of loading the root package
Sets additional defaults and loads repositories
@author Jordi Boggiano <j.boggiano@seld.be>
Hierarchy
- class \Composer\Package\Loader\ArrayLoader implements \Composer\Package\Loader\LoaderInterface
- class \Composer\Package\Loader\RootPackageLoader extends \Composer\Package\Loader\ArrayLoader
Expanded class hierarchy of RootPackageLoader
2 files declare their use of RootPackageLoader
- RequireCommand.php in vendor/
composer/ composer/ src/ Composer/ Command/ RequireCommand.php - UpdateCommand.php in vendor/
composer/ composer/ src/ Composer/ Command/ UpdateCommand.php
File
-
vendor/
composer/ composer/ src/ Composer/ Package/ Loader/ RootPackageLoader.php, line 35
Namespace
Composer\Package\LoaderView source
class RootPackageLoader extends ArrayLoader {
/**
* @var RepositoryManager
*/
private $manager;
/**
* @var Config
*/
private $config;
/**
* @var VersionGuesser
*/
private $versionGuesser;
/**
* @var IOInterface|null
*/
private $io;
public function __construct(RepositoryManager $manager, Config $config, ?VersionParser $parser = null, ?VersionGuesser $versionGuesser = null, ?IOInterface $io = null) {
parent::__construct($parser);
$this->manager = $manager;
$this->config = $config;
$this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor($io), $this->versionParser, $io);
$this->io = $io;
}
/**
* @inheritDoc
*
* @return RootPackage|RootAliasPackage
*
* @phpstan-param class-string<RootPackage> $class
*/
public function load(array $config, string $class = 'Composer\\Package\\RootPackage', ?string $cwd = null) : BasePackage {
if ($class !== 'Composer\\Package\\RootPackage') {
trigger_error('The $class arg is deprecated, please reach out to Composer maintainers ASAP if you still need this.', E_USER_DEPRECATED);
}
if (!isset($config['name'])) {
$config['name'] = '__root__';
}
elseif ($err = ValidatingArrayLoader::hasPackageNamingError($config['name'])) {
throw new \RuntimeException('Your package name ' . $err);
}
$autoVersioned = false;
if (!isset($config['version'])) {
$commit = null;
// override with env var if available
if (Platform::getEnv('COMPOSER_ROOT_VERSION')) {
$config['version'] = $this->versionGuesser
->getRootVersionFromEnv();
}
else {
$versionData = $this->versionGuesser
->guessVersion($config, $cwd ?? Platform::getCwd(true));
if ($versionData) {
$config['version'] = $versionData['pretty_version'];
$config['version_normalized'] = $versionData['version'];
$commit = $versionData['commit'];
}
}
if (!isset($config['version'])) {
if ($this->io !== null && $config['name'] !== '__root__' && 'project' !== ($config['type'] ?? '')) {
$this->io
->warning(sprintf("Composer could not detect the root package (%s) version, defaulting to '1.0.0'. See https://getcomposer.org/root-version", $config['name']));
}
$config['version'] = '1.0.0';
$autoVersioned = true;
}
if ($commit) {
$config['source'] = [
'type' => '',
'url' => '',
'reference' => $commit,
];
$config['dist'] = [
'type' => '',
'url' => '',
'reference' => $commit,
];
}
}
/** @var RootPackage|RootAliasPackage $package */
$package = parent::load($config, $class);
if ($package instanceof RootAliasPackage) {
$realPackage = $package->getAliasOf();
}
else {
$realPackage = $package;
}
if (!$realPackage instanceof RootPackage) {
throw new \LogicException('Expecting a Composer\\Package\\RootPackage at this point');
}
if ($autoVersioned) {
$realPackage->replaceVersion($realPackage->getVersion(), RootPackage::DEFAULT_PRETTY_VERSION);
}
if (isset($config['minimum-stability'])) {
$realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
}
$aliases = [];
$stabilityFlags = [];
$references = [];
foreach ([
'require',
'require-dev',
] as $linkType) {
if (isset($config[$linkType])) {
$linkInfo = BasePackage::$supportedLinkTypes[$linkType];
$method = 'get' . ucfirst($linkInfo['method']);
$links = [];
foreach ($realPackage->{$method}() as $link) {
$links[$link->getTarget()] = $link->getConstraint()
->getPrettyString();
}
$aliases = $this->extractAliases($links, $aliases);
$stabilityFlags = self::extractStabilityFlags($links, $realPackage->getMinimumStability(), $stabilityFlags);
$references = self::extractReferences($links, $references);
if (isset($links[$config['name']])) {
throw new \RuntimeException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL . 'Did you accidentally name your root package after an external package?', $config['name']));
}
}
}
foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
if (isset($config[$linkType])) {
foreach ($config[$linkType] as $linkName => $constraint) {
if ($err = ValidatingArrayLoader::hasPackageNamingError($linkName, true)) {
throw new \RuntimeException($linkType . '.' . $err);
}
}
}
}
$realPackage->setAliases($aliases);
$realPackage->setStabilityFlags($stabilityFlags);
$realPackage->setReferences($references);
if (isset($config['prefer-stable'])) {
$realPackage->setPreferStable((bool) $config['prefer-stable']);
}
if (isset($config['config'])) {
$realPackage->setConfig($config['config']);
}
$repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
foreach ($repos as $repo) {
$this->manager
->addRepository($repo);
}
$realPackage->setRepositories($this->config
->getRepositories());
return $package;
}
/**
* @param array<string, string> $requires
* @param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
*
* @return list<array{package: string, version: string, alias: string, alias_normalized: string}>
*/
private function extractAliases(array $requires, array $aliases) : array {
foreach ($requires as $reqName => $reqVersion) {
if (Preg::isMatchStrictGroups('{(?:^|\\| *|, *)([^,\\s#|]+)(?:#[^ ]+)? +as +([^,\\s|]+)(?:$| *\\|| *,)}', $reqVersion, $match)) {
$aliases[] = [
'package' => strtolower($reqName),
'version' => $this->versionParser
->normalize($match[1], $reqVersion),
'alias' => $match[2],
'alias_normalized' => $this->versionParser
->normalize($match[2], $reqVersion),
];
}
elseif (strpos($reqVersion, ' as ') !== false) {
throw new \UnexpectedValueException('Invalid alias definition in "' . $reqName . '": "' . $reqVersion . '". Aliases should be in the form "exact-version as other-exact-version".');
}
}
return $aliases;
}
/**
* @internal
*
* @param array<string, string> $requires
* @param array<string, int> $stabilityFlags
* @param key-of<BasePackage::STABILITIES> $minimumStability
*
* @return array<string, int>
*
* @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
* @phpstan-return array<string, BasePackage::STABILITY_*>
*/
public static function extractStabilityFlags(array $requires, string $minimumStability, array $stabilityFlags) : array {
$stabilities = BasePackage::STABILITIES;
$minimumStability = $stabilities[$minimumStability];
foreach ($requires as $reqName => $reqVersion) {
$constraints = [];
// extract all sub-constraints in case it is an OR/AND multi-constraint
$orSplit = Preg::split('{\\s*\\|\\|?\\s*}', trim($reqVersion));
foreach ($orSplit as $orConstraint) {
$andSplit = Preg::split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
foreach ($andSplit as $andConstraint) {
$constraints[] = $andConstraint;
}
}
// parse explicit stability flags to the most unstable
$matched = false;
foreach ($constraints as $constraint) {
if (Preg::isMatchStrictGroups('{^[^@]*?@(' . implode('|', array_keys($stabilities)) . ')$}i', $constraint, $match)) {
$name = strtolower($reqName);
$stability = $stabilities[VersionParser::normalizeStability($match[1])];
if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
continue;
}
$stabilityFlags[$name] = $stability;
$matched = true;
}
}
if ($matched) {
continue;
}
foreach ($constraints as $constraint) {
// infer flags for requirements that have an explicit -dev or -beta version specified but only
// for those that are more unstable than the minimumStability or existing flags
$reqVersion = Preg::replace('{^([^,\\s@]+) as .+$}', '$1', $constraint);
if (Preg::isMatch('{^[^,\\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
$name = strtolower($reqName);
$stability = $stabilities[$stabilityName];
if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability || $minimumStability > $stability) {
continue;
}
$stabilityFlags[$name] = $stability;
}
}
}
return $stabilityFlags;
}
/**
* @internal
*
* @param array<string, string> $requires
* @param array<string, string> $references
*
* @return array<string, string>
*/
public static function extractReferences(array $requires, array $references) : array {
foreach ($requires as $reqName => $reqVersion) {
$reqVersion = Preg::replace('{^([^,\\s@]+) as .+$}', '$1', $reqVersion);
if (Preg::isMatchStrictGroups('{^[^,\\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) {
$name = strtolower($reqName);
$references[$name] = $match[1];
}
}
return $references;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
ArrayLoader::$loadOptions | protected | property | @var bool | |
ArrayLoader::$versionParser | protected | property | @var VersionParser | |
ArrayLoader::configureCachedLinks | private | function | ||
ArrayLoader::configureObject | private | function | ||
ArrayLoader::createLink | private | function | ||
ArrayLoader::createObject | private | function | @template PackageClass of CompletePackage | |
ArrayLoader::getBranchAlias | public | function | Retrieves a branch alias (dev-master => 1.0.x-dev for example) if it exists | |
ArrayLoader::loadPackages | public | function | ||
ArrayLoader::parseLinks | public | function | @phpstan-param Link::TYPE_* $description | |
RootPackageLoader::$config | private | property | ||
RootPackageLoader::$io | private | property | ||
RootPackageLoader::$manager | private | property | ||
RootPackageLoader::$versionGuesser | private | property | ||
RootPackageLoader::extractAliases | private | function | ||
RootPackageLoader::extractReferences | public static | function | @internal | |
RootPackageLoader::extractStabilityFlags | public static | function | @internal | |
RootPackageLoader::load | public | function | @inheritDoc | Overrides ArrayLoader::load |
RootPackageLoader::__construct | public | function | Overrides ArrayLoader::__construct |