Remove filterPackages and add RepositoryInterface::search, refactor all commands to use new methods and remove all usage of the full package list for Composer repositories that support providers, fixes #1646
parent
095852933e
commit
be861f090a
|
@ -73,9 +73,8 @@ EOT
|
||||||
}, $input->getOption('link-type'));
|
}, $input->getOption('link-type'));
|
||||||
|
|
||||||
$messages = array();
|
$messages = array();
|
||||||
$repo->filterPackages(function ($package) use ($needle, $types, $linkTypes, &$messages) {
|
$outputPackages = array();
|
||||||
static $outputPackages = array();
|
foreach ($repo->getPackages() as $package) {
|
||||||
|
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
foreach ($package->{'get'.$linkTypes[$type][0]}() as $link) {
|
foreach ($package->{'get'.$linkTypes[$type][0]}() as $link) {
|
||||||
if ($link->getTarget() === $needle) {
|
if ($link->getTarget() === $needle) {
|
||||||
|
@ -86,7 +85,7 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if ($messages) {
|
if ($messages) {
|
||||||
sort($messages);
|
sort($messages);
|
||||||
|
|
|
@ -292,15 +292,7 @@ EOT
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = strtolower($name);
|
return $this->repos->search($name);
|
||||||
|
|
||||||
$this->repos->filterPackages(function ($package) use ($token, &$packages) {
|
|
||||||
if (false !== strpos($package->getName(), $token)) {
|
|
||||||
$packages[] = $package;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return $packages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array())
|
protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array())
|
||||||
|
@ -339,31 +331,57 @@ EOT
|
||||||
''
|
''
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$exactMatch = null;
|
||||||
|
$choices = array();
|
||||||
foreach ($matches as $position => $package) {
|
foreach ($matches as $position => $package) {
|
||||||
$output->writeln(sprintf(' <info>%5s</info> %s <comment>%s</comment>', "[$position]", $package->getPrettyName(), $package->getPrettyVersion()));
|
$choices[] = sprintf(' <info>%5s</info> %s', "[$position]", $package['name']);
|
||||||
|
if ($package['name'] === $package) {
|
||||||
|
$exactMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$output->writeln('');
|
// no match, prompt which to pick
|
||||||
|
if (!$exactMatch) {
|
||||||
|
$output->writeln($choices);
|
||||||
|
$output->writeln('');
|
||||||
|
|
||||||
$validator = function ($selection) use ($matches) {
|
$validator = function ($selection) use ($matches) {
|
||||||
if ('' === $selection) {
|
if ('' === $selection) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_numeric($selection) && preg_match('{^\s*(\S+)\s+(\S.*)\s*$}', $selection, $matches)) {
|
||||||
|
return $matches[1].' '.$matches[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($matches[(int) $selection])) {
|
||||||
|
throw new \Exception('Not a valid selection');
|
||||||
|
}
|
||||||
|
|
||||||
|
$package = $matches[(int) $selection];
|
||||||
|
|
||||||
|
return $package['name'];
|
||||||
|
};
|
||||||
|
|
||||||
|
$package = $dialog->askAndValidate($output, $dialog->getQuestion('Enter package # to add, or the complete package name if it is not listed', false, ':'), $validator, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no constraint yet, prompt user
|
||||||
|
if (false !== $package && false === strpos($package, ' ')) {
|
||||||
|
$validator = function ($input) {
|
||||||
|
$input = trim($input);
|
||||||
|
|
||||||
|
return $input ?: false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$constraint = $dialog->askAndValidate($output, $dialog->getQuestion('Enter the version constraint to require', false, ':'), $validator, 3);
|
||||||
|
if (false === $constraint) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_numeric($selection) && preg_match('{^\s*(\S+) +(\S.*)\s*}', $selection, $matches)) {
|
$package .= ' '.$constraint;
|
||||||
return $matches[1].' '.$matches[2];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($matches[(int) $selection])) {
|
|
||||||
throw new \Exception('Not a valid selection');
|
|
||||||
}
|
|
||||||
|
|
||||||
$package = $matches[(int) $selection];
|
|
||||||
|
|
||||||
return sprintf('%s %s', $package->getName(), $package->getPrettyVersion());
|
|
||||||
};
|
|
||||||
|
|
||||||
$package = $dialog->askAndValidate($output, $dialog->getQuestion('Enter package # to add, or a "[package] [version]" couple if it is not listed', false, ':'), $validator, 3);
|
|
||||||
|
|
||||||
if (false !== $package) {
|
if (false !== $package) {
|
||||||
$requires[] = $package;
|
$requires[] = $package;
|
||||||
|
|
|
@ -109,7 +109,7 @@ EOT
|
||||||
->setPreferDist($input->getOption('prefer-dist'))
|
->setPreferDist($input->getOption('prefer-dist'))
|
||||||
->setDevMode($input->getOption('dev'))
|
->setDevMode($input->getOption('dev'))
|
||||||
->setUpdate(true)
|
->setUpdate(true)
|
||||||
->setUpdateWhitelist($requirements);
|
->setUpdateWhitelist(array_keys($requirements));
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!$install->run()) {
|
if (!$install->run()) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Package\CompletePackageInterface;
|
use Composer\Package\CompletePackageInterface;
|
||||||
use Composer\Package\AliasPackage;
|
use Composer\Package\AliasPackage;
|
||||||
use Composer\Factory;
|
use Composer\Factory;
|
||||||
|
@ -66,79 +67,13 @@ EOT
|
||||||
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->onlyName = $input->getOption('only-name');
|
$onlyName = $input->getOption('only-name');
|
||||||
$this->tokens = $input->getArgument('tokens');
|
|
||||||
$this->output = $output;
|
|
||||||
$repos->filterPackages(array($this, 'processPackage'), 'Composer\Package\CompletePackage');
|
|
||||||
|
|
||||||
foreach ($this->lowMatches as $details) {
|
$flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
|
||||||
$output->writeln($details['name'] . '<comment>:</comment> '. $details['description']);
|
$results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags);
|
||||||
|
|
||||||
|
foreach ($results as $result) {
|
||||||
|
$output->writeln($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processPackage($package)
|
|
||||||
{
|
|
||||||
if ($package instanceof AliasPackage || isset($this->matches[$package->getName()])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($this->tokens as $token) {
|
|
||||||
if (!$score = $this->matchPackage($package, $token)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (false !== ($pos = stripos($package->getName(), $token))) {
|
|
||||||
$name = substr($package->getPrettyName(), 0, $pos)
|
|
||||||
. '<highlight>' . substr($package->getPrettyName(), $pos, strlen($token)) . '</highlight>'
|
|
||||||
. substr($package->getPrettyName(), $pos + strlen($token));
|
|
||||||
} else {
|
|
||||||
$name = $package->getPrettyName();
|
|
||||||
}
|
|
||||||
|
|
||||||
$description = strtok($package->getDescription(), "\r\n");
|
|
||||||
if (false !== ($pos = stripos($description, $token))) {
|
|
||||||
$description = substr($description, 0, $pos)
|
|
||||||
. '<highlight>' . substr($description, $pos, strlen($token)) . '</highlight>'
|
|
||||||
. substr($description, $pos + strlen($token));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($score >= 3) {
|
|
||||||
$this->output->writeln($name . '<comment>:</comment> '. $description);
|
|
||||||
$this->matches[$package->getName()] = true;
|
|
||||||
} else {
|
|
||||||
$this->lowMatches[$package->getName()] = array(
|
|
||||||
'name' => $name,
|
|
||||||
'description' => $description,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tries to find a token within the name/keywords/description
|
|
||||||
*
|
|
||||||
* @param CompletePackageInterface $package
|
|
||||||
* @param string $token
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
private function matchPackage(CompletePackageInterface $package, $token)
|
|
||||||
{
|
|
||||||
$score = 0;
|
|
||||||
|
|
||||||
if (false !== stripos($package->getName(), $token)) {
|
|
||||||
$score += 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->onlyName && false !== stripos(join(',', $package->getKeywords() ?: array()), $token)) {
|
|
||||||
$score += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->onlyName && false !== stripos($package->getDescription(), $token)) {
|
|
||||||
$score += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $score;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,11 @@
|
||||||
namespace Composer\Command;
|
namespace Composer\Command;
|
||||||
|
|
||||||
use Composer\Composer;
|
use Composer\Composer;
|
||||||
|
use Composer\DependencyResolver\Pool;
|
||||||
|
use Composer\DependencyResolver\DefaultPolicy;
|
||||||
use Composer\Factory;
|
use Composer\Factory;
|
||||||
use Composer\Package\CompletePackageInterface;
|
use Composer\Package\CompletePackageInterface;
|
||||||
|
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
@ -22,6 +25,7 @@ use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Composer\Repository\ArrayRepository;
|
use Composer\Repository\ArrayRepository;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
|
use Composer\Repository\ComposerRepository;
|
||||||
use Composer\Repository\PlatformRepository;
|
use Composer\Repository\PlatformRepository;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
|
|
||||||
|
@ -122,20 +126,39 @@ EOT
|
||||||
|
|
||||||
// list packages
|
// list packages
|
||||||
$packages = array();
|
$packages = array();
|
||||||
$repos->filterPackages(function ($package) use (&$packages, $platformRepo, $installedRepo) {
|
|
||||||
if ($platformRepo->hasPackage($package)) {
|
if ($repos instanceof CompositeRepository) {
|
||||||
|
$repos = $repos->getRepositories();
|
||||||
|
} elseif (!is_array($repos)) {
|
||||||
|
$repos = array($repos);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($repos as $repo) {
|
||||||
|
if ($repo === $platformRepo) {
|
||||||
$type = '<info>platform</info>:';
|
$type = '<info>platform</info>:';
|
||||||
} elseif ($installedRepo->hasPackage($package)) {
|
} elseif (
|
||||||
|
$repo === $installedRepo
|
||||||
|
|| ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
|
||||||
|
) {
|
||||||
$type = '<info>installed</info>:';
|
$type = '<info>installed</info>:';
|
||||||
} else {
|
} else {
|
||||||
$type = '<comment>available</comment>:';
|
$type = '<comment>available</comment>:';
|
||||||
}
|
}
|
||||||
if (!isset($packages[$type][$package->getName()])
|
if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
|
||||||
|| version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
|
foreach ($repo->getProviderNames() as $name) {
|
||||||
) {
|
$packages[$type][$name] = $name;
|
||||||
$packages[$type][$package->getName()] = $package;
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($repo->getPackages() as $package) {
|
||||||
|
if (!isset($packages[$type][$package->getName()])
|
||||||
|
|| !is_object($packages[$type][$package->getName()])
|
||||||
|
|| version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
|
||||||
|
) {
|
||||||
|
$packages[$type][$package->getName()] = $package;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 'Composer\Package\CompletePackage');
|
}
|
||||||
|
|
||||||
$tree = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available');
|
$tree = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available');
|
||||||
$indent = $tree ? ' ' : '';
|
$indent = $tree ? ' ' : '';
|
||||||
|
@ -148,8 +171,12 @@ EOT
|
||||||
|
|
||||||
$nameLength = $versionLength = 0;
|
$nameLength = $versionLength = 0;
|
||||||
foreach ($packages[$type] as $package) {
|
foreach ($packages[$type] as $package) {
|
||||||
$nameLength = max($nameLength, strlen($package->getPrettyName()));
|
if (is_object($package)) {
|
||||||
$versionLength = max($versionLength, strlen($this->versionParser->formatVersion($package)));
|
$nameLength = max($nameLength, strlen($package->getPrettyName()));
|
||||||
|
$versionLength = max($versionLength, strlen($this->versionParser->formatVersion($package)));
|
||||||
|
} else {
|
||||||
|
$nameLength = max($nameLength, $package);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
list($width) = $this->getApplication()->getTerminalDimensions();
|
list($width) = $this->getApplication()->getTerminalDimensions();
|
||||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||||
|
@ -159,19 +186,23 @@ EOT
|
||||||
$writeVersion = !$input->getOption('name-only') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
|
$writeVersion = !$input->getOption('name-only') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
|
||||||
$writeDescription = !$input->getOption('name-only') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width);
|
$writeDescription = !$input->getOption('name-only') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width);
|
||||||
foreach ($packages[$type] as $package) {
|
foreach ($packages[$type] as $package) {
|
||||||
$output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
|
if (is_object($package)) {
|
||||||
|
$output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
|
||||||
|
|
||||||
if ($writeVersion) {
|
if ($writeVersion) {
|
||||||
$output->write(' ' . str_pad($this->versionParser->formatVersion($package), $versionLength, ' '), false);
|
$output->write(' ' . str_pad($this->versionParser->formatVersion($package), $versionLength, ' '), false);
|
||||||
}
|
|
||||||
|
|
||||||
if ($writeDescription) {
|
|
||||||
$description = strtok($package->getDescription(), "\r\n");
|
|
||||||
$remaining = $width - $nameLength - $versionLength - 4;
|
|
||||||
if (strlen($description) > $remaining) {
|
|
||||||
$description = substr($description, 0, $remaining - 3) . '...';
|
|
||||||
}
|
}
|
||||||
$output->write(' ' . $description);
|
|
||||||
|
if ($writeDescription) {
|
||||||
|
$description = strtok($package->getDescription(), "\r\n");
|
||||||
|
$remaining = $width - $nameLength - $versionLength - 4;
|
||||||
|
if (strlen($description) > $remaining) {
|
||||||
|
$description = substr($description, 0, $remaining - 3) . '...';
|
||||||
|
}
|
||||||
|
$output->write(' ' . $description);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$output->write($indent . $package);
|
||||||
}
|
}
|
||||||
$output->writeln('');
|
$output->writeln('');
|
||||||
}
|
}
|
||||||
|
@ -195,51 +226,46 @@ EOT
|
||||||
protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
|
protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
|
||||||
{
|
{
|
||||||
$name = strtolower($name);
|
$name = strtolower($name);
|
||||||
|
$constraint = null;
|
||||||
if ($version) {
|
if ($version) {
|
||||||
$version = $this->versionParser->normalize($version);
|
$version = $this->versionParser->normalize($version);
|
||||||
|
$constraint = new VersionConstraint('=', $version);
|
||||||
}
|
}
|
||||||
|
|
||||||
$match = null;
|
$policy = new DefaultPolicy();
|
||||||
$matches = array();
|
$pool = new Pool('dev');
|
||||||
$repos->filterPackages(function ($package) use ($name, $version, &$matches) {
|
$pool->addRepository($repos);
|
||||||
if ($package->getName() === $name) {
|
|
||||||
$matches[] = $package;
|
|
||||||
}
|
|
||||||
}, 'Composer\Package\CompletePackage');
|
|
||||||
|
|
||||||
if (null === $version) {
|
$matchedPackage = null;
|
||||||
// search for a locally installed version
|
$matches = $pool->whatProvides($name, $constraint);
|
||||||
foreach ($matches as $package) {
|
foreach ($matches as $index => $package) {
|
||||||
if ($installedRepo->hasPackage($package)) {
|
// skip providers/replacers
|
||||||
$match = $package;
|
if ($package->getName() !== $name) {
|
||||||
break;
|
unset($matches[$index]);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$match) {
|
// select an exact match if it is in the installed repo and no specific version was required
|
||||||
// fallback to the highest version
|
if (null === $version && $installedRepo->hasPackage($package)) {
|
||||||
foreach ($matches as $package) {
|
$matchedPackage = $package;
|
||||||
if (null === $match || version_compare($package->getVersion(), $match->getVersion(), '>=')) {
|
|
||||||
$match = $package;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// select the specified version
|
|
||||||
foreach ($matches as $package) {
|
|
||||||
if ($package->getVersion() === $version) {
|
|
||||||
$match = $package;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$matches[$index] = $package->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// select prefered package according to policy rules
|
||||||
|
if (!$matchedPackage && $matches && $prefered = $policy->selectPreferedPackages($pool, array(), $matches)) {
|
||||||
|
$matchedPackage = $pool->literalToPackage($prefered[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build versions array
|
// build versions array
|
||||||
$versions = array();
|
$versions = array();
|
||||||
foreach ($matches as $package) {
|
foreach ($matches as $package) {
|
||||||
|
$package = $pool->literalToPackage($package);
|
||||||
$versions[$package->getPrettyVersion()] = $package->getVersion();
|
$versions[$package->getPrettyVersion()] = $package->getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($match, $versions);
|
return array($matchedPackage, $versions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -214,13 +214,13 @@ class Installer
|
||||||
// output suggestions
|
// output suggestions
|
||||||
foreach ($this->suggestedPackages as $suggestion) {
|
foreach ($this->suggestedPackages as $suggestion) {
|
||||||
$target = $suggestion['target'];
|
$target = $suggestion['target'];
|
||||||
if ($installedRepo->filterPackages(function (PackageInterface $package) use ($target) {
|
foreach ($installedRepo->getPackages() as $package) {
|
||||||
if (in_array($target, $package->getNames())) {
|
if (in_array($target, $package->getNames())) {
|
||||||
return false;
|
continue 2;
|
||||||
}
|
}
|
||||||
})) {
|
|
||||||
$this->io->write($suggestion['source'].' suggests installing '.$suggestion['target'].' ('.$suggestion['reason'].')');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->io->write($suggestion['source'].' suggests installing '.$suggestion['target'].' ('.$suggestion['reason'].')');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->dryRun) {
|
if (!$this->dryRun) {
|
||||||
|
|
|
@ -74,6 +74,27 @@ class ArrayRepository implements RepositoryInterface
|
||||||
return $packages;
|
return $packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function search($query, $mode = 0)
|
||||||
|
{
|
||||||
|
$regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
|
||||||
|
|
||||||
|
$matches = array();
|
||||||
|
foreach ($this->getPackages() as $package) {
|
||||||
|
// TODO implement SEARCH_FULLTEXT handling with keywords/description matching
|
||||||
|
if (preg_match($regex, $package->getName())) {
|
||||||
|
$matches[] = array(
|
||||||
|
'name' => $package->getName(),
|
||||||
|
'description' => $package->getDescription(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $matches;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -112,20 +133,6 @@ class ArrayRepository implements RepositoryInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public function filterPackages($callback, $class = 'Composer\Package\Package')
|
|
||||||
{
|
|
||||||
foreach ($this->getPackages() as $package) {
|
|
||||||
if (false === call_user_func($callback, $package)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function createAliasPackage(PackageInterface $package, $alias = null, $prettyAlias = null)
|
protected function createAliasPackage(PackageInterface $package, $alias = null, $prettyAlias = null)
|
||||||
{
|
{
|
||||||
return new AliasPackage($package, $alias ?: $package->getAlias(), $prettyAlias ?: $package->getPrettyAlias());
|
return new AliasPackage($package, $alias ?: $package->getAlias(), $prettyAlias ?: $package->getPrettyAlias());
|
||||||
|
|
|
@ -135,24 +135,54 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function filterPackages($callback, $class = 'Composer\Package\Package')
|
public function search($query, $mode = 0)
|
||||||
{
|
{
|
||||||
if (null === $this->rawData) {
|
$this->loadRootServerFile();
|
||||||
$this->rawData = $this->loadDataFromServer();
|
|
||||||
|
if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
|
||||||
|
$url = str_replace('%query%', $query, $this->searchUrl);
|
||||||
|
|
||||||
|
$json = $this->rfs->getContents($url, $url, false);
|
||||||
|
$results = JsonFile::parseJson($json, $url);
|
||||||
|
|
||||||
|
return $results['results'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->rawData as $package) {
|
if ($this->hasProviders()) {
|
||||||
if (false === call_user_func($callback, $package = $this->createPackage($package, $class))) {
|
$results = array();
|
||||||
return false;
|
$regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
|
||||||
}
|
|
||||||
if ($package->getAlias()) {
|
foreach ($this->getProviderNames() as $name) {
|
||||||
if (false === call_user_func($callback, $this->createAliasPackage($package))) {
|
if (preg_match($regex, $name)) {
|
||||||
return false;
|
$results[] = array('name' => $name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return parent::search($query, $mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProviderNames()
|
||||||
|
{
|
||||||
|
$this->loadRootServerFile();
|
||||||
|
|
||||||
|
if (null === $this->providerListing) {
|
||||||
|
$this->loadProviderListings($this->loadRootServerFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->providersUrl) {
|
||||||
|
return array_keys($this->providerListing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BC handling for old providers-includes
|
||||||
|
$providers = array();
|
||||||
|
foreach (array_keys($this->providerListing) as $provider) {
|
||||||
|
$providers[] = substr($provider, 2, -5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,15 +226,15 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
|
||||||
|
|
||||||
public function whatProvides(Pool $pool, $name)
|
public function whatProvides(Pool $pool, $name)
|
||||||
{
|
{
|
||||||
// skip platform packages
|
|
||||||
if ($name === 'php' || in_array(substr($name, 0, 4), array('ext-', 'lib-'), true) || $name === '__root__') {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->providers[$name])) {
|
if (isset($this->providers[$name])) {
|
||||||
return $this->providers[$name];
|
return $this->providers[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip platform packages
|
||||||
|
if (preg_match('{^(?:php(?:-64bit)?|(?:ext|lib)-[^/]+)$}i', $name) || '__root__' === $name) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
if (null === $this->providerListing) {
|
if (null === $this->providerListing) {
|
||||||
$this->loadProviderListings($this->loadRootServerFile());
|
$this->loadProviderListings($this->loadRootServerFile());
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,20 @@ class CompositeRepository implements RepositoryInterface
|
||||||
return call_user_func_array('array_merge', $packages);
|
return call_user_func_array('array_merge', $packages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function search($query, $mode = 0)
|
||||||
|
{
|
||||||
|
$matches = array();
|
||||||
|
foreach ($this->repositories as $repository) {
|
||||||
|
/* @var $repository RepositoryInterface */
|
||||||
|
$matches[] = $repository->search($query, $mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return call_user_func_array('array_merge', $matches);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,9 +19,13 @@ use Composer\Package\PackageInterface;
|
||||||
*
|
*
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
interface RepositoryInterface extends \Countable
|
interface RepositoryInterface extends \Countable
|
||||||
{
|
{
|
||||||
|
const SEARCH_FULLTEXT = 0;
|
||||||
|
const SEARCH_NAME = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if specified package registered (installed).
|
* Checks if specified package registered (installed).
|
||||||
*
|
*
|
||||||
|
@ -51,24 +55,19 @@ interface RepositoryInterface extends \Countable
|
||||||
*/
|
*/
|
||||||
public function findPackages($name, $version = null);
|
public function findPackages($name, $version = null);
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters all the packages through a callback
|
|
||||||
*
|
|
||||||
* The packages are not guaranteed to be instances in the repository
|
|
||||||
* and this can only be used for streaming through a list of packages.
|
|
||||||
*
|
|
||||||
* If the callback returns false, the process stops
|
|
||||||
*
|
|
||||||
* @param callable $callback
|
|
||||||
* @param string $class
|
|
||||||
* @return bool false if the process was interrupted, true otherwise
|
|
||||||
*/
|
|
||||||
public function filterPackages($callback, $class = 'Composer\Package\Package');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns list of registered packages.
|
* Returns list of registered packages.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getPackages();
|
public function getPackages();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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' => '...')
|
||||||
|
*/
|
||||||
|
public function search($query, $mode = 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ComposerRepositoryTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
$repository
|
$repository
|
||||||
->expects($this->once())
|
->expects($this->exactly(2))
|
||||||
->method('loadRootServerFile')
|
->method('loadRootServerFile')
|
||||||
->will($this->returnValue($repoPackages));
|
->will($this->returnValue($repoPackages));
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class ComposerRepositoryTest extends TestCase
|
||||||
$stubPackage = $this->getPackage('stub/stub', '1.0.0');
|
$stubPackage = $this->getPackage('stub/stub', '1.0.0');
|
||||||
|
|
||||||
$repository
|
$repository
|
||||||
->expects($this->at($at + 1))
|
->expects($this->at($at + 2))
|
||||||
->method('createPackage')
|
->method('createPackage')
|
||||||
->with($this->identicalTo($arg), $this->equalTo('Composer\Package\CompletePackage'))
|
->with($this->identicalTo($arg), $this->equalTo('Composer\Package\CompletePackage'))
|
||||||
->will($this->returnValue($stubPackage));
|
->will($this->returnValue($stubPackage));
|
||||||
|
|
Loading…
Reference in New Issue