diff --git a/js/forms/forms.js b/js/forms/forms.js index 7e36cd763..e2f1820fe 100644 --- a/js/forms/forms.js +++ b/js/forms/forms.js @@ -14,6 +14,8 @@ function triggerTurbo(el) { el.form.querySelector(`[name="${sFormName}[_turbo_trigger]"]`).value = el.getAttribute('name'); el.form.setAttribute('novalidate', true); el.form.requestSubmit(); + el.form.querySelector(`[name="${sFormName}[_turbo_trigger]"]`).value = null; + el.form.setAttribute('novalidate', false); $aFormBlockDataTransmittedData[name] = el.value; } diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index c52174e45..c3a3e74a4 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -534,6 +534,8 @@ return array( 'Combodo\\iTop\\Forms\\Register\\OptionsRegister' => $baseDir . '/sources/Forms/Register/OptionsRegister.php', 'Combodo\\iTop\\Forms\\Register\\RegisterException' => $baseDir . '/sources/Forms/Register/RegisterException.php', 'Combodo\\iTop\\Forms\\Twig\\Extension\\FormCompatibilityExtension' => $baseDir . '/sources/Forms/Twig/Extension/FormCompatibilityExtension.php', + 'Combodo\\iTop\\Forms\\Validator\\AttributeExist' => $baseDir . '/sources/Forms/Validator/AttributeExist.php', + 'Combodo\\iTop\\Forms\\Validator\\AttributeExistValidator' => $baseDir . '/sources/Forms/Validator/AttributeExistValidator.php', 'Combodo\\iTop\\PhpParser\\Evaluation\\PhpExpressionEvaluator' => $baseDir . '/sources/PhpParser/Evaluation/PhpExpressionEvaluator.php', 'Combodo\\iTop\\Renderer\\BlockRenderer' => $baseDir . '/sources/Renderer/BlockRenderer.php', 'Combodo\\iTop\\Renderer\\Bootstrap\\BsFieldRendererMappings' => $baseDir . '/sources/Renderer/Bootstrap/BsFieldRendererMappings.php', @@ -3343,7 +3345,6 @@ return array( 'Symfony\\Component\\Validator\\Mapping\\PropertyMetadataInterface' => $vendorDir . '/symfony/validator/Mapping/PropertyMetadataInterface.php', 'Symfony\\Component\\Validator\\Mapping\\TraversalStrategy' => $vendorDir . '/symfony/validator/Mapping/TraversalStrategy.php', 'Symfony\\Component\\Validator\\ObjectInitializerInterface' => $vendorDir . '/symfony/validator/ObjectInitializerInterface.php', - 'Symfony\\Component\\Validator\\Test\\ConstraintValidatorTestCase' => $vendorDir . '/symfony/validator/Test/ConstraintValidatorTestCase.php', 'Symfony\\Component\\Validator\\Util\\PropertyPath' => $vendorDir . '/symfony/validator/Util/PropertyPath.php', 'Symfony\\Component\\Validator\\Validation' => $vendorDir . '/symfony/validator/Validation.php', 'Symfony\\Component\\Validator\\ValidatorBuilder' => $vendorDir . '/symfony/validator/ValidatorBuilder.php', @@ -3893,5 +3894,5 @@ return array( 'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php', 'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php', 'utils' => $baseDir . '/application/utils.inc.php', - '©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', + '�' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', ); diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index b2d02aab0..1c266fd0c 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -920,6 +920,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Forms\\Register\\OptionsRegister' => __DIR__ . '/../..' . '/sources/Forms/Register/OptionsRegister.php', 'Combodo\\iTop\\Forms\\Register\\RegisterException' => __DIR__ . '/../..' . '/sources/Forms/Register/RegisterException.php', 'Combodo\\iTop\\Forms\\Twig\\Extension\\FormCompatibilityExtension' => __DIR__ . '/../..' . '/sources/Forms/Twig/Extension/FormCompatibilityExtension.php', + 'Combodo\\iTop\\Forms\\Validator\\AttributeExist' => __DIR__ . '/../..' . '/sources/Forms/Validator/AttributeExist.php', + 'Combodo\\iTop\\Forms\\Validator\\AttributeExistValidator' => __DIR__ . '/../..' . '/sources/Forms/Validator/AttributeExistValidator.php', 'Combodo\\iTop\\PhpParser\\Evaluation\\PhpExpressionEvaluator' => __DIR__ . '/../..' . '/sources/PhpParser/Evaluation/PhpExpressionEvaluator.php', 'Combodo\\iTop\\Renderer\\BlockRenderer' => __DIR__ . '/../..' . '/sources/Renderer/BlockRenderer.php', 'Combodo\\iTop\\Renderer\\Bootstrap\\BsFieldRendererMappings' => __DIR__ . '/../..' . '/sources/Renderer/Bootstrap/BsFieldRendererMappings.php', @@ -3729,7 +3731,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\Validator\\Mapping\\PropertyMetadataInterface' => __DIR__ . '/..' . '/symfony/validator/Mapping/PropertyMetadataInterface.php', 'Symfony\\Component\\Validator\\Mapping\\TraversalStrategy' => __DIR__ . '/..' . '/symfony/validator/Mapping/TraversalStrategy.php', 'Symfony\\Component\\Validator\\ObjectInitializerInterface' => __DIR__ . '/..' . '/symfony/validator/ObjectInitializerInterface.php', - 'Symfony\\Component\\Validator\\Test\\ConstraintValidatorTestCase' => __DIR__ . '/..' . '/symfony/validator/Test/ConstraintValidatorTestCase.php', 'Symfony\\Component\\Validator\\Util\\PropertyPath' => __DIR__ . '/..' . '/symfony/validator/Util/PropertyPath.php', 'Symfony\\Component\\Validator\\Validation' => __DIR__ . '/..' . '/symfony/validator/Validation.php', 'Symfony\\Component\\Validator\\ValidatorBuilder' => __DIR__ . '/..' . '/symfony/validator/ValidatorBuilder.php', @@ -4279,7 +4280,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', 'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php', 'utils' => __DIR__ . '/../..' . '/application/utils.inc.php', - '©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', + '�' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/sources/Forms/FormBuilder/FormBuilder.php b/sources/Forms/FormBuilder/FormBuilder.php index e3596a951..97d9f2034 100644 --- a/sources/Forms/FormBuilder/FormBuilder.php +++ b/sources/Forms/FormBuilder/FormBuilder.php @@ -95,9 +95,12 @@ class FormBuilder implements FormBuilderInterface, IteratorAggregate $oFormBlock->oDependencyMap = $this->oDependencyHandler->GetMap(); } - if (is_null($oFormBlock->GetParent())) { + if ($oFormBlock->IsRootBlock()) { // Insert a hidden type to save the place - $this->builder->add('_turbo_trigger', HiddenType::class, ['prevent_form_build' => true]); + $this->builder->add('_turbo_trigger', HiddenType::class, [ + 'prevent_form_build' => true, + 'mapped' => false, + ]); } } diff --git a/sources/Forms/Forms.php b/sources/Forms/Forms.php index decc1ac34..1719c452d 100644 --- a/sources/Forms/Forms.php +++ b/sources/Forms/Forms.php @@ -38,7 +38,9 @@ final class Forms public static function createFormFactoryBuilder(): FormFactoryBuilderInterface { // Set up the Validator component - $validator = Validation::createValidator(); + $validator = Validation::createValidatorBuilder() + ->enableAttributeMapping()->getValidator(); + return (new FormFactoryBuilder()) ->addExtension(new HttpFoundationExtension()) ->addExtension(new ValidatorExtension($validator)) diff --git a/sources/Forms/IO/Converter/OqlToClassConverter.php b/sources/Forms/IO/Converter/OqlToClassConverter.php index cb1a90f7a..d5520c7cb 100644 --- a/sources/Forms/IO/Converter/OqlToClassConverter.php +++ b/sources/Forms/IO/Converter/OqlToClassConverter.php @@ -36,8 +36,6 @@ class OqlToClassConverter extends AbstractConverter $oModelReflection = DIService::GetInstance()->GetService('ModelReflection'); try { $oQuery = $oModelReflection->GetQuery($oData); - } catch (\OQLParserException $e) { - throw new FormBlockIOException($e->GetIssue(), $e->getCode(), $e); } catch (Exception $e) { throw new FormBlockIOException($e->getMessage(), $e->getCode(), $e); } diff --git a/sources/Forms/Validator/AttributeExist.php b/sources/Forms/Validator/AttributeExist.php new file mode 100644 index 000000000..001f94baf --- /dev/null +++ b/sources/Forms/Validator/AttributeExist.php @@ -0,0 +1,68 @@ + $sOqlPropertyPath, + ], $aOptions); + + parent::__construct($aOptions, $aGroups, $oPayload); + + // Retrieve options + $this->sFilter = $sFilter; + $this->sOqlPropertyPath = $aOptions['sOqlPropertyPath']; + } + + public function getDefaultOption(): string + { + return 'sOqlPropertyPath'; + } + + public function getRequiredOptions(): array + { + return ['sOqlPropertyPath']; + } +} diff --git a/sources/Forms/Validator/AttributeExistValidator.php b/sources/Forms/Validator/AttributeExistValidator.php new file mode 100644 index 000000000..ab364b6f2 --- /dev/null +++ b/sources/Forms/Validator/AttributeExistValidator.php @@ -0,0 +1,57 @@ +propertyAccessor = PropertyAccess::createPropertyAccessor(); + } + + /** + * @inheritDoc + */ + public function validate(mixed $value, Constraint $constraint): void + { + $sOql = $this->propertyAccessor->getValue($this->context->getObject(), $constraint->sOqlPropertyPath); + + $oOqlToClassConverter = new OqlToClassConverter(); + $sClass = strval($oOqlToClassConverter->Convert($sOql)); + + $sClass = "UserRequest"; + + /** List attributes @var ModelReflection $oModelReflection */ + $oModelReflection = DIService::GetInstance()->GetService('ModelReflection'); + $aAttributeCodes = array_keys($oModelReflection->ListAttributes($sClass)); + + if (!in_array($value, $aAttributeCodes, true)) { + $this->context->buildViolation($constraint->sMessage) + ->setParameter('{{ attribute }}', $value) + ->setParameter('{{ class }}', $sClass) + ->setParameter('{{ oql }}', $sOql) + ->addViolation(); + } + + } +}