diff --git a/Classes/Validation/Validator/PropertiesValidator.php b/Classes/Validation/Validator/PropertiesValidator.php new file mode 100644 index 0000000..53964df --- /dev/null +++ b/Classes/Validation/Validator/PropertiesValidator.php @@ -0,0 +1,119 @@ + [[], 'List of validators for properties. ', 'array', true], + 'validationGroups' => [['Default'], 'Same as "Validation Groups" of Flow Framework', 'array'], + ]; + + /** + * @inheritDoc + * @throws InvalidValidationConfigurationException + * @throws NoSuchValidatorException + */ + protected function isValid($value): void + { + $validatorConfigs = []; + + foreach ($this->options['validatorsForProperties'] as $property => $validators) { + foreach ($validators as $validator => $options) { + if ($options === null) { + continue; + } + + $validatorConfigs[] = [ + 'validator' => $validator, + 'options' => $options, + 'property' => $property, + ]; + } + } + + foreach ($validatorConfigs as $validatorConfig) { + if (!$this->doesValidationGroupsMatch($validatorConfig)) { + continue; + } + + $this->handleValidationGroups($validatorConfig); + + $validator = $this->validatorResolver->createValidator( + $validatorConfig['validator'], + $validatorConfig['options'] + ); + + if ($validator === null) { + throw new InvalidValidationConfigurationException( + \sprintf( + 'Validator "%s" could not be resolved. Check your Validation.yaml', + $validatorConfig['validator'] + ), + 1402326139 + ); + } + + $this->getResult()->forProperty($validatorConfig['property'])->merge( + $validator->validate(ObjectAccess::getPropertyPath($value, $validatorConfig['property'])) + ); + } + } + + /** + * Check whether at least one configured group does match, if any is configured. + * + * @param array $validatorConfig + * @return bool + */ + protected function doesValidationGroupsMatch(array $validatorConfig): bool + { + return !isset($validatorConfig['options']['validationGroups']) + || \array_intersect( + $validatorConfig['options']['validationGroups'], + $this->options['validationGroups'] + ) !== []; + } + + /** + * Add validation groups for recursion if necessary. + * + * @param array $validatorConfig + */ + protected function handleValidationGroups(array &$validatorConfig): void + { + if ($validatorConfig['validator'] === 'DigiComp.SettingValidator:Settings') { + $validatorConfig['options']['validationGroups'] = $this->options['validationGroups']; + } elseif (isset($validatorConfig['options']['validationGroups'])) { + unset($validatorConfig['options']['validationGroups']); + } + } +} diff --git a/Classes/Validation/Validator/SettingsValidator.php b/Classes/Validation/Validator/SettingsValidator.php index 46715de..5801bc4 100644 --- a/Classes/Validation/Validator/SettingsValidator.php +++ b/Classes/Validation/Validator/SettingsValidator.php @@ -20,7 +20,6 @@ use Neos\Flow\Validation\Exception\InvalidValidationOptionsException; use Neos\Flow\Validation\Exception\NoSuchValidatorException; use Neos\Flow\Validation\Validator\AbstractValidator; use Neos\Flow\Validation\ValidatorResolver; -use Neos\Utility\ObjectAccess; use Neos\Utility\TypeHandling; /** @@ -66,7 +65,44 @@ class SettingsValidator extends AbstractValidator ); } - foreach ($this->getConfigForValidation($validations[$name]) as $validatorConfig) { + // @deprecated - converts old "self" to new structure + if (isset($validations[$name]['self'])) { + foreach ($validations[$name]['self'] as $validator => $options) { + if (isset($validations[$name][$validator])) { + throw new \RuntimeException('The validator "' . $validator . '" is already defined on parent level.', 1725000364); + } + $validations[$name][$validator] = $options; + } + + unset($validations[$name]['self']); + } + + // @deprecated - converts old "properties" to new structure + if (isset($validations[$name]['properties'])) { + if (isset($validations[$name]['DigiComp.SettingValidator:Properties'])) { + throw new \RuntimeException('The validator "DigiComp.SettingValidator:Properties" is already defined on parent level.', 1725000396); + } + $validations[$name]['DigiComp.SettingValidator:Properties'] = [ + 'validatorsForProperties' => $validations[$name]['properties'], + ]; + + unset($validations[$name]['properties']); + } + + $validatorConfigs = []; + + foreach ($validations[$name] as $validator => $options) { + if ($options === null) { + continue; + } + + $validatorConfigs[] = [ + 'validator' => $validator, + 'options' => $options, + ]; + } + + foreach ($validatorConfigs as $validatorConfig) { if (!$this->doesValidationGroupsMatch($validatorConfig)) { continue; } @@ -88,54 +124,10 @@ class SettingsValidator extends AbstractValidator ); } - if (isset($validatorConfig['property'])) { - $this->getResult()->forProperty($validatorConfig['property'])->merge( - $validator->validate(ObjectAccess::getPropertyPath($value, $validatorConfig['property'])) - ); - } else { - $this->getResult()->merge($validator->validate($value)); - } + $this->getResult()->merge($validator->validate($value)); } } - /** - * @param array $validation - * @return array - */ - protected function getConfigForValidation(array $validation): array - { - $config = []; - - if (isset($validation['self'])) { - foreach ($validation['self'] as $validator => $options) { - if ($options === null) { - continue; - } - $config[] = [ - 'validator' => $validator, - 'options' => $options, - ]; - } - } - - if (isset($validation['properties'])) { - foreach ($validation['properties'] as $property => $propertyValidation) { - foreach ($propertyValidation as $validator => $options) { - if ($options === null) { - continue; - } - $config[] = [ - 'property' => $property, - 'validator' => $validator, - 'options' => $options, - ]; - } - } - } - - return $config; - } - /** * Check whether at least one configured group does match, if any is configured. *