diff --git a/library/Icinga/Application/Hook.php b/library/Icinga/Application/Hook.php new file mode 100644 index 000000000..ed11cf458 --- /dev/null +++ b/library/Icinga/Application/Hook.php @@ -0,0 +1,256 @@ + + * Hook::register('grapher', 'My\\Grapher\\Class'); + * + */ +class Hook +{ + /** + * Our hook name registry + * + * @var array + */ + protected static $hooks = array(); + + /** + * Hooks that have already been instantiated + * + * @var array + */ + protected static $instances = array(); + + /** + * Namespace prefix + * + * @var string + */ + public static $BASE_NS = 'Icinga\\Application\\Hook\\'; + + /** + * Append this string to base class + * + * All base classes renamed to *Hook + * + * @var string + */ + public static $classSuffix = 'Hook'; + + /** + * Reset object state + */ + public static function clean() + { + self::$hooks = array(); + self::$instances = array(); + self::$BASE_NS = 'Icinga\\Application\\Hook\\'; + } + + /** + * Whether someone registered itself for the given hook name + * + * @param string $name One of the predefined hook names + * + * @return bool + */ + public static function has($name) + { + $name = self::normalizeHookName($name); + return array_key_exists($name, self::$hooks); + } + + protected static function normalizeHookName($name) + { + if (strpos($name, '\\') === false) { + $parts = explode('/', $name); + foreach ($parts as & $part) { + $part = ucfirst($part); + } + + return implode('\\', $parts); + } + + return $name; + } + + /** + * Create or return an instance of a given hook + * + * TODO: Should return some kind of a hook interface + * + * @param string $name One of the predefined hook names + * @param string $key The identifier of a specific subtype + * + * @return mixed + */ + public static function createInstance($name, $key) + { + $name = self::normalizeHookName($name); + + if (!self::has($name, $key)) { + return null; + } + + if (isset(self::$instances[$name][$key])) { + return self::$instances[$name][$key]; + } + + $class = self::$hooks[$name][$key]; + try { + $instance = new $class(); + } catch (Exception $e) { + Logger::debug( + 'Hook "%s" (%s) (%s) failed, will be unloaded: %s', + $name, + $key, + $class, + $e->getMessage() + ); + // TODO: Persist unloading for "some time" or "current session" + unset(self::$hooks[$name][$key]); + return null; + } + + self::assertValidHook($instance, $name); + self::$instances[$name][$key] = $instance; + return $instance; + } + + protected static function splitHookName($name) + { + $sep = '\\'; + if (false === $module = strpos($name, $sep)) { + return array(null, $name); + } + return array( + substr($name, 0, $module), + substr($name, $module + 1) + ); + } + + /** + * Test for a valid class name + * + * @param mixed $instance + * @param string $name + * + * @throws ProgrammingError + */ + private static function assertValidHook($instance, $name) + { + $name = self::normalizeHookName($name); + + $suffix = self::$classSuffix; // 'Hook' + $base = self::$BASE_NS; // 'Icinga\\Web\\Hook\\' + + list($module, $name) = self::splitHookName($name); + + if ($module === null) { + $base_class = $base . ucfirst($name) . 'Hook'; + + // I'm unsure whether this makes sense. Unused and Wrong. + if (strpos($base_class, $suffix) === false) { + $base_class .= $suffix; + } + } else { + $base_class = 'Icinga\\Module\\' + . ucfirst($module) + . '\\Hook\\' + . ucfirst($name) + . $suffix; + } + + if (!$instance instanceof $base_class) { + + // This is a compatibility check. Should be removed one far day: + if ($module !== null) { + $compat_class = 'Icinga\\Module\\' + . ucfirst($module) + . '\\Web\\Hook\\' + . ucfirst($name) + . $suffix; + + if ($instance instanceof $compat_class) { + return; + } + } + + throw new ProgrammingError( + '%s is not an instance of %s', + get_class($instance), + $base_class + ); + } + } + + /** + * Return all instances of a specific name + * + * @param string $name One of the predefined hook names + * + * @return array + */ + public static function all($name) + { + $name = self::normalizeHookName($name); + if (!self::has($name)) { + return array(); + } + + foreach (self::$hooks[$name] as $key => $hook) { + if (self::createInstance($name, $key) === null) { + return array(); + } + } + + return self::$instances[$name]; + } + + /** + * Get the first hook + * + * @param string $name One of the predefined hook names + * + * @return null|mixed + */ + public static function first($name) + { + $name = self::normalizeHookName($name); + + if (self::has($name)) { + return self::createInstance($name, key(self::$hooks[$name])); + } + } + + /** + * Register a class + * + * @param string $name One of the predefined hook names + * @param string $key The identifier of a specific subtype + * @param string $class Your class name, must inherit one of the + * classes in the Icinga/Application/Hook folder + */ + public static function register($name, $key, $class) + { + $name = self::normalizeHookName($name); + + if (!isset(self::$hooks[$name])) { + self::$hooks[$name] = array(); + } + + self::$hooks[$name][$key] = $class; + } +} diff --git a/library/Icinga/Application/Hook/GrapherHook.php b/library/Icinga/Application/Hook/GrapherHook.php new file mode 100644 index 000000000..b923d2978 --- /dev/null +++ b/library/Icinga/Application/Hook/GrapherHook.php @@ -0,0 +1,111 @@ +init(); + } + + /** + * Overwrite this function if you want to do some initialization stuff + * + * @return void + */ + protected function init() + { + } + + /** + * Whether this grapher provides previews + * + * @return bool + */ + public function hasPreviews() + { + return $this->hasPreviews; + } + + /** + * Whether this grapher provides tiny previews + * + * @return bool + */ + public function hasTinyPreviews() + { + return $this->hasTinyPreviews; + } + + /** + * Whether a graph for the monitoring object exist + * + * @param MonitoredObject $object + * + * @return bool + */ + abstract public function has(MonitoredObject $object); + + /** + * Get a preview for the given object + * + * This function must return an empty string if no graph exists. + * + * @param MonitoredObject $object + * + * @return string + * @throws ProgrammingError + * + */ + public function getPreviewHtml(MonitoredObject $object) + { + throw new ProgrammingError('This hook provide previews but it is not implemented'); + } + + + /** + * Get a tiny preview for the given object + * + * This function must return an empty string if no graph exists. + * + * @param MonitoredObject $object + * + * @return string + * @throws ProgrammingError + */ + public function getTinyPreviewHtml(MonitoredObject $object) + { + throw new ProgrammingError('This hook provide tiny previews but it is not implemented'); + } +} diff --git a/library/Icinga/Application/Hook/TicketHook.php b/library/Icinga/Application/Hook/TicketHook.php new file mode 100644 index 000000000..8e0aa4cc2 --- /dev/null +++ b/library/Icinga/Application/Hook/TicketHook.php @@ -0,0 +1,124 @@ +init(); + } + + /** + * Overwrite this function for hook initialization, e.g. loading the hook's config + */ + protected function init() + { + } + + /** + * Set the hook as failed w/ the given message + * + * @param string $message Error message or error format string + * @param mixed ...$arg Format string argument + */ + private function fail($message) + { + $args = array_slice(func_get_args(), 1); + $lastError = vsprintf($message, $args); + Logger::debug($lastError); + $this->lastError = $lastError; + } + + /** + * Get the last error, if any + * + * @return string|null + */ + public function getLastError() + { + return $this->lastError; + } + + /** + * Get the pattern + * + * @return string + */ + abstract public function getPattern(); + + /** + * Create a link for each matched element in the subject text + * + * @param array $match Array of matched elements according to {@link getPattern()} + * + * @return string Replacement string + */ + abstract public function createLink($match); + + /** + * Create links w/ {@link createLink()} in the given text that matches to the subject from {@link getPattern()} + * + * In case of errors a debug message is recorded to the log and any subsequent call to {@link createLinks()} will + * be a no-op. + * + * @param string $text + * + * @return string + */ + final public function createLinks($text) + { + if ($this->lastError !== null) { + return $text; + } + + try { + $pattern = $this->getPattern(); + } catch (Exception $e) { + $this->fail('Can\'t create ticket links: Retrieving the pattern failed: %s', IcingaException::describe($e)); + return $text; + } + if (empty($pattern)) { + $this->fail('Can\'t create ticket links: Pattern is empty'); + return $text; + } + try { + $text = preg_replace_callback( + $pattern, + array($this, 'createLink'), + $text + ); + } catch (ErrorException $e) { + $this->fail('Can\'t create ticket links: Pattern is invalid: %s', IcingaException::describe($e)); + return $text; + } catch (Exception $e) { + $this->fail('Can\'t create ticket links: %s', IcingaException::describe($e)); + return $text; + } + + return $text; + } +} diff --git a/library/Icinga/Web/Hook/WebBaseHook.php b/library/Icinga/Application/Hook/WebBaseHook.php similarity index 96% rename from library/Icinga/Web/Hook/WebBaseHook.php rename to library/Icinga/Application/Hook/WebBaseHook.php index 544d2afa3..826b52a33 100644 --- a/library/Icinga/Web/Hook/WebBaseHook.php +++ b/library/Icinga/Application/Hook/WebBaseHook.php @@ -1,7 +1,7 @@ name; } + /** + * Get the module namespace + * + * @return string + */ + public function getNamespace() + { + return 'Icinga\\Module\\' . ucfirst($this->getName()); + } + /** * Get the module version * @@ -1238,12 +1248,35 @@ class Module */ protected function registerHook($name, $class, $key = null) { - if ($key === null) { - $key = $this->name; + return $this->provideHook($name, $class, $key); + } + + protected function slashesToNamespace($class) + { + $list = explode('/', $class); + foreach ($list as &$part) { + $part = ucfirst($part); } - Hook::register($name, $key, $class); + return implode('\\', $list); + } + // deprecate $key + protected function provideHook($name, $implementation = null, $key = null) + { + if ($implementation === null) { + $implementation = $name; + } + + if (strpos($implementation, '\\') === false) { + $class = $this->getNamespace() + . '\\ProvidedHook\\' + . $this->slashesToNamespace($implementation); + } else { + $class = $implementation; + } + + Hook::register($name, $implementation, $class); return $this; } diff --git a/library/Icinga/Web/Hook.php b/library/Icinga/Web/Hook.php index 3b9700f27..e3fee951d 100644 --- a/library/Icinga/Web/Hook.php +++ b/library/Icinga/Web/Hook.php @@ -1,218 +1,14 @@ - * Hook::register('grapher', 'My\\Grapher\\Class'); - * + * Deprecated, please use Icinga\Application\Hook instead */ -class Hook +class Hook extends NewHookImplementation { - /** - * Our hook name registry - * - * @var array - */ - protected static $hooks = array(); - - /** - * Hooks that have already been instantiated - * - * @var array - */ - protected static $instances = array(); - - /** - * Namespace prefix - * - * @var string - */ - public static $BASE_NS = 'Icinga\\Web\\Hook\\'; - - /** - * Append this string to base class - * - * All base classes renamed to *Hook - * - * @var string - */ - public static $classSuffix = 'Hook'; - - /** - * Reset object state - */ - public static function clean() - { - self::$hooks = array(); - self::$instances = array(); - self::$BASE_NS = 'Icinga\\Web\\Hook\\'; - } - - /** - * Whether someone registered itself for the given hook name - * - * @param string $name One of the predefined hook names - * - * @return bool - */ - public static function has($name) - { - return array_key_exists($name, self::$hooks); - } - - /** - * Create or return an instance of a given hook - * - * TODO: Should return some kind of a hook interface - * - * @param string $name One of the predefined hook names - * @param string $key The identifier of a specific subtype - * - * @return mixed - */ - public static function createInstance($name, $key) - { - if (!self::has($name, $key)) { - return null; - } - - if (isset(self::$instances[$name][$key])) { - return self::$instances[$name][$key]; - } - - $class = self::$hooks[$name][$key]; - try { - $instance = new $class(); - } catch (Exception $e) { - Logger::debug( - 'Hook "%s" (%s) (%s) failed, will be unloaded: %s', - $name, - $key, - $class, - $e->getMessage() - ); - // TODO: Persist unloading for "some time" or "current session" - unset(self::$hooks[$name][$key]); - return null; - } - - self::assertValidHook($instance, $name); - self::$instances[$name][$key] = $instance; - return $instance; - } - - protected static function splitHookName($name) - { - $sep = '\\'; - if (false === $module = strpos($name, $sep)) { - return array(null, $name); - } - return array( - substr($name, 0, $module), - substr($name, $module + 1) - ); - } - - /** - * Test for a valid class name - * - * @param mixed $instance - * @param string $name - * - * @throws ProgrammingError - */ - private static function assertValidHook($instance, $name) - { - $suffix = self::$classSuffix; // 'Hook' - $base = self::$BASE_NS; // 'Icinga\\Web\\Hook\\' - - list($module, $name) = self::splitHookName($name); - - if ($module === null) { - $base_class = $base . ucfirst($name) . 'Hook'; - - // I'm unsure whether this makes sense. Unused and Wrong. - if (strpos($base_class, $suffix) === false) { - $base_class .= $suffix; - } - } else { - $base_class = 'Icinga\\Module\\' - . ucfirst($module) - . '\\Web\\Hook\\' - . ucfirst($name) - . $suffix; - } - - if (!$instance instanceof $base_class) { - throw new ProgrammingError( - '%s is not an instance of %s', - get_class($instance), - $base_class - ); - } - } - - /** - * Return all instances of a specific name - * - * @param string $name One of the predefined hook names - * - * @return array - */ - public static function all($name) - { - if (!self::has($name)) { - return array(); - } - - foreach (self::$hooks[$name] as $key => $hook) { - if (self::createInstance($name, $key) === null) { - return array(); - } - } - - return self::$instances[$name]; - } - - /** - * Get the first hook - * - * @param string $name One of the predefined hook names - * - * @return null|mixed - */ - public static function first($name) - { - if (self::has($name)) { - return self::createInstance($name, key(self::$hooks[$name])); - } - } - - /** - * Register a class - * - * @param string $name One of the predefined hook names - * @param string $key The identifier of a specific subtype - * @param string $class Your class name, must inherit one of the - * classes in the Icinga/Web/Hook folder - */ - public static function register($name, $key, $class) - { - if (!isset(self::$hooks[$name])) { - self::$hooks[$name] = array(); - } - - self::$hooks[$name][$key] = $class; - } } diff --git a/library/Icinga/Web/Hook/GrapherHook.php b/library/Icinga/Web/Hook/GrapherHook.php index 39edf86e4..377ed24b2 100644 --- a/library/Icinga/Web/Hook/GrapherHook.php +++ b/library/Icinga/Web/Hook/GrapherHook.php @@ -3,109 +3,11 @@ namespace Icinga\Web\Hook; -use Icinga\Exception\ProgrammingError; -use Icinga\Module\Monitoring\Object\MonitoredObject; +use Icinga\Application\Hook\GrapherHook as BaseHook; /** - * Icinga Web Grapher Hook base class + * Deprecated, compat only. * - * Extend this class if you want to integrate your graphing solution nicely into - * Icinga Web. + * Please implement hooks in Icinga\Application\Hook */ -abstract class GrapherHook extends WebBaseHook -{ - /** - * Whether this grapher provides previews - * - * @var bool - */ - protected $hasPreviews = false; - - /** - * Whether this grapher provides tiny previews - * - * @var bool - */ - protected $hasTinyPreviews = false; - - /** - * Constructor must live without arguments right now - * - * Therefore the constructor is final, we might change our opinion about - * this one far day - */ - final public function __construct() - { - $this->init(); - } - - /** - * Overwrite this function if you want to do some initialization stuff - * - * @return void - */ - protected function init() - { - } - - /** - * Whether this grapher provides previews - * - * @return bool - */ - public function hasPreviews() - { - return $this->hasPreviews; - } - - /** - * Whether this grapher provides tiny previews - * - * @return bool - */ - public function hasTinyPreviews() - { - return $this->hasTinyPreviews; - } - - /** - * Whether a graph for the monitoring object exist - * - * @param MonitoredObject $object - * - * @return bool - */ - abstract public function has(MonitoredObject $object); - - /** - * Get a preview for the given object - * - * This function must return an empty string if no graph exists. - * - * @param MonitoredObject $object - * - * @return string - * @throws ProgrammingError - * - */ - public function getPreviewHtml(MonitoredObject $object) - { - throw new ProgrammingError('This hook provide previews but it is not implemented'); - } - - - /** - * Get a tiny preview for the given object - * - * This function must return an empty string if no graph exists. - * - * @param MonitoredObject $object - * - * @return string - * @throws ProgrammingError - */ - public function getTinyPreviewHtml(MonitoredObject $object) - { - throw new ProgrammingError('This hook provide tiny previews but it is not implemented'); - } -} +abstract class GrapherHook extends BaseHook {} diff --git a/library/Icinga/Web/Hook/TicketHook.php b/library/Icinga/Web/Hook/TicketHook.php index 74af1a91f..63a4aa75c 100644 --- a/library/Icinga/Web/Hook/TicketHook.php +++ b/library/Icinga/Web/Hook/TicketHook.php @@ -3,122 +3,11 @@ namespace Icinga\Web\Hook; -use ErrorException; -use Exception; -use Icinga\Application\Logger; -use Icinga\Exception\IcingaException; +use Icinga\Application\Hook\TicketHook as BaseHook; /** - * Base class for ticket hooks + * Deprecated, compat only. * - * Extend this class if you want to integrate your ticketing solution Icinga Web 2 + * Please implement hooks in Icinga\Application\Hook */ -abstract class TicketHook -{ - /** - * Last error, if any - * - * @var string|null - */ - protected $lastError; - - /** - * Create a new ticket hook - * - * @see init() For hook initialization. - */ - final public function __construct() - { - $this->init(); - } - - /** - * Overwrite this function for hook initialization, e.g. loading the hook's config - */ - protected function init() - { - } - - /** - * Set the hook as failed w/ the given message - * - * @param string $message Error message or error format string - * @param mixed ...$arg Format string argument - */ - private function fail($message) - { - $args = array_slice(func_get_args(), 1); - $lastError = vsprintf($message, $args); - Logger::debug($lastError); - $this->lastError = $lastError; - } - - /** - * Get the last error, if any - * - * @return string|null - */ - public function getLastError() - { - return $this->lastError; - } - - /** - * Get the pattern - * - * @return string - */ - abstract public function getPattern(); - - /** - * Create a link for each matched element in the subject text - * - * @param array $match Array of matched elements according to {@link getPattern()} - * - * @return string Replacement string - */ - abstract public function createLink($match); - - /** - * Create links w/ {@link createLink()} in the given text that matches to the subject from {@link getPattern()} - * - * In case of errors a debug message is recorded to the log and any subsequent call to {@link createLinks()} will - * be a no-op. - * - * @param string $text - * - * @return string - */ - final public function createLinks($text) - { - if ($this->lastError !== null) { - return $text; - } - - try { - $pattern = $this->getPattern(); - } catch (Exception $e) { - $this->fail('Can\'t create ticket links: Retrieving the pattern failed: %s', IcingaException::describe($e)); - return $text; - } - if (empty($pattern)) { - $this->fail('Can\'t create ticket links: Pattern is empty'); - return $text; - } - try { - $text = preg_replace_callback( - $pattern, - array($this, 'createLink'), - $text - ); - } catch (ErrorException $e) { - $this->fail('Can\'t create ticket links: Pattern is invalid: %s', IcingaException::describe($e)); - return $text; - } catch (Exception $e) { - $this->fail('Can\'t create ticket links: %s', IcingaException::describe($e)); - return $text; - } - - return $text; - } -} +abstract class TicketHook extends BaseHook {} diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index 5edc8f6f1..f615ece11 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Monitoring\Backend\Ido\Query; use Zend_Db_Expr; use Icinga\Application\Icinga; +use Icinga\Application\Hook; use Icinga\Application\Logger; use Icinga\Data\Db\DbQuery; use Icinga\Data\Filter\Filter; @@ -119,6 +120,15 @@ abstract class IdoQuery extends DbQuery */ protected $joinedVirtualTables = array(); + /** + * A map of virtual table names and corresponding hook instances + * + * Joins for those tables will be delegated to them + * + * @var array + */ + protected $hookedVirtualTables = array(); + /** * List of column aliases used for sorting the result * @@ -593,6 +603,18 @@ abstract class IdoQuery extends DbQuery return isset($this->caseInsensitiveColumns[$table][$alias]); } + /** + * Return our column map + * + * Might be useful for hooks + * + * @return array + */ + public function getColumnMap() + { + return $this->columnMap; + } + /** * Apply oracle specific query initialization */ @@ -651,6 +673,23 @@ abstract class IdoQuery extends DbQuery { parent::init(); $this->prefix = $this->ds->getTablePrefix(); + + foreach (Hook::all('monitoring/idoQueryExtension') as $hook) { + $extensions = $hook->extendColumnMap($this); + if (! is_array($extensions)) continue; + + foreach ($extensions as $vTable => $cols) { + if (! array_key_exists($vTable, $this->columnMap)) { + $this->hookedVirtualTables[$vTable] = $hook; + $this->columMap[$vTable] = array(); + } + + foreach ($cols as $k => $v) { + $this->columnMap[$vTable][$k] = $v; + } + } + } + $dbType = $this->ds->getDbType(); if ($dbType === 'oracle') { $this->initializeForOracle(); @@ -787,7 +826,24 @@ abstract class IdoQuery extends DbQuery if ($this->hasJoinedVirtualTable($name)) { return $this; } - return $this->joinVirtualTable($name); + + if ($this->virtualTableIsHooked($name)) { + return $this->joinHookedVirtualTable($this, $name); + } else { + return $this->joinVirtualTable($name); + } + } + + /** + * Whether a given virtual table name has been provided by a hook + * + * @param string $name Virtual table name + * + * @return boolean + */ + protected function virtualTableIsHooked($name) + { + return array_key_exists($name, $this->hookedVirtualTables); } protected function conflictsWithVirtualTable($name) @@ -826,6 +882,19 @@ abstract class IdoQuery extends DbQuery return $this; } + /** + * Tell a hook to join a virtual table + * + * @param String $table + * @return $this + */ + protected function joinHookedVirtualTable($table) + { + $this->hookedVirtualTables[$table]->joinVirtualTable($table); + $this->joinedVirtualTables[$table] = true; + return $this; + } + /** * Get the table for a specific alias * diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php index 50cd436fd..2afb046d5 100644 --- a/modules/monitoring/library/Monitoring/DataView/DataView.php +++ b/modules/monitoring/library/Monitoring/DataView/DataView.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Monitoring\DataView; use IteratorAggregate; +use Icinga\Application\Hook; use Icinga\Data\ConnectionInterface; use Icinga\Data\Filter\Filter; use Icinga\Data\Filter\FilterMatch; @@ -122,6 +123,18 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite return $view; } + protected function getHookedColumns() + { + $columns = array(); + foreach (Hook::all('monitoring/dataviewExtension') as $hook) { + foreach ($hook->getAdditionalQueryColumns($this->getQueryName()) as $col) { + $columns[] = $col; + } + } + + return $columns; + } + // TODO: This is not the right place for this, move it away protected function applyUrlFilter($request = null) { diff --git a/modules/monitoring/library/Monitoring/DataView/Hoststatus.php b/modules/monitoring/library/Monitoring/DataView/Hoststatus.php index 0ab9dd92e..220ce2226 100644 --- a/modules/monitoring/library/Monitoring/DataView/Hoststatus.php +++ b/modules/monitoring/library/Monitoring/DataView/Hoststatus.php @@ -10,7 +10,7 @@ class HostStatus extends DataView */ public function getColumns() { - return array( + return array_merge($this->getHookedColumns(), array( 'instance_name', 'host_name', 'host_display_name', @@ -63,7 +63,7 @@ class HostStatus extends DataView 'host_problem', 'host_ipv4', 'host_acknowledgement_type' - ); + )); } /** diff --git a/modules/monitoring/library/Monitoring/DataView/Servicestatus.php b/modules/monitoring/library/Monitoring/DataView/Servicestatus.php index db44f62c6..389bc9ae0 100644 --- a/modules/monitoring/library/Monitoring/DataView/Servicestatus.php +++ b/modules/monitoring/library/Monitoring/DataView/Servicestatus.php @@ -10,7 +10,7 @@ class ServiceStatus extends DataView */ public function getColumns() { - return array( + return array_merge($this->getHookedColumns(), array( 'instance_name', 'host_name', 'host_display_name', @@ -98,7 +98,7 @@ class ServiceStatus extends DataView 'service_modified_service_attributes', 'service_host_name', 'service_acknowledgement_type', - ); + )); } /** diff --git a/modules/monitoring/library/Monitoring/Hook/DataviewExtensionHook.php b/modules/monitoring/library/Monitoring/Hook/DataviewExtensionHook.php new file mode 100644 index 000000000..c50d1d747 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Hook/DataviewExtensionHook.php @@ -0,0 +1,20 @@ +provideAdditionalQueryColumns($queryName); + + if (! is_array($cols)) { + return array(); + } + + return $cols; + } + + abstract public function provideAdditionalQueryColumns($queryName); +} diff --git a/modules/monitoring/library/Monitoring/Hook/HostActionsHook.php b/modules/monitoring/library/Monitoring/Hook/HostActionsHook.php new file mode 100644 index 000000000..b7923bcc8 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Hook/HostActionsHook.php @@ -0,0 +1,46 @@ + url, where title will + * be used as link caption. Url should be an Icinga\Web\Url object when + * the link should point to an Icinga Web url - otherwise a string would + * be fine. + * + * Mixed example: + * + * return array( + * 'Wiki' => 'http://my.wiki/host=' . rawurlencode($host->host_name), + * 'Logstash' => Url::fromPath( + * 'logstash/search/syslog', + * array('host' => $host->host_name) + * ) + * ); + * + * + * One might also provide ssh:// or rdp:// urls if equipped with fitting + * (safe) URL handlers for his browser(s). + * + * TODO: I'd love to see some kind of a Link/LinkSet object implemented + * for this and similar hooks. + * + * @param Host $host Monitoring host object + * + * @return array An array containing a list of host action links + */ + abstract public function getActionsForHost(Host $host); +} diff --git a/modules/monitoring/library/Monitoring/Hook/IdoQueryExtensionHook.php b/modules/monitoring/library/Monitoring/Hook/IdoQueryExtensionHook.php new file mode 100644 index 000000000..ea7f663f1 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Hook/IdoQueryExtensionHook.php @@ -0,0 +1,15 @@ + url, where title will + * be used as link caption. Url should be an Icinga\Web\Url object when + * the link should point to an Icinga Web url - otherwise a string would + * be fine. + * + * Mixed example: + * + * return array( + * 'Wiki' => 'http://my.wiki/host=' . rawurlencode($service->service_name), + * 'Logstash' => Url::fromPath( + * 'logstash/search/syslog', + * array('service' => $service->host_name) + * ) + * ); + * + * + * One might also provide ssh:// or rdp:// urls if equipped with fitting + * (safe) URL handlers for his browser(s). + * + * TODO: I'd love to see some kind of a Link/LinkSet object implemented + * for this and similar hooks. + * + * @param Service $service Monitoring service object + * + * @return array An array containing a list of service action links + */ + abstract public function getActionsForService(Service $service); +} diff --git a/modules/monitoring/library/Monitoring/Hook/TimelineProviderHook.php b/modules/monitoring/library/Monitoring/Hook/TimelineProviderHook.php new file mode 100644 index 000000000..2b9524828 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Hook/TimelineProviderHook.php @@ -0,0 +1,37 @@ + url, where title will - * be used as link caption. Url should be an Icinga\Web\Url object when - * the link should point to an Icinga Web url - otherwise a string would - * be fine. - * - * Mixed example: - * - * return array( - * 'Wiki' => 'http://my.wiki/host=' . rawurlencode($host->host_name), - * 'Logstash' => Url::fromPath( - * 'logstash/search/syslog', - * array('host' => $host->host_name) - * ) - * ); - * - * - * One might also provide ssh:// or rdp:// urls if equipped with fitting - * (safe) URL handlers for his browser(s). - * - * TODO: I'd love to see some kind of a Link/LinkSet object implemented - * for this and similar hooks. - * - * @param Host $host Monitoring host object - * - * @return array An array containing a list of host action links - */ - abstract public function getActionsForHost(Host $host); -} +abstract class HostActionsHook extends BaseHook {} diff --git a/modules/monitoring/library/Monitoring/Web/Hook/ServiceActionsHook.php b/modules/monitoring/library/Monitoring/Web/Hook/ServiceActionsHook.php index 2df3c4f55..b118f8d58 100644 --- a/modules/monitoring/library/Monitoring/Web/Hook/ServiceActionsHook.php +++ b/modules/monitoring/library/Monitoring/Web/Hook/ServiceActionsHook.php @@ -3,44 +3,11 @@ namespace Icinga\Module\Monitoring\Web\Hook; -use Icinga\Module\Monitoring\Object\Service; +use Icinga\Module\Monitoring\Hook\ServiceActionsHook as BaseHook; /** - * Base class for host action hooks + * Compat only + * + * Please implement hooks in our Hook direcory */ -abstract class ServiceActionsHook -{ - /** - * Implementors of this method should return an array containing - * additional action links for a specific host. You get a full Service - * object, which allows you to return specific links only for nodes - * with specific properties. - * - * The result array should be in the form title => url, where title will - * be used as link caption. Url should be an Icinga\Web\Url object when - * the link should point to an Icinga Web url - otherwise a string would - * be fine. - * - * Mixed example: - * - * return array( - * 'Wiki' => 'http://my.wiki/host=' . rawurlencode($service->service_name), - * 'Logstash' => Url::fromPath( - * 'logstash/search/syslog', - * array('service' => $service->host_name) - * ) - * ); - * - * - * One might also provide ssh:// or rdp:// urls if equipped with fitting - * (safe) URL handlers for his browser(s). - * - * TODO: I'd love to see some kind of a Link/LinkSet object implemented - * for this and similar hooks. - * - * @param Service $service Monitoring service object - * - * @return array An array containing a list of service action links - */ - abstract public function getActionsForService(Service $service); -} +abstract class ServiceActionsHook extends BaseHook {} diff --git a/modules/monitoring/library/Monitoring/Web/Hook/TimelineProviderHook.php b/modules/monitoring/library/Monitoring/Web/Hook/TimelineProviderHook.php index 0af65d303..ba01d1e03 100644 --- a/modules/monitoring/library/Monitoring/Web/Hook/TimelineProviderHook.php +++ b/modules/monitoring/library/Monitoring/Web/Hook/TimelineProviderHook.php @@ -3,35 +3,11 @@ namespace Icinga\Module\Monitoring\Web\Hook; -use Icinga\Module\Monitoring\Timeline\TimeRange; +use Icinga\Module\Monitoring\Hook\TimelineProviderHook as BaseHook; /** - * Base class for TimeLine providers + * Compat only + * + * Please implement hooks in our Hook direcory */ -abstract class TimelineProviderHook -{ - /** - * Return the names by which to group entries - * - * @return array An array with the names as keys and their attribute-lists as values - */ - abstract public function getIdentifiers(); - - /** - * Return the visible entries supposed to be shown on the timeline - * - * @param TimeRange $range The range of time for which to fetch entries - * - * @return array The entries to display on the timeline - */ - abstract public function fetchEntries(TimeRange $range); - - /** - * Return the entries supposed to be used to calculate forecasts - * - * @param TimeRange $range The range of time for which to fetch forecasts - * - * @return array The entries to calculate forecasts with - */ - abstract public function fetchForecasts(TimeRange $range); -} +abstract class TimelineProviderHook extends BaseHook {}