diff --git a/CHANGELOG.md b/CHANGELOG.md index dcbc79864..9144b63a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # v1.6.7 ## mm/dd/2019 +1. [](#new) + * Added a new `bin/grav yamllinter` CLI command to find YAML Linting issues [#2468](https://github.com/getgrav/grav/issues/2468#issuecomment-485151681) 1. [](#improved) * Improve `FormTrait` backwards compatibility with existing forms * Added a new `Utils::getSubnet()` function for IPv6 parsing [#2465](https://github.com/getgrav/grav/pull/2465) diff --git a/bin/grav b/bin/grav index 2a81d4c51..7120218c0 100755 --- a/bin/grav +++ b/bin/grav @@ -3,6 +3,7 @@ use Grav\Common\Composer; use Grav\Common\Grav; +use League\CLImate\CLImate; use Symfony\Component\Console\Application; \define('GRAV_CLI', true); @@ -24,7 +25,22 @@ if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) { exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req)); } -Grav::instance(array('loader' => $autoload)); +$climate = new League\CLImate\CLImate; +$climate->arguments->add([ + 'environment' => [ + 'prefix' => 'e', + 'longPrefix' => 'env', + 'description' => 'Configuration Environment', + 'defaultValue' => 'localhost' + ] +]); +$climate->arguments->parse(); + +// Set up environment based on params. +$environment = $climate->arguments->get('environment'); + +$grav = Grav::instance(array('loader' => $autoload)); +$grav->setup($environment); if (!ini_get('date.timezone')) { date_default_timezone_set('UTC'); @@ -46,5 +62,6 @@ $app->addCommands(array( new \Grav\Console\Cli\SchedulerCommand(), new \Grav\Console\Cli\SecurityCommand(), new \Grav\Console\Cli\LogViewerCommand(), + new \Grav\Console\Cli\YamlLinterCommand(), )); $app->run(); diff --git a/system/src/Grav/Common/Helpers/YamlLinter.php b/system/src/Grav/Common/Helpers/YamlLinter.php new file mode 100644 index 000000000..3d1af5c00 --- /dev/null +++ b/system/src/Grav/Common/Helpers/YamlLinter.php @@ -0,0 +1,68 @@ +isStream($path)) { + $directory = $locator->getRecursiveIterator($path, $flags); + } else { + $directory = new \RecursiveDirectoryIterator($path, $flags); + } + $recursive = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST); + $iterator = new \RegexIterator($recursive, '/^.+\.'.$extensions.'$/i'); + + /** @var \RecursiveDirectoryIterator $file */ + foreach ($iterator as $filepath => $file) { + try { + Yaml::parse(static::extractYaml($filepath)); + } catch (\Exception $e) { + $lint_errors[str_replace(GRAV_ROOT, '', $filepath)] = $e->getMessage(); + } + } + + return $lint_errors; + } + + protected static function extractYaml($path) + { + $extension = pathinfo($path, PATHINFO_EXTENSION); + if ($extension === 'md') { + $file = MarkdownFile::instance($path); + $contents = $file->frontmatter(); + } else { + $contents = file_get_contents($path); + } + return $contents; + } + +} diff --git a/system/src/Grav/Console/Cli/YamlLinterCommand.php b/system/src/Grav/Console/Cli/YamlLinterCommand.php new file mode 100644 index 000000000..18cdb493f --- /dev/null +++ b/system/src/Grav/Console/Cli/YamlLinterCommand.php @@ -0,0 +1,73 @@ +setName('yamllinter') + ->addOption( + 'env', + 'e', + InputOption::VALUE_OPTIONAL, + 'The environment to trigger a specific configuration. For example: localhost, mysite.dev, www.mysite.com' + ) + ->setDescription('Checks various files for YAML errors') + ->setHelp("Checks various files for YAML errors"); + } + + protected function serve() + { + $grav = Grav::instance(); + $grav->setup(); + + $io = new SymfonyStyle($this->input, $this->output); + + $io->title('Yaml Linter'); + + $io->section('User Configuration'); + $errors = YamlLinter::lintConfig(); + + if (empty($errors)) { + $io->success('No YAML Linting issues with configuration'); + } else { + $this->displayErrors($errors, $io); + } + + + $io->section('Pages Frontmatter'); + $errors = YamlLinter::lintPages(); + + if (empty($errors)) { + $io->success('No YAML Linting issues with pages'); + } else { + $this->displayErrors($errors, $io); + } + + } + + protected function displayErrors($errors, $io) + { + $io->error("YAML Linting issues found..."); + foreach ($errors as $path => $error) { + $io->writeln("$path - $error"); + } + } +}