From 9a87aa1aaf554743d7689fe289d9424fb3e1a630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Scho=CC=88nthal?= Date: Fri, 22 Nov 2013 09:44:44 +0100 Subject: [PATCH 1/6] added "home" command like the npm one, opens a package in your browser --- src/Composer/Command/HomeCommand.php | 138 +++++++++++++++++++++++++++ src/Composer/Console/Application.php | 1 + 2 files changed, 139 insertions(+) create mode 100644 src/Composer/Command/HomeCommand.php diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php new file mode 100644 index 000000000..376d99050 --- /dev/null +++ b/src/Composer/Command/HomeCommand.php @@ -0,0 +1,138 @@ + + * 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\DependencyResolver\Pool; +use Composer\Factory; +use Composer\Package\CompletePackageInterface; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; +use Composer\Repository\CompositeRepository; +use Composer\Repository\RepositoryInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Exception\InvalidArgumentException; + +/** + * @author Robert Schönthal + */ +class HomeCommand extends Command +{ + protected $versionParser; + + protected function configure() + { + $this + ->setName('home') + ->setDescription('opens the package in your browser') + ->setDefinition(array( + new InputArgument('package', InputArgument::REQUIRED, 'Package to goto'), + )) + ->setHelp(<<initializeRepo($input, $output); + $package = $this->getPackage($repo, $input->getArgument('package')); + + /** @var CompletePackageInterface $package */ + if ($package instanceof CompletePackageInterface && filter_var($package->getSourceUrl(), FILTER_VALIDATE_URL)) { + $this->openBrowser($package->getSourceUrl()); + } elseif ($package instanceof CompletePackageInterface) { + $this->getIO()->write('no valid source-url given for ' . $package->getName()); + } else { + throw new InvalidArgumentException('package not found'); + } + } + + /** + * finds a package by name + * + * @param RepositoryInterface $repos + * @param string $name + * @return CompletePackageInterface + */ + protected function getPackage(RepositoryInterface $repos, $name) + { + $name = strtolower($name); + $pool = new Pool('dev'); + $pool->addRepository($repos); + $matches = $pool->whatProvides($name); + + foreach ($matches as $index => $package) { + // skip providers/replacers + if ($package->getName() !== $name) { + unset($matches[$index]); + continue; + } + + return $package; + } + } + + /** + * opens a url in your system default browser + * + * @param string $url + */ + private function openBrowser($url) + { + passthru('which xdg-open', $linux); + passthru('which open', $osx); + $windows = defined('PHP_WINDOWS_VERSION_MAJOR'); + + if (0 === $linux) { + passthru('xdg-open ' . $url); + } elseif (0 === $osx) { + passthru('open ' . $url); + } elseif (true === $windows) { + passthru('start "web" explorer "' . $url . '"'); + } else { + $this->getIO()->write('no suitable browser opening tool found, open yourself: ' . $url); + } + } + + /** + * initializes the repo + * + * @param InputInterface $input + * @param OutputInterface $output + * @return CompositeRepository + */ + private function initializeRepo(InputInterface $input, OutputInterface $output) + { + $composer = $this->getComposer(false); + + if ($composer) { + $repo = new CompositeRepository($composer->getRepositoryManager()->getRepositories()); + } else { + $defaultRepos = Factory::createDefaultRepositories($this->getIO()); + $repo = new CompositeRepository($defaultRepos); + } + + if ($composer) { + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'home', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); + + return $repo; + } + + return $repo; + } + +} diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 9d622cf67..cf11358d9 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -227,6 +227,7 @@ class Application extends BaseApplication $commands[] = new Command\RunScriptCommand(); $commands[] = new Command\LicensesCommand(); $commands[] = new Command\GlobalCommand(); + $commands[] = new Command\HomeCommand(); if ('phar:' === substr(__FILE__, 0, 5)) { $commands[] = new Command\SelfUpdateCommand(); From 25d062ccb49d3bd16c87b0ad1a5f935649460638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Scho=CC=88nthal?= Date: Fri, 22 Nov 2013 10:24:10 +0100 Subject: [PATCH 2/6] some minor refactorings --- src/Composer/Command/HomeCommand.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index 376d99050..b1d3aac76 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -29,8 +29,9 @@ use Symfony\Component\Process\Exception\InvalidArgumentException; */ class HomeCommand extends Command { - protected $versionParser; - + /** + * {@inheritDoc} + */ protected function configure() { $this @@ -45,18 +46,20 @@ EOT ); } + /** + * {@inheritDoc} + */ protected function execute(InputInterface $input, OutputInterface $output) { $repo = $this->initializeRepo($input, $output); $package = $this->getPackage($repo, $input->getArgument('package')); - /** @var CompletePackageInterface $package */ - if ($package instanceof CompletePackageInterface && filter_var($package->getSourceUrl(), FILTER_VALIDATE_URL)) { + if (!$package instanceof CompletePackageInterface) { + throw new InvalidArgumentException('package not found'); + } elseif (filter_var($package->getSourceUrl(), FILTER_VALIDATE_URL)) { $this->openBrowser($package->getSourceUrl()); - } elseif ($package instanceof CompletePackageInterface) { - $this->getIO()->write('no valid source-url given for ' . $package->getName()); } else { - throw new InvalidArgumentException('package not found'); + $output->writeln('no valid source-url given for ' . $package->getName()); } } @@ -92,18 +95,19 @@ EOT */ private function openBrowser($url) { + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { + return passthru('start "web" explorer "' . $url . '"'); + } + passthru('which xdg-open', $linux); passthru('which open', $osx); - $windows = defined('PHP_WINDOWS_VERSION_MAJOR'); if (0 === $linux) { passthru('xdg-open ' . $url); } elseif (0 === $osx) { passthru('open ' . $url); - } elseif (true === $windows) { - passthru('start "web" explorer "' . $url . '"'); } else { - $this->getIO()->write('no suitable browser opening tool found, open yourself: ' . $url); + $this->getIO()->write('no suitable browser opening command found, open yourself: ' . $url); } } From 325c57f30c8cb2078b824f01f16a88679d3f5d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Scho=CC=88nthal?= Date: Fri, 22 Nov 2013 11:45:27 +0100 Subject: [PATCH 3/6] tiny refactorings --- src/Composer/Command/HomeCommand.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index b1d3aac76..985ee61de 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -56,8 +56,11 @@ EOT if (!$package instanceof CompletePackageInterface) { throw new InvalidArgumentException('package not found'); - } elseif (filter_var($package->getSourceUrl(), FILTER_VALIDATE_URL)) { - $this->openBrowser($package->getSourceUrl()); + } + if (filter_var($package->getSourceUrl(), FILTER_VALIDATE_URL)) { + $support = $package->getSupport(); + $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl(); + $this->openBrowser($url); } else { $output->writeln('no valid source-url given for ' . $package->getName()); } From e36d7f23ef285afe5f7a7f3df8fa64ae750b540b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Scho=CC=88nthal?= Date: Sat, 23 Nov 2013 19:39:04 +0100 Subject: [PATCH 4/6] escape shell args --- src/Composer/Command/HomeCommand.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index 985ee61de..effe4a847 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -98,6 +98,8 @@ EOT */ private function openBrowser($url) { + $url = escapeshellarg($url); + if (defined('PHP_WINDOWS_VERSION_MAJOR')) { return passthru('start "web" explorer "' . $url . '"'); } From 3a1edd3776ad232ca0ccc1133ed5ff04b3adc163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Scho=CC=88nthal?= Date: Fri, 31 Jan 2014 22:00:45 +0100 Subject: [PATCH 5/6] rename command --- src/Composer/Command/HomeCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index effe4a847..2192af147 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -35,7 +35,8 @@ class HomeCommand extends Command protected function configure() { $this - ->setName('home') + ->setName('browse') + ->setAliases(array('home')) ->setDescription('opens the package in your browser') ->setDefinition(array( new InputArgument('package', InputArgument::REQUIRED, 'Package to goto'), From 2b5a9aee6c780a8ab62f5f7d582fb15d4fd94883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Scho=CC=88nthal?= Date: Fri, 31 Jan 2014 22:09:55 +0100 Subject: [PATCH 6/6] some tiny refactorings --- src/Composer/Command/HomeCommand.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Composer/Command/HomeCommand.php b/src/Composer/Command/HomeCommand.php index 2192af147..550f06308 100644 --- a/src/Composer/Command/HomeCommand.php +++ b/src/Composer/Command/HomeCommand.php @@ -15,8 +15,7 @@ namespace Composer\Command; use Composer\DependencyResolver\Pool; use Composer\Factory; use Composer\Package\CompletePackageInterface; -use Composer\Plugin\CommandEvent; -use Composer\Plugin\PluginEvents; +use Composer\Package\Loader\InvalidPackageException; use Composer\Repository\CompositeRepository; use Composer\Repository\RepositoryInterface; use Symfony\Component\Console\Input\InputArgument; @@ -63,7 +62,7 @@ EOT $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl(); $this->openBrowser($url); } else { - $output->writeln('no valid source-url given for ' . $package->getName()); + throw new InvalidPackageException(array($package->getName() => 'invalid source-url')); } } @@ -135,13 +134,6 @@ EOT $repo = new CompositeRepository($defaultRepos); } - if ($composer) { - $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'home', $input, $output); - $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); - - return $repo; - } - return $repo; }