-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
322 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
|
||
/** Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */ | ||
|
||
namespace Icinga\Module\Icingadb\Hook; | ||
|
||
use Icinga\Application\Hook; | ||
use Icinga\Application\Logger; | ||
use Icinga\Module\Icingadb\Hook\Common\HookUtils; | ||
use ipl\Orm\Model; | ||
use Throwable; | ||
|
||
abstract class CustomVarEnricherHook | ||
{ | ||
use HookUtils; | ||
|
||
/** | ||
* Return the grouped custom vars | ||
* | ||
* @return array | ||
*/ | ||
abstract public function getGroups(): array; | ||
|
||
/** | ||
* Return a group name for the given variable name | ||
* | ||
* @param array $vars | ||
* | ||
* @return array | ||
*/ | ||
abstract public function enrichCustomVars(array $vars, Model $object): array; | ||
|
||
public static function prepareCustomEnrichedVar(array $vars, Model $object): array | ||
{ | ||
$enrichedVars = []; | ||
|
||
$groups = []; | ||
foreach (Hook::all('Icingadb/CustomVarRenderer') as $hook) { | ||
/** @var self $hook */ | ||
try { | ||
$enrichedVars[] = $hook->enrichCustomVars($vars, $object); | ||
$groups[] = $hook->getGroups(); | ||
} catch (Throwable $e) { | ||
Logger::error('Failed to load hook %s:', get_class($hook), $e); | ||
} | ||
} | ||
|
||
$enrichedVars = array_merge([], ...$enrichedVars); | ||
$groups = array_merge([], ...$groups); | ||
foreach ($vars as $key => $var) { | ||
if (array_key_exists($key, $enrichedVars)) { | ||
$label = key($enrichedVars[$key]); | ||
$vars[$label] = $enrichedVars[$key][$label]; | ||
|
||
unset($vars[$key]); | ||
|
||
$key = $label; | ||
} | ||
|
||
foreach ($groups as $group) { | ||
if (array_key_exists($key, $group)) { | ||
unset($vars[$key]); | ||
|
||
break; | ||
} | ||
} | ||
} | ||
|
||
return [$vars, $groups]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
/** Icinga DB Web | (c) 2024 Icinga GmbH | GPLv2 */ | ||
|
||
namespace Icinga\Module\Icingadb\Common; | ||
|
||
use ipl\Html\BaseHtmlElement; | ||
use ipl\Html\ValidHtml; | ||
|
||
class CustomVarItem extends BaseHtmlElement | ||
{ | ||
// TODO: Class for an item in custom HTML Section | ||
protected $item; | ||
|
||
public function __construct(ValidHtml $item) | ||
{ | ||
$this->item = $item; | ||
} | ||
|
||
protected function assemble() | ||
{ | ||
$this->addHtml($this->item); | ||
} | ||
} |
178 changes: 178 additions & 0 deletions
178
library/Icingadb/ProvidedHook/Icingadb/CustomVarRenderer.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
<?php | ||
|
||
namespace Icinga\Module\Icingadb\ProvidedHook\Icingadb; | ||
|
||
use Icinga\Application\Config; | ||
use Icinga\Module\Director\Data\Db\DbConnection; | ||
use Icinga\Module\Director\DataType\DataTypeDatalist; | ||
use Icinga\Module\Director\DataType\DataTypeDictionary; | ||
use Icinga\Module\Director\Db; | ||
use Icinga\Module\Director\Objects\IcingaHost; | ||
use Icinga\Module\Director\Objects\IcingaService; | ||
use Icinga\Module\Director\Web\Form\IcingaObjectFieldLoader; | ||
use Icinga\Module\Icingadb\Hook\CustomVarRendererHook; | ||
use Icinga\Module\Icingadb\Model\Host; | ||
use Icinga\Module\Icingadb\Model\Service; | ||
use ipl\Orm\Model; | ||
|
||
class CustomVarRenderer extends CustomVarRendererHook | ||
{ | ||
protected $fieldConfig; | ||
|
||
protected $datalistMaps; | ||
|
||
protected $groups = []; | ||
|
||
public function prefetchForObject(Model $object): bool | ||
{ | ||
return false; | ||
} | ||
|
||
public function renderCustomVarKey(string $key) | ||
{ | ||
return $key; | ||
} | ||
|
||
public function renderCustomVarValue(string $key, $value) | ||
{ | ||
return $value; | ||
} | ||
|
||
public function identifyCustomVarGroup(string $key): ?string | ||
{ | ||
return null; | ||
} | ||
|
||
public function enrichCustomVars(array $vars, Model $object): array | ||
{ | ||
$directorObject = null; | ||
$connection = Db::fromResourceName(Config::module('director')->get('db', 'resource')); | ||
if ($object instanceof Host) { | ||
$directorObject = IcingaHost::load($object->name, $connection); | ||
} elseif ($object instanceof Service) { | ||
$directorHost = IcingaHost::load($object->host->name, $connection); | ||
$directorObject = IcingaService::load( | ||
['object_name' => $object->name, 'host_id' => $directorHost->get('id')], | ||
$connection | ||
); | ||
} | ||
|
||
$newVars = []; | ||
$this->fieldConfig = (new IcingaObjectFieldLoader($directorObject))->getFields(); | ||
|
||
$this->buildDataListMap($connection); | ||
if ($directorObject) { | ||
foreach ($vars as $varName => $customVar) { | ||
$newVars[$varName] = $this->resolveCustomVarMapping($varName, $customVar, $connection); | ||
} | ||
} else { | ||
$newVars = $vars; | ||
} | ||
|
||
return $newVars; | ||
} | ||
|
||
/** | ||
* Returns the resolved mapping to custom variables in Director | ||
* | ||
* @param string $name | ||
* @param $val | ||
* @param DbConnection $conn | ||
* @param bool $grouping Whether to enable grouping of custom variables into sections | ||
* | ||
* @return array | ||
*/ | ||
protected function resolveCustomVarMapping(string $name, $val, DbConnection $conn, bool $grouping = true): array | ||
{ | ||
if (isset($this->fieldConfig[$name])) { | ||
$field = $this->fieldConfig[$name]; | ||
$dataType = $field->get('datatype'); | ||
|
||
if ($dataType === get_class(new DataTypeDictionary())) { | ||
$newVarValue = []; | ||
foreach ($val as $nestedVarName => $nestedVarValue) { | ||
if (isset($this->fieldConfig[$nestedVarName]) && is_array($nestedVarValue)) { | ||
$childValues = []; | ||
foreach ($nestedVarValue as $childName => $childValue) { | ||
$childValues[] = $this->resolveCustomVarMapping($childName, $childValue, $conn, false); | ||
} | ||
|
||
$newVarValue[] = [$nestedVarName => array_merge([], ...$childValues)]; | ||
} else { | ||
$newVarValue[] = [ | ||
$nestedVarName => $this->resolveCustomVarMapping( | ||
$nestedVarName, | ||
$nestedVarValue, | ||
$conn, | ||
false | ||
) | ||
]; | ||
} | ||
} | ||
|
||
return [$field->get('caption') => array_merge([], ...$newVarValue)]; | ||
} elseif ($dataType === get_class(new DataTypeDatalist())) { | ||
if (isset($this->datalistMaps[$name])) { | ||
$val = $this->datalistMaps[$name][$val]; | ||
} | ||
|
||
$name = $field->get('caption'); | ||
} else { | ||
$name = $field->get('caption'); | ||
} | ||
|
||
if ($grouping && $field->get('category_id') !== null) { | ||
if (! isset($this->groups[$field->getCategoryName()])) { | ||
$this->groups[$field->getCategoryName()] = [$name => $val]; | ||
} else { | ||
$this->groups[$field->getCategoryName()][$name] = $val; | ||
} | ||
} | ||
} elseif (is_array($val)) { | ||
$newValue = []; | ||
foreach ($val as $childName => $childValue) { | ||
$newValue[] = $this->resolveCustomVarMapping($childName, $childValue, $conn, false); | ||
} | ||
|
||
$val = array_merge([], ...$newValue); | ||
} | ||
|
||
return [$name => $val]; | ||
} | ||
|
||
private function buildDataListMap(DbConnection $db) | ||
{ | ||
$fieldsWithDataLists = []; | ||
foreach ($this->fieldConfig as $field) { | ||
if ($field->get('datatype') === 'Icinga\Module\Director\DataType\DataTypeDatalist') { | ||
$fieldsWithDataLists[$field->get('id')] = $field; | ||
} | ||
} | ||
|
||
if (! empty($fieldsWithDataLists)) { | ||
$dataListEntries = $db->select()->from( | ||
['dds' => 'director_datafield_setting'], | ||
[ | ||
'dds.datafield_id', | ||
'dde.entry_name', | ||
'dde.entry_value' | ||
] | ||
)->join( | ||
['dde' => 'director_datalist_entry'], | ||
'CAST(dds.setting_value AS integer) = dde.list_id', | ||
[] | ||
)->where('dds.datafield_id', array_keys($fieldsWithDataLists)) | ||
->where('dds.setting_name', 'datalist_id'); | ||
|
||
foreach ($dataListEntries as $dataListEntry) { | ||
$field = $fieldsWithDataLists[$dataListEntry->datafield_id]; | ||
$this->datalistMaps[$field->get('varname')][$dataListEntry->entry_name] = $dataListEntry->entry_value; | ||
} | ||
} | ||
} | ||
|
||
public function getGroups(): array | ||
{ | ||
return $this->groups; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
library/Icingadb/ProvidedHook/Icingadb/CustomVarSection.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
/** Icinga DB Web | (c) 2024 Icinga GmbH | GPLv2 */ | ||
|
||
namespace Icinga\Module\Icingadb\Common; | ||
|
||
use ipl\Html\BaseHtmlElement; | ||
|
||
class CustomVarSection extends BaseHtmlElement | ||
{ | ||
// TODO: Class for custom HTML section | ||
protected $items; | ||
|
||
public function addItem(CustomVarItem $item) | ||
{ | ||
$this->items[] = $item; | ||
} | ||
|
||
public function assemble() | ||
{ | ||
$this->addHtml($this->items); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters