Skip to content

Commit

Permalink
Validate CSV file by applying schema rules. If errors are found, disp…
Browse files Browse the repository at this point in the history
…lay error messages with details. If no errors are found, display "Looks good!" message.
  • Loading branch information
Denis Smet committed Mar 10, 2024
1 parent e646c1b commit 8daa1fe
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 155 deletions.
92 changes: 92 additions & 0 deletions src/Commands/ValidateCsv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

/**
* JBZoo Toolbox - Csv-Blueprint.
*
* This file is part of the JBZoo Toolbox project.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT
* @copyright Copyright (C) JBZoo.com, All rights reserved.
* @see https://github.com/JBZoo/Csv-Blueprint
*/

declare(strict_types=1);

namespace JBZoo\CsvBlueprint\Commands;

use JBZoo\Cli\CliCommand;
use JBZoo\Cli\OutLvl;
use JBZoo\CsvBlueprint\Csv\CsvFile;
use JBZoo\CsvBlueprint\Exception;
use JBZoo\CsvBlueprint\Validators\ErrorSuite;
use Symfony\Component\Console\Input\InputOption;

final class ValidateCsv extends CliCommand
{
protected function configure(): void
{
$this
->setName('validate:csv')
->setDescription('Validate CSV file by rule')
->addOption(
'csv',
'c',
InputOption::VALUE_REQUIRED,
'CSV filepath to validate. If not set or empty, then the STDIN is used.',
)
->addOption(
'schema',
's',
InputOption::VALUE_REQUIRED,
'Schema rule filepath',
);

parent::configure();
}

protected function executeAction(): int
{
$csvFilename = $this->getCsvFilepath();
$schemaFilename = $this->getSchemaFilepath();

$csvFile = new CsvFile($csvFilename, $schemaFilename);
$errorSuite = $csvFile->validate();
if ($errorSuite->count() > 0) {
$this->_($errorSuite->render(ErrorSuite::RENDER_TEXT), OutLvl::ERROR);

throw new Exception('CSV file is not valid! Found ' . $errorSuite->count() . ' errors.');
}

$this->_('<green>Looks good!</green>');

return self::SUCCESS;
}

private function getCsvFilepath(): string
{
$csvFilename = $this->getOptString('csv');

if (\file_exists($csvFilename) === false) {
throw new Exception("CSV file not found: {$csvFilename}");
}

$this->_('<blue>CSV :</blue> ' . \str_replace(PATH_ROOT, '.', \realpath($csvFilename)));

return $csvFilename;
}

private function getSchemaFilepath(): string
{
$schemaFilename = $this->getOptString('schema');

if (\file_exists($schemaFilename) === false) {
throw new Exception("Schema file not found: {$schemaFilename}");
}

$this->_('<blue>Schema :</blue> ' . \str_replace(PATH_ROOT, '.', \realpath($schemaFilename)));

return $schemaFilename;
}
}
52 changes: 0 additions & 52 deletions src/Commands/ValidateFile.php

This file was deleted.

5 changes: 3 additions & 2 deletions src/Csv/CsvFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ private function validateHeader(): ErrorSuite
if ($column->getName() === '') {
$error = new Error(
'csv_structure.header',
"Property \"name\" is not defined in schema: {$this->schema->getFilename()}",
"Property \"name\" is not defined in schema: \"{$this->schema->getFilename()}\"",
$column->getHumanName(),
1,
);

$errors->addError($error);
Expand All @@ -146,7 +147,7 @@ private function validateEachCell(bool $quickStop = false): ErrorSuite
continue;
}

$errors->addErrorSuit($column->validate($record[$column->getKey()], $line));
$errors->addErrorSuit($column->validate($record[$column->getKey()], $line + 1));
if ($quickStop && $errors->count() > 0) {
return $errorAcc;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Validators/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function __construct(

public function __toString(): string
{
return "Error \"{$this->getRuleCode()}\" at line {$this->getLine()}, " .
return "\"{$this->getRuleCode()}\" at line {$this->getLine()}, " .
"column \"{$this->getColumnName()}\". {$this->getMessage()}.";
}

Expand Down
14 changes: 7 additions & 7 deletions src/Validators/ErrorSuite.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,28 @@

final class ErrorSuite
{
public const MODE_PLAIN_TEXT = 'plain';
public const MODE_PLAIN_LIST = 'list';
public const RENDER_TEXT = 'plain';
public const RENDER_LIST = 'list';

/** @var Error[] */
private array $errors = [];

public function __toString(): string
{
return $this->render(self::MODE_PLAIN_TEXT);
return $this->render(self::RENDER_TEXT);
}

public function render(string $mode = self::MODE_PLAIN_TEXT): string
public function render(string $mode = self::RENDER_TEXT): string
{
if ($this->count() === 0) {
return '';
}

if ($mode === self::MODE_PLAIN_TEXT) {
if ($mode === self::RENDER_TEXT) {
return $this->renderPlainText();
}

if ($mode === self::MODE_PLAIN_LIST) {
if ($mode === self::RENDER_LIST) {
return $this->renderList();
}

Expand Down Expand Up @@ -105,6 +105,6 @@ private function renderList(): string
$result[] = (string)$error;
}

return ' * ' . \implode("\n * ", $result) . "\n";
return ' * ' . \implode("\n * ", $result);
}
}
Loading

0 comments on commit 8daa1fe

Please sign in to comment.