mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
SDK Form demonstrator
This commit is contained in:
@@ -562,7 +562,70 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
|
||||
</event_data>
|
||||
</event>
|
||||
</events>
|
||||
<forms>
|
||||
<form id="DashletHeaderDynamicProperties" xsi:type="FormType">
|
||||
<form_types>
|
||||
<form_type id="title" xsi:type="TextType">
|
||||
<options>
|
||||
<label>UI:DashletHeaderDynamic:Prop-Title</label>
|
||||
<default>UI:DashletHeaderDynamic:Prop-Title:Default</default>
|
||||
</options>
|
||||
</form_type>
|
||||
<form_type id="icon" xsi:type="IconType">
|
||||
<options>
|
||||
<label>UI:DashletHeaderDynamic:Prop-Icon</label>
|
||||
<default>images/icons/icons8-customer.svg</default>
|
||||
</options>
|
||||
</form_type>
|
||||
<form_type id="subtitle" xsi:type="TextType">
|
||||
<options>
|
||||
<label>UI:DashletHeaderDynamic:Prop-Subtitle</label>
|
||||
<default>UI:DashletHeaderDynamic:Prop-Subtitle:Default</default>
|
||||
</options>
|
||||
</form_type>
|
||||
<form_type id="query" xsi:type="QueryType">
|
||||
<options>
|
||||
<label>UI:DashletHeaderDynamic:Prop-Query</label>
|
||||
<default>SELECT Contact</default>
|
||||
</options>
|
||||
</form_type>
|
||||
<form_type id="group_by" xsi:type="GroupByAttcodeType">
|
||||
<options>
|
||||
<label>UI:DashletHeaderDynamic:Prop-GroupBy</label>
|
||||
<default>status</default>
|
||||
<class_source>query</class_source>
|
||||
</options>
|
||||
</form_type>
|
||||
<form_type id="values" xsi:type="ValuesFromAttcodeType">
|
||||
<options>
|
||||
<label>UI:DashletHeaderDynamic:Prop-Values</label>
|
||||
<default>
|
||||
<values>
|
||||
<value id="active"/>
|
||||
<value id="inactive"/>
|
||||
</values>
|
||||
</default>
|
||||
<attcode_source>group_by</attcode_source>
|
||||
</options>
|
||||
</form_type>
|
||||
</form_types>
|
||||
</form>
|
||||
</forms>
|
||||
<meta>
|
||||
<form_type_definitions>
|
||||
<form_type_definition id="IconType">
|
||||
<options>
|
||||
<option id="label">
|
||||
<mandatory>true</mandatory>
|
||||
<type>string</type>
|
||||
</option>
|
||||
<option id="default">
|
||||
<mandatory>true</mandatory>
|
||||
<type>string</type>
|
||||
</option>
|
||||
</options>
|
||||
</form_type_definition>
|
||||
</form_type_definitions>
|
||||
<classes>
|
||||
<class id="cmdbAbstractObject" _delta="define">
|
||||
<methods>
|
||||
|
||||
@@ -42,6 +42,7 @@ register_shutdown_function(function()
|
||||
$sReservedMemory = null;
|
||||
if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR))
|
||||
{
|
||||
var_export($err);
|
||||
// Remove stack trace from MySQLException (since 2.7.2 see N°3174)
|
||||
$sMessage = $err['message'];
|
||||
if (strpos($sMessage, 'MySQLException') !== false) {
|
||||
|
||||
@@ -430,6 +430,12 @@ return array(
|
||||
'Combodo\\iTop\\Dependencies\\NPM\\iTopNPM' => $baseDir . '/sources/Dependencies/NPM/iTopNPM.php',
|
||||
'Combodo\\iTop\\DesignDocument' => $baseDir . '/core/designdocument.class.inc.php',
|
||||
'Combodo\\iTop\\DesignElement' => $baseDir . '/core/designdocument.class.inc.php',
|
||||
'Combodo\\iTop\\FormType\\Base\\HiddenType' => $baseDir . '/sources/FormType/Base/HiddenType.php',
|
||||
'Combodo\\iTop\\FormType\\Base\\TextType' => $baseDir . '/sources/FormType/Base/TextType.php',
|
||||
'Combodo\\iTop\\FormType\\Base\\TextareaType' => $baseDir . '/sources/FormType/Base/TextareaType.php',
|
||||
'Combodo\\iTop\\FormType\\Orm\\AttCodeGroupByType' => $baseDir . '/sources/FormType/Orm/AttCodeGroupByType.php',
|
||||
'Combodo\\iTop\\FormType\\Orm\\QueryType' => $baseDir . '/sources/FormType/Orm/QueryType.php',
|
||||
'Combodo\\iTop\\FormType\\Orm\\ValuesFromAttcodeType' => $baseDir . '/sources/FormType/Orm/ValuesFromAttcodeType.php',
|
||||
'Combodo\\iTop\\Form\\Field\\AbstractSimpleField' => $baseDir . '/sources/Form/Field/AbstractSimpleField.php',
|
||||
'Combodo\\iTop\\Form\\Field\\BlobField' => $baseDir . '/sources/Form/Field/BlobField.php',
|
||||
'Combodo\\iTop\\Form\\Field\\CaseLogField' => $baseDir . '/sources/Form/Field/CaseLogField.php',
|
||||
|
||||
@@ -785,6 +785,12 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'Combodo\\iTop\\Dependencies\\NPM\\iTopNPM' => __DIR__ . '/../..' . '/sources/Dependencies/NPM/iTopNPM.php',
|
||||
'Combodo\\iTop\\DesignDocument' => __DIR__ . '/../..' . '/core/designdocument.class.inc.php',
|
||||
'Combodo\\iTop\\DesignElement' => __DIR__ . '/../..' . '/core/designdocument.class.inc.php',
|
||||
'Combodo\\iTop\\FormType\\Base\\HiddenType' => __DIR__ . '/../..' . '/sources/FormType/Base/HiddenType.php',
|
||||
'Combodo\\iTop\\FormType\\Base\\TextType' => __DIR__ . '/../..' . '/sources/FormType/Base/TextType.php',
|
||||
'Combodo\\iTop\\FormType\\Base\\TextareaType' => __DIR__ . '/../..' . '/sources/FormType/Base/TextareaType.php',
|
||||
'Combodo\\iTop\\FormType\\Orm\\AttCodeGroupByType' => __DIR__ . '/../..' . '/sources/FormType/Orm/AttCodeGroupByType.php',
|
||||
'Combodo\\iTop\\FormType\\Orm\\QueryType' => __DIR__ . '/../..' . '/sources/FormType/Orm/QueryType.php',
|
||||
'Combodo\\iTop\\FormType\\Orm\\ValuesFromAttcodeType' => __DIR__ . '/../..' . '/sources/FormType/Orm/ValuesFromAttcodeType.php',
|
||||
'Combodo\\iTop\\Form\\Field\\AbstractSimpleField' => __DIR__ . '/../..' . '/sources/Form/Field/AbstractSimpleField.php',
|
||||
'Combodo\\iTop\\Form\\Field\\BlobField' => __DIR__ . '/../..' . '/sources/Form/Field/BlobField.php',
|
||||
'Combodo\\iTop\\Form\\Field\\CaseLogField' => __DIR__ . '/../..' . '/sources/Form/Field/CaseLogField.php',
|
||||
|
||||
@@ -697,6 +697,9 @@ abstract class Controller extends AbstractController
|
||||
|
||||
public function GetForm(string $type = FormType::class, mixed $data = null, array $options = []): FormInterface
|
||||
{
|
||||
if (is_null($data)) {
|
||||
$data = $type::GetDefaultData();
|
||||
}
|
||||
return $this->GetFormBuilder($type, $data,$options)->getForm();
|
||||
}
|
||||
|
||||
|
||||
23
sources/FormType/Base/HiddenType.php
Normal file
23
sources/FormType/Base/HiddenType.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\FormType\Base;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType as SymfonyHiddenType;
|
||||
|
||||
class HiddenType extends AbstractType
|
||||
{
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return SymfonyHiddenType::class;
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'itop_hidden';
|
||||
}
|
||||
}
|
||||
23
sources/FormType/Base/TextType.php
Normal file
23
sources/FormType/Base/TextType.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\FormType\Base;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType as SymfonyTextType;
|
||||
|
||||
class TextType extends AbstractType
|
||||
{
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return SymfonyTextType::class;
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'itop_text';
|
||||
}
|
||||
}
|
||||
29
sources/FormType/Base/TextareaType.php
Normal file
29
sources/FormType/Base/TextareaType.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\FormType\Base;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType as SymfonyTextareaType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class TextareaType extends AbstractType
|
||||
{
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return SymfonyTextareaType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'itop_textarea';
|
||||
}
|
||||
}
|
||||
124
sources/FormType/Orm/AttCodeGroupByType.php
Normal file
124
sources/FormType/Orm/AttCodeGroupByType.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\FormType\Orm;
|
||||
|
||||
use Combodo\iTop\FormType\Base\HiddenType;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType as SymfonyChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AttCodeGroupByType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('hidden', HiddenType::class, ['mapped' => false]);
|
||||
$sRelatedNode = $options['query_source'];
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($sRelatedNode): void {
|
||||
$oForm = $event->getForm();
|
||||
$sCurrentValue = $oForm->getParent()->get($sRelatedNode)->getData();
|
||||
$this->BuildSubField($oForm, $sCurrentValue);
|
||||
});
|
||||
|
||||
$builder->get('hidden')->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($sRelatedNode): void {
|
||||
$oForm = $event->getForm()->getParent();
|
||||
$sCurrentValue = $oForm->getParent()->get($sRelatedNode)->getData();
|
||||
$this->BuildSubField($oForm, $sCurrentValue);
|
||||
});
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
$resolver->setRequired('query_source');
|
||||
$resolver->setAllowedTypes('query_source', 'string');
|
||||
}
|
||||
|
||||
public function BuildSubField(FormInterface $oForm, string $sQuery): void
|
||||
{
|
||||
$aData = $oForm->getParent()->getData();
|
||||
\IssueLog::Info('Form Data: '.var_export($aData, true));
|
||||
|
||||
//$aFormOptions['inherit_data'] = true;
|
||||
$aFormOptions['choices'] = $this->GetGroupByOptions($sQuery);
|
||||
$aFormOptions['multiple'] = false;
|
||||
|
||||
// create the field, this is similar the $builder->add()
|
||||
// field name, field type, field options
|
||||
$oForm->add('selected', SymfonyChoiceType::class, $aFormOptions);
|
||||
}
|
||||
|
||||
protected $oModelReflection;
|
||||
|
||||
protected function GetGroupByOptions($sOql)
|
||||
{
|
||||
$this->oModelReflection = new \ModelReflectionRuntime();
|
||||
|
||||
$aGroupBy = array();
|
||||
try
|
||||
{
|
||||
$oQuery = $this->oModelReflection->GetQuery($sOql);
|
||||
$sClass = $oQuery->GetClass();
|
||||
foreach($this->oModelReflection->ListAttributes($sClass) as $sAttCode => $sAttType)
|
||||
{
|
||||
// For external fields, find the real type of the target
|
||||
$sExtFieldAttCode = $sAttCode;
|
||||
$sTargetClass = $sClass;
|
||||
while (is_a($sAttType, 'AttributeExternalField', true))
|
||||
{
|
||||
$sExtKeyAttCode = $this->oModelReflection->GetAttributeProperty($sTargetClass, $sExtFieldAttCode, 'extkey_attcode');
|
||||
$sTargetAttCode = $this->oModelReflection->GetAttributeProperty($sTargetClass, $sExtFieldAttCode, 'target_attcode');
|
||||
$sTargetClass = $this->oModelReflection->GetAttributeProperty($sTargetClass, $sExtKeyAttCode, 'targetclass');
|
||||
$aTargetAttCodes = $this->oModelReflection->ListAttributes($sTargetClass);
|
||||
$sAttType = $aTargetAttCodes[$sTargetAttCode];
|
||||
$sExtFieldAttCode = $sTargetAttCode;
|
||||
}
|
||||
|
||||
$aForbidenAttType = [
|
||||
'AttributeLinkedSet',
|
||||
'AttributeFriendlyName',
|
||||
|
||||
'iAttributeNoGroupBy', //we cannot only use iAttributeNoGroupBy since this method is also used by the designer who do not have access to the classes' PHP reflection API. So the known classes has to be listed altogether
|
||||
'AttributeOneWayPassword',
|
||||
'AttributeEncryptedString',
|
||||
'AttributePassword',
|
||||
];
|
||||
foreach ($aForbidenAttType as $sForbidenAttType) {
|
||||
if (is_a($sAttType, $sForbidenAttType, true))
|
||||
{
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode);
|
||||
if (!in_array($sLabel, $aGroupBy))
|
||||
{
|
||||
$aGroupBy[$sAttCode] = $sLabel;
|
||||
|
||||
if (is_a($sAttType, 'AttributeDateTime', true))
|
||||
{
|
||||
$aGroupBy[$sAttCode.':hour'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-Hour', $sLabel);
|
||||
$aGroupBy[$sAttCode.':month'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-Month', $sLabel);
|
||||
$aGroupBy[$sAttCode.':day_of_week'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-DayOfWeek', $sLabel);
|
||||
$aGroupBy[$sAttCode.':day_of_month'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-DayOfMonth', $sLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
asort($aGroupBy);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Fallback in case of OQL problem
|
||||
}
|
||||
return array_flip($aGroupBy);
|
||||
}
|
||||
}
|
||||
30
sources/FormType/Orm/QueryType.php
Normal file
30
sources/FormType/Orm/QueryType.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\FormType\Orm;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType as SymfonyTextareaType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class QueryType extends AbstractType
|
||||
{
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return SymfonyTextareaType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
$resolver->setDefault('attr', ['class' => 'ibo-is-code ibo-query-oql']);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'itop_query';
|
||||
}
|
||||
}
|
||||
62
sources/FormType/Orm/ValuesFromAttcodeType.php
Normal file
62
sources/FormType/Orm/ValuesFromAttcodeType.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\FormType\Orm;
|
||||
|
||||
use Combodo\iTop\FormType\Base\HiddenType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType as SymfonyChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ValuesFromAttcodeType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('hidden', HiddenType::class, ['mapped' => false]);
|
||||
$sAttCodeType = $options['attcode_source'];
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($sAttCodeType): void {
|
||||
$oForm = $event->getForm();
|
||||
$sAttCode = $oForm->getParent()->get($sAttCodeType)->get('selected')->getData();
|
||||
$this->BuildSubField($oForm, $sAttCode);
|
||||
});
|
||||
|
||||
$builder->get('hidden')->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($sAttCodeType): void {
|
||||
$oForm = $event->getForm()->getParent();
|
||||
$sAttCode = $oForm->getParent()->get($sAttCodeType)->get('selected')->getData();
|
||||
$this->BuildSubField($oForm, $sAttCode);
|
||||
});
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
$resolver->setRequired('attcode_source');
|
||||
$resolver->setAllowedTypes('attcode_source', 'string');
|
||||
}
|
||||
|
||||
public function BuildSubField(FormInterface $oForm, string $sAttCode): void
|
||||
{
|
||||
$aData = $oForm->getParent()->getData();
|
||||
\IssueLog::Info('Form Data: '.var_export($aData, true));
|
||||
|
||||
$sQuery = $aData['query'];
|
||||
$sClass = \DBSearch::FromOQL($sQuery)->GetClass();
|
||||
$oAttDef = \MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
|
||||
//$aFormOptions['inherit_data'] = true;
|
||||
$aFormOptions['choices'] = array_flip($oAttDef->GetAllowedValues());
|
||||
$aFormOptions['multiple'] = true;
|
||||
|
||||
// create the field, this is similar the $builder->add()
|
||||
// field name, field type, field options
|
||||
$oForm->add('selected', SymfonyChoiceType::class, $aFormOptions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\FormType\Base;
|
||||
|
||||
use Combodo\iTop\FormType\Orm\AttCodeGroupByType;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\Forms;
|
||||
|
||||
class TextTypeTest extends iTopTestCase
|
||||
{
|
||||
public function GetFormBuilder(string $type = FormType::class, mixed $data = null, array $options = []): FormBuilderInterface
|
||||
{
|
||||
$oFormFactory = Forms::createFormFactoryBuilder()
|
||||
->addExtension(new HttpFoundationExtension())
|
||||
->getFormFactory();
|
||||
return $oFormFactory->createBuilder($type, $data,$options);
|
||||
}
|
||||
|
||||
public function GetForm(string $type = FormType::class, mixed $data = null, array $options = []): FormInterface
|
||||
{
|
||||
return $this->GetFormBuilder($type, $data,$options)->getForm();
|
||||
}
|
||||
|
||||
public function testTextType()
|
||||
{
|
||||
$oFormView = $this->GetForm(AttCodeGroupByType::class)->createView();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user