* Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Command; use Composer\Composer; use Composer\Factory; use Composer\Package\CompletePackageInterface; use Composer\Package\Version\VersionParser; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Composer\Repository\ArrayRepository; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryInterface; /** * @author Robert Schönthal * @author Jordi Boggiano */ class ShowCommand extends Command { protected $versionParser; protected function configure() { $this ->setName('show') ->setDescription('Show information about packages') ->setDefinition(array( new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect'), new InputArgument('version', InputArgument::OPTIONAL, 'Version to inspect'), new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only'), new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'), new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'), new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables display of dev-require packages.'), )) ->setHelp(<<versionParser = new VersionParser; // init repos $platformRepo = new PlatformRepository; $getRepositories = function (Composer $composer, $dev) { $manager = $composer->getRepositoryManager(); $repos = new CompositeRepository(array($manager->getLocalRepository())); if ($dev) { $repos->addRepository($manager->getLocalDevRepository()); } return $repos; }; if ($input->getOption('self')) { $package = $this->getComposer(false)->getPackage(); $repos = $installedRepo = new ArrayRepository(array($package)); } elseif ($input->getOption('platform')) { $repos = $installedRepo = $platformRepo; } elseif ($input->getOption('installed')) { $repos = $installedRepo = $getRepositories($this->getComposer(), $input->getOption('dev')); } elseif ($composer = $this->getComposer(false)) { $localRepo = $getRepositories($composer, $input->getOption('dev')); $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 packages from ' . implode(', ', array_keys($defaultRepos))); $installedRepo = $platformRepo; $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); } // show single package or single version if ($input->getArgument('package') || !empty($package)) { $versions = array(); if (empty($package)) { list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version')); if (!$package) { throw new \InvalidArgumentException('Package '.$input->getArgument('package').' not found'); } } else { $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("\nsuggests"); foreach ($package->getSuggests() as $suggested => $reason) { $output->writeln($suggested . ' ' . $reason . ''); } } $this->printLinks($input, $output, $package, 'provides'); $this->printLinks($input, $output, $package, 'conflicts'); $this->printLinks($input, $output, $package, 'replaces'); return; } // list packages $packages = array(); $repos->filterPackages(function ($package) use (&$packages, $platformRepo, $installedRepo) { if ($platformRepo->hasPackage($package)) { $type = 'platform:'; } elseif ($installedRepo->hasPackage($package)) { $type = 'installed:'; } else { $type = 'available:'; } if (!isset($packages[$type][$package->getName()]) || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<') ) { $packages[$type][$package->getName()] = $package; } }, 'Composer\Package\CompletePackage'); foreach (array('platform:' => true, 'available:' => false, 'installed:' => true) as $type => $showVersion) { if (isset($packages[$type])) { $output->writeln($type); ksort($packages[$type]); foreach ($packages[$type] as $package) { $output->writeln(' '.$package->getPrettyName() .' '.($showVersion ? '['.$this->versionParser->formatVersion($package).']' : '').' : '. strtok($package->getDescription(), "\r\n")); } $output->writeln(''); } } } /** * finds a package by name and version if provided * * @param RepositoryInterface $installedRepo * @param RepositoryInterface $repos * @param string $name * @param string $version * @return array array(CompletePackageInterface, array of versions) * @throws \InvalidArgumentException */ protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null) { $name = strtolower($name); if ($version) { $version = $this->versionParser->normalize($version); } $match = null; $matches = array(); $repos->filterPackages(function ($package) use ($name, $version, &$matches) { if ($package->getName() === $name) { $matches[] = $package; } }, 'Composer\Package\CompletePackage'); if (null === $version) { // search for a locally installed version foreach ($matches as $package) { if ($installedRepo->hasPackage($package)) { $match = $package; break; } } if (!$match) { // fallback to the highest version foreach ($matches as $package) { if (null === $match || version_compare($package->getVersion(), $match->getVersion(), '>=')) { $match = $package; } } } } else { // select the specified version foreach ($matches as $package) { if ($package->getVersion() === $version) { $match = $package; } } } // build versions array $versions = array(); foreach ($matches as $package) { $versions[$package->getPrettyVersion()] = $package->getVersion(); } return array($match, $versions); } /** * prints package meta data */ protected function printMeta(InputInterface $input, OutputInterface $output, CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, RepositoryInterface $repos) { $output->writeln('name : ' . $package->getPrettyName()); $output->writeln('descrip. : ' . $package->getDescription()); $output->writeln('keywords : ' . join(', ', $package->getKeywords() ?: array())); $this->printVersions($input, $output, $package, $versions, $installedRepo, $repos); $output->writeln('type : ' . $package->getType()); $output->writeln('license : ' . implode(', ', $package->getLicense())); $output->writeln('source : ' . sprintf('[%s] %s %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference())); $output->writeln('dist : ' . sprintf('[%s] %s %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference())); $output->writeln('names : ' . implode(', ', $package->getNames())); if ($package->getSupport()) { $output->writeln("\nsupport"); foreach ($package->getSupport() as $type => $value) { $output->writeln('' . $type . ' : '.$value); } } if ($package->getAutoload()) { $output->writeln("\nautoload"); foreach ($package->getAutoload() as $type => $autoloads) { $output->writeln('' . $type . ''); if ($type === 'psr-0') { foreach ($autoloads as $name => $path) { $output->writeln(($name ?: '*') . ' => ' . ($path ?: '.')); } } elseif ($type === 'classmap') { $output->writeln(implode(', ', $autoloads)); } } if ($package->getIncludePaths()) { $output->writeln('include-path'); $output->writeln(implode(', ', $package->getIncludePaths())); } } } /** * 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) { if ($input->getArgument('version')) { $output->writeln('version : ' . $package->getPrettyVersion()); return; } uasort($versions, 'version_compare'); $versions = array_keys(array_reverse($versions)); // highlight installed version if ($installedRepo->hasPackage($package)) { $installedVersion = $package->getPrettyVersion(); $key = array_search($installedVersion, $versions); if (false !== $key) { $versions[$key] = '* ' . $installedVersion . ''; } } $versions = implode(', ', $versions); $output->writeln('versions : ' . $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) { $title = $title ?: $linkType; if ($links = $package->{'get'.ucfirst($linkType)}()) { $output->writeln("\n" . $title . ""); foreach ($links as $link) { $output->writeln($link->getTarget() . ' ' . $link->getPrettyConstraint() . ''); } } } }