From 8044a550c10e1501fae7f4cdeb907aeef45c2e5f Mon Sep 17 00:00:00 2001 From: raviks789 Date: Wed, 28 Aug 2024 11:56:36 +0200 Subject: [PATCH] Icingadb/CustomVarRenderer: Render key and values as HtmlElements --- .../Icingadb/CustomVarRenderer.php | 176 ++++++++++++++++-- 1 file changed, 159 insertions(+), 17 deletions(-) diff --git a/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php b/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php index 7252840ca..717bb491c 100644 --- a/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php +++ b/library/Director/ProvidedHook/Icingadb/CustomVarRenderer.php @@ -12,6 +12,11 @@ use Icinga\Module\Icingadb\Hook\CustomVarRendererHook; use Icinga\Module\Icingadb\Model\Host; use Icinga\Module\Icingadb\Model\Service; +use ipl\Html\Attributes; +use ipl\Html\Html; +use ipl\Html\HtmlElement; +use ipl\Html\Text; +use ipl\Html\ValidHtml; use ipl\Orm\Model; class CustomVarRenderer extends CustomVarRendererHook @@ -25,6 +30,14 @@ class CustomVarRenderer extends CustomVarRendererHook /** @var array Related dictionary field names */ protected $dictionaryNames = []; + protected $dictionaryLevel = 0; + + /** @var HtmlElement Table for dictionary fields */ + private $dictionaryTable; + + /** @var HtmlElement Table body for dictionary fields */ + private $dictionaryBody; + /** * Get a database connection to the director database * @@ -120,7 +133,11 @@ public function prefetchForObject(Model $object): bool public function renderCustomVarKey(string $key) { if (isset($this->fieldConfig[$key]['label'])) { - return $this->fieldConfig[$key]['label']; + return new HtmlElement( + 'span', + Attributes::create(['title' => $this->fieldConfig[$key]['label'] . " [$key]"]), + Text::create($this->fieldConfig[$key]['label']) + ); } return null; @@ -134,14 +151,13 @@ public function renderCustomVarValue(string $key, $value) } if (isset($this->datalistMaps[$key][$value])) { - return $this->datalistMaps[$key][$value]; -<<<<<<< Updated upstream - } elseif (in_array($key, $this->dictionaryNames)) { - return $this->renderDictionaryVal($value); -======= + return new HtmlElement( + 'span', + Attributes::create(['title' => $this->datalistMaps[$key][$value] . " [$value]"]), + Text::create($this->datalistMaps[$key][$value]) + ); } elseif ($value !== null && in_array($key, $this->dictionaryNames)) { return $this->renderDictionaryVal($key, (array) $value); ->>>>>>> Stashed changes } } @@ -158,25 +174,151 @@ public function identifyCustomVarGroup(string $key): ?string } /** - * Render the value of the dictionary + * Render the dictionary value * + * @param string $key * @param array $value * - * @return array + * @return ?ValidHtml */ - protected function renderDictionaryVal(array $value): array + protected function renderDictionaryVal(string $key, array $value): ?ValidHtml { - $newValue = []; + if ($this->dictionaryLevel > 0) { + $numItems = count($value); + $label = $this->renderCustomVarKey($key) ?? $key; + + $this->dictionaryBody->addHtml( + new HtmlElement( + 'tr', + Attributes::create(['class' => "level-{$this->dictionaryLevel}"]), + new HtmlElement('th', null, Html::wantHtml($label)), + new HtmlElement( + 'td', + null, + Text::create(sprintf(tp('%d item', '%d items', $numItems), $numItems)) + ) + ) + ); + } else { + $this->dictionaryTable = new HtmlElement( + 'table', + Attributes::create(['class' => ['custom-var-table', 'name-value-table']]) + ); + + $this->dictionaryBody = new HtmlElement('tbody'); + } + + $this->dictionaryLevel++; + foreach ($value as $key => $val) { - if (is_array($val)) { - foreach ($val as $subKey => $subVal) { - $label = $this->renderCustomVarKey($subKey) ?? $subKey; - $subVal = $this->renderCustomVarValue($subKey, $subVal) ?? $subVal; - $newValue[$key][$label] = $subVal; + if ($key !== null && is_array($val) || is_object($val)) { + $val = (array) $val; + $numChildItems = count($val); + + $this->dictionaryBody->addHtml( + new HtmlElement( + 'tr', + Attributes::create(['class' => "level-{$this->dictionaryLevel}"]), + new HtmlElement('th', null, Html::wantHtml($key)), + new HtmlElement( + 'td', + null, + Text::create(sprintf(tp('%d item', '%d items', $numChildItems), $numChildItems)) + ) + ) + ); + + $this->dictionaryLevel++; + foreach ($val as $childKey => $childVal) { + $childVal = $this->renderCustomVarValue($childKey, $childVal) ?? $childVal; + if (! in_array($childKey, $this->dictionaryNames)) { + $label = $this->renderCustomVarKey($childKey) ?? $childKey; + + if (is_array($childVal)) { + $this->renderArrayVal($label, $childVal); + } else { + $this->dictionaryBody->addHtml( + new HtmlElement( + 'tr', + Attributes::create(['class' => "level-{$this->dictionaryLevel}"]), + new HtmlElement('th', null, Html::wantHtml( + $label + )), + new HtmlElement('td', null, Html::wantHtml($childVal)) + ) + ); + } + } } + + $this->dictionaryLevel--; + } elseif (is_array($val)) { + $this->renderArrayVal($key, $val); + } else { + $this->dictionaryBody->addHtml( + new HtmlElement( + 'tr', + Attributes::create(['class' => "level-{$this->dictionaryLevel}"]), + new HtmlElement('th', null, Html::wantHtml($key)), + new HtmlElement('td', null, Html::wantHtml($val)) + ) + ); } } - return $newValue; + $this->dictionaryLevel--; + + if ($this->dictionaryLevel === 0) { + return $this->dictionaryTable->addHtml($this->dictionaryBody); + } + + return null; + } + + /** + * Render an array + * + * @param HtmlElement|string $name + * @param array $array + * + * @return void + */ + protected function renderArrayVal($name, array $array) + { + $numItems = count($array); + + if ($name instanceof HtmlElement) { + $name->addHtml(Text::create(' (Array)')); + } else { + $name = (new HtmlDocument())->addHtml( + Html::wantHtml($name), + Text::create(' (Array)') + ); + } + + $this->dictionaryBody->addHtml( + new HtmlElement( + 'tr', + Attributes::create(['class' => "level-{$this->dictionaryLevel}"]), + new HtmlElement('th', null, Html::wantHtml($name)), + new HtmlElement('td', null, Html::wantHtml(sprintf(tp('%d item', '%d items', $numItems), $numItems))) + ) + ); + + ++$this->dictionaryLevel; + + ksort($array); + foreach ($array as $key => $value) { + $this->dictionaryBody->addHtml( + new HtmlElement( + 'tr', + Attributes::create(['class' => "level-{$this->dictionaryLevel}"]), + new HtmlElement('th', null, Html::wantHtml("[$key]")), + new HtmlElement('td', null, Html::wantHtml($value)) + ) + ); + } + + --$this->dictionaryLevel; } }