diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 963b54e032..0d3415edb6 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -480,13 +480,14 @@ return array( 'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeValueChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/OqlFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\FormBlock' => $baseDir . '/sources/Forms/Block/FormBlock.php', + 'Combodo\\iTop\\Forms\\Block\\FormBlockException' => $baseDir . '/sources/Forms/Block/FormBlockException.php', 'Combodo\\iTop\\Forms\\Block\\FormInput' => $baseDir . '/sources/Forms/Block/FormInput.php', 'Combodo\\iTop\\Forms\\Block\\FormOutput' => $baseDir . '/sources/Forms/Block/FormOutput.php', 'Combodo\\iTop\\Forms\\Converter\\AbstractConverter' => $baseDir . '/sources/Forms/Converter/AbstractConverter.php', 'Combodo\\iTop\\Forms\\Converter\\OqlToClassName' => $baseDir . '/sources/Forms/Converter/OqlToClassName.php', - 'Combodo\\iTop\\Forms\\Dependency\\DependencyDescription' => $baseDir . '/sources/Forms/Dependency/DependencyDescription.php', - 'Combodo\\iTop\\Forms\\Dependency\\DependencyHandler' => $baseDir . '/sources/Forms/Dependency/DependencyHandler.php', + 'Combodo\\iTop\\Forms\\FormBuilder\\DependencyHandler' => $baseDir . '/sources/Forms/FormBuilder/DependencyHandler.php', 'Combodo\\iTop\\Forms\\FormBuilder\\FormBuilder' => $baseDir . '/sources/Forms/FormBuilder/FormBuilder.php', + 'Combodo\\iTop\\Forms\\FormBuilder\\FormBuilderException' => $baseDir . '/sources/Forms/FormBuilder/FormBuilderException.php', 'Combodo\\iTop\\Forms\\FormBuilder\\FormTypeExtension' => $baseDir . '/sources/Forms/FormBuilder/FormTypeExtension.php', 'Combodo\\iTop\\Forms\\FormBuilder\\ResolvedFormType' => $baseDir . '/sources/Forms/FormBuilder/ResolvedFormType.php', 'Combodo\\iTop\\Forms\\FormBuilder\\ResolvedFormTypeFactory' => $baseDir . '/sources/Forms/FormBuilder/ResolvedFormTypeFactory.php', @@ -494,6 +495,7 @@ return array( 'Combodo\\iTop\\Forms\\FormType\\AttributeValueChoiceType' => $baseDir . '/sources/Forms/FormType/AttributeValueChoiceType.php', 'Combodo\\iTop\\Forms\\FormType\\OqlType' => $baseDir . '/sources/Forms/FormType/OqlType.php', 'Combodo\\iTop\\Forms\\Forms' => $baseDir . '/sources/Forms/Forms.php', + 'Combodo\\iTop\\Forms\\FormsException' => $baseDir . '/sources/Forms/FormsException.php', 'Combodo\\iTop\\Forms\\Twig\\Extension\\FormCompatibilityExtension' => $baseDir . '/sources/Forms/Twig/Extension/FormCompatibilityExtension.php', 'Combodo\\iTop\\PhpParser\\Evaluation\\PhpExpressionEvaluator' => $baseDir . '/sources/PhpParser/Evaluation/PhpExpressionEvaluator.php', 'Combodo\\iTop\\Renderer\\BlockRenderer' => $baseDir . '/sources/Renderer/BlockRenderer.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 027a597258..be1f8c67ea 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -861,13 +861,14 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeValueChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/OqlFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\FormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/FormBlock.php', + 'Combodo\\iTop\\Forms\\Block\\FormBlockException' => __DIR__ . '/../..' . '/sources/Forms/Block/FormBlockException.php', 'Combodo\\iTop\\Forms\\Block\\FormInput' => __DIR__ . '/../..' . '/sources/Forms/Block/FormInput.php', 'Combodo\\iTop\\Forms\\Block\\FormOutput' => __DIR__ . '/../..' . '/sources/Forms/Block/FormOutput.php', 'Combodo\\iTop\\Forms\\Converter\\AbstractConverter' => __DIR__ . '/../..' . '/sources/Forms/Converter/AbstractConverter.php', 'Combodo\\iTop\\Forms\\Converter\\OqlToClassName' => __DIR__ . '/../..' . '/sources/Forms/Converter/OqlToClassName.php', - 'Combodo\\iTop\\Forms\\Dependency\\DependencyDescription' => __DIR__ . '/../..' . '/sources/Forms/Dependency/DependencyDescription.php', - 'Combodo\\iTop\\Forms\\Dependency\\DependencyHandler' => __DIR__ . '/../..' . '/sources/Forms/Dependency/DependencyHandler.php', + 'Combodo\\iTop\\Forms\\FormBuilder\\DependencyHandler' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/DependencyHandler.php', 'Combodo\\iTop\\Forms\\FormBuilder\\FormBuilder' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/FormBuilder.php', + 'Combodo\\iTop\\Forms\\FormBuilder\\FormBuilderException' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/FormBuilderException.php', 'Combodo\\iTop\\Forms\\FormBuilder\\FormTypeExtension' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/FormTypeExtension.php', 'Combodo\\iTop\\Forms\\FormBuilder\\ResolvedFormType' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/ResolvedFormType.php', 'Combodo\\iTop\\Forms\\FormBuilder\\ResolvedFormTypeFactory' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/ResolvedFormTypeFactory.php', @@ -875,6 +876,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Forms\\FormType\\AttributeValueChoiceType' => __DIR__ . '/../..' . '/sources/Forms/FormType/AttributeValueChoiceType.php', 'Combodo\\iTop\\Forms\\FormType\\OqlType' => __DIR__ . '/../..' . '/sources/Forms/FormType/OqlType.php', 'Combodo\\iTop\\Forms\\Forms' => __DIR__ . '/../..' . '/sources/Forms/Forms.php', + 'Combodo\\iTop\\Forms\\FormsException' => __DIR__ . '/../..' . '/sources/Forms/FormsException.php', 'Combodo\\iTop\\Forms\\Twig\\Extension\\FormCompatibilityExtension' => __DIR__ . '/../..' . '/sources/Forms/Twig/Extension/FormCompatibilityExtension.php', 'Combodo\\iTop\\PhpParser\\Evaluation\\PhpExpressionEvaluator' => __DIR__ . '/../..' . '/sources/PhpParser/Evaluation/PhpExpressionEvaluator.php', 'Combodo\\iTop\\Renderer\\BlockRenderer' => __DIR__ . '/../..' . '/sources/Renderer/BlockRenderer.php', diff --git a/sources/Forms/Block/AbstractFormBlock.php b/sources/Forms/Block/AbstractFormBlock.php index 87dd97e741..5e56dbdb6a 100644 --- a/sources/Forms/Block/AbstractFormBlock.php +++ b/sources/Forms/Block/AbstractFormBlock.php @@ -69,13 +69,13 @@ abstract class AbstractFormBlock * @param string $sOutputName * * @return $this - * @throws \Combodo\iTop\Forms\Block\FormsBlockException + * @throws \Combodo\iTop\Forms\Block\FormBlockException */ public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock { $oFormInput = $this->GetInput($sInputName); if (is_null($oFormInput)) { - throw new FormsBlockException('Missing input ' . $sInputName . ' for ' . $this->sName); + throw new FormBlockException('Missing input ' . $sInputName . ' for ' . $this->sName); } $oFormInput->Connect($sOutputBlockName, $sOutputName); @@ -92,6 +92,18 @@ abstract class AbstractFormBlock return false; } + public function GetConnections(): array + { + $aConnections = []; + /** @var \Combodo\iTop\Forms\Block\FormInput $oFormInput */ + foreach ($this->aFormInputs as $oFormInput) { + if ($oFormInput->HasConnections()) { + $aConnections[$oFormInput->GetName()] = $oFormInput->GetConnections(); + } + } + return $aConnections; + } + abstract public function GetFormType(): string; abstract public function InitInputs(): void; diff --git a/sources/Forms/Block/DataModel/OqlFormBlock.php b/sources/Forms/Block/DataModel/OqlFormBlock.php index 0a5ba104da..e8fab91d67 100644 --- a/sources/Forms/Block/DataModel/OqlFormBlock.php +++ b/sources/Forms/Block/DataModel/OqlFormBlock.php @@ -4,6 +4,7 @@ namespace Combodo\iTop\Forms\Block\DataModel; use Combodo\iTop\Forms\Block\Base\StringFormBlock; use Combodo\iTop\Forms\Block\FormOutput; +use Combodo\iTop\Forms\Converter\OqlToClassName; class OqlFormBlock extends StringFormBlock { @@ -13,7 +14,7 @@ class OqlFormBlock extends StringFormBlock public function InitOutputs(): void { parent::InitOutputs(); - $this->AddOutput(new FormOutput(self::OUTPUT_SELECTED_CLASS, 'string')); + $this->AddOutput(new FormOutput(self::OUTPUT_SELECTED_CLASS, 'string', new OqlToClassName())); } } \ No newline at end of file diff --git a/sources/Forms/Block/FormsBlockException.php b/sources/Forms/Block/FormBlockException.php similarity index 80% rename from sources/Forms/Block/FormsBlockException.php rename to sources/Forms/Block/FormBlockException.php index d19e99a458..3f114a8ca7 100644 --- a/sources/Forms/Block/FormsBlockException.php +++ b/sources/Forms/Block/FormBlockException.php @@ -8,7 +8,7 @@ namespace Combodo\iTop\Forms\Block; use Combodo\iTop\Forms\FormsException; -class FormsBlockException extends FormsException +class FormBlockException extends FormsException { } \ No newline at end of file diff --git a/sources/Forms/Block/FormInput.php b/sources/Forms/Block/FormInput.php index 7cb124790c..33ef8a9047 100644 --- a/sources/Forms/Block/FormInput.php +++ b/sources/Forms/Block/FormInput.php @@ -38,7 +38,7 @@ class FormInput public function Connect(string $sOutputBlockName, string $sOutputName) { - $this->aConnections[] = ['block' => $sOutputBlockName, 'output' => $sOutputName]; + $this->aConnections[] = ['output_block' => $sOutputBlockName, 'output' => $sOutputName]; } public function GetConnections(): array diff --git a/sources/Forms/Block/FormOutput.php b/sources/Forms/Block/FormOutput.php index 280759b8f7..ba75be92ce 100644 --- a/sources/Forms/Block/FormOutput.php +++ b/sources/Forms/Block/FormOutput.php @@ -11,6 +11,7 @@ class FormOutput private string $sType; private null|AbstractConverter $oConverter; + private array $aValues; public function __construct(string $sName, string $sType, AbstractConverter $oConverter = null) { @@ -39,10 +40,23 @@ class FormOutput $this->sType = $sType; } - public function GetOutputValue(mixed $oData): mixed + public function ConvertValue(mixed $oData): mixed { + if (is_null($this->oConverter)) { + return $oData; + } return $this->oConverter->Convert($oData); } + public function UpdateOutputValue(mixed $oData, string $sEventType): void + { + $this->aValues[$sEventType] = $this->ConvertValue($oData); + } + + public function GetValue(string $sEventType): mixed + { + return $this->aValues[$sEventType] ?? null; + } + } \ No newline at end of file diff --git a/sources/Forms/Dependency/DependencyDescription.php b/sources/Forms/Dependency/DependencyDescription.php deleted file mode 100644 index ac10635d09..0000000000 --- a/sources/Forms/Dependency/DependencyDescription.php +++ /dev/null @@ -1,107 +0,0 @@ -isAdded; - } - - public function SetAdded(bool $bAdded): void - { - $this->isAdded = $bAdded; - } - - public function IsDataReady(string $sEventType): bool - { - $aData = ($sEventType === FormEvents::POST_SET_DATA) ? $this->aPostSetData : $this->aPostSubmitData; - - foreach (array_keys($this->aDependencies) as $sInput){ - if(!array_key_exists($sInput, $aData) || $aData[$sInput] == null){ - return false; - } - } - - return true; - } - - public function IsPostSetDataReady(): bool - { - foreach ($this->aDependencies as $sData => $sValue) { - if (!array_key_exists($sData, $this->aPostSetData)) { - return false; - } - } - return true; - } - - public function IsPostSubmitDataReady(): bool - { - foreach ($this->aDependencies as $sData => $sValue) { - if (!array_key_exists($sData, $this->aPostSubmitData)) { - return false; - } - } - return true; - } - - public function SetData(string $sEventType, string $sData, mixed $oValue): void - { - if($oValue === null) return; - - if($sEventType === FormEvents::POST_SET_DATA){ - $this->aPostSetData[$sData] = $oValue; - } - else{ - $this->aPostSubmitData[$sData] = $oValue; - } - } - - public function GetData(string $sEventType): array - { - if($sEventType === FormEvents::POST_SET_DATA){ - return $this->aPostSetData; - } - else{ - return $this->aPostSubmitData; - } - } - - public function SetPostSetData(string $sInput, mixed $oData): void - { - $this->aPostSetData[$sInput] = $oData; - } - - public function SetPostSubmitData(string $sInput, mixed $oData): void - { - $this->aPostSubmitData[$sInput] = $oData; - } - - public function IsReady(string $sEventType): bool - { - $aData = ($sEventType === FormEvents::POST_SET_DATA) ? $this->aPostSetData : $this->aPostSubmitData; - - foreach (array_keys($this->aDependencies) as $sInput){ - if(!array_key_exists($sInput, $aData)){ - return false; - } - } - - return true; - } -} \ No newline at end of file diff --git a/sources/Forms/Dependency/DependencyHandler.php b/sources/Forms/Dependency/DependencyHandler.php index 3bba15ff56..7005c60c37 100644 --- a/sources/Forms/Dependency/DependencyHandler.php +++ b/sources/Forms/Dependency/DependencyHandler.php @@ -1,172 +1,172 @@ addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { - $oForm = $event->getForm(); - $this->InitializeDependenciesMap($oForm); - }); - } - - /** - *Initialize the dependencies map and register listeners on the dependencies inputs. - * - * @param FormInterface $oForm - * - * @return void - */ - private function InitializeDependenciesMap(FormInterface $oForm): void - { - - /** iterate throw dependencies descriptions... @var DependencyDescription $oDependencyDescription */ - foreach ($this->aDependenciesDescription as $oDependencyDescription) { - - /** iterate throw dependencies items... */ - foreach ($oDependencyDescription->aDependencies as $sInput => $aData) { - - // get the dependency field name - $sDependency = $aData['source']; - - // get the field input name - $sOutput = array_key_exists('output', $aData) ? $aData['output'] : null; - - // add the dependency to the map - if(!array_key_exists($sDependency, $this->aDependenciesMap)){ - $this->aDependenciesMap[$sDependency] = []; - } - $this->aDependenciesMap[$sDependency][] = ['description' => $oDependencyDescription, 'input' => $sInput, 'output' => $sOutput]; - } - } - - /** iterate throw dependencies... */ - foreach (array_keys($this->aDependenciesMap) as $sDependency){ - - // Listen the dependency - $this->builder->get($sDependency)->addEventListener(FormEvents::POST_SET_DATA, $this->GetEventListeningCallback()); - $this->builder->get($sDependency)->addEventListener(FormEvents::POST_SUBMIT, $this->GetEventListeningCallback()); - } - - } - - /** - * Add a dependency description. - * - * @param DependencyDescription $oDependencyDescription - * - * @return void - */ - public function AddDependencyDescription(DependencyDescription $oDependencyDescription): void - { - $this->aDependenciesDescription[] = $oDependencyDescription; - } - - /** - * The event handling callback. - * - * @return callable - */ - private function GetEventListeningCallback(): callable - { - return function (FormEvent $event){ - - // Get the event type - $sEventType = $this->GetEventType($event); - - // Get the form - $oForm = $event->getForm(); - - /** Iterate throw dependencies map... */ - foreach ($this->aDependenciesMap[$event->getForm()->getName()] as $aData){ - - // Get the map data - $oDependencyDescription = $aData['description']; - $sInput = $aData['input']; - $sOutput = $aData['output']; - - // Compute output value - $oValue = $event->getData(); - if(array_key_exists('outputs', $event->getForm()->getConfig()->getOptions())){ - $aOutputs = $event->getForm()->getConfig()->getOptions()['outputs']; - if(array_key_exists($sOutput, $aOutputs)){ - $oValue = $aOutputs[$sOutput]($oValue); - } - } - - // Store the input value - $oDependencyDescription->SetData($sEventType, $sInput, $oValue); - - // When dependencies met, add the dependent field if not already done - if(!$oDependencyDescription->IsAdded() && $oDependencyDescription->IsDataReady($sEventType)) { - - // Get the dependent field options - $aOptions = $oDependencyDescription->options; - - // Add the listener callback to the dependent field if it is also a dependency for another field - if(is_string($oDependencyDescription->child) && array_key_exists($oDependencyDescription->child, $this->aDependenciesMap)) { - $aOptions = array_merge($aOptions, [ - 'listener_callback' => $this->GetEventListeningCallback(), - ]); - } - - // Add the dependent field to the form - $oForm->getParent()->add($oDependencyDescription->child, $oDependencyDescription->type, array_merge($aOptions, $oDependencyDescription->type::GetOptionsFromInputs($oDependencyDescription->GetData($sEventType)))); - - // Mark the dependency as added - $oDependencyDescription->SetAdded(true); - } - } - - }; - - } - - /** - * Get the event type. - * - * @param FormEvent $event - * - * @return string - * @throws Exception - */ - private function GetEventType(FormEvent $event): string - { - if($event instanceof PostSetDataEvent) { - return FormEvents::POST_SET_DATA; - } - else if($event instanceof PostSubmitEvent) { - return FormEvents::POST_SUBMIT; - } - - throw new Exception(sprintf("Unknown event type %s", get_class($event))); - } - - - - - - -} \ No newline at end of file +// +//namespace Combodo\iTop\Forms\Dependency; +// +//use Exception; +//use Symfony\Component\Form\Event\PostSetDataEvent; +//use Symfony\Component\Form\Event\PostSubmitEvent; +//use Symfony\Component\Form\FormBuilderInterface; +//use Symfony\Component\Form\FormEvent; +//use Symfony\Component\Form\FormEvents; +//use Symfony\Component\Form\FormInterface; +// +//class DependencyHandler +//{ +// /** @var array dépendencies descriptions stored on builder add */ +// private array $aDependenciesDescription = []; +// +// /** @var array dependencies map computed on form pre set data */ +// private array $aDependenciesMap = []; +// +// /** +// * Constructor. +// * +// * @param FormBuilderInterface $builder +// */ +// public function __construct(public FormBuilderInterface $builder) +// { +// // Initialize the dependencies listeners once the form is built +// $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { +// $oForm = $event->getForm(); +// $this->InitializeDependenciesMap($oForm); +// }); +// } +// +// /** +// *Initialize the dependencies map and register listeners on the dependencies inputs. +// * +// * @param FormInterface $oForm +// * +// * @return void +// */ +// private function InitializeDependenciesMap(FormInterface $oForm): void +// { +// +// /** iterate throw dependencies descriptions... @var DependencyDescription $oDependencyDescription */ +// foreach ($this->aDependenciesDescription as $oDependencyDescription) { +// +// /** iterate throw dependencies items... */ +// foreach ($oDependencyDescription->aDependencies as $sInput => $aData) { +// +// // get the dependency field name +// $sDependency = $aData['source']; +// +// // get the field input name +// $sOutput = array_key_exists('output', $aData) ? $aData['output'] : null; +// +// // add the dependency to the map +// if(!array_key_exists($sDependency, $this->aDependenciesMap)){ +// $this->aDependenciesMap[$sDependency] = []; +// } +// $this->aDependenciesMap[$sDependency][] = ['description' => $oDependencyDescription, 'input' => $sInput, 'output' => $sOutput]; +// } +// } +// +// /** iterate throw dependencies... */ +// foreach (array_keys($this->aDependenciesMap) as $sDependency){ +// +// // Listen the dependency +// $this->builder->get($sDependency)->addEventListener(FormEvents::POST_SET_DATA, $this->GetEventListeningCallback()); +// $this->builder->get($sDependency)->addEventListener(FormEvents::POST_SUBMIT, $this->GetEventListeningCallback()); +// } +// +// } +// +// /** +// * Add a dependency description. +// * +// * @param DependencyDescription $oDependencyDescription +// * +// * @return void +// */ +// public function AddDependencyDescription(DependencyDescription $oDependencyDescription): void +// { +// $this->aDependenciesDescription[] = $oDependencyDescription; +// } +// +// /** +// * The event handling callback. +// * +// * @return callable +// */ +// private function GetEventListeningCallback(): callable +// { +// return function (FormEvent $event){ +// +// // Get the event type +// $sEventType = $this->GetEventType($event); +// +// // Get the form +// $oForm = $event->getForm(); +// +// /** Iterate throw dependencies map... */ +// foreach ($this->aDependenciesMap[$event->getForm()->getName()] as $aData){ +// +// // Get the map data +// $oDependencyDescription = $aData['description']; +// $sInput = $aData['input']; +// $sOutput = $aData['output']; +// +// // Compute output value +// $oValue = $event->getData(); +// if(array_key_exists('outputs', $event->getForm()->getConfig()->getOptions())){ +// $aOutputs = $event->getForm()->getConfig()->getOptions()['outputs']; +// if(array_key_exists($sOutput, $aOutputs)){ +// $oValue = $aOutputs[$sOutput]($oValue); +// } +// } +// +// // Store the input value +// $oDependencyDescription->SetData($sEventType, $sInput, $oValue); +// +// // When dependencies met, add the dependent field if not already done +// if(!$oDependencyDescription->IsAdded() && $oDependencyDescription->IsDataReady($sEventType)) { +// +// // Get the dependent field options +// $aOptions = $oDependencyDescription->options; +// +// // Add the listener callback to the dependent field if it is also a dependency for another field +// if(is_string($oDependencyDescription->child) && array_key_exists($oDependencyDescription->child, $this->aDependenciesMap)) { +// $aOptions = array_merge($aOptions, [ +// 'listener_callback' => $this->GetEventListeningCallback(), +// ]); +// } +// +// // Add the dependent field to the form +// $oForm->getParent()->add($oDependencyDescription->child, $oDependencyDescription->type, array_merge($aOptions, $oDependencyDescription->type::GetOptionsFromInputs($oDependencyDescription->GetData($sEventType)))); +// +// // Mark the dependency as added +// $oDependencyDescription->SetAdded(true); +// } +// } +// +// }; +// +// } +// +// /** +// * Get the event type. +// * +// * @param FormEvent $event +// * +// * @return string +// * @throws Exception +// */ +// private function GetEventType(FormEvent $event): string +// { +// if($event instanceof PostSetDataEvent) { +// return FormEvents::POST_SET_DATA; +// } +// else if($event instanceof PostSubmitEvent) { +// return FormEvents::POST_SUBMIT; +// } +// +// throw new Exception(sprintf("Unknown event type %s", get_class($event))); +// } +// +// +// +// +// +// +//} \ No newline at end of file diff --git a/sources/Forms/FormBuilder/DependencyHandler.php b/sources/Forms/FormBuilder/DependencyHandler.php new file mode 100644 index 0000000000..8fa2f6ea19 --- /dev/null +++ b/sources/Forms/FormBuilder/DependencyHandler.php @@ -0,0 +1,112 @@ +aDependentBlocks = $aDependentBlocks; + $this->oFormBuilder = $oFormBuilder; + + // Initialize the dependencies listeners once the form is built + $oFormBuilder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $oForm = $event->getForm(); + $this->InitializeDependenciesMap($oForm); + }); + } + + private function InitializeDependenciesMap(FormInterface $oForm) + { + // Connections from output pov + $aDependenciesMap = []; + + /** @var \Combodo\iTop\Forms\Block\FormBlock $oDependentBlock */ + foreach ($this->aDependentBlocks as $oDependentBlock) { + foreach ($oDependentBlock->GetConnections() as $sInputName => $aConnections) { + foreach ($aConnections as $aConnection) { + $sOutputBlockName = $aConnection['output_block']; + $sOutputName = $aConnection['output']; + + if (!isset($aDependenciesMap[$sOutputBlockName])) { + $aDependenciesMap[$sOutputBlockName] = []; + } + if (!isset($aDependenciesMap[$sOutputBlockName][$sOutputName])) { + $aDependenciesMap[$sOutputBlockName][$sOutputName] = []; + } + + $aDependenciesMap[$sOutputBlockName][$sOutputName][] = ['input_block' => $oDependentBlock, 'input_name' => $sInputName]; + } + } + } + + $this->aDependenciesMap = $aDependenciesMap; + + foreach (array_keys($aDependenciesMap) as $sOutputBlockName) { + + // Listen the dependency + $this->oFormBuilder->get($sOutputBlockName)->addEventListener(FormEvents::POST_SET_DATA, $this->GetEventListeningCallback()); + $this->oFormBuilder->get($sOutputBlockName)->addEventListener(FormEvents::POST_SUBMIT, $this->GetEventListeningCallback()); + } + + } + + private function GetEventListeningCallback(): callable + { + return function (FormEvent $oEvent) { + // Get the event type + $sEventType = $this->GetEventType($oEvent); + + // Get the form + $oForm = $oEvent->getForm(); + + /** Iterate throw dependencies map... */ + $sOutputBlockName = $oForm->getName(); + $oOutputBlock = $this->oFormBuilder->GetFormBlock($sOutputBlockName); + foreach (array_keys($this->aDependenciesMap[$sOutputBlockName]) as $sOutputName) { + $oOutput = $oOutputBlock->GetOutput($sOutputName); + $oOutput->UpdateOutputValue($oEvent->getData(), $sEventType); + } + + return; + }; + + } + + /** + * Get the event type. + * + * @param FormEvent $event + * + * @return string + * @throws \Combodo\iTop\Forms\FormBuilder\FormBuilderException + */ + private function GetEventType(FormEvent $event): string + { + if ($event instanceof PostSetDataEvent) { + return FormEvents::POST_SET_DATA; + } else if ($event instanceof PostSubmitEvent) { + return FormEvents::POST_SUBMIT; + } + + throw new FormBuilderException(sprintf('Unknown event type %s', get_class($event))); + } +} \ No newline at end of file diff --git a/sources/Forms/FormBuilder/FormBuilder.php b/sources/Forms/FormBuilder/FormBuilder.php index e92d41cafe..f8b09c6acb 100644 --- a/sources/Forms/FormBuilder/FormBuilder.php +++ b/sources/Forms/FormBuilder/FormBuilder.php @@ -2,7 +2,7 @@ namespace Combodo\iTop\Forms\FormBuilder; -use Combodo\iTop\Forms\Dependency\DependencyHandler; +use Combodo\iTop\Forms\Block\AbstractFormBlock; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\DataMapperInterface; @@ -19,8 +19,8 @@ use Traversable; class FormBuilder implements FormBuilderInterface, \IteratorAggregate { - /** @var DependencyHandler|null dependencies handler */ - private DependencyHandler|null $dependencyHandler = null; + private ?DependencyHandler $oDependencyHandler = null; + private array $aFormBlocks = []; /** * Constructor. @@ -45,14 +45,26 @@ class FormBuilder implements FormBuilderInterface, \IteratorAggregate return; } + $aDependentBlocks = []; /** @var \Combodo\iTop\Forms\Block\FormBlock $oSubFormBlock */ foreach ($oFormBlock->GetSubFormBlocks() as $oSubFormBlock) { + $this->aFormBlocks[$oSubFormBlock->getName()] = $oSubFormBlock; if ($oSubFormBlock->HasConnections()) { $this->builder->add($oSubFormBlock->GetName(), HiddenType::class); + $aDependentBlocks[] = $oSubFormBlock; } else { $this->add($oSubFormBlock->GetName(), $oSubFormBlock->GetFormType(), $oSubFormBlock->getOptions()); } } + + if (count($aDependentBlocks) > 0) { + $this->oDependencyHandler = new DependencyHandler($this, $aDependentBlocks); + } + } + + public function GetFormBlock(string $sName): ?AbstractFormBlock + { + return $this->aFormBlocks[$sName] ?? null; } // pure decoration of FormBuilderInterface diff --git a/sources/Forms/FormBuilder/FormBuilderException.php b/sources/Forms/FormBuilder/FormBuilderException.php new file mode 100644 index 0000000000..78b41e9d33 --- /dev/null +++ b/sources/Forms/FormBuilder/FormBuilderException.php @@ -0,0 +1,14 @@ +