diff --git a/composer.json b/composer.json index 9c94b94..4fa9f04 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "symfony/http-kernel": ">=6.0", "symfony/dependency-injection": ">=6.0", "symfony/config": ">=6.0", - "swaggest/json-schema": ">=0.12.41" + "swaggest/json-schema": ">=0.12.41", + "opis/json-schema": "^2.3" }, "require-dev": { "vimeo/psalm": "5.x-dev" diff --git a/config/services.php b/config/services.php index 06e3de7..b3a51d6 100644 --- a/config/services.php +++ b/config/services.php @@ -5,6 +5,7 @@ use KnpLabs\JsonSchema\Collection; use KnpLabs\JsonSchema\JsonSchemaInterface; use KnpLabs\JsonSchemaBundle\RequestHandler; +use KnpLabs\JsonSchemaBundle\Validator\OpisValidator; use KnpLabs\JsonSchemaBundle\Validator\SwaggestValidator; return function(ContainerConfigurator $configurator) { @@ -19,7 +20,7 @@ ; $services->set(SwaggestValidator::class); - $services->alias('KnpLabs\JsonSchema\Validator', SwaggestValidator::class); + $services->set(OpisValidator::class); $services->set(Collection::class) ->arg('$schemas', tagged_iterator('knp.json_schema')) diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php new file mode 100644 index 0000000..62fa931 --- /dev/null +++ b/src/DependencyInjection/Configuration.php @@ -0,0 +1,27 @@ +getRootNode() + ->children() + ->enumNode('validator') + ->values(['OpisValidator', 'SwaggestValidator']) + ->defaultValue('SwaggestValidator') + ->end() + ->end() + ; + + return $treeBuilder; + } +} diff --git a/src/DependencyInjection/JsonSchemaExtension.php b/src/DependencyInjection/JsonSchemaExtension.php index 0ababdd..e542d00 100644 --- a/src/DependencyInjection/JsonSchemaExtension.php +++ b/src/DependencyInjection/JsonSchemaExtension.php @@ -14,6 +14,10 @@ class JsonSchemaExtension extends Extension { public function load(array $configs, ContainerBuilder $container): void { + $configuration = new Configuration(); + + $config = $this->processConfiguration($configuration, $configs); + $loader = new PhpFileLoader( $container, new FileLocator(__DIR__ . '/../../config') @@ -21,6 +25,11 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('services.php'); + $container->setAlias( + 'KnpLabs\JsonSchema\Validator', + sprintf('KnpLabs\\JsonSchemaBundle\\Validator\\%s', $config['validator']) + ); + $container ->registerForAutoconfiguration(JsonSchemaInterface::class) ->addTag('knp.json_schema') diff --git a/src/Validator/OpisValidator.php b/src/Validator/OpisValidator.php new file mode 100644 index 0000000..cde0a56 --- /dev/null +++ b/src/Validator/OpisValidator.php @@ -0,0 +1,78 @@ +validator = new JsonSchemaValidator(); + $this->validator->setMaxErrors(10); + } + + public function validate(array $data, JsonSchemaInterface $schema): ?Errors + { + /** + * @var mixed + */ + $data = json_decode( + json_encode( + $data, + flags: JSON_THROW_ON_ERROR, + ), + flags: JSON_THROW_ON_ERROR + ); + + $schema = json_decode( + json_encode( + $schema->getSchema(), + flags: JSON_THROW_ON_ERROR, + ), + flags: JSON_THROW_ON_ERROR + ); + + $result = $this->validator->validate($data, $schema); + + if ($result->isValid()) { + return null; + } + + return new Errors( + ...$this->yieldErrors($result->error()) + ); + } + + /** + * @return iterable + */ + private function yieldErrors(ValidationError $error): iterable + { + $formatter = new ErrorFormatter(); + + $errors = $formatter->format($error); + + foreach ($errors as $field => $message) { + $formatted = sizeof($message) === 1 + ? $message[0] + : json_encode($message) + ; + + yield new KnpJsonSchemaError( + $field, + $formatted, + ); + } + } +}