diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 5be1f82276..b794dc0016 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -481,12 +481,14 @@ return array( '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\\FormBlockIOException' => $baseDir . '/sources/Forms/Block/IO/FormBlockIOException.php', 'Combodo\\iTop\\Forms\\Block\\IO\\FormInput' => $baseDir . '/sources/Forms/Block/IO/FormInput.php', 'Combodo\\iTop\\Forms\\Block\\IO\\FormOutput' => $baseDir . '/sources/Forms/Block/IO/FormOutput.php', 'Combodo\\iTop\\Forms\\Block\\IO\\Format\\AttributeIOFormat' => $baseDir . '/sources/Forms/Block/IO/Format/AttributeIOFormat.php', 'Combodo\\iTop\\Forms\\Block\\IO\\Format\\ClassIOFormat' => $baseDir . '/sources/Forms/Block/IO/Format/ClassIOFormat.php', 'Combodo\\iTop\\Forms\\Converter\\AbstractOutputConverter' => $baseDir . '/sources/Forms/Converter/AbstractOutputConverter.php', - 'Combodo\\iTop\\Forms\\Converter\\OqlToClassName' => $baseDir . '/sources/Forms/Converter/OqlToClassName.php', + 'Combodo\\iTop\\Forms\\Converter\\OqlToClassConverter' => $baseDir . '/sources/Forms/Converter/OqlToClassConverter.php', + 'Combodo\\iTop\\Forms\\Converter\\StringToAttributeConverter' => $baseDir . '/sources/Forms/Converter/StringToAttributeConverter.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', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 8cd85ea6f0..cbb87c11a3 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -862,12 +862,14 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f '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\\FormBlockIOException' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/FormBlockIOException.php', 'Combodo\\iTop\\Forms\\Block\\IO\\FormInput' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/FormInput.php', 'Combodo\\iTop\\Forms\\Block\\IO\\FormOutput' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/FormOutput.php', 'Combodo\\iTop\\Forms\\Block\\IO\\Format\\AttributeIOFormat' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Format/AttributeIOFormat.php', 'Combodo\\iTop\\Forms\\Block\\IO\\Format\\ClassIOFormat' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Format/ClassIOFormat.php', 'Combodo\\iTop\\Forms\\Converter\\AbstractOutputConverter' => __DIR__ . '/../..' . '/sources/Forms/Converter/AbstractOutputConverter.php', - 'Combodo\\iTop\\Forms\\Converter\\OqlToClassName' => __DIR__ . '/../..' . '/sources/Forms/Converter/OqlToClassName.php', + 'Combodo\\iTop\\Forms\\Converter\\OqlToClassConverter' => __DIR__ . '/../..' . '/sources/Forms/Converter/OqlToClassConverter.php', + 'Combodo\\iTop\\Forms\\Converter\\StringToAttributeConverter' => __DIR__ . '/../..' . '/sources/Forms/Converter/StringToAttributeConverter.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', diff --git a/sources/Forms/Block/AbstractFormBlock.php b/sources/Forms/Block/AbstractFormBlock.php index 92d9ce5309..3a75cdb627 100644 --- a/sources/Forms/Block/AbstractFormBlock.php +++ b/sources/Forms/Block/AbstractFormBlock.php @@ -157,16 +157,16 @@ abstract class AbstractFormBlock * Attach an input to a block output. * * @param string $sInputName - * @param string $sOutputBlockName + * @param FormBlock $sOutputBlock * @param string $sOutputName * * @return $this * @throws FormBlockException */ - public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock + public function DependsOn(string $sInputName, FormBlock $sOutputBlock, string $sOutputName): AbstractFormBlock { $oFormInput = $this->GetInput($sInputName); - $oFormInput->Connect($sOutputBlockName, $sOutputName); + $oFormInput->Connect($sOutputBlock, $sOutputName); return $this; } @@ -181,7 +181,7 @@ abstract class AbstractFormBlock return false; } - public function GetConnections(): array + public function GetInputsConnections(): array { $aConnections = []; /** @var FormInput $oFormInput */ diff --git a/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php b/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php index d59dc05956..dd03334d39 100644 --- a/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php +++ b/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php @@ -7,8 +7,12 @@ namespace Combodo\iTop\Forms\Block\DataModel; use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock; +use Combodo\iTop\Forms\Block\IO\Format\AttributeIOFormat; use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat; use Combodo\iTop\Forms\Block\IO\FormInput; +use Combodo\iTop\Forms\Block\IO\FormOutput; +use Combodo\iTop\Forms\Converter\OqlToClassConverter; +use Combodo\iTop\Forms\Converter\StringToAttributeConverter; /** * Form block for choice of class attributes. @@ -20,6 +24,9 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock // inputs public const INPUT_CLASS_NAME = 'class_name'; + // outputs + public const OUTPUT_ATTRIBUTE = 'attribute'; + /** @inheritdoc */ public function InitInputs(): void { @@ -27,4 +34,9 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock $this->AddInput(new FormInput(self::INPUT_CLASS_NAME, ClassIOFormat::class)); } + public function InitOutputs(): void + { + parent::InitOutputs(); + $this->AddOutput(new FormOutput(self::OUTPUT_ATTRIBUTE, AttributeIOFormat::class, new StringToAttributeConverter())); + } } \ No newline at end of file diff --git a/sources/Forms/Block/DataModel/OqlFormBlock.php b/sources/Forms/Block/DataModel/OqlFormBlock.php index 1e8cc0ea86..70c982d205 100644 --- a/sources/Forms/Block/DataModel/OqlFormBlock.php +++ b/sources/Forms/Block/DataModel/OqlFormBlock.php @@ -9,7 +9,7 @@ namespace Combodo\iTop\Forms\Block\DataModel; use Combodo\iTop\Forms\Block\Base\StringFormBlock; use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat; use Combodo\iTop\Forms\Block\IO\FormOutput; -use Combodo\iTop\Forms\Converter\OqlToClassName; +use Combodo\iTop\Forms\Converter\OqlToClassConverter; /** * Form block for oql expression. @@ -25,7 +25,7 @@ class OqlFormBlock extends StringFormBlock public function InitOutputs(): void { parent::InitOutputs(); - $this->AddOutput(new FormOutput(self::OUTPUT_SELECTED_CLASS, ClassIOFormat::class, new OqlToClassName())); + $this->AddOutput(new FormOutput(self::OUTPUT_SELECTED_CLASS, ClassIOFormat::class, new OqlToClassConverter())); } } \ No newline at end of file diff --git a/sources/Forms/Block/IO/FormBlockIOException.php b/sources/Forms/Block/IO/FormBlockIOException.php new file mode 100644 index 0000000000..5fd40589b7 --- /dev/null +++ b/sources/Forms/Block/IO/FormBlockIOException.php @@ -0,0 +1,14 @@ +sName = $sName; - $this->sType = $sName; + $this->sType = $sType; } public function GetName(): string @@ -40,9 +43,14 @@ class FormInput $this->sType = $sType; } - public function Connect(string $sOutputBlockName, string $sOutputName): void + public function Connect(FormBlock $sOutputBlock, string $sOutputName): void { - $this->aConnections[] = ['output_block' => $sOutputBlockName, 'output' => $sOutputName]; + $sOutputType = $sOutputBlock->GetOutput($sOutputName)->GetType(); + if($this->sType !== $sOutputType){ + throw new FormBlockIOException('Cannot connect input types incompatibles ' . $this->sName . ' to ' . $sOutputBlock->GetName() . ' ' . $sOutputName); + } + + $this->aConnections[] = ['output_block' => $sOutputBlock, 'output' => $sOutputName]; } public function GetConnections(): array diff --git a/sources/Forms/Block/IO/FormOutput.php b/sources/Forms/Block/IO/FormOutput.php index f0f47f39fe..047db6415e 100644 --- a/sources/Forms/Block/IO/FormOutput.php +++ b/sources/Forms/Block/IO/FormOutput.php @@ -20,7 +20,7 @@ class FormOutput public function __construct(string $sName, string $sType, AbstractOutputConverter $oConverter = null) { $this->sName = $sName; - $this->sType = $sName; + $this->sType = $sType; $this->oConverter = $oConverter; } diff --git a/sources/Forms/Converter/OqlToClassName.php b/sources/Forms/Converter/OqlToClassConverter.php similarity index 89% rename from sources/Forms/Converter/OqlToClassName.php rename to sources/Forms/Converter/OqlToClassConverter.php index 21e97422bd..ed29150f66 100644 --- a/sources/Forms/Converter/OqlToClassName.php +++ b/sources/Forms/Converter/OqlToClassConverter.php @@ -11,7 +11,7 @@ use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat; /** * OQL expression to class converter. */ -class OqlToClassName extends AbstractOutputConverter +class OqlToClassConverter extends AbstractOutputConverter { /** @inheritdoc */ public function Convert(mixed $oData): ?ClassIOFormat diff --git a/sources/Forms/Converter/StringToAttributeConverter.php b/sources/Forms/Converter/StringToAttributeConverter.php new file mode 100644 index 0000000000..890615c6b1 --- /dev/null +++ b/sources/Forms/Converter/StringToAttributeConverter.php @@ -0,0 +1,24 @@ +aDependentBlocks = $aDependentBlocks; $this->oFormBuilder = $oFormBuilder; + // add form ready listener + $this->AddFormReadyListener(); + } + + /** + * Add form ready listener. + * + * Listen the form PRE_SET_DATA + * First event from Symfony framework, we know that the form is built at this step. + * + * @return void + */ + private function AddFormReadyListener(): void + { // Initialize the dependencies listeners once the form is built - $oFormBuilder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $this->oFormBuilder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { $oForm = $event->getForm(); $this->InitializeDependenciesMap($oForm); }); } - private function InitializeDependenciesMap(FormInterface $oForm) + /** + * Initialize dependencies map. + * + * @param FormInterface $oForm + * + * @return void + */ + private function InitializeDependenciesMap(FormInterface $oForm): void { // Connections from output pov $aDependenciesMap = []; - /** @var \Combodo\iTop\Forms\Block\FormBlock $oDependentBlock */ + /** iterate throw dependents blocks... @var FormBlock $oDependentBlock */ foreach ($this->aDependentBlocks as $oDependentBlock) { - foreach ($oDependentBlock->GetConnections() as $sInputName => $aConnections) { + + /** iterate throw the block inputs connections... **/ + foreach ($oDependentBlock->GetInputsConnections() as $sInputName => $aConnections) { + + /** Iterate throw the input connections... */ foreach ($aConnections as $aConnection) { - $sOutputBlockName = $aConnection['output_block']; + + // connection information + $sOutputBlock = $aConnection['output_block']; + $sOutputBlockName = $sOutputBlock->getName(); $sOutputName = $aConnection['output']; + // initialize map if (!isset($aDependenciesMap[$sOutputBlockName])) { $aDependenciesMap[$sOutputBlockName] = []; } @@ -53,22 +94,30 @@ class DependencyHandler $aDependenciesMap[$sOutputBlockName][$sOutputName] = []; } + // add to map $aDependenciesMap[$sOutputBlockName][$sOutputName][] = ['input_block' => $oDependentBlock, 'input_name' => $sInputName]; } } } + // store the dependencies map $this->aDependenciesMap = $aDependenciesMap; + /** Iterate throw output blocks */ foreach (array_keys($aDependenciesMap) as $sOutputBlockName) { - // Listen the dependency + // Listen the output block POST_SET_DATA & POST_SUBMIT $this->oFormBuilder->get($sOutputBlockName)->addEventListener(FormEvents::POST_SET_DATA, $this->GetEventListeningCallback()); $this->oFormBuilder->get($sOutputBlockName)->addEventListener(FormEvents::POST_SUBMIT, $this->GetEventListeningCallback()); } } + /** + * Get the listening callback. + * + * @return callable + */ private function GetEventListeningCallback(): callable { return function (FormEvent $oEvent) { @@ -97,7 +146,7 @@ class DependencyHandler * @param FormEvent $event * * @return string - * @throws \Combodo\iTop\Forms\FormBuilder\FormBuilderException + * @throws FormBuilderException */ private function GetEventType(FormEvent $event): string {