From da4f409a8de933277cf7ac03050684cd141d431c Mon Sep 17 00:00:00 2001 From: Robin Krahnen Date: Fri, 30 Aug 2024 14:47:28 +0200 Subject: [PATCH] add conditional validator to allow more flexible configuration --- .../Validator/ConditionalValidator.php | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Classes/Validation/Validator/ConditionalValidator.php diff --git a/Classes/Validation/Validator/ConditionalValidator.php b/Classes/Validation/Validator/ConditionalValidator.php new file mode 100644 index 0000000..53b49da --- /dev/null +++ b/Classes/Validation/Validator/ConditionalValidator.php @@ -0,0 +1,152 @@ + [[], 'List of entries with "condition" (eel expression) and "validators" (list of validators).', 'array', true], + 'fallbackValidators' => [[], 'List of validators that is used if no condition matched.', 'array'], + 'validationGroups' => [['Default'], 'Same as "Validation Groups" of Flow Framework', 'array'], + ]; + + /** + * @inheritDoc + * @throws InvalidValidationConfigurationException + * @throws NeosEelException + * @throws NoSuchValidatorException + */ + protected function isValid($value): void + { + $validatorConfigs = []; + + $hasMatch = false; + + foreach ($this->options['conditions'] as $condition) { + if ($this->eelEvaluator instanceof DependencyProxy) { + $this->eelEvaluator->_activateDependency(); + } + + if (!Utility::evaluateEelExpression($condition['condition'], $this->eelEvaluator, ['this' => $value])) { + continue; + } + + $hasMatch = true; + + foreach ($condition['validators'] as $validator => $options) { + if ($options === null) { + continue; + } + + $validatorConfigs[] = [ + 'validator' => $validator, + 'options' => $options, + ]; + } + } + + if (!$hasMatch) { + foreach ($this->options['fallbackValidators'] as $validator => $options) { + if ($options === null) { + continue; + } + + $validatorConfigs[] = [ + 'validator' => $validator, + 'options' => $options, + ]; + } + } + + 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()->merge($validator->validate($value)); + } + } + + /** + * 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']); + } + } +}