|
@@ -16,9 +16,11 @@ use Composer\DependencyResolver\Pool;
|
|
|
use Composer\DependencyResolver\DefaultPolicy;
|
|
|
use Composer\Factory;
|
|
|
use Composer\Package\CompletePackageInterface;
|
|
|
-use Composer\Package\Version\VersionParser;
|
|
|
+use Composer\Semver\VersionParser;
|
|
|
use Composer\Plugin\CommandEvent;
|
|
|
use Composer\Plugin\PluginEvents;
|
|
|
+use Composer\Package\PackageInterface;
|
|
|
+use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
@@ -28,14 +30,17 @@ use Composer\Repository\CompositeRepository;
|
|
|
use Composer\Repository\ComposerRepository;
|
|
|
use Composer\Repository\PlatformRepository;
|
|
|
use Composer\Repository\RepositoryInterface;
|
|
|
+use Composer\Spdx\SpdxLicenses;
|
|
|
|
|
|
/**
|
|
|
* @author Robert Schönthal <seroscho@googlemail.com>
|
|
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
|
|
+ * @author Jérémy Romey <jeremyFreeAgent>
|
|
|
*/
|
|
|
class ShowCommand extends Command
|
|
|
{
|
|
|
protected $versionParser;
|
|
|
+ protected $colors;
|
|
|
|
|
|
protected function configure()
|
|
|
{
|
|
@@ -54,6 +59,7 @@ class ShowCommand extends Command
|
|
|
new InputOption('disable-tls', null, InputOption::VALUE_NONE, 'Disable SSL/TLS protection for HTTPS requests'),
|
|
|
new InputOption('cafile', null, InputOption::VALUE_REQUIRED, 'The path to a valid CA certificate file for SSL/TLS certificate verification'),
|
|
|
new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
|
|
|
+ new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
|
|
|
))
|
|
|
->setHelp(<<<EOT
|
|
|
The show command displays detailed information about a package, or
|
|
@@ -67,11 +73,25 @@ EOT
|
|
|
protected function execute(InputInterface $input, OutputInterface $output)
|
|
|
{
|
|
|
$this->versionParser = new VersionParser;
|
|
|
+ if ($input->getOption('tree')) {
|
|
|
+ $this->initStyles($output);
|
|
|
+ }
|
|
|
+
|
|
|
+ $composer = $this->getComposer(false);
|
|
|
+ $io = $this->getIO();
|
|
|
+
|
|
|
+ if ($input->getOption('tree') && !$input->getOption('installed')) {
|
|
|
+ $io->writeError('The --tree (-t) option is only usable in combination with --installed (-i) or by passing a single package name to show, assuming -i');
|
|
|
+ $input->setOption('installed', true);
|
|
|
+ }
|
|
|
|
|
|
// init repos
|
|
|
- $platformRepo = new PlatformRepository;
|
|
|
+ $platformOverrides = array();
|
|
|
+ if ($composer) {
|
|
|
+ $platformOverrides = $composer->getConfig()->get('platform') ?: array();
|
|
|
+ }
|
|
|
+ $platformRepo = new PlatformRepository(array(), $platformOverrides);
|
|
|
|
|
|
- $composer = $this->getComposer(false);
|
|
|
if ($input->getOption('self')) {
|
|
|
$package = $this->getComposer()->getPackage();
|
|
|
$repos = $installedRepo = new ArrayRepository(array($package));
|
|
@@ -84,17 +104,17 @@ EOT
|
|
|
if ($composer) {
|
|
|
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
|
|
} else {
|
|
|
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
|
|
|
+ $defaultRepos = Factory::createDefaultRepositories($io);
|
|
|
$repos = new CompositeRepository($defaultRepos);
|
|
|
- $output->writeln('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
|
|
+ $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
|
|
}
|
|
|
} elseif ($composer) {
|
|
|
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
|
|
$installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
|
|
|
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
|
|
|
} else {
|
|
|
- $defaultRepos = Factory::createDefaultRepositories($this->getIO());
|
|
|
- $output->writeln('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
|
|
+ $defaultRepos = Factory::createDefaultRepositories($io);
|
|
|
+ $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
|
|
|
$installedRepo = $platformRepo;
|
|
|
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
|
|
}
|
|
@@ -117,24 +137,42 @@ EOT
|
|
|
$versions = array($package->getPrettyVersion() => $package->getVersion());
|
|
|
}
|
|
|
|
|
|
- $this->printMeta($input, $output, $package, $versions, $installedRepo, $repos);
|
|
|
- $this->printLinks($input, $output, $package, 'requires');
|
|
|
- $this->printLinks($input, $output, $package, 'devRequires', 'requires (dev)');
|
|
|
- if ($package->getSuggests()) {
|
|
|
- $output->writeln("\n<info>suggests</info>");
|
|
|
- foreach ($package->getSuggests() as $suggested => $reason) {
|
|
|
- $output->writeln($suggested . ' <comment>' . $reason . '</comment>');
|
|
|
+ if ($input->getOption('tree')) {
|
|
|
+ $this->displayPackageTree($package, $installedRepo, $repos, $output);
|
|
|
+ } else {
|
|
|
+ $this->printMeta($package, $versions, $installedRepo, $repos);
|
|
|
+ $this->printLinks($package, 'requires');
|
|
|
+ $this->printLinks($package, 'devRequires', 'requires (dev)');
|
|
|
+ if ($package->getSuggests()) {
|
|
|
+ $io->write("\n<info>suggests</info>");
|
|
|
+ foreach ($package->getSuggests() as $suggested => $reason) {
|
|
|
+ $io->write($suggested . ' <comment>' . $reason . '</comment>');
|
|
|
+ }
|
|
|
}
|
|
|
+ $this->printLinks($package, 'provides');
|
|
|
+ $this->printLinks($package, 'conflicts');
|
|
|
+ $this->printLinks($package, 'replaces');
|
|
|
}
|
|
|
- $this->printLinks($input, $output, $package, 'provides');
|
|
|
- $this->printLinks($input, $output, $package, 'conflicts');
|
|
|
- $this->printLinks($input, $output, $package, 'replaces');
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // list packages
|
|
|
- $packages = array();
|
|
|
+ // show tree view if requested
|
|
|
+ if ($input->getOption('tree')) {
|
|
|
+ $rootPackage = $this->getComposer()->getPackage();
|
|
|
+ $rootRequires = array_map(
|
|
|
+ 'strtolower',
|
|
|
+ array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
|
|
|
+ );
|
|
|
+
|
|
|
+ foreach ($installedRepo->getPackages() as $package) {
|
|
|
+ if (in_array($package->getName(), $rootRequires, true)) {
|
|
|
+ $this->displayPackageTree($package, $installedRepo, $repos, $output);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
if ($repos instanceof CompositeRepository) {
|
|
|
$repos = $repos->getRepositories();
|
|
@@ -142,6 +180,9 @@ EOT
|
|
|
$repos = array($repos);
|
|
|
}
|
|
|
|
|
|
+ // list packages
|
|
|
+ $packages = array();
|
|
|
+
|
|
|
foreach ($repos as $repo) {
|
|
|
if ($repo === $platformRepo) {
|
|
|
$type = '<info>platform</info>:';
|
|
@@ -169,12 +210,12 @@ EOT
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- $tree = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available');
|
|
|
- $indent = $tree ? ' ' : '';
|
|
|
+ $showAllTypes = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available');
|
|
|
+ $indent = $showAllTypes ? ' ' : '';
|
|
|
foreach (array('<info>platform</info>:' => true, '<comment>available</comment>:' => false, '<info>installed</info>:' => true) as $type => $showVersion) {
|
|
|
if (isset($packages[$type])) {
|
|
|
- if ($tree) {
|
|
|
- $output->writeln($type);
|
|
|
+ if ($showAllTypes) {
|
|
|
+ $io->write($type);
|
|
|
}
|
|
|
ksort($packages[$type]);
|
|
|
|
|
@@ -182,7 +223,7 @@ EOT
|
|
|
foreach ($packages[$type] as $package) {
|
|
|
if (is_object($package)) {
|
|
|
$nameLength = max($nameLength, strlen($package->getPrettyName()));
|
|
|
- $versionLength = max($versionLength, strlen($this->versionParser->formatVersion($package)));
|
|
|
+ $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
|
|
|
} else {
|
|
|
$nameLength = max($nameLength, $package);
|
|
|
}
|
|
@@ -197,6 +238,11 @@ EOT
|
|
|
$width--;
|
|
|
}
|
|
|
|
|
|
+ if ($input->getOption('path') && null === $composer) {
|
|
|
+ $io->writeError('No composer.json found in the current directory, disabling "path" option');
|
|
|
+ $input->setOption('path', false);
|
|
|
+ }
|
|
|
+
|
|
|
$writePath = !$input->getOption('name-only') && $input->getOption('path');
|
|
|
$writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
|
|
|
$writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width);
|
|
@@ -205,7 +251,7 @@ EOT
|
|
|
$output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
|
|
|
|
|
|
if ($writeVersion) {
|
|
|
- $output->write(' ' . str_pad($this->versionParser->formatVersion($package), $versionLength, ' '), false);
|
|
|
+ $output->write(' ' . str_pad($package->getFullPrettyVersion(), $versionLength, ' '), false);
|
|
|
}
|
|
|
|
|
|
if ($writeDescription) {
|
|
@@ -224,10 +270,10 @@ EOT
|
|
|
} else {
|
|
|
$output->write($indent . $package);
|
|
|
}
|
|
|
- $output->writeln('');
|
|
|
+ $io->write('');
|
|
|
}
|
|
|
- if ($tree) {
|
|
|
- $output->writeln('');
|
|
|
+ if ($showAllTypes) {
|
|
|
+ $io->write('');
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -240,8 +286,8 @@ EOT
|
|
|
* @param RepositoryInterface $repos
|
|
|
* @param string $name
|
|
|
* @param string $version
|
|
|
- * @return array array(CompletePackageInterface, array of versions)
|
|
|
* @throws \InvalidArgumentException
|
|
|
+ * @return array array(CompletePackageInterface, array of versions)
|
|
|
*/
|
|
|
protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
|
|
|
{
|
|
@@ -274,9 +320,9 @@ EOT
|
|
|
$matches[$index] = $package->getId();
|
|
|
}
|
|
|
|
|
|
- // select prefered package according to policy rules
|
|
|
- if (!$matchedPackage && $matches && $prefered = $policy->selectPreferedPackages($pool, array(), $matches)) {
|
|
|
- $matchedPackage = $pool->literalToPackage($prefered[0]);
|
|
|
+ // select preferred package according to policy rules
|
|
|
+ if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
|
|
|
+ $matchedPackage = $pool->literalToPackage($preferred[0]);
|
|
|
}
|
|
|
|
|
|
return array($matchedPackage, $versions);
|
|
@@ -285,55 +331,56 @@ EOT
|
|
|
/**
|
|
|
* prints package meta data
|
|
|
*/
|
|
|
- protected function printMeta(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, RepositoryInterface $repos)
|
|
|
+ protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
|
|
|
{
|
|
|
- $output->writeln('<info>name</info> : ' . $package->getPrettyName());
|
|
|
- $output->writeln('<info>descrip.</info> : ' . $package->getDescription());
|
|
|
- $output->writeln('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
|
|
|
- $this->printVersions($input, $output, $package, $versions, $installedRepo, $repos);
|
|
|
- $output->writeln('<info>type</info> : ' . $package->getType());
|
|
|
- $output->writeln('<info>license</info> : ' . implode(', ', $package->getLicense()));
|
|
|
- $output->writeln('<info>source</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
|
|
|
- $output->writeln('<info>dist</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
|
|
|
- $output->writeln('<info>names</info> : ' . implode(', ', $package->getNames()));
|
|
|
+ $io = $this->getIO();
|
|
|
+ $io->write('<info>name</info> : ' . $package->getPrettyName());
|
|
|
+ $io->write('<info>descrip.</info> : ' . $package->getDescription());
|
|
|
+ $io->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
|
|
|
+ $this->printVersions($package, $versions, $installedRepo);
|
|
|
+ $io->write('<info>type</info> : ' . $package->getType());
|
|
|
+ $this->printLicenses($package);
|
|
|
+ $io->write('<info>source</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
|
|
|
+ $io->write('<info>dist</info> : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
|
|
|
+ $io->write('<info>names</info> : ' . implode(', ', $package->getNames()));
|
|
|
|
|
|
if ($package->isAbandoned()) {
|
|
|
$replacement = ($package->getReplacementPackage() !== null)
|
|
|
? ' The author suggests using the ' . $package->getReplacementPackage(). ' package instead.'
|
|
|
: null;
|
|
|
|
|
|
- $output->writeln(
|
|
|
- sprintf('<error>Attention: This package is abandoned and no longer maintained.%s</error>', $replacement)
|
|
|
+ $io->writeError(
|
|
|
+ sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
|
|
|
);
|
|
|
}
|
|
|
|
|
|
if ($package->getSupport()) {
|
|
|
- $output->writeln("\n<info>support</info>");
|
|
|
+ $io->write("\n<info>support</info>");
|
|
|
foreach ($package->getSupport() as $type => $value) {
|
|
|
- $output->writeln('<comment>' . $type . '</comment> : '.$value);
|
|
|
+ $io->write('<comment>' . $type . '</comment> : '.$value);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if ($package->getAutoload()) {
|
|
|
- $output->writeln("\n<info>autoload</info>");
|
|
|
+ $io->write("\n<info>autoload</info>");
|
|
|
foreach ($package->getAutoload() as $type => $autoloads) {
|
|
|
- $output->writeln('<comment>' . $type . '</comment>');
|
|
|
+ $io->write('<comment>' . $type . '</comment>');
|
|
|
|
|
|
if ($type === 'psr-0') {
|
|
|
foreach ($autoloads as $name => $path) {
|
|
|
- $output->writeln(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
|
|
+ $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
|
|
}
|
|
|
} elseif ($type === 'psr-4') {
|
|
|
foreach ($autoloads as $name => $path) {
|
|
|
- $output->writeln(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
|
|
+ $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
|
|
|
}
|
|
|
} elseif ($type === 'classmap') {
|
|
|
- $output->writeln(implode(', ', $autoloads));
|
|
|
+ $io->write(implode(', ', $autoloads));
|
|
|
}
|
|
|
}
|
|
|
if ($package->getIncludePaths()) {
|
|
|
- $output->writeln('<comment>include-path</comment>');
|
|
|
- $output->writeln(implode(', ', $package->getIncludePaths()));
|
|
|
+ $io->write('<comment>include-path</comment>');
|
|
|
+ $io->write(implode(', ', $package->getIncludePaths()));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -341,7 +388,7 @@ EOT
|
|
|
/**
|
|
|
* prints all available versions of this package and highlights the installed one if any
|
|
|
*/
|
|
|
- protected function printVersions(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, RepositoryInterface $repos)
|
|
|
+ protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
|
|
|
{
|
|
|
uasort($versions, 'version_compare');
|
|
|
$versions = array_keys(array_reverse($versions));
|
|
@@ -357,27 +404,172 @@ EOT
|
|
|
|
|
|
$versions = implode(', ', $versions);
|
|
|
|
|
|
- $output->writeln('<info>versions</info> : ' . $versions);
|
|
|
+ $this->getIO()->write('<info>versions</info> : ' . $versions);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* print link objects
|
|
|
*
|
|
|
- * @param InputInterface $input
|
|
|
- * @param OutputInterface $output
|
|
|
* @param CompletePackageInterface $package
|
|
|
* @param string $linkType
|
|
|
* @param string $title
|
|
|
*/
|
|
|
- protected function printLinks(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, $linkType, $title = null)
|
|
|
+ protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
|
|
|
{
|
|
|
$title = $title ?: $linkType;
|
|
|
+ $io = $this->getIO();
|
|
|
if ($links = $package->{'get'.ucfirst($linkType)}()) {
|
|
|
- $output->writeln("\n<info>" . $title . "</info>");
|
|
|
+ $io->write("\n<info>" . $title . "</info>");
|
|
|
|
|
|
foreach ($links as $link) {
|
|
|
- $output->writeln($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
|
|
|
+ $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Prints the licenses of a package with metadata
|
|
|
+ *
|
|
|
+ * @param CompletePackageInterface $package
|
|
|
+ */
|
|
|
+ protected function printLicenses(CompletePackageInterface $package)
|
|
|
+ {
|
|
|
+ $spdxLicenses = new SpdxLicenses();
|
|
|
+
|
|
|
+ $licenses = $package->getLicense();
|
|
|
+ $io = $this->getIO();
|
|
|
+
|
|
|
+ foreach ($licenses as $licenseId) {
|
|
|
+ $license = $spdxLicenses->getLicenseByIdentifier($licenseId); // keys: 0 fullname, 1 osi, 2 url
|
|
|
+
|
|
|
+ if (!$license) {
|
|
|
+ $out = $licenseId;
|
|
|
+ } else {
|
|
|
+ // is license OSI approved?
|
|
|
+ if ($license[1] === true) {
|
|
|
+ $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
|
|
|
+ } else {
|
|
|
+ $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $io->write('<info>license</info> : ' . $out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Init styles for tree
|
|
|
+ *
|
|
|
+ * @param OutputInterface $output
|
|
|
+ */
|
|
|
+ protected function initStyles(OutputInterface $output)
|
|
|
+ {
|
|
|
+ $this->colors = array(
|
|
|
+ 'green',
|
|
|
+ 'yellow',
|
|
|
+ 'cyan',
|
|
|
+ 'magenta',
|
|
|
+ 'blue',
|
|
|
+ );
|
|
|
+
|
|
|
+ foreach ($this->colors as $color) {
|
|
|
+ $style = new OutputFormatterStyle($color);
|
|
|
+ $output->getFormatter()->setStyle($color, $style);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Display the tree
|
|
|
+ *
|
|
|
+ * @param PackageInterface|string $package
|
|
|
+ * @param RepositoryInterface $installedRepo
|
|
|
+ * @param RepositoryInterface $distantRepos
|
|
|
+ * @param OutputInterface $output
|
|
|
+ */
|
|
|
+ protected function displayPackageTree(PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, OutputInterface $output)
|
|
|
+ {
|
|
|
+ $packagesInTree = array();
|
|
|
+ $packagesInTree[] = $package;
|
|
|
+
|
|
|
+ $output->write(sprintf('<info>%s</info>', $package->getPrettyName()));
|
|
|
+ $output->write(' ' . $package->getPrettyVersion());
|
|
|
+ $output->write(' ' . strtok($package->getDescription(), "\r\n"));
|
|
|
+ $output->writeln('');
|
|
|
+
|
|
|
+ if (is_object($package)) {
|
|
|
+ $requires = $package->getRequires();
|
|
|
+ $treeBar = '├';
|
|
|
+ $j = 0;
|
|
|
+ $total = count($requires);
|
|
|
+ foreach ($requires as $requireName => $require) {
|
|
|
+ $j++;
|
|
|
+ if ($j == 0) {
|
|
|
+ $this->writeTreeLine($treeBar);
|
|
|
+ }
|
|
|
+ if ($j == $total) {
|
|
|
+ $treeBar = '└';
|
|
|
+ }
|
|
|
+ $level = 1;
|
|
|
+ $color = $this->colors[$level];
|
|
|
+ $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
|
|
|
+ $this->writeTreeLine($info);
|
|
|
+
|
|
|
+ $treeBar = str_replace('└', ' ', $treeBar);
|
|
|
+
|
|
|
+ $packagesInTree[] = $requireName;
|
|
|
+
|
|
|
+ $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $output, $treeBar, $level + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Display a package tree
|
|
|
+ *
|
|
|
+ * @param string $name
|
|
|
+ * @param PackageInterface|string $package
|
|
|
+ * @param RepositoryInterface $installedRepo
|
|
|
+ * @param RepositoryInterface $distantRepos
|
|
|
+ * @param array $packagesInTree
|
|
|
+ * @param OutputInterface $output
|
|
|
+ * @param string $previousTreeBar
|
|
|
+ * @param integer $level
|
|
|
+ */
|
|
|
+ protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, OutputInterface $output, $previousTreeBar = '├', $level = 1)
|
|
|
+ {
|
|
|
+ $previousTreeBar = str_replace('├', '│', $previousTreeBar);
|
|
|
+ list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
|
|
|
+ if (is_object($package)) {
|
|
|
+ $requires = $package->getRequires();
|
|
|
+ $treeBar = $previousTreeBar . ' ├';
|
|
|
+ $i = 0;
|
|
|
+ $total = count($requires);
|
|
|
+ foreach ($requires as $requireName => $require) {
|
|
|
+ $i++;
|
|
|
+ if ($i == $total) {
|
|
|
+ $treeBar = $previousTreeBar . ' └';
|
|
|
+ }
|
|
|
+ $colorIdent = $level % count($this->colors);
|
|
|
+ $color = $this->colors[$colorIdent];
|
|
|
+ $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
|
|
|
+ $this->writeTreeLine($info);
|
|
|
+
|
|
|
+ $treeBar = str_replace('└', ' ', $treeBar);
|
|
|
+ if (!in_array($requireName, $packagesInTree)) {
|
|
|
+ $packagesInTree[] = $requireName;
|
|
|
+ $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $output, $treeBar, $level + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private function writeTreeLine($line)
|
|
|
+ {
|
|
|
+ $io = $this->getIO();
|
|
|
+ if (!$io->isDecorated()) {
|
|
|
+ $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
|
|
|
+ }
|
|
|
+
|
|
|
+ $io->write($line);
|
|
|
+ }
|
|
|
}
|