Skip to content

Commit

Permalink
Split configuration processing to different services. Implement schem…
Browse files Browse the repository at this point in the history
…a configuration validation and nesting loading. Add schema validation console command.
  • Loading branch information
Nitro-N committed Jul 12, 2021
1 parent 46a0f67 commit a69202e
Show file tree
Hide file tree
Showing 18 changed files with 1,744 additions and 715 deletions.
105 changes: 105 additions & 0 deletions Command/ValidateDataSchemaCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

namespace Glavweb\DataSchemaBundle\Command;

use Glavweb\DataSchemaBundle\Service\DataSchemaValidator;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;

class ValidateDataSchemaCommand extends ContainerAwareCommand
{
/**
* Configure
*/
protected function configure()
{
$this->setName('glavweb:data-schema:validate')
->setDescription('Validates data schema configuration file')
->addArgument(
'path',
InputArgument::OPTIONAL,
'File path relative to directory defined in "data_schema.dir" bundle configuration parameter. Validates all files in folder if not specified.'
);
}

/**
* @inheritDoc
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var DataSchemaValidator $dataSchemaValidator */
$dataSchemaValidator = $this->getContainer()->get('glavweb_data_schema.validator');
$rootDir = $this->getContainer()->getParameter('glavweb_data_schema.data_schema_dir');
$nestingDepth = $this->getContainer()->getParameter('glavweb_data_schema.data_schema_max_nesting_depth');

$successful = false;
$path = $input->getArgument('path');

$output->writeln(
[
'DataSchema Validator',
'====================',
'',
]
);

if ($path) {
try {
$dataSchemaValidator->validateFile($path, $nestingDepth);

$successful = true;
$output->writeln('<info>Validation successful</info>');

} catch (\Exception $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
$output->writeln('<error>Validation failed</error>');
}

} else {
$finder = new Finder();
$finder->in($rootDir)->files();
$totalCount = $finder->count();
$errorsCount = 0;

if (!$totalCount) {
$output->writeln(sprintf('<comment>Files not found in "%s" directory</comment>', $rootDir));

return 0;
}

$output->writeln([sprintf('<info>Validating %s configuration files...</info>', $totalCount), '']);

foreach ($finder as $file) {
try {
$dataSchemaValidator->validateFile($file->getRelativePathname(), $nestingDepth);
} catch (\Exception $e) {
$errorsCount++;

$output->writeln(
[
sprintf('%s:', $file->getRelativePathname()),
'--------------------',
sprintf('<comment>%s</comment>', $e->getMessage()),
''
]
);
}
}

if ($errorsCount) {
$output->writeln(
sprintf('<error>Validation failed. %s configuration files have errors.</error>', $errorsCount)
);

} else {
$successful = true;
$output->writeln('<info>Validation successful</info>');
}
}

return $successful ? 0 : 1;
}
}
125 changes: 125 additions & 0 deletions Configuration/DataSchemaConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

namespace Glavweb\DataSchemaBundle\Configuration;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class DataSchemaConfiguration implements ConfigurationInterface
{
/**
* @var int
*/
private $nestingDepth;

/**
* DataSchemaConfiguration constructor.
*
* @param int $nestingDepth
*/
public function __construct(int $nestingDepth = 0)
{
$this->nestingDepth = $nestingDepth;
}

/**
* @inheritDoc
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();

$rootNode = $treeBuilder->root('schema');

$rootNode
->children()
->scalarNode('schema')
->end()
->enumNode('db_driver')
->isRequired()
->values(['orm'])
->end()
->scalarNode('class')
->isRequired()
->end()
->arrayNode('roles')
->beforeNormalization()
->castToArray()
->end()
->end()
->booleanNode('filter_null_values')
->defaultTrue()
->end()
->arrayNode('query')
->addDefaultsIfNotSet()
->children()
->arrayNode('selects')
->useAttributeAsKey('name')
->scalarPrototype()->end()
->end()
->end()
->end()
->append($this->addPropertiesNode($this->nestingDepth))
->end()
;


return $treeBuilder;
}

public function addPropertiesNode($depth)
{
$treeBuilder = new TreeBuilder();

$rootNode = $treeBuilder->root('properties');

if ($depth === 0) {
return $rootNode;
}

$rootNode
->useAttributeAsKey('name')
->arrayPrototype()
->children()
->scalarNode('schema')
->defaultNull()
->end()
->scalarNode('class')
->defaultNull()
->end()
->scalarNode('description')
->defaultNull()
->end()
->scalarNode('discriminator')
->defaultNull()
->end()
->booleanNode('filter_null_values')
->defaultTrue()
->end()
->enumNode('join')
->defaultValue('none')
->values(['none', 'left', 'inner'])
->end()
->scalarNode('type')
->defaultNull()
->end()
->scalarNode('source')
->defaultNull()
->end()
->scalarNode('decode')
->defaultNull()
->end()
->scalarNode('hidden')
->defaultFalse()
->end()
->arrayNode('conditions')
->scalarPrototype()->end()
->end()
->end()
->append($this->addPropertiesNode(--$depth))
->end()
;

return $rootNode;
}
}
Loading

0 comments on commit a69202e

Please sign in to comment.