Skip to content

Commit

Permalink
ObjectsRendererHook: Add implementation to fetch object name as string
Browse files Browse the repository at this point in the history
  • Loading branch information
raviks789 committed May 28, 2024
1 parent cc852e0 commit e5786fb
Showing 1 changed file with 98 additions and 12 deletions.
110 changes: 98 additions & 12 deletions library/Notifications/Hook/ObjectsRendererHook.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Icinga\Application\Hook;
use Icinga\Application\Logger;
use Icinga\Module\Notifications\Model\Objects;
use ipl\Html\Attributes;
use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\Html\ValidHtml;
use ipl\Web\Url;
Expand Down Expand Up @@ -37,6 +39,26 @@ abstract class ObjectsRendererHook
*/
private static $objectNameHtmls = [];

/**
* Array of object names with their corresponding object IDs as keys
*
* It has the following structure : ['object ID' => 'object name'].
*
* @var array<string, string>
*/
private static $objectNames = [];

/**
* Get the object names for the objects using the object ID tags
*
* @param array<array<string, string>> $objectIdTags Array of object ID tags with their corresponding
* object IDs as keys. It has the following structure:
* ['object ID' => [object ID tags]]
*
* @return Generator<array<string, string>, string> Generator for object names with their object ID tags as keys
*/
abstract public function getObjectNames(array $objectIdTags): Generator;

/**
* Get the HTML for the object names for the objects using the object ID tags
*
Expand Down Expand Up @@ -80,11 +102,13 @@ final public static function register(Objects $obj): void
/**
* Load HTMLs to be rendered for the object names to the cache using the cached objects
*
* @param bool $asHtml If true loads object names as HTMLs otherwise as tring
*
* @return void
*/
final public static function load(): void
final public static function load(bool $asHtml = true): void
{
self::prepare(self::$objectIdTags);
self::prepare(self::$objectIdTags, $asHtml); // Prepare object names as HTML or string

self::$objectIdTags = [];
}
Expand All @@ -96,15 +120,17 @@ final public static function load(): void
* ['object source type' => ['object ID' => [object ID tags]]].
*
* @param array<string, array<string, array<string, string>>> $objectIdTags Array of object ID tags for each source
* @param bool $asHtml When true, object names are prepared as HTML otherwise as string
*
* @return void
*/
private static function prepare(array $objectIdTags): void
private static function prepare(array $objectIdTags, bool $asHtml = true): void
{
$idTagToObjectIdMap = [];
$objectNames = $asHtml ? self::$objectNameHtmls : self::$objectNames;
foreach ($objectIdTags as $sourceType => $objects) {
foreach ($objects as $objectId => $tags) {
if (! isset(self::$objectNameHtmls[$objectId])) {
if (! isset($objectNames[$objectId])) {
$idTagToObjectIdMap[$sourceType][] = [$objectId, $tags];
}
}
Expand All @@ -125,13 +151,31 @@ function ($object) {
$idTagToObjectIdMap[$source]
);

$objectNamesFromSource = $asHtml
? $hook->getHtmlForObjectNames($objectIDTagsForSource)
: $hook->getObjectNames($objectIDTagsForSource);

/** @var array $objectIdTag */
foreach ($hook->getHtmlForObjectNames($objectIDTagsForSource) as $objectIdTag => $validHtml) {
foreach ($objectNamesFromSource as $objectIdTag => $objectName) {
foreach ($idTagToObjectIdMap[$source] as $key => $val) {
$diff = array_intersect_assoc($val[1], $objectIdTag);
if (count($diff) === count($val[1])) {
unset($idTagToObjectIdMap[$key]);
$objectDisplayNames[$val[0]] = $validHtml;

if ($asHtml) {
$objectName = HtmlElement::create(
'div',
Attributes::create([
'class' => [
'icinga-module',
'module-' . ($source === 'icinga2' ? 'icingadb' : $source)
]
]),
$objectName
);
}

$objectDisplayNames[$val[0]] = $objectName;

continue 2;
}
Expand All @@ -143,7 +187,11 @@ function ($object) {
}
}

self::$objectNameHtmls += $objectDisplayNames;
if ($asHtml) {
self::$objectNameHtmls += $objectDisplayNames;
} else {
self::$objectNames += $objectDisplayNames;
}
}

/**
Expand All @@ -166,15 +214,46 @@ final public static function getObjectName(Objects $obj): ValidHtml
return self::$objectNameHtmls[$objId];
}

self::$objectNameHtmls[$objId] = new HtmlString(self::createOrFetchObjectNameAsString($obj));

return self::$objectNameHtmls[$objId];
}

/**
* Get the object name of the given object as string
*
* If the object name is not loaded, it is prepared using object ID tags and the same is returned.
*
* @param Objects $obj
* @param bool $prepare If true prepares the object name string from the hook implementation if it is not
* already present in the cache
*
* @return string
*/
final public static function getObjectNameAsString(Objects $obj): string
{
$objId = $obj->id;
if (! isset(self::$objectNames[$objId])) {
self::prepare([$obj->source->type => [$objId => $obj->id_tags]], false);
}

return self::createObjectNameAsString($obj);
}

private static function createObjectNameAsString(Objects $obj)
{
$objId = $obj->id;
if (isset(self::$objectNames[$objId])) {
return self::$objectNames[$objId];
}

$objectTags = [];

foreach ($obj->id_tags as $tag => $value) {
$objectTags[] = sprintf('%s=%s', $tag, $value);
}

self::$objectNameHtmls[$objId] = new HtmlString(implode(', ', $objectTags));

return self::$objectNameHtmls[$objId];
return implode(', ', $objectTags);
}

/**
Expand All @@ -189,8 +268,15 @@ final public static function renderObjectLink(Objects $object): ?ValidHtml
/** @var self $hook */
foreach (Hook::all('Notifications\\ObjectsRenderer') as $hook) {
try {
if ($object->source->type === $hook->getSourceType()) {
return $hook->createObjectLink($object->id_tags);
$sourceType = $hook->getSourceType();
if ($object->source->type === $sourceType) {
return $hook->createObjectLink($object->id_tags)
->addAttributes([
'class' => [
'icinga-module',
'module-' . ($sourceType === 'icinga2' ? 'icingadb' : $sourceType)
]
]);
}
} catch (Exception $e) {
Logger::error('Failed to load hook %s:', get_class($hook), $e);
Expand Down

0 comments on commit e5786fb

Please sign in to comment.