diff --git a/system/src/Grav/Console/Gpm/IndexCommand.php b/system/src/Grav/Console/Gpm/IndexCommand.php index b75c55d59..70a262953 100644 --- a/system/src/Grav/Console/Gpm/IndexCommand.php +++ b/system/src/Grav/Console/Gpm/IndexCommand.php @@ -21,6 +21,16 @@ class IndexCommand extends ConsoleCommand */ protected $gpm; + /** + * @var + */ + protected $options; + + /** + * @var array + */ + protected $sortKeys = ['name', 'slug', 'author', 'date']; + /** * */ @@ -34,6 +44,43 @@ class IndexCommand extends ConsoleCommand InputOption::VALUE_NONE, 'Force re-fetching the data from remote' ) + ->addOption( + 'filter', + 'F', + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Allows to limit the results based on one or multiple filters input. This can be either portion of a name/slug or a regex' + ) + ->addOption( + 'themes-only', + 'T', + InputOption::VALUE_NONE, + 'Filters the results to only Themes' + ) + ->addOption( + 'plugins-only', + 'P', + InputOption::VALUE_NONE, + 'Filters the results to only Plugins' + ) + ->addOption( + 'updates-only', + 'U', + InputOption::VALUE_NONE, + 'Filters the results to Updatable Themes and Plugins only' + ) + ->addOption( + 'sort', + 's', + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Allows to sort (ASC) the results based on one or multiple keys. SORT can be either "name", "slug", "author", "date"', + ['date'] + ) + ->addOption( + 'desc', + 'D', + InputOption::VALUE_NONE, + 'Reverses the order of the output.' + ) ->setDescription("Lists the plugins and themes available for installation") ->setHelp('The index command lists the plugins and themes available for installation') ; @@ -44,16 +91,21 @@ class IndexCommand extends ConsoleCommand */ protected function serve() { - $this->gpm = new GPM($this->input->getOption('force')); + $this->options = $this->input->getOptions(); + + $this->gpm = new GPM($this->options['force']); $this->data = $this->gpm->getRepository(); $this->output->writeln(''); - foreach ($this->data as $type => $packages) { + $data = $this->filter($this->data); + + foreach ($data as $type => $packages) { $this->output->writeln("" . ucfirst($type) . " [ " . count($packages) . " ]"); - $index = 0; + $index = 0; + $packages = $this->sort($packages); foreach ($packages as $slug => $package) { $this->output->writeln( // index @@ -108,4 +160,65 @@ class IndexCommand extends ConsoleCommand return ''; } + + /** + * @param $data + * + * @return mixed + */ + public function filter($data) + { + // filtering and sorting + if ($this->options['plugins-only']) { + unset($data['themes']); + } + if ($this->options['themes-only']) { + unset($data['plugins']); + } + + if ($this->options['filter'] || $this->options['updates-only'] || $this->options['desc']) { + foreach ($data as $type => $packages) { + foreach ($packages as $slug => $package) { + $filter = true; + + // Filtering by string + if ($this->options['filter']) { + $filter = preg_grep('/(' . (implode('|', $this->options['filter'])) . ')/i', [$slug, $package->name]); + } + + // Filtering updatables only + if ($this->options['updates-only'] && $filter) { + $method = ucfirst(preg_replace("/s$/", '', $package->package_type)); + $filter = $this->gpm->{'is' . $method . 'Updatable'}($package->slug); + } + + if (!$filter) { + unset($data[$type][$slug]); + } + } + } + } + + return $data; + } + + /** + * @param $packages + */ + public function sort($packages) + { + foreach ($this->options['sort'] as $key) { + $packages = $packages->sort(function ($a, $b) use ($key) { + switch ($key) { + case 'author': + return strcmp($a->{$key}['name'], $b->{$key}['name']); + break; + default: + return strcmp($a->$key, $b->$key); + } + }, $this->options['desc'] ? true : false); + } + + return $packages; + } }