diff --git a/application/datamodel.application.xml b/application/datamodel.application.xml
index a294dbe2a..eb18e600f 100644
--- a/application/datamodel.application.xml
+++ b/application/datamodel.application.xml
@@ -863,22 +863,13 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
-
-
-
-
-
-
{{query.selected_class}}
-
- bars
-
@@ -893,17 +884,11 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
-
-
-
{{query.selected_class}}
{{aggregation_function.value != 'count'}}
-
-
-
{{query.selected_class}}
numeric
@@ -924,9 +909,6 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
-
-
-
@@ -966,23 +948,15 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
-
-
-
-
-
-
{{query.selected_class}}
enum
-
-
-
+
{{query.selected_class}}
{{group_by.attribute}}
diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php
index 95caade5c..6bc2e551d 100644
--- a/lib/composer/autoload_classmap.php
+++ b/lib/composer/autoload_classmap.php
@@ -556,6 +556,13 @@ return array(
'Combodo\\iTop\\PropertyType\\PropertyTypeException' => $baseDir . '/sources/PropertyType/PropertyTypeException.php',
'Combodo\\iTop\\PropertyType\\PropertyTypeFactory' => $baseDir . '/sources/PropertyType/PropertyTypeFactory.php',
'Combodo\\iTop\\PropertyType\\PropertyTypeService' => $baseDir . '/sources/PropertyType/PropertyTypeService.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\SerializerException' => $baseDir . '/sources/PropertyType/Serializer/SerializerException.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\AbstractXMLFormat' => $baseDir . '/sources/PropertyType/Serializer/XMLFormat/AbstractXMLFormat.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatCSV' => $baseDir . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatCSV.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatFactory' => $baseDir . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatFactory.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatFlatArray' => $baseDir . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatFlatArray.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatValueAsId' => $baseDir . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatValueAsId.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLSerializer' => $baseDir . '/sources/PropertyType/Serializer/XMLSerializer.php',
'Combodo\\iTop\\PropertyType\\ValueType\\AbstractValueType' => $baseDir . '/sources/PropertyType/ValueType/AbstractValueType.php',
'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\AbstractBranchValueType' => $baseDir . '/sources/PropertyType/ValueType/Branch/AbstractBranchValueType.php',
'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\ValueTypeCollection' => $baseDir . '/sources/PropertyType/ValueType/Branch/ValueTypeCollection.php',
diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php
index 63fcc0a7f..7d7e438e8 100644
--- a/lib/composer/autoload_static.php
+++ b/lib/composer/autoload_static.php
@@ -942,6 +942,13 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\PropertyType\\PropertyTypeException' => __DIR__ . '/../..' . '/sources/PropertyType/PropertyTypeException.php',
'Combodo\\iTop\\PropertyType\\PropertyTypeFactory' => __DIR__ . '/../..' . '/sources/PropertyType/PropertyTypeFactory.php',
'Combodo\\iTop\\PropertyType\\PropertyTypeService' => __DIR__ . '/../..' . '/sources/PropertyType/PropertyTypeService.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\SerializerException' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/SerializerException.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\AbstractXMLFormat' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLFormat/AbstractXMLFormat.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatCSV' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatCSV.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatFactory' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatFactory.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatFlatArray' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatFlatArray.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLFormat\\XMLFormatValueAsId' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatValueAsId.php',
+ 'Combodo\\iTop\\PropertyType\\Serializer\\XMLSerializer' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLSerializer.php',
'Combodo\\iTop\\PropertyType\\ValueType\\AbstractValueType' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/AbstractValueType.php',
'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\AbstractBranchValueType' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/Branch/AbstractBranchValueType.php',
'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\ValueTypeCollection' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/Branch/ValueTypeCollection.php',
diff --git a/sources/PropertyType/Compiler/PropertyTypeCompiler.php b/sources/PropertyType/Compiler/PropertyTypeCompiler.php
index fe97afb16..d7a1e7672 100644
--- a/sources/PropertyType/Compiler/PropertyTypeCompiler.php
+++ b/sources/PropertyType/Compiler/PropertyTypeCompiler.php
@@ -43,7 +43,7 @@ class PropertyTypeCompiler
* @throws \Combodo\iTop\PropertyType\PropertyTypeException
* @throws \DOMFormatException
*/
- protected function CompilePropertyTypeFromXML(string $sXMLContent): PropertyType
+ public function CompilePropertyTypeFromXML(string $sXMLContent): PropertyType
{
$oDoc = new DesignDocument();
libxml_clear_errors();
@@ -66,7 +66,7 @@ class PropertyTypeCompiler
* @return string
* @throws \Combodo\iTop\PropertyType\Compiler\PropertyTypeCompilerException
*/
- protected function GetXMLContent(string $sId, string $sType): string
+ public function GetXMLContent(string $sId, string $sType): string
{
$sPath = utils::GetAbsoluteModulePath('core')."property_types/$sType/$sId.xml";
if (!file_exists($sPath)) {
@@ -93,21 +93,6 @@ class PropertyTypeCompiler
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
@@ -123,11 +108,4 @@ class PropertyTypeCompiler
return $this->CompileFormFromXML($sXMLContent);
}
-
- public function CompileEntity(string $sId, string $sType): string
- {
- $sXMLContent = $this->GetXMLContent($sId, $sType);
-
- return $this->CompileEntityFromXML($sXMLContent);
- }
}
diff --git a/sources/PropertyType/PropertyType.php b/sources/PropertyType/PropertyType.php
index e01611c42..4f27fea99 100644
--- a/sources/PropertyType/PropertyType.php
+++ b/sources/PropertyType/PropertyType.php
@@ -37,7 +37,7 @@ class PropertyType
$sDefinitionNodeType = $oDefinitionNode->getAttribute('xsi:type');
if (!is_a($sDefinitionNodeType, AbstractValueType::class, true)) {
- throw new PropertyTypeException('Unsupported type '.json_encode($sDefinitionNodeType).' in ');
+ throw new PropertyTypeException('Unsupported xsi:type '.json_encode($sDefinitionNodeType), $oDomNode);
}
$this->oValueType = new $sDefinitionNodeType();
@@ -50,18 +50,11 @@ class PropertyType
$aPHPFragments = [];
if ($this->oValueType->IsLeaf()) {
+ $sFormBlockClass = $this->oValueType->GetFormBlockClass();
$sLocalPHP = <<sId extends Combodo\iTop\Forms\Block\Base\FormBlock
+class FormFor__$this->sId extends $sFormBlockClass
{
- protected function BuildForm(): void
- {
-PHP;
-
- $sLocalPHP .= "\n".$this->oValueType->ToPHPFormBlock($aPHPFragments);
-
- $sLocalPHP .= <<sParentType;
}
+
+ public function SerializeToDOMNode(mixed $value, DesignElement$oDOMNode): void
+ {
+ $this->oValueType->SerializeToDOMNode($value, $oDOMNode);
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
+ {
+ return $this->oValueType->UnserializeFromDOMNode($oDOMNode);
+ }
}
diff --git a/sources/PropertyType/PropertyTypeException.php b/sources/PropertyType/PropertyTypeException.php
index 2f433c0ac..620e187c2 100644
--- a/sources/PropertyType/PropertyTypeException.php
+++ b/sources/PropertyType/PropertyTypeException.php
@@ -7,11 +7,21 @@
namespace Combodo\iTop\PropertyType;
+use Combodo\iTop\DesignDocument;
+use Combodo\iTop\DesignElement;
use Exception;
+use Throwable;
/**
* @since 3.3.0
*/
class PropertyTypeException extends Exception
{
+ public function __construct(string $message = "", ?DesignElement $oNode = null, ?Throwable $previous = null)
+ {
+ if (!is_null($oNode)) {
+ $message = DesignDocument::GetItopNodePath($oNode).': '.$message;
+ }
+ parent::__construct($message, 0, $previous);
+ }
}
diff --git a/sources/PropertyType/Serializer/SerializerException.php b/sources/PropertyType/Serializer/SerializerException.php
new file mode 100644
index 000000000..f9ca12fc8
--- /dev/null
+++ b/sources/PropertyType/Serializer/SerializerException.php
@@ -0,0 +1,14 @@
+ownerDocument->createTextNode($sXmlValue);
+ $oDOMNode->appendChild($oTextNode);
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
+ {
+ $sValue = $oDOMNode->GetText('');
+ return explode(',', $sValue);
+ }
+}
diff --git a/sources/PropertyType/Serializer/XMLFormat/XMLFormatFactory.php b/sources/PropertyType/Serializer/XMLFormat/XMLFormatFactory.php
new file mode 100644
index 000000000..79e787b03
--- /dev/null
+++ b/sources/PropertyType/Serializer/XMLFormat/XMLFormatFactory.php
@@ -0,0 +1,56 @@
+getAttribute('xsi:type');
+
+ if (utils::IsNullOrEmptyString($sNodeType)) {
+ throw new SerializerException("Missing xsi:type in node specification", $oDomNode);
+ }
+
+ if (is_a($sNodeType, AbstractXMLFormat::class, true)) {
+ $oNode = new $sNodeType();
+ $oNode->InitFromDomNode($oDomNode);
+
+ return $oNode;
+ }
+
+ throw new SerializerException("Unknown type node class: ".json_encode($sNodeType), $oDomNode);
+ }
+
+}
diff --git a/sources/PropertyType/Serializer/XMLFormat/XMLFormatFlatArray.php b/sources/PropertyType/Serializer/XMLFormat/XMLFormatFlatArray.php
new file mode 100644
index 000000000..cdc2d2b1f
--- /dev/null
+++ b/sources/PropertyType/Serializer/XMLFormat/XMLFormatFlatArray.php
@@ -0,0 +1,79 @@
+GetChildText('tag-format');
+ if (is_null($sTagFormat)) {
+ throw new SerializerException('Missing element', $oDomNode);
+ }
+ $this->sTagFormat = $sTagFormat;
+
+ $sCountTag = $oDomNode->GetChildText('count-tag');
+ if (is_null($sCountTag)) {
+ throw new SerializerException('Missing element', $oDomNode);
+ }
+ $this->sCountTag = $sCountTag;
+ }
+
+ public function SerializeToDOMNode($value, $oDOMNode, AbstractValueType $oValueType): void
+ {
+ if (!$oValueType instanceof ValueTypeCollection) {
+ throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
+ }
+
+ $oCountNode = $oDOMNode->ownerDocument->createElement($this->sCountTag, count($value));
+ $oDOMNode->appendChild($oCountNode);
+ foreach ($value as $iRank => $aValues) {
+ foreach ($oValueType->GetChildren() as $oChild) {
+ $sId = $oChild->GetId();
+ if (isset($aValues[$sId])) {
+ $sTagName = \MetaModel::ApplyParams($this->sTagFormat, ['rank' => $iRank, 'id' => $sId]);
+ $oChildNode = $oDOMNode->ownerDocument->createElement($sTagName);
+ $oDOMNode->appendChild($oChildNode);
+ $oChild->SerializeToDOMNode($aValues[$sId], $oChildNode);
+ }
+ }
+ }
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
+ {
+ $aResults = [];
+
+ if (!$oValueType instanceof ValueTypeCollection) {
+ throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
+ }
+
+ $iCount = $oDOMNode->GetUniqueElement($this->sCountTag)->GetText(0);
+ for ($iRank = 0; $iRank < $iCount; $iRank++) {
+ foreach ($oValueType->GetChildren() as $oChild) {
+ $sId = $oChild->GetId();
+ $sTagName = \MetaModel::ApplyParams($this->sTagFormat, ['rank' => $iRank, 'id' => $sId]);
+ $oChildNode = $oDOMNode->GetOptionalElement($sTagName);
+ if ($oChildNode) {
+ $aResults[$iRank][$sId] = $oChildNode->GetText('');
+ }
+ }
+ }
+
+ return $aResults;
+ }
+}
diff --git a/sources/PropertyType/Serializer/XMLFormat/XMLFormatValueAsId.php b/sources/PropertyType/Serializer/XMLFormat/XMLFormatValueAsId.php
new file mode 100644
index 000000000..59e275a32
--- /dev/null
+++ b/sources/PropertyType/Serializer/XMLFormat/XMLFormatValueAsId.php
@@ -0,0 +1,48 @@
+GetChildText('tag-name');
+ if (is_null($sTagName)) {
+ throw new SerializerException("Missing element", $oDomNode);
+ }
+ $this->sTagName = $sTagName;
+ }
+
+ public function SerializeToDOMNode($value, $oDOMNode, AbstractValueType $oValueType): void
+ {
+ foreach ($value as $item) {
+ $oChildNode = $oDOMNode->ownerDocument->createElement($this->sTagName);
+ $oChildNode->setAttribute('id', "$item");
+ $oDOMNode->appendChild($oChildNode);
+ }
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
+ {
+ $aResult = [];
+
+ foreach ($oDOMNode->getElementsByTagName($this->sTagName) as $oNode) {
+ $sValue = $oNode->getAttribute('id');
+ $aResult[] = $sValue;
+ }
+
+ return $aResult;
+ }
+}
diff --git a/sources/PropertyType/Serializer/XMLSerializer.php b/sources/PropertyType/Serializer/XMLSerializer.php
new file mode 100644
index 000000000..1d3187998
--- /dev/null
+++ b/sources/PropertyType/Serializer/XMLSerializer.php
@@ -0,0 +1,57 @@
+GetXMLContent($sId, $sType);
+
+ $this->SerializeForPropertyType($value, $oParentNode, $sPropertyTypeXML);
+ }
+
+ public function Unserialize(DesignElement $oDOMNode, string $sId, string $sType): mixed
+ {
+ return null;
+ }
+
+ public function SerializeForPropertyType(mixed $value, DesignElement $oParentNode, string $sPropertyTypeXML): void
+ {
+ $oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
+
+ $oPropertyType->SerializeToDOMNode($value, $oParentNode);
+ }
+
+ public function UnserializeForPropertyType(DesignElement $oParentNode, string $sPropertyTypeXML): mixed
+ {
+ $oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
+
+ return $oPropertyType->UnserializeFromDOMNode($oParentNode);
+ }
+}
diff --git a/sources/PropertyType/ValueType/AbstractValueType.php b/sources/PropertyType/ValueType/AbstractValueType.php
index effdd22c2..3786e8d0a 100644
--- a/sources/PropertyType/ValueType/AbstractValueType.php
+++ b/sources/PropertyType/ValueType/AbstractValueType.php
@@ -219,6 +219,11 @@ PHP;
}
}
+ public function GetId(): string
+ {
+ return $this->sId;
+ }
+
protected function GetSibling(string $sId): ?AbstractValueType
{
if (is_null($this->oParent)) {
@@ -228,4 +233,20 @@ PHP;
return $this->oParent->GetChild($sId);
}
+ public function SerializeToDOMNode(mixed $value, DesignElement $oDOMNode): void
+ {
+ $sXmlValue = $value;
+ $oTextNode = $oDOMNode->ownerDocument->createTextNode($sXmlValue);
+ $oDOMNode->appendChild($oTextNode);
+ }
+
+ /**
+ * @param $oDOMNode
+ *
+ * @return mixed
+ */
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
+ {
+ return $oDOMNode->GetText();
+ }
}
diff --git a/sources/PropertyType/ValueType/Branch/ValueTypeCollection.php b/sources/PropertyType/ValueType/Branch/ValueTypeCollection.php
index e1d735d3b..cb1fd8a69 100644
--- a/sources/PropertyType/ValueType/Branch/ValueTypeCollection.php
+++ b/sources/PropertyType/ValueType/Branch/ValueTypeCollection.php
@@ -9,6 +9,8 @@ namespace Combodo\iTop\PropertyType\ValueType\Branch;
use Combodo\iTop\DesignElement;
use Combodo\iTop\Forms\Block\Base\CollectionBlock;
+use Combodo\iTop\PropertyType\Serializer\XMLFormat\AbstractXMLFormat;
+use Combodo\iTop\PropertyType\Serializer\XMLFormat\XMLFormatFactory;
use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory;
use utils;
@@ -18,6 +20,8 @@ use utils;
*/
class ValueTypeCollection extends ValueTypePropertyTree
{
+ private AbstractXMLFormat $oXMLFormat;
+
/**
* @param \Combodo\iTop\DesignElement $oDomNode
* @param \Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType|null $oParent
@@ -33,6 +37,9 @@ class ValueTypeCollection extends ValueTypePropertyTree
$this->sSubTreeClass = 'SubFormFor__'.$this->sIdWithPath;
$this->aFormBlockOptionsForPHP['block_entry_type'] = utils::QuoteForPHP($this->sSubTreeClass);
+ $oNode = $oDomNode->GetUniqueElement('xml-format');
+ $this->oXMLFormat = XMLFormatFactory::GetInstance()->CreateXMLFormatFromDomNode($oNode);
+
// read child properties
foreach ($oDomNode->GetUniqueElement('prototype')->childNodes as $oNode) {
if ($oNode instanceof DesignElement) {
@@ -74,4 +81,14 @@ class ValueTypeCollection extends ValueTypePropertyTree
return $this->GetLocalPHPForValueType();
}
+
+ public function SerializeToDOMNode(mixed $value, DesignElement $oDOMNode): void
+ {
+ $this->oXMLFormat->SerializeToDOMNode($value, $oDOMNode, $this);
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
+ {
+ return $this->oXMLFormat->UnserializeFromDOMNode($oDOMNode, $this);
+ }
}
diff --git a/sources/PropertyType/ValueType/Branch/ValueTypePropertyTree.php b/sources/PropertyType/ValueType/Branch/ValueTypePropertyTree.php
index 599926b8f..9d39442a3 100644
--- a/sources/PropertyType/ValueType/Branch/ValueTypePropertyTree.php
+++ b/sources/PropertyType/ValueType/Branch/ValueTypePropertyTree.php
@@ -9,19 +9,7 @@ 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
@@ -86,4 +74,32 @@ PHP;
return $this->GetLocalPHPForValueType($this->sSubTreeClass);
}
+
+ public function SerializeToDOMNode(mixed $value, DesignElement $oDOMNode): void
+ {
+ foreach ($this->aChildren as $oChild) {
+ $sId = $oChild->sId;
+ if (isset($value[$sId])) {
+ /** @var DesignElement $oChildNode */
+ $oChildNode = $oDOMNode->ownerDocument->createElement($sId);
+ $oDOMNode->appendChild($oChildNode);
+ $oChild->SerializeToDOMNode($value[$sId], $oChildNode);
+ }
+ }
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
+ {
+ $aResults = [];
+
+ foreach ($this->aChildren as $oChild) {
+ $sId = $oChild->sId;
+ $oChildNode = $oDOMNode->GetOptionalElement($sId);
+ if ($oChildNode) {
+ $aResults[$sId] = $oChild->UnserializeFromDOMNode($oChildNode);
+ }
+ }
+
+ return $aResults;
+ }
}
diff --git a/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php b/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php
index 56568ef46..7f747ea6e 100644
--- a/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php
+++ b/sources/PropertyType/ValueType/Leaf/ValueTypeClass.php
@@ -30,7 +30,7 @@ class ValueTypeClass extends AbstractLeafValueType
{
parent::InitFromDomNode($oDomNode, $oParent);
- $sCategories = $oDomNode->GetChildText('categories-csv');
+ $sCategories = $oDomNode->GetChildText('categories-csv', '');
/** @var \ModelReflection $oModelReflection */
$oModelReflection = ServiceLocator::GetInstance()->get('ModelReflection');
diff --git a/sources/PropertyType/ValueType/Leaf/ValueTypeCollectionOfValues.php b/sources/PropertyType/ValueType/Leaf/ValueTypeCollectionOfValues.php
index 693a80bd8..eb3b5ee41 100644
--- a/sources/PropertyType/ValueType/Leaf/ValueTypeCollectionOfValues.php
+++ b/sources/PropertyType/ValueType/Leaf/ValueTypeCollectionOfValues.php
@@ -10,6 +10,8 @@ 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\Serializer\XMLFormat\AbstractXMLFormat;
+use Combodo\iTop\PropertyType\Serializer\XMLFormat\XMLFormatFactory;
use Combodo\iTop\PropertyType\ValueType\Branch\AbstractBranchValueType;
use Combodo\iTop\PropertyType\ValueType\Leaf\AbstractLeafValueType;
use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory;
@@ -17,6 +19,7 @@ use Combodo\iTop\PropertyType\ValueType\ValueTypeFactory;
class ValueTypeCollectionOfValues extends AbstractLeafValueType
{
private string $sFormBlockClass;
+ private AbstractXMLFormat $oXMLFormat;
public function GetFormBlockClass(): string
{
@@ -33,6 +36,19 @@ class ValueTypeCollectionOfValues extends AbstractLeafValueType
$this->aFormBlockOptionsForPHP['multiple'] = 'true';
}
+ $oNode = $oDomNode->GetUniqueElement('xml-format');
+ $this->oXMLFormat = XMLFormatFactory::GetInstance()->CreateXMLFormatFromDomNode($oNode);
+
parent::InitFromDomNode($oDomNode, $oParent);
}
+
+ public function SerializeToDOMNode(mixed $value, DesignElement $oDOMNode): void
+ {
+ $this->oXMLFormat->SerializeToDOMNode($value, $oDOMNode, $this);
+ }
+
+ public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
+ {
+ return $this->oXMLFormat->UnserializeFromDOMNode($oDOMNode, $this);
+ }
}
diff --git a/sources/PropertyType/ValueType/ValueTypeFactory.php b/sources/PropertyType/ValueType/ValueTypeFactory.php
index c0ffaa000..3d158f190 100644
--- a/sources/PropertyType/ValueType/ValueTypeFactory.php
+++ b/sources/PropertyType/ValueType/ValueTypeFactory.php
@@ -46,7 +46,7 @@ class ValueTypeFactory
if (utils::IsNullOrEmptyString($sNodeType)) {
$sId = $oDomNode->getAttribute('id');
- throw new PropertyTypeException("Node: $sId, missing value-type in node specification");
+ throw new PropertyTypeException("Missing value-type in node specification", $oDomNode);
}
if (is_a($sNodeType, AbstractValueType::class, true)) {
@@ -57,6 +57,6 @@ class ValueTypeFactory
}
$sId = $oDomNode->getAttribute('id');
- throw new PropertyTypeException("Node: $sId, unknown type node class: ".json_encode($sNodeType));
+ throw new PropertyTypeException("Unknown value-type node class: ".json_encode($sNodeType), $oDomNode);
}
}
diff --git a/sources/alias.php b/sources/alias.php
index b3183cfe4..56dc31c5b 100644
--- a/sources/alias.php
+++ b/sources/alias.php
@@ -117,3 +117,7 @@ class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeLabel::class, 'Co
class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeOQL::class, 'Combodo-ValueType-OQL');
class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeString::class, 'Combodo-ValueType-String');
class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeText::class, 'Combodo-ValueType-Text');
+
+class_alias(\Combodo\iTop\PropertyType\Serializer\XMLFormat\XMLFormatCSV::class, 'Combodo-XMLFormat-CSV');
+class_alias(\Combodo\iTop\PropertyType\Serializer\XMLFormat\XMLFormatValueAsId::class, 'Combodo-XMLFormat-ValueAsId');
+class_alias(\Combodo\iTop\PropertyType\Serializer\XMLFormat\XMLFormatFlatArray::class, 'Combodo-XMLFormat-FlatArray');
diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
index ca3df00f4..7ef63081d 100644
--- a/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
+++ b/tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
@@ -9,6 +9,7 @@ namespace Combodo\iTop\Test\UnitTest;
use CMDBSource;
use DeprecatedCallsLog;
+use DOMDocument;
use MySQLTransactionNotClosedException;
use ParseError;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
@@ -717,4 +718,34 @@ abstract class ItopTestCase extends KernelTestCase
return $this->CallUrl($sUrl, $aPostFields, $aCurlOptions, $bXDebugEnabled);
}
+
+ /**
+ * @param $sXML
+ *
+ * @return false|string
+ */
+ protected function CanonicalizeXML($sXML)
+ {
+ // Canonicalize the expected XML (to cope with indentation)
+ $oExpectedDocument = new DOMDocument();
+ $oExpectedDocument->preserveWhiteSpace = false;
+ $oExpectedDocument->formatOutput = true;
+ $oExpectedDocument->loadXML($sXML);
+
+ $sSavedXML = $oExpectedDocument->SaveXML();
+
+ return str_replace(' encoding="UTF-8"', '', $sSavedXML);
+ }
+
+ /**
+ * @param $sExpected
+ * @param $sActual
+ * @param string $sMessage
+ */
+ protected function AssertEqualiTopXML($sExpected, $sActual, string $sMessage = '')
+ {
+ // Note: assertEquals reports the differences in a diff which is easier to interpret (in PHPStorm)
+ // as compared to the report given by assertEqualXMLStructure
+ static::assertEquals($this->CanonicalizeXML($sExpected), $this->CanonicalizeXML($sActual), $sMessage);
+ }
}
diff --git a/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php b/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php
index bce50f46f..16e1aec59 100644
--- a/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php
+++ b/tests/php-unit-tests/unitary-tests/setup/ModelFactoryTest.php
@@ -64,36 +64,6 @@ class ModelFactoryTest extends ItopTestCase
return $oFactory;
}
- /**
- * @param $sXML
- *
- * @return false|string
- */
- protected function CanonicalizeXML($sXML)
- {
- // Canonicalize the expected XML (to cope with indentation)
- $oExpectedDocument = new DOMDocument();
- $oExpectedDocument->preserveWhiteSpace = false;
- $oExpectedDocument->formatOutput = true;
- $oExpectedDocument->loadXML($sXML);
-
- $sSavedXML = $oExpectedDocument->SaveXML();
-
- return str_replace(' encoding="UTF-8"', '', $sSavedXML);
- }
-
- /**
- * @param $sExpected
- * @param $sActual
- * @param string $sMessage
- */
- protected function AssertEqualiTopXML($sExpected, $sActual, string $sMessage = '')
- {
- // Note: assertEquals reports the differences in a diff which is easier to interpret (in PHPStorm)
- // as compared to the report given by assertEqualXMLStructure
- static::assertEquals($this->CanonicalizeXML($sExpected), $this->CanonicalizeXML($sActual), $sMessage);
- }
-
/**
* Assertion ignoring some of the unexpected decoration brought by DOM Elements.
*/
diff --git a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php
index e6542d163..52965df43 100644
--- a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php
+++ b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Compiler/FormsCompilerTest.php
@@ -136,7 +136,7 @@ PHP,
- test
+ test
@@ -244,6 +244,10 @@ PHP,
+
+ item_count
+ item_\$rank\$_\$id\$
+
@@ -580,6 +584,7 @@ PHP,
+
Contact
status
@@ -600,6 +605,22 @@ class FormFor__CollectionOfValuesTest extends Combodo\iTop\Forms\Block\Base\Form
]);
}
}
+PHP,
+ ],
+ 'Single value' => [
+ 'sXMLContent' => <<
+
+ Dashlet
+
+
+
+
+XML,
+ 'sExpectedPHP' => << [
@@ -731,7 +752,7 @@ XML,
'Missing value-type in node specification' => [
'sXMLContent' => <<
-
+
Dashlet
@@ -743,13 +764,12 @@ XML,
XML,
'sExpectedClass' => 'Combodo\iTop\PropertyType\PropertyTypeException',
- 'sExpectedMessage' => 'Node: source_property, missing value-type in node specification',
+ 'sExpectedMessage' => '/property_type[WrongDefinition]/definition/nodes/node[source_property]: Missing value-type in node specification',
],
-
'Wrong class for value-type in node specification' => [
'sXMLContent' => <<
-
+
Dashlet
@@ -761,7 +781,71 @@ XML,
XML,
'sExpectedClass' => 'Combodo\iTop\PropertyType\PropertyTypeException',
- 'sExpectedMessage' => 'Node: source_property, unknown type node class: "Test-Combodo"',
+ 'sExpectedMessage' => '/property_type[WrongDefinition]/definition/nodes/node[source_property]: Unknown value-type node class: "Test-Combodo"',
+ ],
+ 'Wrong class for xml-format in node specification' => [
+ 'sXMLContent' => <<
+
+ Dashlet
+
+
+
+
+
+
+ Contact
+ status
+
+
+
+
+
+XML,
+ 'sExpectedClass' => 'Combodo\iTop\PropertyType\Serializer\SerializerException',
+ 'sExpectedMessage' => '/property_type[WrongDefinition]/definition/nodes/node[coll]/xml-format: Unknown type node class: "Combodo-test"',
+ ],
+ 'Missing class for xml-format in node specification' => [
+ 'sXMLContent' => <<
+
+ Dashlet
+
+
+
+
+
+
+ Contact
+ status
+
+
+
+
+
+XML,
+ 'sExpectedClass' => 'Combodo\iTop\PropertyType\Serializer\SerializerException',
+ 'sExpectedMessage' => '/property_type[WrongDefinition]/definition/nodes/node[coll]/xml-format: Missing xsi:type in node specification',
+ ],
+ 'Missing tag in xml-format ' => [
+ 'sXMLContent' => <<
+
+ Dashlet
+
+
+
+
+
+
+
+
+
+
+
+XML,
+ 'sExpectedClass' => 'Combodo\iTop\PropertyType\Serializer\SerializerException',
+ 'sExpectedMessage' => '/property_type[WrongDefinition]/definition/nodes/node/xml-format: Missing element',
],
];
}