diff --git a/application/menunode.class.inc.php b/application/menunode.class.inc.php
index 2e39d6382..0b1087a4d 100644
--- a/application/menunode.class.inc.php
+++ b/application/menunode.class.inc.php
@@ -1219,7 +1219,6 @@ class NewObjectMenuNode extends MenuNode
}
}
-require_once(APPROOT.'application/dashboard.class.inc.php');
/**
* This class defines a menu item which content is based on XML dashboard.
*/
diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php
index 8d6fe8ebc..86f8de148 100644
--- a/lib/composer/autoload_classmap.php
+++ b/lib/composer/autoload_classmap.php
@@ -131,6 +131,7 @@ return array(
'Collator' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/Collator.php',
'Combodo\\iTop\\Application\\Branding' => $baseDir . '/sources/Application/Branding.php',
'Combodo\\iTop\\Application\\Dashboard\\Controller\\DashboardController' => $baseDir . '/sources/Application/Dashboard/Controller/DashboardController.php',
+ 'Combodo\\iTop\\Application\\Dashboard\\Dashboard' => $baseDir . '/sources/Application/Dashboard/Dashboard.php',
'Combodo\\iTop\\Application\\Dashboard\\DashboardException' => $baseDir . '/sources/Application/Dashboard/DashboardException.php',
'Combodo\\iTop\\Application\\Dashboard\\FormBlock\\DashboardFormBlock' => $baseDir . '/sources/Application/Dashboard/FormBlock/DashboardFormBlock.php',
'Combodo\\iTop\\Application\\Dashboard\\FormBlock\\DashletFormBlock' => $baseDir . '/sources/Application/Dashboard/FormBlock/DashletFormBlock.php',
@@ -702,7 +703,6 @@ return array(
'DBUnionSearch' => $baseDir . '/core/dbunionsearch.class.php',
'DOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php',
'DailyRotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php',
- 'Dashboard' => $baseDir . '/application/dashboard.class.inc.php',
'DashboardLayout' => $baseDir . '/application/dashboardlayout.class.inc.php',
'DashboardLayoutMultiCol' => $baseDir . '/application/dashboardlayout.class.inc.php',
'DashboardLayoutOneCol' => $baseDir . '/application/dashboardlayout.class.inc.php',
@@ -1440,7 +1440,7 @@ return array(
'RowStatus_NewObj' => $baseDir . '/core/bulkchange.class.inc.php',
'RowStatus_NoChange' => $baseDir . '/core/bulkchange.class.inc.php',
'RunTimeIconSelectionField' => $baseDir . '/application/forms.class.inc.php',
- 'RuntimeDashboard' => $baseDir . '/application/dashboard.class.inc.php',
+ 'RuntimeDashboard' => $baseDir . '/sources/Application/Dashboard/RuntimeDashboard.php',
'SQLExpression' => $baseDir . '/core/oql/expression.class.inc.php',
'SQLObjectQuery' => $baseDir . '/core/sqlobjectquery.class.inc.php',
'SQLObjectQueryBuilder' => $baseDir . '/core/sqlobjectquerybuilder.class.inc.php',
diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php
index 7a397c21e..1b5a8c729 100644
--- a/lib/composer/autoload_static.php
+++ b/lib/composer/autoload_static.php
@@ -517,6 +517,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Collator' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/Collator.php',
'Combodo\\iTop\\Application\\Branding' => __DIR__ . '/../..' . '/sources/Application/Branding.php',
'Combodo\\iTop\\Application\\Dashboard\\Controller\\DashboardController' => __DIR__ . '/../..' . '/sources/Application/Dashboard/Controller/DashboardController.php',
+ 'Combodo\\iTop\\Application\\Dashboard\\Dashboard' => __DIR__ . '/../..' . '/sources/Application/Dashboard/Dashboard.php',
'Combodo\\iTop\\Application\\Dashboard\\DashboardException' => __DIR__ . '/../..' . '/sources/Application/Dashboard/DashboardException.php',
'Combodo\\iTop\\Application\\Dashboard\\FormBlock\\DashboardFormBlock' => __DIR__ . '/../..' . '/sources/Application/Dashboard/FormBlock/DashboardFormBlock.php',
'Combodo\\iTop\\Application\\Dashboard\\FormBlock\\DashletFormBlock' => __DIR__ . '/../..' . '/sources/Application/Dashboard/FormBlock/DashletFormBlock.php',
@@ -1088,7 +1089,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'DBUnionSearch' => __DIR__ . '/../..' . '/core/dbunionsearch.class.php',
'DOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php',
'DailyRotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php',
- 'Dashboard' => __DIR__ . '/../..' . '/application/dashboard.class.inc.php',
'DashboardLayout' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php',
'DashboardLayoutMultiCol' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php',
'DashboardLayoutOneCol' => __DIR__ . '/../..' . '/application/dashboardlayout.class.inc.php',
@@ -1826,7 +1826,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'RowStatus_NewObj' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php',
'RowStatus_NoChange' => __DIR__ . '/../..' . '/core/bulkchange.class.inc.php',
'RunTimeIconSelectionField' => __DIR__ . '/../..' . '/application/forms.class.inc.php',
- 'RuntimeDashboard' => __DIR__ . '/../..' . '/application/dashboard.class.inc.php',
+ 'RuntimeDashboard' => __DIR__ . '/../..' . '/sources/Application/Dashboard/RuntimeDashboard.php',
'SQLExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
'SQLObjectQuery' => __DIR__ . '/../..' . '/core/sqlobjectquery.class.inc.php',
'SQLObjectQueryBuilder' => __DIR__ . '/../..' . '/core/sqlobjectquerybuilder.class.inc.php',
diff --git a/sources/Application/Dashboard/Dashboard.php b/sources/Application/Dashboard/Dashboard.php
new file mode 100644
index 000000000..dfa7c399f
--- /dev/null
+++ b/sources/Application/Dashboard/Dashboard.php
@@ -0,0 +1,773 @@
+sTitle = '';
+ $this->sLayoutClass = 'DashboardLayoutOneCol';
+ $this->bAutoReload = false;
+ $this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
+ $this->aCells = [];
+ $this->oDOMNode = null;
+ $this->sId = $sId;
+ $this->oDashletFactory = DashletFactory::GetInstance();
+ }
+
+ /**
+ * @param string $sXml
+ *
+ * @throws \Exception
+ */
+ public function FromXml($sXml)
+ {
+ $this->aCells = []; // reset the content of the dashboard
+ set_error_handler(['Dashboard', 'ErrorHandler']);
+ $oDoc = new PropertyTypeDesign();
+ $oDoc->loadXML($sXml);
+ restore_error_handler();
+ $this->FromDOMDocument($oDoc);
+ }
+
+ /**
+ * @param \DOMDocument $oDoc
+ */
+ public function FromDOMDocument(DesignDocument $oDoc)
+ {
+ $this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
+
+ if ($this->oDOMNode->getElementsByTagName('cells')->count() === 0) {
+ $this->FromDOMDocumentV2($oDoc);
+ return;
+ }
+
+ if ($oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0)) {
+ $this->sLayoutClass = $oLayoutNode->textContent;
+ } else {
+ $this->sLayoutClass = 'DashboardLayoutOneCol';
+ }
+
+ if ($oTitleNode = $this->oDOMNode->getElementsByTagName('title')->item(0)) {
+ $this->sTitle = $oTitleNode->textContent;
+ } else {
+ $this->sTitle = '';
+ }
+
+ $this->bAutoReload = false;
+ $this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
+ if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0)) {
+ if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0)) {
+ $this->bAutoReload = ($oAutoReloadEnabled->textContent == 'true');
+ }
+ if ($oAutoReloadInterval = $oAutoReloadNode->getElementsByTagName('interval')->item(0)) {
+ $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$oAutoReloadInterval->textContent);
+ }
+ }
+
+ if ($oCellsNode = $this->oDOMNode->getElementsByTagName('cells')->item(0)) {
+ $oCellsList = $oCellsNode->getElementsByTagName('cell');
+ $aCellOrder = [];
+ $iCellRank = 0;
+ /** @var \DOMElement $oCellNode */
+ foreach ($oCellsList as $oCellNode) {
+ $oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
+ if ($oCellRank) {
+ $iCellRank = (float)$oCellRank->textContent;
+ }
+ $oDashletsNode = $oCellNode->getElementsByTagName('dashlets')->item(0);
+ {
+ $oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
+ $iRank = 0;
+ $aDashletOrder = [];
+ /** @var DesignElement $oDomNode */
+ foreach ($oDashletList as $oDomNode) {
+ $oRank = $oDomNode->getElementsByTagName('rank')->item(0);
+ if ($oRank) {
+ $iRank = (float)$oRank->textContent;
+ }
+
+ $oNewDashlet = $this->InitDashletFromDOMNode($oDomNode);
+ $aDashletOrder[] = ['rank' => $iRank, 'dashlet' => $oNewDashlet];
+ }
+ usort($aDashletOrder, [get_class($this), 'SortOnRank']);
+ $aDashletList = [];
+ foreach ($aDashletOrder as $aItem) {
+ $aDashletList[] = $aItem['dashlet'];
+ }
+ $aCellOrder[] = ['rank' => $iCellRank, 'dashlets' => $aDashletList];
+ }
+ }
+ usort($aCellOrder, [get_class($this), 'SortOnRank']);
+ foreach ($aCellOrder as $aItem) {
+ $this->aCells[] = $aItem['dashlets'];
+ }
+ } else {
+ $this->aCells = [];
+ }
+ }
+
+ /**
+ * @param \DOMDocument $oDoc
+ */
+ public function FromDOMDocumentV2(DesignDocument $oDoc)
+ {
+ $this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
+
+ $this->sLayoutClass = DashboardLayoutGrid::class;
+ $this->sTitle = $this->oDOMNode->GetChildText('title', '');
+
+ $iRefresh = intval($this->oDOMNode->GetChildText('refresh', '0'));
+
+ $this->bAutoReload = $iRefresh > 0;
+ $this->iAutoReloadSec = $iRefresh;
+
+ $oDashletsNode = $this->oDOMNode->GetUniqueElement('pos_dashlets');
+ $oDashletList = $oDashletsNode->getElementsByTagName('pos_dashlet');
+ foreach ($oDashletList as $oPosDashletNode) {
+ $aGridDashlet = [];
+ $aGridDashlet['position_x'] = intval($oPosDashletNode->GetChildText('position_x', '0'));
+ $aGridDashlet['position_y'] = intval($oPosDashletNode->GetChildText('position_y', '0'));
+ $aGridDashlet['width'] = intval($oPosDashletNode->GetChildText('width', '2'));
+ $aGridDashlet['height'] = intval($oPosDashletNode->GetChildText('height', '1'));
+ $oDashletNode = $oPosDashletNode->GetUniqueElement('dashlet');
+ $sId = $oPosDashletNode->getAttribute('id');
+ $oDashlet = $this->InitDashletFromDOMNode($oDashletNode);
+ $oDashlet->SetID($sId);
+ $aGridDashlet['dashlet'] = $oDashlet;
+ $this->aGridDashlets[] = $aGridDashlet;
+ }
+ }
+
+ /**
+ * @param DesignElement $oDomNode
+ *
+ * @return mixed
+ */
+ protected function InitDashletFromDOMNode($oDomNode)
+ {
+ $sId = $oDomNode->getAttribute('id');
+
+ $sDashletType = $oDomNode->getAttribute('xsi:type');
+
+ // Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
+ $sClass = static::GetDashletClassFromType($sDashletType);
+ /** @var \Dashlet $oNewDashlet */
+ $oNewDashlet = $this->oDashletFactory->CreateDashlet($sClass, $sId);
+ $oNewDashlet->FromDOMNode($oDomNode);
+
+ return $oNewDashlet;
+ }
+
+ /**
+ * @param array $aItem1
+ * @param array $aItem2
+ *
+ * @return int
+ */
+ public static function SortOnRank($aItem1, $aItem2)
+ {
+ return ($aItem1['rank'] > $aItem2['rank']) ? +1 : -1;
+ }
+
+ /**
+ * Error handler to turn XML loading warnings into exceptions
+ *
+ * @param $errno
+ * @param $errstr
+ * @param $errfile
+ * @param $errline
+ *
+ * @return bool
+ * @throws \DOMException
+ */
+ public static function ErrorHandler($errno, $errstr, $errfile, $errline)
+ {
+ if ($errno == E_WARNING && (substr_count($errstr, "DOMDocument::loadXML()") > 0)) {
+ throw new DOMException($errstr);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @return string
+ * @throws \Exception
+ */
+ public function ToXml()
+ {
+ $oMainNode = $this->CreateEmptyDashboard();
+
+ $this->ToDOMNode($oMainNode);
+
+ $sXml = $oMainNode->ownerDocument->saveXML();
+
+ return $sXml;
+ }
+
+ /**
+ * @return DesignElement
+ * @throws \DOMException
+ */
+ public function CreateEmptyDashboard(): DesignElement
+ {
+ $oDoc = new DesignDocument();
+ $oDoc->formatOutput = true; // indent (must be loaded with option LIBXML_NOBLANKS)
+ $oDoc->preserveWhiteSpace = true; // otherwise the formatOutput option would have no effect
+
+ /** @var DesignElement $oMainNode */
+ $oMainNode = $oDoc->createElement('dashboard');
+ $oMainNode->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+ $oDoc->appendChild($oMainNode);
+
+ return $oMainNode;
+ }
+
+ /**
+ * @param \DOMElement $oDefinition
+ */
+ public function ToDOMNode($oDefinition)
+ {
+ /** @var \DOMDocument $oDoc */
+ $oDoc = $oDefinition->ownerDocument;
+
+ $oNode = $oDoc->createElement('layout', $this->sLayoutClass);
+ $oDefinition->appendChild($oNode);
+
+ $oNode = $oDoc->createElement('title', $this->sTitle);
+ $oDefinition->appendChild($oNode);
+
+ $oAutoReloadNode = $oDoc->createElement('auto_reload');
+ $oDefinition->appendChild($oAutoReloadNode);
+ $oNode = $oDoc->createElement('enabled', $this->bAutoReload ? 'true' : 'false');
+ $oAutoReloadNode->appendChild($oNode);
+ $oNode = $oDoc->createElement('interval', $this->iAutoReloadSec);
+ $oAutoReloadNode->appendChild($oNode);
+
+ $oCellsNode = $oDoc->createElement('cells');
+ $oDefinition->appendChild($oCellsNode);
+
+ $iCellRank = 0;
+ foreach ($this->aCells as $aCell) {
+ $oCellNode = $oDoc->createElement('cell');
+ $oCellNode->setAttribute('id', $iCellRank);
+ $oCellsNode->appendChild($oCellNode);
+ $oCellRank = $oDoc->createElement('rank', $iCellRank);
+ $oCellNode->appendChild($oCellRank);
+ $iCellRank++;
+
+ $iDashletRank = 0;
+ $oDashletsNode = $oDoc->createElement('dashlets');
+ $oCellNode->appendChild($oDashletsNode);
+ /** @var \Dashlet $oDashlet */
+ foreach ($aCell as $oDashlet) {
+ $oNode = $oDoc->createElement('dashlet');
+ $oDashletsNode->appendChild($oNode);
+ $oNode->setAttribute('id', $oDashlet->GetID());
+ $oNode->setAttribute('xsi:type', $oDashlet->GetDashletType());
+ $oDashletRank = $oDoc->createElement('rank', $iDashletRank);
+ $oNode->appendChild($oDashletRank);
+ $iDashletRank++;
+ $oDashlet->ToDOMNode($oNode);
+ }
+ }
+ }
+
+ /**
+ * @param array $aParams
+ */
+ public function FromParams($aParams)
+ {
+ $this->sLayoutClass = $aParams['layout_class'];
+ if (!is_subclass_of($this->sLayoutClass, DashboardLayout::class)) {
+ throw new InvalidParameterException('Invalid parameter layout_class "'.$aParams['layout_class'].'"');
+ }
+ $this->sTitle = $aParams['title'];
+ $this->bAutoReload = $aParams['auto_reload'] == 'true';
+ $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$aParams['auto_reload_sec']);
+
+ foreach ($aParams['cells'] as $aCell) {
+ $aCellDashlets = [];
+ foreach ($aCell as $aDashletParams) {
+ $sDashletClass = $aDashletParams['dashlet_class'];
+ $sId = $aDashletParams['dashlet_id'];
+ /** @var \Dashlet $oNewDashlet */
+ $oNewDashlet = $this->oDashletFactory->CreateDashlet($sDashletClass, $sId);
+ if (isset($aDashletParams['dashlet_type'])) {
+ $oNewDashlet->SetDashletType($aDashletParams['dashlet_type']);
+ }
+ $oForm = $oNewDashlet->GetForm();
+ $oForm->SetParamsContainer($sId);
+ $oForm->SetPrefix('');
+ $aValues = $oForm->ReadParams();
+ $oNewDashlet->FromParams($aValues);
+ $aCellDashlets[] = $oNewDashlet;
+ }
+ $this->aCells[] = $aCellDashlets;
+ }
+
+ }
+
+ public function Save()
+ {
+ }
+
+ public function PersistDashboard(string $sXml): bool
+ {
+ return true;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function GetId()
+ {
+ return $this->sId;
+ }
+
+ /**
+ * Return a sanitize ID for usages in XML/HTML attributes
+ *
+ * @return string
+ * @since 2.7.0
+ */
+ public function GetSanitizedId()
+ {
+ return utils::Sanitize($this->GetId(), '', 'element_identifier');
+ }
+
+ /**
+ * @return string
+ */
+ public function GetLayout()
+ {
+ return $this->sLayoutClass;
+ }
+
+ /**
+ * @param string $sLayoutClass
+ */
+ public function SetLayout($sLayoutClass)
+ {
+ $this->sLayoutClass = $sLayoutClass;
+ }
+
+ /**
+ * @return string
+ */
+ public function GetTitle()
+ {
+ return $this->sTitle;
+ }
+
+ /**
+ * @param string $sTitle
+ */
+ public function SetTitle($sTitle)
+ {
+ $this->sTitle = $sTitle;
+ }
+
+ /**
+ * @return bool
+ */
+ public function GetAutoReload()
+ {
+ return $this->bAutoReload;
+ }
+
+ /**
+ * @param bool $bAutoReload
+ */
+ public function SetAutoReload($bAutoReload)
+ {
+ $this->bAutoReload = $bAutoReload;
+ }
+
+ /**
+ * @return float|int
+ */
+ public function GetAutoReloadInterval()
+ {
+ return $this->iAutoReloadSec;
+ }
+
+ /**
+ * @param bool $iAutoReloadSec
+ */
+ public function SetAutoReloadInterval($iAutoReloadSec)
+ {
+ $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$iAutoReloadSec);
+ }
+
+ /**
+ * @param \Dashlet $oDashlet
+ */
+ public function AddDashlet($oDashlet)
+ {
+ $sId = $this->GetNewDashletId();
+ $oDashlet->SetId($sId);
+ $this->aCells[] = [$oDashlet];
+ }
+
+ /**
+ * @param WebPage $oPage *
+ * @param array $aExtraParams
+ *
+ * @throws \ReflectionException
+ * @throws \Exception
+ */
+ public function RenderProperties($oPage, $aExtraParams = [])
+ {
+ // menu to pick a layout and edit other properties of the dashboard
+ $oPage->add('
');
+ $sUrl = utils::GetAbsoluteUrlAppRoot();
+
+ $oPage->add('
'.Dict::S('UI:DashboardEdit:Layout').'
');
+ $oPage->add('
');
+
+ $oForm = new DesignerForm();
+
+ $oField = new DesignerHiddenField('dashboard_id', '', $this->sId);
+ $oForm->AddField($oField);
+
+ $oField = new DesignerTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
+ $oForm->AddField($oField);
+
+ $oField = new DesignerBooleanField('auto_reload', Dict::S('UI:DashboardEdit:AutoReload'), $this->bAutoReload);
+ $oForm->AddField($oField);
+
+ $oField = new DesignerIntegerField('auto_reload_sec', Dict::S('UI:DashboardEdit:AutoReloadSec'), $this->iAutoReloadSec);
+ $oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit
+ $oForm->AddField($oField);
+
+ $this->SetFormParams($oForm, $aExtraParams);
+ $oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
+
+ $oPage->add('
');
+
+ $sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval')));
+ $oPage->add_ready_script(
+ <<GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
+
+ /** @var \DashboardLayout $oLayout */
+ $oLayout = new $this->sLayoutClass();
+
+ foreach ($this->aCells as $iCellIdx => $aDashlets) {
+ foreach ($aDashlets as $oDashlet) {
+ $aDashletCoordinates = $oLayout->GetDashletCoordinates($iCellIdx);
+ $this->PrepareDashletForRendering($oDashlet, $aDashletCoordinates, $aExtraParams);
+ }
+ }
+
+ if (count($this->aCells) > 0) {
+ $aDashlets = $this->aCells;
+ } else {
+ $aDashlets = $this->aGridDashlets;
+ }
+
+ $oDashboard = $oLayout->Render($oPage, $aDashlets, $bEditMode, $aExtraParams);
+ $oPage->AddUiBlock($oDashboard);
+
+ $bFromDasboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
+
+ if ($bFromDasboardPage) {
+ $sTitleForHTML = utils::HtmlEntities(Dict::S($this->sTitle));
+ $sHtml = "{$sTitleForHTML}
";
+ if ($oPage instanceof iTopWebPage) {
+ $oTopBar = $oPage->GetTopBarLayout();
+ $oToolbar = ToolbarUIBlockFactory::MakeStandard();
+ $oTopBar->SetToolbar($oToolbar);
+
+ $oToolbar->AddHtml($sHtml);
+ } else {
+ $oPage->add_script(
+ <<').html("$sTitleForHTML").text());
+JS
+ );
+ }
+ } else {
+ $oDashboard->SetTitle(Dict::S($this->sTitle));
+ }
+
+ if (!$bEditMode) {
+ $oPage->LinkScriptFromAppRoot('js/dashlet.js');
+ $oPage->LinkScriptFromAppRoot('js/dashboard.js');
+ }
+
+ return $oDashboard;
+ }
+
+ /**
+ * @param WebPage $oPage
+ *
+ * @throws \ReflectionException
+ * @throws \Exception
+ */
+ public function RenderDashletsSelection(WebPage $oPage)
+ {
+ // Toolbox/palette to drag and drop dashlets
+ $oPage->add('');
+ $sUrl = utils::GetAbsoluteUrlAppRoot();
+
+ $oPage->add('
');
+ $aAvailableDashlets = $this->GetAvailableDashlets();
+ foreach ($aAvailableDashlets as $sDashletClass => $aInfo) {
+ $oPage->add('

');
+ }
+ $oPage->add('
');
+
+ $oPage->add('
');
+ $oPage->add_ready_script("$('.dashlet_icon').draggable({cursor: 'move', helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
+ }
+
+ /**
+ * @param WebPage $oPage
+ * @param array $aExtraParams
+ */
+ public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = [])
+ {
+ // Toolbox/palette to edit the properties of each dashlet
+ $oPage->add('');
+
+ /** @var \DashboardLayoutMultiCol $oLayout */
+ $oLayout = new $this->sLayoutClass();
+
+ $oPage->add('
');
+ foreach ($this->aCells as $iCellIdx => $aCell) {
+ /** @var \Dashlet $oDashlet */
+ foreach ($aCell as $oDashlet) {
+ if ($oDashlet->IsVisible()) {
+ $oPage->add('
');
+ $oForm = $oDashlet->GetForm();
+ $this->SetFormParams($oForm, $aExtraParams);
+ $oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
+ $oPage->add('
');
+ }
+ }
+ }
+ $oPage->add('
');
+
+ $oPage->add('
');
+ }
+
+ /**
+ * Return an array of dashlets available for selection.
+ *
+ * @return array
+ * @throws \Combodo\iTop\Application\Dashlet\DashletException
+ * @throws \DOMFormatException
+ */
+ protected function GetAvailableDashlets(): array
+ {
+ return DashletService::GetInstance()->GetAvailableDashlets();
+ }
+
+ /**
+ * @return int|mixed
+ */
+ protected function GetNewDashletId()
+ {
+ $iNewId = 0;
+ foreach ($this->aCells as $aDashlets) {
+ /** @var \Dashlet $oDashlet */
+ foreach ($aDashlets as $oDashlet) {
+ $iNewId = max($iNewId, (int)$oDashlet->GetID());
+ }
+ }
+
+ return $iNewId + 1;
+ }
+
+ /**
+ * Prepare dashlet for rendering (eg. change its ID or another processing).
+ * Meant to be overloaded.
+ *
+ * @param \Dashlet $oDashlet
+ * @param array $aCoordinates
+ * @param array $aExtraParams
+ *
+ * @return void
+ */
+ abstract protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = []);
+
+ /**
+ * @param \DesignerForm $oForm
+ * @param array $aExtraParams
+ *
+ * @return mixed
+ */
+ abstract protected function SetFormParams($oForm, $aExtraParams = []);
+
+ /**
+ * @param string $sType
+ * @param \ModelFactory|null $oFactory
+ *
+ * @return string
+ */
+ public static function GetDashletClassFromType($sType, $oFactory = null)
+ {
+ if (is_subclass_of($sType, 'Dashlet')) {
+ return $sType;
+ }
+
+ return 'DashletUnknown';
+ }
+
+ /**
+ * N°2634: we must have a unique id per dashlet!
+ * To avoid collision with other dashlets with the same ID we prefix it with row/cell id
+ * Collisions typically happen with extensions.
+ *
+ * @param boolean $bIsCustomized
+ * @param string $sDashboardDivId
+ * @param int $iRow
+ * @param int $iCol
+ * @param string $sDashletOrigId
+ *
+ * @return string
+ *
+ * @since 2.7.0 N°2735
+ */
+ public static function GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCol, $sDashletOrigId)
+ {
+ if (strpos($sDashletOrigId, '_ID_row') !== false) {
+ return $sDashletOrigId;
+ }
+
+ $sDashletId = $sDashboardDivId."_ID_row".$iRow."_col".$iCol."_".$sDashletOrigId;
+ if ($bIsCustomized) {
+ $sDashletId = 'CUSTOM_'.$sDashletId;
+ }
+
+ return $sDashletId;
+ }
+}
diff --git a/sources/Application/Dashboard/dashboard.class.inc.php b/sources/Application/Dashboard/RuntimeDashboard.php
similarity index 57%
rename from sources/Application/Dashboard/dashboard.class.inc.php
rename to sources/Application/Dashboard/RuntimeDashboard.php
index 6929b4c8d..125cc6c54 100644
--- a/sources/Application/Dashboard/dashboard.class.inc.php
+++ b/sources/Application/Dashboard/RuntimeDashboard.php
@@ -1,768 +1,20 @@
sTitle = '';
- $this->sLayoutClass = 'DashboardLayoutOneCol';
- $this->bAutoReload = false;
- $this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
- $this->aCells = [];
- $this->oDOMNode = null;
- $this->sId = $sId;
- $this->oDashletFactory = DashletFactory::GetInstance();
- }
-
- /**
- * @param string $sXml
- *
- * @throws \Exception
- */
- public function FromXml($sXml)
- {
- $this->aCells = []; // reset the content of the dashboard
- set_error_handler(['Dashboard', 'ErrorHandler']);
- $oDoc = new PropertyTypeDesign();
- $oDoc->loadXML($sXml);
- restore_error_handler();
- $this->FromDOMDocument($oDoc);
- }
-
- /**
- * @param \DOMDocument $oDoc
- */
- public function FromDOMDocument(DesignDocument $oDoc)
- {
- $this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
-
- if ($this->oDOMNode->getElementsByTagName('cells')->count() === 0) {
- $this->FromDOMDocumentV2($oDoc);
- return;
- }
-
- if ($oLayoutNode = $this->oDOMNode->getElementsByTagName('layout')->item(0)) {
- $this->sLayoutClass = $oLayoutNode->textContent;
- } else {
- $this->sLayoutClass = 'DashboardLayoutOneCol';
- }
-
- if ($oTitleNode = $this->oDOMNode->getElementsByTagName('title')->item(0)) {
- $this->sTitle = $oTitleNode->textContent;
- } else {
- $this->sTitle = '';
- }
-
- $this->bAutoReload = false;
- $this->iAutoReloadSec = MetaModel::GetConfig()->GetStandardReloadInterval();
- if ($oAutoReloadNode = $this->oDOMNode->getElementsByTagName('auto_reload')->item(0)) {
- if ($oAutoReloadEnabled = $oAutoReloadNode->getElementsByTagName('enabled')->item(0)) {
- $this->bAutoReload = ($oAutoReloadEnabled->textContent == 'true');
- }
- if ($oAutoReloadInterval = $oAutoReloadNode->getElementsByTagName('interval')->item(0)) {
- $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$oAutoReloadInterval->textContent);
- }
- }
-
- if ($oCellsNode = $this->oDOMNode->getElementsByTagName('cells')->item(0)) {
- $oCellsList = $oCellsNode->getElementsByTagName('cell');
- $aCellOrder = [];
- $iCellRank = 0;
- /** @var \DOMElement $oCellNode */
- foreach ($oCellsList as $oCellNode) {
- $oCellRank = $oCellNode->getElementsByTagName('rank')->item(0);
- if ($oCellRank) {
- $iCellRank = (float)$oCellRank->textContent;
- }
- $oDashletsNode = $oCellNode->getElementsByTagName('dashlets')->item(0);
- {
- $oDashletList = $oDashletsNode->getElementsByTagName('dashlet');
- $iRank = 0;
- $aDashletOrder = [];
- /** @var \DOMElement $oDomNode */
- foreach ($oDashletList as $oDomNode) {
- $oRank = $oDomNode->getElementsByTagName('rank')->item(0);
- if ($oRank) {
- $iRank = (float)$oRank->textContent;
- }
-
- $oNewDashlet = $this->InitDashletFromDOMNode($oDomNode);
- $aDashletOrder[] = ['rank' => $iRank, 'dashlet' => $oNewDashlet];
- }
- usort($aDashletOrder, [get_class($this), 'SortOnRank']);
- $aDashletList = [];
- foreach ($aDashletOrder as $aItem) {
- $aDashletList[] = $aItem['dashlet'];
- }
- $aCellOrder[] = ['rank' => $iCellRank, 'dashlets' => $aDashletList];
- }
- }
- usort($aCellOrder, [get_class($this), 'SortOnRank']);
- foreach ($aCellOrder as $aItem) {
- $this->aCells[] = $aItem['dashlets'];
- }
- } else {
- $this->aCells = [];
- }
- }
-
- /**
- * @param \DOMDocument $oDoc
- */
- public function FromDOMDocumentV2(DesignDocument $oDoc)
- {
- $this->oDOMNode = $oDoc->getElementsByTagName('dashboard')->item(0);
-
- $this->sLayoutClass = DashboardLayoutGrid::class;
- $this->sTitle = $this->oDOMNode->GetChildText('title', '');
-
- $iRefresh = intval($this->oDOMNode->GetChildText('refresh', '0'));
-
- $this->bAutoReload = $iRefresh > 0;
- $this->iAutoReloadSec = $iRefresh;
-
- $oDashletsNode = $this->oDOMNode->GetUniqueElement('pos_dashlets');
- $oDashletList = $oDashletsNode->getElementsByTagName('pos_dashlet');
- foreach ($oDashletList as $oPosDashletNode) {
- $aGridDashlet = [];
- $aGridDashlet['position_x'] = intval($oPosDashletNode->GetChildText('position_x', '0'));
- $aGridDashlet['position_y'] = intval($oPosDashletNode->GetChildText('position_y', '0'));
- $aGridDashlet['width'] = intval($oPosDashletNode->GetChildText('width', '2'));
- $aGridDashlet['height'] = intval($oPosDashletNode->GetChildText('height', '1'));
- $oDashletNode = $oPosDashletNode->GetUniqueElement('dashlet');
- $sId = $oPosDashletNode->getAttribute('id');
- $oDashlet = $this->InitDashletFromDOMNode($oDashletNode);
- $oDashlet->SetID($sId);
- $aGridDashlet['dashlet'] = $oDashlet;
- $this->aGridDashlets[] = $aGridDashlet;
- }
- }
-
- /**
- * @param DesignElement $oDomNode
- *
- * @return mixed
- */
- protected function InitDashletFromDOMNode($oDomNode)
- {
- $sId = $oDomNode->getAttribute('id');
-
- $sDashletType = $oDomNode->getAttribute('xsi:type');
-
- // Test if dashlet can be instantiated, otherwise (uninstalled, broken, ...) we display a placeholder
- $sClass = static::GetDashletClassFromType($sDashletType);
- /** @var \Dashlet $oNewDashlet */
- $oNewDashlet = $this->oDashletFactory->CreateDashlet($sClass, $sId);
- $oNewDashlet->FromDOMNode($oDomNode);
-
- return $oNewDashlet;
- }
-
- /**
- * @param array $aItem1
- * @param array $aItem2
- *
- * @return int
- */
- public static function SortOnRank($aItem1, $aItem2)
- {
- return ($aItem1['rank'] > $aItem2['rank']) ? +1 : -1;
- }
-
- /**
- * Error handler to turn XML loading warnings into exceptions
- *
- * @param $errno
- * @param $errstr
- * @param $errfile
- * @param $errline
- *
- * @return bool
- * @throws \DOMException
- */
- public static function ErrorHandler($errno, $errstr, $errfile, $errline)
- {
- if ($errno == E_WARNING && (substr_count($errstr, "DOMDocument::loadXML()") > 0)) {
- throw new DOMException($errstr);
- } else {
- return false;
- }
- }
-
- /**
- * @return string
- * @throws \Exception
- */
- public function ToXml()
- {
- $oMainNode = $this->CreateEmptyDashboard();
-
- $this->ToDOMNode($oMainNode);
-
- $sXml = $oMainNode->ownerDocument->saveXML();
-
- return $sXml;
- }
-
- /**
- * @return DesignElement
- * @throws \DOMException
- */
- public function CreateEmptyDashboard(): DesignElement
- {
- $oDoc = new DesignDocument();
- $oDoc->formatOutput = true; // indent (must be loaded with option LIBXML_NOBLANKS)
- $oDoc->preserveWhiteSpace = true; // otherwise the formatOutput option would have no effect
-
- /** @var DesignElement $oMainNode */
- $oMainNode = $oDoc->createElement('dashboard');
- $oMainNode->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
- $oDoc->appendChild($oMainNode);
-
- return $oMainNode;
- }
-
- /**
- * @param \DOMElement $oDefinition
- */
- public function ToDOMNode($oDefinition)
- {
- /** @var \DOMDocument $oDoc */
- $oDoc = $oDefinition->ownerDocument;
-
- $oNode = $oDoc->createElement('layout', $this->sLayoutClass);
- $oDefinition->appendChild($oNode);
-
- $oNode = $oDoc->createElement('title', $this->sTitle);
- $oDefinition->appendChild($oNode);
-
- $oAutoReloadNode = $oDoc->createElement('auto_reload');
- $oDefinition->appendChild($oAutoReloadNode);
- $oNode = $oDoc->createElement('enabled', $this->bAutoReload ? 'true' : 'false');
- $oAutoReloadNode->appendChild($oNode);
- $oNode = $oDoc->createElement('interval', $this->iAutoReloadSec);
- $oAutoReloadNode->appendChild($oNode);
-
- $oCellsNode = $oDoc->createElement('cells');
- $oDefinition->appendChild($oCellsNode);
-
- $iCellRank = 0;
- foreach ($this->aCells as $aCell) {
- $oCellNode = $oDoc->createElement('cell');
- $oCellNode->setAttribute('id', $iCellRank);
- $oCellsNode->appendChild($oCellNode);
- $oCellRank = $oDoc->createElement('rank', $iCellRank);
- $oCellNode->appendChild($oCellRank);
- $iCellRank++;
-
- $iDashletRank = 0;
- $oDashletsNode = $oDoc->createElement('dashlets');
- $oCellNode->appendChild($oDashletsNode);
- /** @var \Dashlet $oDashlet */
- foreach ($aCell as $oDashlet) {
- $oNode = $oDoc->createElement('dashlet');
- $oDashletsNode->appendChild($oNode);
- $oNode->setAttribute('id', $oDashlet->GetID());
- $oNode->setAttribute('xsi:type', $oDashlet->GetDashletType());
- $oDashletRank = $oDoc->createElement('rank', $iDashletRank);
- $oNode->appendChild($oDashletRank);
- $iDashletRank++;
- $oDashlet->ToDOMNode($oNode);
- }
- }
- }
-
- /**
- * @param array $aParams
- */
- public function FromParams($aParams)
- {
- $this->sLayoutClass = $aParams['layout_class'];
- if (!is_subclass_of($this->sLayoutClass, DashboardLayout::class)) {
- throw new InvalidParameterException('Invalid parameter layout_class "'.$aParams['layout_class'].'"');
- }
- $this->sTitle = $aParams['title'];
- $this->bAutoReload = $aParams['auto_reload'] == 'true';
- $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$aParams['auto_reload_sec']);
-
- foreach ($aParams['cells'] as $aCell) {
- $aCellDashlets = [];
- foreach ($aCell as $aDashletParams) {
- $sDashletClass = $aDashletParams['dashlet_class'];
- $sId = $aDashletParams['dashlet_id'];
- /** @var \Dashlet $oNewDashlet */
- $oNewDashlet = $this->oDashletFactory->CreateDashlet($sDashletClass, $sId);
- if (isset($aDashletParams['dashlet_type'])) {
- $oNewDashlet->SetDashletType($aDashletParams['dashlet_type']);
- }
- $oForm = $oNewDashlet->GetForm();
- $oForm->SetParamsContainer($sId);
- $oForm->SetPrefix('');
- $aValues = $oForm->ReadParams();
- $oNewDashlet->FromParams($aValues);
- $aCellDashlets[] = $oNewDashlet;
- }
- $this->aCells[] = $aCellDashlets;
- }
-
- }
-
- public function Save()
- {
- }
-
- public function PersistDashboard(string $sXml): bool
- {
- return true;
- }
-
- /**
- * @return mixed
- */
- public function GetId()
- {
- return $this->sId;
- }
-
- /**
- * Return a sanitize ID for usages in XML/HTML attributes
- *
- * @return string
- * @since 2.7.0
- */
- public function GetSanitizedId()
- {
- return utils::Sanitize($this->GetId(), '', 'element_identifier');
- }
-
- /**
- * @return string
- */
- public function GetLayout()
- {
- return $this->sLayoutClass;
- }
-
- /**
- * @param string $sLayoutClass
- */
- public function SetLayout($sLayoutClass)
- {
- $this->sLayoutClass = $sLayoutClass;
- }
-
- /**
- * @return string
- */
- public function GetTitle()
- {
- return $this->sTitle;
- }
-
- /**
- * @param string $sTitle
- */
- public function SetTitle($sTitle)
- {
- $this->sTitle = $sTitle;
- }
-
- /**
- * @return bool
- */
- public function GetAutoReload()
- {
- return $this->bAutoReload;
- }
-
- /**
- * @param bool $bAutoReload
- */
- public function SetAutoReload($bAutoReload)
- {
- $this->bAutoReload = $bAutoReload;
- }
-
- /**
- * @return float|int
- */
- public function GetAutoReloadInterval()
- {
- return $this->iAutoReloadSec;
- }
-
- /**
- * @param bool $iAutoReloadSec
- */
- public function SetAutoReloadInterval($iAutoReloadSec)
- {
- $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$iAutoReloadSec);
- }
-
- /**
- * @param \Dashlet $oDashlet
- */
- public function AddDashlet($oDashlet)
- {
- $sId = $this->GetNewDashletId();
- $oDashlet->SetId($sId);
- $this->aCells[] = [$oDashlet];
- }
-
- /**
- * @param WebPage $oPage *
- * @param array $aExtraParams
- *
- * @throws \ReflectionException
- * @throws \Exception
- */
- public function RenderProperties($oPage, $aExtraParams = [])
- {
- // menu to pick a layout and edit other properties of the dashboard
- $oPage->add('');
- $sUrl = utils::GetAbsoluteUrlAppRoot();
-
- $oPage->add('
'.Dict::S('UI:DashboardEdit:Layout').'
');
- $oPage->add('
');
-
- $oForm = new DesignerForm();
-
- $oField = new DesignerHiddenField('dashboard_id', '', $this->sId);
- $oForm->AddField($oField);
-
- $oField = new DesignerTextField('dashboard_title', Dict::S('UI:DashboardEdit:DashboardTitle'), $this->sTitle);
- $oForm->AddField($oField);
-
- $oField = new DesignerBooleanField('auto_reload', Dict::S('UI:DashboardEdit:AutoReload'), $this->bAutoReload);
- $oForm->AddField($oField);
-
- $oField = new DesignerIntegerField('auto_reload_sec', Dict::S('UI:DashboardEdit:AutoReloadSec'), $this->iAutoReloadSec);
- $oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit
- $oForm->AddField($oField);
-
- $this->SetFormParams($oForm, $aExtraParams);
- $oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
-
- $oPage->add('
');
-
- $sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval')));
- $oPage->add_ready_script(
- <<GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
-
- /** @var \DashboardLayout $oLayout */
- $oLayout = new $this->sLayoutClass();
-
- foreach ($this->aCells as $iCellIdx => $aDashlets) {
- foreach ($aDashlets as $oDashlet) {
- $aDashletCoordinates = $oLayout->GetDashletCoordinates($iCellIdx);
- $this->PrepareDashletForRendering($oDashlet, $aDashletCoordinates, $aExtraParams);
- }
- }
-
- if (count($this->aCells) > 0) {
- $aDashlets = $this->aCells;
- } else {
- $aDashlets = $this->aGridDashlets;
- }
-
- $oDashboard = $oLayout->Render($oPage, $aDashlets, $bEditMode, $aExtraParams);
- $oPage->AddUiBlock($oDashboard);
-
- $bFromDasboardPage = isset($aExtraParams['from_dashboard_page']) ? isset($aExtraParams['from_dashboard_page']) : false;
-
- if ($bFromDasboardPage) {
- $sTitleForHTML = utils::HtmlEntities(Dict::S($this->sTitle));
- $sHtml = "{$sTitleForHTML}
";
- if ($oPage instanceof iTopWebPage) {
- $oTopBar = $oPage->GetTopBarLayout();
- $oToolbar = ToolbarUIBlockFactory::MakeStandard();
- $oTopBar->SetToolbar($oToolbar);
-
- $oToolbar->AddHtml($sHtml);
- } else {
- $oPage->add_script(
- <<').html("$sTitleForHTML").text());
-JS
- );
- }
- } else {
- $oDashboard->SetTitle(Dict::S($this->sTitle));
- }
-
- if (!$bEditMode) {
- $oPage->LinkScriptFromAppRoot('js/dashlet.js');
- $oPage->LinkScriptFromAppRoot('js/dashboard.js');
- }
-
- return $oDashboard;
- }
-
- /**
- * @param WebPage $oPage
- *
- * @throws \ReflectionException
- * @throws \Exception
- */
- public function RenderDashletsSelection(WebPage $oPage)
- {
- // Toolbox/palette to drag and drop dashlets
- $oPage->add('');
- $sUrl = utils::GetAbsoluteUrlAppRoot();
-
- $oPage->add('
');
- $aAvailableDashlets = $this->GetAvailableDashlets();
- foreach ($aAvailableDashlets as $sDashletClass => $aInfo) {
- $oPage->add('

');
- }
- $oPage->add('
');
-
- $oPage->add('
');
- $oPage->add_ready_script("$('.dashlet_icon').draggable({cursor: 'move', helper: 'clone', appendTo: 'body', zIndex: 10000, revert:'invalid'});");
- }
-
- /**
- * @param WebPage $oPage
- * @param array $aExtraParams
- */
- public function RenderDashletsProperties(WebPage $oPage, $aExtraParams = [])
- {
- // Toolbox/palette to edit the properties of each dashlet
- $oPage->add('');
-
- /** @var \DashboardLayoutMultiCol $oLayout */
- $oLayout = new $this->sLayoutClass();
-
- $oPage->add('
');
- foreach ($this->aCells as $iCellIdx => $aCell) {
- /** @var \Dashlet $oDashlet */
- foreach ($aCell as $oDashlet) {
- if ($oDashlet->IsVisible()) {
- $oPage->add('
');
- $oForm = $oDashlet->GetForm();
- $this->SetFormParams($oForm, $aExtraParams);
- $oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard');
- $oPage->add('
');
- }
- }
- }
- $oPage->add('
');
-
- $oPage->add('
');
- }
-
- /**
- * Return an array of dashlets available for selection.
- *
- * @return array
- * @throws \Combodo\iTop\Application\Dashlet\DashletException
- * @throws \DOMFormatException
- */
- protected function GetAvailableDashlets(): array
- {
- return DashletService::GetInstance()->GetAvailableDashlets();
- }
-
- /**
- * @return int|mixed
- */
- protected function GetNewDashletId()
- {
- $iNewId = 0;
- foreach ($this->aCells as $aDashlets) {
- /** @var \Dashlet $oDashlet */
- foreach ($aDashlets as $oDashlet) {
- $iNewId = max($iNewId, (int)$oDashlet->GetID());
- }
- }
-
- return $iNewId + 1;
- }
-
- /**
- * Prepare dashlet for rendering (eg. change its ID or another processing).
- * Meant to be overloaded.
- *
- * @param \Dashlet $oDashlet
- * @param array $aCoordinates
- * @param array $aExtraParams
- *
- * @return void
- */
- abstract protected function PrepareDashletForRendering(Dashlet $oDashlet, $aCoordinates, $aExtraParams = []);
-
- /**
- * @param \DesignerForm $oForm
- * @param array $aExtraParams
- *
- * @return mixed
- */
- abstract protected function SetFormParams($oForm, $aExtraParams = []);
-
- /**
- * @param string $sType
- * @param \ModelFactory|null $oFactory
- *
- * @return string
- */
- public static function GetDashletClassFromType($sType, $oFactory = null)
- {
- if (is_subclass_of($sType, 'Dashlet')) {
- return $sType;
- }
-
- return 'DashletUnknown';
- }
-
- /**
- * N°2634: we must have a unique id per dashlet!
- * To avoid collision with other dashlets with the same ID we prefix it with row/cell id
- * Collisions typically happen with extensions.
- *
- * @param boolean $bIsCustomized
- * @param string $sDashboardDivId
- * @param int $iRow
- * @param int $iCol
- * @param string $sDashletOrigId
- *
- * @return string
- *
- * @since 2.7.0 N°2735
- */
- public static function GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCol, $sDashletOrigId)
- {
- if (strpos($sDashletOrigId, '_ID_row') !== false) {
- return $sDashletOrigId;
- }
-
- $sDashletId = $sDashboardDivId."_ID_row".$iRow."_col".$iCol."_".$sDashletOrigId;
- if ($bIsCustomized) {
- $sDashletId = 'CUSTOM_'.$sDashletId;
- }
-
- return $sDashletId;
- }
-}
-
/**
* Class RuntimeDashboard
*/
diff --git a/sources/alias.php b/sources/alias.php
index 725504fa5..6e509a5aa 100644
--- a/sources/alias.php
+++ b/sources/alias.php
@@ -97,7 +97,8 @@ class_alias(\Combodo\iTop\Core\AttributeDefinition\AttributeURL::class, 'Attribu
class_alias(\Combodo\iTop\Core\AttributeDefinition\iAttributeNoGroupBy::class, 'iAttributeNoGroupBy');
class_alias(\Combodo\iTop\Core\AttributeDefinition\MissingColumnException::class, 'MissingColumnException');
-// Dashlets
+// Dashboards/Dashlets
+class_alias(\Combodo\iTop\Application\Dashboard\Dashboard::class, 'Dashboard');
class_alias(\Combodo\iTop\Application\Dashlet\Dashlet::class, 'Dashlet');
class_alias(\Combodo\iTop\Application\Dashlet\Base\DashletBadge::class, 'DashletBadge');
class_alias(\Combodo\iTop\Application\Dashlet\Base\DashletGroupBy::class, 'DashletGroupBy');