blob: 7f880e811bc3adb7f7fb2c7e97407168a39e157a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
<?php
/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */
namespace Icinga\Module\Icingadb\Hook\ExtensionHook;
use Exception;
use Icinga\Application\Hook;
use Icinga\Application\Logger;
use Icinga\Exception\IcingaException;
use Icinga\Module\Icingadb\Hook\EventDetailExtensionHook;
use Icinga\Module\Icingadb\Hook\HostDetailExtensionHook;
use Icinga\Module\Icingadb\Hook\ServiceDetailExtensionHook;
use Icinga\Module\Icingadb\Hook\UserDetailExtensionHook;
use Icinga\Module\Icingadb\Hook\UsergroupDetailExtensionHook;
use Icinga\Module\Icingadb\Model\History;
use Icinga\Module\Icingadb\Model\Host;
use Icinga\Module\Icingadb\Model\Service;
use Icinga\Module\Icingadb\Model\User;
use Icinga\Module\Icingadb\Model\Usergroup;
use InvalidArgumentException;
use ipl\Html\Attributes;
use ipl\Html\HtmlElement;
use ipl\Html\HtmlString;
use ipl\Html\Text;
use ipl\Html\ValidHtml;
use ipl\Orm\Model;
use function ipl\Stdlib\get_php_type;
abstract class ObjectDetailExtensionHook extends BaseExtensionHook
{
/**
* Load all extensions for the given object
*
* @param Host|Service|User|Usergroup|History $object
*
* @return array<int, ValidHtml>
*
* @throws InvalidArgumentException If the given model is not supported
*/
final public static function loadExtensions(Model $object): array
{
switch (true) {
case $object instanceof Host:
$hookName = 'Icingadb\\HostDetailExtension';
break;
case $object instanceof Service:
$hookName = 'Icingadb\\ServiceDetailExtension';
break;
case $object instanceof User:
$hookName = 'Icingadb\\UserDetailExtension';
break;
case $object instanceof Usergroup:
$hookName = 'Icingadb\\UsergroupDetailExtension';
break;
case $object instanceof History:
$hookName = 'Icingadb\\EventDetailExtension';
break;
default:
throw new InvalidArgumentException(
sprintf('%s is not a supported object type', get_php_type($object))
);
}
$extensions = [];
$lastUsedLocations = [];
/**
* @var $hook HostDetailExtensionHook
* @var $hook ServiceDetailExtensionHook
* @var $hook UserDetailExtensionHook
* @var $hook UsergroupDetailExtensionHook
* @var $hook EventDetailExtensionHook
*/
foreach (Hook::all($hookName) as $hook) {
$location = $hook->getLocation();
if ($location < 0) {
$location = null;
}
if ($location === null) {
$section = $hook->getSection();
if (! isset(self::BASE_LOCATIONS[$section])) {
Logger::error('Detail extension %s is using an invalid section: %s', get_class($hook), $section);
$section = self::DETAIL_SECTION;
}
if (isset($lastUsedLocations[$section])) {
$location = ++$lastUsedLocations[$section];
} else {
$location = self::BASE_LOCATIONS[$section];
$lastUsedLocations[$section] = $location;
}
}
try {
// It may be ValidHtml, but modules shouldn't be able to break our views.
// That's why it needs to be rendered instantly, as any error will then
// be caught here.
$extension = (string) $hook->getHtmlForObject(clone $object);
$moduleName = $hook->getModule()->getName();
$extensions[$location] = new HtmlElement(
'div',
Attributes::create([
'class' => 'icinga-module module-' . $moduleName,
'data-icinga-module' => $moduleName
]),
HtmlString::create($extension)
);
} catch (Exception $e) {
Logger::error("Failed to load detail extension: %s\n%s", $e, $e->getTraceAsString());
$extensions[$location] = Text::create(IcingaException::describe($e));
}
}
return $extensions;
}
}
|