mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Save as XML serialized
This commit is contained in:
@@ -146,7 +146,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
|
||||
if ($oDashlet::IsVisible()) {
|
||||
$sDashletId = $oDashlet->GetID();
|
||||
$sDashletClass = $oDashlet->GetDashletType();
|
||||
$aDashletDenormalizedProperties = $oDashlet->GetDenormalizedProperties();
|
||||
$aDashletDenormalizedProperties = $oDashlet->GetModelData();
|
||||
$aDashletsInfo = DashletService::GetInstance()->GetDashletDefinition($sDashletClass);
|
||||
|
||||
// GRID LAYOUT: Set position relative to grid
|
||||
|
||||
@@ -453,7 +453,7 @@
|
||||
//
|
||||
// Method: jQuery.deparam
|
||||
//
|
||||
// Deserialize a params string into an object, optionally coercing numbers,
|
||||
// DeserializeFromDOMNode a params string into an object, optionally coercing numbers,
|
||||
// booleans, null and undefined values; this method is the counterpart to the
|
||||
// internal jQuery.param method.
|
||||
//
|
||||
|
||||
@@ -587,14 +587,12 @@ return array(
|
||||
'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\\XMLEncoder' => $baseDir . '/sources/PropertyType/Serializer/XMLEncoder.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\\XMLFormatCollectionWithId' => $baseDir . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatCollectionWithId.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\\XMLNormalizer' => $baseDir . '/sources/PropertyType/Serializer/XMLNormalizer.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',
|
||||
@@ -3962,5 +3960,5 @@ return array(
|
||||
'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php',
|
||||
'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php',
|
||||
'utils' => $baseDir . '/application/utils.inc.php',
|
||||
'©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
'<EFBFBD>' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
);
|
||||
|
||||
@@ -973,14 +973,12 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'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\\XMLEncoder' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLEncoder.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\\XMLFormatCollectionWithId' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLFormat/XMLFormatCollectionWithId.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\\XMLNormalizer' => __DIR__ . '/../..' . '/sources/PropertyType/Serializer/XMLNormalizer.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',
|
||||
@@ -4348,7 +4346,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
|
||||
'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
|
||||
'utils' => __DIR__ . '/../..' . '/application/utils.inc.php',
|
||||
'©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
'<EFBFBD>' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
||||
562
lib/symfony/cache/Adapter/ArrayAdapter.php
vendored
562
lib/symfony/cache/Adapter/ArrayAdapter.php
vendored
@@ -28,341 +28,341 @@ use Symfony\Contracts\Cache\CacheInterface;
|
||||
*/
|
||||
class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
use LoggerAwareTrait;
|
||||
|
||||
private bool $storeSerialized;
|
||||
private array $values = [];
|
||||
private array $tags = [];
|
||||
private array $expiries = [];
|
||||
private int $defaultLifetime;
|
||||
private float $maxLifetime;
|
||||
private int $maxItems;
|
||||
private bool $storeSerialized;
|
||||
private array $values = [];
|
||||
private array $tags = [];
|
||||
private array $expiries = [];
|
||||
private int $defaultLifetime;
|
||||
private float $maxLifetime;
|
||||
private int $maxItems;
|
||||
|
||||
private static \Closure $createCacheItem;
|
||||
private static \Closure $createCacheItem;
|
||||
|
||||
/**
|
||||
* @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
|
||||
*/
|
||||
public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true, float $maxLifetime = 0, int $maxItems = 0)
|
||||
{
|
||||
if (0 > $maxLifetime) {
|
||||
throw new InvalidArgumentException(\sprintf('Argument $maxLifetime must be positive, %F passed.', $maxLifetime));
|
||||
}
|
||||
/**
|
||||
* @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
|
||||
*/
|
||||
public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true, float $maxLifetime = 0, int $maxItems = 0)
|
||||
{
|
||||
if (0 > $maxLifetime) {
|
||||
throw new InvalidArgumentException(\sprintf('Argument $maxLifetime must be positive, %F passed.', $maxLifetime));
|
||||
}
|
||||
|
||||
if (0 > $maxItems) {
|
||||
throw new InvalidArgumentException(\sprintf('Argument $maxItems must be a positive integer, %d passed.', $maxItems));
|
||||
}
|
||||
if (0 > $maxItems) {
|
||||
throw new InvalidArgumentException(\sprintf('Argument $maxItems must be a positive integer, %d passed.', $maxItems));
|
||||
}
|
||||
|
||||
$this->defaultLifetime = $defaultLifetime;
|
||||
$this->storeSerialized = $storeSerialized;
|
||||
$this->maxLifetime = $maxLifetime;
|
||||
$this->maxItems = $maxItems;
|
||||
self::$createCacheItem ??= \Closure::bind(
|
||||
static function ($key, $value, $isHit, $tags) {
|
||||
$item = new CacheItem();
|
||||
$item->key = $key;
|
||||
$item->value = $value;
|
||||
$item->isHit = $isHit;
|
||||
if (null !== $tags) {
|
||||
$item->metadata[CacheItem::METADATA_TAGS] = $tags;
|
||||
}
|
||||
$this->defaultLifetime = $defaultLifetime;
|
||||
$this->storeSerialized = $storeSerialized;
|
||||
$this->maxLifetime = $maxLifetime;
|
||||
$this->maxItems = $maxItems;
|
||||
self::$createCacheItem ??= \Closure::bind(
|
||||
static function ($key, $value, $isHit, $tags) {
|
||||
$item = new CacheItem();
|
||||
$item->key = $key;
|
||||
$item->value = $value;
|
||||
$item->isHit = $isHit;
|
||||
if (null !== $tags) {
|
||||
$item->metadata[CacheItem::METADATA_TAGS] = $tags;
|
||||
}
|
||||
|
||||
return $item;
|
||||
},
|
||||
null,
|
||||
CacheItem::class
|
||||
);
|
||||
}
|
||||
return $item;
|
||||
},
|
||||
null,
|
||||
CacheItem::class
|
||||
);
|
||||
}
|
||||
|
||||
public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
|
||||
{
|
||||
$item = $this->getItem($key);
|
||||
$metadata = $item->getMetadata();
|
||||
public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed
|
||||
{
|
||||
$item = $this->getItem($key);
|
||||
$metadata = $item->getMetadata();
|
||||
|
||||
// ArrayAdapter works in memory, we don't care about stampede protection
|
||||
if (\INF === $beta || !$item->isHit()) {
|
||||
$save = true;
|
||||
$item->set($callback($item, $save));
|
||||
if ($save) {
|
||||
$this->save($item);
|
||||
}
|
||||
}
|
||||
// ArrayAdapter works in memory, we don't care about stampede protection
|
||||
if (\INF === $beta || !$item->isHit()) {
|
||||
$save = true;
|
||||
$item->set($callback($item, $save));
|
||||
if ($save) {
|
||||
$this->save($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $item->get();
|
||||
}
|
||||
return $item->get();
|
||||
}
|
||||
|
||||
public function delete(string $key): bool
|
||||
{
|
||||
return $this->deleteItem($key);
|
||||
}
|
||||
public function delete(string $key): bool
|
||||
{
|
||||
return $this->deleteItem($key);
|
||||
}
|
||||
|
||||
public function hasItem(mixed $key): bool
|
||||
{
|
||||
if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
|
||||
if ($this->maxItems) {
|
||||
// Move the item last in the storage
|
||||
$value = $this->values[$key];
|
||||
unset($this->values[$key]);
|
||||
$this->values[$key] = $value;
|
||||
}
|
||||
public function hasItem(mixed $key): bool
|
||||
{
|
||||
if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) {
|
||||
if ($this->maxItems) {
|
||||
// Move the item last in the storage
|
||||
$value = $this->values[$key];
|
||||
unset($this->values[$key]);
|
||||
$this->values[$key] = $value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
\assert('' !== CacheItem::validateKey($key));
|
||||
return true;
|
||||
}
|
||||
\assert('' !== CacheItem::validateKey($key));
|
||||
|
||||
return isset($this->expiries[$key]) && !$this->deleteItem($key);
|
||||
}
|
||||
return isset($this->expiries[$key]) && !$this->deleteItem($key);
|
||||
}
|
||||
|
||||
public function getItem(mixed $key): CacheItem
|
||||
{
|
||||
if (!$isHit = $this->hasItem($key)) {
|
||||
$value = null;
|
||||
public function getItem(mixed $key): CacheItem
|
||||
{
|
||||
if (!$isHit = $this->hasItem($key)) {
|
||||
$value = null;
|
||||
|
||||
if (!$this->maxItems) {
|
||||
// Track misses in non-LRU mode only
|
||||
$this->values[$key] = null;
|
||||
}
|
||||
} else {
|
||||
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
|
||||
}
|
||||
if (!$this->maxItems) {
|
||||
// Track misses in non-LRU mode only
|
||||
$this->values[$key] = null;
|
||||
}
|
||||
} else {
|
||||
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
|
||||
}
|
||||
|
||||
return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null);
|
||||
}
|
||||
return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null);
|
||||
}
|
||||
|
||||
public function getItems(array $keys = []): iterable
|
||||
{
|
||||
\assert(self::validateKeys($keys));
|
||||
public function getItems(array $keys = []): iterable
|
||||
{
|
||||
\assert(self::validateKeys($keys));
|
||||
|
||||
return $this->generateItems($keys, microtime(true), self::$createCacheItem);
|
||||
}
|
||||
return $this->generateItems($keys, microtime(true), self::$createCacheItem);
|
||||
}
|
||||
|
||||
public function deleteItem(mixed $key): bool
|
||||
{
|
||||
\assert('' !== CacheItem::validateKey($key));
|
||||
unset($this->values[$key], $this->tags[$key], $this->expiries[$key]);
|
||||
public function deleteItem(mixed $key): bool
|
||||
{
|
||||
\assert('' !== CacheItem::validateKey($key));
|
||||
unset($this->values[$key], $this->tags[$key], $this->expiries[$key]);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function deleteItems(array $keys): bool
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
$this->deleteItem($key);
|
||||
}
|
||||
public function deleteItems(array $keys): bool
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
$this->deleteItem($key);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function save(CacheItemInterface $item): bool
|
||||
{
|
||||
if (!$item instanceof CacheItem) {
|
||||
return false;
|
||||
}
|
||||
$item = (array) $item;
|
||||
$key = $item["\0*\0key"];
|
||||
$value = $item["\0*\0value"];
|
||||
$expiry = $item["\0*\0expiry"];
|
||||
public function save(CacheItemInterface $item): bool
|
||||
{
|
||||
if (!$item instanceof CacheItem) {
|
||||
return false;
|
||||
}
|
||||
$item = (array) $item;
|
||||
$key = $item["\0*\0key"];
|
||||
$value = $item["\0*\0value"];
|
||||
$expiry = $item["\0*\0expiry"];
|
||||
|
||||
$now = microtime(true);
|
||||
$now = microtime(true);
|
||||
|
||||
if (null !== $expiry) {
|
||||
if (!$expiry) {
|
||||
$expiry = \PHP_INT_MAX;
|
||||
} elseif ($expiry <= $now) {
|
||||
$this->deleteItem($key);
|
||||
if (null !== $expiry) {
|
||||
if (!$expiry) {
|
||||
$expiry = \PHP_INT_MAX;
|
||||
} elseif ($expiry <= $now) {
|
||||
$this->deleteItem($key);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
|
||||
return false;
|
||||
}
|
||||
if (null === $expiry && 0 < $this->defaultLifetime) {
|
||||
$expiry = $this->defaultLifetime;
|
||||
$expiry = $now + ($expiry > ($this->maxLifetime ?: $expiry) ? $this->maxLifetime : $expiry);
|
||||
} elseif ($this->maxLifetime && (null === $expiry || $expiry > $now + $this->maxLifetime)) {
|
||||
$expiry = $now + $this->maxLifetime;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
|
||||
return false;
|
||||
}
|
||||
if (null === $expiry && 0 < $this->defaultLifetime) {
|
||||
$expiry = $this->defaultLifetime;
|
||||
$expiry = $now + ($expiry > ($this->maxLifetime ?: $expiry) ? $this->maxLifetime : $expiry);
|
||||
} elseif ($this->maxLifetime && (null === $expiry || $expiry > $now + $this->maxLifetime)) {
|
||||
$expiry = $now + $this->maxLifetime;
|
||||
}
|
||||
|
||||
if ($this->maxItems) {
|
||||
unset($this->values[$key], $this->tags[$key]);
|
||||
if ($this->maxItems) {
|
||||
unset($this->values[$key], $this->tags[$key]);
|
||||
|
||||
// Iterate items and vacuum expired ones while we are at it
|
||||
foreach ($this->values as $k => $v) {
|
||||
if ($this->expiries[$k] > $now && \count($this->values) < $this->maxItems) {
|
||||
break;
|
||||
}
|
||||
// Iterate items and vacuum expired ones while we are at it
|
||||
foreach ($this->values as $k => $v) {
|
||||
if ($this->expiries[$k] > $now && \count($this->values) < $this->maxItems) {
|
||||
break;
|
||||
}
|
||||
|
||||
unset($this->values[$k], $this->tags[$k], $this->expiries[$k]);
|
||||
}
|
||||
}
|
||||
unset($this->values[$k], $this->tags[$k], $this->expiries[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->values[$key] = $value;
|
||||
$this->expiries[$key] = $expiry ?? \PHP_INT_MAX;
|
||||
$this->values[$key] = $value;
|
||||
$this->expiries[$key] = $expiry ?? \PHP_INT_MAX;
|
||||
|
||||
if (null === $this->tags[$key] = $item["\0*\0newMetadata"][CacheItem::METADATA_TAGS] ?? null) {
|
||||
unset($this->tags[$key]);
|
||||
}
|
||||
if (null === $this->tags[$key] = $item["\0*\0newMetadata"][CacheItem::METADATA_TAGS] ?? null) {
|
||||
unset($this->tags[$key]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function saveDeferred(CacheItemInterface $item): bool
|
||||
{
|
||||
return $this->save($item);
|
||||
}
|
||||
public function saveDeferred(CacheItemInterface $item): bool
|
||||
{
|
||||
return $this->save($item);
|
||||
}
|
||||
|
||||
public function commit(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function commit(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function clear(string $prefix = ''): bool
|
||||
{
|
||||
if ('' !== $prefix) {
|
||||
$now = microtime(true);
|
||||
public function clear(string $prefix = ''): bool
|
||||
{
|
||||
if ('' !== $prefix) {
|
||||
$now = microtime(true);
|
||||
|
||||
foreach ($this->values as $key => $value) {
|
||||
if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || str_starts_with($key, $prefix)) {
|
||||
unset($this->values[$key], $this->tags[$key], $this->expiries[$key]);
|
||||
}
|
||||
}
|
||||
foreach ($this->values as $key => $value) {
|
||||
if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || str_starts_with($key, $prefix)) {
|
||||
unset($this->values[$key], $this->tags[$key], $this->expiries[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->values) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($this->values) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->values = $this->tags = $this->expiries = [];
|
||||
$this->values = $this->tags = $this->expiries = [];
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all cached values, with cache miss as null.
|
||||
*/
|
||||
public function getValues(): array
|
||||
{
|
||||
if (!$this->storeSerialized) {
|
||||
return $this->values;
|
||||
}
|
||||
/**
|
||||
* Returns all cached values, with cache miss as null.
|
||||
*/
|
||||
public function getValues(): array
|
||||
{
|
||||
if (!$this->storeSerialized) {
|
||||
return $this->values;
|
||||
}
|
||||
|
||||
$values = $this->values;
|
||||
foreach ($values as $k => $v) {
|
||||
if (null === $v || 'N;' === $v) {
|
||||
continue;
|
||||
}
|
||||
if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
|
||||
$values[$k] = serialize($v);
|
||||
}
|
||||
}
|
||||
$values = $this->values;
|
||||
foreach ($values as $k => $v) {
|
||||
if (null === $v || 'N;' === $v) {
|
||||
continue;
|
||||
}
|
||||
if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) {
|
||||
$values[$k] = serialize($v);
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->clear();
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
private function generateItems(array $keys, float $now, \Closure $f): \Generator
|
||||
{
|
||||
foreach ($keys as $i => $key) {
|
||||
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
|
||||
$value = null;
|
||||
private function generateItems(array $keys, float $now, \Closure $f): \Generator
|
||||
{
|
||||
foreach ($keys as $i => $key) {
|
||||
if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) {
|
||||
$value = null;
|
||||
|
||||
if (!$this->maxItems) {
|
||||
// Track misses in non-LRU mode only
|
||||
$this->values[$key] = null;
|
||||
}
|
||||
} else {
|
||||
if ($this->maxItems) {
|
||||
// Move the item last in the storage
|
||||
$value = $this->values[$key];
|
||||
unset($this->values[$key]);
|
||||
$this->values[$key] = $value;
|
||||
}
|
||||
if (!$this->maxItems) {
|
||||
// Track misses in non-LRU mode only
|
||||
$this->values[$key] = null;
|
||||
}
|
||||
} else {
|
||||
if ($this->maxItems) {
|
||||
// Move the item last in the storage
|
||||
$value = $this->values[$key];
|
||||
unset($this->values[$key]);
|
||||
$this->values[$key] = $value;
|
||||
}
|
||||
|
||||
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
|
||||
}
|
||||
unset($keys[$i]);
|
||||
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
|
||||
}
|
||||
unset($keys[$i]);
|
||||
|
||||
yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null);
|
||||
}
|
||||
yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null);
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
yield $key => $f($key, null, false);
|
||||
}
|
||||
}
|
||||
foreach ($keys as $key) {
|
||||
yield $key => $f($key, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
private function freeze($value, string $key): string|int|float|bool|array|\UnitEnum|null
|
||||
{
|
||||
if (null === $value) {
|
||||
return 'N;';
|
||||
}
|
||||
if (\is_string($value)) {
|
||||
// Serialize strings if they could be confused with serialized objects or arrays
|
||||
if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
|
||||
return serialize($value);
|
||||
}
|
||||
} elseif (!\is_scalar($value)) {
|
||||
try {
|
||||
$serialized = serialize($value);
|
||||
} catch (\Exception $e) {
|
||||
if (!isset($this->expiries[$key])) {
|
||||
unset($this->values[$key]);
|
||||
}
|
||||
$type = get_debug_type($value);
|
||||
$message = \sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage());
|
||||
CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
|
||||
private function freeze($value, string $key): string|int|float|bool|array|\UnitEnum|null
|
||||
{
|
||||
if (null === $value) {
|
||||
return 'N;';
|
||||
}
|
||||
if (\is_string($value)) {
|
||||
// SerializeToDOMNode strings if they could be confused with serialized objects or arrays
|
||||
if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
|
||||
return serialize($value);
|
||||
}
|
||||
} elseif (!\is_scalar($value)) {
|
||||
try {
|
||||
$serialized = serialize($value);
|
||||
} catch (\Exception $e) {
|
||||
if (!isset($this->expiries[$key])) {
|
||||
unset($this->values[$key]);
|
||||
}
|
||||
$type = get_debug_type($value);
|
||||
$message = \sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage());
|
||||
CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
|
||||
|
||||
return null;
|
||||
}
|
||||
// Keep value serialized if it contains any objects or any internal references
|
||||
if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Keep value serialized if it contains any objects or any internal references
|
||||
if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) {
|
||||
return $serialized;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function unfreeze(string $key, bool &$isHit): mixed
|
||||
{
|
||||
if ('N;' === $value = $this->values[$key]) {
|
||||
return null;
|
||||
}
|
||||
if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
|
||||
try {
|
||||
$value = unserialize($value);
|
||||
} catch (\Exception $e) {
|
||||
CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
|
||||
$value = false;
|
||||
}
|
||||
if (false === $value) {
|
||||
$value = null;
|
||||
$isHit = false;
|
||||
private function unfreeze(string $key, bool &$isHit): mixed
|
||||
{
|
||||
if ('N;' === $value = $this->values[$key]) {
|
||||
return null;
|
||||
}
|
||||
if (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
|
||||
try {
|
||||
$value = unserialize($value);
|
||||
} catch (\Exception $e) {
|
||||
CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
|
||||
$value = false;
|
||||
}
|
||||
if (false === $value) {
|
||||
$value = null;
|
||||
$isHit = false;
|
||||
|
||||
if (!$this->maxItems) {
|
||||
$this->values[$key] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->maxItems) {
|
||||
$this->values[$key] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function validateKeys(array $keys): bool
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
if (!\is_string($key) || !isset($this->expiries[$key])) {
|
||||
CacheItem::validateKey($key);
|
||||
}
|
||||
}
|
||||
private function validateKeys(array $keys): bool
|
||||
{
|
||||
foreach ($keys as $key) {
|
||||
if (!\is_string($key) || !isset($this->expiries[$key])) {
|
||||
CacheItem::validateKey($key);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17291,7 +17291,7 @@ class TCPDF {
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize data to be used with TCPDF tag in HTML code.
|
||||
* SerializeToDOMNode data to be used with TCPDF tag in HTML code.
|
||||
* @param string $method TCPDF method name
|
||||
* @param array $params Method parameters
|
||||
* @return string Serialized data
|
||||
|
||||
@@ -49,9 +49,9 @@ class DashboardController extends Controller
|
||||
// TODO 3.3 This is not the place to register this service, do better please
|
||||
ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime());
|
||||
if (!empty($aValues)) {
|
||||
$oDashlet->FromDenormalizedParams($aValues);
|
||||
$oDashlet->FromModelData($aValues);
|
||||
} else {
|
||||
$aValues = $oDashlet->GetDenormalizedProperties();
|
||||
$aValues = $oDashlet->GetModelData();
|
||||
}
|
||||
|
||||
// TODO 3.3 Removing bEditMode for dashlet rendering fixes id having an "_edit" issues, but is it the right solution ?
|
||||
@@ -89,28 +89,27 @@ class DashboardController extends Controller
|
||||
|
||||
public function OperationSave()
|
||||
{
|
||||
$sValues = utils::ReadParam('values', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
$aValues = !empty($sValues) ? json_decode($sValues, true, 20) : [];
|
||||
$sStatus = 'error';
|
||||
$sMessage = 'Unknown error';
|
||||
$sViewData = utils::ReadParam('values', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
$aViewData = !empty($sViewData) ? json_decode($sViewData, true, 20) : [];
|
||||
|
||||
try {
|
||||
// Get the form block from the service (and the compiler)
|
||||
$oRequest = $this->getRequest();
|
||||
$oFormBlock = FormBlockService::GetInstance()->GetFormBlockById('DashboardGrid', 'Dashboard');
|
||||
$oBuilder = $this->GetFormBuilder($oFormBlock, $aValues);
|
||||
$oBuilder = $this->GetFormBuilder($oFormBlock, $aViewData);
|
||||
$oForm = $oBuilder->getForm();
|
||||
$oForm->handleRequest($oRequest);
|
||||
// We are in the submit action, so we submit the form with the provided values
|
||||
$oForm->submit($aValues);
|
||||
$oForm->submit($aViewData);
|
||||
|
||||
// TODO 3.3 Validate the form, it requires CSRF + stripping extra fields
|
||||
// See $oForm->getErrors(true) to get all errors
|
||||
if ($oForm->isSubmitted() && (true || $oForm->isValid())) {
|
||||
// Save XML
|
||||
$oDashboard = new RuntimeDashboard($aValues['id']);
|
||||
$aModelData = $oForm->getData();
|
||||
$oDashboard = new RuntimeDashboard($aModelData['id']);
|
||||
$oDomNode = $oDashboard->CreateEmptyDashboard();
|
||||
XMLSerializer::GetInstance()->Serialize($aValues, $oDomNode, 'DashboardGrid', 'Dashboard');
|
||||
XMLSerializer::GetInstance()->Serialize($aModelData, $oDomNode, 'DashboardGrid', 'Dashboard');
|
||||
$sXml = $oDomNode->ownerDocument->saveXML();
|
||||
$oDashboard->PersistDashboard($sXml);
|
||||
$sStatus = 'ok';
|
||||
|
||||
@@ -28,7 +28,7 @@ class DashboardLayoutGrid extends \DashboardLayout
|
||||
if ($oDashlet) {
|
||||
$sDashletId = $oDashlet->GetID();
|
||||
$sDashletClass = $oDashlet->GetDashletType();
|
||||
$aDashletDenormalizedProperties = $oDashlet->GetDenormalizedProperties();
|
||||
$aDashletDenormalizedProperties = $oDashlet->GetModelData();
|
||||
$aDashletsInfo = DashletService::GetInstance()->GetDashletDefinition($sDashletClass);
|
||||
|
||||
// Also set minimal height/width
|
||||
|
||||
@@ -944,7 +944,7 @@ JS
|
||||
*/
|
||||
private function GetDashletObjectListAppUserPreferencesPrefix(DashletObjectList $oDashlet, $aExtraParams, $sDashletId)
|
||||
{
|
||||
$sDataTableId = Dashlet::APPUSERPREFERENCES_PREFIX.$sDashletId;
|
||||
$sDataTableId = Dashlet::APP_USER_PREFERENCES_PREFIX.$sDashletId;
|
||||
$aClassAliases = [];
|
||||
try {
|
||||
$oFilter = $oDashlet->GetDBSearch($aExtraParams);
|
||||
|
||||
@@ -64,7 +64,7 @@ class DashletObjectList extends Dashlet
|
||||
$oBlock = new DisplayBlock($oFilter, 'list');
|
||||
$aParams = [
|
||||
'menu' => $sShowMenu,
|
||||
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
|
||||
'table_id' => self::APP_USER_PREFERENCES_PREFIX.$this->sId,
|
||||
'surround_with_panel' => true,
|
||||
'max_height' => '500px',
|
||||
"panel_title" => Dict::S($sTitle),
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
|
||||
namespace Combodo\iTop\Application\Dashlet;
|
||||
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Dashlet\DashletContainer;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Dashlet\DashletFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\iUIBlock;
|
||||
use Combodo\iTop\Application\UI\Base\UIBlock;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
@@ -38,7 +34,7 @@ use utils;
|
||||
abstract class Dashlet
|
||||
{
|
||||
/** @var string */
|
||||
public const APPUSERPREFERENCES_PREFIX = 'Dashlet';
|
||||
public const APP_USER_PREFERENCES_PREFIX = 'Dashlet';
|
||||
|
||||
protected $oModelReflection;
|
||||
protected $sId;
|
||||
@@ -203,9 +199,10 @@ abstract class Dashlet
|
||||
$this->OnUpdate();
|
||||
}
|
||||
|
||||
public function FromDenormalizedParams(array $aDenormalizedParams)
|
||||
public function FromModelData(array $aModelData)
|
||||
{
|
||||
$this->aProperties = XMLNormalizer::GetInstance()->Normalize($aDenormalizedParams, $this->sDashletType, 'Dashlet');
|
||||
$this->aProperties = $aModelData;
|
||||
// $this->aProperties = XMLNormalizer::GetInstance()->Normalize($aModelData, $this->sDashletType, 'Dashlet');
|
||||
$this->OnUpdate();
|
||||
}
|
||||
|
||||
@@ -331,7 +328,10 @@ EOF
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function GetPropertiesFields(\DesignerForm $oForm);
|
||||
public function GetPropertiesFields(\DesignerForm $oForm)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DOMNode $oContainerNode
|
||||
@@ -514,8 +514,9 @@ EOF
|
||||
$this->sDashletType = $sDashletType;
|
||||
}
|
||||
|
||||
public function GetDenormalizedProperties(): ?array
|
||||
public function GetModelData(): ?array
|
||||
{
|
||||
return XMLNormalizer::GetInstance()->Denormalize($this->aProperties, $this->sDashletType, 'Dashlet');
|
||||
return $this->aProperties;
|
||||
//return XMLNormalizer::GetInstance()->Denormalize($this->aProperties, $this->sDashletType, 'Dashlet');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,32 +72,11 @@ PHP;
|
||||
|
||||
public function SerializeToDOMNode(mixed $value, DesignElement$oDOMNode): void
|
||||
{
|
||||
$this->oValueType->SerializeToDOMNode($value, $oDOMNode);
|
||||
$this->oValueType->SerializeToDOMNode(null, $value, $oDOMNode);
|
||||
}
|
||||
|
||||
public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
return $this->oValueType->UnserializeFromDOMNode($oDOMNode);
|
||||
return $this->oValueType->DeserializeFromDOMNode($oDOMNode);
|
||||
}
|
||||
|
||||
public function Normalize(mixed $value): mixed
|
||||
{
|
||||
return $this->oValueType->Normalize($value);
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode): void
|
||||
{
|
||||
$this->oValueType->EncodeToDOMNode($normalizedValue, $oDOMNode);
|
||||
}
|
||||
|
||||
public function DecodeFromDomNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
return $this->oValueType->DecodeFromDomNode($oDOMNode);
|
||||
}
|
||||
|
||||
public function Denormalize(mixed $normalizedValue): mixed
|
||||
{
|
||||
return $this->oValueType->Denormalize($normalizedValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType\Serializer;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompiler;
|
||||
|
||||
class XMLEncoder
|
||||
{
|
||||
private static XMLEncoder $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): XMLEncoder
|
||||
{
|
||||
if (!isset(static::$oInstance)) {
|
||||
static::$oInstance = new XMLEncoder();
|
||||
}
|
||||
|
||||
return static::$oInstance;
|
||||
}
|
||||
|
||||
public function Encode(mixed $normalizedValue, DesignElement $oParentNode, string $sId, string $sType): void
|
||||
{
|
||||
$sPropertyTypeXML = PropertyTypeCompiler::GetInstance()->GetXMLContent($sId, $sType);
|
||||
|
||||
$this->EncodeForPropertyType($normalizedValue, $oParentNode, $sPropertyTypeXML);
|
||||
}
|
||||
|
||||
public function Decode(DesignElement $oDOMNode, string $sId, string $sType): mixed
|
||||
{
|
||||
$sPropertyTypeXML = PropertyTypeCompiler::GetInstance()->GetXMLContent($sId, $sType);
|
||||
|
||||
return $this->DecodeForPropertyType($oDOMNode, $sPropertyTypeXML);
|
||||
}
|
||||
|
||||
public function EncodeForPropertyType(mixed $normalizedValue, DesignElement $oParentNode, string $sPropertyTypeXML): void
|
||||
{
|
||||
$oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
|
||||
|
||||
$oPropertyType->EncodeToDOMNode($normalizedValue, $oParentNode);
|
||||
}
|
||||
|
||||
public function DecodeForPropertyType(DesignElement $oParentNode, string $sPropertyTypeXML): mixed
|
||||
{
|
||||
$oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
|
||||
|
||||
return $oPropertyType->DecodeFromDomNode($oParentNode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,11 +16,8 @@ abstract class AbstractXMLFormat
|
||||
{
|
||||
}
|
||||
|
||||
abstract public function Normalize($value, AbstractValueType $oValueType): mixed;
|
||||
abstract public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode, AbstractValueType $oValueType): void;
|
||||
|
||||
abstract public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode, AbstractValueType $oValueType): void;
|
||||
abstract public function DeserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed;
|
||||
|
||||
abstract public function DecodeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed;
|
||||
|
||||
abstract public function Denormalize($normalizedValue, AbstractValueType $oValueType): mixed;
|
||||
}
|
||||
|
||||
@@ -12,32 +12,20 @@ use Combodo\iTop\PropertyType\ValueType\AbstractValueType;
|
||||
|
||||
class XMLFormatCSV extends AbstractXMLFormat
|
||||
{
|
||||
public function Normalize($value, AbstractValueType $oValueType): mixed
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
if (is_array($normalizedValue)) {
|
||||
$normalizedValue = implode(',', $normalizedValue);
|
||||
if (is_null($sPropertyName)) {
|
||||
$oTextNode = $oDOMNode->ownerDocument->createTextNode(implode(',', $value));
|
||||
$oDOMNode->appendChild($oTextNode);
|
||||
} else {
|
||||
$oPropertyNode = $oDOMNode->ownerDocument->createElement($sPropertyName, implode(',', $value));
|
||||
$oDOMNode->appendChild($oPropertyNode);
|
||||
}
|
||||
$oTextNode = $oDOMNode->ownerDocument->createTextNode($normalizedValue);
|
||||
$oDOMNode->appendChild($oTextNode);
|
||||
}
|
||||
|
||||
public function DecodeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
$value = $oDOMNode->GetText('');
|
||||
return explode(',', $value);
|
||||
}
|
||||
|
||||
public function Denormalize($normalizedValue, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
if (is_string($normalizedValue)) {
|
||||
return explode(',', $normalizedValue);
|
||||
}
|
||||
|
||||
return $normalizedValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,35 +22,34 @@ class XMLFormatCollectionWithId extends AbstractXMLFormat
|
||||
$this->sTagName = $oDomNode->GetChildText('tag-name');
|
||||
}
|
||||
|
||||
public function Normalize($value, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
foreach ($normalizedValue as $sItemId => $aValues) {
|
||||
/** @var DesignElement $oNode */
|
||||
$oNode = $oDOMNode->ownerDocument->createElement($this->sTagName);
|
||||
$oNode->setAttribute('id', $sItemId);
|
||||
$oDOMNode->appendChild($oNode);
|
||||
if (!is_null($sPropertyName)) {
|
||||
$oPropertyNode = $oDOMNode->ownerDocument->createElement($sPropertyName);
|
||||
$oDOMNode->appendChild($oPropertyNode);
|
||||
} else {
|
||||
$oPropertyNode = $oDOMNode;
|
||||
}
|
||||
|
||||
foreach ($value as $sItemId => $aValues) {
|
||||
/** @var DesignElement $oItemNode */
|
||||
$oItemNode = $oPropertyNode->ownerDocument->createElement($this->sTagName);
|
||||
$oItemNode->setAttribute('id', $sItemId);
|
||||
$oPropertyNode->appendChild($oItemNode);
|
||||
foreach ($oValueType->GetChildren() as $oChild) {
|
||||
$sPropertyId = $oChild->GetId();
|
||||
if (isset($aValues[$sPropertyId])) {
|
||||
/** @var DesignElement $oSubNode */
|
||||
$oSubNode = $oDOMNode->ownerDocument->createElement($sPropertyId);
|
||||
$oNode->appendChild($oSubNode);
|
||||
$oChild->EncodeToDOMNode($aValues[$sPropertyId], $oSubNode);
|
||||
$oChild->SerializeToDOMNode($sPropertyId, $aValues[$sPropertyId], $oItemNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function DecodeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
@@ -63,16 +62,11 @@ class XMLFormatCollectionWithId extends AbstractXMLFormat
|
||||
$sItemId = $oNode->getAttribute('id');
|
||||
$aSubArray = [];
|
||||
foreach ($oValueType->GetChildren() as $oChild) {
|
||||
$aSubArray[$oChild->GetId()] = $oChild->DecodeFromDomNode($oNode->GetUniqueElement($oChild->GetId()));
|
||||
$aSubArray[$oChild->GetId()] = $oChild->DeserializeFromDOMNode($oNode->GetUniqueElement($oChild->GetId()));
|
||||
}
|
||||
$aNormalizedValues[$sItemId] = $aSubArray;
|
||||
}
|
||||
|
||||
return $aNormalizedValues;
|
||||
}
|
||||
|
||||
public function Denormalize($normalizedValue, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
return $normalizedValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,14 +33,36 @@ class XMLFormatFlatArray extends AbstractXMLFormat
|
||||
$this->sCountTag = $sCountTag;
|
||||
}
|
||||
|
||||
public function UnserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
$aResults = [];
|
||||
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
$oNode = $oDOMNode->ownerDocument->createElement($this->sCountTag, count($value));
|
||||
$oDOMNode->appendChild($oNode);
|
||||
|
||||
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]);
|
||||
|
||||
$oNode = $oDOMNode->ownerDocument->createElement($sTagName, $aValues[$sId]);
|
||||
$oDOMNode->appendChild($oNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
$aResults = [];
|
||||
|
||||
$iCount = $oDOMNode->GetUniqueElement($this->sCountTag)->GetText(0);
|
||||
for ($iRank = 0; $iRank < $iCount; $iRank++) {
|
||||
foreach ($oValueType->GetChildren() as $oChild) {
|
||||
@@ -55,85 +77,4 @@ class XMLFormatFlatArray extends AbstractXMLFormat
|
||||
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
public function Normalize($value, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
$aNormalizedValues = [];
|
||||
$aNormalizedValues[$this->sCountTag] = count($value);
|
||||
|
||||
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]);
|
||||
$aNormalizedValues[$sTagName] = $oChild->Normalize($aValues[$sId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aNormalizedValues;
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
foreach ($normalizedValue as $sTag => $value) {
|
||||
$oNode = $oDOMNode->ownerDocument->createElement($sTag, $value);
|
||||
$oDOMNode->appendChild($oNode);
|
||||
}
|
||||
}
|
||||
|
||||
public function DecodeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
$aNormalizedValues = [];
|
||||
|
||||
$iCount = $oDOMNode->GetUniqueElement($this->sCountTag)->GetText(0);
|
||||
$aNormalizedValues[$this->sCountTag] = $iCount;
|
||||
|
||||
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) {
|
||||
$aNormalizedValues[$sTagName] = $oChildNode->GetText('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aNormalizedValues;
|
||||
}
|
||||
|
||||
public function Denormalize($normalizedValue, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
if (!$oValueType instanceof ValueTypeCollection) {
|
||||
throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes');
|
||||
}
|
||||
|
||||
$aValues = [];
|
||||
|
||||
$iCount = $normalizedValue[$this->sCountTag];
|
||||
for ($iRank = 0; $iRank < $iCount; $iRank++) {
|
||||
foreach ($oValueType->GetChildren() as $oChild) {
|
||||
$sId = $oChild->GetId();
|
||||
$sTagName = \MetaModel::ApplyParams($this->sTagFormat, ['rank' => $iRank, 'id' => $sId]);
|
||||
if (isset($normalizedValue[$sTagName])) {
|
||||
$aValues[$iRank][$sId] = $normalizedValue[$sTagName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,55 +25,36 @@ class XMLFormatValueAsId extends AbstractXMLFormat
|
||||
$this->sTagName = $sTagName;
|
||||
}
|
||||
|
||||
public function SerializeToDOMNode($value, $oDOMNode, AbstractValueType $oValueType): void
|
||||
public function SerializeToDOMNode(?string $sPropertyName, $value, $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
if (!is_null($sPropertyName)) {
|
||||
$oPropertyNode = $oDOMNode->ownerDocument->createElement($sPropertyName);
|
||||
$oDOMNode->appendChild($oPropertyNode);
|
||||
} else {
|
||||
$oPropertyNode = $oDOMNode;
|
||||
}
|
||||
foreach ($value as $item) {
|
||||
$oChildNode = $oDOMNode->ownerDocument->createElement($this->sTagName);
|
||||
$oChildNode->setAttribute('id', "$item");
|
||||
$oDOMNode->appendChild($oChildNode);
|
||||
$oPropertyNode->appendChild($oChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
public function UnserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
$aResult = [];
|
||||
|
||||
foreach ($oDOMNode->getElementsByTagName($this->sTagName) as $oNode) {
|
||||
foreach ($oDOMNode->childNodes as $oNode) {
|
||||
if (!$oNode instanceof DesignElement) {
|
||||
continue;
|
||||
}
|
||||
if ($oNode->tagName !== $this->sTagName) {
|
||||
continue;
|
||||
}
|
||||
$sValue = $oNode->getAttribute('id');
|
||||
$aResult[] = $sValue;
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function Normalize($value, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode, AbstractValueType $oValueType): void
|
||||
{
|
||||
foreach ($normalizedValue as $item) {
|
||||
$oChildNode = $oDOMNode->ownerDocument->createElement($this->sTagName);
|
||||
$oChildNode->setAttribute('id', "$item");
|
||||
$oDOMNode->appendChild($oChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
public function DecodeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
$aResult = [];
|
||||
|
||||
foreach ($oDOMNode->getElementsByTagName($this->sTagName) as $oNode) {
|
||||
$sValue = $oNode->getAttribute('id');
|
||||
$aResult[] = $sValue;
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function Denormalize($normalizedValue, AbstractValueType $oValueType): mixed
|
||||
{
|
||||
return $normalizedValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\PropertyType\Serializer;
|
||||
|
||||
use Combodo\iTop\DesignElement;
|
||||
use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompiler;
|
||||
|
||||
class XMLNormalizer
|
||||
{
|
||||
private static XMLNormalizer $oInstance;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
final public static function GetInstance(): XMLNormalizer
|
||||
{
|
||||
if (!isset(static::$oInstance)) {
|
||||
static::$oInstance = new XMLNormalizer();
|
||||
}
|
||||
|
||||
return static::$oInstance;
|
||||
}
|
||||
|
||||
public function Normalize(mixed $value, string $sId, string $sType): mixed
|
||||
{
|
||||
$sPropertyTypeXML = PropertyTypeCompiler::GetInstance()->GetXMLContent($sId, $sType);
|
||||
|
||||
return $this->NormalizeForPropertyType($value, $sPropertyTypeXML);
|
||||
}
|
||||
|
||||
public function Denormalize(mixed $normalizedValue, string $sId, string $sType): mixed
|
||||
{
|
||||
$sPropertyTypeXML = PropertyTypeCompiler::GetInstance()->GetXMLContent($sId, $sType);
|
||||
|
||||
return $this->DenormalizeForPropertyType($normalizedValue, $sPropertyTypeXML);
|
||||
}
|
||||
|
||||
public function NormalizeForPropertyType(mixed $normalizedValue, string $sPropertyTypeXML): mixed
|
||||
{
|
||||
$oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
|
||||
|
||||
return $oPropertyType->Normalize($normalizedValue);
|
||||
}
|
||||
|
||||
public function DenormalizeForPropertyType(mixed $normalizedValue, string $sPropertyTypeXML): mixed
|
||||
{
|
||||
$oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
|
||||
|
||||
return $oPropertyType->Denormalize($normalizedValue);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,15 +45,15 @@ class XMLSerializer
|
||||
|
||||
public function SerializeForPropertyType(mixed $value, DesignElement $oParentNode, string $sPropertyTypeXML): void
|
||||
{
|
||||
$normalizedValue = XMLNormalizer::GetInstance()->NormalizeForPropertyType($value, $sPropertyTypeXML);
|
||||
$oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
|
||||
|
||||
XMLEncoder::GetInstance()->EncodeForPropertyType($normalizedValue, $oParentNode, $sPropertyTypeXML);
|
||||
$oPropertyType->SerializeToDOMNode($value, $oParentNode);
|
||||
}
|
||||
|
||||
public function DeserializeForPropertyType(DesignElement $oParentNode, string $sPropertyTypeXML): mixed
|
||||
{
|
||||
$normalizedValue = XMLEncoder::GetInstance()->DecodeForPropertyType($oParentNode, $sPropertyTypeXML);
|
||||
$oPropertyType = PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sPropertyTypeXML);
|
||||
|
||||
return XMLNormalizer::GetInstance()->DenormalizeForPropertyType($normalizedValue, $sPropertyTypeXML);
|
||||
return $oPropertyType->DeserializeFromDOMNode($oParentNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,24 +233,19 @@ PHP;
|
||||
return $this->oParent->GetChild($sId);
|
||||
}
|
||||
|
||||
public function Normalize(mixed $value): mixed
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement$oDOMNode): void
|
||||
{
|
||||
return $value;
|
||||
if (is_null($sPropertyName)) {
|
||||
$oTextNode = $oDOMNode->ownerDocument->createTextNode($value);
|
||||
$oDOMNode->appendChild($oTextNode);
|
||||
} else {
|
||||
$oPropertyNode = $oDOMNode->ownerDocument->createElement($sPropertyName, $value);
|
||||
$oDOMNode->appendChild($oPropertyNode);
|
||||
}
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode): void
|
||||
{
|
||||
$oTextNode = $oDOMNode->ownerDocument->createTextNode($normalizedValue);
|
||||
$oDOMNode->appendChild($oTextNode);
|
||||
}
|
||||
|
||||
public function DecodeFromDomNode(DesignElement $oDOMNode): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
return $oDOMNode->GetText();
|
||||
}
|
||||
|
||||
public function Denormalize(mixed $normalizedValue): mixed
|
||||
{
|
||||
return $normalizedValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,23 +82,13 @@ class ValueTypeCollection extends ValueTypePropertyTree
|
||||
return $this->GetLocalPHPForValueType();
|
||||
}
|
||||
|
||||
public function Normalize(mixed $value): mixed
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement$oDOMNode): void
|
||||
{
|
||||
return $this->oXMLFormat->Normalize($value, $this);
|
||||
$this->oXMLFormat->SerializeToDOMNode($sPropertyName, $value, $oDOMNode, $this);
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode): void
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
$this->oXMLFormat->EncodeToDOMNode($normalizedValue, $oDOMNode, $this);
|
||||
}
|
||||
|
||||
public function DecodeFromDomNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
return $this->oXMLFormat->DecodeFromDOMNode($oDOMNode, $this);
|
||||
}
|
||||
|
||||
public function Denormalize(mixed $normalizedValue): mixed
|
||||
{
|
||||
return $this->oXMLFormat->Denormalize($normalizedValue, $this);
|
||||
return $this->oXMLFormat->DeserializeFromDOMNode($oDOMNode, $this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,25 +29,32 @@ class ValueTypePolymorphic extends AbstractBranchValueType
|
||||
return "// ValueTypePolymorphic Block\n";
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode): void
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode): void
|
||||
{
|
||||
$sType = $normalizedValue['type'];
|
||||
$oDOMNode->setAttribute('xsi:type', $sType);
|
||||
if (!is_null($sPropertyName)) {
|
||||
$oPropertyNode = $oDOMNode->ownerDocument->createElement($sPropertyName);
|
||||
$oDOMNode->appendChild($oPropertyNode);
|
||||
} else {
|
||||
$oPropertyNode = $oDOMNode;
|
||||
}
|
||||
|
||||
$sType = $value['type'];
|
||||
$oPropertyNode->setAttribute('xsi:type', $sType);
|
||||
|
||||
$oPropertyType = PropertyTypeService::GetInstance()->GetPropertyType($sType);
|
||||
|
||||
$aProperties = $normalizedValue['properties'];
|
||||
$oPropertyType->EncodeToDOMNode($aProperties, $oDOMNode);
|
||||
$aProperties = $value['properties'];
|
||||
$oPropertyType->SerializeToDOMNode($aProperties, $oPropertyNode);
|
||||
}
|
||||
|
||||
public function DecodeFromDomNode(DesignElement $oDOMNode): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
$sType = $oDOMNode->getAttribute('xsi:type');
|
||||
$oPropertyType = PropertyTypeService::GetInstance()->GetPropertyType($sType);
|
||||
|
||||
return [
|
||||
'type' => $sType,
|
||||
'properties' => $oPropertyType->DecodeFromDOMNode($oDOMNode),
|
||||
'properties' => $oPropertyType->DeserializeFromDOMNode($oDOMNode),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,20 +75,23 @@ PHP;
|
||||
return $this->GetLocalPHPForValueType($this->sSubTreeClass);
|
||||
}
|
||||
|
||||
public function SerializeToDOMNode(mixed $value, DesignElement $oDOMNode): void
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode): void
|
||||
{
|
||||
if (!is_null($sPropertyName)) {
|
||||
$oPropertyNode = $oDOMNode->ownerDocument->createElement($sPropertyName);
|
||||
$oDOMNode->appendChild($oPropertyNode);
|
||||
} else {
|
||||
$oPropertyNode = $oDOMNode;
|
||||
}
|
||||
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);
|
||||
$oChild->SerializeToDOMNode($sId, $value[$sId], $oPropertyNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function UnserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
$aResults = [];
|
||||
|
||||
@@ -96,66 +99,13 @@ PHP;
|
||||
$sId = $oChild->sId;
|
||||
$oChildNode = $oDOMNode->GetOptionalElement($sId);
|
||||
if ($oChildNode) {
|
||||
$aResults[$sId] = $oChild->UnserializeFromDOMNode($oChildNode);
|
||||
$aResults[$sId] = $oChild->DeserializeFromDOMNode($oChildNode);
|
||||
} else {
|
||||
// For flat arrays, no node with $sId is present
|
||||
$aResults[$sId] = $oChild->DeserializeFromDOMNode($oDOMNode);
|
||||
}
|
||||
}
|
||||
|
||||
return $aResults;
|
||||
}
|
||||
|
||||
public function Normalize(mixed $value): mixed
|
||||
{
|
||||
$aNormalizedValues = [];
|
||||
|
||||
foreach ($this->aChildren as $oChild) {
|
||||
$sId = $oChild->sId;
|
||||
if (isset($value[$sId])) {
|
||||
$aNormalizedValues[$sId] = $oChild->Normalize($value[$sId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $aNormalizedValues;
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode): void
|
||||
{
|
||||
foreach ($this->aChildren as $oChild) {
|
||||
$sId = $oChild->sId;
|
||||
if (isset($normalizedValue[$sId])) {
|
||||
/** @var DesignElement $oChildNode */
|
||||
$oChildNode = $oDOMNode->ownerDocument->createElement($sId);
|
||||
$oDOMNode->appendChild($oChildNode);
|
||||
$oChild->EncodeToDOMNode($normalizedValue[$sId], $oChildNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function DecodeFromDomNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
$aNormalizedValue = [];
|
||||
|
||||
foreach ($this->aChildren as $oChild) {
|
||||
$sId = $oChild->sId;
|
||||
$oChildNode = $oDOMNode->GetOptionalElement($sId);
|
||||
if ($oChildNode) {
|
||||
$aNormalizedValue[$sId] = $oChild->DecodeFromDomNode($oChildNode);
|
||||
}
|
||||
}
|
||||
|
||||
return $aNormalizedValue;
|
||||
}
|
||||
|
||||
public function Denormalize(mixed $normalizedValue): mixed
|
||||
{
|
||||
$aValues = [];
|
||||
|
||||
foreach ($this->aChildren as $oChild) {
|
||||
$sId = $oChild->sId;
|
||||
if (isset($normalizedValue[$sId])) {
|
||||
$aValues[$sId] = $oChild->Denormalize($normalizedValue[$sId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $aValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,23 +54,13 @@ class ValueTypeCollectionOfValues extends AbstractLeafValueType
|
||||
return $this->oRealValueType->ToPHPFormBlock($aPHPFragments);
|
||||
}
|
||||
|
||||
public function Normalize(mixed $value): mixed
|
||||
public function SerializeToDOMNode(?string $sPropertyName, mixed $value, DesignElement $oDOMNode): void
|
||||
{
|
||||
return $this->oXMLFormat->Normalize($value, $this);
|
||||
$this->oXMLFormat->SerializeToDOMNode($sPropertyName, $value, $oDOMNode, $this);
|
||||
}
|
||||
|
||||
public function EncodeToDOMNode(mixed $normalizedValue, DesignElement $oDOMNode): void
|
||||
public function DeserializeFromDOMNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
$this->oXMLFormat->EncodeToDOMNode($normalizedValue, $oDOMNode, $this);
|
||||
}
|
||||
|
||||
public function DecodeFromDomNode(DesignElement $oDOMNode): mixed
|
||||
{
|
||||
return $this->oXMLFormat->DecodeFromDOMNode($oDOMNode, $this);
|
||||
}
|
||||
|
||||
public function Denormalize(mixed $normalizedValue): mixed
|
||||
{
|
||||
return $this->oXMLFormat->Denormalize($normalizedValue, $this);
|
||||
return $this->oXMLFormat->DeserializeFromDOMNode($oDOMNode, $this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\PropertyType\Compiler\PropertyTypeCompiler;
|
||||
use Combodo\iTop\PropertyType\PropertyTypeDesign;
|
||||
use Combodo\iTop\Service\DependencyInjection\ServiceLocator;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
class XMLNormalizerTest extends ItopDataTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider XMLNormalizerProvider
|
||||
*
|
||||
* @param $denormalizedValue
|
||||
* @param string $sPropertyTypeXML
|
||||
* @param string $normalizedValue
|
||||
*
|
||||
* @return void
|
||||
* @throws \DOMException
|
||||
*/
|
||||
public function testNormalizeXML($denormalizedValue, string $sPropertyTypeXML, $normalizedValue)
|
||||
{
|
||||
ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime());
|
||||
|
||||
$oDOMDocument = new PropertyTypeDesign();
|
||||
$oDOMDocument->preserveWhiteSpace = false;
|
||||
$oDOMDocument->formatOutput = true;
|
||||
|
||||
/** @var \Combodo\iTop\DesignElement $oRootNode */
|
||||
$oRootNode = $oDOMDocument->createElement('root');
|
||||
$oDOMDocument->appendChild($oRootNode);
|
||||
|
||||
$actualValue = Combodo\iTop\PropertyType\Serializer\XMLNormalizer::GetInstance()->NormalizeForPropertyType($denormalizedValue, $sPropertyTypeXML);
|
||||
|
||||
$this->assertEquals($normalizedValue, $actualValue);
|
||||
}
|
||||
|
||||
public function XMLNormalizerProvider()
|
||||
{
|
||||
return [
|
||||
'Basic test should serialize to XML' => [
|
||||
'denormalizedValue' => 'text',
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="basic_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-Label">
|
||||
</definition>
|
||||
</property_type>
|
||||
XML,
|
||||
'normalizedValue' => 'text',
|
||||
],
|
||||
'Collection of values as CSV' => [
|
||||
'denormalizedValue' => ['Contact', 'Organization'],
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="basic_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-CollectionOfValues">
|
||||
<xml-format xsi:type="Combodo-XMLFormat-CSV"/>
|
||||
<value-type xsi:type="Combodo-ValueType-Class">
|
||||
</value-type>
|
||||
</definition>
|
||||
</property_type>
|
||||
XML,
|
||||
'normalizedValue' => ['Contact', 'Organization'],
|
||||
],
|
||||
'Collection of values as id attribute' => [
|
||||
'denormalizedValue' => ['Contact', 'Organization'],
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="class_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-CollectionOfValues">
|
||||
<xml-format xsi:type="Combodo-XMLFormat-ValueAsId">
|
||||
<tag-name>item</tag-name>
|
||||
</xml-format>
|
||||
<value-type xsi:type="Combodo-ValueType-Class">
|
||||
</value-type>
|
||||
</definition>
|
||||
</property_type>
|
||||
XML,
|
||||
'normalizedValue' => ['Contact', 'Organization'],
|
||||
],
|
||||
'Collection of tree as flat array' => [
|
||||
'denormalizedValue' => [
|
||||
[
|
||||
'title_property' => 'title_a',
|
||||
'class_property' => 'class_a',
|
||||
],
|
||||
[
|
||||
'title_property' => 'title_b',
|
||||
'class_property' => 'class_b',
|
||||
],
|
||||
],
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="collection_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-Collection">
|
||||
<xml-format xsi:type="Combodo-XMLFormat-FlatArray">
|
||||
<count-tag>item_count</count-tag>
|
||||
<tag-format>item_\$rank\$_\$id\$</tag-format>
|
||||
</xml-format>
|
||||
<prototype>
|
||||
<node id="title_property" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:BasicTest:Prop-Title</label>
|
||||
</node>
|
||||
<node id="class_property" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:BasicTest:Prop-Class</label>
|
||||
<categories-csv>test</categories-csv>
|
||||
</node>
|
||||
</prototype>
|
||||
</definition>
|
||||
</property_type>
|
||||
XML,
|
||||
'normalizedValue' => [
|
||||
'item_count' => 2,
|
||||
'item_0_title_property' => 'title_a',
|
||||
'item_0_class_property' => 'class_a',
|
||||
'item_1_title_property' => 'title_b',
|
||||
'item_1_class_property' => 'class_b',
|
||||
],
|
||||
],
|
||||
'Property tree' => [
|
||||
'denormalizedValue' => ['title_property' => 'title', 'class_property' => 'class'],
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="property_tree_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="title_property" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:BasicTest:Prop-Title</label>
|
||||
</node>
|
||||
<node id="class_property" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:BasicTest:Prop-Class</label>
|
||||
<categories-csv>test</categories-csv>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
XML,
|
||||
'normalizedValue' => ['title_property' => 'title', 'class_property' => 'class'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider XMLNormalizerProvider
|
||||
*
|
||||
* @param $sInputXMLContent
|
||||
* @param string $sPropertyTypeXML
|
||||
* @param $expectedValue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDenormalizeXML($denormalizedValue, string $sPropertyTypeXML, $normalizedValue)
|
||||
{
|
||||
ServiceLocator::GetInstance()->RegisterService('ModelReflection', new ModelReflectionRuntime());
|
||||
|
||||
$aActualValue = Combodo\iTop\PropertyType\Serializer\XMLNormalizer::GetInstance()->DenormalizeForPropertyType($normalizedValue, $sPropertyTypeXML);
|
||||
|
||||
$this->assertEquals($denormalizedValue, $aActualValue);
|
||||
}
|
||||
}
|
||||
@@ -145,21 +145,40 @@ XML,
|
||||
</root>
|
||||
XML,
|
||||
],
|
||||
'Property tree' => [
|
||||
'normalizedValue' => ['title_property' => 'title', 'class_property' => 'class'],
|
||||
'Collection of tree as flat array in a property tree' => [
|
||||
'normalizedValue' => [
|
||||
'collection' => [
|
||||
[
|
||||
'title_property' => 'title_a',
|
||||
'class_property' => 'class_a',
|
||||
],
|
||||
[
|
||||
'title_property' => 'title_b',
|
||||
'class_property' => 'class_b',
|
||||
],
|
||||
],
|
||||
],
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="property_tree_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<property_type id="collection_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="title_property" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:BasicTest:Prop-Title</label>
|
||||
</node>
|
||||
<node id="class_property" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:BasicTest:Prop-Class</label>
|
||||
<categories-csv>test</categories-csv>
|
||||
</node>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="collection" xsi:type="Combodo-ValueType-Collection">
|
||||
<xml-format xsi:type="Combodo-XMLFormat-FlatArray">
|
||||
<count-tag>item_count</count-tag>
|
||||
<tag-format>item_\$rank\$_\$id\$</tag-format>
|
||||
</xml-format>
|
||||
<prototype>
|
||||
<node id="title_property" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:BasicTest:Prop-Title</label>
|
||||
</node>
|
||||
<node id="class_property" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:BasicTest:Prop-Class</label>
|
||||
<categories-csv>test</categories-csv>
|
||||
</node>
|
||||
</prototype>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
@@ -167,8 +186,11 @@ XML,
|
||||
'sXMLContent' => <<<XML
|
||||
<?xml version="1.0"?>
|
||||
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<title_property>title</title_property>
|
||||
<class_property>class</class_property>
|
||||
<item_count>2</item_count>
|
||||
<item_0_title_property>title_a</item_0_title_property>
|
||||
<item_0_class_property>class_a</item_0_class_property>
|
||||
<item_1_title_property>title_b</item_1_title_property>
|
||||
<item_1_class_property>class_b</item_1_class_property>
|
||||
</root>
|
||||
XML,
|
||||
],
|
||||
@@ -243,6 +265,79 @@ XML,
|
||||
<class_property>class_b</class_property>
|
||||
</item>
|
||||
</root>
|
||||
XML,
|
||||
],
|
||||
'Property tree' => [
|
||||
'normalizedValue' => [
|
||||
'title_property' => 'title',
|
||||
'sub_tree' => [
|
||||
'sub_tree_property' => 'my_class',
|
||||
],
|
||||
'items' => [
|
||||
'a' => [
|
||||
'title_property' => 'title_a',
|
||||
'class_property' => 'class_a',
|
||||
],
|
||||
'b' => [
|
||||
'title_property' => 'title_b',
|
||||
'class_property' => 'class_b',
|
||||
],
|
||||
],
|
||||
],
|
||||
'sPropertyTypeXML' => <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<property_type id="property_tree_test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Combodo-PropertyType" xsi:noNamespaceSchemaLocation = "https://www.combodo.com/itop-schema/3.3">
|
||||
<extends>Dashlet</extends>
|
||||
<definition xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<nodes>
|
||||
<node id="title_property" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:BasicTest:Prop-Title</label>
|
||||
</node>
|
||||
<node id="sub_tree" xsi:type="Combodo-ValueType-PropertyTree">
|
||||
<label>My sub tree</label>
|
||||
<nodes>
|
||||
<node id="sub_tree_property" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:BasicTest:Prop-Class</label>
|
||||
<categories-csv>test</categories-csv>
|
||||
</node>
|
||||
</nodes>
|
||||
</node>
|
||||
<node id="items" xsi:type="Combodo-ValueType-Collection">
|
||||
<xml-format xsi:type="Combodo-XMLFormat-CollectionWithId">
|
||||
<tag-name>item</tag-name>
|
||||
</xml-format>
|
||||
<prototype>
|
||||
<node id="title_property" xsi:type="Combodo-ValueType-Label">
|
||||
<label>UI:BasicTest:Prop-Title</label>
|
||||
</node>
|
||||
<node id="class_property" xsi:type="Combodo-ValueType-Class">
|
||||
<label>UI:BasicTest:Prop-Class</label>
|
||||
<categories-csv>test</categories-csv>
|
||||
</node>
|
||||
</prototype>
|
||||
</node>
|
||||
</nodes>
|
||||
</definition>
|
||||
</property_type>
|
||||
XML,
|
||||
'sXMLContent' => <<<XML
|
||||
<?xml version="1.0"?>
|
||||
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<title_property>title</title_property>
|
||||
<sub_tree>
|
||||
<sub_tree_property>my_class</sub_tree_property>
|
||||
</sub_tree>
|
||||
<items>
|
||||
<item id="a">
|
||||
<title_property>title_a</title_property>
|
||||
<class_property>class_a</class_property>
|
||||
</item>
|
||||
<item id="b">
|
||||
<title_property>title_b</title_property>
|
||||
<class_property>class_b</class_property>
|
||||
</item>
|
||||
</items>
|
||||
</root>
|
||||
XML,
|
||||
],
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user