From a790af3f9d6d4aef4bd2f967e08f93eaae8cc795 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Wed, 27 Jul 2022 23:14:53 +0800 Subject: [PATCH] Add search command support --- composer.json | 3 +- src/Commands/Search.php | 134 ++++++++++++++++++++ src/Composer.php | 1 + src/Exceptions/ComposerExceptionHandler.php | 4 +- tests/Cases/Commands/SearchTest.php | 96 ++++++++++++++ 5 files changed, 235 insertions(+), 3 deletions(-) create mode 100644 src/Commands/Search.php create mode 100644 tests/Cases/Commands/SearchTest.php diff --git a/composer.json b/composer.json index 394f1ea..5a89b07 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "coverage": "XDEBUG_MODE=coverage phpunit --testdox --colors=\"auto\" --coverage-html=\"coverage\"" }, "require": { - "php": "^7.4.0 || ^8.0 || ^8.1", + "php": "^7.4.0 || ^8.0", "ext-openssl": "*", "ext-zip": "*", "ext-zlib": "*", @@ -30,6 +30,7 @@ "symfony/process": "^4.3.4 || ^5.0 || ^6.0" }, "require-dev": { + "dms/phpunit-arraysubset-asserts": "^0.4.0", "phpstan/phpstan": "^1.6", "phpunit/phpunit": "^8.5.15 || ^9.5.4", "symfony/phpunit-bridge": "^4.3.4 || ^5.0 || ^6.0" diff --git a/src/Commands/Search.php b/src/Commands/Search.php new file mode 100644 index 0000000..9325a0e --- /dev/null +++ b/src/Commands/Search.php @@ -0,0 +1,134 @@ + The results returned from the query. + */ + public array $results = []; + + /** + * Command handler. + */ + public function handle( + string $query, + ?string $type = null, + bool $onlyNames = false, + bool $onlyVendors = false + ): void { + $this->query = $query; + $this->type = $type; + + if ($onlyNames) { + $this->limitTo = 'name'; + } elseif ($onlyVendors) { + $this->limitTo = 'vendor'; + } + } + + /** + * @inheritDoc + */ + public function execute() + { + $output = $this->runComposerCommand(); + + if ($output['code'] !== 0) { + throw new CommandException(implode(PHP_EOL, $output['output'])); + } + + $this->results = json_decode(implode(PHP_EOL, $output['output']), true); + + return $this; + } + + /** + * @inheritDoc + */ + public function getCommandName(): string + { + return 'search'; + } + + /** + * @inheritDoc + */ + public function requiresWorkDir(): bool + { + return false; + } + + /** + * Returns the list of results found. + * + * @return array + */ + public function getResults(): array + { + return $this->results; + } + + /** + * Returns the number of results found. + */ + public function count(): int + { + return count($this->results); + } + + /** + * @inheritDoc + */ + public function arguments(): array + { + $arguments = []; + + if (!empty($this->type)) { + $arguments['--type'] = $this->type; + } + + if ($this->limitTo === 'name') { + $arguments['--only-name'] = true; + } elseif ($this->limitTo === 'vendor') { + $arguments['--only-vendor'] = true; + } + + $arguments['--format'] = 'json'; + + $arguments['tokens'] = preg_split('/ +/', $this->query, -1, PREG_SPLIT_NO_EMPTY); + + return $arguments; + } +} diff --git a/src/Composer.php b/src/Composer.php index 5779c45..c00d3da 100644 --- a/src/Composer.php +++ b/src/Composer.php @@ -51,6 +51,7 @@ class Composer protected $commands = [ 'i' => \Winter\Packager\Commands\Install::class, 'install' => \Winter\Packager\Commands\Install::class, + 'search' => \Winter\Packager\Commands\Search::class, 'show' => \Winter\Packager\Commands\Show::class, 'update' => \Winter\Packager\Commands\Update::class, 'version' => \Winter\Packager\Commands\Version::class, diff --git a/src/Exceptions/ComposerExceptionHandler.php b/src/Exceptions/ComposerExceptionHandler.php index 9012f78..b9ddeff 100644 --- a/src/Exceptions/ComposerExceptionHandler.php +++ b/src/Exceptions/ComposerExceptionHandler.php @@ -9,14 +9,14 @@ * Handles a Composer exception and returns a corresponding Packager exception. * * @author Ben Thomson - * @since 0.1.6 + * @since 0.2.0 */ class ComposerExceptionHandler { /** * Handles a Composer exception and returns a corresponding Packager exception. * - * @param Throwable $exception + * @param \Throwable $exception * @param BaseCommand $command * @return array */ diff --git a/tests/Cases/Commands/SearchTest.php b/tests/Cases/Commands/SearchTest.php new file mode 100644 index 0000000..3551453 --- /dev/null +++ b/tests/Cases/Commands/SearchTest.php @@ -0,0 +1,96 @@ +mockCommandOutput( + 'search', + Search::class, + 0, + json_encode([ + [ + 'name' => 'winter/wn-system-module', + 'description' => 'System module for Winter CMS', + 'url' => 'https://packagist.org/packages/winter/wn-system-module', + 'repository' => 'https://github.com/wintercms/wn-system-module', + ], + [ + 'name' => 'winter/wn-cms-module', + 'description' => 'CMS module for Winter CMS', + 'url' => 'https://packagist.org/packages/winter/wn-cms-module', + 'repository' => 'https://github.com/wintercms/wn-cms-module', + ], + [ + 'name' => 'winter/wn-backend-module', + 'description' => 'Backend module for Winter CMS', + 'url' => 'https://packagist.org/packages/winter/wn-backend-module', + 'repository' => 'https://github.com/wintercms/wn-backend-module', + ], + ], JSON_PRETTY_PRINT) + ); + + $search = $this->composer->search('winter', 'winter-module'); + + $this->assertArraySubset([ + [ + 'name' => 'winter/wn-system-module', + ], + [ + 'name' => 'winter/wn-cms-module', + ], + [ + 'name' => 'winter/wn-backend-module', + ], + ], $search->getResults()); + $this->assertEquals(3, $search->count()); + } + + /** + * @test + * @testdox can run a real search and show a few results. + * @covers ::handle + * @covers ::execute + * @covers ::getResults + * @covers ::count + */ + public function itCanRunRealSearch(): void + { + $search = $this->composer->search('winter', 'winter-module'); + + $this->assertArraySubset([ + [ + 'name' => 'winter/wn-system-module', + ], + [ + 'name' => 'winter/wn-cms-module', + ], + [ + 'name' => 'winter/wn-backend-module', + ], + ], $search->getResults()); + $this->assertEquals(3, $search->count()); + } +}