mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 02:58:43 +02:00
N°8772 - dynamic form
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
32
sources/Forms/Block/Base/ChoiceFromInputs.php
Normal file
32
sources/Forms/Block/Base/ChoiceFromInputs.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user