N°9065 - XML Definition for Dashlet properties

This commit is contained in:
Eric Espie
2026-01-06 15:59:46 +01:00
parent 904cd0b518
commit efb1bd765b
56 changed files with 2433 additions and 1270 deletions

View File

@@ -0,0 +1,231 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Expression\BooleanExpressionFormBlock;
use Combodo\iTop\Forms\Block\Expression\NumberExpressionFormBlock;
use Combodo\iTop\Forms\Block\Expression\StringExpressionFormBlock;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\IO\Format\NumberIOFormat;
use Combodo\iTop\Forms\IO\Format\StringIOFormat;
use Combodo\iTop\Forms\IO\FormInput;
use Combodo\iTop\PropertyType\PropertyTypeException;
use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType;
use Combodo\iTop\PropertyType\ValueType\Branch\ValueTypePropertyTree;
use Exception;
use Expression;
use utils;
/**
* @since 3.3.0
*/
abstract class AbstractValueType
{
protected ?AbstractBranchValueType $oParent;
protected string $sIdWithPath;
/** @var FormInput[] */
protected array $aInputs = [];
protected array $aOutputs = [];
protected array $aInputValues = [];
protected array $aDynamicInputValues = [];
protected array $aFormBlockOptionsForPHP = [];
protected string $sId;
protected ?string $sRelevanceCondition = null;
protected ?string $sLabel;
abstract public function GetFormBlockClass(): string;
/**
* @param \Combodo\iTop\DesignElement $oDomNode
* @param \Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType|null $oParent Parent node (used for trees)
*
* @return void
* @throws \DOMFormatException
*/
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
$this->oParent = $oParent;
// id can already be set for the definition root node
$this->sId = $this->sId ?? $oDomNode->getAttribute('id');
if (is_null($oParent)) {
$this->sIdWithPath = $this->sId;
} else {
$this->sIdWithPath = $oParent->sIdWithPath.'__'.$this->sId;
}
$this->sLabel = $oDomNode->GetChildText('label');
$this->sRelevanceCondition = $oDomNode->GetChildText('relevance-condition');
$sBlockNodeClass = $this->GetFormBlockClass();
$oBlockNode = new $sBlockNodeClass('foo');
foreach ($oBlockNode->GetInputs() as $oInput) {
$sInputName = $oInput->GetName();
$this->aInputs[$sInputName] = $oInput;
$sInputValue = $oDomNode->GetChildText($sInputName);
if (utils::IsNotNullOrEmptyString($sInputValue)) {
$this->aInputValues[$sInputName] = $sInputValue;
}
}
foreach ($oBlockNode->GetOutputs() as $oOutput) {
$this->aOutputs[] = $oOutput->GetName();
}
}
public function GetFormBlockOptions(): array
{
return $this->aFormBlockOptionsForPHP;
}
public function GetInputValues(): array
{
return $this->aInputValues;
}
public function GetInputType(string $sInputName): string
{
return $this->aInputs[$sInputName]->GetDataType();
}
public function GetDynamicInputValues(): array
{
return $this->aDynamicInputValues;
}
public function GetOutputs(): array
{
return $this->aOutputs;
}
public function SetRootId(string $sId): void
{
$this->sId = $sId;
$this->sIdWithPath = $sId;
}
abstract public function IsLeaf(): bool;
abstract public function ToPHPFormBlock(array &$aPHPFragments = []): string;
/**
* @param array $aPHPFragments
*
* @return string
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
*/
protected function GetLocalPHPForValueType(?string $sFormBlockClass = null): string
{
$sFormBlockClass = $sFormBlockClass ?? $this->GetFormBlockClass();
$sInputs = '';
$sPrerequisiteExpressions = '';
if (!is_null($this->sRelevanceCondition)) {
$this->GenerateInputs('visible', $this->sRelevanceCondition, $sPrerequisiteExpressions, $sInputs);
}
foreach ($this->GetInputValues() as $sInputName => $sValue) {
$this->GenerateInputs($sInputName, $sValue, $sPrerequisiteExpressions, $sInputs);
}
foreach ($this->GetDynamicInputValues() as $sInputName => $sValue) {
$this->GenerateInputs($sInputName, $sValue, $sPrerequisiteExpressions, $sInputs, true);
}
$sLabel = utils::QuoteForPHP($this->sLabel ?? '');
$aOptions = [
'label' => $sLabel,
];
$aOptions += $this->GetFormBlockOptions();
$sOptions = '';
foreach ($aOptions as $sOption => $sValue) {
$sOptions .= "\t\t\t".utils::QuoteForPHP($sOption)." => $sValue,\n";
}
return <<<PHP
\t\t{$sPrerequisiteExpressions}\$this->Add('$this->sId', '$sFormBlockClass', [
$sOptions\t\t]){$sInputs};\n
PHP;
}
private function GenerateInputs(string $sInputName, string $sValue, string &$sPrerequisiteExpressions, string &$sInputs, bool $bIsDynamic = false): void
{
if (preg_match('/^{{(?<node>\w+)\.(?<output>\w+)}}$/', $sValue, $aMatches) === 1) {
$sVerb = $bIsDynamic ? 'AddInputDependsOn' : 'InputDependsOn';
$sInputs .= "\n ->$sVerb('$sInputName', '{$aMatches['node']}', '{$aMatches['output']}')";
} elseif (preg_match('/^{{(?<expression>.*)}}$/', $sValue, $aMatches) === 1) {
$sExpression = $aMatches['expression'];
$sBindings = '';
try {
$oExpression = Expression::FromOQL($sExpression);
} catch (Exception $e) {
throw new PropertyTypeException("Node: {$this->sId}, invalid syntax in condition: ".$e->getMessage());
}
$aFieldsToResolve = array_unique($oExpression->ListRequiredFields());
foreach ($aFieldsToResolve as $sFieldToResolve) {
if (preg_match('/(?<node>\w+)\.(?<output>\w+)/', $sFieldToResolve, $aMatches) === 1) {
$sNode = $aMatches['node'];
$oSibling = $this->GetSibling($sNode);
if (is_null($oSibling)) {
// Search in collection
if (is_a($this->oParent ?? null, 'Combodo-ValueType-Collection')) {
$bSourceNodeFound = false;
$aSiblings = $this->oParent->GetChildren();
foreach ($aSiblings as $oSibling) {
if ($oSibling->sId == $sNode) {
$bSourceNodeFound = true;
break;
}
}
if (!$bSourceNodeFound) {
throw new PropertyTypeException("node: {$this->sId}, source: $sNode not found in collection: {$this->oParent->sId}");
}
} else {
throw new PropertyTypeException("Node: {$this->sId}, invalid source in condition: $sNode");
}
}
$sOutput = $aMatches['output'];
if (!in_array($sOutput, $oSibling->GetOutputs())) {
throw new PropertyTypeException("Node: {$this->sId}, invalid output in condition: $sFieldToResolve");
}
$sBindings .= "\n\t\t\t->AddInputDependsOn('{$sNode}.$sOutput', '$sNode', '$sOutput')";
} else {
throw new PropertyTypeException("Node: {$this->sId}, missing output or source in condition: $sFieldToResolve");
}
}
$sExpressionClass = match ($this->GetInputType($sInputName)) {
BooleanIOFormat::class => BooleanExpressionFormBlock::class,
StringIOFormat::class, ClassIOFormat::class => StringExpressionFormBlock::class,
NumberIOFormat::class => NumberExpressionFormBlock::class,
default => throw new PropertyTypeException("Node: {$this->sId}, unsupported expression for input type: $sInputName"),
};
$sExpression = utils::QuoteForPHP($sExpression);
$sPrerequisiteExpressions = <<<PHP
\$this->Add('{$this->sId}_{$sInputName}_expression', '$sExpressionClass', [
'expression' => $sExpression,
]){$sBindings};\n\n\t\t
PHP;
$sVerb = $bIsDynamic ? 'AddInputDependsOn' : 'InputDependsOn';
$sInputs .= "\n\t\t\t->$sVerb('$sInputName', '{$this->sId}_{$sInputName}_expression', 'result')";
} else {
$sInputs .= "\n\t\t\t->SetInputValue('$sInputName', ".utils::QuoteForPHP($sValue).')';
}
}
protected function GetSibling(string $sId): ?AbstractValueType
{
if (is_null($this->oParent)) {
return null;
}
return $this->oParent->GetChild($sId);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Branch;
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
/**
* @since 3.3.0
*/
abstract class AbstractBranchValueType extends AbstractValueType
{
/** @var AbstractValueType[] */
protected array $aChildren = [];
/**
* @return bool
*/
public function IsLeaf(): bool
{
return false;
}
/**
* @return bool
*/
public function IsRoot(): bool
{
return is_null($this->oParent);
}
/**
* @param \Combodo\iTop\PropertyType\ValueType\AbstractValueType $oChild
*
* @return void
*/
public function AddChild(AbstractValueType $oChild): void
{
$this->aChildren[$oChild->sId] = $oChild;
}
/**
* @param string $sId
*
* @return \Combodo\iTop\PropertyType\ValueType\AbstractValueType|null
*/
public function GetChild(string $sId): ?AbstractValueType
{
return $this->aChildren[$sId] ?? null;
}
/**
* @return AbstractValueType[]
*/
public function GetChildren(): array
{
return $this->aChildren;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Branch;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\CollectionBlock;
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory;
use utils;
/**
* @since 3.3.0
*/
class ValueTypeCollection extends ValueTypePropertyTree
{
/**
* @param \Combodo\iTop\DesignElement $oDomNode
* @param \Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType|null $oParent
*
* @return void
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
* @throws \DOMFormatException
*/
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
parent::InitFromDomNode($oDomNode, $oParent);
$this->aFormBlockOptionsForPHP['button_label'] = utils::QuoteForPHP('UI:AddSubTree');
$this->sSubTreeClass = 'SubFormFor__'.$this->sIdWithPath;
$this->aFormBlockOptionsForPHP['block_entry_type'] = utils::QuoteForPHP($this->sSubTreeClass);
// read child properties
foreach ($oDomNode->GetUniqueElement('prototype')->childNodes as $oNode) {
if ($oNode instanceof DesignElement) {
$this->AddChild(ValueTypeFactory::GetInstance()->CreateValueTypeFromDomNode($oNode, $this));
}
}
}
public function GetFormBlockClass(): string
{
return CollectionBlock::class;
}
/**
* @param array $aPHPFragments
*
* @return string
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
*/
public function ToPHPFormBlock(array &$aPHPFragments = []): string
{
$sSubClassPHP = <<<PHP
class $this->sSubTreeClass extends Combodo\iTop\Forms\Block\Base\FormBlock
{
protected function BuildForm(): void
{
PHP;
foreach ($this->GetChildren() as $oProperty) {
$sSubClassPHP .= "\n".$oProperty->ToPHPFormBlock($aPHPFragments);
}
$sSubClassPHP .= <<<PHP
}
}
PHP;
$aPHPFragments[] = $sSubClassPHP;
return $this->GetLocalPHPForValueType();
}
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Branch;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\FormBlock;
use Combodo\iTop\Forms\Block\Expression\BooleanExpressionFormBlock;
use Combodo\iTop\Forms\Block\Expression\NumberExpressionFormBlock;
use Combodo\iTop\Forms\Block\Expression\StringExpressionFormBlock;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\IO\Format\NumberIOFormat;
use Combodo\iTop\Forms\IO\Format\StringIOFormat;
use Combodo\iTop\PropertyType\PropertyTypeException;
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory;
use Exception;
use Expression;
use utils;
/**
* @since 3.3.0
*/
class ValueTypePropertyTree extends AbstractBranchValueType
{
protected string $sSubTreeClass;
public function GetFormBlockClass(): string
{
return FormBlock::class;
}
/**
* @param \Combodo\iTop\DesignElement $oDomNode
* @param \Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType|null $oParent
*
* @return void
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
* @throws \DOMFormatException
*/
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
parent::InitFromDomNode($oDomNode, $oParent);
// read child properties
$oNodes = $oDomNode->GetOptionalElement('nodes');
if (!is_null($oNodes)) {
foreach ($oNodes->childNodes as $oNode) {
if ($oNode instanceof DesignElement) {
$this->AddChild(ValueTypeFactory::GetInstance()->CreateValueTypeFromDomNode($oNode, $this));
}
}
}
}
public function ToPHPFormBlock(array &$aPHPFragments = []): string
{
if ($this->IsRoot()) {
$this->sSubTreeClass = 'FormFor__'.$this->sId;
} else {
$this->sSubTreeClass = 'SubFormFor__'.$this->sIdWithPath;
}
$sLocalPHP = <<<PHP
class $this->sSubTreeClass extends Combodo\iTop\Forms\Block\Base\FormBlock
{
protected function BuildForm(): void
{
PHP;
foreach ($this->aChildren as $oChild) {
$sLocalPHP .= "\n".$oChild->ToPHPFormBlock($aPHPFragments);
}
$sLocalPHP .= <<<PHP
}
}
PHP;
$aPHPFragments[] = $sLocalPHP;
return $this->GetLocalPHPForValueType($this->sSubTreeClass);
}
}

View File

@@ -0,0 +1,43 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\Expression\BooleanExpressionFormBlock;
use Combodo\iTop\Forms\Block\Expression\NumberExpressionFormBlock;
use Combodo\iTop\Forms\Block\Expression\StringExpressionFormBlock;
use Combodo\iTop\Forms\IO\Format\BooleanIOFormat;
use Combodo\iTop\Forms\IO\Format\ClassIOFormat;
use Combodo\iTop\Forms\IO\Format\NumberIOFormat;
use Combodo\iTop\Forms\IO\Format\StringIOFormat;
use Combodo\iTop\PropertyType\PropertyTypeException;
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
use Exception;
use Expression;
use utils;
/**
* @since 3.3.0
*/
abstract class AbstractLeafValueType extends AbstractValueType
{
public function IsLeaf(): bool
{
return true;
}
/**
* @param array $aPHPFragments
*
* @return string
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
*/
public function ToPHPFormBlock(array &$aPHPFragments = []): string
{
return $this->GetLocalPHPForValueType();
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\DataModel\Dashlet\AggregateFunctionFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeAggregateFunction extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return AggregateFunctionFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\Base\CheckboxFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeBoolean extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return CheckboxFormBlock::class;
}
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType;
use Combodo\iTop\PropertyType\ValueType\Branch\ValueTypePropertyTree;
use utils;
/**
* @since 3.3.0
*/
class ValueTypeChoice extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return ChoiceFormBlock::class;
}
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
parent::InitFromDomNode($oDomNode, $oParent);
$sChoices = "[\n";
foreach ($oDomNode->GetNodes('values/value') as $oValueNode) {
/** @var DesignElement $oValueNode */
$sValue = utils::QuoteForPHP($oValueNode->GetAttribute('id'));
$sLabel = utils::QuoteForPHP($oValueNode->GetChildText('label'));
$sChoices .= <<<PHP
\Dict::S($sLabel) => $sValue,
PHP;
}
$sChoices .= "\t\t\t]";
$this->aFormBlockOptionsForPHP['choices'] = $sChoices;
}
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\ChoiceFromInputsBlock;
use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType;
use Combodo\iTop\PropertyType\ValueType\Branch\ValueTypePropertyTree;
use utils;
/**
* @since 3.3.0
*/
class ValueTypeChoiceFromInput extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return ChoiceFromInputsBlock::class;
}
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
parent::InitFromDomNode($oDomNode, $oParent);
foreach ($oDomNode->GetNodes('values/value') as $oValueNode) {
/** @var DesignElement $oValueNode */
$sValue = $oValueNode->GetAttribute('id');
$sLabel = $oValueNode->GetChildText('label');
$this->aDynamicInputValues[$sValue] = $sLabel;
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType;
use Combodo\iTop\PropertyType\ValueType\Branch\ValueTypePropertyTree;
use Combodo\iTop\Service\DependencyInjection\ServiceLocator;
use utils;
/**
* @since 3.3.0
*/
class ValueTypeClass extends AbstractLeafValueType
{
protected array $aCategories = [];
public function GetFormBlockClass(): string
{
return ChoiceFormBlock::class;
}
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
parent::InitFromDomNode($oDomNode, $oParent);
$sCategories = $oDomNode->GetChildText('categories-csv');
/** @var \ModelReflection $oModelReflection */
$oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection');
$sChoices = "[\n";
$aClasses = $oModelReflection->GetClasses($sCategories, true);
sort($aClasses);
foreach ($aClasses as $sClass) {
if ($oModelReflection->IsAbstract($sClass)) {
continue;
}
$sValue = utils::QuoteForPHP($sClass);
$sChoices .= <<<PHP
\Dict::S('Class:$sClass') => $sValue,
PHP;
}
$sChoices .= "\t\t\t]";
$this->aFormBlockOptionsForPHP['choices'] = $sChoices;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\DataModel\AttributeChoiceFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeClassAttribute extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return AttributeChoiceFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\DataModel\Dashlet\ClassAttributeGroupByFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeClassAttributeGroupBy extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return ClassAttributeGroupByFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\DataModel\AttributeValueChoiceFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeClassAttributeValue extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return AttributeValueChoiceFormBlock::class;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
use Combodo\iTop\Forms\Block\Base\FormBlock;
use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType;
use Combodo\iTop\PropertyType\ValueType\Leaf\AbstractLeafValueType;
use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory;
class ValueTypeCollectionOfValues extends AbstractLeafValueType
{
private string $sFormBlockClass;
public function GetFormBlockClass(): string
{
return $this->sFormBlockClass;
}
public function InitFromDomNode(DesignElement $oDomNode, ?AbstractBranchValueType $oParent = null): void
{
$oNode = $oDomNode->GetUniqueElement('value-type');
$oRealValueType = ValueTypeFactory::GetInstance()->CreateValueTypeFromDomNode($oNode, $oParent);
$this->sFormBlockClass = $oRealValueType->getFormBlockClass();
if (is_a($this->sFormBlockClass, ChoiceFormBlock::class, true)) {
$this->aFormBlockOptionsForPHP['multiple'] = 'true';
}
parent::InitFromDomNode($oDomNode, $oParent);
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\Base\ChoiceFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeIcon extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return ChoiceFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\Base\IntegerFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeInteger extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return IntegerFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\DataModel\LabelFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeLabel extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return LabelFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\DataModel\OqlFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeOQL extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return OqlFormBlock::class;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
/**
* @since 3.3.0
*/
class ValueTypeProfileName extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return '';
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\Base\TextFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeString extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return TextFormBlock::class;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType\Leaf;
use Combodo\iTop\Forms\Block\Base\TextAreaFormBlock;
/**
* @since 3.3.0
*/
class ValueTypeText extends AbstractLeafValueType
{
public function GetFormBlockClass(): string
{
return TextAreaFormBlock::class;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/*
* @copyright Copyright (C) 2010-2025 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\PropertyType\ValueType;
use Combodo\iTop\DesignElement;
use Combodo\iTop\PropertyType\PropertyTypeException;
use utils;
/**
* Build Value type from XML DOM
* @since 3.3.0
*/
class ValueTypeFactory
{
private static ValueTypeFactory $oInstance;
protected function __construct()
{
}
final public static function GetInstance(): ValueTypeFactory
{
if (!isset(static::$oInstance)) {
static::$oInstance = new ValueTypeFactory();
}
return static::$oInstance;
}
/**
* @param \Combodo\iTop\DesignElement $oDomNode
* @param \Combodo\iTop\PropertyType\ValueType\AbstractValueType|null $oParent
*
* @return \Combodo\iTop\PropertyType\ValueType\AbstractValueType
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
* @throws \DOMFormatException
*/
public function CreateValueTypeFromDomNode(DesignElement $oDomNode, ?AbstractValueType $oParent = null): AbstractValueType
{
$sNodeType = $oDomNode->getAttribute('xsi:type');
if (utils::IsNullOrEmptyString($sNodeType)) {
$sId = $oDomNode->getAttribute('id');
throw new PropertyTypeException("Node: $sId, missing value-type in node specification");
}
if (is_a($sNodeType, AbstractValueType::class, true)) {
$oNode = new $sNodeType();
$oNode->InitFromDomNode($oDomNode, $oParent);
return $oNode;
}
$sId = $oDomNode->getAttribute('id');
throw new PropertyTypeException("Node: $sId, unknown type node class: ".json_encode($sNodeType));
}
}