Fixed broken list in bin/gpm index, CLI/GPM command failures returning success [#3092, #3017]

This commit is contained in:
Matias Griese
2020-12-07 12:56:47 +02:00
parent dd30b96210
commit c2a2ef212e
26 changed files with 1576 additions and 296 deletions

View File

@@ -1,10 +1,13 @@
# v1.7.0 # v1.7.0
## mm/dd/2020 ## mm/dd/2020
1. [](#new)
* Auto-Escape enabled by default. Manually enable **Twig Compatibility** and disable **Auto-Escape** to use the old setting.
* Updated unit tests to use codeception 4.1
1. [](#bugfix) 1. [](#bugfix)
* Fixed potential error when upgrading Grav * Fixed potential error when upgrading Grav
* Updated unit tests to use codeception 4.1 * Fixed broken list in `bin/gpm index` [#3092](https://github.com/getgrav/grav/issues/3092)
* Auto-Escape enabled by default. Manually enable **Twig Compatibility** to * Fixed CLI/GPM command failures returning 0 (success) value [#3017](https://github.com/getgrav/grav/issues/3017)
# v1.7.0-rc.19 # v1.7.0-rc.19
## 12/02/2020 ## 12/02/2020

849
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,12 @@ use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function count;
/**
* Class BackupCommand
* @package Grav\Console\Cli
*/
class BackupCommand extends ConsoleCommand class BackupCommand extends ConsoleCommand
{ {
/** @var string $source */ /** @var string $source */
@@ -25,7 +30,10 @@ class BackupCommand extends ConsoleCommand
/** @var ProgressBar $progress */ /** @var ProgressBar $progress */
protected $progress; protected $progress;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('backup') ->setName('backup')
@@ -40,7 +48,10 @@ class BackupCommand extends ConsoleCommand
$this->source = getcwd(); $this->source = getcwd();
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->initializeGrav(); $this->initializeGrav();
@@ -53,7 +64,7 @@ class BackupCommand extends ConsoleCommand
if (!class_exists(\ZipArchive::class)) { if (!class_exists(\ZipArchive::class)) {
$io->error('php-zip extension needs to be enabled!'); $io->error('php-zip extension needs to be enabled!');
exit; return 1;
} }
/** @var Backups $backups */ /** @var Backups $backups */
@@ -69,7 +80,7 @@ class BackupCommand extends ConsoleCommand
} }
if (null === $id) { if (null === $id) {
if (\count($backups_list) > 1) { if (count($backups_list) > 1) {
$helper = $this->getHelper('question'); $helper = $this->getHelper('question');
$question = new ChoiceQuestion( $question = new ChoiceQuestion(
'Choose a backup?', 'Choose a backup?',
@@ -91,12 +102,15 @@ class BackupCommand extends ConsoleCommand
$io->newline(2); $io->newline(2);
$io->success('Backup Successfully Created: ' . $backup); $io->success('Backup Successfully Created: ' . $backup);
return 0;
} }
/** /**
* @param array $args * @param array $args
* @return void
*/ */
public function outputProgress($args) public function outputProgress($args): void
{ {
switch ($args['type']) { switch ($args['type']) {
case 'count': case 'count':

View File

@@ -15,6 +15,10 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Formatter\OutputFormatterStyle;
/**
* Class CleanCommand
* @package Grav\Console\Cli
*/
class CleanCommand extends Command class CleanCommand extends Command
{ {
/* @var InputInterface $output */ /* @var InputInterface $output */
@@ -260,7 +264,10 @@ class CleanCommand extends Command
'cache/compiled/', 'cache/compiled/',
]; ];
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('clean') ->setName('clean')
@@ -271,15 +278,21 @@ class CleanCommand extends Command
/** /**
* @param InputInterface $input * @param InputInterface $input
* @param OutputInterface $output * @param OutputInterface $output
* @return int
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$this->setupConsole($input, $output); $this->setupConsole($input, $output);
$this->cleanPaths(); $this->cleanPaths();
return 0;
} }
private function cleanPaths() /**
* @return void
*/
private function cleanPaths(): void
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<red>DELETING</red>'); $this->output->writeln('<red>DELETING</red>');
@@ -305,8 +318,9 @@ class CleanCommand extends Command
* *
* @param InputInterface $input * @param InputInterface $input
* @param OutputInterface $output * @param OutputInterface $output
* @return void
*/ */
public function setupConsole(InputInterface $input, OutputInterface $output) public function setupConsole(InputInterface $input, OutputInterface $output): void
{ {
$this->input = $input; $this->input = $input;
$this->output = $output; $this->output = $output;

View File

@@ -13,9 +13,16 @@ use Grav\Common\Cache;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
/**
* Class ClearCacheCommand
* @package Grav\Console\Cli
*/
class ClearCacheCommand extends ConsoleCommand class ClearCacheCommand extends ConsoleCommand
{ {
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('cache') ->setName('cache')
@@ -32,16 +39,23 @@ class ClearCacheCommand extends ConsoleCommand
->setHelp('The <info>cache</info> command allows you to interact with Grav cache'); ->setHelp('The <info>cache</info> command allows you to interact with Grav cache');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->initializePlugins(); $this->initializePlugins();
$this->cleanPaths(); $this->cleanPaths();
return 0;
} }
/** /**
* loops over the array of paths and deletes the files/folders * loops over the array of paths and deletes the files/folders
*
* @return void
*/ */
private function cleanPaths() private function cleanPaths(): void
{ {
$this->output->writeln(''); $this->output->writeln('');

View File

@@ -12,9 +12,16 @@ namespace Grav\Console\Cli;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
/**
* Class ComposerCommand
* @package Grav\Console\Cli
*/
class ComposerCommand extends ConsoleCommand class ComposerCommand extends ConsoleCommand
{ {
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('composer') ->setName('composer')
@@ -34,7 +41,10 @@ class ComposerCommand extends ConsoleCommand
->setHelp('The <info>composer</info> command updates the composer vendor dependencies needed by Grav'); ->setHelp('The <info>composer</info> command updates the composer vendor dependencies needed by Grav');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$action = $this->input->getOption('install') ? 'install' : ($this->input->getOption('update') ? 'update' : 'install'); $action = $this->input->getOption('install') ? 'install' : ($this->input->getOption('update') ? 'update' : 'install');
@@ -45,5 +55,7 @@ class ComposerCommand extends ConsoleCommand
// Updates composer first // Updates composer first
$this->output->writeln("\nInstalling vendor dependencies"); $this->output->writeln("\nInstalling vendor dependencies");
$this->output->writeln($this->composerUpdate(GRAV_ROOT, $action)); $this->output->writeln($this->composerUpdate(GRAV_ROOT, $action));
return 0;
} }
} }

View File

@@ -14,6 +14,10 @@ use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
/**
* Class InstallCommand
* @package Grav\Console\Cli
*/
class InstallCommand extends ConsoleCommand class InstallCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -28,7 +32,10 @@ class InstallCommand extends ConsoleCommand
/** @var string */ /** @var string */
protected $user_path; protected $user_path;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('install') ->setName('install')
@@ -47,7 +54,10 @@ class InstallCommand extends ConsoleCommand
->setHelp('The <info>install</info> command installs the dependencies needed by Grav. Optionally can create symbolic links'); ->setHelp('The <info>install</info> command installs the dependencies needed by Grav. Optionally can create symbolic links');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$dependencies_file = '.dependencies'; $dependencies_file = '.dependencies';
$this->destination = $this->input->getArgument('destination') ?: ROOT_DIR; $this->destination = $this->input->getArgument('destination') ?: ROOT_DIR;
@@ -72,38 +82,46 @@ class InstallCommand extends ConsoleCommand
$this->output->writeln('<yellow>HINT</yellow> <info>Are you trying to install Grav? Grav is already installed. You need to run this command only if you download a skeleton from GitHub directly.'); $this->output->writeln('<yellow>HINT</yellow> <info>Are you trying to install Grav? Grav is already installed. You need to run this command only if you download a skeleton from GitHub directly.');
} }
return; return 1;
} }
$this->config = $file->content(); $this->config = $file->content();
$file->free(); $file->free();
// If yaml config, process // If no config, fail.
if ($this->config) { if (!$this->config) {
if (!$this->input->getOption('symlink')) {
// Updates composer first
$this->output->writeln("\nInstalling vendor dependencies");
$this->output->writeln($this->composerUpdate(GRAV_ROOT, 'install'));
$this->gitclone();
} else {
$this->symlink();
}
} else {
$this->output->writeln('<red>ERROR</red> invalid YAML in ' . $dependencies_file); $this->output->writeln('<red>ERROR</red> invalid YAML in ' . $dependencies_file);
return 1;
} }
$error = 0;
if (!$this->input->getOption('symlink')) {
// Updates composer first
$this->output->writeln("\nInstalling vendor dependencies");
$this->output->writeln($this->composerUpdate(GRAV_ROOT, 'install'));
$error = $this->gitclone();
} else {
$error = $this->symlink();
}
return $error;
} }
/** /**
* Clones from Git * Clones from Git
*
* @return int
*/ */
private function gitclone() private function gitclone(): int
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<green>Cloning Bits</green>'); $this->output->writeln('<green>Cloning Bits</green>');
$this->output->writeln('============'); $this->output->writeln('============');
$this->output->writeln(''); $this->output->writeln('');
$error = 0;
foreach ($this->config['git'] as $repo => $data) { foreach ($this->config['git'] as $repo => $data) {
$this->destination = rtrim($this->destination, DS); $this->destination = rtrim($this->destination, DS);
$path = $this->destination . DS . $data['path']; $path = $this->destination . DS . $data['path'];
@@ -114,6 +132,7 @@ class InstallCommand extends ConsoleCommand
$this->output->writeln('<green>SUCCESS</green> cloned <magenta>' . $data['url'] . '</magenta> -> <cyan>' . $path . '</cyan>'); $this->output->writeln('<green>SUCCESS</green> cloned <magenta>' . $data['url'] . '</magenta> -> <cyan>' . $path . '</cyan>');
} else { } else {
$this->output->writeln('<red>ERROR</red> cloning <magenta>' . $data['url']); $this->output->writeln('<red>ERROR</red> cloning <magenta>' . $data['url']);
$error = 1;
} }
$this->output->writeln(''); $this->output->writeln('');
@@ -122,12 +141,16 @@ class InstallCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
} }
} }
return $error;
} }
/** /**
* Symlinks * Symlinks
*
* @return int
*/ */
private function symlink() private function symlink(): int
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<green>Symlinking Bits</green>'); $this->output->writeln('<green>Symlinking Bits</green>');
@@ -137,9 +160,11 @@ class InstallCommand extends ConsoleCommand
if (!$this->local_config) { if (!$this->local_config) {
$this->output->writeln('<red>No local configuration available, aborting...</red>'); $this->output->writeln('<red>No local configuration available, aborting...</red>');
$this->output->writeln(''); $this->output->writeln('');
return;
return 1;
} }
$error = 0;
exec('cd ' . $this->destination); exec('cd ' . $this->destination);
foreach ($this->config['links'] as $repo => $data) { foreach ($this->config['links'] as $repo => $data) {
$repos = (array) $this->local_config[$data['scm'] . '_repos']; $repos = (array) $this->local_config[$data['scm'] . '_repos'];
@@ -157,16 +182,17 @@ class InstallCommand extends ConsoleCommand
if (!$from) { if (!$from) {
$this->output->writeln('<red>source for ' . $data['src'] . ' does not exists, skipping...</red>'); $this->output->writeln('<red>source for ' . $data['src'] . ' does not exists, skipping...</red>');
$this->output->writeln(''); $this->output->writeln('');
$error = 1;
} elseif (!file_exists($to)) {
symlink($from, $to);
$this->output->writeln('<green>SUCCESS</green> symlinked <magenta>' . $data['src'] . '</magenta> -> <cyan>' . $data['path'] . '</cyan>');
$this->output->writeln('');
} else { } else {
if (!file_exists($to)) { $this->output->writeln('<red>destination: ' . $to . ' already exists, skipping...</red>');
symlink($from, $to); $this->output->writeln('');
$this->output->writeln('<green>SUCCESS</green> symlinked <magenta>' . $data['src'] . '</magenta> -> <cyan>' . $data['path'] . '</cyan>');
$this->output->writeln('');
} else {
$this->output->writeln('<red>destination: ' . $to . ' already exists, skipping...</red>');
$this->output->writeln('');
}
} }
} }
return $error;
} }
} }

View File

@@ -9,15 +9,23 @@
namespace Grav\Console\Cli; namespace Grav\Console\Cli;
use DateTime;
use Grav\Common\Grav; use Grav\Common\Grav;
use Grav\Common\Helpers\LogViewer; use Grav\Common\Helpers\LogViewer;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Class LogViewerCommand
* @package Grav\Console\Cli
*/
class LogViewerCommand extends ConsoleCommand class LogViewerCommand extends ConsoleCommand
{ {
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('logviewer') ->setName('logviewer')
@@ -34,14 +42,17 @@ class LogViewerCommand extends ConsoleCommand
'number of lines (default = 10)' 'number of lines (default = 10)'
) )
->setDescription('Display the last few entries of Grav log') ->setDescription('Display the last few entries of Grav log')
->setHelp("Display the last few entries of Grav log"); ->setHelp('Display the last few entries of Grav log');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$file = $this->input->getOption('file') ?? 'grav.log'; $file = $this->input->getOption('file') ?? 'grav.log';
$lines = $this->input->getOption('lines') ?? 20; $lines = $this->input->getOption('lines') ?? 20;
$verbose = $this->input->getOption('verbose', false); $verbose = $this->input->getOption('verbose') ?? false;
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
@@ -53,29 +64,33 @@ class LogViewerCommand extends ConsoleCommand
$viewer = new LogViewer(); $viewer = new LogViewer();
$grav = Grav::instance(); $grav = Grav::instance();
$logfile = $grav['locator']->findResource('log://' . $file); $logfile = $grav['locator']->findResource('log://' . $file);
if (!$logfile) {
if ($logfile) {
$rows = $viewer->objectTail($logfile, $lines, true);
foreach ($rows as $log) {
$date = $log['date'];
$level_color = LogViewer::levelColor($log['level']);
if ($date instanceof \DateTime) {
$output = "<yellow>{$log['date']->format('Y-m-d h:i:s')}</yellow> [<{$level_color}>{$log['level']}</{$level_color}>]";
if ($log['trace'] && $verbose) {
$output .= " <white>{$log['message']}</white>\n";
foreach ((array) $log['trace'] as $index => $tracerow) {
$output .= "<white>{$index}</white>${tracerow}\n";
}
} else {
$output .= " {$log['message']}";
}
$io->writeln($output);
}
}
} else {
$io->error('cannot find the log file: logs/' . $file); $io->error('cannot find the log file: logs/' . $file);
return 1;
} }
$rows = $viewer->objectTail($logfile, $lines, true);
foreach ($rows as $log) {
$date = $log['date'];
$level_color = LogViewer::levelColor($log['level']);
if ($date instanceof DateTime) {
$output = "<yellow>{$log['date']->format('Y-m-d h:i:s')}</yellow> [<{$level_color}>{$log['level']}</{$level_color}>]";
if ($log['trace'] && $verbose) {
$output .= " <white>{$log['message']}</white>\n";
foreach ((array) $log['trace'] as $index => $tracerow) {
$output .= "<white>{$index}</white>${tracerow}\n";
}
} else {
$output .= " {$log['message']}";
}
$io->writeln($output);
}
}
return 0;
} }
} }

View File

@@ -14,9 +14,16 @@ use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
/**
* Class NewProjectCommand
* @package Grav\Console\Cli
*/
class NewProjectCommand extends ConsoleCommand class NewProjectCommand extends ConsoleCommand
{ {
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('new-project') ->setName('new-project')
@@ -36,7 +43,10 @@ class NewProjectCommand extends ConsoleCommand
->setHelp("The <info>new-project</info> command is a combination of the `setup` and `install` commands.\nCreates a new Grav instance and performs the installation of all the required dependencies."); ->setHelp("The <info>new-project</info> command is a combination of the `setup` and `install` commands.\nCreates a new Grav instance and performs the installation of all the required dependencies.");
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$sandboxCommand = $this->getApplication()->find('sandbox'); $sandboxCommand = $this->getApplication()->find('sandbox');
$installCommand = $this->getApplication()->find('install'); $installCommand = $this->getApplication()->find('install');
@@ -53,7 +63,11 @@ class NewProjectCommand extends ConsoleCommand
'-s' => $this->input->getOption('symlink') '-s' => $this->input->getOption('symlink')
]); ]);
$sandboxCommand->run($sandboxArguments, $this->output); $error = $sandboxCommand->run($sandboxArguments, $this->output);
$installCommand->run($installArguments, $this->output); if ($error === 0) {
$error = $installCommand->run($installArguments, $this->output);
}
return $error;
} }
} }

View File

@@ -17,7 +17,13 @@ use Grav\Common\Page\Pages;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use RocketTheme\Toolbox\Event\Event; use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use function in_array;
use function is_object;
/**
* Class PageSystemValidatorCommand
* @package Grav\Console\Cli
*/
class PageSystemValidatorCommand extends ConsoleCommand class PageSystemValidatorCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -125,7 +131,10 @@ class PageSystemValidatorCommand extends ConsoleCommand
/** @var Grav */ /** @var Grav */
protected $grav; protected $grav;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('page-system-validator') ->setName('page-system-validator')
@@ -135,7 +144,10 @@ class PageSystemValidatorCommand extends ConsoleCommand
->setHelp('The <info>page-system-validator</info> command can be used to test the pages before and after upgrade'); ->setHelp('The <info>page-system-validator</info> command can be used to test the pages before and after upgrade');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->setLanguage('en'); $this->setLanguage('en');
$this->initializePages(); $this->initializePages();
@@ -182,8 +194,13 @@ class PageSystemValidatorCommand extends ConsoleCommand
$this->output->writeln('<green>page-system-validator [-r|--record] [-c|--check]</green>'); $this->output->writeln('<green>page-system-validator [-r|--record] [-c|--check]</green>');
} }
$this->output->writeln(''); $this->output->writeln('');
return 0;
} }
/**
* @return array
*/
private function record() private function record()
{ {
/** @var Pages $pages */ /** @var Pages $pages */
@@ -243,7 +260,12 @@ class PageSystemValidatorCommand extends ConsoleCommand
return $results; return $results;
} }
private function check(array $old, array $new) /**
* @param array $old
* @param array $new
* @return array
*/
private function check(array $old, array $new): array
{ {
$errors = []; $errors = [];
foreach ($old as $path => $page) { foreach ($old as $path => $page) {

View File

@@ -11,9 +11,15 @@ namespace Grav\Console\Cli;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use Grav\Common\Filesystem\Folder; use Grav\Common\Filesystem\Folder;
use RuntimeException;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use function count;
/**
* Class SandboxCommand
* @package Grav\Console\Cli
*/
class SandboxCommand extends ConsoleCommand class SandboxCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -61,7 +67,10 @@ class SandboxCommand extends ConsoleCommand
/** @var string */ /** @var string */
protected $destination; protected $destination;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('sandbox') ->setName('sandbox')
@@ -81,38 +90,52 @@ class SandboxCommand extends ConsoleCommand
$source = getcwd(); $source = getcwd();
if ($source === false) { if ($source === false) {
throw new \RuntimeException('Internal Error'); throw new RuntimeException('Internal Error');
} }
$this->source = $source; $this->source = $source;
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->destination = $this->input->getArgument('destination'); $this->destination = $this->input->getArgument('destination');
// Symlink the Core Stuff // Create Some core stuff if it doesn't exist
if ($this->input->getOption('symlink')) { $error = $this->createDirectories();
// Create Some core stuff if it doesn't exist if ($error) {
$this->createDirectories(); return $error;
// Loop through the symlink mappings and create the symlinks
$this->symlink();
// Copy the Core STuff
} else {
// Create Some core stuff if it doesn't exist
$this->createDirectories();
// Loop through the symlink mappings and copy what otherwise would be symlinks
$this->copy();
} }
$this->pages(); // Copy files or create symlinks
$this->initFiles(); $error = $this->input->getOption('symlink') ? $this->symlink() : $this->copy();
$this->perms(); if ($error) {
return $error;
}
$error = $this->pages();
if ($error) {
return $error;
}
$error = $this->initFiles();
if ($error) {
return $error;
}
$error = $this->perms();
if ($error) {
return $error;
}
return 0;
} }
private function createDirectories() /**
* @return int
*/
private function createDirectories(): int
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<comment>Creating Directories</comment>'); $this->output->writeln('<comment>Creating Directories</comment>');
@@ -133,9 +156,14 @@ class SandboxCommand extends ConsoleCommand
if (!$dirs_created) { if (!$dirs_created) {
$this->output->writeln(' <red>Directories already exist</red>'); $this->output->writeln(' <red>Directories already exist</red>');
} }
return 0;
} }
private function copy() /**
* @return int
*/
private function copy(): int
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<comment>Copying Files</comment>'); $this->output->writeln('<comment>Copying Files</comment>');
@@ -152,9 +180,14 @@ class SandboxCommand extends ConsoleCommand
$this->output->writeln(' <cyan>' . $source . '</cyan> <comment>-></comment> ' . $to); $this->output->writeln(' <cyan>' . $source . '</cyan> <comment>-></comment> ' . $to);
@Folder::rcopy($from, $to); @Folder::rcopy($from, $to);
} }
return 0;
} }
private function symlink() /**
* @return int
*/
private function symlink(): int
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<comment>Resetting Symbolic Links</comment>'); $this->output->writeln('<comment>Resetting Symbolic Links</comment>');
@@ -177,11 +210,39 @@ class SandboxCommand extends ConsoleCommand
} }
symlink($from, $to); symlink($from, $to);
} }
return 0;
} }
private function initFiles() /**
* @return int
*/
private function pages(): int
{ {
$this->check(); $this->output->writeln('');
$this->output->writeln('<comment>Pages Initializing</comment>');
// get pages files and initialize if no pages exist
$pages_dir = $this->destination . '/user/pages';
$pages_files = array_diff(scandir($pages_dir), ['..', '.']);
if (count($pages_files) === 0) {
$destination = $this->source . '/user/pages';
Folder::rcopy($destination, $pages_dir);
$this->output->writeln(' <cyan>' . $destination . '</cyan> <comment>-></comment> Created');
}
return 0;
}
/**
* @return int
*/
private function initFiles(): int
{
if (!$this->check()) {
return 1;
}
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<comment>File Initializing</comment>'); $this->output->writeln('<comment>File Initializing</comment>');
@@ -206,25 +267,14 @@ class SandboxCommand extends ConsoleCommand
if (!$files_init) { if (!$files_init) {
$this->output->writeln(' <red>Files already exist</red>'); $this->output->writeln(' <red>Files already exist</red>');
} }
return 0;
} }
private function pages() /**
{ * @return int
$this->output->writeln(''); */
$this->output->writeln('<comment>Pages Initializing</comment>'); private function perms(): int
// get pages files and initialize if no pages exist
$pages_dir = $this->destination . '/user/pages';
$pages_files = array_diff(scandir($pages_dir), ['..', '.']);
if (\count($pages_files) === 0) {
$destination = $this->source . '/user/pages';
Folder::rcopy($destination, $pages_dir);
$this->output->writeln(' <cyan>' . $destination . '</cyan> <comment>-></comment> Created');
}
}
private function perms()
{ {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<comment>Permissions Initializing</comment>'); $this->output->writeln('<comment>Permissions Initializing</comment>');
@@ -239,14 +289,19 @@ class SandboxCommand extends ConsoleCommand
} }
$this->output->writeln(""); $this->output->writeln("");
return 0;
} }
private function check() /**
* @return bool
*/
private function check(): bool
{ {
$success = true; $success = true;
if (!file_exists($this->destination)) { if (!file_exists($this->destination)) {
$this->output->writeln(' file: <red>$this->destination</red> does not exist!'); $this->output->writeln(' file: <red>' . $this->destination . '</red> does not exist!');
$success = false; $success = false;
} }
@@ -267,7 +322,8 @@ class SandboxCommand extends ConsoleCommand
if (!$success) { if (!$success) {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<comment>install should be run with --symlink|--s to symlink first</comment>'); $this->output->writeln('<comment>install should be run with --symlink|--s to symlink first</comment>');
exit;
} }
return $success;
} }
} }

View File

@@ -18,10 +18,18 @@ use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function is_null;
/**
* Class SchedulerCommand
* @package Grav\Console\Cli
*/
class SchedulerCommand extends ConsoleCommand class SchedulerCommand extends ConsoleCommand
{ {
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('scheduler') ->setName('scheduler')
@@ -53,11 +61,13 @@ class SchedulerCommand extends ConsoleCommand
->setHelp("Running without any options will force the Scheduler to run through it's jobs and process them"); ->setHelp("Running without any options will force the Scheduler to run through it's jobs and process them");
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->initializePlugins(); $this->initializePlugins();
// error_reporting(1);
$grav = Grav::instance(); $grav = Grav::instance();
$grav['backups']->init(); $grav['backups']->init();
@@ -68,6 +78,7 @@ class SchedulerCommand extends ConsoleCommand
$this->setHelp('foo'); $this->setHelp('foo');
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
$error = 0;
if ($this->input->getOption('jobs')) { if ($this->input->getOption('jobs')) {
// Show jobs list // Show jobs list
@@ -159,6 +170,7 @@ class SchedulerCommand extends ConsoleCommand
if ($job->isSuccessful()) { if ($job->isSuccessful()) {
$io->success('Job ran successfully...'); $io->success('Job ran successfully...');
} else { } else {
$error = 1;
$io->error('Job failed to run successfully...'); $io->error('Job failed to run successfully...');
} }
@@ -168,6 +180,7 @@ class SchedulerCommand extends ConsoleCommand
$this->output->write($output); $this->output->write($output);
} }
} else { } else {
$error = 1;
$io->error('Could not find a job with id: ' . $jobid); $io->error('Could not find a job with id: ' . $jobid);
} }
} elseif ($this->input->getOption('install')) { } elseif ($this->input->getOption('install')) {
@@ -180,6 +193,7 @@ class SchedulerCommand extends ConsoleCommand
$verb = 'reinstall'; $verb = 'reinstall';
} else { } else {
$user = $scheduler->whoami(); $user = $scheduler->whoami();
$error = 1;
$io->error('Can\'t find a crontab for ' . $user . '. You need to set up Grav\'s Scheduler in your crontab'); $io->error('Can\'t find a crontab for ' . $user . '. You need to set up Grav\'s Scheduler in your crontab');
} }
if (!Utils::isWindows()) { if (!Utils::isWindows()) {
@@ -199,5 +213,7 @@ class SchedulerCommand extends ConsoleCommand
$io->text($scheduler->getVerboseOutput()); $io->text($scheduler->getVerboseOutput());
} }
} }
return $error;
} }
} }

View File

@@ -14,13 +14,21 @@ use Grav\Common\Security;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function count;
/**
* Class SecurityCommand
* @package Grav\Console\Cli
*/
class SecurityCommand extends ConsoleCommand class SecurityCommand extends ConsoleCommand
{ {
/** @var ProgressBar $progress */ /** @var ProgressBar $progress */
protected $progress; protected $progress;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('security') ->setName('security')
@@ -28,13 +36,16 @@ class SecurityCommand extends ConsoleCommand
->setHelp('The <info>security</info> runs various security checks on your Grav site'); ->setHelp('The <info>security</info> runs various security checks on your Grav site');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->initializePages(); $this->initializePages();
/** @var Grav $grav */ /** @var Grav $grav */
$grav = Grav::instance(); $grav = Grav::instance();
$this->progress = new ProgressBar($this->output, \count($grav['pages']->routes()) - 1); $this->progress = new ProgressBar($this->output, count($grav['pages']->routes()) - 1);
$this->progress->setFormat('Scanning <cyan>%current%</cyan> pages [<green>%bar%</green>] <white>%percent:3s%%</white> %elapsed:6s%'); $this->progress->setFormat('Scanning <cyan>%current%</cyan> pages [<green>%bar%</green>] <white>%percent:3s%%</white> %elapsed:6s%');
$this->progress->setBarWidth(100); $this->progress->setBarWidth(100);
@@ -45,28 +56,33 @@ class SecurityCommand extends ConsoleCommand
$io->newline(2); $io->newline(2);
$error = 0;
if (!empty($output)) { if (!empty($output)) {
$counter = 1; $counter = 1;
foreach ($output as $route => $results) { foreach ($output as $route => $results) {
$results_parts = array_map(function ($value, $key) { $results_parts = array_map(static function ($value, $key) {
return $key.': \''.$value . '\''; return $key.': \''.$value . '\'';
}, array_values($results), array_keys($results)); }, array_values($results), array_keys($results));
$io->writeln($counter++ .' - <cyan>' . $route . '</cyan> → <red>' . implode(', ', $results_parts) . '</red>'); $io->writeln($counter++ .' - <cyan>' . $route . '</cyan> → <red>' . implode(', ', $results_parts) . '</red>');
} }
$io->error('Security Scan complete: ' . \count($output) . ' potential XSS issues found...'); $error = 1;
$io->error('Security Scan complete: ' . count($output) . ' potential XSS issues found...');
} else { } else {
$io->success('Security Scan complete: No issues found...'); $io->success('Security Scan complete: No issues found...');
} }
$io->newline(1); $io->newline(1);
return $error;
} }
/** /**
* @param array $args * @param array $args
* @return void
*/ */
public function outputProgress($args) public function outputProgress($args): void
{ {
switch ($args['type']) { switch ($args['type']) {
case 'count': case 'count':

View File

@@ -16,6 +16,10 @@ use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
/**
* Class ServerCommand
* @package Grav\Console\Cli
*/
class ServerCommand extends ConsoleCommand class ServerCommand extends ConsoleCommand
{ {
const SYMFONY_SERVER = 'Symfony Server'; const SYMFONY_SERVER = 'Symfony Server';
@@ -28,7 +32,10 @@ class ServerCommand extends ConsoleCommand
/** @var SymfonyStyle */ /** @var SymfonyStyle */
protected $io; protected $io;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('server') ->setName('server')
@@ -39,7 +46,10 @@ class ServerCommand extends ConsoleCommand
->setHelp("Runs built-in web-server, Symfony first, then tries PHP's"); ->setHelp("Runs built-in web-server, Symfony first, then tries PHP's");
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$io = $this->io = new SymfonyStyle($this->input, $this->output); $io = $this->io = new SymfonyStyle($this->input, $this->output);
@@ -59,7 +69,6 @@ class ServerCommand extends ConsoleCommand
$this->ip = '127.0.0.1'; $this->ip = '127.0.0.1';
$this->port = (int)($this->input->getOption('port') ?? 8000); $this->port = (int)($this->input->getOption('port') ?? 8000);
// Get an open port // Get an open port
while (!$this->portAvailable($this->ip, $this->port)) { while (!$this->portAvailable($this->ip, $this->port)) {
$this->port++; $this->port++;
@@ -80,6 +89,7 @@ class ServerCommand extends ConsoleCommand
unset($commands[self::SYMFONY_SERVER]); unset($commands[self::SYMFONY_SERVER]);
} }
$error = 0;
foreach ($commands as $name => $command) { foreach ($commands as $name => $command) {
$process = $this->runProcess($name, $command); $process = $this->runProcess($name, $command);
@@ -92,18 +102,26 @@ class ServerCommand extends ConsoleCommand
($name === self::SYMFONY_SERVER && $force_symfony) || ($name === self::SYMFONY_SERVER && $force_symfony) ||
($name === self::PHP_SERVER) ($name === self::PHP_SERVER)
)) { )) {
$error = 1;
$io->error('Could not start ' . $name); $io->error('Could not start ' . $name);
} }
} }
return $error;
} }
/**
* @param string $name
* @param string $cmd
* @return Process
*/
protected function runProcess($name, $cmd) protected function runProcess($name, $cmd)
{ {
$process = new Process($cmd); $process = new Process([$cmd]);
$process->setTimeout(0); $process->setTimeout(0);
$process->start(); $process->start();
if ($name == self::SYMFONY_SERVER && Utils::contains($process->getErrorOutput(), 'symfony: not found')) { if ($name === self::SYMFONY_SERVER && Utils::contains($process->getErrorOutput(), 'symfony: not found')) {
$this->io->error('The symfony binary could not be found, please install the CLI tools: https://symfony.com/download'); $this->io->error('The symfony binary could not be found, please install the CLI tools: https://symfony.com/download');
$this->io->warning('Falling back to PHP web server...'); $this->io->warning('Falling back to PHP web server...');
} }
@@ -126,7 +144,7 @@ class ServerCommand extends ConsoleCommand
* @param int $port * @param int $port
* @return bool * @return bool
*/ */
protected function portAvailable($ip, $port) protected function portAvailable($ip, $port): bool
{ {
$fp = @fsockopen($ip, $port, $errno, $errstr, 0.1); $fp = @fsockopen($ip, $port, $errno, $errstr, 0.1);
if (!$fp) { if (!$fp) {
@@ -134,6 +152,7 @@ class ServerCommand extends ConsoleCommand
} }
fclose($fp); fclose($fp);
return false; return false;
} }
} }

View File

@@ -14,9 +14,16 @@ use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Class YamlLinterCommand
* @package Grav\Console\Cli
*/
class YamlLinterCommand extends ConsoleCommand class YamlLinterCommand extends ConsoleCommand
{ {
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('yamllinter') ->setName('yamllinter')
@@ -39,15 +46,19 @@ class YamlLinterCommand extends ConsoleCommand
'Go through specific folder' 'Go through specific folder'
) )
->setDescription('Checks various files for YAML errors') ->setDescription('Checks various files for YAML errors')
->setHelp("Checks various files for YAML errors"); ->setHelp('Checks various files for YAML errors');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
$io->title('Yaml Linter'); $io->title('Yaml Linter');
$error = 0;
if ($this->input->getOption('all')) { if ($this->input->getOption('all')) {
$io->section('All'); $io->section('All');
$errors = YamlLinter::lint(''); $errors = YamlLinter::lint('');
@@ -55,6 +66,7 @@ class YamlLinterCommand extends ConsoleCommand
if (empty($errors)) { if (empty($errors)) {
$io->success('No YAML Linting issues found'); $io->success('No YAML Linting issues found');
} else { } else {
$error = 1;
$this->displayErrors($errors, $io); $this->displayErrors($errors, $io);
} }
} elseif ($folder = $this->input->getOption('folder')) { } elseif ($folder = $this->input->getOption('folder')) {
@@ -64,6 +76,7 @@ class YamlLinterCommand extends ConsoleCommand
if (empty($errors)) { if (empty($errors)) {
$io->success('No YAML Linting issues found'); $io->success('No YAML Linting issues found');
} else { } else {
$error = 1;
$this->displayErrors($errors, $io); $this->displayErrors($errors, $io);
} }
} else { } else {
@@ -73,6 +86,7 @@ class YamlLinterCommand extends ConsoleCommand
if (empty($errors)) { if (empty($errors)) {
$io->success('No YAML Linting issues with configuration'); $io->success('No YAML Linting issues with configuration');
} else { } else {
$error = 1;
$this->displayErrors($errors, $io); $this->displayErrors($errors, $io);
} }
@@ -82,6 +96,7 @@ class YamlLinterCommand extends ConsoleCommand
if (empty($errors)) { if (empty($errors)) {
$io->success('No YAML Linting issues with pages'); $io->success('No YAML Linting issues with pages');
} else { } else {
$error = 1;
$this->displayErrors($errors, $io); $this->displayErrors($errors, $io);
} }
@@ -91,12 +106,20 @@ class YamlLinterCommand extends ConsoleCommand
if (empty($errors)) { if (empty($errors)) {
$io->success('No YAML Linting issues with blueprints'); $io->success('No YAML Linting issues with blueprints');
} else { } else {
$error = 1;
$this->displayErrors($errors, $io); $this->displayErrors($errors, $io);
} }
} }
return $error;
} }
protected function displayErrors($errors, SymfonyStyle $io) /**
* @param array $errors
* @param SymfonyStyle $io
* @return void
*/
protected function displayErrors($errors, SymfonyStyle $io): void
{ {
$io->error('YAML Linting issues found...'); $io->error('YAML Linting issues found...');
foreach ($errors as $path => $error) { foreach ($errors as $path => $error) {

View File

@@ -11,13 +11,16 @@ namespace Grav\Console;
use Grav\Common\Grav; use Grav\Common\Grav;
use Grav\Common\Language\Language; use Grav\Common\Language\Language;
use Grav\Common\Page\Page;
use Grav\Common\Processors\InitializeProcessor; use Grav\Common\Processors\InitializeProcessor;
use RocketTheme\Toolbox\Event\Event; use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
/**
* Class ConsoleCommand
* @package Grav\Console
*/
class ConsoleCommand extends Command class ConsoleCommand extends Command
{ {
use ConsoleTrait; use ConsoleTrait;
@@ -38,14 +41,19 @@ class ConsoleCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$this->setupConsole($input, $output); $this->setupConsole($input, $output);
$this->serve();
return $this->serve();
} }
/** /**
* Override with your implementation. * Override with your implementation.
*
* @return int
*/ */
protected function serve() protected function serve()
{ {
// Return error.
return 1;
} }
/** /**
@@ -73,6 +81,7 @@ class ConsoleCommand extends Command
* Set language to be used in CLI. * Set language to be used in CLI.
* *
* @param string|null $code * @param string|null $code
* @return $this
*/ */
final protected function setLanguage(string $code = null) final protected function setLanguage(string $code = null)
{ {
@@ -88,6 +97,8 @@ class ConsoleCommand extends Command
$language->setActive($language->getDefault()); $language->setActive($language->getDefault());
} }
} }
return $this;
} }
/** /**
@@ -178,6 +189,9 @@ class ConsoleCommand extends Command
return $this; return $this;
} }
/**
* @return void
*/
protected function displayGPMRelease() protected function displayGPMRelease()
{ {
$this->output->writeln(''); $this->output->writeln('');

View File

@@ -9,10 +9,10 @@
namespace Grav\Console; namespace Grav\Console;
use Exception;
use Grav\Common\Cache; use Grav\Common\Cache;
use Grav\Common\Grav; use Grav\Common\Grav;
use Grav\Common\Composer; use Grav\Common\Composer;
use Grav\Common\GravTrait;
use Grav\Console\Cli\ClearCacheCommand; use Grav\Console\Cli\ClearCacheCommand;
use RocketTheme\Toolbox\File\YamlFile; use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Formatter\OutputFormatterStyle;
@@ -20,6 +20,10 @@ use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
/**
* Trait ConsoleTrait
* @package Grav\Console
*/
trait ConsoleTrait trait ConsoleTrait
{ {
/** @var string */ /** @var string */
@@ -39,6 +43,7 @@ trait ConsoleTrait
* *
* @param InputInterface $input * @param InputInterface $input
* @param OutputInterface $output * @param OutputInterface $output
* @return void
*/ */
public function setupConsole(InputInterface $input, OutputInterface $output) public function setupConsole(InputInterface $input, OutputInterface $output)
{ {
@@ -61,6 +66,7 @@ trait ConsoleTrait
/** /**
* @param string $path * @param string $path
* @return void
*/ */
public function isGravInstance($path) public function isGravInstance($path)
{ {
@@ -89,6 +95,11 @@ trait ConsoleTrait
} }
} }
/**
* @param string $path
* @param string $action
* @return string|false
*/
public function composerUpdate($path, $action = 'install') public function composerUpdate($path, $action = 'install')
{ {
$composer = Composer::getComposerExecutor(); $composer = Composer::getComposerExecutor();
@@ -100,7 +111,7 @@ trait ConsoleTrait
* @param array $all * @param array $all
* *
* @return int * @return int
* @throws \Exception * @throws Exception
*/ */
public function clearCache($all = []) public function clearCache($all = [])
{ {
@@ -113,6 +124,9 @@ trait ConsoleTrait
return $command->run($input, $this->output); return $command->run($input, $this->output);
} }
/**
* @return void
*/
public function invalidateCache() public function invalidateCache()
{ {
Cache::invalidateCache(); Cache::invalidateCache();
@@ -121,7 +135,7 @@ trait ConsoleTrait
/** /**
* Load the local config file * Load the local config file
* *
* @return mixed string the local config file name. false if local config does not exist * @return string|false The local config file name. false if local config does not exist
*/ */
public function loadLocalConfig() public function loadLocalConfig()
{ {

View File

@@ -9,6 +9,7 @@
namespace Grav\Console\Gpm; namespace Grav\Console\Gpm;
use Exception;
use Grav\Common\Cache; use Grav\Common\Cache;
use Grav\Common\Grav; use Grav\Common\Grav;
use Grav\Common\Filesystem\Folder; use Grav\Common\Filesystem\Folder;
@@ -16,11 +17,18 @@ use Grav\Common\GPM\GPM;
use Grav\Common\GPM\Installer; use Grav\Common\GPM\Installer;
use Grav\Common\GPM\Response; use Grav\Common\GPM\Response;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use RuntimeException;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function is_array;
use function is_callable;
/**
* Class DirectInstallCommand
* @package Grav\Console\Gpm
*/
class DirectInstallCommand extends ConsoleCommand class DirectInstallCommand extends ConsoleCommand
{ {
/** @var string */ /** @var string */
@@ -29,7 +37,10 @@ class DirectInstallCommand extends ConsoleCommand
/** @var string */ /** @var string */
protected $destination; protected $destination;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('direct-install') ->setName('direct-install')
@@ -57,15 +68,16 @@ class DirectInstallCommand extends ConsoleCommand
} }
/** /**
* @return bool * @return int
*/ */
protected function serve() protected function serve(): int
{ {
if (!class_exists(\ZipArchive::class)) { if (!class_exists(\ZipArchive::class)) {
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
$io->title('Direct Install'); $io->title('Direct Install');
$io->error('php-zip extension needs to be enabled!'); $io->error('php-zip extension needs to be enabled!');
exit;
return 1;
} }
// Making sure the destination is usable // Making sure the destination is usable
@@ -75,9 +87,9 @@ class DirectInstallCommand extends ConsoleCommand
!Installer::isValidDestination($this->destination, [Installer::EXISTS, Installer::IS_LINK]) !Installer::isValidDestination($this->destination, [Installer::EXISTS, Installer::IS_LINK])
) { ) {
$this->output->writeln('<red>ERROR</red>: ' . Installer::lastErrorMsg()); $this->output->writeln('<red>ERROR</red>: ' . Installer::lastErrorMsg());
exit;
}
return 1;
}
$this->all_yes = $this->input->getOption('all-yes'); $this->all_yes = $this->input->getOption('all-yes');
@@ -91,7 +103,8 @@ class DirectInstallCommand extends ConsoleCommand
if (!$answer) { if (!$answer) {
$this->output->writeln('exiting...'); $this->output->writeln('exiting...');
$this->output->writeln(''); $this->output->writeln('');
exit;
return 1;
} }
$tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true); $tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
@@ -105,11 +118,12 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->write(' |- Downloading package... 0%'); $this->output->write(' |- Downloading package... 0%');
try { try {
$zip = GPM::downloadPackage($package_file, $tmp_zip); $zip = GPM::downloadPackage($package_file, $tmp_zip);
} catch (\RuntimeException $e) { } catch (RuntimeException $e) {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln(" `- <red>ERROR: {$e->getMessage()}</red>"); $this->output->writeln(" `- <red>ERROR: {$e->getMessage()}</red>");
$this->output->writeln(''); $this->output->writeln('');
exit;
return 1;
} }
if ($zip) { if ($zip) {
@@ -138,7 +152,8 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->writeln(' |- Extracting package... <red>failed</red>'); $this->output->writeln(' |- Extracting package... <red>failed</red>');
Folder::delete($tmp_source); Folder::delete($tmp_source);
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
exit;
return 1;
} }
$this->output->write("\x0D"); $this->output->write("\x0D");
@@ -152,7 +167,8 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
Folder::delete($tmp_source); Folder::delete($tmp_source);
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
exit;
return 1;
} }
$blueprint = GPM::getBlueprints($extracted); $blueprint = GPM::getBlueprints($extracted);
@@ -181,7 +197,8 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
Folder::delete($tmp_source); Folder::delete($tmp_source);
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
exit;
return 1;
} }
} }
} }
@@ -196,7 +213,8 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
Folder::delete($tmp_source); Folder::delete($tmp_source);
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
exit;
return 1;
} }
$this->output->write("\x0D"); $this->output->write("\x0D");
@@ -204,7 +222,7 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->write(' |- Installing package... '); $this->output->write(' |- Installing package... ');
static::upgradeGrav($zip, $extracted); $this->upgradeGrav($zip, $extracted);
} else { } else {
$name = GPM::getPackageName($extracted); $name = GPM::getPackageName($extracted);
@@ -213,7 +231,8 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
Folder::delete($tmp_source); Folder::delete($tmp_source);
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
exit;
return 1;
} }
$install_path = GPM::getInstallPath($type, $name); $install_path = GPM::getInstallPath($type, $name);
@@ -222,14 +241,15 @@ class DirectInstallCommand extends ConsoleCommand
$this->output->write(' |- Checking destination... '); $this->output->write(' |- Checking destination... ');
Installer::isValidDestination(GRAV_ROOT . DS . $install_path); Installer::isValidDestination(GRAV_ROOT . DS . $install_path);
if (Installer::lastErrorCode() == Installer::IS_LINK) { if (Installer::lastErrorCode() === Installer::IS_LINK) {
$this->output->write("\x0D"); $this->output->write("\x0D");
$this->output->writeln(' |- Checking destination... <yellow>symbolic link</yellow>'); $this->output->writeln(' |- Checking destination... <yellow>symbolic link</yellow>');
$this->output->writeln(" '- <red>ERROR: symlink found...</red> <yellow>" . GRAV_ROOT . DS . $install_path . '</yellow>'); $this->output->writeln(" '- <red>ERROR: symlink found...</red> <yellow>" . GRAV_ROOT . DS . $install_path . '</yellow>');
$this->output->writeln(''); $this->output->writeln('');
Folder::delete($tmp_source); Folder::delete($tmp_source);
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
exit;
return 1;
} }
$this->output->write("\x0D"); $this->output->write("\x0D");
@@ -263,6 +283,9 @@ class DirectInstallCommand extends ConsoleCommand
} }
} else { } else {
$this->output->writeln(" '- <red>ERROR: ZIP package could not be found</red>"); $this->output->writeln(" '- <red>ERROR: ZIP package could not be found</red>");
Folder::delete($tmp_zip);
return 1;
} }
Folder::delete($tmp_zip); Folder::delete($tmp_zip);
@@ -270,9 +293,14 @@ class DirectInstallCommand extends ConsoleCommand
// clear cache after successful upgrade // clear cache after successful upgrade
$this->clearCache(); $this->clearCache();
return true; return 0;
} }
/**
* @param string $zip
* @param string $folder
* @param false $keepFolder
*/
private function upgradeGrav($zip, $folder, $keepFolder = false) private function upgradeGrav($zip, $folder, $keepFolder = false)
{ {
static $ignores = [ static $ignores = [
@@ -306,7 +334,7 @@ class DirectInstallCommand extends ConsoleCommand
Cache::clearCache(); Cache::clearCache();
} }
} catch (\Exception $e) { } catch (Exception $e) {
Installer::setError($e->getMessage()); Installer::setError($e->getMessage());
} }
} }

View File

@@ -14,9 +14,15 @@ use Grav\Common\GPM\GPM;
use Grav\Common\GPM\Remote\Packages; use Grav\Common\GPM\Remote\Packages;
use Grav\Common\Utils; use Grav\Common\Utils;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use League\CLImate\CLImate; use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle;
use function count;
/**
* Class IndexCommand
* @package Grav\Console\Gpm
*/
class IndexCommand extends ConsoleCommand class IndexCommand extends ConsoleCommand
{ {
/** @var Packages */ /** @var Packages */
@@ -28,7 +34,10 @@ class IndexCommand extends ConsoleCommand
/** @var array */ /** @var array */
protected $options; protected $options;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('index') ->setName('index')
@@ -86,7 +95,10 @@ class IndexCommand extends ConsoleCommand
; ;
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->options = $this->input->getOptions(); $this->options = $this->input->getOptions();
$this->gpm = new GPM($this->options['force']); $this->gpm = new GPM($this->options['force']);
@@ -95,28 +107,30 @@ class IndexCommand extends ConsoleCommand
$data = $this->filter($this->data); $data = $this->filter($this->data);
$climate = new CLImate; $io = new SymfonyStyle($this->input, $this->output);
$climate->extend('Grav\Console\TerminalObjects\Table');
if (!$data) { if (count($data) === 0) {
$this->output->writeln('No data was found in the GPM repository stored locally.'); $io->writeln('No data was found in the GPM repository stored locally.');
$this->output->writeln('Please try clearing cache and running the <green>bin/gpm index -f</green> command again'); $io->writeln('Please try clearing cache and running the <green>bin/gpm index -f</green> command again');
$this->output->writeln('If this doesn\'t work try tweaking your GPM system settings.'); $io->writeln('If this doesn\'t work try tweaking your GPM system settings.');
$this->output->writeln(''); $io->writeln('');
$this->output->writeln('For more help go to:'); $io->writeln('For more help go to:');
$this->output->writeln(' -> <yellow>https://learn.getgrav.org/troubleshooting/common-problems#cannot-connect-to-the-gpm</yellow>'); $io->writeln(' -> <yellow>https://learn.getgrav.org/troubleshooting/common-problems#cannot-connect-to-the-gpm</yellow>');
die; return 1;
} }
foreach ($data as $type => $packages) { foreach ($data as $type => $packages) {
$this->output->writeln('<green>' . strtoupper($type) . '</green> [ ' . \count($packages) . ' ]'); $io->writeln('<green>' . strtoupper($type) . '</green> [ ' . count($packages) . ' ]');
$packages = $this->sort($packages); $packages = $this->sort($packages);
if (!empty($packages)) { if (!empty($packages)) {
$table = []; $section = $this->output->section('Packages table');
$index = 0; $table = new Table($section);
$table->setHeaders(['Count', 'Name', 'Slug', 'Version', 'Installed']);
$index = 0;
foreach ($packages as $slug => $package) { foreach ($packages as $slug => $package) {
$row = [ $row = [
'Count' => $index++ + 1, 'Count' => $index++ + 1,
@@ -125,21 +139,24 @@ class IndexCommand extends ConsoleCommand
'Version'=> $this->version($package), 'Version'=> $this->version($package),
'Installed' => $this->installed($package) 'Installed' => $this->installed($package)
]; ];
$table[] = $row;
$table->addRow($row);
} }
$climate->table($table); $table->render();
} }
$this->output->writeln(''); $io->writeln('');
} }
$this->output->writeln('You can either get more informations about a package by typing:'); $io->writeln('You can either get more informations about a package by typing:');
$this->output->writeln(" <green>{$this->argv} info <cyan><package></cyan></green>"); $io->writeln(" <green>{$this->argv} info <cyan><package></cyan></green>");
$this->output->writeln(''); $io->writeln('');
$this->output->writeln('Or you can install a package by typing:'); $io->writeln('Or you can install a package by typing:');
$this->output->writeln(" <green>{$this->argv} install <cyan><package></cyan></green>"); $io->writeln(" <green>{$this->argv} install <cyan><package></cyan></green>");
$this->output->writeln(''); $io->writeln('');
return 0;
} }
/** /**
@@ -205,7 +222,7 @@ class IndexCommand extends ConsoleCommand
$this->options['desc'] $this->options['desc']
]; ];
if (\count(array_filter($filter))) { if (count(array_filter($filter))) {
foreach ($data as $type => $packages) { foreach ($data as $type => $packages) {
foreach ($packages as $slug => $package) { foreach ($packages as $slug => $package) {
$filter = true; $filter = true;

View File

@@ -15,6 +15,10 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion;
/**
* Class InfoCommand
* @package Grav\Console\Gpm
*/
class InfoCommand extends ConsoleCommand class InfoCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -26,7 +30,10 @@ class InfoCommand extends ConsoleCommand
/** @var string */ /** @var string */
protected $all_yes; protected $all_yes;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('info') ->setName('info')
@@ -48,13 +55,13 @@ class InfoCommand extends ConsoleCommand
'The package of which more informations are desired. Use the "index" command for a list of packages' 'The package of which more informations are desired. Use the "index" command for a list of packages'
) )
->setDescription('Shows more informations about a package') ->setDescription('Shows more informations about a package')
->setHelp('The <info>info</info> shows more informations about a package'); ->setHelp('The <info>info</info> shows more information about a package');
} }
/** /**
* @return int|null|void * @return int
*/ */
protected function serve() protected function serve(): int
{ {
$this->gpm = new GPM($this->input->getOption('force')); $this->gpm = new GPM($this->input->getOption('force'));
@@ -70,7 +77,8 @@ class InfoCommand extends ConsoleCommand
$this->output->writeln('You can list all the available packages by typing:'); $this->output->writeln('You can list all the available packages by typing:');
$this->output->writeln(" <green>{$this->argv} index</green>"); $this->output->writeln(" <green>{$this->argv} index</green>");
$this->output->writeln(''); $this->output->writeln('');
exit;
return 1;
} }
$this->output->writeln("Found package <cyan>'{$this->input->getArgument('package')}'</cyan> under the '<green>" . ucfirst($foundPackage->package_type) . "</green>' section"); $this->output->writeln("Found package <cyan>'{$this->input->getArgument('package')}'</cyan> under the '<green>" . ucfirst($foundPackage->package_type) . "</green>' section");
@@ -147,7 +155,7 @@ class InfoCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
foreach ($changelog as $version => $log) { foreach ($changelog as $version => $log) {
$title = $version . ' [' . $log['date'] . ']'; $title = $version . ' [' . $log['date'] . ']';
$content = preg_replace_callback('/\d\.\s\[\]\(#(.*)\)/', function ($match) { $content = preg_replace_callback('/\d\.\s\[\]\(#(.*)\)/', static function ($match) {
return "\n" . ucfirst($match[1]) . ':'; return "\n" . ucfirst($match[1]) . ':';
}, $log['content']); }, $log['content']);
@@ -176,5 +184,7 @@ class InfoCommand extends ConsoleCommand
} }
$this->output->writeln(''); $this->output->writeln('');
return 0;
} }
} }

View File

@@ -9,6 +9,7 @@
namespace Grav\Console\Gpm; namespace Grav\Console\Gpm;
use Exception;
use Grav\Common\Filesystem\Folder; use Grav\Common\Filesystem\Folder;
use Grav\Common\GPM\GPM; use Grav\Common\GPM\GPM;
use Grav\Common\GPM\Installer; use Grav\Common\GPM\Installer;
@@ -22,9 +23,15 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function array_key_exists;
use function count;
\define('GIT_REGEX', '/http[s]?:\/\/(?:.*@)?(github|bitbucket)(?:.org|.com)\/.*\/(.*)/'); \define('GIT_REGEX', '/http[s]?:\/\/(?:.*@)?(github|bitbucket)(?:.org|.com)\/.*\/(.*)/');
/**
* Class InstallCommand
* @package Grav\Console\Gpm
*/
class InstallCommand extends ConsoleCommand class InstallCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -54,7 +61,10 @@ class InstallCommand extends ConsoleCommand
/** @var string */ /** @var string */
protected $all_yes; protected $all_yes;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('install') ->setName('install')
@@ -97,15 +107,16 @@ class InstallCommand extends ConsoleCommand
} }
/** /**
* @return bool * @return int
*/ */
protected function serve() protected function serve(): int
{ {
if (!class_exists(\ZipArchive::class)) { if (!class_exists(\ZipArchive::class)) {
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
$io->title('GPM Install'); $io->title('GPM Install');
$io->error('php-zip extension needs to be enabled!'); $io->error('php-zip extension needs to be enabled!');
exit;
return 1;
} }
$this->gpm = new GPM($this->input->getOption('force')); $this->gpm = new GPM($this->input->getOption('force'));
@@ -124,7 +135,8 @@ class InstallCommand extends ConsoleCommand
!Installer::isValidDestination($this->destination, [Installer::EXISTS, Installer::IS_LINK]) !Installer::isValidDestination($this->destination, [Installer::EXISTS, Installer::IS_LINK])
) { ) {
$this->output->writeln('<red>ERROR</red>: ' . Installer::lastErrorMsg()); $this->output->writeln('<red>ERROR</red>: ' . Installer::lastErrorMsg());
exit;
return 1;
} }
$this->output->writeln(''); $this->output->writeln('');
@@ -132,10 +144,11 @@ class InstallCommand extends ConsoleCommand
if (!$this->data['total']) { if (!$this->data['total']) {
$this->output->writeln('Nothing to install.'); $this->output->writeln('Nothing to install.');
$this->output->writeln(''); $this->output->writeln('');
exit;
return 0;
} }
if (\count($this->data['not_found'])) { if (count($this->data['not_found'])) {
$this->output->writeln('These packages were not found on Grav: <red>' . implode( $this->output->writeln('These packages were not found on Grav: <red>' . implode(
'</red>, <red>', '</red>, <red>',
array_keys($this->data['not_found']) array_keys($this->data['not_found'])
@@ -161,11 +174,12 @@ class InstallCommand extends ConsoleCommand
try { try {
$dependencies = $this->gpm->getDependencies($packages); $dependencies = $this->gpm->getDependencies($packages);
} catch (\Exception $e) { } catch (Exception $e) {
//Error out if there are incompatible packages requirements and tell which ones, and what to do //Error out if there are incompatible packages requirements and tell which ones, and what to do
//Error out if there is any error in parsing the dependencies and their versions, and tell which one is broken //Error out if there is any error in parsing the dependencies and their versions, and tell which one is broken
$this->output->writeln("<red>{$e->getMessage()}</red>"); $this->output->writeln("<red>{$e->getMessage()}</red>");
return false;
return 1;
} }
if ($dependencies) { if ($dependencies) {
@@ -173,9 +187,10 @@ class InstallCommand extends ConsoleCommand
$this->installDependencies($dependencies, 'install', 'The following dependencies need to be installed...'); $this->installDependencies($dependencies, 'install', 'The following dependencies need to be installed...');
$this->installDependencies($dependencies, 'update', 'The following dependencies need to be updated...'); $this->installDependencies($dependencies, 'update', 'The following dependencies need to be updated...');
$this->installDependencies($dependencies, 'ignore', "The following dependencies can be updated as there is a newer version, but it's not mandatory...", false); $this->installDependencies($dependencies, 'ignore', "The following dependencies can be updated as there is a newer version, but it's not mandatory...", false);
} catch (\Exception $e) { } catch (Exception $e) {
$this->output->writeln('<red>Installation aborted</red>'); $this->output->writeln('<red>Installation aborted</red>');
return false;
return 1;
} }
$this->output->writeln('<green>Dependencies are OK</green>'); $this->output->writeln('<green>Dependencies are OK</green>');
@@ -197,9 +212,10 @@ class InstallCommand extends ConsoleCommand
try { try {
$this->askConfirmationIfMajorVersionUpdated($package); $this->askConfirmationIfMajorVersionUpdated($package);
$this->gpm->checkNoOtherPackageNeedsThisDependencyInALowerVersion($package->slug, $package->available, array_keys($data)); $this->gpm->checkNoOtherPackageNeedsThisDependencyInALowerVersion($package->slug, $package->available, array_keys($data));
} catch (\Exception $e) { } catch (Exception $e) {
$this->output->writeln("<red>{$e->getMessage()}</red>"); $this->output->writeln("<red>{$e->getMessage()}</red>");
return false;
return 1;
} }
$helper = $this->getHelper('question'); $helper = $this->getHelper('question');
@@ -223,7 +239,7 @@ class InstallCommand extends ConsoleCommand
} }
} }
if (\count($this->demo_processing) > 0) { if (count($this->demo_processing) > 0) {
foreach ($this->demo_processing as $package) { foreach ($this->demo_processing as $package) {
$this->installDemoContent($package); $this->installDemoContent($package);
} }
@@ -232,15 +248,16 @@ class InstallCommand extends ConsoleCommand
// clear cache after successful upgrade // clear cache after successful upgrade
$this->clearCache(); $this->clearCache();
return true; return 0;
} }
/** /**
* If the package is updated from an older major release, show warning and ask confirmation * If the package is updated from an older major release, show warning and ask confirmation
* *
* @param Package $package * @param Package $package
* @return void
*/ */
public function askConfirmationIfMajorVersionUpdated($package) public function askConfirmationIfMajorVersionUpdated($package): void
{ {
$helper = $this->getHelper('question'); $helper = $this->getHelper('question');
$package_name = $package->name; $package_name = $package->name;
@@ -273,15 +290,15 @@ class InstallCommand extends ConsoleCommand
* @param string $type The type of dependency to show: install, update, ignore * @param string $type The type of dependency to show: install, update, ignore
* @param string $message A message to be shown prior to listing the dependencies * @param string $message A message to be shown prior to listing the dependencies
* @param bool $required A flag that determines if the installation is required or optional * @param bool $required A flag that determines if the installation is required or optional
* * @return void
* @throws \Exception * @throws Exception
*/ */
public function installDependencies($dependencies, $type, $message, $required = true) public function installDependencies($dependencies, $type, $message, $required = true): void
{ {
$packages = array_filter($dependencies, function ($action) use ($type) { $packages = array_filter($dependencies, static function ($action) use ($type) {
return $action === $type; return $action === $type;
}); });
if (\count($packages) > 0) { if (count($packages) > 0) {
$this->output->writeln($message); $this->output->writeln($message);
foreach ($packages as $dependencyName => $dependencyVersion) { foreach ($packages as $dependencyName => $dependencyVersion) {
@@ -298,13 +315,13 @@ class InstallCommand extends ConsoleCommand
$questionAction = 'Update'; $questionAction = 'Update';
} }
if (\count($packages) === 1) { if (count($packages) === 1) {
$questionArticle = 'this'; $questionArticle = 'this';
} else { } else {
$questionArticle = 'these'; $questionArticle = 'these';
} }
if (\count($packages) === 1) { if (count($packages) === 1) {
$questionNoun = 'package'; $questionNoun = 'package';
} else { } else {
$questionNoun = 'packages'; $questionNoun = 'packages';
@@ -319,10 +336,8 @@ class InstallCommand extends ConsoleCommand
$this->processPackage($package, $type === 'update'); $this->processPackage($package, $type === 'update');
} }
$this->output->writeln(''); $this->output->writeln('');
} else { } elseif ($required) {
if ($required) { throw new Exception();
throw new \Exception();
}
} }
} }
} }
@@ -330,8 +345,9 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package|null $package * @param Package|null $package
* @param bool $is_update True if the package is an update * @param bool $is_update True if the package is an update
* @return void
*/ */
private function processPackage($package, $is_update = false) private function processPackage($package, $is_update = false): void
{ {
if (!$package) { if (!$package) {
$this->output->writeln('<red>Package not found on the GPM!</red>'); $this->output->writeln('<red>Package not found on the GPM!</red>');
@@ -355,8 +371,9 @@ class InstallCommand extends ConsoleCommand
* Add package to the queue to process the demo content, if demo content exists * Add package to the queue to process the demo content, if demo content exists
* *
* @param Package $package * @param Package $package
* @return void
*/ */
private function processDemo($package) private function processDemo($package): void
{ {
$demo_dir = $this->destination . DS . $package->install_path . DS . '_demo'; $demo_dir = $this->destination . DS . $package->install_path . DS . '_demo';
if (file_exists($demo_dir)) { if (file_exists($demo_dir)) {
@@ -368,8 +385,9 @@ class InstallCommand extends ConsoleCommand
* Prompt to install the demo content of a package * Prompt to install the demo content of a package
* *
* @param Package $package * @param Package $package
* @return void
*/ */
private function installDemoContent($package) private function installDemoContent($package): void
{ {
$demo_dir = $this->destination . DS . $package->install_path . DS . '_demo'; $demo_dir = $this->destination . DS . $package->install_path . DS . '_demo';
@@ -424,8 +442,7 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package $package * @param Package $package
* * @return array|false
* @return array|bool
*/ */
private function getGitRegexMatches($package) private function getGitRegexMatches($package)
{ {
@@ -442,8 +459,7 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package $package * @param Package $package
* * @return string|false
* @return bool|string
*/ */
private function getSymlinkSource($package) private function getSymlinkSource($package)
{ {
@@ -470,10 +486,10 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package $package * @param Package $package
* @return void
*/ */
private function processSymlink($package) private function processSymlink($package): void
{ {
exec('cd ' . $this->destination); exec('cd ' . $this->destination);
$to = $this->destination . DS . $package->install_path; $to = $this->destination . DS . $package->install_path;
@@ -491,18 +507,16 @@ class InstallCommand extends ConsoleCommand
if (!$checks) { if (!$checks) {
$this->output->writeln(" '- <red>Installation failed or aborted.</red>"); $this->output->writeln(" '- <red>Installation failed or aborted.</red>");
$this->output->writeln(''); $this->output->writeln('');
} elseif (file_exists($to)) {
$this->output->writeln(" '- <red>Symlink cannot overwrite an existing package, please remove first</red>");
$this->output->writeln('');
} else { } else {
if (file_exists($to)) { symlink($from, $to);
$this->output->writeln(" '- <red>Symlink cannot overwrite an existing package, please remove first</red>");
$this->output->writeln('');
} else {
symlink($from, $to);
// extra white spaces to clear out the buffer properly // extra white spaces to clear out the buffer properly
$this->output->writeln(' |- Symlinking package... <green>ok</green> '); $this->output->writeln(' |- Symlinking package... <green>ok</green> ');
$this->output->writeln(" '- <green>Success!</green> "); $this->output->writeln(" '- <green>Success!</green> ");
$this->output->writeln(''); $this->output->writeln('');
}
} }
return; return;
@@ -515,12 +529,11 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package $package * @param Package $package
* @param bool $is_update * @param bool $is_update
*
* @return bool * @return bool
*/ */
private function processGpm($package, $is_update = false) private function processGpm($package, $is_update = false)
{ {
$version = isset($package->available) ? $package->available : $package->version; $version = $package->available ?? $package->version;
$license = Licenses::get($package->slug); $license = Licenses::get($package->slug);
$this->output->writeln("Preparing to install <cyan>{$package->name}</cyan> [v{$version}]"); $this->output->writeln("Preparing to install <cyan>{$package->name}</cyan> [v{$version}]");
@@ -561,7 +574,6 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package $package * @param Package $package
* @param string|null $license * @param string|null $license
*
* @return string|null * @return string|null
*/ */
private function downloadPackage($package, $license = null) private function downloadPackage($package, $license = null)
@@ -573,7 +585,7 @@ class InstallCommand extends ConsoleCommand
$query = ''; $query = '';
if (!empty($package->premium)) { if (!empty($package->premium)) {
$query = \json_encode(array_merge( $query = json_encode(array_merge(
$package->premium, $package->premium,
[ [
'slug' => $package->slug, 'slug' => $package->slug,
@@ -588,7 +600,7 @@ class InstallCommand extends ConsoleCommand
try { try {
$output = Response::get($package->zipball_url . $query, [], [$this, 'progress']); $output = Response::get($package->zipball_url . $query, [], [$this, 'progress']);
} catch (\Exception $e) { } catch (Exception $e) {
$error = str_replace("\n", "\n | '- ", $e->getMessage()); $error = str_replace("\n", "\n | '- ", $e->getMessage());
$this->output->write("\x0D"); $this->output->write("\x0D");
// extra white spaces to clear out the buffer properly // extra white spaces to clear out the buffer properly
@@ -611,16 +623,15 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param Package $package * @param Package $package
*
* @return bool * @return bool
*/ */
private function checkDestination($package) private function checkDestination($package): bool
{ {
$question_helper = $this->getHelper('question'); $question_helper = $this->getHelper('question');
Installer::isValidDestination($this->destination . DS . $package->install_path); Installer::isValidDestination($this->destination . DS . $package->install_path);
if (Installer::lastErrorCode() == Installer::IS_LINK) { if (Installer::lastErrorCode() === Installer::IS_LINK) {
$this->output->write("\x0D"); $this->output->write("\x0D");
$this->output->writeln(' |- Checking destination... <yellow>symbolic link</yellow>'); $this->output->writeln(' |- Checking destination... <yellow>symbolic link</yellow>');
@@ -656,7 +667,6 @@ class InstallCommand extends ConsoleCommand
* *
* @param Package $package * @param Package $package
* @param bool $is_update True if it's an update. False if it's an install * @param bool $is_update True if it's an update. False if it's an install
*
* @return bool * @return bool
*/ */
private function installPackage($package, $is_update = false) private function installPackage($package, $is_update = false)
@@ -692,8 +702,9 @@ class InstallCommand extends ConsoleCommand
/** /**
* @param array $progress * @param array $progress
* @return void
*/ */
public function progress($progress) public function progress($progress): void
{ {
$this->output->write("\x0D"); $this->output->write("\x0D");
$this->output->write(' |- Downloading package... ' . str_pad( $this->output->write(' |- Downloading package... ' . str_pad(

View File

@@ -9,6 +9,7 @@
namespace Grav\Console\Gpm; namespace Grav\Console\Gpm;
use Exception;
use Grav\Common\Cache; use Grav\Common\Cache;
use Grav\Common\Filesystem\Folder; use Grav\Common\Filesystem\Folder;
use Grav\Common\GPM\Installer; use Grav\Common\GPM\Installer;
@@ -20,7 +21,13 @@ use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function is_callable;
use function strlen;
/**
* Class SelfupgradeCommand
* @package Grav\Console\Gpm
*/
class SelfupgradeCommand extends ConsoleCommand class SelfupgradeCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -47,7 +54,10 @@ class SelfupgradeCommand extends ConsoleCommand
/** @var int */ /** @var int */
protected $timeout; protected $timeout;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('self-upgrade') ->setName('self-upgrade')
@@ -81,13 +91,17 @@ class SelfupgradeCommand extends ConsoleCommand
->setHelp('The <info>update</info> command updates Grav itself when a new version is available'); ->setHelp('The <info>update</info> command updates Grav itself when a new version is available');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
if (!class_exists(\ZipArchive::class)) { if (!class_exists(\ZipArchive::class)) {
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
$io->title('GPM Self Upgrade'); $io->title('GPM Self Upgrade');
$io->error('php-zip extension needs to be enabled!'); $io->error('php-zip extension needs to be enabled!');
exit;
return 1;
} }
$this->upgrader = new Upgrader($this->input->getOption('force')); $this->upgrader = new Upgrader($this->input->getOption('force'));
@@ -111,12 +125,14 @@ class SelfupgradeCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('Selfupgrade aborted.'); $this->output->writeln('Selfupgrade aborted.');
$this->output->writeln(''); $this->output->writeln('');
exit;
return 1;
} }
if (!$this->overwrite && !$this->upgrader->isUpgradable()) { if (!$this->overwrite && !$this->upgrader->isUpgradable()) {
$this->output->writeln("You are already running the latest version of Grav (v{$local}) released on {$release}"); $this->output->writeln("You are already running the latest version of Grav (v{$local}) released on {$release}");
exit;
return 0;
} }
Installer::isValidDestination(GRAV_ROOT . '/system'); Installer::isValidDestination(GRAV_ROOT . '/system');
@@ -124,7 +140,8 @@ class SelfupgradeCommand extends ConsoleCommand
$this->output->writeln('<red>ATTENTION:</red> Grav is symlinked, cannot upgrade, aborting...'); $this->output->writeln('<red>ATTENTION:</red> Grav is symlinked, cannot upgrade, aborting...');
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln("You are currently running a symbolically linked Grav v{$local}. Latest available is v{$remote}."); $this->output->writeln("You are currently running a symbolically linked Grav v{$local}. Latest available is v{$remote}.");
exit;
return 1;
} }
// not used but preloaded just in case! // not used but preloaded just in case!
@@ -148,12 +165,12 @@ class SelfupgradeCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
foreach ($changelog as $version => $log) { foreach ($changelog as $version => $log) {
$title = $version . ' [' . $log['date'] . ']'; $title = $version . ' [' . $log['date'] . ']';
$content = preg_replace_callback('/\d\.\s\[\]\(#(.*)\)/', function ($match) { $content = preg_replace_callback('/\d\.\s\[\]\(#(.*)\)/', static function ($match) {
return "\n" . ucfirst($match[1]) . ':'; return "\n" . ucfirst($match[1]) . ':';
}, $log['content']); }, $log['content']);
$this->output->writeln($title); $this->output->writeln($title);
$this->output->writeln(str_repeat('-', \strlen($title))); $this->output->writeln(str_repeat('-', strlen($title)));
$this->output->writeln($content); $this->output->writeln($content);
$this->output->writeln(''); $this->output->writeln('');
} }
@@ -168,7 +185,7 @@ class SelfupgradeCommand extends ConsoleCommand
if (!$answer) { if (!$answer) {
$this->output->writeln('Aborting...'); $this->output->writeln('Aborting...');
exit; return 1;
} }
} }
@@ -181,9 +198,11 @@ class SelfupgradeCommand extends ConsoleCommand
$this->output->write(' |- Installing upgrade... '); $this->output->write(' |- Installing upgrade... ');
$installation = $this->upgrade(); $installation = $this->upgrade();
$error = 0;
if (!$installation) { if (!$installation) {
$this->output->writeln(" '- <red>Installation failed or aborted.</red>"); $this->output->writeln(" '- <red>Installation failed or aborted.</red>");
$this->output->writeln(''); $this->output->writeln('');
$error = 1;
} else { } else {
$this->output->writeln(" '- <green>Success!</green> "); $this->output->writeln(" '- <green>Success!</green> ");
$this->output->writeln(''); $this->output->writeln('');
@@ -191,11 +210,12 @@ class SelfupgradeCommand extends ConsoleCommand
// clear cache after successful upgrade // clear cache after successful upgrade
$this->clearCache(['all']); $this->clearCache(['all']);
return $error;
} }
/** /**
* @param array $package * @param array $package
*
* @return string * @return string
*/ */
private function download($package) private function download($package)
@@ -235,7 +255,7 @@ class SelfupgradeCommand extends ConsoleCommand
$folder = false; $folder = false;
} }
static::upgradeGrav($this->file, $folder); $this->upgradeGrav($this->file, $folder);
$errorCode = Installer::lastErrorCode(); $errorCode = Installer::lastErrorCode();
@@ -261,8 +281,9 @@ class SelfupgradeCommand extends ConsoleCommand
/** /**
* @param array $progress * @param array $progress
* @return void
*/ */
public function progress($progress) public function progress($progress): void
{ {
$this->output->write("\x0D"); $this->output->write("\x0D");
$this->output->write(" |- Downloading upgrade [{$this->formatBytes($progress['filesize']) }]... " . str_pad( $this->output->write(" |- Downloading upgrade [{$this->formatBytes($progress['filesize']) }]... " . str_pad(
@@ -276,7 +297,6 @@ class SelfupgradeCommand extends ConsoleCommand
/** /**
* @param int|float $size * @param int|float $size
* @param int $precision * @param int $precision
*
* @return string * @return string
*/ */
public function formatBytes($size, $precision = 2) public function formatBytes($size, $precision = 2)
@@ -287,6 +307,11 @@ class SelfupgradeCommand extends ConsoleCommand
return round(1024 ** ($base - floor($base)), $precision) . $suffixes[(int)floor($base)]; return round(1024 ** ($base - floor($base)), $precision) . $suffixes[(int)floor($base)];
} }
/**
* @param string $zip
* @param string $folder
* @param false $keepFolder
*/
private function upgradeGrav($zip, $folder, $keepFolder = false) private function upgradeGrav($zip, $folder, $keepFolder = false)
{ {
static $ignores = [ static $ignores = [
@@ -320,7 +345,7 @@ class SelfupgradeCommand extends ConsoleCommand
Cache::clearCache(); Cache::clearCache();
} }
} catch (\Exception $e) { } catch (Exception $e) {
Installer::setError($e->getMessage()); Installer::setError($e->getMessage());
} }
} }

View File

@@ -17,7 +17,14 @@ use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion;
use function count;
use function in_array;
use function is_array;
/**
* Class UninstallCommand
* @package Grav\Console\Gpm
*/
class UninstallCommand extends ConsoleCommand class UninstallCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -41,7 +48,10 @@ class UninstallCommand extends ConsoleCommand
/** @var string */ /** @var string */
protected $all_yes; protected $all_yes;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('uninstall') ->setName('uninstall')
@@ -60,7 +70,10 @@ class UninstallCommand extends ConsoleCommand
->setHelp('The <info>uninstall</info> command allows to uninstall plugins and themes'); ->setHelp('The <info>uninstall</info> command allows to uninstall plugins and themes');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
$this->gpm = new GPM(); $this->gpm = new GPM();
@@ -87,7 +100,8 @@ class UninstallCommand extends ConsoleCommand
if (!$this->data['total']) { if (!$this->data['total']) {
$this->output->writeln('Nothing to uninstall.'); $this->output->writeln('Nothing to uninstall.');
$this->output->writeln(''); $this->output->writeln('');
exit;
return 0;
} }
if (count($this->data['not_found'])) { if (count($this->data['not_found'])) {
@@ -99,6 +113,7 @@ class UninstallCommand extends ConsoleCommand
unset($this->data['not_found'], $this->data['total']); unset($this->data['not_found'], $this->data['total']);
$error = 0;
foreach ($this->data as $slug => $package) { foreach ($this->data as $slug => $package) {
$this->output->writeln("Preparing to uninstall <cyan>{$package->name}</cyan> [v{$package->version}]"); $this->output->writeln("Preparing to uninstall <cyan>{$package->name}</cyan> [v{$package->version}]");
@@ -108,11 +123,13 @@ class UninstallCommand extends ConsoleCommand
if (!$checks) { if (!$checks) {
$this->output->writeln(" '- <red>Installation failed or aborted.</red>"); $this->output->writeln(" '- <red>Installation failed or aborted.</red>");
$this->output->writeln(''); $this->output->writeln('');
$error = 1;
} else { } else {
$uninstall = $this->uninstallPackage($slug, $package); $uninstall = $this->uninstallPackage($slug, $package);
if (!$uninstall) { if (!$uninstall) {
$this->output->writeln(" '- <red>Uninstallation failed or aborted.</red>"); $this->output->writeln(" '- <red>Uninstallation failed or aborted.</red>");
$error = 1;
} else { } else {
$this->output->writeln(" '- <green>Success!</green> "); $this->output->writeln(" '- <green>Success!</green> ");
} }
@@ -121,13 +138,13 @@ class UninstallCommand extends ConsoleCommand
// clear cache after successful upgrade // clear cache after successful upgrade
$this->clearCache(); $this->clearCache();
}
return $error;
}
/** /**
* @param string $slug * @param string $slug
* @param Package $package * @param Package $package
*
* @return bool * @return bool
*/ */
private function uninstallPackage($slug, $package, $is_dependency = false) private function uninstallPackage($slug, $package, $is_dependency = false)
@@ -143,7 +160,7 @@ class UninstallCommand extends ConsoleCommand
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('<red>Uninstallation failed.</red>'); $this->output->writeln('<red>Uninstallation failed.</red>');
$this->output->writeln(''); $this->output->writeln('');
if (\count($dependent_packages) > ($is_dependency ? 2 : 1)) { if (count($dependent_packages) > ($is_dependency ? 2 : 1)) {
$this->output->writeln('The installed packages <cyan>' . implode('</cyan>, <cyan>', $dependent_packages) . '</cyan> depends on this package. Please remove those first.'); $this->output->writeln('The installed packages <cyan>' . implode('</cyan>, <cyan>', $dependent_packages) . '</cyan> depends on this package. Please remove those first.');
} else { } else {
$this->output->writeln('The installed package <cyan>' . implode('</cyan>, <cyan>', $dependent_packages) . '</cyan> depends on this package. Please remove it first.'); $this->output->writeln('The installed package <cyan>' . implode('</cyan>, <cyan>', $dependent_packages) . '</cyan> depends on this package. Please remove it first.');
@@ -158,15 +175,13 @@ class UninstallCommand extends ConsoleCommand
if ($is_dependency) { if ($is_dependency) {
foreach ($dependencies as $key => $dependency) { foreach ($dependencies as $key => $dependency) {
if (\in_array($dependency['name'], $this->dependencies, true)) { if (in_array($dependency['name'], $this->dependencies, true)) {
unset($dependencies[$key]); unset($dependencies[$key]);
} }
} }
} else { } elseif (count($dependencies) > 0) {
if (\count($dependencies) > 0) { $this->output->writeln(' `- Dependencies found...');
$this->output->writeln(' `- Dependencies found...'); $this->output->writeln('');
$this->output->writeln('');
}
} }
$questionHelper = $this->getHelper('question'); $questionHelper = $this->getHelper('question');
@@ -174,7 +189,7 @@ class UninstallCommand extends ConsoleCommand
foreach ($dependencies as $dependency) { foreach ($dependencies as $dependency) {
$this->dependencies[] = $dependency['name']; $this->dependencies[] = $dependency['name'];
if (\is_array($dependency)) { if (is_array($dependency)) {
$dependency = $dependency['name']; $dependency = $dependency['name'];
} }
if ($dependency === 'grav' || $dependency === 'php') { if ($dependency === 'grav' || $dependency === 'php') {
@@ -239,10 +254,8 @@ class UninstallCommand extends ConsoleCommand
/** /**
* @param string $slug * @param string $slug
* @param Package $package * @param Package $package
*
* @return bool * @return bool
*/ */
private function checkDestination($slug, $package) private function checkDestination($slug, $package)
{ {
$questionHelper = $this->getHelper('question'); $questionHelper = $this->getHelper('question');
@@ -289,6 +302,7 @@ class UninstallCommand extends ConsoleCommand
{ {
$path = Grav::instance()['locator']->findResource($package->package_type . '://' . $slug); $path = Grav::instance()['locator']->findResource($package->package_type . '://' . $slug);
Installer::isValidDestination($path); Installer::isValidDestination($path);
return Installer::lastErrorCode(); return Installer::lastErrorCode();
} }
} }

View File

@@ -18,7 +18,13 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Question\ConfirmationQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
use function array_key_exists;
use function count;
/**
* Class UpdateCommand
* @package Grav\Console\Gpm
*/
class UpdateCommand extends ConsoleCommand class UpdateCommand extends ConsoleCommand
{ {
/** @var array */ /** @var array */
@@ -45,7 +51,10 @@ class UpdateCommand extends ConsoleCommand
/** @var Upgrader */ /** @var Upgrader */
protected $upgrader; protected $upgrader;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('update') ->setName('update')
@@ -95,13 +104,17 @@ class UpdateCommand extends ConsoleCommand
->setHelp('The <info>update</info> command updates plugins and themes when a new version is available'); ->setHelp('The <info>update</info> command updates plugins and themes when a new version is available');
} }
protected function serve() /**
* @return int
*/
protected function serve(): int
{ {
if (!class_exists(\ZipArchive::class)) { if (!class_exists(\ZipArchive::class)) {
$io = new SymfonyStyle($this->input, $this->output); $io = new SymfonyStyle($this->input, $this->output);
$io->title('GPM Update'); $io->title('GPM Update');
$io->error('php-zip extension needs to be enabled!'); $io->error('php-zip extension needs to be enabled!');
exit;
return 1;
} }
$this->upgrader = new Upgrader($this->input->getOption('force')); $this->upgrader = new Upgrader($this->input->getOption('force'));
@@ -116,7 +129,8 @@ class UpdateCommand extends ConsoleCommand
if (!$answer) { if (!$answer) {
$this->output->writeln('<red>Update aborted. Exiting...</red>'); $this->output->writeln('<red>Update aborted. Exiting...</red>');
exit;
return 1;
} }
} }
@@ -152,7 +166,8 @@ class UpdateCommand extends ConsoleCommand
if (!$this->overwrite && !$this->data['total']) { if (!$this->overwrite && !$this->data['total']) {
$this->output->writeln('Nothing to update.'); $this->output->writeln('Nothing to update.');
exit;
return 0;
} }
$this->output->write("Found <green>{$this->gpm->countInstalled()}</green> packages installed of which <magenta>{$this->data['total']}</magenta>{$description}"); $this->output->write("Found <green>{$this->gpm->countInstalled()}</green> packages installed of which <magenta>{$this->data['total']}</magenta>{$description}");
@@ -170,7 +185,7 @@ class UpdateCommand extends ConsoleCommand
$index = 0; $index = 0;
foreach ($this->data as $packages) { foreach ($this->data as $packages) {
foreach ($packages as $slug => $package) { foreach ($packages as $slug => $package) {
if (!array_key_exists($slug, $limit_to) && \count($only_packages)) { if (!array_key_exists($slug, $limit_to) && count($only_packages)) {
continue; continue;
} }
@@ -199,7 +214,8 @@ class UpdateCommand extends ConsoleCommand
if (!$answer) { if (!$answer) {
$this->output->writeln('<red>Update aborted. Exiting...</red>'); $this->output->writeln('<red>Update aborted. Exiting...</red>');
exit;
return 1;
} }
} }
@@ -217,13 +233,15 @@ class UpdateCommand extends ConsoleCommand
if ($command_exec != 0) { if ($command_exec != 0) {
$this->output->writeln('<red>Error:</red> An error occurred while trying to install the packages'); $this->output->writeln('<red>Error:</red> An error occurred while trying to install the packages');
exit;
return 1;
} }
return 0;
} }
/** /**
* @param array $only_packages * @param array $only_packages
*
* @return array * @return array
*/ */
private function userInputPackages($only_packages) private function userInputPackages($only_packages)
@@ -231,7 +249,7 @@ class UpdateCommand extends ConsoleCommand
$found = ['total' => 0]; $found = ['total' => 0];
$ignore = []; $ignore = [];
if (!\count($only_packages)) { if (!count($only_packages)) {
$this->output->writeln(''); $this->output->writeln('');
} else { } else {
foreach ($only_packages as $only_package) { foreach ($only_packages as $only_package) {
@@ -262,7 +280,7 @@ class UpdateCommand extends ConsoleCommand
) . '</cyan>'); ) . '</cyan>');
} }
if (\count($ignore)) { if (count($ignore)) {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln('Packages not found or not requiring updates: <red>' . implode( $this->output->writeln('Packages not found or not requiring updates: <red>' . implode(
'</red>, <red>', '</red>, <red>',

View File

@@ -11,17 +11,26 @@ namespace Grav\Console\Gpm;
use Grav\Common\GPM\GPM; use Grav\Common\GPM\GPM;
use Grav\Common\GPM\Upgrader; use Grav\Common\GPM\Upgrader;
use Grav\Common\Grav;
use Grav\Console\ConsoleCommand; use Grav\Console\ConsoleCommand;
use RocketTheme\Toolbox\File\YamlFile; use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use function count;
/**
* Class VersionCommand
* @package Grav\Console\Gpm
*/
class VersionCommand extends ConsoleCommand class VersionCommand extends ConsoleCommand
{ {
/** @var GPM */ /** @var GPM */
protected $gpm; protected $gpm;
protected function configure() /**
* @return void
*/
protected function configure(): void
{ {
$this $this
->setName('version') ->setName('version')
@@ -41,9 +50,9 @@ class VersionCommand extends ConsoleCommand
} }
/** /**
* @return int|null|void * @return int
*/ */
protected function serve() protected function serve(): int
{ {
$this->gpm = new GPM($this->input->getOption('force')); $this->gpm = new GPM($this->input->getOption('force'));
$packages = $this->input->getArgument('package'); $packages = $this->input->getArgument('package');
@@ -70,7 +79,7 @@ class VersionCommand extends ConsoleCommand
} }
} else { } else {
// get currently installed version // get currently installed version
$locator = \Grav\Common\Grav::instance()['locator']; $locator = Grav::instance()['locator'];
$blueprints_path = $locator->findResource('plugins://' . $package . DS . 'blueprints.yaml'); $blueprints_path = $locator->findResource('plugins://' . $package . DS . 'blueprints.yaml');
if (!file_exists($blueprints_path)) { // theme? if (!file_exists($blueprints_path)) { // theme?
$blueprints_path = $locator->findResource('themes://' . $package . DS . 'blueprints.yaml'); $blueprints_path = $locator->findResource('themes://' . $package . DS . 'blueprints.yaml');
@@ -107,5 +116,7 @@ class VersionCommand extends ConsoleCommand
$this->output->writeln("Package <red>{$package}</red> not found"); $this->output->writeln("Package <red>{$package}</red> not found");
} }
} }
return 0;
} }
} }

View File

@@ -9,8 +9,15 @@
namespace Grav\Console\TerminalObjects; namespace Grav\Console\TerminalObjects;
/**
* Class Table
* @package Grav\Console\TerminalObjects
*/
class Table extends \League\CLImate\TerminalObject\Basic\Table class Table extends \League\CLImate\TerminalObject\Basic\Table
{ {
/**
* @return array
*/
public function result() public function result()
{ {
$this->column_widths = $this->getColumnWidths(); $this->column_widths = $this->getColumnWidths();