HomeCommand.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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\Package\CompletePackageInterface;
  13. use Composer\Repository\RepositoryInterface;
  14. use Composer\Repository\ArrayRepository;
  15. use Composer\Repository\RepositoryFactory;
  16. use Composer\Util\Platform;
  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 BaseCommand
  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, 'Package(s) to browse to.'),
  38. new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
  39. new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
  40. ))
  41. ->setHelp(
  42. <<<EOT
  43. The home command opens or shows a package's repository URL or
  44. homepage in your default browser.
  45. To open the homepage by default, use -H or --homepage.
  46. To show instead of open the repository or homepage URL, use -s or --show.
  47. Read more at https://getcomposer.org/doc/03-cli.md#browse-home
  48. EOT
  49. );
  50. }
  51. /**
  52. * {@inheritDoc}
  53. */
  54. protected function execute(InputInterface $input, OutputInterface $output)
  55. {
  56. $repos = $this->initializeRepos();
  57. $io = $this->getIO();
  58. $return = 0;
  59. $packages = $input->getArgument('packages');
  60. if (!$packages) {
  61. $io->writeError('No package specified, opening homepage for the root package');
  62. $packages = array($this->getComposer()->getPackage()->getName());
  63. }
  64. foreach ($packages as $packageName) {
  65. $handled = false;
  66. $packageExists = false;
  67. foreach ($repos as $repo) {
  68. foreach ($repo->findPackages($packageName) as $package) {
  69. $packageExists = true;
  70. if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
  71. $handled = true;
  72. break 2;
  73. }
  74. }
  75. }
  76. if (!$packageExists) {
  77. $return = 1;
  78. $io->writeError('<warning>Package '.$packageName.' not found</warning>');
  79. }
  80. if (!$handled) {
  81. $return = 1;
  82. $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
  83. }
  84. }
  85. return $return;
  86. }
  87. private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
  88. {
  89. $support = $package->getSupport();
  90. $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
  91. if (!$url || $showHomepage) {
  92. $url = $package->getHomepage();
  93. }
  94. if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
  95. return false;
  96. }
  97. if ($showOnly) {
  98. $this->getIO()->write(sprintf('<info>%s</info>', $url));
  99. } else {
  100. $this->openBrowser($url);
  101. }
  102. return true;
  103. }
  104. /**
  105. * opens a url in your system default browser
  106. *
  107. * @param string $url
  108. */
  109. private function openBrowser($url)
  110. {
  111. $url = ProcessExecutor::escape($url);
  112. $process = new ProcessExecutor($this->getIO());
  113. if (Platform::isWindows()) {
  114. return $process->execute('start "web" explorer "' . $url . '"', $output);
  115. }
  116. $linux = $process->execute('which xdg-open', $output);
  117. $osx = $process->execute('which open', $output);
  118. if (0 === $linux) {
  119. $process->execute('xdg-open ' . $url, $output);
  120. } elseif (0 === $osx) {
  121. $process->execute('open ' . $url, $output);
  122. } else {
  123. $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
  124. }
  125. }
  126. /**
  127. * Initializes repositories
  128. *
  129. * Returns an array of repos in order they should be checked in
  130. *
  131. * @return RepositoryInterface[]
  132. */
  133. private function initializeRepos()
  134. {
  135. $composer = $this->getComposer(false);
  136. if ($composer) {
  137. return array_merge(
  138. array(new ArrayRepository(array($composer->getPackage()))), // root package
  139. array($composer->getRepositoryManager()->getLocalRepository()), // installed packages
  140. $composer->getRepositoryManager()->getRepositories() // remotes
  141. );
  142. }
  143. return RepositoryFactory::defaultRepos($this->getIO());
  144. }
  145. }