-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split configuration processing to different services. Implement schem…
…a configuration validation and nesting loading. Add schema validation console command.
- Loading branch information
Showing
18 changed files
with
1,744 additions
and
715 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.