diff --git a/system/src/Grav/Common/Helpers/YamlLinter.php b/system/src/Grav/Common/Helpers/YamlLinter.php
index 64de4c493..7136ae06c 100644
--- a/system/src/Grav/Common/Helpers/YamlLinter.php
+++ b/system/src/Grav/Common/Helpers/YamlLinter.php
@@ -27,39 +27,47 @@ class YamlLinter
{
/**
* @param string|null $folder
+ * @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
* @return array
*/
- public static function lint(?string $folder = null)
+ public static function lint(?string $folder = null, ?callable $callback = null)
{
if (null !== $folder) {
$folder = $folder ?: GRAV_ROOT;
- return static::recurseFolder($folder);
+ return static::recurseFolder($folder, '(md|yaml)', $callback);
}
- return array_merge(static::lintConfig(), static::lintPages(), static::lintBlueprints());
+ return array_merge(
+ static::lintConfig($callback),
+ static::lintPages($callback),
+ static::lintBlueprints($callback)
+ );
}
/**
+ * @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
* @return array
*/
- public static function lintPages()
+ public static function lintPages(?callable $callback = null)
{
- return static::recurseFolder('page://');
+ return static::recurseFolder('page://', '(md|yaml)', $callback);
}
/**
+ * @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
* @return array
*/
- public static function lintConfig()
+ public static function lintConfig(?callable $callback = null)
{
- return static::recurseFolder('config://');
+ return static::recurseFolder('config://', '(md|yaml)', $callback);
}
/**
+ * @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
* @return array
*/
- public static function lintBlueprints()
+ public static function lintBlueprints(?callable $callback = null)
{
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
@@ -68,15 +76,16 @@ class YamlLinter
$theme_path = 'themes://' . $current_theme . '/blueprints';
$locator->addPath('blueprints', '', [$theme_path]);
- return static::recurseFolder('blueprints://');
+ return static::recurseFolder('blueprints://', '(md|yaml)', $callback);
}
/**
* @param string $path
* @param string $extensions
+ * @param callable|null $callback Optional callback for progress: function(string $file, bool $success, ?string $error)
* @return array
*/
- public static function recurseFolder($path, $extensions = '(md|yaml)')
+ public static function recurseFolder($path, $extensions = '(md|yaml)', ?callable $callback = null)
{
$lint_errors = [];
@@ -93,10 +102,17 @@ class YamlLinter
/** @var RecursiveDirectoryIterator $file */
foreach ($iterator as $filepath => $file) {
+ $relativePath = str_replace(GRAV_ROOT, '', $filepath);
try {
Yaml::parse(static::extractYaml($filepath));
+ if ($callback) {
+ $callback($relativePath, true, null);
+ }
} catch (Exception $e) {
- $lint_errors[str_replace(GRAV_ROOT, '', $filepath)] = $e->getMessage();
+ $lint_errors[$relativePath] = $e->getMessage();
+ if ($callback) {
+ $callback($relativePath, false, $e->getMessage());
+ }
}
}
diff --git a/system/src/Grav/Console/Cli/YamlLinterCommand.php b/system/src/Grav/Console/Cli/YamlLinterCommand.php
index c794d8487..94be94305 100644
--- a/system/src/Grav/Console/Cli/YamlLinterCommand.php
+++ b/system/src/Grav/Console/Cli/YamlLinterCommand.php
@@ -53,62 +53,88 @@ class YamlLinterCommand extends GravCommand
$io->title('Yaml Linter');
+ $verbose = $io->isVerbose();
+ $checked = 0;
+ $callback = $verbose ? function (string $file, bool $success, ?string $error) use ($io, &$checked) {
+ $checked++;
+ if ($success) {
+ $io->writeln("[OK] {$file}");
+ } else {
+ $io->writeln("[ERROR] {$file}");
+ }
+ } : null;
+
$error = 0;
if ($input->getOption('all')) {
$io->section('All');
- $errors = YamlLinter::lint('');
+ $errors = YamlLinter::lint('', $callback);
- if (empty($errors)) {
- $io->success('No YAML Linting issues found');
- } else {
+ $this->displayResult($errors, $io, 'No YAML Linting issues found', $verbose, $checked);
+ if (!empty($errors)) {
$error = 1;
- $this->displayErrors($errors, $io);
}
} elseif ($folder = $input->getOption('folder')) {
$io->section($folder);
- $errors = YamlLinter::lint($folder);
+ $errors = YamlLinter::lint($folder, $callback);
- if (empty($errors)) {
- $io->success('No YAML Linting issues found');
- } else {
+ $this->displayResult($errors, $io, 'No YAML Linting issues found', $verbose, $checked);
+ if (!empty($errors)) {
$error = 1;
- $this->displayErrors($errors, $io);
}
} else {
$io->section('User Configuration');
- $errors = YamlLinter::lintConfig();
+ $checked = 0;
+ $errors = YamlLinter::lintConfig($callback);
- if (empty($errors)) {
- $io->success('No YAML Linting issues with configuration');
- } else {
+ $this->displayResult($errors, $io, 'No YAML Linting issues with configuration', $verbose, $checked);
+ if (!empty($errors)) {
$error = 1;
- $this->displayErrors($errors, $io);
}
$io->section('Pages Frontmatter');
- $errors = YamlLinter::lintPages();
+ $checked = 0;
+ $errors = YamlLinter::lintPages($callback);
- if (empty($errors)) {
- $io->success('No YAML Linting issues with pages');
- } else {
+ $this->displayResult($errors, $io, 'No YAML Linting issues with pages', $verbose, $checked);
+ if (!empty($errors)) {
$error = 1;
- $this->displayErrors($errors, $io);
}
$io->section('Page Blueprints');
- $errors = YamlLinter::lintBlueprints();
+ $checked = 0;
+ $errors = YamlLinter::lintBlueprints($callback);
- if (empty($errors)) {
- $io->success('No YAML Linting issues with blueprints');
- } else {
+ $this->displayResult($errors, $io, 'No YAML Linting issues with blueprints', $verbose, $checked);
+ if (!empty($errors)) {
$error = 1;
- $this->displayErrors($errors, $io);
}
}
return $error;
}
+ /**
+ * @param array $errors
+ * @param SymfonyStyle $io
+ * @param string $successMessage
+ * @param bool $verbose
+ * @param int $checked
+ * @return void
+ */
+ protected function displayResult(array $errors, SymfonyStyle $io, string $successMessage, bool $verbose, int $checked): void
+ {
+ if ($verbose) {
+ $io->newLine();
+ $io->writeln("Files checked: {$checked}");
+ }
+
+ if (empty($errors)) {
+ $io->success($successMessage);
+ } else {
+ $this->displayErrors($errors, $io);
+ }
+ }
+
/**
* @param array $errors
* @param SymfonyStyle $io