commit
894b53c115
|
@ -41,6 +41,7 @@ class SearchCommand extends BaseCommand
|
|||
->setDescription('Search for packages')
|
||||
->setDefinition(array(
|
||||
new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
|
||||
new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
|
||||
new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
|
||||
))
|
||||
->setHelp(<<<EOT
|
||||
|
@ -68,9 +69,10 @@ EOT
|
|||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||
|
||||
$onlyName = $input->getOption('only-name');
|
||||
$type = $input->getOption('type') ?: null;
|
||||
|
||||
$flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
|
||||
$results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags);
|
||||
$results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
|
||||
|
||||
foreach ($results as $result) {
|
||||
$io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
|
||||
|
|
|
@ -89,7 +89,7 @@ class ArrayRepository extends BaseRepository
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function search($query, $mode = 0)
|
||||
public function search($query, $mode = 0, $type = null)
|
||||
{
|
||||
$regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
|
||||
|
||||
|
@ -102,9 +102,13 @@ class ArrayRepository extends BaseRepository
|
|||
if (preg_match($regex, $name)
|
||||
|| ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
|
||||
) {
|
||||
if (null !== $type && $package->getType() !== $type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matches[$name] = array(
|
||||
'name' => $package->getPrettyName(),
|
||||
'description' => $package->getDescription(),
|
||||
'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,12 +190,12 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function search($query, $mode = 0)
|
||||
public function search($query, $mode = 0, $type = null)
|
||||
{
|
||||
$this->loadRootServerFile();
|
||||
|
||||
if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
|
||||
$url = str_replace('%query%', $query, $this->searchUrl);
|
||||
$url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
|
||||
|
||||
$hostname = parse_url($url, PHP_URL_HOST) ?: $url;
|
||||
$json = $this->rfs->getContents($hostname, $url, false);
|
||||
|
@ -642,6 +642,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
|||
|
||||
$hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
|
||||
$rfs = $preFileDownloadEvent->getRemoteFilesystem();
|
||||
|
||||
$json = $rfs->getContents($hostname, $filename, false);
|
||||
if ($sha256 && $sha256 !== hash('sha256', $json)) {
|
||||
if ($retries) {
|
||||
|
|
|
@ -97,12 +97,12 @@ class CompositeRepository extends BaseRepository
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function search($query, $mode = 0)
|
||||
public function search($query, $mode = 0, $type = null)
|
||||
{
|
||||
$matches = array();
|
||||
foreach ($this->repositories as $repository) {
|
||||
/* @var $repository RepositoryInterface */
|
||||
$matches[] = $repository->search($query, $mode);
|
||||
$matches[] = $repository->search($query, $mode, $type);
|
||||
}
|
||||
|
||||
return $matches ? call_user_func_array('array_merge', $matches) : array();
|
||||
|
|
|
@ -67,7 +67,9 @@ interface RepositoryInterface extends \Countable
|
|||
*
|
||||
* @param string $query search query
|
||||
* @param int $mode a set of SEARCH_* constants to search on, implementations should do a best effort only
|
||||
* @return array[] an array of array('name' => '...', 'description' => '...')
|
||||
* @param string $type The type of package to search for. Defaults to all types of packages
|
||||
*
|
||||
* @return \array[] an array of array('name' => '...', 'description' => '...')
|
||||
*/
|
||||
public function search($query, $mode = 0);
|
||||
public function search($query, $mode = 0, $type = null);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\Test\Repository;
|
||||
|
||||
use Composer\Repository\ArrayRepository;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\TestCase;
|
||||
|
||||
class ArrayRepositoryTest extends TestCase
|
||||
|
@ -80,4 +81,50 @@ class ArrayRepositoryTest extends TestCase
|
|||
$this->assertTrue($repo->hasPackage($this->getPackage('foo', '1')));
|
||||
$this->assertTrue($repo->hasPackage($this->getPackage('foo', '2')));
|
||||
}
|
||||
|
||||
public function testSearch()
|
||||
{
|
||||
$repo = new ArrayRepository();
|
||||
|
||||
$repo->addPackage($this->getPackage('foo', '1'));
|
||||
$repo->addPackage($this->getPackage('bar', '1'));
|
||||
|
||||
$this->assertSame(
|
||||
array(array('name' => 'foo', 'description' => null)),
|
||||
$repo->search('foo', RepositoryInterface::SEARCH_FULLTEXT)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
array(array('name' => 'bar', 'description' => null)),
|
||||
$repo->search('bar')
|
||||
);
|
||||
|
||||
$this->assertEmpty(
|
||||
$repo->search('foobar')
|
||||
);
|
||||
}
|
||||
|
||||
public function testSearchWithPackageType()
|
||||
{
|
||||
$repo = new ArrayRepository();
|
||||
|
||||
$repo->addPackage($this->getPackage('foo', '1', 'Composer\Package\CompletePackage'));
|
||||
$repo->addPackage($this->getPackage('bar', '1', 'Composer\Package\CompletePackage'));
|
||||
|
||||
$package = $this->getPackage('foobar', '1', 'Composer\Package\CompletePackage');
|
||||
$package->setType('composer-plugin');
|
||||
$repo->addPackage($package);
|
||||
|
||||
$this->assertSame(
|
||||
array(array('name' => 'foo', 'description' => null)),
|
||||
$repo->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'library')
|
||||
);
|
||||
|
||||
$this->assertEmpty($repo->search('bar', RepositoryInterface::SEARCH_FULLTEXT, 'package'));
|
||||
|
||||
$this->assertSame(
|
||||
array(array('name' => 'foobar', 'description' => null)),
|
||||
$repo->search('foo', 0, 'composer-plugin')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
namespace Composer\Test\Repository;
|
||||
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Repository\ComposerRepository;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Test\Mock\FactoryMock;
|
||||
use Composer\TestCase;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
|
@ -165,4 +167,45 @@ class ComposerRepositoryTest extends TestCase
|
|||
$this->assertSame($packages['2'], $packages['2-root']->getAliasOf());
|
||||
$this->assertSame($packages['2'], $packages['2-alias']->getAliasOf());
|
||||
}
|
||||
|
||||
public function testSearchWithType()
|
||||
{
|
||||
$repoConfig = array(
|
||||
'url' => 'http://example.org',
|
||||
);
|
||||
|
||||
$result = array(
|
||||
'results' => array(
|
||||
array(
|
||||
'name' => 'foo',
|
||||
'description' => null
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$rfs = $this->getMockBuilder('Composer\Util\RemoteFilesystem')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$rfs->expects($this->at(0))
|
||||
->method('getContents')
|
||||
->with('example.org', 'http://example.org/packages.json', false)
|
||||
->willReturn(json_encode(array('search' => '/search.json?q=%query%&type=%type%')));
|
||||
|
||||
$rfs->expects($this->at(1))
|
||||
->method('getContents')
|
||||
->with('example.org', 'http://example.org/search.json?q=foo&type=composer-plugin', false)
|
||||
->willReturn(json_encode($result));
|
||||
|
||||
$repository = new ComposerRepository($repoConfig, new NullIO, FactoryMock::createConfig(), null, $rfs);
|
||||
|
||||
$this->assertSame(
|
||||
array(array('name' => 'foo', 'description' => null)),
|
||||
$repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'composer-plugin')
|
||||
);
|
||||
|
||||
$this->assertEmpty(
|
||||
$repository->search('foo', RepositoryInterface::SEARCH_FULLTEXT, 'library')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue