class ExtraPackage in Zircon Profile 8
Same name and namespace in other branches
- 8.0 vendor/wikimedia/composer-merge-plugin/src/Merge/ExtraPackage.php \Wikimedia\Composer\Merge\ExtraPackage
Processing for a composer.json file that will be merged into a RootPackageInterface
@author Bryan Davis <bd808@bd808.com>
Hierarchy
- class \Wikimedia\Composer\Merge\ExtraPackage
Expanded class hierarchy of ExtraPackage
1 file declares its use of ExtraPackage
- MergePlugin.php in vendor/
wikimedia/ composer-merge-plugin/ src/ MergePlugin.php
File
- vendor/
wikimedia/ composer-merge-plugin/ src/ Merge/ ExtraPackage.php, line 33
Namespace
Wikimedia\Composer\MergeView source
class ExtraPackage {
/**
* @var Composer $composer
*/
protected $composer;
/**
* @var Logger $logger
*/
protected $logger;
/**
* @var string $path
*/
protected $path;
/**
* @var array $json
*/
protected $json;
/**
* @var CompletePackage $package
*/
protected $package;
/**
* @param string $path Path to composer.json file
* @param Composer $composer
* @param Logger $logger
*/
public function __construct($path, Composer $composer, Logger $logger) {
$this->path = $path;
$this->composer = $composer;
$this->logger = $logger;
$this->json = $this
->readPackageJson($path);
$this->package = $this
->loadPackage($this->json);
}
/**
* Get list of additional packages to include if precessing recursively.
*
* @return array
*/
public function getIncludes() {
return isset($this->json['extra']['merge-plugin']['include']) ? $this->json['extra']['merge-plugin']['include'] : array();
}
/**
* Get list of additional packages to require if precessing recursively.
*
* @return array
*/
public function getRequires() {
return isset($this->json['extra']['merge-plugin']['require']) ? $this->json['extra']['merge-plugin']['require'] : array();
}
/**
* Read the contents of a composer.json style file into an array.
*
* The package contents are fixed up to be usable to create a Package
* object by providing dummy "name" and "version" values if they have not
* been provided in the file. This is consistent with the default root
* package loading behavior of Composer.
*
* @param string $path
* @return array
*/
protected function readPackageJson($path) {
$file = new JsonFile($path);
$json = $file
->read();
if (!isset($json['name'])) {
$json['name'] = 'merge-plugin/' . strtr($path, DIRECTORY_SEPARATOR, '-');
}
if (!isset($json['version'])) {
$json['version'] = '1.0.0';
}
return $json;
}
/**
* @return CompletePackage
*/
protected function loadPackage($json) {
$loader = new ArrayLoader();
$package = $loader
->load($json);
// @codeCoverageIgnoreStart
if (!$package instanceof CompletePackage) {
throw new UnexpectedValueException('Expected instance of CompletePackage, got ' . get_class($package));
}
// @codeCoverageIgnoreEnd
return $package;
}
/**
* Merge this package into a RootPackageInterface
*
* @param RootPackageInterface $root
* @param PluginState $state
*/
public function mergeInto(RootPackageInterface $root, PluginState $state) {
$this
->addRepositories($root);
$this
->mergeRequires('require', $root, $state);
if ($state
->isDevMode()) {
$this
->mergeRequires('require-dev', $root, $state);
}
$this
->mergePackageLinks('conflict', $root);
$this
->mergePackageLinks('replace', $root);
$this
->mergePackageLinks('provide', $root);
$this
->mergeSuggests($root);
$this
->mergeAutoload('autoload', $root);
if ($state
->isDevMode()) {
$this
->mergeAutoload('devAutoload', $root);
}
$this
->mergeExtra($root, $state);
}
/**
* Add a collection of repositories described by the given configuration
* to the given package and the global repository manager.
*
* @param RootPackageInterface $root
*/
protected function addRepositories(RootPackageInterface $root) {
if (!isset($this->json['repositories'])) {
return;
}
$repoManager = $this->composer
->getRepositoryManager();
$newRepos = array();
foreach ($this->json['repositories'] as $repoJson) {
if (!isset($repoJson['type'])) {
continue;
}
$this->logger
->info("Adding {$repoJson['type']} repository");
$repo = $repoManager
->createRepository($repoJson['type'], $repoJson);
$repoManager
->addRepository($repo);
$newRepos[] = $repo;
}
$unwrapped = self::unwrapIfNeeded($root, 'setRepositories');
$unwrapped
->setRepositories(array_merge($newRepos, $root
->getRepositories()));
}
/**
* Merge require or require-dev into a RootPackageInterface
*
* @param string $type 'require' or 'require-dev'
* @param RootPackageInterface $root
* @param PluginState $state
*/
protected function mergeRequires($type, RootPackageInterface $root, PluginState $state) {
$linkType = BasePackage::$supportedLinkTypes[$type];
$getter = 'get' . ucfirst($linkType['method']);
$setter = 'set' . ucfirst($linkType['method']);
$requires = $this->package
->{$getter}();
if (empty($requires)) {
return;
}
$this
->mergeStabilityFlags($root, $requires);
$requires = $this
->replaceSelfVersionDependencies($type, $requires, $root);
$root
->{$setter}($this
->mergeOrDefer($type, $root
->{$getter}(), $requires, $state));
}
/**
* Merge two collections of package links and collect duplicates for
* subsequent processing.
*
* @param string $type 'require' or 'require-dev'
* @param array $origin Primary collection
* @param array $merge Additional collection
* @param PluginState $state
* @return array Merged collection
*/
protected function mergeOrDefer($type, array $origin, array $merge, $state) {
$dups = array();
foreach ($merge as $name => $link) {
if (!isset($origin[$name]) || $state
->replaceDuplicateLinks()) {
$this->logger
->info("Merging <comment>{$name}</comment>");
$origin[$name] = $link;
}
else {
// Defer to solver.
$this->logger
->info("Deferring duplicate <comment>{$name}</comment>");
$dups[] = $link;
}
}
$state
->addDuplicateLinks($type, $dups);
return $origin;
}
/**
* Merge autoload or autoload-dev into a RootPackageInterface
*
* @param string $type 'autoload' or 'devAutoload'
* @param RootPackageInterface $root
*/
protected function mergeAutoload($type, RootPackageInterface $root) {
$getter = 'get' . ucfirst($type);
$setter = 'set' . ucfirst($type);
$autoload = $this->package
->{$getter}();
if (empty($autoload)) {
return;
}
$unwrapped = self::unwrapIfNeeded($root, $setter);
$unwrapped
->{$setter}(array_merge_recursive($root
->{$getter}(), $this
->fixRelativePaths($autoload)));
}
/**
* Fix a collection of paths that are relative to this package to be
* relative to the base package.
*
* @param array $paths
* @return array
*/
protected function fixRelativePaths(array $paths) {
$base = dirname($this->path);
$base = $base === '.' ? '' : "{$base}/";
array_walk_recursive($paths, function (&$path) use ($base) {
$path = "{$base}{$path}";
});
return $paths;
}
/**
* Extract and merge stability flags from the given collection of
* requires and merge them into a RootPackageInterface
*
* @param RootPackageInterface $root
* @param array $requires
*/
protected function mergeStabilityFlags(RootPackageInterface $root, array $requires) {
$flags = $root
->getStabilityFlags();
$sf = new StabilityFlags($flags, $root
->getMinimumStability());
$unwrapped = self::unwrapIfNeeded($root, 'setStabilityFlags');
$unwrapped
->setStabilityFlags(array_merge($flags, $sf
->extractAll($requires)));
}
/**
* Merge package links of the given type into a RootPackageInterface
*
* @param string $type 'conflict', 'replace' or 'provide'
* @param RootPackageInterface $root
*/
protected function mergePackageLinks($type, RootPackageInterface $root) {
$linkType = BasePackage::$supportedLinkTypes[$type];
$getter = 'get' . ucfirst($linkType['method']);
$setter = 'set' . ucfirst($linkType['method']);
$links = $this->package
->{$getter}();
if (!empty($links)) {
$unwrapped = self::unwrapIfNeeded($root, $setter);
if ($root !== $unwrapped) {
$this->logger
->warning('This Composer version does not support ' . "'{$type}' merging for aliased packages.");
}
$unwrapped
->{$setter}(array_merge($root
->{$getter}(), $this
->replaceSelfVersionDependencies($type, $links, $root)));
}
}
/**
* Merge suggested packages into a RootPackageInterface
*
* @param RootPackageInterface $root
*/
protected function mergeSuggests(RootPackageInterface $root) {
$suggests = $this->package
->getSuggests();
if (!empty($suggests)) {
$unwrapped = self::unwrapIfNeeded($root, 'setSuggests');
$unwrapped
->setSuggests(array_merge($root
->getSuggests(), $suggests));
}
}
/**
* Merge extra config into a RootPackageInterface
*
* @param RootPackageInterface $root
* @param PluginState $state
*/
public function mergeExtra(RootPackageInterface $root, PluginState $state) {
$extra = $this->package
->getExtra();
unset($extra['merge-plugin']);
if (!$state
->shouldMergeExtra() || empty($extra)) {
return;
}
$rootExtra = $root
->getExtra();
$unwrapped = self::unwrapIfNeeded($root, 'setExtra');
if ($state
->replaceDuplicateLinks()) {
$unwrapped
->setExtra(array_merge($rootExtra, $extra));
}
else {
foreach (array_intersect(array_keys($extra), array_keys($rootExtra)) as $key) {
$this->logger
->info("Ignoring duplicate <comment>{$key}</comment> in " . "<comment>{$this->path}</comment> extra config.");
}
$unwrapped
->setExtra(array_merge($extra, $rootExtra));
}
}
/**
* Update Links with a 'self.version' constraint with the root package's
* version.
*
* @param string $type Link type
* @param array $links
* @param RootPackageInterface $root
* @return array
*/
protected function replaceSelfVersionDependencies($type, array $links, RootPackageInterface $root) {
$linkType = BasePackage::$supportedLinkTypes[$type];
$version = $root
->getVersion();
$prettyVersion = $root
->getPrettyVersion();
$vp = new VersionParser();
return array_map(function ($link) use ($linkType, $version, $prettyVersion, $vp) {
if ('self.version' === $link
->getPrettyConstraint()) {
return new Link($link
->getSource(), $link
->getTarget(), $vp
->parseConstraints($version), $linkType['description'], $prettyVersion);
}
return $link;
}, $links);
}
/**
* Get a full featured Package from a RootPackageInterface.
*
* In Composer versions before 599ad77 the RootPackageInterface only
* defines a sub-set of operations needed by composer-merge-plugin and
* RootAliasPackage only implemented those methods defined by the
* interface. Most of the unimplemented methods in RootAliasPackage can be
* worked around because the getter methods that are implemented proxy to
* the aliased package which we can modify by unwrapping. The exception
* being modifying the 'conflicts', 'provides' and 'replaces' collections.
* We have no way to actually modify those collections unfortunately in
* older versions of Composer.
*
* @param RootPackageInterface $root
* @param string $method Method needed
* @return RootPackageInterface|RootPackage
*/
public static function unwrapIfNeeded(RootPackageInterface $root, $method = 'setExtra') {
if ($root instanceof RootAliasPackage && !method_exists($root, $method)) {
// Unwrap and return the aliased RootPackage.
$root = $root
->getAliasOf();
}
return $root;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ExtraPackage:: |
protected | property | ||
ExtraPackage:: |
protected | property | ||
ExtraPackage:: |
protected | property | ||
ExtraPackage:: |
protected | property | ||
ExtraPackage:: |
protected | property | ||
ExtraPackage:: |
protected | function | Add a collection of repositories described by the given configuration to the given package and the global repository manager. | |
ExtraPackage:: |
protected | function | Fix a collection of paths that are relative to this package to be relative to the base package. | |
ExtraPackage:: |
public | function | Get list of additional packages to include if precessing recursively. | |
ExtraPackage:: |
public | function | Get list of additional packages to require if precessing recursively. | |
ExtraPackage:: |
protected | function | ||
ExtraPackage:: |
protected | function | Merge autoload or autoload-dev into a RootPackageInterface | |
ExtraPackage:: |
public | function | Merge extra config into a RootPackageInterface | |
ExtraPackage:: |
public | function | Merge this package into a RootPackageInterface | |
ExtraPackage:: |
protected | function | Merge two collections of package links and collect duplicates for subsequent processing. | |
ExtraPackage:: |
protected | function | Merge package links of the given type into a RootPackageInterface | |
ExtraPackage:: |
protected | function | Merge require or require-dev into a RootPackageInterface | |
ExtraPackage:: |
protected | function | Extract and merge stability flags from the given collection of requires and merge them into a RootPackageInterface | |
ExtraPackage:: |
protected | function | Merge suggested packages into a RootPackageInterface | |
ExtraPackage:: |
protected | function | Read the contents of a composer.json style file into an array. | |
ExtraPackage:: |
protected | function | Update Links with a 'self.version' constraint with the root package's version. | |
ExtraPackage:: |
public static | function | Get a full featured Package from a RootPackageInterface. | |
ExtraPackage:: |
public | function |