setName("index") ->addOption( 'force', 'f', 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( 'installed-only', 'I', InputOption::VALUE_NONE, 'Filters the results to only the Themes and Plugins you have installed' ) ->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') ; } /** * @return int|null|void */ protected function serve() { $this->options = $this->input->getOptions(); $this->gpm = new GPM($this->options['force']); $this->displayGPMRelease(); $this->data = $this->gpm->getRepository(); $data = $this->filter($this->data); $climate = new CLImate; $climate->extend('Grav\Console\TerminalObjects\Table'); if (!$data) { $this->output->writeln('No data was found in the GPM repository stored locally.'); $this->output->writeln('Please try clearing cache and running the bin/gpm index -f command again'); $this->output->writeln('If this doesn\'t work try tweaking your GPM system settings.'); $this->output->writeln(''); $this->output->writeln('For more help go to:'); $this->output->writeln(' -> https://learn.getgrav.org/troubleshooting/common-problems#cannot-connect-to-the-gpm'); die; } foreach ($data as $type => $packages) { $this->output->writeln("" . strtoupper($type) . " [ " . count($packages) . " ]"); $packages = $this->sort($packages); if (!empty($packages)) { $table = []; $index = 0; foreach ($packages as $slug => $package) { $row = [ 'Count' => $index++ + 1, 'Name' => "" . Utils::truncate($package->name, 20, false, ' ', '...') . " ", 'Slug' => $slug, 'Version'=> $this->version($package), 'Installed' => $this->installed($package) ]; $table[] = $row; } $climate->table($table); } $this->output->writeln(''); } $this->output->writeln('You can either get more informations about a package by typing:'); $this->output->writeln(' ' . $this->argv . ' info '); $this->output->writeln(''); $this->output->writeln('Or you can install a package by typing:'); $this->output->writeln(' ' . $this->argv . ' install '); $this->output->writeln(''); } /** * @param $package * * @return string */ private function version($package) { $list = $this->gpm->{'getUpdatable' . ucfirst($package->package_type)}(); $package = isset($list[$package->slug]) ? $list[$package->slug] : $package; $type = ucfirst(preg_replace("/s$/", '', $package->package_type)); $updatable = $this->gpm->{'is' . $type . 'Updatable'}($package->slug); $installed = $this->gpm->{'is' . $type . 'Installed'}($package->slug); $local = $this->gpm->{'getInstalled' . $type}($package->slug); if (!$installed || !$updatable) { $version = $installed ? $local->version : $package->version; return "v" . $version . ""; } if ($updatable) { return "v" . $package->version . " -> v" . $package->available . ""; } return ''; } /** * @param $package * * @return string */ private function installed($package) { $package = isset($list[$package->slug]) ? $list[$package->slug] : $package; $type = ucfirst(preg_replace("/s$/", '', $package->package_type)); $installed = $this->gpm->{'is' . $type . 'Installed'}($package->slug); return !$installed ? 'not installed' : 'installed'; } /** * @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']); } $filter = [ $this->options['filter'], $this->options['installed-only'], $this->options['updates-only'], $this->options['desc'] ]; if (count(array_filter($filter))) { 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['installed-only'] && $filter) { $method = ucfirst(preg_replace("/s$/", '', $package->package_type)); $filter = $this->gpm->{'is' . $method . 'Installed'}($package->slug); } // 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; } }