HomeCommand.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Command;
  12. use Composer\DependencyResolver\Pool;
  13. use Composer\Factory;
  14. use Composer\Package\CompletePackageInterface;
  15. use Composer\Repository\CompositeRepository;
  16. use Composer\Repository\RepositoryInterface;
  17. use Composer\Util\ProcessExecutor;
  18. use Symfony\Component\Console\Input\InputArgument;
  19. use Symfony\Component\Console\Input\InputOption;
  20. use Symfony\Component\Console\Input\InputInterface;
  21. use Symfony\Component\Console\Output\OutputInterface;
  22. /**
  23. * @author Robert Schönthal <seroscho@googlemail.com>
  24. */
  25. class HomeCommand extends Command
  26. {
  27. /**
  28. * {@inheritDoc}
  29. */
  30. protected function configure()
  31. {
  32. $this
  33. ->setName('browse')
  34. ->setAliases(array('home'))
  35. ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
  36. ->setDefinition(array(
  37. new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Package(s) to browse to.'),
  38. new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
  39. ))
  40. ->setHelp(<<<EOT
  41. The home command opens a package's repository URL or
  42. homepage in your default browser.
  43. To open the homepage by default, use -H or --homepage.
  44. EOT
  45. );
  46. }
  47. /**
  48. * {@inheritDoc}
  49. */
  50. protected function execute(InputInterface $input, OutputInterface $output)
  51. {
  52. $repo = $this->initializeRepo($input, $output);
  53. $return = 0;
  54. foreach ($input->getArgument('packages') as $packageName) {
  55. $package = $this->getPackage($repo, $packageName);
  56. if (!$package instanceof CompletePackageInterface) {
  57. $return = 1;
  58. $output->writeln('<warning>Package '.$packageName.' not found</warning>');
  59. continue;
  60. }
  61. $support = $package->getSupport();
  62. $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
  63. if (!$url || $input->getOption('homepage')) {
  64. $url = $package->getHomepage();
  65. }
  66. if (!filter_var($url, FILTER_VALIDATE_URL)) {
  67. $return = 1;
  68. $output->writeln('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
  69. continue;
  70. }
  71. $this->openBrowser($url);
  72. }
  73. return $return;
  74. }
  75. /**
  76. * finds a package by name
  77. *
  78. * @param RepositoryInterface $repos
  79. * @param string $name
  80. * @return CompletePackageInterface
  81. */
  82. protected function getPackage(RepositoryInterface $repos, $name)
  83. {
  84. $name = strtolower($name);
  85. $pool = new Pool('dev');
  86. $pool->addRepository($repos);
  87. $matches = $pool->whatProvides($name);
  88. foreach ($matches as $index => $package) {
  89. // skip providers/replacers
  90. if ($package->getName() !== $name) {
  91. unset($matches[$index]);
  92. continue;
  93. }
  94. return $package;
  95. }
  96. }
  97. /**
  98. * opens a url in your system default browser
  99. *
  100. * @param string $url
  101. */
  102. private function openBrowser($url)
  103. {
  104. $url = ProcessExecutor::escape($url);
  105. if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
  106. return passthru('start "web" explorer "' . $url . '"');
  107. }
  108. passthru('which xdg-open', $linux);
  109. passthru('which open', $osx);
  110. if (0 === $linux) {
  111. passthru('xdg-open ' . $url);
  112. } elseif (0 === $osx) {
  113. passthru('open ' . $url);
  114. } else {
  115. $this->getIO()->write('no suitable browser opening command found, open yourself: ' . $url);
  116. }
  117. }
  118. /**
  119. * initializes the repo
  120. *
  121. * @param InputInterface $input
  122. * @param OutputInterface $output
  123. * @return CompositeRepository
  124. */
  125. private function initializeRepo(InputInterface $input, OutputInterface $output)
  126. {
  127. $composer = $this->getComposer(false);
  128. if ($composer) {
  129. $repo = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
  130. } else {
  131. $defaultRepos = Factory::createDefaultRepositories($this->getIO());
  132. $repo = new CompositeRepository($defaultRepos);
  133. }
  134. return $repo;
  135. }
  136. }