1
0
cms11/app/Console/Commands/Bundle/Validate.php

176 lines
4.6 KiB
PHP
Raw Normal View History

2024-04-26 12:50:38 +02:00
<?php
namespace App\Console\Commands\Bundle;
use App\Classes\Bundle;
use Illuminate\Console\Command;
2024-05-06 22:11:20 +02:00
use Illuminate\Contracts\Filesystem\Filesystem;
2024-04-26 12:50:38 +02:00
use Illuminate\Support\Facades\Storage;
2024-05-06 22:11:20 +02:00
use Illuminate\Support\Str;
2024-04-26 12:50:38 +02:00
use JsonSchema\Validator;
2024-05-06 22:11:20 +02:00
use function Laravel\Prompts\progress;
2024-04-26 12:50:38 +02:00
class Validate extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Validate bundles metadata';
2024-05-06 22:11:20 +02:00
protected Filesystem $sourceDisk;
protected array $invalid = [];
public function __construct()
{
$this->signature = 'bundle:validate
{ --r|recursive : Also render sub-bundles }
{ --source-disk= : Use specified content disk - Defaults to <info>' . env('CONTENT_DISK') . '</info> }
{ path? : Path to a specific bundle to render - Default to <info>/</info> }
';
parent::__construct();
}
2024-04-26 12:50:38 +02:00
/**
* Execute the console command.
*/
public function handle()
2024-05-06 22:11:20 +02:00
{
$this->selectDisk()
->validate()
->showReport();
}
/**
* Select the disk we will be working on
*/
private function selectDisk(): self
{
$sourceDisk = $this->option('source-disk') ?? env('CONTENT_DISK');
$this->sourceDisk = Storage::disk($sourceDisk);
$this->comment(
sprintf(
'Using `%s` as source disk',
$sourceDisk
)
);
return $this;
}
/**
* Collect a list of bundles to validate
*/
private function getBundles()
2024-04-26 12:50:38 +02:00
{
$path = $this->argument('path') ?? '/';
2024-05-06 22:11:20 +02:00
$comment = sprintf('Validating %s', $path);
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
if ($this->option('recursive')) {
$comment .= ' and all sub-bundles';
}
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
$this->comment($comment);
$this->output->write('Collecting bundles... ');
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
if ($this->option('recursive')) {
$bundles = Bundle::findBundles($this->sourceDisk, $path, true);
} else {
$bundles = [new Bundle($path, $this->sourceDisk)];
}
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
$this->info('OK');
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
return $bundles;
}
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
/**
* Return an associative array containing available bundles metadata files
* as keys and json-decoded validation schemas as values
*/
private function getValidators()
{
return array_map(function ($path) {
return json_decode(file_get_contents($path));
}, config('json_validator'));
}
/**
* Perform json validation on selected bundles
*/
private function validate(): self
{
$bundles = $this->getBundles();
$validators = $this->getValidators();
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
progress(
label: 'Validating... ',
steps: $bundles,
callback: fn (Bundle $bundle, $progress) => $this->handleBundle($bundle, $progress, $validators)
);
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
return $this;
}
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
/**
* Handle specific bundle
*/
private function handleBundle(Bundle $bundle, $progress, $validators)
{
$progress->label(sprintf('Validating %s ...', $bundle->getPath()));
foreach ($validators as $metadataFilename => $schema) {
$progress->hint(sprintf('Validating %s ...', $metadataFilename));
$filepath = $bundle->metadata($metadataFilename)->getFilename();
if (!$this->sourceDisk->exists($filepath)) {
continue;
2024-04-26 12:50:38 +02:00
}
2024-05-06 22:11:20 +02:00
$source = $this->sourceDisk->get($filepath) ?? '{}';
$data = json_decode($source);
$validator = new Validator();
$validator->validate($data, $schema);
if (!$validator->isValid()) {
$this->invalid[$bundle->getPath()] = [
'metadata' => $metadataFilename,
'errors' => $validator->getErrors(),
];
2024-04-26 12:50:38 +02:00
}
}
2024-05-06 22:11:20 +02:00
}
2024-04-26 12:50:38 +02:00
2024-05-06 22:11:20 +02:00
/**
* Show a report in case of need
*/
private function showReport()
{
if (empty($this->invalid)) {
$this->info('All files are valid');
2024-04-26 12:50:38 +02:00
} else {
2024-05-06 22:11:20 +02:00
$count = count($this->invalid);
$this->error(sprintf('%d invalid %s reported', $count, Str::plural('file', $count)));
$this->newLine(2);
foreach ($this->invalid as $bundlePath => $data) {
$this->line($bundlePath);
$this->line(sprintf(' > In <comment>%s</comment>:', $data['metadata']));
foreach ($data['errors'] as $error) {
$this->line(sprintf(' - %s', $error['message']));
}
}
2024-04-26 12:50:38 +02:00
}
}
}