mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 18:48:51 +02:00
N°9065 - XML Definition for Dashlet properties
This commit is contained in:
133
sources/PropertyType/Compiler/PropertyTypeCompiler.php
Normal file
133
sources/PropertyType/Compiler/PropertyTypeCompiler.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType\Compiler;
|
||||
|
||||
use Combodo\iTop\DesignDocument;
|
||||
use Combodo\iTop\PropertyType\PropertyType;
|
||||
use Combodo\iTop\PropertyType\PropertyTypeFactory;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* XML to PHP Forms compiler.
|
||||
*
|
||||
* @package Combodo\iTop\PropertyType\Compiler
|
||||
* @since 3.3.0
|
||||
*/
|
||||
class PropertyTypeCompiler
|
||||
{
|
||||
private static PropertyTypeCompiler $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): PropertyTypeCompiler
|
||||
{
|
||||
if (!isset(static::$oInstance)) {
|
||||
static::$oInstance = new PropertyTypeCompiler();
|
||||
}
|
||||
|
||||
return static::$oInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sXMLContent
|
||||
*
|
||||
* @return \Combodo\iTop\PropertyType\PropertyType
|
||||
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
protected function CompilePropertyTypeFromXML(string $sXMLContent): PropertyType
|
||||
{
|
||||
$oDoc = new DesignDocument();
|
||||
libxml_clear_errors();
|
||||
$oDoc->loadXML($sXMLContent);
|
||||
$aErrors = libxml_get_errors();
|
||||
if (count($aErrors) > 0) {
|
||||
throw new PropertyTypeCompilerException('Property types definition not correctly formatted!');
|
||||
}
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oRoot */
|
||||
$oRoot = $oDoc->firstChild;
|
||||
|
||||
return PropertyTypeFactory::GetInstance()->CreatePropertyTypeFromDom($oRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sId
|
||||
* @param string $sType
|
||||
*
|
||||
* @return string
|
||||
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
|
||||
*/
|
||||
protected function GetXMLContent(string $sId, string $sType): string
|
||||
{
|
||||
$sPath = utils::GetAbsoluteModulePath('core')."property_types/$sType/$sId.xml";
|
||||
if (!file_exists($sPath)) {
|
||||
throw new PropertyTypeCompilerException("Properties definition $sType/$sId not present");
|
||||
}
|
||||
|
||||
return file_get_contents($sPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile XML property tree into PHP to create the configuration form
|
||||
*
|
||||
* @param string $sXMLContent property tree structure in xml
|
||||
*
|
||||
* @return string Generated PHP
|
||||
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function CompileFormFromXML(string $sXMLContent): string
|
||||
{
|
||||
$oPropertyType = $this->CompilePropertyTypeFromXML($sXMLContent);
|
||||
|
||||
return $oPropertyType->ToPHPFormBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sXMLContent
|
||||
*
|
||||
* @return string
|
||||
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function CompileEntityFromXML(string $sXMLContent): string
|
||||
{
|
||||
$oPropertyType = $this->CompilePropertyTypeFromXML($sXMLContent);
|
||||
|
||||
return $oPropertyType->ToPHPEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sId
|
||||
* @param string $sType
|
||||
*
|
||||
* @return string Generated PHP
|
||||
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function CompileForm(string $sId, string $sType): string
|
||||
{
|
||||
$sXMLContent = $this->GetXMLContent($sId, $sType);
|
||||
|
||||
return $this->CompileFormFromXML($sXMLContent);
|
||||
}
|
||||
|
||||
public function CompileEntity(string $sId, string $sType): string
|
||||
{
|
||||
$sXMLContent = $this->GetXMLContent($sId, $sType);
|
||||
|
||||
return $this->CompileEntityFromXML($sXMLContent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType\Compiler;
|
||||
|
||||
use Combodo\iTop\PropertyType\PropertyTypeException;
|
||||
|
||||
class PropertyTypeCompilerException extends PropertyTypeException
|
||||
{
|
||||
}
|
||||
79
sources/PropertyType/PropertyType.php
Normal file
79
sources/PropertyType/PropertyType.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
|
||||
|
||||
/**
|
||||
* A property type is a definition of properties (organized in tree)
|
||||
* used for dashlet for example.
|
||||
* @since 3.3.0
|
||||
*/
|
||||
class PropertyType
|
||||
{
|
||||
private string $sParentType = '';
|
||||
private string $sId;
|
||||
private AbstractValueType $oValueType;
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\DesignElement $oDomNode
|
||||
*
|
||||
* @return void
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function InitFromDomNode(DesignElement $oDomNode): void
|
||||
{
|
||||
$this->sId = $oDomNode->getAttribute('id');
|
||||
$this->sParentType = $oDomNode->GetChildText('extends', '');
|
||||
|
||||
$oDefinitionNode = $oDomNode->GetUniqueElement('definition');
|
||||
$sDefinitionNodeType = $oDefinitionNode->getAttribute('xsi:type');
|
||||
|
||||
if (!is_a($sDefinitionNodeType, AbstractValueType::class, true)) {
|
||||
throw new PropertyTypeException('Unsupported type '.json_encode($sDefinitionNodeType).' in ');
|
||||
}
|
||||
|
||||
$this->oValueType = new $sDefinitionNodeType();
|
||||
$this->oValueType->SetRootId($this->sId);
|
||||
$this->oValueType->InitFromDomNode($oDefinitionNode);
|
||||
}
|
||||
|
||||
public function ToPHPFormBlock(): string
|
||||
{
|
||||
$aPHPFragments = [];
|
||||
|
||||
if ($this->oValueType->IsLeaf()) {
|
||||
|
||||
$sLocalPHP = <<<PHP
|
||||
class FormFor__$this->sId extends Combodo\iTop\Forms\Block\Base\FormBlock
|
||||
{
|
||||
protected function BuildForm(): void
|
||||
{
|
||||
PHP;
|
||||
|
||||
$sLocalPHP .= "\n".$this->oValueType->ToPHPFormBlock($aPHPFragments);
|
||||
|
||||
$sLocalPHP .= <<<PHP
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
$aPHPFragments[] = $sLocalPHP;
|
||||
} else {
|
||||
$this->oValueType->ToPHPFormBlock($aPHPFragments);
|
||||
}
|
||||
|
||||
return implode("\n\n", $aPHPFragments);
|
||||
}
|
||||
|
||||
public function GetParentType(): string
|
||||
{
|
||||
return $this->sParentType;
|
||||
}
|
||||
}
|
||||
85
sources/PropertyType/PropertyTypeDesign.php
Normal file
85
sources/PropertyType/PropertyTypeDesign.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType;
|
||||
|
||||
use Combodo\iTop\DesignDocument;
|
||||
use Exception;
|
||||
use ReturnTypeWillChange;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* Load and save XML definitions of property types
|
||||
* @since 3.3.0
|
||||
*/
|
||||
class PropertyTypeDesign extends DesignDocument
|
||||
{
|
||||
public function __construct(string $sDesignSourceId = null, string $sType = 'Default')
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
if (!is_null($sDesignSourceId)) {
|
||||
$this->LoadFromCompiledDesigns($sDesignSourceId, $sType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data where the compiler has left them...
|
||||
* @param $sDesignSourceId String Identifier of the section module_design (generally a module name)
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function LoadFromCompiledDesigns(string $sDesignSourceId, string $sType)
|
||||
{
|
||||
$sDesignDir = APPROOT.'env-'.utils::GetCurrentEnvironment()."/core/property_trees/$sType/";
|
||||
$sFile = $sDesignDir.$sDesignSourceId.'.xml';
|
||||
if (!file_exists($sFile)) {
|
||||
$aFiles = glob($sDesignDir.'/*/*.xml');
|
||||
if (count($aFiles) == 0) {
|
||||
$sAvailable = 'none!';
|
||||
} else {
|
||||
$aAvailable = [];
|
||||
foreach ($aFiles as $sFile) {
|
||||
$aAvailable[] = "'".basename($sFile, '.xml')."'";
|
||||
}
|
||||
$sAvailable = implode(', ', $aAvailable);
|
||||
}
|
||||
throw new Exception("Could not load property tree design '$sDesignSourceId'. Available designs: $sAvailable");
|
||||
}
|
||||
|
||||
// Silently keep track of errors
|
||||
libxml_use_internal_errors(true);
|
||||
libxml_clear_errors();
|
||||
$this->load($sFile);
|
||||
//$bValidated = $oDocument->schemaValidate(APPROOT.'setup/itop_design.xsd');
|
||||
$aErrors = libxml_get_errors();
|
||||
if (count($aErrors) > 0) {
|
||||
$aDisplayErrors = [];
|
||||
foreach ($aErrors as $oXmlError) {
|
||||
$aDisplayErrors[] = 'Line '.$oXmlError->line.': '.$oXmlError->message;
|
||||
}
|
||||
|
||||
throw new Exception("Invalid XML in '$sFile'. Errors: ".implode(', ', $aDisplayErrors));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of the standard API
|
||||
*
|
||||
* @param $filename
|
||||
* @param int $options
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
// Return type union is not supported by PHP 7.4, we can remove the following PHP attribute and add the return type once iTop min PHP version is PHP 8.0+
|
||||
#[ReturnTypeWillChange]
|
||||
public function save($filename, $options = null)
|
||||
{
|
||||
$this->documentElement->setAttribute('xsi:noNamespaceSchemaLocation', 'https://www.combodo.com/itop-schema/'.ITOP_DESIGN_LATEST_VERSION);
|
||||
|
||||
return parent::save($filename);
|
||||
}
|
||||
}
|
||||
17
sources/PropertyType/PropertyTypeException.php
Normal file
17
sources/PropertyType/PropertyTypeException.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @since 3.3.0
|
||||
*/
|
||||
class PropertyTypeException extends Exception
|
||||
{
|
||||
}
|
||||
51
sources/PropertyType/PropertyTypeFactory.php
Normal file
51
sources/PropertyType/PropertyTypeFactory.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
|
||||
|
||||
/**
|
||||
* Build a property type form XML DOM
|
||||
* @since 3.3.0
|
||||
*/
|
||||
class PropertyTypeFactory
|
||||
{
|
||||
private static PropertyTypeFactory $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): PropertyTypeFactory
|
||||
{
|
||||
if (!isset(static::$oInstance)) {
|
||||
static::$oInstance = new PropertyTypeFactory();
|
||||
}
|
||||
|
||||
return static::$oInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a property node from a design element
|
||||
*
|
||||
* @param \Combodo\iTop\DesignElement $oDomNode
|
||||
* @param \Combodo\iTop\PropertyType\ValueType\AbstractValueType|null $oParent
|
||||
*
|
||||
* @return \Combodo\iTop\PropertyType\PropertyType
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function CreatePropertyTypeFromDom(DesignElement $oDomNode, ?AbstractValueType $oParent = null): PropertyType
|
||||
{
|
||||
$oNode = new PropertyType();
|
||||
$oNode->InitFromDomNode($oDomNode);
|
||||
|
||||
return $oNode;
|
||||
}
|
||||
}
|
||||
91
sources/PropertyType/PropertyTypeService.php
Normal file
91
sources/PropertyType/PropertyTypeService.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType;
|
||||
|
||||
use Combodo\iTop\Forms\Block\Base\FormBlock;
|
||||
use Combodo\iTop\Forms\Block\FormBlockException;
|
||||
use Combodo\iTop\Forms\Block\FormBlockService;
|
||||
use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompiler;
|
||||
use Combodo\iTop\Service\Cache\DataModelDependantCache;
|
||||
use utils;
|
||||
|
||||
class PropertyTypeService
|
||||
{
|
||||
public const FORM_CACHE_POOL = 'Forms';
|
||||
|
||||
private DataModelDependantCache $oCacheService;
|
||||
|
||||
private static PropertyTypeService $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
$this->oCacheService = DataModelDependantCache::GetInstance();
|
||||
}
|
||||
|
||||
final public static function GetInstance(): PropertyTypeService
|
||||
{
|
||||
if (!isset(static::$oInstance)) {
|
||||
static::$oInstance = new PropertyTypeService();
|
||||
}
|
||||
|
||||
return static::$oInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sId name of the form to retrieve
|
||||
* @param string $sType
|
||||
*
|
||||
* @return \Combodo\iTop\Forms\Block\Base\FormBlock
|
||||
* @throws \Combodo\iTop\Forms\Block\FormBlockException
|
||||
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
|
||||
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
|
||||
* @throws \DOMFormatException
|
||||
*/
|
||||
public function GetFormBlockById(string $sId, string $sType): FormBlock
|
||||
{
|
||||
$sFilteredId = $this->SanitizeId($sId);
|
||||
$sCacheKey = $this->GetCacheKey($sType, $sFilteredId);
|
||||
|
||||
if (!$this->oCacheService->HasEntry(self::FORM_CACHE_POOL, $sCacheKey) || utils::IsDevelopmentEnvironment()) {
|
||||
// Cache not found, compile the form
|
||||
$sPHPContent = PropertyTypeCompiler::GetInstance()->CompileForm($sFilteredId, $sType);
|
||||
$this->oCacheService->StorePhpContent(self::FORM_CACHE_POOL, $sCacheKey, "<?php\n\n$sPHPContent");
|
||||
}
|
||||
$this->oCacheService->FetchPHP(self::FORM_CACHE_POOL, $sCacheKey);
|
||||
$sFormBlockClass = 'FormFor__'.$sFilteredId;
|
||||
|
||||
return new $sFormBlockClass($sFilteredId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sId
|
||||
*
|
||||
* @return string
|
||||
* @throws \Combodo\iTop\Forms\Block\FormBlockException
|
||||
*/
|
||||
private function SanitizeId(string $sId): string
|
||||
{
|
||||
$sFilteredId = preg_replace('/[^0-9a-zA-Z_]/', '', $sId);
|
||||
if (strlen($sFilteredId) === 0 || $sFilteredId !== $sId) {
|
||||
throw new FormBlockException('Malformed name for block: '.json_encode($sId));
|
||||
}
|
||||
|
||||
return $sFilteredId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sType
|
||||
* @param string $sFilteredId
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function GetCacheKey(string $sType, string $sFilteredId): string
|
||||
{
|
||||
return $sType.'/'.$sFilteredId;
|
||||
}
|
||||
}
|
||||
231
sources/PropertyType/ValueType/AbstractValueType.php
Normal file
231
sources/PropertyType/ValueType/AbstractValueType.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeBoolean.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeBoolean.php
Normal 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;
|
||||
}
|
||||
}
|
||||
44
sources/PropertyType/ValueType/Leaf/ValueTypeChoice.php
Normal file
44
sources/PropertyType/ValueType/Leaf/ValueTypeChoice.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
sources/PropertyType/ValueType/Leaf/ValueTypeClass.php
Normal file
55
sources/PropertyType/ValueType/Leaf/ValueTypeClass.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeIcon.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeIcon.php
Normal 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;
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeInteger.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeInteger.php
Normal 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;
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeLabel.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeLabel.php
Normal 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;
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeOQL.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeOQL.php
Normal 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;
|
||||
}
|
||||
}
|
||||
19
sources/PropertyType/ValueType/Leaf/ValueTypeProfileName.php
Normal file
19
sources/PropertyType/ValueType/Leaf/ValueTypeProfileName.php
Normal 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 '';
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeString.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeString.php
Normal 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;
|
||||
}
|
||||
}
|
||||
21
sources/PropertyType/ValueType/Leaf/ValueTypeText.php
Normal file
21
sources/PropertyType/ValueType/Leaf/ValueTypeText.php
Normal 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;
|
||||
}
|
||||
}
|
||||
62
sources/PropertyType/ValueType/ValueTypeFactory.php
Normal file
62
sources/PropertyType/ValueType/ValueTypeFactory.php
Normal 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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user