diff --git a/core/datamodel.core.xml b/core/datamodel.core.xml index e5a43f20b..189dbb0de 100644 --- a/core/datamodel.core.xml +++ b/core/datamodel.core.xml @@ -1285,6 +1285,17 @@ + + Dashlet + + + + + bizmodel + + + + diff --git a/core/modelreflection.class.inc.php b/core/modelreflection.class.inc.php index 04966dbb7..2103e0081 100644 --- a/core/modelreflection.class.inc.php +++ b/core/modelreflection.class.inc.php @@ -55,6 +55,11 @@ abstract class ModelReflection abstract public function GetFiltersList($sClass); abstract public function IsValidFilterCode($sClass, $sFilterCode); + /** + * @since 3.3.0 + */ + abstract public function IsAbstract($sClass): bool; + /** * @param string $sOQL * @@ -230,6 +235,11 @@ class ModelReflectionRuntime extends ModelReflection return MetaModel::IsValidFilterCode($sClass, $sFilterCode); } + public function IsAbstract($sClass): bool + { + return MetaModel::IsAbstract($sClass); + } + public function GetQuery($sOQL) { return new QueryReflectionRuntime($sOQL, $this); diff --git a/sources/PropertyTree/ValueType/ValueTypeClass.php b/sources/PropertyTree/ValueType/ValueTypeClass.php index ad749bb58..ca0a1e00d 100644 --- a/sources/PropertyTree/ValueType/ValueTypeClass.php +++ b/sources/PropertyTree/ValueType/ValueTypeClass.php @@ -7,13 +7,44 @@ namespace Combodo\iTop\PropertyTree\ValueType; +use Combodo\iTop\DesignElement; +use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock; use Combodo\iTop\Forms\Block\Base\TextFormBlock; use Combodo\iTop\PropertyTree\ValueType\AbstractValueType; +use Combodo\iTop\Service\DependencyInjection\DIService; +use utils; class ValueTypeClass extends AbstractValueType { + protected array $aCategories = []; + public function GetFormBlockClass(): string { - return TextFormBlock::class; + return ChoiceFormBlock::class; } + + public function InitFromDomNode(DesignElement $oDomNode): void + { + parent::InitFromDomNode($oDomNode); + + $sCategories = $oDomNode->GetChildText('categories-csv'); + /** @var \ModelReflection $oModelReflection */ + $oModelReflection = DIService::GetInstance()->GetService('ModelReflection'); + + $sChoices = "[\n"; + foreach ($oModelReflection->GetClasses($sCategories, true) as $sClass) { + if ($oModelReflection->IsAbstract($sClass)) { + continue; + } + $sValue = utils::QuoteForPHP($sClass); + $sChoices .= << $sValue, + +PHP; + } + $sChoices .= "\t\t\t]"; + + $this->aFormBlockOptionsForPHP['choices'] = $sChoices; + } + } diff --git a/tests/php-unit-tests/unitary-tests/sources/Forms/Compiler/FormsCompilerTest.php b/tests/php-unit-tests/unitary-tests/sources/Forms/Compiler/FormsCompilerTest.php index ea1863181..8b1ef6f41 100644 --- a/tests/php-unit-tests/unitary-tests/sources/Forms/Compiler/FormsCompilerTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/Forms/Compiler/FormsCompilerTest.php @@ -6,6 +6,7 @@ */ use Combodo\iTop\Forms\Compiler\FormsCompiler; +use Combodo\iTop\Service\DependencyInjection\DIService; use Combodo\iTop\Test\UnitTest\ItopDataTestCase; class FormsCompilerTest extends ItopDataTestCase @@ -23,6 +24,8 @@ class FormsCompilerTest extends ItopDataTestCase */ public function testCompileFormFromXML(string $sXMLContent, string $sExpectedPHP) { + DIService::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime()); + $sProducedPHP = FormsCompiler::GetInstance()->CompileFormFromXML($sXMLContent); $this->AssertPHPCodeIsValid($sProducedPHP); @@ -46,6 +49,7 @@ class FormsCompilerTest extends ItopDataTestCase + test @@ -60,8 +64,10 @@ class FormFor__basic_test extends Combodo\iTop\Forms\Block\Base\FormBlock 'label' => 'UI:BasicTest:Prop-Title', ]); - \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\TextFormBlock', [ + \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\ChoiceFormBlock', [ 'label' => 'UI:BasicTest:Prop-Class', + 'choices' => [ + ], ]); } } @@ -128,6 +134,7 @@ PHP, + test @@ -198,8 +205,10 @@ class FormFor__AllValueTypesTest extends Combodo\iTop\Forms\Block\Base\FormBlock ], ]); - \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\TextFormBlock', [ + \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\ChoiceFormBlock', [ 'label' => 'UI:Class', + 'choices' => [ + ], ]); \$this->Add('class_attribute_property', 'Combodo\iTop\Forms\Block\DataModel\AttributeChoiceFormBlock', [ @@ -365,6 +374,7 @@ PHP, + test @@ -381,8 +391,10 @@ class FormFor__input_binding_test extends Combodo\iTop\Forms\Block\Base\FormBloc { protected function BuildForm(): void { - \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\TextFormBlock', [ + \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\ChoiceFormBlock', [ 'label' => 'UI:Class', + 'choices' => [ + ], ]); \$this->Add('class_attribute_property', 'Combodo\iTop\Forms\Block\DataModel\AttributeChoiceFormBlock', [ @@ -402,12 +414,13 @@ PHP, + test - {{IF(class_property.text = '', 'Person', class_property.text)}} + {{IF(class_property.value = '', 'Person', class_property.value)}} @@ -418,14 +431,16 @@ class FormFor__input_binding_expression extends Combodo\iTop\Forms\Block\Base\Fo { protected function BuildForm(): void { - \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\TextFormBlock', [ + \$this->Add('class_property', 'Combodo\iTop\Forms\Block\Base\ChoiceFormBlock', [ 'label' => 'UI:Class', + 'choices' => [ + ], ]); \$this->Add('class_attribute_property_class_expression', 'Combodo\iTop\Forms\Block\Expression\StringExpressionFormBlock', [ - 'expression' => 'IF(class_property.text = \'\', \'Person\', class_property.text)', + 'expression' => 'IF(class_property.value = \'\', \'Person\', class_property.value)', ]) - ->AddInputDependsOn('class_property.text', 'class_property', 'text'); + ->AddInputDependsOn('class_property.value', 'class_property', 'value'); \$this->Add('class_attribute_property', 'Combodo\iTop\Forms\Block\DataModel\AttributeChoiceFormBlock', [ 'label' => 'UI:ClassAttribute', @@ -527,6 +542,65 @@ class FormFor__ComplexRelevanceCondition extends Combodo\iTop\Forms\Block\Base\F ->InputDependsOn('visible', 'dependant_property_visible_expression', 'result'); } } +PHP, + ], + 'Class category for value type class' => [ + 'sXMLContent' => << + + + + + + addon/authentication,grant_by_profile,silo + + + + +XML, + 'sExpectedPHP' => <<Add('class_property', 'Combodo\iTop\Forms\Block\Base\ChoiceFormBlock', [ + 'label' => 'UI:Class', + 'choices' => [ + \Dict::S('Class:UserExternal') => 'UserExternal', + \Dict::S('Class:UserLDAP') => 'UserLDAP', + \Dict::S('Class:UserLocal') => 'UserLocal', + \Dict::S('Class:AuditRule') => 'AuditRule', + \Dict::S('Class:AuditCategory') => 'AuditCategory', + \Dict::S('Class:AuditDomain') => 'AuditDomain', + \Dict::S('Class:QueryOQL') => 'QueryOQL', + \Dict::S('Class:ActionEmail') => 'ActionEmail', + \Dict::S('Class:TriggerOnPortalUpdate') => 'TriggerOnPortalUpdate', + \Dict::S('Class:TriggerOnStateEnter') => 'TriggerOnStateEnter', + \Dict::S('Class:TriggerOnStateLeave') => 'TriggerOnStateLeave', + \Dict::S('Class:TriggerOnObjectCreate') => 'TriggerOnObjectCreate', + \Dict::S('Class:TriggerOnObjectDelete') => 'TriggerOnObjectDelete', + \Dict::S('Class:TriggerOnObjectUpdate') => 'TriggerOnObjectUpdate', + \Dict::S('Class:TriggerOnObjectMention') => 'TriggerOnObjectMention', + \Dict::S('Class:TriggerOnAttributeBlobDownload') => 'TriggerOnAttributeBlobDownload', + \Dict::S('Class:TriggerOnThresholdReached') => 'TriggerOnThresholdReached', + \Dict::S('Class:SynchroDataSource') => 'SynchroDataSource', + \Dict::S('Class:SynchroAttribute') => 'SynchroAttribute', + \Dict::S('Class:SynchroAttExtKey') => 'SynchroAttExtKey', + \Dict::S('Class:SynchroAttLinkSet') => 'SynchroAttLinkSet', + \Dict::S('Class:SynchroLog') => 'SynchroLog', + \Dict::S('Class:SynchroReplica') => 'SynchroReplica', + \Dict::S('Class:ActionNewsroom') => 'ActionNewsroom', + \Dict::S('Class:TriggerOnAttachmentCreate') => 'TriggerOnAttachmentCreate', + \Dict::S('Class:TriggerOnAttachmentDelete') => 'TriggerOnAttachmentDelete', + \Dict::S('Class:TriggerOnAttachmentDownload') => 'TriggerOnAttachmentDownload', + \Dict::S('Class:OAuthClientAzure') => 'OAuthClientAzure', + \Dict::S('Class:OAuthClientGoogle') => 'OAuthClientGoogle', + \Dict::S('Class:URP_Profiles') => 'URP_Profiles', + \Dict::S('Class:URP_UserOrg') => 'URP_UserOrg', + ], + ]); + } +} PHP, ], 'test' => [