Skip to content

Commit

Permalink
Add search command support
Browse files Browse the repository at this point in the history
  • Loading branch information
bennothommo committed Jul 27, 2022
1 parent d113b26 commit a790af3
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 3 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@
"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": "*",
"composer/composer": "^2.1.0",
"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"
Expand Down
134 changes: 134 additions & 0 deletions src/Commands/Search.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?php

namespace Winter\Packager\Commands;

use Winter\Packager\Exceptions\CommandException;

/**
* Search command.
*
* Runs "composer search" within PHP.
*
* @author Ben Thomson
* @since 0.2.0
*/
class Search extends BaseCommand
{
/**
* The search query to find packages.
*/
public string $query;

/**
* The type of package to search for.
*/
public ?string $type = null;

/**
* Limit the search parameters. This can be one of the following:
*
* - `name`: Search and return package names only
* - `vendor`: Search and return vendors only
*
* @var string|null
*/
public ?string $limitTo = null;

/**
* @var array<int, mixed> 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<int, mixed>
*/
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;
}
}
1 change: 1 addition & 0 deletions src/Composer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/Exceptions/ComposerExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, mixed>
*/
Expand Down
96 changes: 96 additions & 0 deletions tests/Cases/Commands/SearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

declare(strict_types=1);

namespace Winter\Packager\Tests\Cases;

use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
use Winter\Packager\Commands\Search;
use Winter\Packager\Tests\ComposerTestCase;

/**
* @testdox The Search command
* @coversDefaultClass \Winter\Packager\Commands\Search
*/
final class SearchTest extends ComposerTestCase
{
use ArraySubsetAsserts;

/**
* @test
* @testdox can run a (mocked) search and show a few results.
* @covers ::handle
* @covers ::execute
* @covers ::getResults
* @covers ::count
*/
public function itCanRunAMockedSearch(): void
{
$this->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());
}
}

0 comments on commit a790af3

Please sign in to comment.