mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-04 00:24:14 +01:00
N°8771 - Add Symfony form component to iTop core
- IO debug
This commit is contained in:
@@ -482,6 +482,8 @@ return array(
|
||||
'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\\AbstractFormIO' => $baseDir . '/sources/Forms/Block/IO/AbstractFormIO.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',
|
||||
|
||||
@@ -863,6 +863,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'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\\AbstractFormIO' => __DIR__ . '/../..' . '/sources/Forms/Block/IO/AbstractFormIO.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',
|
||||
|
||||
@@ -34,6 +34,9 @@ abstract class AbstractFormBlock
|
||||
/** @var array form block outputs */
|
||||
private array $aFormOutputs = [];
|
||||
|
||||
/** @var bool flag */
|
||||
private bool $bIsAdded = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -49,6 +52,7 @@ abstract class AbstractFormBlock
|
||||
|
||||
$this->InitInputs();
|
||||
$this->InitOutputs();
|
||||
$this->aOptions = array_merge($this->aOptions, $this->InitOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,6 +108,7 @@ abstract class AbstractFormBlock
|
||||
*/
|
||||
public function AddInput(FormInput $oFormInput): void
|
||||
{
|
||||
$oFormInput->SetOwnerBlock($this);
|
||||
$this->aFormInputs[$oFormInput->GetName()] = $oFormInput;
|
||||
}
|
||||
|
||||
@@ -133,6 +138,7 @@ abstract class AbstractFormBlock
|
||||
*/
|
||||
public function AddOutput(FormOutput $oFormOutput): void
|
||||
{
|
||||
$oFormOutput->SetOwnerBlock($this);
|
||||
$this->aFormOutputs[$oFormOutput->GetName()] = $oFormOutput;
|
||||
}
|
||||
|
||||
@@ -168,10 +174,11 @@ abstract class AbstractFormBlock
|
||||
* @return $this
|
||||
* @throws FormBlockException
|
||||
*/
|
||||
public function DependsOn(string $sInputName, FormBlock $sOutputBlock, string $sOutputName): AbstractFormBlock
|
||||
public function DependsOn(string $sInputName, FormBlock $oOutputBlock, string $sOutputName): AbstractFormBlock
|
||||
{
|
||||
$oFormInput = $this->GetInput($sInputName);
|
||||
$oFormInput->Connect($sOutputBlock, $sOutputName);
|
||||
$oFormOutput = $oOutputBlock->GetOutput($sOutputName);
|
||||
$oFormInput->Bind($oFormOutput);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -179,23 +186,47 @@ abstract class AbstractFormBlock
|
||||
public function HasConnections(): bool
|
||||
{
|
||||
foreach ($this->aFormInputs as $oFormInput) {
|
||||
if ($oFormInput->HasConnections()) {
|
||||
if ($oFormInput->IsConnected()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetInputsConnections(): array
|
||||
public function GetInputsBindings(): array
|
||||
{
|
||||
$aConnections = [];
|
||||
$aBindings = [];
|
||||
|
||||
/** @var FormInput $oFormInput */
|
||||
foreach ($this->aFormInputs as $oFormInput) {
|
||||
if ($oFormInput->HasConnections()) {
|
||||
$aConnections[$oFormInput->GetName()] = $oFormInput->GetConnections();
|
||||
if ($oFormInput->IsConnected()) {
|
||||
$aBindings[$oFormInput->GetName()] = $oFormInput->GetBinding();
|
||||
}
|
||||
}
|
||||
return $aConnections;
|
||||
return $aBindings;
|
||||
}
|
||||
|
||||
public function IsInputsReady(string $sEventType): bool
|
||||
{
|
||||
foreach ($this->aFormInputs as $oFormInput) {
|
||||
if ($oFormInput->IsConnected()) {
|
||||
if(!$oFormInput->IsDataReady($sEventType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function IsAdded(): bool
|
||||
{
|
||||
return $this->bIsAdded;
|
||||
}
|
||||
|
||||
public function SetAdded(bool $bIsAdded): void
|
||||
{
|
||||
$this->bIsAdded = $bIsAdded;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +253,7 @@ abstract class AbstractFormBlock
|
||||
/**
|
||||
* Initialize options.
|
||||
*
|
||||
* @return void
|
||||
* @return array
|
||||
*/
|
||||
abstract public function InitOptions(): void;
|
||||
abstract public function InitOptions(): array;
|
||||
}
|
||||
@@ -11,7 +11,6 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -34,9 +33,25 @@ class AttributeChoiceFormBlock extends ChoiceFormBlock
|
||||
$this->AddInput(new FormInput(self::INPUT_CLASS_NAME, ClassIOFormat::class));
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function InitOutputs(): void
|
||||
{
|
||||
parent::InitOutputs();
|
||||
$this->AddOutput(new FormOutput(self::OUTPUT_ATTRIBUTE, AttributeIOFormat::class, new StringToAttributeConverter()));
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function GetOptions(): array
|
||||
{
|
||||
$aOptions = parent::GetOptions();
|
||||
|
||||
$oBinding = $this->GetInput(self::INPUT_CLASS_NAME)->GetBinding();
|
||||
$oConnectionValue = $oBinding->oOutput->Value();
|
||||
|
||||
$aAttributeCodes = \MetaModel::GetAttributesList($oConnectionValue);
|
||||
$aAttributeCodes = array_combine($aAttributeCodes, $aAttributeCodes) ;
|
||||
$aOptions['choices'] = $aAttributeCodes;
|
||||
|
||||
return $aOptions;
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,15 @@ class AttributeValueChoiceFormBlock extends ChoiceFormBlock
|
||||
public const INPUT_ATTRIBUTE = 'attribute';
|
||||
|
||||
/** @inheritdoc */
|
||||
public function InitOptions(array &$aOptions = []): void
|
||||
public function InitOptions(array &$aOptions = []): array
|
||||
{
|
||||
$aOptions['multiple'] = true;
|
||||
$aOptions['attr'] = [
|
||||
'size' => 10,
|
||||
'style' => 'height: auto;'
|
||||
];
|
||||
|
||||
return $aOptions;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@@ -36,4 +42,22 @@ class AttributeValueChoiceFormBlock extends ChoiceFormBlock
|
||||
$this->AddInput(new FormInput(self::INPUT_ATTRIBUTE, AttributeIOFormat::class));
|
||||
}
|
||||
|
||||
public function GetOptions(): array
|
||||
{
|
||||
$aOptions = parent::GetOptions();
|
||||
|
||||
$oBindingClassName = $this->GetInput(self::INPUT_CLASS_NAME)->GetBinding();
|
||||
$oClassName = $oBindingClassName->oOutput->Value();
|
||||
|
||||
$oBindingAttribute = $this->GetInput(self::INPUT_ATTRIBUTE)->GetBinding();
|
||||
$oAttribute = $oBindingAttribute->oOutput->Value();
|
||||
|
||||
$oAttDef = \MetaModel::GetAttributeDef(strval($oClassName), strval($oAttribute));
|
||||
$aValues = $oAttDef->GetAllowedValues();
|
||||
|
||||
$aOptions['choices'] = array_flip($aValues);
|
||||
|
||||
return $aOptions;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,8 +35,8 @@ class FormBlock extends AbstractFormBlock
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function InitOptions(): void
|
||||
public function InitOptions(): array
|
||||
{
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
26
sources/Forms/Block/IO/AbstractFormIO.php
Normal file
26
sources/Forms/Block/IO/AbstractFormIO.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Forms\Block\IO;
|
||||
|
||||
use Combodo\iTop\Forms\Block\AbstractFormBlock;
|
||||
|
||||
class AbstractFormIO
|
||||
{
|
||||
|
||||
private AbstractFormBlock $oOwnerBlock;
|
||||
|
||||
public function SetOwnerBlock(AbstractFormBlock $oOwnerBlock): void
|
||||
{
|
||||
$this->oOwnerBlock = $oOwnerBlock;
|
||||
}
|
||||
|
||||
public function GetOwnerBlock(): AbstractFormBlock
|
||||
{
|
||||
return $this->oOwnerBlock;
|
||||
}
|
||||
|
||||
}
|
||||
16
sources/Forms/Block/IO/FormBinding.php
Normal file
16
sources/Forms/Block/IO/FormBinding.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Forms\Block\IO;
|
||||
|
||||
|
||||
class FormBinding
|
||||
{
|
||||
public function __construct(public readonly FormInput $oInput, public readonly FormOutput $oOutput)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,16 +6,15 @@
|
||||
|
||||
namespace Combodo\iTop\Forms\Block\IO;
|
||||
|
||||
use Combodo\iTop\Forms\Block\FormBlock;
|
||||
use Combodo\iTop\Forms\Block\FormBlockIOException;
|
||||
|
||||
class FormInput
|
||||
class FormInput extends AbstractFormIO
|
||||
{
|
||||
private string $sName;
|
||||
|
||||
private string $sType;
|
||||
|
||||
private array $aConnections = [];
|
||||
private FormBinding|null $oBinding = null;
|
||||
|
||||
public function __construct(string $sName, string $sType)
|
||||
{
|
||||
@@ -43,23 +42,28 @@ class FormInput
|
||||
$this->sType = $sType;
|
||||
}
|
||||
|
||||
public function Connect(FormBlock $sOutputBlock, string $sOutputName): void
|
||||
public function Bind(FormOutput $oFormOutput): void
|
||||
{
|
||||
$sOutputType = $sOutputBlock->GetOutput($sOutputName)->GetType();
|
||||
if($this->sType !== $sOutputType){
|
||||
if($this->sType !== $oFormOutput->GetType()){
|
||||
throw new FormBlockIOException('Cannot connect input types incompatibles ' . $this->sName . ' to ' . $sOutputBlock->GetName() . ' ' . $sOutputName);
|
||||
}
|
||||
|
||||
$this->aConnections[] = ['output_block' => $sOutputBlock, 'output' => $sOutputName];
|
||||
$this->oBinding = new FormBinding($this, $oFormOutput);
|
||||
}
|
||||
|
||||
public function GetConnections(): array
|
||||
public function GetBinding(): FormBinding
|
||||
{
|
||||
return $this->aConnections;
|
||||
return $this->oBinding;
|
||||
}
|
||||
|
||||
public function HasConnections(): bool
|
||||
public function IsDataReady(string $sEventType): bool
|
||||
{
|
||||
return count($this->aConnections) > 0;
|
||||
return $this->oBinding->oOutput->HasValue($sEventType);
|
||||
}
|
||||
|
||||
public function IsConnected(): bool
|
||||
{
|
||||
return $this->oBinding !== null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,15 +7,16 @@
|
||||
namespace Combodo\iTop\Forms\Block\IO;
|
||||
|
||||
use Combodo\iTop\Forms\Converter\AbstractOutputConverter;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
class FormOutput
|
||||
class FormOutput extends AbstractFormIO
|
||||
{
|
||||
private string $sName;
|
||||
|
||||
private string $sType;
|
||||
|
||||
private null|AbstractOutputConverter $oConverter;
|
||||
private ?array $aValues = null;
|
||||
private array $aValues = [];
|
||||
|
||||
public function __construct(string $sName, string $sType, AbstractOutputConverter $oConverter = null)
|
||||
{
|
||||
@@ -62,9 +63,25 @@ class FormOutput
|
||||
return $this->aValues[$sEventType] ?? null;
|
||||
}
|
||||
|
||||
public function Value(): mixed
|
||||
{
|
||||
if(array_key_exists(FormEvents::POST_SUBMIT, $this->aValues) ){
|
||||
return $this->aValues[FormEvents::POST_SUBMIT];
|
||||
}
|
||||
if(array_key_exists(FormEvents::POST_SET_DATA, $this->aValues) ){
|
||||
return $this->aValues[FormEvents::POST_SET_DATA];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function HasValue(string $sEventType): bool
|
||||
{
|
||||
return array_key_exists($sEventType, $this->aValues) && $this->aValues[$sEventType] !== null;
|
||||
}
|
||||
|
||||
public function HasValues(): bool
|
||||
{
|
||||
return $this->aValues !== null;
|
||||
return count($this->aValues) > 0;
|
||||
}
|
||||
|
||||
public function GetValues(): array
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
<?php
|
||||
//
|
||||
//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)));
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//}
|
||||
@@ -6,11 +6,10 @@
|
||||
|
||||
namespace Combodo\iTop\Forms\FormBuilder;
|
||||
|
||||
use Symfony\Component\Form\Event\PostSetDataEvent;
|
||||
use Symfony\Component\Form\Event\PostSubmitEvent;
|
||||
use Combodo\iTop\Forms\Block\FormBlock;
|
||||
use Combodo\iTop\Forms\Block\IO\FormInput;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
|
||||
/**
|
||||
* Dependencies handler.
|
||||
@@ -86,13 +85,44 @@ class DependencyHandler
|
||||
|
||||
/** Iterate throw dependencies map... */
|
||||
$sOutputBlockName = $oForm->getName();
|
||||
$oOutputBlock = $this->oFormBuilder->GetFormBlock($sOutputBlockName);
|
||||
foreach ($this->aDependenciesMap->GetOutputsForBlock($sOutputBlockName) as $sOutputName) {
|
||||
$oOutput = $oOutputBlock->GetOutput($sOutputName);
|
||||
$oOutput->UpdateOutputValue($oEvent->getData(), $sEventType);
|
||||
if($this->aDependenciesMap->IsBlockHasOutputs($sOutputBlockName)){
|
||||
$oOutputBlock = $this->oFormBuilder->GetFormBlock($sOutputBlockName);
|
||||
foreach ($this->aDependenciesMap->GetOutputsForBlock($sOutputBlockName) as $sOutputName) {
|
||||
$oOutput = $oOutputBlock->GetOutput($sOutputName);
|
||||
$oOutput->UpdateOutputValue($oEvent->getData(), $sEventType);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
||||
foreach ($this->aDependentBlocks as $oDependentBlock)
|
||||
{
|
||||
|
||||
// When dependencies met, add the dependent field if not already done
|
||||
if(!$oDependentBlock->IsAdded() && $oDependentBlock->IsInputsReady($sEventType)) {
|
||||
|
||||
// Get the dependent field options
|
||||
$aOptions = $oDependentBlock->GetOptions();
|
||||
|
||||
// Add the listener callback to the dependent field if it is also a dependency for another field
|
||||
if($this->aDependenciesMap->IsTheBlockInDependencies($oDependentBlock->getName())) {
|
||||
$aOptions = array_merge($aOptions, [
|
||||
'listener_callback' => $this->GetEventListeningCallback(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Mark the dependency as added
|
||||
$oDependentBlock->SetAdded(true);
|
||||
|
||||
// Add the dependent field to the form
|
||||
$oForm->getParent()->add($oDependentBlock->GetName(), $oDependentBlock->GetFormType(), $aOptions);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
namespace Combodo\iTop\Forms\FormBuilder;
|
||||
|
||||
use Combodo\iTop\Forms\Block\FormBlock;
|
||||
use Symfony\Component\Form\Event\PostSetDataEvent;
|
||||
use Symfony\Component\Form\Event\PostSubmitEvent;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Combodo\iTop\Forms\Block\IO\FormBinding;
|
||||
|
||||
/**
|
||||
* Dependencies handler.
|
||||
@@ -19,64 +15,95 @@ use Symfony\Component\Form\FormInterface;
|
||||
*/
|
||||
class DependencyMap
|
||||
{
|
||||
/** @var array dependant blocks */
|
||||
private array $aDependentBlocks = [];
|
||||
|
||||
/** @var array dependencies map */
|
||||
private array $aDependenciesMap = [];
|
||||
private array $aDependenciesMap;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $aDependentBlocks
|
||||
*/
|
||||
public function __construct(array $aDependentBlocks)
|
||||
public function __construct(private readonly array $aDependentBlocks)
|
||||
{
|
||||
$this->aDependentBlocks = $aDependentBlocks;
|
||||
|
||||
// Initialization
|
||||
$this->Init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function Init(): void
|
||||
{
|
||||
/** iterate throw dependents blocks... @var FormBlock $oDependentBlock */
|
||||
foreach ($this->aDependentBlocks as $oDependentBlock) {
|
||||
|
||||
/** iterate throw the block inputs connections... **/
|
||||
foreach ($oDependentBlock->GetInputsConnections() as $sInputName => $aConnections) {
|
||||
/** iterate throw the block inputs connections... @var FormBinding $oBinding**/
|
||||
foreach ($oDependentBlock->GetInputsBindings() as $sInputName => $oBinding) {
|
||||
|
||||
/** Iterate throw the input connections... */
|
||||
foreach ($aConnections as $aConnection) {
|
||||
// connection information
|
||||
$sOutputBlockName = $oBinding->oOutput->GetOwnerBlock()->GetName();
|
||||
$sOutputName = $oBinding->oOutput->GetName();
|
||||
|
||||
// connection information
|
||||
$sOutputBlock = $aConnection['output_block'];
|
||||
$sOutputBlockName = $sOutputBlock->getName();
|
||||
$sOutputName = $aConnection['output'];
|
||||
|
||||
// initialize map
|
||||
if (!isset($this->aDependenciesMap[$sOutputBlockName])) {
|
||||
$this->aDependenciesMap[$sOutputBlockName] = [];
|
||||
}
|
||||
if (!isset($this->aDependenciesMap[$sOutputBlockName][$sOutputName])) {
|
||||
$this->aDependenciesMap[$sOutputBlockName][$sOutputName] = [];
|
||||
}
|
||||
|
||||
// add to map
|
||||
$this->aDependenciesMap[$sOutputBlockName][$sOutputName][] = ['input_block' => $oDependentBlock, 'input_name' => $sInputName];
|
||||
// initialize map
|
||||
if (!isset($this->aDependenciesMap[$sOutputBlockName])) {
|
||||
$this->aDependenciesMap[$sOutputBlockName] = [];
|
||||
}
|
||||
if (!isset($this->aDependenciesMap[$sOutputBlockName][$sOutputName])) {
|
||||
$this->aDependenciesMap[$sOutputBlockName][$sOutputName] = [];
|
||||
}
|
||||
|
||||
// add to map
|
||||
$this->aDependenciesMap[$sOutputBlockName][$sOutputName][] = $oBinding;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetListenedBlockNames(): array
|
||||
{
|
||||
return array_keys($this->aDependenciesMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sBlockName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsBlockHasOutputs(string $sBlockName): bool
|
||||
{
|
||||
return array_key_exists($sBlockName, $this->aDependenciesMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sBlockName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetOutputsForBlock(string $sBlockName): array
|
||||
{
|
||||
return array_keys($this->aDependenciesMap[$sBlockName]);
|
||||
}
|
||||
|
||||
public function GetOutputsDependenciesForBlock(string $sOutputBlockName): array
|
||||
{
|
||||
return $this->aDependenciesMap[$sOutputBlockName];
|
||||
}
|
||||
|
||||
public function IsTheBlockInDependencies(string $sBlockName): bool
|
||||
{
|
||||
foreach ($this->aDependentBlocks as $oDependentBlock)
|
||||
{
|
||||
if($oDependentBlock->getName() === $sBlockName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ class FormBuilder implements FormBuilderInterface, \IteratorAggregate
|
||||
$aDependentBlocks[] = $oSubFormBlock;
|
||||
} else {
|
||||
$this->add($oSubFormBlock->GetName(), $oSubFormBlock->GetFormType(), $oSubFormBlock->getOptions());
|
||||
$oSubFormBlock->SetAdded(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,13 +60,6 @@ class AttributeChoiceType extends AbstractType
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function GetOptionsFromInputs(array $inputs): array
|
||||
{
|
||||
$aAttributeCodes = \MetaModel::GetAttributesList($inputs['object_class']);
|
||||
|
||||
return [
|
||||
'choices' => array_combine($aAttributeCodes, $aAttributeCodes)
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,29 +21,26 @@
|
||||
{%- block form_row -%}
|
||||
{% set row_attr = row_attr|merge({class: (row_attr.class|default('') ~ ' ibo-field ibo-content-block ibo-block ibo-field-small')|trim}) %}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_row -%}
|
||||
|
||||
{%- block form_widget -%}
|
||||
{{- parent() -}}
|
||||
{% if form_block is defined %}
|
||||
{% for output in form_block.GetOutputs() %}
|
||||
<ul>
|
||||
{% if output.HasValues %}
|
||||
<li style="background-color:#dac2e3;border-radius: 8px;padding: 1px 4px;font-size: 1rem;margin: 5px 0;">
|
||||
<div>
|
||||
<div><b>{{ output.name }}</b></div>
|
||||
{% for t,v in output.GetValues %}
|
||||
<div>- {{ t }}: {{ v }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if output.HasValues %}
|
||||
<li style="background-color:#dac2e3;border-radius: 8px;padding: 1px 4px;font-size: 1rem;margin: 5px 0;">
|
||||
<div>
|
||||
<div><b>{{ output.name }}</b></div>
|
||||
{% for t,v in output.GetValues %}
|
||||
<div>- {{ t }}: {{ v }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% else %}
|
||||
Aucun output
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{%- endblock form_widget -%}
|
||||
{%- endblock form_row -%}
|
||||
|
||||
{%- block form_errors -%}
|
||||
<div class="form-error">
|
||||
|
||||
Reference in New Issue
Block a user