N°8772 - dynamic form

This commit is contained in:
Benjamin Dalsass
2025-11-14 10:50:57 +01:00
parent 4d159ea3f1
commit e5058fb8f7
42 changed files with 880 additions and 540 deletions

View File

@@ -481,6 +481,7 @@ return array(
'Combodo\\iTop\\Forms\\Block\\AbstractTypeFormBlock' => $baseDir . '/sources/Forms/Block/AbstractTypeFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\CheckboxFormBlock' => $baseDir . '/sources/Forms/Block/Base/CheckboxFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\ChoiceFormBlock' => $baseDir . '/sources/Forms/Block/Base/ChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\ChoiceFromInputs' => $baseDir . '/sources/Forms/Block/Base/ChoiceFromInputs.php',
'Combodo\\iTop\\Forms\\Block\\Base\\CollectionBlock' => $baseDir . '/sources/Forms/Block/Base/CollectionBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\DateFormBlock' => $baseDir . '/sources/Forms/Block/Base/DateFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\DateTimeFormBlock' => $baseDir . '/sources/Forms/Block/Base/DateTimeFormBlock.php',
@@ -493,26 +494,6 @@ return array(
'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/OqlFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Expression\\ExpressionFormBlock' => $baseDir . '/sources/Forms/Block/Expression/ExpressionFormBlock.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\\FormType\\ChoiceFormType' => $baseDir . '/sources/Forms/Block/FormType/ChoiceFormType.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\CollectionFormType' => $baseDir . '/sources/Forms/Block/FormType/CollectionFormType.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\FormType' => $baseDir . '/sources/Forms/Block/FormType/FormType.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\FormTypeHelper' => $baseDir . '/sources/Forms/Block/FormType/FormTypeHelper.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\OqlFormType' => $baseDir . '/sources/Forms/Block/FormType/OqlFormType.php',
'Combodo\\iTop\\Forms\\Block\\IO\\AbstractFormIO' => $baseDir . '/sources/Forms/Block/IO/AbstractFormIO.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\AbstractConverter' => $baseDir . '/sources/Forms/Block/IO/Converter/AbstractConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\ChoiceValueToLabelConverter' => $baseDir . '/sources/Forms/Block/IO/Converter/ChoiceValueToLabelConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\OqlToClassConverter' => $baseDir . '/sources/Forms/Block/IO/Converter/OqlToClassConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\StringToAttributeConverter' => $baseDir . '/sources/Forms/Block/IO/Converter/StringToAttributeConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\StringToBooleanConverter' => $baseDir . '/sources/Forms/Block/IO/Converter/StringToBooleanConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\FormBinding' => $baseDir . '/sources/Forms/Block/IO/FormBinding.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\\BooleanIOFormat' => $baseDir . '/sources/Forms/Block/IO/Format/BooleanIOFormat.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Format\\ClassIOFormat' => $baseDir . '/sources/Forms/Block/IO/Format/ClassIOFormat.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Format\\NumberIOFormat' => $baseDir . '/sources/Forms/Block/IO/Format/NumberIOFormat.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Format\\RawFormat' => $baseDir . '/sources/Forms/Block/IO/Format/RawFormat.php',
'Combodo\\iTop\\Forms\\FormBuilder\\DependencyHandler' => $baseDir . '/sources/Forms/FormBuilder/DependencyHandler.php',
'Combodo\\iTop\\Forms\\FormBuilder\\DependencyMap' => $baseDir . '/sources/Forms/FormBuilder/DependencyMap.php',
'Combodo\\iTop\\Forms\\FormBuilder\\FormBuilder' => $baseDir . '/sources/Forms/FormBuilder/FormBuilder.php',
@@ -521,11 +502,33 @@ return array(
'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',
'Combodo\\iTop\\Forms\\FormType\\Base\\ChoiceFormType' => $baseDir . '/sources/Forms/FormType/Base/ChoiceFormType.php',
'Combodo\\iTop\\Forms\\FormType\\Base\\CollectionFormType' => $baseDir . '/sources/Forms/FormType/Base/CollectionFormType.php',
'Combodo\\iTop\\Forms\\FormType\\Base\\FormType' => $baseDir . '/sources/Forms/FormType/Base/FormType.php',
'Combodo\\iTop\\Forms\\FormType\\DataModel\\OqlFormType' => $baseDir . '/sources/Forms/FormType/DataModel/OqlFormType.php',
'Combodo\\iTop\\Forms\\FormType\\FormTypeHelper' => $baseDir . '/sources/Forms/FormType/FormTypeHelper.php',
'Combodo\\iTop\\Forms\\Forms' => $baseDir . '/sources/Forms/Forms.php',
'Combodo\\iTop\\Forms\\FormsException' => $baseDir . '/sources/Forms/FormsException.php',
'Combodo\\iTop\\Forms\\IFormBlock' => $baseDir . '/sources/Forms/IFormBlock.php',
'Combodo\\iTop\\Forms\\IO\\AbstractFormIO' => $baseDir . '/sources/Forms/IO/AbstractFormIO.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\AbstractConverter' => $baseDir . '/sources/Forms/IO/Converter/AbstractConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\ChoiceValueToLabelConverter' => $baseDir . '/sources/Forms/IO/Converter/ChoiceValueToLabelConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\OqlToClassConverter' => $baseDir . '/sources/Forms/IO/Converter/OqlToClassConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\StringToAttributeConverter' => $baseDir . '/sources/Forms/IO/Converter/StringToAttributeConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\StringToBooleanConverter' => $baseDir . '/sources/Forms/IO/Converter/StringToBooleanConverter.php',
'Combodo\\iTop\\Forms\\IO\\FormBinding' => $baseDir . '/sources/Forms/IO/FormBinding.php',
'Combodo\\iTop\\Forms\\IO\\FormBlockIOException' => $baseDir . '/sources/Forms/IO/FormBlockIOException.php',
'Combodo\\iTop\\Forms\\IO\\FormInput' => $baseDir . '/sources/Forms/IO/FormInput.php',
'Combodo\\iTop\\Forms\\IO\\FormOutput' => $baseDir . '/sources/Forms/IO/FormOutput.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeIOFormat' => $baseDir . '/sources/Forms/IO/Format/AttributeIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\BooleanIOFormat' => $baseDir . '/sources/Forms/IO/Format/BooleanIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\ClassIOFormat' => $baseDir . '/sources/Forms/IO/Format/ClassIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\NumberIOFormat' => $baseDir . '/sources/Forms/IO/Format/NumberIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\RawFormat' => $baseDir . '/sources/Forms/IO/Format/RawFormat.php',
'Combodo\\iTop\\Forms\\Register\\IORegister' => $baseDir . '/sources/Forms/Register/IORegister.php',
'Combodo\\iTop\\Forms\\Register\\Option' => $baseDir . '/sources/Forms/Register/Option.php',
'Combodo\\iTop\\Forms\\Register\\OptionsRegister' => $baseDir . '/sources/Forms/Register/OptionsRegister.php',
'Combodo\\iTop\\Forms\\Twig\\Extension\\FormCompatibilityExtension' => $baseDir . '/sources/Forms/Twig/Extension/FormCompatibilityExtension.php',
'Combodo\\iTop\\ItopSdkFormDemonstrator\\Form\\Block\\ExpressionFormBlock' => $baseDir . '/sources/Forms/Block/Base/ExpressionFormBlock.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',

View File

@@ -862,6 +862,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\Forms\\Block\\AbstractTypeFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/AbstractTypeFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\CheckboxFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/CheckboxFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\ChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/ChoiceFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\ChoiceFromInputs' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/ChoiceFromInputs.php',
'Combodo\\iTop\\Forms\\Block\\Base\\CollectionBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/CollectionBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\DateFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/DateFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Base\\DateTimeFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/DateTimeFormBlock.php',
@@ -874,26 +875,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/OqlFormBlock.php',
'Combodo\\iTop\\Forms\\Block\\Expression\\ExpressionFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Expression/ExpressionFormBlock.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\\FormType\\ChoiceFormType' => __DIR__ . '/../..' . '/sources/Forms/Block/FormType/ChoiceFormType.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\CollectionFormType' => __DIR__ . '/../..' . '/sources/Forms/Block/FormType/CollectionFormType.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\FormType' => __DIR__ . '/../..' . '/sources/Forms/Block/FormType/FormType.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\FormTypeHelper' => __DIR__ . '/../..' . '/sources/Forms/Block/FormType/FormTypeHelper.php',
'Combodo\\iTop\\Forms\\Block\\FormType\\OqlFormType' => __DIR__ . '/../..' . '/sources/Forms/Block/FormType/OqlFormType.php',
'Combodo\\iTop\\Forms\\Block\\IO\\AbstractFormIO' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/AbstractFormIO.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\AbstractConverter' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Converter/AbstractConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\ChoiceValueToLabelConverter' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Converter/ChoiceValueToLabelConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\OqlToClassConverter' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Converter/OqlToClassConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\StringToAttributeConverter' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Converter/StringToAttributeConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Converter\\StringToBooleanConverter' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Converter/StringToBooleanConverter.php',
'Combodo\\iTop\\Forms\\Block\\IO\\FormBinding' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/FormBinding.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\\BooleanIOFormat' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Format/BooleanIOFormat.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Format\\ClassIOFormat' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Format/ClassIOFormat.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Format\\NumberIOFormat' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Format/NumberIOFormat.php',
'Combodo\\iTop\\Forms\\Block\\IO\\Format\\RawFormat' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/Format/RawFormat.php',
'Combodo\\iTop\\Forms\\FormBuilder\\DependencyHandler' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/DependencyHandler.php',
'Combodo\\iTop\\Forms\\FormBuilder\\DependencyMap' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/DependencyMap.php',
'Combodo\\iTop\\Forms\\FormBuilder\\FormBuilder' => __DIR__ . '/../..' . '/sources/Forms/FormBuilder/FormBuilder.php',
@@ -902,11 +883,33 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'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',
'Combodo\\iTop\\Forms\\FormType\\Base\\ChoiceFormType' => __DIR__ . '/../..' . '/sources/Forms/FormType/Base/ChoiceFormType.php',
'Combodo\\iTop\\Forms\\FormType\\Base\\CollectionFormType' => __DIR__ . '/../..' . '/sources/Forms/FormType/Base/CollectionFormType.php',
'Combodo\\iTop\\Forms\\FormType\\Base\\FormType' => __DIR__ . '/../..' . '/sources/Forms/FormType/Base/FormType.php',
'Combodo\\iTop\\Forms\\FormType\\DataModel\\OqlFormType' => __DIR__ . '/../..' . '/sources/Forms/FormType/DataModel/OqlFormType.php',
'Combodo\\iTop\\Forms\\FormType\\FormTypeHelper' => __DIR__ . '/../..' . '/sources/Forms/FormType/FormTypeHelper.php',
'Combodo\\iTop\\Forms\\Forms' => __DIR__ . '/../..' . '/sources/Forms/Forms.php',
'Combodo\\iTop\\Forms\\FormsException' => __DIR__ . '/../..' . '/sources/Forms/FormsException.php',
'Combodo\\iTop\\Forms\\IFormBlock' => __DIR__ . '/../..' . '/sources/Forms/IFormBlock.php',
'Combodo\\iTop\\Forms\\IO\\AbstractFormIO' => __DIR__ . '/../..' . '/sources/Forms/IO/AbstractFormIO.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\AbstractConverter' => __DIR__ . '/../..' . '/sources/Forms/IO/Converter/AbstractConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\ChoiceValueToLabelConverter' => __DIR__ . '/../..' . '/sources/Forms/IO/Converter/ChoiceValueToLabelConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\OqlToClassConverter' => __DIR__ . '/../..' . '/sources/Forms/IO/Converter/OqlToClassConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\StringToAttributeConverter' => __DIR__ . '/../..' . '/sources/Forms/IO/Converter/StringToAttributeConverter.php',
'Combodo\\iTop\\Forms\\IO\\Converter\\StringToBooleanConverter' => __DIR__ . '/../..' . '/sources/Forms/IO/Converter/StringToBooleanConverter.php',
'Combodo\\iTop\\Forms\\IO\\FormBinding' => __DIR__ . '/../..' . '/sources/Forms/IO/FormBinding.php',
'Combodo\\iTop\\Forms\\IO\\FormBlockIOException' => __DIR__ . '/../..' . '/sources/Forms/IO/FormBlockIOException.php',
'Combodo\\iTop\\Forms\\IO\\FormInput' => __DIR__ . '/../..' . '/sources/Forms/IO/FormInput.php',
'Combodo\\iTop\\Forms\\IO\\FormOutput' => __DIR__ . '/../..' . '/sources/Forms/IO/FormOutput.php',
'Combodo\\iTop\\Forms\\IO\\Format\\AttributeIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/AttributeIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\BooleanIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/BooleanIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\ClassIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/ClassIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\NumberIOFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/NumberIOFormat.php',
'Combodo\\iTop\\Forms\\IO\\Format\\RawFormat' => __DIR__ . '/../..' . '/sources/Forms/IO/Format/RawFormat.php',
'Combodo\\iTop\\Forms\\Register\\IORegister' => __DIR__ . '/../..' . '/sources/Forms/Register/IORegister.php',
'Combodo\\iTop\\Forms\\Register\\Option' => __DIR__ . '/../..' . '/sources/Forms/Register/Option.php',
'Combodo\\iTop\\Forms\\Register\\OptionsRegister' => __DIR__ . '/../..' . '/sources/Forms/Register/OptionsRegister.php',
'Combodo\\iTop\\Forms\\Twig\\Extension\\FormCompatibilityExtension' => __DIR__ . '/../..' . '/sources/Forms/Twig/Extension/FormCompatibilityExtension.php',
'Combodo\\iTop\\ItopSdkFormDemonstrator\\Form\\Block\\ExpressionFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/ExpressionFormBlock.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',

View File

@@ -7,13 +7,13 @@
namespace Combodo\iTop\Forms\Block;
use Combodo\iTop\Forms\Block\Base\FormBlock;
use Combodo\iTop\Forms\Block\IO\AbstractFormIO;
use Combodo\iTop\Forms\Block\IO\Converter\AbstractConverter;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use Combodo\iTop\Forms\Block\IO\FormInput;
use Combodo\iTop\Forms\Block\IO\FormOutput;
use Combodo\iTop\Forms\IO\AbstractFormIO;
use Combodo\iTop\Forms\IO\Format\RawFormat;
use Combodo\iTop\Forms\IO\FormInput;
use Combodo\iTop\Forms\IO\FormOutput;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
use Combodo\iTop\Forms\IFormBlock;
use Forms\BlockIO;
/**
* Abstract form block.
@@ -30,49 +30,38 @@ abstract class AbstractFormBlock implements IFormBlock
/** @var null|FormBlock */
private ?FormBlock $oParent = null;
/** @var array form options */
private array $aOptions = [];
/** @var OptionsRegister */
private OptionsRegister $oOptionsRegister;
/** @var array form dynamic options */
protected array $aDynamicOptions = [];
/** @var array form block inputs */
private array $aFormInputs = [];
/** @var array form block outputs */
private array $aFormOutputs = [];
/** @var bool flag indicating the form insertion */
private bool $bIsAddedToForm = false;
/** @var IORegister */
private IORegister $oIORegister;
/**
* Constructor.
*
* @param string $sName
* @param array $aUserOptions
* @param array $aOptions
*/
public function __construct(private readonly string $sName, protected array $aUserOptions = [])
public function __construct(private readonly string $sName, array $aOptions = [])
{
// Compute options
$this->aOptions = $aUserOptions;
$this->InitBlockOptions($this->aOptions);
// Register options
$this->RegisterOptions($this->oOptionsRegister = new OptionsRegister());
$this->SetOptions($aOptions);
$this->AfterOptionsRegistered($this->oOptionsRegister);
// Initialize block inputs
$this->InitInputs();
// Initialize block outputs
$this->InitOutputs();
// Register IO
$this->RegisterIO($this->oIORegister = new IORegister($this));
$this->AfterIORegistered($this->oIORegister);
}
/**
* Initialize options.
*
* @param array $aUserOptions
* Return the form block name.
*
* @return string
*/
public function InitBlockOptions(array &$aUserOptions): void
public function GetName(): string
{
$aUserOptions['form_block'] = $this;
return $this->sName;
}
/**
@@ -108,13 +97,36 @@ abstract class AbstractFormBlock implements IFormBlock
}
/**
* Return the form block name.
* Register options.
*
* @param OptionsRegister $oOptionsRegister
*
* @return string
*/
public function GetName(): string
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
return $this->sName;
$oOptionsRegister->SetOption('form_block', $this);
}
/**
* @param array $aOptions
*
* @return void
*/
private function SetOptions(array $aOptions): void
{
foreach ($aOptions as $sOptionName => $mOptionValue) {
$this->oOptionsRegister->SetOption($sOptionName, $mOptionValue);
}
}
/**
* @param OptionsRegister $oOptionsRegister
*
* @return void
*/
protected function AfterOptionsRegistered(OptionsRegister $oOptionsRegister): void
{
}
/**
@@ -125,27 +137,43 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function GetOptions(): array
{
return $this->aOptions;
}
public function GetOptionsMergedWithDynamic(string $sEventType = null): array
{
return array_merge($this->GetDynamicOptions(), $this->GetOptions());
}
public function GetDynamicOptions(string $sEventType = null): array
{
return $this->aDynamicOptions;
return $this->oOptionsRegister->GetOptions();
}
/**
* @param string|null $sEventType
* @param string $sOption
*
* @return mixed
*/
public function GetOption(string $sOption): mixed
{
return $this->oOptionsRegister->GetOption($sOption);
}
/**
* @param OptionsRegister $oOptionsRegister
*
* @return void
*/
public function UpdateDynamicOptions(string $sEventType = null): void
public function UpdateOptions(OptionsRegister $oOptionsRegister): void
{
$this->aDynamicOptions = [];
}
/**
* @return array
*/
public function GetBoundInputsBindings(): array
{
return $this->oIORegister->GetBoundInputsBindings();
}
/**
* @return array
*/
public function GetBoundOutputBindings(): array
{
return $this->oIORegister->GetBoundOutputBindings();
}
/**
@@ -158,9 +186,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function AddInput(string $sName, string $sType): AbstractFormBlock
{
$oFormInput = new FormInput($sName, $sType, $this);
$this->aFormInputs[$oFormInput->GetName()] = $oFormInput;
$this->oIORegister->AddInput($sName, $sType);
return $this;
}
@@ -176,12 +202,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function AddInputDependsOn(string $sName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock
{
$oOutputBlock = $this->GetParent()->Get($sOutputBlockName);
$oBlockOutput = $oOutputBlock->GetOutput($sOutputName);
$this->AddInput($sName, $oBlockOutput->GetDataType());
$this->DependsOn($sName, $sOutputBlockName, $sOutputName);
$this->oIORegister->AddInputDependsOn($sName, $sOutputBlockName, $sOutputName);
return $this;
}
@@ -195,11 +216,20 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function GetInput(string $sName): FormInput
{
if (!array_key_exists($sName, $this->aFormInputs)) {
throw new FormBlockException('Missing input '.$sName.' for '.$this->sName);
}
return $this->oIORegister->GetInput($sName);
}
return $this->aFormInputs[$sName];
/**
* Get an input value.
*
* @param string $sName
*
* @return mixed
* @throws FormBlockException
*/
public function GetInputValue(string $sName): mixed
{
return $this->oIORegister->GetInput($sName)->GetValue();
}
/**
@@ -213,9 +243,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function AddOutput(string $sName, string $sType, AbstractConverter $oConverter = null): AbstractFormBlock
{
$oFormOutput = new FormOutput($sName, $sType, $this, $oConverter);
$this->aFormOutputs[$oFormOutput->GetName()] = $oFormOutput;
$this->oIORegister->AddOutput($sName, $sType, $oConverter);
return $this;
}
@@ -229,11 +257,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function GetOutput(string $sName): FormOutput
{
if (!array_key_exists($sName, $this->aFormOutputs)) {
throw new FormBlockException('Missing output '.$sName.' for '.$this->sName);
}
return $this->aFormOutputs[$sName];
return $this->oIORegister->GetOutput($sName);
}
/**
@@ -243,7 +267,17 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function GetInputs(): array
{
return $this->aFormInputs;
return $this->oIORegister->GetInputs();
}
public function GetBoundInputs(): array
{
return $this->oIORegister->GetBoundInputs();
}
public function GetBoundOutputs(): array
{
return $this->oIORegister->GetBoundOutputs();
}
/**
@@ -253,7 +287,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function GetOutputs(): array
{
return $this->aFormOutputs;
return $this->oIORegister->GetOutputs();
}
/**
@@ -268,12 +302,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock
{
$oOutputBlock = $this->GetParent()->Get($sOutputBlockName);
$oFormInput = $this->GetInput($sInputName);
$oFormOutput = $oOutputBlock->GetOutput($sOutputName);
$oFormOutput->BindToInput($oFormInput);
$this->oIORegister->DependsOn($sInputName, $sOutputBlockName, $sOutputName);
return $this;
}
@@ -288,10 +317,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function DependsOnParent(string $sInputName, string $sParentInputName): AbstractFormBlock
{
$oFormInput = $this->GetInput($sInputName);
$oParentFormInput = $this->GetParent()->GetInput($sParentInputName);
$oParentFormInput->BindToInput($oFormInput);
$this->oIORegister->DependsOnParent($sInputName, $sParentInputName);
return $this;
}
@@ -306,10 +332,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function ImpactParent(string $sOutputName, string $sParentOutputName): AbstractFormBlock
{
$oFormOutput = $this->GetOutput($sOutputName);
$oParentFormOutput = $this->GetParent()->GetOutput($sParentOutputName);
$oFormOutput->BindToOutput($oParentFormOutput);
$this->oIORegister->ImpactParent($sOutputName, $sParentOutputName);
return $this;
}
@@ -320,13 +343,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function HasDependenciesBlocks(): bool
{
foreach ($this->aFormInputs as $oFormInput) {
if ($oFormInput->IsBound()) {
return true;
}
}
return false;
return $this->oIORegister->HasDependenciesBlocks();
}
/**
@@ -336,74 +353,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function ImpactDependentsBlocks(): bool
{
/** @var FormOutput $oFormOutput */
foreach ($this->aFormOutputs as $oFormOutput) {
if (count($oFormOutput->GetBindings()) > 0) {
return true;
}
}
return false;
}
/**
* Get bound inputs bindings.
*
* @return array
*/
public function GetBoundInputsBindings(): array
{
$aBindings = [];
/** @var FormInput $oFormInput */
foreach ($this->aFormInputs as $oFormInput) {
if ($oFormInput->IsBound()) {
$aBindings[$oFormInput->GetName()] = $oFormInput->GetBinding();
}
}
return $aBindings;
}
/**
* Get bound outputs bindings.
*
* @return array
*/
public function GetBoundOutputBindings(): array
{
$aBindings = [];
/** @var FormInput $oFormInput */
foreach ($this->aFormOutputs as $oFormOutput) {
if ($oFormOutput->IsBound()) {
$aBindings[$oFormOutput->GetName()] = $oFormOutput->GetBinding();
}
}
return $aBindings;
}
/**
* The block has been added to its parent.
*
* @return bool
*/
public function IsAdded(): bool
{
return $this->bIsAddedToForm;
}
/**
* Indicate that the block has been added to its parent.
*
* @param bool $bIsAdded
*
* @return void
*/
public function SetAdded(bool $bIsAdded): void
{
$this->bIsAddedToForm = $bIsAdded;
return $this->oIORegister->ImpactDependentsBlocks();
}
/**
@@ -415,15 +365,7 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function IsInputsDataReady(string $sType = null): bool
{
foreach ($this->aFormInputs as $oFormInput) {
if ($oFormInput->IsBound()) {
if (!$oFormInput->IsEventDataReady($sType)) {
return false;
}
}
}
return true;
return $this->oIORegister->IsInputsDataReady($sType);
}
/**
@@ -436,34 +378,24 @@ abstract class AbstractFormBlock implements IFormBlock
*/
public function ComputeOutputs(string $sEventType, mixed $oData): void
{
/** Iterate throw output @var FormOutput $oFormOutput */
foreach ($this->aFormOutputs as $oFormOutput) {
// Compute the output value
$oFormOutput->ComputeValue($sEventType, $oData);
}
}
/**
* Initialize inputs.
*
* @return void
*/
public function InitInputs(): void
{
$this->oIORegister->ComputeOutputs($sEventType, $oData);
}
/**
* Initialize outputs.
* Register IO.
*
* @param IORegister $oIORegister
*
* @return void
*/
public function InitOutputs(): void
protected function RegisterIO(IORegister $oIORegister): void
{
$this->AddOutput(self::OUTPUT_VALUE, RawFormat::class);
$oIORegister->AddOutput(self::OUTPUT_VALUE, RawFormat::class);
}
protected function AfterIORegistered(IORegister $oIORegister): void
{
}
/**
@@ -476,6 +408,7 @@ abstract class AbstractFormBlock implements IFormBlock
public function BindingReceivedEvent(AbstractFormIO $oBlockIO): void
{
if ($this->IsInputsDataReady()) {
$this->UpdateOptions($this->oOptionsRegister);
$this->AllInputsReadyEvent();
}
}

View File

@@ -6,12 +6,17 @@
namespace Combodo\iTop\Forms\Block;
use Combodo\iTop\Forms\Block\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\Register\IORegister;
abstract class AbstractTypeFormBlock extends AbstractFormBlock
{
// Inputs
public const INPUT_VISIBLE = 'visible';
public const INPUT_ENABLE = 'enable';
/** @var bool flag indicating the form insertion */
private bool $bIsAddedToForm = false;
/**
* Return the form type.
@@ -20,15 +25,12 @@ abstract class AbstractTypeFormBlock extends AbstractFormBlock
*/
abstract public function GetFormType(): string;
/**
* Initialize inputs.
*
* @return void
*/
public function InitInputs(): void
/** @inheritdoc */
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitInputs();
$this->AddInput(self::INPUT_VISIBLE, BooleanIOFormat::class);
parent::RegisterIO($oIORegister);
$oIORegister->AddInput(self::INPUT_VISIBLE, BooleanIOFormat::class);
$oIORegister->AddInput(self::INPUT_ENABLE, BooleanIOFormat::class);
}
/**
@@ -56,4 +58,26 @@ abstract class AbstractTypeFormBlock extends AbstractFormBlock
{
return true;
}
/**
* The block has been added to its parent.
*
* @return bool
*/
public function IsAdded(): bool
{
return $this->bIsAddedToForm;
}
/**
* Indicate that the block has been added to its parent.
*
* @param bool $bIsAdded
*
* @return void
*/
public function SetAdded(bool $bIsAdded): void
{
$this->bIsAddedToForm = $bIsAdded;
}
}

View File

@@ -7,8 +7,10 @@
namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Block\IO\Converter\StringToBooleanConverter;
use Combodo\iTop\Forms\Block\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Converter\StringToBooleanConverter;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
/**
@@ -27,16 +29,16 @@ class CheckboxFormBlock extends AbstractTypeFormBlock
}
/** @inheritdoc */
function InitBlockOptions(array &$aUserOptions): void
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['required'] = false;
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('required', false);
}
/** @inheritdoc */
function InitOutputs(): void
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_CHECKED, BooleanIOFormat::class, new StringToBooleanConverter());
parent::RegisterIO($oIORegister);
$oIORegister->AddOutput(self::OUTPUT_CHECKED, BooleanIOFormat::class, new StringToBooleanConverter());
}
}

View File

@@ -7,9 +7,10 @@
namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Block\FormType\ChoiceFormType;
use Combodo\iTop\Forms\Block\IO\Converter\ChoiceValueToLabelConverter;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use Combodo\iTop\Forms\FormType\Base\ChoiceFormType;
use Combodo\iTop\Forms\IO\Converter\ChoiceValueToLabelConverter;
use Combodo\iTop\Forms\IO\Format\RawFormat;
use Combodo\iTop\Forms\Register\IORegister;
/**
* Form block for choices.
@@ -26,9 +27,10 @@ class ChoiceFormBlock extends AbstractTypeFormBlock
return ChoiceFormType::class;
}
public function InitOutputs(): void
/** @inheritdoc */
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_LABEL, RawFormat::class, new ChoiceValueToLabelConverter($this));
parent::RegisterIO($oIORegister);
$oIORegister->AddOutput(self::OUTPUT_LABEL, RawFormat::class, new ChoiceValueToLabelConverter($this));
}
}

View File

@@ -0,0 +1,32 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\IO\FormInput;
use Combodo\iTop\Forms\Register\OptionsRegister;
/**
*
*/
class ChoiceFromInputs extends ChoiceFormBlock
{
/** @inheritdoc */
public function UpdateOptions(OptionsRegister $oOptionsRegister): void
{
parent::UpdateOptions($oOptionsRegister);
// Compute options based on inputs values
$aChoices = [];
/** @var FormInput $oInput */
foreach ($this->GetInputs() as $oInput) {
if($oInput->HasValue()){
$aChoices[strval($oInput->GetValue())] = $oInput->GetName();
}
}
$oOptionsRegister->SetOption('choices', $aChoices);
}
}

View File

@@ -7,8 +7,10 @@
namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Block\FormType\CollectionFormType;
use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\FormType\Base\CollectionFormType;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
/**
* Collection form type.
@@ -19,16 +21,8 @@ class CollectionBlock extends AbstractTypeFormBlock
// Inputs
public const INPUT_CLASS_NAME = 'class_name';
/**
* Constructor.
*
* @param string $sName
* @param array $aOptions
*/
public function __construct(string $sName, array $aOptions = [])
{
parent::__construct($sName, $aOptions);
}
/** @var FormBlock block */
protected AbstractTypeFormBlock $oPrototypeBlock;
/** @inheritdoc */
public function GetFormType(): string
@@ -36,47 +30,54 @@ class CollectionBlock extends AbstractTypeFormBlock
return CollectionFormType::class;
}
/** @inheritdoc */
public function InitInputs(): void
/**
* Get the prototype block.
*
* @return AbstractTypeFormBlock
*/
public function GetPrototypeBlock(): AbstractTypeFormBlock
{
parent::InitInputs();
$this->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
return $this->oPrototypeBlock;
}
protected $oBlock;
public function GetOptions(): array
/** @inheritdoc */
protected function RegisterIO(IORegister $oIORegister): void
{
$aOptions = parent::GetOptions();
parent::RegisterIO($oIORegister);
$oIORegister->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
}
// Convert block information in type information
if(isset($aOptions['block_entry_type'])) {
$aOptions['prototype'] = true;
$aOptions['allow_add'] = true;
$aOptions['prototype_options'] = [
'label' => false
];
}
/** @inheritdoc */
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::RegisterOptions($oOptionsRegister);
$sBlockEntryType = $aOptions['block_entry_type'];
$sBlockEntryOptions = $aOptions['block_entry_options'];
$this->oBlock = new ($sBlockEntryType)('prototype', $sBlockEntryOptions);
$oOptionsRegister->SetOption('prototype', true);
$oOptionsRegister->SetOption('allow_add', true);
$oOptionsRegister->SetOption('prototype_options', [
'label' => false
]);
// $this->HandleBlockDependencies();
// not type options
$oOptionsRegister->SetOption('block_entry_type', FormBlock::class, false);
$oOptionsRegister->SetOption('block_entry_options', [], false);
}
/** @inheritdoc */
protected function AfterOptionsRegistered(OptionsRegister $oOptionsRegister): void
{
parent::AfterOptionsRegistered($oOptionsRegister);
$sBlockEntryType = $this->GetOption('block_entry_type');
$sBlockEntryOptions = $this->GetOption('block_entry_options');
$this->oPrototypeBlock = new ($sBlockEntryType)('prototype', $sBlockEntryOptions);
// $this->HandleBlockDependencies();
// $this->oBlock->SetParent($this->GetParent());
// $oBlock->DependsOn('company', 'company', AbstractFormBlock::OUTPUT_VALUE);
unset($aOptions['block_entry_type']);
unset($aOptions['block_entry_options']);
$aOptions['entry_type'] = $this->oBlock->GetFormType();
$aOptions['entry_options'] = $this->oBlock->GetOptions();
return $aOptions;
}
public function HandleBlockDependencies(): void
{
$oOptionsRegister->SetOption('entry_type', $this->oPrototypeBlock->GetFormType());
$oOptionsRegister->SetOption('entry_options', $this->oPrototypeBlock->GetOptions());
}
}

View File

@@ -7,6 +7,7 @@
namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Register\OptionsRegister;
use Symfony\Component\Form\Extension\Core\Type\DateType;
/**
@@ -21,9 +22,10 @@ class DateFormBlock extends AbstractTypeFormBlock
return DateType::class;
}
public function InitBlockOptions(array &$aUserOptions): void
/** @inheritdoc */
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['widget'] = 'single_text';
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('widget', 'single_text');
}
}

View File

@@ -7,6 +7,7 @@
namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Register\OptionsRegister;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
/**
@@ -21,9 +22,10 @@ class DateTimeFormBlock extends AbstractTypeFormBlock
return DateTimeType::class;
}
public function InitBlockOptions(array &$aUserOptions): void
/** @inheritdoc */
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['widget'] = 'single_text';
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('widget', 'single_text');
}
}

View File

@@ -1,96 +0,0 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\ItopSdkFormDemonstrator\Form\Block;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use Combodo\iTop\Forms\FormsException;
use IssueLog;
use Symfony\Component\Form\FormEvents;
class ExpressionFormBlock extends AbstractFormBlock
{
const OUTPUT_RESULT = "result";
public function InitBlockOptions(array &$aUserOptions): void
{
parent::InitBlockOptions($aUserOptions);
}
public function InitOutputs(): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_RESULT, BooleanIOFormat::class);
// $this->AddOutput(self::OUTPUT_RAW, RawFormat::class);
}
// public function InputHasChanged()
// {
// if (!$this->IsInputsDataReady()) {
// return;
// }
// $sExpression = $this->GetOptions()['expression'];
// $sValue = preg_replace_callback(
// "/\[\[(?<input>[^\]]+)]]/",
// function(array $aMatches): string {
// return $this->GetInput($aMatches['input'])->GetValue();
// },
// $sExpression);
//
// foreach ($this->GetInputs() as $oFormInput) {
// IssueLog::Info($oFormInput->GetName().' = '.$oFormInput->GetValue());
// }
// IssueLog::Info("Result of [$sExpression] is [$sValue]");
//
// $result = '';
// eval('$result = '.$sValue.';');
// IssueLog::Info("Result of [$sExpression] is eval to [$result]");
//
// $this->GetOutput(self::OUTPUT_RESULT)->SetValue(FormEvents::POST_SUBMIT, new BooleanIOFormat($result));
// $this->GetOutput(self::OUTPUT_VALUE)->SetValue(FormEvents::POST_SUBMIT, new RawFormat($result));
// }
public function InputHasChanged()
{
if (!$this->IsInputsDataReady()) {
return;
}
$sExpression = $this->GetOptions()['expression'];
$this->Compute($sExpression, FormEvents::POST_SET_DATA);
$this->Compute($sExpression, FormEvents::POST_SUBMIT);
}
public function Compute(string $sExpression, string $sEventType): void
{
try{
$sValue = preg_replace_callback(
"/\[\[(?<input>[^\]]+)]]/",
function(array $aMatches) use ($sEventType): ?string {
$oInput = $this->GetInput($aMatches['input']);
if(!$oInput->HasEventValue($sEventType)){
throw new FormsException('Unable to compute expression: input '.$aMatches['input'].' has no value for event '.$sEventType.'.');
}
return $oInput->GetValue($sEventType);
},
$sExpression);
$result = '';
eval('$result = '.$sValue.';');
$this->GetOutput(self::OUTPUT_RESULT)->SetValue($sEventType, new BooleanIOFormat($result));
$this->GetOutput(self::OUTPUT_VALUE)->SetValue($sEventType, new RawFormat($result));
}
catch(\Exception $e){
IssueLog::Exception('Compute expression block issue', $e);
}
}
}

View File

@@ -9,11 +9,13 @@ namespace Combodo\iTop\Forms\Block\Base;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Block\FormBlockException;
use Combodo\iTop\Forms\Block\FormType\FormType;
use Combodo\iTop\Forms\FormType\Base\FormType;
use Combodo\iTop\Forms\Register\OptionsRegister;
use Combodo\iTop\Forms\FormBuilder\DependencyMap;
use Combodo\iTop\Forms\FormsException;
use Exception;
use ReflectionClass;
use ReflectionException;
/**
* Complex form type.
@@ -53,15 +55,11 @@ class FormBlock extends AbstractTypeFormBlock
}
/** @inheritdoc */
public function InitBlockOptions(array &$aUserOptions): void
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['compound'] = true;
$aUserOptions['attr'] = [
'class' => 'form',
];
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('compound', true);
$oOptionsRegister->SetOptionArrayValue('attr', 'class', 'form');
}
/**
@@ -69,12 +67,13 @@ class FormBlock extends AbstractTypeFormBlock
*
* @param string $sName block name
* @param string $sType block class name
* @param array $aSymfonyOptions options
* @param array $aOptions options
*
* @return $this
* @throws \ReflectionException
* @throws ReflectionException
*/
public function Add(string $sName, string $sType, array $aOptions): AbstractFormBlock
public function Add(string $sName, string $sType, array $aSymfonyOptions, array $aOptions = []): AbstractFormBlock
{
$oRef = new ReflectionClass($sType);
if($oRef->isSubclassOf(AbstractFormBlock::class) === false){
@@ -82,7 +81,7 @@ class FormBlock extends AbstractTypeFormBlock
}
$aOptions['priority'] = -count($this->aChildrenBlocks);
$oSubFormBlock = new ($sType)($sName, $aOptions);
$oSubFormBlock = new ($sType)($sName, $aSymfonyOptions, $aOptions);
$this->aChildrenBlocks[$sName] = $oSubFormBlock;
$oSubFormBlock->SetParent($this);

View File

@@ -7,12 +7,11 @@
namespace Combodo\iTop\Forms\Block\DataModel;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\Forms\Block\FormBlockException;
use Combodo\iTop\Forms\Block\IO\Converter\StringToAttributeConverter;
use Combodo\iTop\Forms\Block\IO\Format\AttributeIOFormat;
use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use CoreException;
use Combodo\iTop\Forms\IO\Converter\StringToAttributeConverter;
use Combodo\iTop\Forms\IO\Format\AttributeIOFormat;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
use MetaModel;
/**
@@ -29,31 +28,31 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
public const OUTPUT_ATTRIBUTE = 'attribute';
/** @inheritdoc */
public function InitBlockOptions(array &$aUserOptions): void
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['placeholder'] = 'Select an attribute...';
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('placeholder', 'Select an attribute...');
}
/** @inheritdoc */
public function InitInputs(): void
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitInputs();
$this->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
}
/** @inheritdoc */
public function InitOutputs(): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_ATTRIBUTE, AttributeIOFormat::class, new StringToAttributeConverter());
parent::RegisterIO($oIORegister);
$oIORegister->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
$oIORegister->AddOutput(self::OUTPUT_ATTRIBUTE, AttributeIOFormat::class, new StringToAttributeConverter());
}
/** @inheritdoc */
public function UpdateDynamicOptions(string $sEventType = null): void
public function UpdateOptions(OptionsRegister $oOptionsRegister): void
{
$oClass = $this->GetInput(self::INPUT_CLASS_NAME)->GetValue($sEventType);
parent::UpdateOptions($oOptionsRegister);
$oClass = $this->GetInputValue(self::INPUT_CLASS_NAME);
if($oClass === null){
$oOptionsRegister->SetOption('choices', []);
return;
}
$aAttributeCodes = MetaModel::GetAttributesList($oClass);
@@ -63,7 +62,7 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
$aAttributes[$oAttribute->GetLabel()] = $sAttributeCode;
}
$this->aDynamicOptions['choices'] = $aAttributes;
$oOptionsRegister->SetOption('choices', $aAttributes);
}
}

View File

@@ -7,10 +7,11 @@
namespace Combodo\iTop\Forms\Block\DataModel;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\Forms\Block\FormBlockException;
use Combodo\iTop\Forms\Block\IO\Format\AttributeIOFormat;
use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use Combodo\iTop\Forms\IO\Format\AttributeIOFormat;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\IO\Format\RawFormat;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
use Exception;
use MetaModel;
@@ -29,41 +30,36 @@ class AttributeValueChoiceFormBlock extends ChoiceFormBlock
public const OUTPUT_VALUE = 'value';
/** @inheritdoc */
public function InitBlockOptions(array &$aUserOptions): void
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['multiple'] = true;
$aUserOptions['attr'] = [
'size' => 5,
'style' => 'height: auto;',
];
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('multiple', true);
$oOptionsRegister->SetOptionArrayValue('attr', 'size', 5);
$oOptionsRegister->SetOptionArrayValue('attr', 'style', 'height: auto;');
}
/** @inheritdoc */
public function InitInputs(): void
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitInputs();
$this->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
$this->AddInput(self::INPUT_ATTRIBUTE, AttributeIOFormat::class);
}
/** @inheritdoc */
public function InitOutputs(): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_VALUE, RawFormat::class);
parent::RegisterIO($oIORegister);
$oIORegister->AddInput(self::INPUT_CLASS_NAME, ClassIOFormat::class);
$oIORegister->AddInput(self::INPUT_ATTRIBUTE, AttributeIOFormat::class);
$oIORegister->AddOutput(self::OUTPUT_VALUE, RawFormat::class);
}
/** @inheritdoc */
public function UpdateDynamicOptions(string $sEventType = null): void
public function UpdateOptions(OptionsRegister $oOptionsRegister): void
{
$oClassName = $this->GetInput(self::INPUT_CLASS_NAME)->GetValue($sEventType);
$oAttribute = $this->GetInput(self::INPUT_ATTRIBUTE)->GetValue($sEventType);
parent::UpdateOptions($oOptionsRegister);
$oClassName = $this->GetInputValue(self::INPUT_CLASS_NAME);
$oAttribute = $this->GetInputValue(self::INPUT_ATTRIBUTE);
try{
$oAttDef = MetaModel::GetAttributeDef(strval($oClassName), strval($oAttribute));
$aValues = $oAttDef->GetAllowedValues();
$this->aDynamicOptions['choices'] = array_flip($aValues ?? []);
$oOptionsRegister->SetOption('choices', array_flip($aValues ?? []));
}
catch(Exception){}
}

View File

@@ -7,9 +7,11 @@
namespace Combodo\iTop\Forms\Block\DataModel;
use Combodo\iTop\Forms\Block\Base\TextAreaFormBlock;
use Combodo\iTop\Forms\Block\FormType\OqlFormType;
use Combodo\iTop\Forms\Block\IO\Converter\OqlToClassConverter;
use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\FormType\DataModel\OqlFormType;
use Combodo\iTop\Forms\IO\Converter\OqlToClassConverter;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\Register\OptionsRegister;
/**
* Form block for oql expression.
@@ -28,16 +30,18 @@ class OqlFormBlock extends TextAreaFormBlock
}
/** @inheritdoc */
public function InitOutputs(): void
protected function RegisterOptions(OptionsRegister $oOptionsRegister): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_SELECTED_CLASS, ClassIOFormat::class, new OqlToClassConverter());
parent::RegisterOptions($oOptionsRegister);
$oOptionsRegister->SetOption('with_ai_button', true);
}
/** @inheritdoc */
public function InitBlockOptions(array &$aUserOptions): void
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitBlockOptions($aUserOptions);
$aUserOptions['with_ai_button'] = true;
parent::RegisterIO($oIORegister);
$oIORegister->AddOutput(self::OUTPUT_SELECTED_CLASS, ClassIOFormat::class, new OqlToClassConverter());
}
}

View File

@@ -7,8 +7,9 @@
namespace Combodo\iTop\Forms\Block\Expression;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Format\RawFormat;
use Combodo\iTop\Forms\Register\IORegister;
use Combodo\iTop\Forms\FormsException;
use IssueLog;
use Symfony\Component\Form\FormEvents;
@@ -25,17 +26,17 @@ class ExpressionFormBlock extends AbstractFormBlock
const OUTPUT_RESULT_INVERT = "result_invert";
/** @inheritdoc */
public function InitOutputs(): void
protected function RegisterIO(IORegister $oIORegister): void
{
parent::InitOutputs();
$this->AddOutput(self::OUTPUT_RESULT, BooleanIOFormat::class);
$this->AddOutput(self::OUTPUT_RESULT_INVERT, BooleanIOFormat::class);
parent::RegisterIO($oIORegister);
$oIORegister->AddOutput(self::OUTPUT_RESULT, BooleanIOFormat::class);
$oIORegister->AddOutput(self::OUTPUT_RESULT_INVERT, BooleanIOFormat::class);
}
/** @inheritdoc */
public function AllInputsReadyEvent(): void
{
parent::AllInputsReadyEvent();
$this->ComputeExpression(FormEvents::POST_SET_DATA);
$this->ComputeExpression(FormEvents::POST_SUBMIT);
}
@@ -50,7 +51,7 @@ class ExpressionFormBlock extends AbstractFormBlock
public function ComputeExpression(string $sEventType): void
{
try{
$sExpression = $this->GetOptions()['expression'];
$sExpression = $this->GetOption('expression');
$sValue = preg_replace_callback(
self::EXPRESSION_PATTERN,

View File

@@ -29,7 +29,6 @@ class DependencyHandler
/** @var array events */
private array $aEvents = [];
private readonly string $sName;
private readonly FormBuilder $oFormBuilder;
private readonly FormBlock $oFormBlock;
private readonly array $aDependentBlocks;
@@ -43,7 +42,6 @@ class DependencyHandler
*/
public function __construct(FormBuilder $oFormBuilder, FormBlock $oFormBlock, array $aDependentBlocks)
{
$this->sName = $oFormBuilder->getName();
$this->aDependentBlocks = $aDependentBlocks;
$this->oFormBuilder = $oFormBuilder;
$this->oFormBlock = $oFormBlock;
@@ -61,6 +59,36 @@ class DependencyHandler
self::$aDependencyHandlers[] = $this;
}
/**
* Get the form name.
*
* @return string
*/
public function GetName(): string
{
return $this->oFormBuilder->getName();
}
/**
* Get the debug data.
*
* @return array
*/
public function GetDebugData(): array
{
return $this->aEvents;
}
/**
* Get the dependencies map.
*
* @return DependencyMap
*/
public function GetMap(): DependencyMap
{
return $this->oDependenciesMap;
}
/**
* Add form ready listener.
*
@@ -148,9 +176,8 @@ class DependencyHandler
// When dependencies met, add the dependent field if not already done or options changed
if ($oDependentBlock->IsVisible($sEventType) && $oDependentBlock->IsInputsDataReady($sEventType)) {
// Get the dependent field options
$oDependentBlock->UpdateDynamicOptions($sEventType);
$aOptions = $oDependentBlock->GetOptionsMergedWithDynamic($sEventType);
// Get the Symfony options
$aOptions = $oDependentBlock->GetOptions();
// Add the listener callback to the dependent field if it is also a dependency for another field
if ($this->oDependenciesMap->HasBlocksImpactedBy($oDependentBlock->getName())) {
@@ -192,29 +219,16 @@ class DependencyHandler
}
/**
* Get the debug data.
* Add a debug event.
*
* @return array
* @param string $sEvent
* @param string $sForm
* @param mixed $oValue
*
* @return void
*/
public function GetDebugData(): array
{
return $this->aEvents;
}
public function GetMap(): DependencyMap
{
return $this->oDependenciesMap;
}
public function GetName(): string
{
return $this->sName;
}
private function AddEvent(string $sEvent, string $sForm, mixed $oValue = 'NA'): void
{
$this->aEvents[] = [
'builder' => $this->oFormBuilder->getName(),
'event' => $sEvent,

View File

@@ -9,9 +9,9 @@ namespace Combodo\iTop\Forms\FormBuilder;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\Expression\ExpressionFormBlock;
use Combodo\iTop\Forms\Block\FormBlock;
use Combodo\iTop\Forms\Block\IO\FormBinding;
use Combodo\iTop\Forms\Block\IO\FormInput;
use Combodo\iTop\Forms\Block\IO\FormOutput;
use Combodo\iTop\Forms\IO\FormBinding;
use Combodo\iTop\Forms\IO\FormInput;
use Combodo\iTop\Forms\IO\FormOutput;
/**
* Dependencies handler.

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\FormType;
namespace Combodo\iTop\Forms\FormType\Base;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Event\PreSetDataEvent;

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\FormType;
namespace Combodo\iTop\Forms\FormType\Base;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

View File

@@ -4,10 +4,11 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\FormType;
namespace Combodo\iTop\Forms\FormType\Base;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Block\Base\FormBlock;
use Combodo\iTop\Forms\FormType\FormTypeHelper;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\FormType;
namespace Combodo\iTop\Forms\FormType\DataModel;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\FormType;
namespace Combodo\iTop\Forms\FormType;
use Combodo\iTop\Forms\Block\Base\FormBlock;
use Symfony\Component\Form\FormInterface;

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO;
namespace Combodo\iTop\Forms\IO;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Symfony\Component\Form\FormEvents;

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO\Converter;
namespace Combodo\iTop\Forms\IO\Converter;
/**
* Output converter.

View File

@@ -4,10 +4,10 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO\Converter;
namespace Combodo\iTop\Forms\IO\Converter;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
use Combodo\iTop\Forms\IO\Format\RawFormat;
/**
*
@@ -28,7 +28,7 @@ class ChoiceValueToLabelConverter extends AbstractConverter
return null;
}
$aOptions = array_flip($this->oChoiceBlock->GetOptionsMergedWithDynamic()['choices']);
$aOptions = array_flip($this->oChoiceBlock->GetOption('choices'));
return new RawFormat($aOptions[$oData]);
}

View File

@@ -4,9 +4,9 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO\Converter;
namespace Combodo\iTop\Forms\IO\Converter;
use Combodo\iTop\Forms\Block\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use MetaModel;
use Symfony\Component\Filesystem\Exception\IOException;

View File

@@ -4,9 +4,9 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO\Converter;
namespace Combodo\iTop\Forms\IO\Converter;
use Combodo\iTop\Forms\Block\IO\Format\AttributeIOFormat;
use Combodo\iTop\Forms\IO\Format\AttributeIOFormat;
/**
* String to attribute converter.

View File

@@ -4,9 +4,9 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO\Converter;
namespace Combodo\iTop\Forms\IO\Converter;
use Combodo\iTop\Forms\Block\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
/**
* OQL expression to class converter.

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO;
namespace Combodo\iTop\Forms\IO;
/**
*

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block;
namespace Combodo\iTop\Forms\IO;
use Combodo\iTop\Forms\FormsException;

View File

@@ -4,7 +4,7 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO;
namespace Combodo\iTop\Forms\IO;
/**
*

View File

@@ -4,10 +4,10 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Block\IO;
namespace Combodo\iTop\Forms\IO;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\IO\Converter\AbstractConverter;
use Combodo\iTop\Forms\IO\Converter\AbstractConverter;
/**
*

View File

@@ -1,6 +1,6 @@
<?php
namespace Combodo\iTop\Forms\Block\IO\Format;
namespace Combodo\iTop\Forms\IO\Format;
use JsonSerializable;

View File

@@ -1,6 +1,6 @@
<?php
namespace Combodo\iTop\Forms\Block\IO\Format;
namespace Combodo\iTop\Forms\IO\Format;
use JsonSerializable;

View File

@@ -1,6 +1,6 @@
<?php
namespace Combodo\iTop\Forms\Block\IO\Format;
namespace Combodo\iTop\Forms\IO\Format;
use JsonSerializable;

View File

@@ -1,6 +1,6 @@
<?php
namespace Combodo\iTop\Forms\Block\IO\Format;
namespace Combodo\iTop\Forms\IO\Format;
class NumberIOFormat
{

View File

@@ -1,6 +1,6 @@
<?php
namespace Combodo\iTop\Forms\Block\IO\Format;
namespace Combodo\iTop\Forms\IO\Format;
class RawFormat
{

View File

@@ -0,0 +1,316 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Register;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\FormBlockException;
use Combodo\iTop\Forms\IO\Converter\AbstractConverter;
use Combodo\iTop\Forms\IO\FormInput;
use Combodo\iTop\Forms\IO\FormOutput;
/**
*
*/
class IORegister
{
/** @var array */
private array $aInputs = [];
/** @var array */
private array $aOutputs = [];
/**
* @param \Combodo\iTop\Forms\Block\AbstractFormBlock $oFormBlock
*/
public function __construct(private readonly AbstractFormBlock $oFormBlock)
{
}
public function AddInput(string $sName, string $sType): void
{
$oFormInput = new FormInput($sName, $sType, $this->oFormBlock);
$this->aInputs[$oFormInput->GetName()] = $oFormInput;
}
/**
* Add an input connected to another block.
*
* @param string $sName the input name
* @param string $sOutputBlockName
* @param string $sOutputName
*
* @return AbstractFormBlock
* @throws FormBlockException
*/
public function AddInputDependsOn(string $sName, string $sOutputBlockName, string $sOutputName): self
{
$oOutputBlock = $this->oFormBlock->GetParent()->Get($sOutputBlockName);
$oBlockOutput = $oOutputBlock->GetOutput($sOutputName);
$this->AddInput($sName, $oBlockOutput->GetDataType());
$this->DependsOn($sName, $sOutputBlockName, $sOutputName);
return $this;
}
/**
* Attach an input to a block output.
*
* @param string $sInputName the input name
* @param string $sOutputBlockName the dependency block name
* @param string $sOutputName the dependency output name
*
* @return $this
* @throws FormBlockException
*/
public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): self
{
$oOutputBlock = $this->oFormBlock->GetParent()->Get($sOutputBlockName);
$oFormInput = $this->GetInput($sInputName);
$oFormOutput = $oOutputBlock->GetOutput($sOutputName);
$oFormOutput->BindToInput($oFormInput);
return $this;
}
/**
* Attach an output to a parent block output.
*
* @param string $sOutputName output name
* @param string $sParentOutputName parent output name
*
* @return $this
* @throws FormBlockException
*/
public function ImpactParent(string $sOutputName, string $sParentOutputName): self
{
$oFormOutput = $this->GetOutput($sOutputName);
$oParentFormOutput = $this->oFormBlock->GetParent()->GetOutput($sParentOutputName);
$oFormOutput->BindToOutput($oParentFormOutput);
return $this;
}
public function AddOutput(string $sName, string $sType, AbstractConverter $oConverter = null): void
{
$oFormOutput = new FormOutput($sName, $sType, $this->oFormBlock, $oConverter);
$this->aOutputs[$oFormOutput->GetName()] = $oFormOutput;
}
/**
* Get an input.
*
* @param string $sName
*
* @return FormInput
* @throws FormBlockException
*/
public function GetInput(string $sName): FormInput
{
if (!array_key_exists($sName, $this->aInputs)) {
throw new FormBlockException('Missing input '.$sName.' for '.$this->oFormBlock->GetName());
}
return $this->aInputs[$sName];
}
/**
* @return array
*/
public function GetInputs(): array
{
return $this->aInputs;
}
/**
* @return array
*/
public function GetBoundInputs(): array
{
$aInputs = [];
/** @var FormInput $oFormInput */
foreach ($this->aInputs as $oFormInput) {
if ($oFormInput->IsBound() || $oFormInput->HasBindingOut()) {
$aInputs[] = $oFormInput;
}
}
return $aInputs;
}
/**
* @return array
*/
public function GetBoundOutputs(): array
{
$aOutputs = [];
/** @var FormOutput $oFormOutput */
foreach ($this->aOutputs as $oFormOutput) {
if ($oFormOutput->IsBound() || $oFormOutput->HasBindingOut()) {
$aOutputs[] = $oFormOutput;
}
}
return $aOutputs;
}
/**
* Get an output.
*
* @param string $sName output name
*
* @return FormOutput
* @throws FormBlockException
*/
public function GetOutput(string $sName): FormOutput
{
if (!array_key_exists($sName, $this->aOutputs)) {
throw new FormBlockException('Missing output '.$sName.' for '.$this->oFormBlock->GetName());
}
return $this->aOutputs[$sName];
}
/**
* @return array
*/
public function GetOutputs(): array
{
return $this->aOutputs;
}
/**
* Check existence of one or more dependencies.
*
* @return bool
*/
public function HasDependenciesBlocks(): bool
{
foreach ($this->aInputs as $oFormInput) {
if ($oFormInput->IsBound()) {
return true;
}
}
return false;
}
/**
* Check existence of one or more dependents blocks.
*
* @return bool
*/
public function ImpactDependentsBlocks(): bool
{
/** @var FormOutput $oFormOutput */
foreach ($this->aOutputs as $oFormOutput) {
if (count($oFormOutput->GetBindings()) > 0) {
return true;
}
}
return false;
}
/**
* Get bound inputs bindings.
*
* @return array
*/
public function GetBoundInputsBindings(): array
{
$aBindings = [];
/** @var FormInput $oFormInput */
foreach ($this->aInputs as $oFormInput) {
if ($oFormInput->IsBound()) {
$aBindings[$oFormInput->GetName()] = $oFormInput->GetBinding();
}
}
return $aBindings;
}
/**
* Get bound outputs bindings.
*
* @return array
*/
public function GetBoundOutputBindings(): array
{
$aBindings = [];
/** @var FormInput $oFormInput */
foreach ($this->aOutputs as $oFormOutput) {
if ($oFormOutput->IsBound()) {
$aBindings[$oFormOutput->GetName()] = $oFormOutput->GetBinding();
}
}
return $aBindings;
}
/**
* Inputs data ready.
*
* @param string|null $sType
*
* @return bool
*/
public function IsInputsDataReady(string $sType = null): bool
{
foreach ($this->aInputs as $oFormInput) {
if ($oFormInput->IsBound()) {
if (!$oFormInput->IsEventDataReady($sType)) {
return false;
}
}
}
return true;
}
/**
* Compute outputs values.
*
* @param string $sEventType
* @param mixed $oData
*
* @return void
*/
public function ComputeOutputs(string $sEventType, mixed $oData): void
{
/** Iterate throw output @var FormOutput $oFormOutput */
foreach ($this->aOutputs as $oFormOutput) {
// Compute the output value
$oFormOutput->ComputeValue($sEventType, $oData);
}
}
/**
* Attach an input to a parent block input.
*
* @param string $sInputName input name
* @param string $sParentInputName parent input name
*
* @return $this
* @throws FormBlockException
*/
public function DependsOnParent(string $sInputName, string $sParentInputName): self
{
$oFormInput = $this->GetInput($sInputName);
$oParentFormInput = $this->oFormBlock->GetParent()->GetInput($sParentInputName);
$oParentFormInput->BindToInput($oFormInput);
return $this;
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Combodo\iTop\Forms\Register;
class Option
{
public function __construct(public string $sName, public mixed $oValue, public bool $bIsTypeOption = true)
{
}
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Forms\Register;
/**
*
*/
class OptionsRegister
{
/** @var Option[] options used for Symfony type creation */
private array $aOptions = [];
/**
* Set an option.
*
* @param string $sOptionName
* @param mixed $mDefaultValue
* @param bool $bTypeOption
*
* @return void
*/
public function SetOption(string $sOptionName, mixed $mDefaultValue = null, bool $bTypeOption = true): void
{
if(isset($this->aOptions[$sOptionName])){
$this->aOptions[$sOptionName]->oValue = $mDefaultValue;
}
else{
$this->aOptions[$sOptionName] = new Option($sOptionName, $mDefaultValue, $bTypeOption);
}
}
/**
* Set an option array value.
*
* @param string $sOptionName
* @param string $sArrayKey
* @param mixed $mDefaultValue
*
* @return void
*/
public function SetOptionArrayValue(string $sOptionName, string $sArrayKey, mixed $mDefaultValue = null): void
{
// Initialization of the option as an array if not set
if(!isset($this->aOptions[$sOptionName])){
$this->SetOption($sOptionName, []);
}
$this->aOptions[$sOptionName]->oValue[$sArrayKey] = $mDefaultValue;
}
/**
* Get all options.
*
* @return array
*/
public function GetOptions(): array
{
$aOptions = array_filter($this->aOptions, fn ($oElement) => $oElement->bIsTypeOption);
return array_map( fn ($oElement) => $oElement->oValue, $aOptions);
}
/**
* Get a type option.
*
* @param string $sOption
*
* @return mixed
*/
public function GetOption(string $sOption): mixed
{
return $this->aOptions[$sOption]->oValue;
}
/**
* Check if an option exists.
*
* @param string $sOption
*
* @return bool
*/
public function HasOption(string $sOption): bool
{
return array_key_exists($sOption, $this->aOptions);
}
}

View File

@@ -7,6 +7,7 @@
namespace Forms;
use Combodo\iTop\Forms\Block\AbstractFormBlock;
use Combodo\iTop\Forms\Block\AbstractTypeFormBlock;
use Combodo\iTop\Forms\Block\Base\CheckboxFormBlock;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\Forms\Block\Base\FormBlock;
@@ -38,8 +39,10 @@ class Block extends ItopDataTestCase
$aFormBlocks = InterfaceDiscovery::GetInstance()->FindItopClasses(iFormBlock::class);
foreach ($aFormBlocks as $sFormBlock) {
$oChoiceBlock = new($sFormBlock)($sFormBlock);
$oClass = new \ReflectionClass($oChoiceBlock->GetFormType());
$this->assertTrue($oClass->isSubclassOf(AbstractType::class));
if($oChoiceBlock instanceof AbstractTypeFormBlock){
$oClass = new \ReflectionClass($oChoiceBlock->GetFormType());
$this->assertTrue($oClass->isSubclassOf(AbstractType::class));
}
}
}
@@ -63,7 +66,7 @@ class Block extends ItopDataTestCase
$aFormBlocks = InterfaceDiscovery::GetInstance()->FindItopClasses(iFormBlock::class);
foreach ($aFormBlocks as $sFormBlock) {
$oChoiceBlock = new($sFormBlock)($sFormBlock);
$this->assertTrue($oChoiceBlock->GetOptions()['form_block'] === $oChoiceBlock);
$this->assertTrue($oChoiceBlock->GetOption('form_block') === $oChoiceBlock);
}
}
@@ -79,7 +82,7 @@ class Block extends ItopDataTestCase
$oFormBlock = new FormBlock('formBlock');
$oFormBlock->Add('allow_age', CheckboxFormBlock::class, []);
$oBirthdateBlock = $oFormBlock->Add('birthdate', TextFormBlock::class, [])
->DependsOn(AbstractFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
->DependsOn(AbstractTypeFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
$this->assertTrue($oBirthdateBlock->HasDependenciesBlocks());
}
@@ -99,7 +102,7 @@ class Block extends ItopDataTestCase
$oFormBlock->Add('lastname', TextFormBlock::class, []);
$oFormBlock->Add('allow_age', CheckboxFormBlock::class, []);
$oFormBlock->Add('birthdate', TextFormBlock::class, [])
->DependsOn(AbstractFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
->DependsOn(AbstractTypeFormBlock::INPUT_VISIBLE, 'allow_age', CheckboxFormBlock::OUTPUT_CHECKED);
// form builder
$oFormFactoryBuilder = Forms::createFormFactoryBuilder();