mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-05 17:14:20 +01:00
N°8772 - Form dependencies manager implementation - WIP
This commit is contained in:
@@ -477,6 +477,7 @@ return array(
|
||||
'Combodo\\iTop\\Forms\\Block\\Base\\ChoiceFormBlock' => $baseDir . '/sources/Forms/Block/Base/ChoiceFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\Base\\StringFormBlock' => $baseDir . '/sources/Forms/Block/Base/StringFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeValueChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/OqlFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\FormBlock' => $baseDir . '/sources/Forms/Block/FormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\FormInput' => $baseDir . '/sources/Forms/Block/FormInput.php',
|
||||
|
||||
@@ -858,6 +858,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'Combodo\\iTop\\Forms\\Block\\Base\\ChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/ChoiceFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\Base\\StringFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/StringFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeValueChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeValueChoiceFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\DataModel\\OqlFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/OqlFormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\FormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/FormBlock.php',
|
||||
'Combodo\\iTop\\Forms\\Block\\FormInput' => __DIR__ . '/../..' . '/sources/Forms/Block/FormInput.php',
|
||||
|
||||
@@ -32,9 +32,10 @@ abstract class AbstractFormBlock
|
||||
return $this->aOptions;
|
||||
}
|
||||
|
||||
public function AddSubFormBlock(AbstractFormBlock $oSubFormBlock): void
|
||||
public function AddSubFormBlock(AbstractFormBlock $oSubFormBlock): AbstractFormBlock
|
||||
{
|
||||
$this->aSubFormBlocks[] = $oSubFormBlock;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function GetSubFormBlocks(): array
|
||||
@@ -57,11 +58,40 @@ abstract class AbstractFormBlock
|
||||
$this->aFormOutputs[$oFormOutput->GetName()] = $oFormOutput;
|
||||
}
|
||||
|
||||
public function GetOutput(string $sName): FormOutput
|
||||
public function GetOutput(string $sName): ?FormOutput
|
||||
{
|
||||
return $this->aFormOutputs[$sName];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sInputName
|
||||
* @param string $sOutputBlockName
|
||||
* @param string $sOutputName
|
||||
*
|
||||
* @return $this
|
||||
* @throws \Combodo\iTop\Forms\Block\FormsBlockException
|
||||
*/
|
||||
public function DependsOn(string $sInputName, string $sOutputBlockName, string $sOutputName): AbstractFormBlock
|
||||
{
|
||||
$oFormInput = $this->GetInput($sInputName);
|
||||
if (is_null($oFormInput)) {
|
||||
throw new FormsBlockException('Missing input ' . $sInputName . ' for ' . $this->sName);
|
||||
}
|
||||
$oFormInput->Connect($sOutputBlockName, $sOutputName);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function HasConnections(): bool
|
||||
{
|
||||
foreach ($this->aFormInputs as $oFormInput) {
|
||||
if ($oFormInput->HasConnections()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract public function GetFormType(): string;
|
||||
|
||||
abstract public function InitInputs(): void;
|
||||
|
||||
@@ -7,11 +7,11 @@ use Combodo\iTop\Forms\Block\FormInput;
|
||||
|
||||
class AttributeChoiceFormBlock extends ChoiceFormBlock
|
||||
{
|
||||
|
||||
public const INPUT_CLASS_NAME = 'class_name';
|
||||
|
||||
public function InitInputs(): void
|
||||
{
|
||||
$this->AddInput(new FormInput('class_name', 'string'));
|
||||
$this->AddInput(new FormInput(self::INPUT_CLASS_NAME, 'string'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Forms\Block\DataModel;
|
||||
|
||||
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
|
||||
use Combodo\iTop\Forms\Block\FormInput;
|
||||
|
||||
class AttributeValueChoiceFormBlock extends ChoiceFormBlock
|
||||
{
|
||||
|
||||
public const INPUT_CLASS_NAME = 'class_name';
|
||||
public const INPUT_ATTRIBUTE = 'attribute';
|
||||
|
||||
public function __construct(string $sName, array $aOptions = [])
|
||||
{
|
||||
$aOptions['multiple'] = true;
|
||||
parent::__construct($sName, $aOptions);
|
||||
}
|
||||
|
||||
public function InitInputs(): void
|
||||
{
|
||||
$this->AddInput(new FormInput(self::INPUT_CLASS_NAME, 'string'));
|
||||
$this->AddInput(new FormInput(self::INPUT_ATTRIBUTE, 'string'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -8,9 +8,12 @@ use Combodo\iTop\Forms\Block\FormOutput;
|
||||
class OqlFormBlock extends StringFormBlock
|
||||
{
|
||||
|
||||
public const OUTPUT_SELECTED_CLASS = 'selected_class';
|
||||
|
||||
public function InitOutputs(): void
|
||||
{
|
||||
$this->AddOutput(new FormOutput('selected_class', 'string'));
|
||||
parent::InitOutputs();
|
||||
$this->AddOutput(new FormOutput(self::OUTPUT_SELECTED_CLASS, 'string'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,17 +3,17 @@
|
||||
namespace Combodo\iTop\Forms\Block;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
|
||||
class FormBlock extends AbstractFormBlock
|
||||
{
|
||||
public const OUTPUT_VALUE = 'value';
|
||||
|
||||
public function __construct(string $sName, array $aOptions = [])
|
||||
{
|
||||
$aOptions['form_block'] = $this;
|
||||
parent::__construct($sName, $aOptions);
|
||||
}
|
||||
|
||||
|
||||
public function GetFormType(): string
|
||||
{
|
||||
return FormType::class;
|
||||
@@ -25,14 +25,6 @@ class FormBlock extends AbstractFormBlock
|
||||
|
||||
public function InitOutputs(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function Build(FormBuilderInterface $oBuilder): FormInterface
|
||||
{
|
||||
foreach ($this->GetSubFormBlocks() as $oSubForm) {
|
||||
$oBuilder->add($oSubForm->GetName(), $oSubForm->GetFormType(), $oSubForm->GetOptions());
|
||||
}
|
||||
|
||||
return $oBuilder->getForm();
|
||||
$this->AddOutput(new FormOutput(self::OUTPUT_VALUE, 'string'));
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ class FormInput
|
||||
|
||||
private string $sType;
|
||||
|
||||
private array $aConnections = [];
|
||||
|
||||
public function __construct(string $sName, string $sType)
|
||||
{
|
||||
$this->sName = $sName;
|
||||
@@ -33,4 +35,19 @@ class FormInput
|
||||
{
|
||||
$this->sType = $sType;
|
||||
}
|
||||
|
||||
public function Connect(string $sOutputBlockName, string $sOutputName)
|
||||
{
|
||||
$this->aConnections[] = ['block' => $sOutputBlockName, 'output' => $sOutputName];
|
||||
}
|
||||
|
||||
public function GetConnections(): array
|
||||
{
|
||||
return $this->aConnections;
|
||||
}
|
||||
|
||||
public function HasConnections(): bool
|
||||
{
|
||||
return count($this->aConnections) > 0;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class FormOutput
|
||||
|
||||
private string $sType;
|
||||
|
||||
private AbstractConverter $oConverter;
|
||||
private null|AbstractConverter $oConverter;
|
||||
|
||||
public function __construct(string $sName, string $sType, AbstractConverter $oConverter = null)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ class FormOutput
|
||||
|
||||
public function GetOutputValue(mixed $oData): mixed
|
||||
{
|
||||
$this->oConverter->Convert($oData);
|
||||
return $this->oConverter->Convert($oData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
14
sources/Forms/Block/FormsBlockException.php
Normal file
14
sources/Forms/Block/FormsBlockException.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Forms\Block;
|
||||
|
||||
use Combodo\iTop\Forms\FormsException;
|
||||
|
||||
class FormsBlockException extends FormsException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Combodo\iTop\Forms\FormBuilder;
|
||||
|
||||
use Combodo\iTop\Forms\Dependency\DependencyDescription;
|
||||
use Combodo\iTop\Forms\Dependency\DependencyHandler;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
@@ -30,44 +29,30 @@ class FormBuilder implements FormBuilderInterface, \IteratorAggregate
|
||||
*/
|
||||
public function __construct(private FormBuilderInterface $builder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a dependency description to the form builder.
|
||||
* The associate form will be created as a hidden field and added later when all its dependencies were met.
|
||||
*
|
||||
* @param DependencyDescription $oDependencyDescription the dependency description
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function AddDependency(DependencyDescription $oDependencyDescription): void
|
||||
{
|
||||
if($this->dependencyHandler === null){
|
||||
\IssueLog::Error('create dependency handler ' . $this->builder->getName());
|
||||
$this->dependencyHandler = new DependencyHandler($this->builder);
|
||||
}
|
||||
|
||||
$this->dependencyHandler->AddDependencyDescription($oDependencyDescription);
|
||||
$this->InitFormBlocks();
|
||||
}
|
||||
|
||||
public function add(string|FormBuilderInterface $child, ?string $type = null, array $options = []): static
|
||||
{
|
||||
if(!empty($options['bindings'])) {
|
||||
$this->builder->add($child, HiddenType::class);
|
||||
$this->AddDependency(new DependencyDescription($options['bindings'], $child, $type, $options));
|
||||
}
|
||||
else{
|
||||
$this->builder->add($child, $type, $options);
|
||||
}
|
||||
|
||||
$this->builder->add($child, $type, $options);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addExpression(string $name, string $expression): static
|
||||
private function InitFormBlocks()
|
||||
{
|
||||
$options['bindings'] = [$expression];
|
||||
return $this->add($name, null, $options);
|
||||
$oFormBlock = $this->builder->getOption('form_block');
|
||||
if (is_null($oFormBlock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var \Combodo\iTop\Forms\Block\FormBlock $oSubFormBlock */
|
||||
foreach ($oFormBlock->GetSubFormBlocks() as $oSubFormBlock) {
|
||||
if ($oSubFormBlock->HasConnections()) {
|
||||
$this->builder->add($oSubFormBlock->GetName(), HiddenType::class);
|
||||
} else {
|
||||
$this->add($oSubFormBlock->GetName(), $oSubFormBlock->GetFormType(), $oSubFormBlock->getOptions());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pure decoration of FormBuilderInterface
|
||||
|
||||
@@ -6,8 +6,6 @@ use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class FormTypeExtension extends AbstractTypeExtension
|
||||
@@ -23,9 +21,7 @@ class FormTypeExtension extends AbstractTypeExtension
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefined([
|
||||
'inputs',
|
||||
'outputs',
|
||||
'bindings',
|
||||
'form_block',
|
||||
'listener_callback',
|
||||
]);
|
||||
}
|
||||
|
||||
12
sources/Forms/FormsException.php
Normal file
12
sources/Forms/FormsException.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Forms;
|
||||
|
||||
class FormsException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user