diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 834c6f3687..861f1e6882 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -308,7 +308,11 @@ abstract class Dashboard public function Save() { + } + public function PersistDashboard(string $sXml): bool + { + return true; } /** @@ -771,6 +775,26 @@ class RuntimeDashboard extends Dashboard public function Save() { $sXml = $this->ToXml(); + + return $this->PersistDashboard($sXml); + } + + /** + * @param string $sXml + * + * @return bool + * @throws \ArchivedObjectException + * @throws \CoreCannotSaveObjectException + * @throws \CoreException + * @throws \CoreUnexpectedValue + * @throws \CoreWarning + * @throws \MissingQueryArgument + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + * @throws \OQLException + */ + public function PersistDashboard(string $sXml): bool + { $oUDSearch = new DBObjectSearch('UserDashboard'); $oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '='); $oUDSearch->AddCondition('menu_code', $this->sId, '='); diff --git a/application/datamodel.application.xml b/application/datamodel.application.xml index dcd93fecf7..4676c5e470 100644 --- a/application/datamodel.application.xml +++ b/application/datamodel.application.xml @@ -852,6 +852,70 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att + + + Dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pos_dashlet + + + + + + + + + + + + + + + + + + Dashlet + + + + + + + Dashlet diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 4de2c60493..ab427b4456 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -500,6 +500,7 @@ return array( 'Combodo\\iTop\\Forms\\Block\\Base\\HiddenFormBlock' => $baseDir . '/sources/Forms/Block/Base/HiddenFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\IntegerFormBlock' => $baseDir . '/sources/Forms/Block/Base/IntegerFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\NumberFormBlock' => $baseDir . '/sources/Forms/Block/Base/NumberFormBlock.php', + 'Combodo\\iTop\\Forms\\Block\\Base\\PolymorphicFormBlock' => $baseDir . '/sources/Forms/Block/Base/PolymorphicFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\TextAreaFormBlock' => $baseDir . '/sources/Forms/Block/Base/TextAreaFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\TextFormBlock' => $baseDir . '/sources/Forms/Block/Base/TextFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeChoiceFormBlock' => $baseDir . '/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php', @@ -570,6 +571,7 @@ return array( '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', @@ -578,6 +580,7 @@ return array( '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', + 'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\ValueTypePolymorphic' => $baseDir . '/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php', 'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\ValueTypePropertyTree' => $baseDir . '/sources/PropertyType/ValueType/Branch/ValueTypePropertyTree.php', 'Combodo\\iTop\\PropertyType\\ValueType\\Leaf\\AbstractLeafValueType' => $baseDir . '/sources/PropertyType/ValueType/Leaf/AbstractLeafValueType.php', 'Combodo\\iTop\\PropertyType\\ValueType\\Leaf\\ValueTypeAggregateFunction' => $baseDir . '/sources/PropertyType/ValueType/Leaf/ValueTypeAggregateFunction.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index f5032b3df1..b717847b60 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -28,12 +28,12 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f ); public static $prefixLengthsPsr4 = array ( - 'T' => + 'T' => array ( 'Twig\\' => 5, 'TheNetworg\\OAuth2\\Client\\' => 25, ), - 'S' => + 'S' => array ( 'Symfony\\Polyfill\\Php83\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, @@ -82,7 +82,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'ScssPhp\\ScssPhp\\' => 16, 'Sabberworm\\CSS\\' => 15, ), - 'P' => + 'P' => array ( 'Psr\\Log\\' => 8, 'Psr\\Http\\Message\\' => 17, @@ -93,298 +93,298 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'PhpParser\\' => 10, 'Pelago\\Emogrifier\\' => 18, ), - 'L' => + 'L' => array ( 'League\\OAuth2\\Client\\' => 21, ), - 'G' => + 'G' => array ( 'GuzzleHttp\\Psr7\\' => 16, 'GuzzleHttp\\Promise\\' => 19, 'GuzzleHttp\\' => 11, ), - 'F' => + 'F' => array ( 'Firebase\\JWT\\' => 13, ), - 'E' => + 'E' => array ( 'Egulias\\EmailValidator\\' => 23, ), - 'D' => + 'D' => array ( 'Doctrine\\Common\\Lexer\\' => 22, ), ); public static $prefixDirsPsr4 = array ( - 'Twig\\' => + 'Twig\\' => array ( 0 => __DIR__ . '/..' . '/twig/twig/src', ), - 'TheNetworg\\OAuth2\\Client\\' => + 'TheNetworg\\OAuth2\\Client\\' => array ( 0 => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src', ), - 'Symfony\\Polyfill\\Php83\\' => + 'Symfony\\Polyfill\\Php83\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php83', ), - 'Symfony\\Polyfill\\Mbstring\\' => + 'Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), - 'Symfony\\Polyfill\\Intl\\Normalizer\\' => + 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer', ), - 'Symfony\\Polyfill\\Intl\\Idn\\' => + 'Symfony\\Polyfill\\Intl\\Idn\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', ), - 'Symfony\\Polyfill\\Intl\\Icu\\' => + 'Symfony\\Polyfill\\Intl\\Icu\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-icu', ), - 'Symfony\\Polyfill\\Intl\\Grapheme\\' => + 'Symfony\\Polyfill\\Intl\\Grapheme\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme', ), - 'Symfony\\Polyfill\\Ctype\\' => + 'Symfony\\Polyfill\\Ctype\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', ), - 'Symfony\\Contracts\\Translation\\' => + 'Symfony\\Contracts\\Translation\\' => array ( 0 => __DIR__ . '/..' . '/symfony/translation-contracts', ), - 'Symfony\\Contracts\\Service\\' => + 'Symfony\\Contracts\\Service\\' => array ( 0 => __DIR__ . '/..' . '/symfony/service-contracts', ), - 'Symfony\\Contracts\\EventDispatcher\\' => + 'Symfony\\Contracts\\EventDispatcher\\' => array ( 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', ), - 'Symfony\\Contracts\\Cache\\' => + 'Symfony\\Contracts\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/symfony/cache-contracts', ), - 'Symfony\\Component\\Yaml\\' => + 'Symfony\\Component\\Yaml\\' => array ( 0 => __DIR__ . '/..' . '/symfony/yaml', ), - 'Symfony\\Component\\VarExporter\\' => + 'Symfony\\Component\\VarExporter\\' => array ( 0 => __DIR__ . '/..' . '/symfony/var-exporter', ), - 'Symfony\\Component\\VarDumper\\' => + 'Symfony\\Component\\VarDumper\\' => array ( 0 => __DIR__ . '/..' . '/symfony/var-dumper', ), - 'Symfony\\Component\\Validator\\' => + 'Symfony\\Component\\Validator\\' => array ( 0 => __DIR__ . '/..' . '/symfony/validator', ), - 'Symfony\\Component\\String\\' => + 'Symfony\\Component\\String\\' => array ( 0 => __DIR__ . '/..' . '/symfony/string', ), - 'Symfony\\Component\\Stopwatch\\' => + 'Symfony\\Component\\Stopwatch\\' => array ( 0 => __DIR__ . '/..' . '/symfony/stopwatch', ), - 'Symfony\\Component\\Security\\Csrf\\' => + 'Symfony\\Component\\Security\\Csrf\\' => array ( 0 => __DIR__ . '/..' . '/symfony/security-csrf', ), - 'Symfony\\Component\\Security\\Core\\' => + 'Symfony\\Component\\Security\\Core\\' => array ( 0 => __DIR__ . '/..' . '/symfony/security-core', ), - 'Symfony\\Component\\Routing\\' => + 'Symfony\\Component\\Routing\\' => array ( 0 => __DIR__ . '/..' . '/symfony/routing', ), - 'Symfony\\Component\\PropertyInfo\\' => + 'Symfony\\Component\\PropertyInfo\\' => array ( 0 => __DIR__ . '/..' . '/symfony/property-info', ), - 'Symfony\\Component\\PropertyAccess\\' => + 'Symfony\\Component\\PropertyAccess\\' => array ( 0 => __DIR__ . '/..' . '/symfony/property-access', ), - 'Symfony\\Component\\PasswordHasher\\' => + 'Symfony\\Component\\PasswordHasher\\' => array ( 0 => __DIR__ . '/..' . '/symfony/password-hasher', ), - 'Symfony\\Component\\OptionsResolver\\' => + 'Symfony\\Component\\OptionsResolver\\' => array ( 0 => __DIR__ . '/..' . '/symfony/options-resolver', ), - 'Symfony\\Component\\Mime\\' => + 'Symfony\\Component\\Mime\\' => array ( 0 => __DIR__ . '/..' . '/symfony/mime', ), - 'Symfony\\Component\\Mailer\\' => + 'Symfony\\Component\\Mailer\\' => array ( 0 => __DIR__ . '/..' . '/symfony/mailer', ), - 'Symfony\\Component\\HttpKernel\\' => + 'Symfony\\Component\\HttpKernel\\' => array ( 0 => __DIR__ . '/..' . '/symfony/http-kernel', ), - 'Symfony\\Component\\HttpFoundation\\' => + 'Symfony\\Component\\HttpFoundation\\' => array ( 0 => __DIR__ . '/..' . '/symfony/http-foundation', ), - 'Symfony\\Component\\Form\\' => + 'Symfony\\Component\\Form\\' => array ( 0 => __DIR__ . '/..' . '/symfony/form', ), - 'Symfony\\Component\\Finder\\' => + 'Symfony\\Component\\Finder\\' => array ( 0 => __DIR__ . '/..' . '/symfony/finder', ), - 'Symfony\\Component\\Filesystem\\' => + 'Symfony\\Component\\Filesystem\\' => array ( 0 => __DIR__ . '/..' . '/symfony/filesystem', ), - 'Symfony\\Component\\EventDispatcher\\' => + 'Symfony\\Component\\EventDispatcher\\' => array ( 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', ), - 'Symfony\\Component\\ErrorHandler\\' => + 'Symfony\\Component\\ErrorHandler\\' => array ( 0 => __DIR__ . '/..' . '/symfony/error-handler', ), - 'Symfony\\Component\\Dotenv\\' => + 'Symfony\\Component\\Dotenv\\' => array ( 0 => __DIR__ . '/..' . '/symfony/dotenv', ), - 'Symfony\\Component\\DependencyInjection\\' => + 'Symfony\\Component\\DependencyInjection\\' => array ( 0 => __DIR__ . '/..' . '/symfony/dependency-injection', ), - 'Symfony\\Component\\CssSelector\\' => + 'Symfony\\Component\\CssSelector\\' => array ( 0 => __DIR__ . '/..' . '/symfony/css-selector', ), - 'Symfony\\Component\\Console\\' => + 'Symfony\\Component\\Console\\' => array ( 0 => __DIR__ . '/..' . '/symfony/console', ), - 'Symfony\\Component\\Config\\' => + 'Symfony\\Component\\Config\\' => array ( 0 => __DIR__ . '/..' . '/symfony/config', ), - 'Symfony\\Component\\Cache\\' => + 'Symfony\\Component\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/symfony/cache', ), - 'Symfony\\Bundle\\WebProfilerBundle\\' => + 'Symfony\\Bundle\\WebProfilerBundle\\' => array ( 0 => __DIR__ . '/..' . '/symfony/web-profiler-bundle', ), - 'Symfony\\Bundle\\TwigBundle\\' => + 'Symfony\\Bundle\\TwigBundle\\' => array ( 0 => __DIR__ . '/..' . '/symfony/twig-bundle', ), - 'Symfony\\Bundle\\FrameworkBundle\\' => + 'Symfony\\Bundle\\FrameworkBundle\\' => array ( 0 => __DIR__ . '/..' . '/symfony/framework-bundle', ), - 'Symfony\\Bridge\\Twig\\' => + 'Symfony\\Bridge\\Twig\\' => array ( 0 => __DIR__ . '/..' . '/symfony/twig-bridge', ), - 'Soundasleep\\' => + 'Soundasleep\\' => array ( 0 => __DIR__ . '/..' . '/soundasleep/html2text/src', ), - 'ScssPhp\\ScssPhp\\' => + 'ScssPhp\\ScssPhp\\' => array ( 0 => __DIR__ . '/..' . '/scssphp/scssphp/src', ), - 'Sabberworm\\CSS\\' => + 'Sabberworm\\CSS\\' => array ( 0 => __DIR__ . '/..' . '/sabberworm/php-css-parser/src', ), - 'Psr\\Log\\' => + 'Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/src', ), - 'Psr\\Http\\Message\\' => + 'Psr\\Http\\Message\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-factory/src', 1 => __DIR__ . '/..' . '/psr/http-message/src', ), - 'Psr\\Http\\Client\\' => + 'Psr\\Http\\Client\\' => array ( 0 => __DIR__ . '/..' . '/psr/http-client/src', ), - 'Psr\\EventDispatcher\\' => + 'Psr\\EventDispatcher\\' => array ( 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src', ), - 'Psr\\Container\\' => + 'Psr\\Container\\' => array ( 0 => __DIR__ . '/..' . '/psr/container/src', ), - 'Psr\\Cache\\' => + 'Psr\\Cache\\' => array ( 0 => __DIR__ . '/..' . '/psr/cache/src', ), - 'PhpParser\\' => + 'PhpParser\\' => array ( 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', ), - 'Pelago\\Emogrifier\\' => + 'Pelago\\Emogrifier\\' => array ( 0 => __DIR__ . '/..' . '/pelago/emogrifier/src', ), - 'League\\OAuth2\\Client\\' => + 'League\\OAuth2\\Client\\' => array ( 0 => __DIR__ . '/..' . '/league/oauth2-google/src', 1 => __DIR__ . '/..' . '/league/oauth2-client/src', ), - 'GuzzleHttp\\Psr7\\' => + 'GuzzleHttp\\Psr7\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src', ), - 'GuzzleHttp\\Promise\\' => + 'GuzzleHttp\\Promise\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src', ), - 'GuzzleHttp\\' => + 'GuzzleHttp\\' => array ( 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src', ), - 'Firebase\\JWT\\' => + 'Firebase\\JWT\\' => array ( 0 => __DIR__ . '/..' . '/firebase/php-jwt/src', ), - 'Egulias\\EmailValidator\\' => + 'Egulias\\EmailValidator\\' => array ( 0 => __DIR__ . '/..' . '/egulias/email-validator/src', ), - 'Doctrine\\Common\\Lexer\\' => + 'Doctrine\\Common\\Lexer\\' => array ( 0 => __DIR__ . '/..' . '/doctrine/lexer/src', ), ); public static $prefixesPsr0 = array ( - 'C' => + 'C' => array ( - 'Console' => + 'Console' => array ( 0 => __DIR__ . '/..' . '/pear/console_getopt', ), ), - 'A' => + 'A' => array ( - 'Archive_Tar' => + 'Archive_Tar' => array ( 0 => __DIR__ . '/..' . '/pear/archive_tar', ), @@ -886,6 +886,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Forms\\Block\\Base\\HiddenFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/HiddenFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\IntegerFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/IntegerFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\NumberFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/NumberFormBlock.php', + 'Combodo\\iTop\\Forms\\Block\\Base\\PolymorphicFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/PolymorphicFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\TextAreaFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/TextAreaFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\Base\\TextFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/Base/TextFormBlock.php', 'Combodo\\iTop\\Forms\\Block\\DataModel\\AttributeChoiceFormBlock' => __DIR__ . '/../..' . '/sources/Forms/Block/DataModel/AttributeChoiceFormBlock.php', @@ -956,6 +957,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f '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', @@ -964,6 +966,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f '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', + 'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\ValueTypePolymorphic' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php', 'Combodo\\iTop\\PropertyType\\ValueType\\Branch\\ValueTypePropertyTree' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/Branch/ValueTypePropertyTree.php', 'Combodo\\iTop\\PropertyType\\ValueType\\Leaf\\AbstractLeafValueType' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/Leaf/AbstractLeafValueType.php', 'Combodo\\iTop\\PropertyType\\ValueType\\Leaf\\ValueTypeAggregateFunction' => __DIR__ . '/../..' . '/sources/PropertyType/ValueType/Leaf/ValueTypeAggregateFunction.php', diff --git a/sources/Controller/Base/Layout/DashboardController.php b/sources/Controller/Base/Layout/DashboardController.php index 3cb3797cc3..7576215a3b 100644 --- a/sources/Controller/Base/Layout/DashboardController.php +++ b/sources/Controller/Base/Layout/DashboardController.php @@ -10,7 +10,10 @@ use Combodo\iTop\Application\UI\Base\iUIBlock; use Combodo\iTop\Application\WebPage\AjaxPage; use Combodo\iTop\Application\WebPage\JsonPage; use Combodo\iTop\Controller\AbstractController; +use Combodo\iTop\Forms\Block\FormBlockService; +use Combodo\iTop\ItopSdkFormDemonstrator\Helper\ItopSdkFormDemonstratorLog; use Combodo\iTop\Service\DependencyInjection\ServiceLocator; +use Exception; use ModelReflectionRuntime; use utils; @@ -78,7 +81,30 @@ class DashboardController extends Controller $sValues = utils::ReadParam('values', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA); $aValues = !empty($sValues) ? json_decode($sValues, true, 20) : []; - // TODO 3.3 Consume the values and persist them + try { + // Get the form block from the service (and the compiler) + $oRequest = $this->getRequest(); + $oFormBlock = FormBlockService::GetInstance()->GetFormBlockById('dashboard_type', 'Dashboard'); + $oBuilder = $this->GetFormBuilder($oFormBlock, []); + $oForm = $oBuilder->getForm(); + $oForm->handleRequest($oRequest); + + if ($oForm->isSubmitted()) { + if ($oForm->isValid()) { + // Save XML + + } + + // Compute blocks to redraw + $this->HandleFormSubmitted($oFormBlock, $oForm); + } + } catch (Exception $e) { + ItopSdkFormDemonstratorLog::Exception($e->getMessage(), $e); + $this->DisplayPage([ + 'sControllerError' => $e->getMessage(), + ], 'itop_error_update', Controller::ENUM_PAGE_TYPE_TURBO_FORM_AJAX); + return null; + } $oPage = new JsonPage(); $oPage->SetData($aValues); diff --git a/sources/Forms/Block/Base/PolymorphicFormBlock.php b/sources/Forms/Block/Base/PolymorphicFormBlock.php new file mode 100644 index 0000000000..5b42c5a3c9 --- /dev/null +++ b/sources/Forms/Block/Base/PolymorphicFormBlock.php @@ -0,0 +1,14 @@ +DisplayPage([ - // 'form' => $oForm->createView(), - // 'sAction' => utils::GetAbsoluteUrlAppRoot().'pages/UI.php?route=forms.dashlet_configuration&dashlet_code='.urlencode($sDashletId), - // ], 'itop_form'); - } catch (Exception $e) { ItopSdkFormDemonstratorLog::Exception($e->getMessage(), $e); $this->DisplayPage([ diff --git a/sources/PropertyType/PropertyTypeService.php b/sources/PropertyType/PropertyTypeService.php index b5c2ea77f0..e01a5dc58a 100644 --- a/sources/PropertyType/PropertyTypeService.php +++ b/sources/PropertyType/PropertyTypeService.php @@ -76,6 +76,13 @@ class PropertyTypeService return PropertyTypeCompiler::GetInstance()->ListPropertyTypesByType($sType); } + public function GetPropertyType(string $sId, string $sType = 'Dashlet'): PropertyType + { + $sXML = PropertyTypeCompiler::GetInstance()->GetXMLContent($sId, $sType); + + return PropertyTypeCompiler::GetInstance()->CompilePropertyTypeFromXML($sXML); + } + /** * @param string $sId * diff --git a/sources/PropertyType/Serializer/XMLFormat/XMLFormatCollectionWithId.php b/sources/PropertyType/Serializer/XMLFormat/XMLFormatCollectionWithId.php new file mode 100644 index 0000000000..d45b7a8c6e --- /dev/null +++ b/sources/PropertyType/Serializer/XMLFormat/XMLFormatCollectionWithId.php @@ -0,0 +1,78 @@ +sTagName = $oDomNode->GetChildText('tag-name'); + } + + public function Normalize($value, AbstractValueType $oValueType): mixed + { + return $value; + } + + 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 $sItemId => $aValues) { + /** @var DesignElement $oNode */ + $oNode = $oDOMNode->ownerDocument->createElement($this->sTagName); + $oNode->setAttribute('id', $sItemId); + $oDOMNode->appendChild($oNode); + 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); + } + } + } + } + + public function DecodeFromDOMNode(DesignElement $oDOMNode, AbstractValueType $oValueType): mixed + { + if (!$oValueType instanceof ValueTypeCollection) { + throw new SerializerException('XMLFormatFlatArray is allowed only in ValueTypeCollection nodes'); + } + + $aNormalizedValues = []; + + /** @var DesignElement $oNode */ + foreach ($oDOMNode->GetNodes($this->sTagName) as $oNode) { + $sItemId = $oNode->getAttribute('id'); + $aSubArray = []; + foreach ($oValueType->GetChildren() as $oChild) { + $aSubArray[$oChild->GetId()] = $oChild->DecodeFromDomNode($oNode->GetUniqueElement($oChild->GetId())); + } + $aNormalizedValues[$sItemId] = $aSubArray; + } + + return $aNormalizedValues; + } + + public function Denormalize($normalizedValue, AbstractValueType $oValueType): mixed + { + return $normalizedValue; + } +} diff --git a/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php b/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php new file mode 100644 index 0000000000..8ef6f0f8e2 --- /dev/null +++ b/sources/PropertyType/ValueType/Branch/ValueTypePolymorphic.php @@ -0,0 +1,53 @@ +setAttribute('xsi:type', $sType); + + $oPropertyType = PropertyTypeService::GetInstance()->GetPropertyType($sType); + + $aProperties = $normalizedValue['properties']; + $oPropertyType->EncodeToDOMNode($aProperties, $oDOMNode); + } + + public function DecodeFromDomNode(DesignElement $oDOMNode): mixed + { + $sType = $oDOMNode->getAttribute('xsi:type'); + $oPropertyType = PropertyTypeService::GetInstance()->GetPropertyType($sType); + + return [ + 'type' => $sType, + 'properties' => $oPropertyType->DecodeFromDOMNode($oDOMNode), + ]; + } +} diff --git a/sources/alias.php b/sources/alias.php index 56dc31c5b6..1ab3d41a46 100644 --- a/sources/alias.php +++ b/sources/alias.php @@ -101,6 +101,7 @@ class_alias(\Combodo\iTop\PropertyType\PropertyType::class, 'Combodo-PropertyTyp class_alias(\Combodo\iTop\PropertyType\ValueType\Branch\ValueTypeCollection::class, 'Combodo-ValueType-Collection'); class_alias(\Combodo\iTop\PropertyType\ValueType\Branch\ValueTypePropertyTree::class, 'Combodo-ValueType-PropertyTree'); +class_alias(\Combodo\iTop\PropertyType\ValueType\Branch\ValueTypePolymorphic::class, 'Combodo-ValueType-Polymorphic'); class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeAggregateFunction::class, 'Combodo-ValueType-AggregateFunction'); class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeBoolean::class, 'Combodo-ValueType-Boolean'); @@ -121,3 +122,4 @@ class_alias(\Combodo\iTop\PropertyType\ValueType\Leaf\ValueTypeText::class, 'Com 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'); +class_alias(\Combodo\iTop\PropertyType\Serializer\XMLFormat\XMLFormatCollectionWithId::class, 'Combodo-XMLFormat-CollectionWithId'); diff --git a/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php b/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php new file mode 100644 index 0000000000..8fa0fd648a --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/sources/Application/Dashboard/ValueType/DashboardSerializerTest.php @@ -0,0 +1,95 @@ +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); + + Combodo\iTop\PropertyType\Serializer\XMLSerializer::GetInstance()->Serialize($normalizedValue, $oRootNode, 'DashboardDefinition', 'Dashboard'); + + $sActualXML = $oDOMDocument->saveXML(); + + $this->AssertEqualiTopXML($sXMLContent, $sActualXML); + } + + public function XMLSerializerProvider() + { + return [ + 'Basic test should serialize to XML' => [ + 'normalizedValue' => [ + 'schema_version' => 2, + 'id' => 'WelcomeMenuPage', + 'title' => 'Bienvenido al Panel de Control Panel', + 'refresh' => '60', + 'pos_dashlets' => [ + 'CUSTOM_WelcomeMenuPage_ID_row0_col0_1' => [ + 'position_x' => 1, + 'position_y' => 2, + 'width' => 3, + 'height' => 1, + 'dashlet' => [ + 'type' => 'DashletHeaderStatic', + 'properties' => [ + 'title' => 'Menu:ConfigManagementCI', + 'icon' => '../images/icons/icons8-database.svg', + ], + ], + ], + ], + ], + 'sXMLContent' => << + + Bienvenido al Panel de Control Panel + 60 + + + 1 + 2 + 3 + 1 + + Menu:ConfigManagementCI + ../images/icons/icons8-database.svg + + + + +XML, + ], + ]; + } +} diff --git a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php index ee2adce924..018987772d 100644 --- a/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php +++ b/tests/php-unit-tests/unitary-tests/sources/PropertyType/Serializer/XMLSerializerTest.php @@ -32,6 +32,8 @@ class XMLSerializerTest extends ItopDataTestCase /** @var \Combodo\iTop\DesignElement $oRootNode */ $oRootNode = $oDOMDocument->createElement('root'); + $oRootNode->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $oDOMDocument->appendChild($oRootNode); Combodo\iTop\PropertyType\Serializer\XMLSerializer::GetInstance()->SerializeForPropertyType($normalizedValue, $oRootNode, $sPropertyTypeXML); @@ -56,7 +58,7 @@ class XMLSerializerTest extends ItopDataTestCase XML, 'sXMLContent' => << -text +text XML, ], 'Collection of values as CSV' => [ @@ -74,7 +76,7 @@ XML, XML, 'sXMLContent' => << -Contact,Organization +Contact,Organization XML, ], 'Collection of values as id attribute' => [ @@ -94,7 +96,7 @@ XML, XML, 'sXMLContent' => << - + @@ -134,7 +136,7 @@ XML, XML, 'sXMLContent' => << - + 2 title_a class_a @@ -164,10 +166,83 @@ XML, XML, 'sXMLContent' => << - + title class +XML, + ], + 'Polymorphic tree' => [ + 'normalizedValue' => [ + 'type' => 'DashletHeaderStatic', + 'properties' => [ + 'title' => 'Menu:ConfigManagementCI', + 'icon' => '../images/icons/icons8-database.svg', + ], + ], + 'sPropertyTypeXML' => << + + Dashlet + + + + Dashlet + + + +XML, + 'sXMLContent' => << + + Menu:ConfigManagementCI + ../images/icons/icons8-database.svg + +XML, + ], + 'Collection of tree with id' => [ + 'normalizedValue' => [ + 'a' => [ + 'title_property' => 'title_a', + 'class_property' => 'class_a', + ], + 'b' => [ + 'title_property' => 'title_b', + 'class_property' => 'class_b', + ], + ], + 'sPropertyTypeXML' => << + + Dashlet + + + item + + + + + + + + test + + + + +XML, + 'sXMLContent' => << + + + title_a + class_a + + + title_b + class_b + + XML, ], ]; diff --git a/validation/property_types.xsd b/validation/property_types.xsd index 7f360abb31..25842567f0 100644 --- a/validation/property_types.xsd +++ b/validation/property_types.xsd @@ -354,6 +354,26 @@ + + + + + + + Format of the property in the source XML + + + + + + + + + + + + + @@ -396,5 +416,15 @@ + + + + + + + + + + \ No newline at end of file