Browse Source

Added --type option to search

Pierre du Plessis 8 years ago
parent
commit
6a557e45b8

+ 3 - 1
src/Composer/Command/SearchCommand.php

@@ -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'] : ''));

+ 6 - 2
src/Composer/Repository/ArrayRepository.php

@@ -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,
                 );
             }
         }

+ 3 - 2
src/Composer/Repository/ComposerRepository.php

@@ -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) {

+ 2 - 2
src/Composer/Repository/CompositeRepository.php

@@ -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();

+ 6 - 4
src/Composer/Repository/RepositoryInterface.php

@@ -65,9 +65,11 @@ interface RepositoryInterface extends \Countable
     /**
      * Searches the repository for packages containing the query
      *
-     * @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 $query search query
+     * @param  int    $mode  a set of SEARCH_* constants to search on, implementations should do a best effort only
+     * @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);
 }

+ 47 - 0
tests/Composer/Test/Repository/ArrayRepositoryTest.php

@@ -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')
+        );
+    }
 }

+ 43 - 0
tests/Composer/Test/Repository/ComposerRepositoryTest.php

@@ -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')
+        );
+    }
 }