From 9f39660f50004ca7c49ea171e2a6f199487cd667 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 14 Apr 2024 15:18:42 +0200 Subject: Adding upstream version 1.3.0. Signed-off-by: Daniel Baumann --- library/Eventdb/Data/LegacyFilterParser.php | 153 +++++++++++++++++ library/Eventdb/Event.php | 120 ++++++++++++++ library/Eventdb/Eventdb.php | 184 +++++++++++++++++++++ library/Eventdb/EventdbController.php | 181 ++++++++++++++++++++ library/Eventdb/Hook/DetailviewExtensionHook.php | 124 ++++++++++++++ .../Monitoring/DetailviewExtension.php | 81 +++++++++ .../ProvidedHook/Monitoring/EventdbActionHook.php | 182 ++++++++++++++++++++ .../ProvidedHook/Monitoring/HostActions.php | 15 ++ .../ProvidedHook/Monitoring/ServiceActions.php | 15 ++ library/Eventdb/Test/BaseTestCase.php | 27 +++ library/Eventdb/Test/Bootstrap.php | 35 ++++ library/Eventdb/Test/PseudoHost.php | 15 ++ library/Eventdb/Test/PseudoMonitoringBackend.php | 14 ++ library/Eventdb/Test/PseudoService.php | 16 ++ library/Eventdb/Web/EventdbOutputFormat.php | 66 ++++++++ 15 files changed, 1228 insertions(+) create mode 100644 library/Eventdb/Data/LegacyFilterParser.php create mode 100644 library/Eventdb/Event.php create mode 100644 library/Eventdb/Eventdb.php create mode 100644 library/Eventdb/EventdbController.php create mode 100644 library/Eventdb/Hook/DetailviewExtensionHook.php create mode 100644 library/Eventdb/ProvidedHook/Monitoring/DetailviewExtension.php create mode 100644 library/Eventdb/ProvidedHook/Monitoring/EventdbActionHook.php create mode 100644 library/Eventdb/ProvidedHook/Monitoring/HostActions.php create mode 100644 library/Eventdb/ProvidedHook/Monitoring/ServiceActions.php create mode 100644 library/Eventdb/Test/BaseTestCase.php create mode 100644 library/Eventdb/Test/Bootstrap.php create mode 100644 library/Eventdb/Test/PseudoHost.php create mode 100644 library/Eventdb/Test/PseudoMonitoringBackend.php create mode 100644 library/Eventdb/Test/PseudoService.php create mode 100644 library/Eventdb/Web/EventdbOutputFormat.php (limited to 'library/Eventdb') diff --git a/library/Eventdb/Data/LegacyFilterParser.php b/library/Eventdb/Data/LegacyFilterParser.php new file mode 100644 index 0000000..2907202 --- /dev/null +++ b/library/Eventdb/Data/LegacyFilterParser.php @@ -0,0 +1,153 @@ +host = str_replace('.*', '*', $data->host); + if ($data->host === '*') { + $data->host = null; + } + } else { + $data->host = $host; + } + if ($data->host !== null) { + $filter->andFilter(Filter::expression('host_name', '=', $data->host)); + } + + static::handleArray($filter, $data, 'programInclusion', 'program'); + static::handleArray($filter, $data, 'programExclusion', 'program', '!='); + + static::handleArray($filter, $data, 'priorityExclusion', 'priority', '!='); + static::handleArray($filter, $data, 'sourceExclusion', 'source', '!='); + static::handleArray($filter, $data, 'facilityExclusion', 'facility', '!='); + + // TODO: msg - when really needed + // TODO: startTime - when really needed + + // Note: any other field or data part gets ignored... + + return $filter; + } + + protected static function handleArray(Filter $filter, $data, $property, $filterAttr, $op = '=') + { + if (property_exists($data, $property) && ! empty($data->$property)) { + if ($op === '!=') { + $subFilter = $filter; + } else { + $subFilter = new FilterOr; + } + + /* + if (is_array($data->$property) && count($data->$property) === 1) { + $data->$property = current($data->$property); + } + */ + if (! is_array($data->$property)) { + $data->$property = array($data->$property); + } + foreach ($data->$property as $val) { + $subFilter->addFilter(Filter::expression($filterAttr, $op, $val)); + } + + if ($subFilter !== $filter) { + $filters = $subFilter->filters(); + if ($filter->isChain() && count($filters) > 1) { + $filter->andFilter($subFilter); + } else { + $filter->andFilter(current($filters)); + } + } + } + } + + /** + * @author partially by NikiC https://stackoverflow.com/users/385378/nikic + * @source partially from https://stackoverflow.com/a/20440596/449813 + * + * @param $json string + * + * @return string + */ + public static function fixJSONQuotes($json) + { + // fix unquoted identifiers + $json = preg_replace('/([{,]+)(\s*)([^"]+?)\s*:/', '$1"$3":', $json); + + $regex = <<<'REGEX' +~ + "[^"\\]*(?:\\.|[^"\\]*)*" + (*SKIP)(*F) + | '([^'\\]*(?:\\.|[^'\\]*)*)' +~x +REGEX; + + return preg_replace_callback($regex, function ($matches) { + return '"' . preg_replace('~\\\\.(*SKIP)(*F)|"~', '\\"', $matches[1]) . '"'; + }, $json); + } + + /** + * Basic check if it looks like a JSON filter + * + * @param $string + * + * @return bool + */ + static public function isJsonFilter($string) + { + if (! $string || ! is_string($string)) { + return false; + } + + $string = trim($string); + if (empty($string)) { + return false; + } + + if (preg_match('/^\{.*\}$/s', $string)) { + // looks like JSON data + return true; + } + return false; + } +} diff --git a/library/Eventdb/Event.php b/library/Eventdb/Event.php new file mode 100644 index 0000000..a3bba1a --- /dev/null +++ b/library/Eventdb/Event.php @@ -0,0 +1,120 @@ + 'kernel messages', + 1 => 'user-level messages', + 2 => 'mail system', + 3 => 'system daemons', + 4 => 'security/authorization messages', + 5 => 'messages generated internally by syslogd', + 6 => 'line printer subsystem', + 7 => 'network news subsystem', + 8 => 'UUCP subsystem', + 9 => 'clock daemon', + 10 => 'security/authorization messages', + 11 => 'FTP daemon', + 12 => 'NTP subsystem', + 13 => 'log audit', + 14 => 'log alert', + 15 => 'clock daemon', + 16 => 'local use 0', + 17 => 'local use 1', + 18 => 'local use 2', + 19 => 'local use 3', + 20 => 'local use 4', + 21 => 'local use 5', + 22 => 'local use 6', + 23 => 'local use 7' + ); + + public static $priorities = array( + 0 => 'emergency', + 1 => 'alert', + 2 => 'critical', + 3 => 'error', + 4 => 'warning', + 5 => 'notice', + 6 => 'info', + 7 => 'debug' + ); + + public static $types = array( + 0 => 'syslog', + 1 => 'snmp', + 2 => 'mail' + ); + + public static $typeIcons = array( + '_default' => 'help', + 'syslog' => 'doc-text', + 'snmp' => 'plug', + 'mail' => 'bell', + ); + + public function __construct($data) + { + parent::__construct($data, ArrayObject::ARRAY_AS_PROPS); + } + + public function offsetGet($index) + { + if (! $this->offsetExists($index)) { + return null; + } + $getter = 'get' . ucfirst($index); + if (method_exists($this, $getter)) { + return $this->$getter(); + } + return parent::offsetGet($index); + } + + public function getAck() + { + return (bool) parent::offsetGet('ack'); + } + + public function getFacility() + { + $facility = (int) parent::offsetGet('facility'); + return array_key_exists($facility, static::$facilities) ? static::$facilities[$facility] : $facility; + } + + public function getPriority() + { + $priority = (int) parent::offsetGet('priority'); + return array_key_exists($priority, static::$priorities) ? static::$priorities[$priority] : $priority; + } + + public function getType() + { + $type = (int) parent::offsetGet('type'); + return array_key_exists($type, static::$types) ? static::$types[$type] : $type; + } + + public function getTypeIcon() + { + if (array_key_exists($type = $this->getType(), static::$typeIcons)) { + return static::$typeIcons[$type]; + } else { + return static::$typeIcons['_default']; + } + } + + public static function fromData($data) + { + return new static($data); + } + + public static function getPriorityId($priorityName) + { + $priorities = array_flip(static::$priorities); + return $priorities[$priorityName]; + } +} diff --git a/library/Eventdb/Eventdb.php b/library/Eventdb/Eventdb.php new file mode 100644 index 0000000..b885258 --- /dev/null +++ b/library/Eventdb/Eventdb.php @@ -0,0 +1,184 @@ + 'c', + 'event' => 'e', + ); + + /** + * Default query columns + * + * @var array + */ + protected static $defaultQueryColumns = array( + 'event' => array( + 'id', + 'host_name', + 'host_address', + 'type', + 'facility', + 'priority', + 'program', + 'message', + 'alternative_message', + 'ack', + 'created', + 'modified', + ), + 'comment' => array( + 'id', + 'event_id', + 'type', + 'message', + 'created', + 'modified', + 'user' + ) + ); + + protected static $edbcQueryColumns = array( + 'event' => array( + 'group_active', + 'group_id', + 'group_count', + 'group_leader', + 'group_autoclear', + 'flags', + 'alternative_message' + ) + ); + + /** @var bool */ + protected $hasCorrelatorExtensions = null; + + /** + * Checks if Event repository has EDBC columns + * + * @return bool + */ + public function hasCorrelatorExtensions() + { + if ($this->hasCorrelatorExtensions === null) { + $dba = $this->getDataSource()->getDbAdapter(); + $result = $dba->fetchRow("SHOW COLUMNS FROM `event` LIKE 'group_leader'"); + + $this->hasCorrelatorExtensions = ! ! $result; + } + return $this->hasCorrelatorExtensions; + } + + public function filterGroups(RepositoryQuery $query) + { + if ($this->hasCorrelatorExtensions()) { + $query->addFilter(Filter::matchAny( + Filter::expression('group_leader', '=', -1), + new FilterExpression('group_leader', 'IS', new \Zend_Db_Expr('NULL')) + )); + } + return $this; + } + + /** + * {@inheritdoc} + */ + protected function initializeQueryColumns() + { + $additionalColumns = Config::module('eventdb', 'columns')->keys(); + $queryColumns = static::$defaultQueryColumns; + if ($this->hasCorrelatorExtensions()) { + foreach (static::$edbcQueryColumns as $table => $fields) { + if (array_key_exists($table, $queryColumns)) { + $queryColumns[$table] = array_merge($queryColumns[$table], $fields); + } else { + $queryColumns[$table] = $fields; + } + } + } + if ($additionalColumns !== null) { + $eventColumns = $queryColumns['event']; + $queryColumns['event'] = array_merge($eventColumns, array_diff($additionalColumns, $eventColumns)); + } + return $queryColumns; + } + + /** + * Create and return a new instance of the Eventdb + * + * @param ConfigObject $config The configuration to use, otherwise the module's configuration + * + * @return static + * + * @throws ConfigurationError In case no resource has been configured in the module's configuration + */ + public static function fromConfig(ConfigObject $config = null) + { + if ($config === null) { + $moduleConfig = Config::module('eventdb'); + if (($resourceName = $moduleConfig->get('backend', 'resource')) === null) { + throw new ConfigurationError( + mt('eventdb', 'You need to configure a resource to access the EventDB database first') + ); + } + + $resource = ResourceFactory::create($resourceName); + } else { + $resource = ResourceFactory::createResource($config); + } + + return new static($resource); + } + + /** + * {@inheritdoc} + */ + protected function initializeConversionRules() + { + return array('event' => array('host_address' => 'ip_address')); + } + + /** + * Convert an IP address into its human-readable form + * + * @param string $rawAddress + * + * @return string + */ + protected function retrieveIpAddress($rawAddress) + { + return $rawAddress === null ? null : inet_ntop($rawAddress); + } + + /** + * Convert an IP address into its binary form + * + * @param string $address + * + * @return string + */ + protected function persistIpAddress($address) + { + return $address === null ? null : inet_pton($address); + } +} diff --git a/library/Eventdb/EventdbController.php b/library/Eventdb/EventdbController.php new file mode 100644 index 0000000..538553e --- /dev/null +++ b/library/Eventdb/EventdbController.php @@ -0,0 +1,181 @@ +Auth()->isAuthenticated()) { + foreach ($this->Auth()->getUser()->getRoles() as $role) { + if ($permission !== null && ! in_array($permission, $role->getPermissions())) { + continue; + } + $restrictionsFromRole = $role->getRestrictions($name); + if (empty($restrictionsFromRole)) { + $restrictions = array(); + break; + } else { + if (! is_array($restrictionsFromRole)) { + $restrictionsFromRole = array($restrictionsFromRole); + } + $restrictions = array_merge($restrictions, array_values($restrictionsFromRole)); + } + } + } + return $restrictions; + } + + /** + * Retrieves the Icinga MonitoringBackend + * + * @param string|null $name + * + * @return MonitoringBackend + * @throws IcingaException When monitoring is not enabled + */ + protected function monitoringBackend($name = null) + { + if ($this->monitoringBackend === null) { + if (! Icinga::app()->getModuleManager()->hasEnabled('monitoring')) { + throw new IcingaException('The module "monitoring" must be enabled and configured!'); + } + $this->monitoringBackend = MonitoringBackend::instance($name); + } + return $this->monitoringBackend; + } + + protected function setViewScript($name) + { + $this->_helper->viewRenderer->setNoController(true); + $this->_helper->viewRenderer->setScriptAction($name); + } + + protected function isFormatRequest() + { + return $this->hasParam('format'); + } + + protected function isApiRequest() + { + $format = $this->getParam('format'); + $header = $this->getRequest()->getHeader('Accept'); + + if ($format === 'json' || preg_match('#application/json(;.+)?#', $header)) { + return true; + } else { + return false; + } + } + + protected function isTextRequest() + { + $format = $this->getParam('format'); + if ($format === 'text' || $this->isPlainTextRequest()) { + return true; + } else { + return false; + } + } + + protected function isPlainTextRequest() + { + $header = $this->getRequest()->getHeader('Accept'); + if ($header !== null && preg_match('#text/plain#', $header)) { + return true; + } else { + return false; + } + } + + /** + * Send the user a summary of SQL queries + * + * @param array|QueryInterface $queries + */ + protected function sendSqlSummary($queries) + { + if (! is_array($queries)) { + $queries = array($queries); + } + + $str = ''; + foreach ($queries as $query) { + if ($query !== null) { + $str .= wordwrap($query) . "\n\n"; + } + } + + $this->sendText($str); + } + + /** + * Output JSON data to the requester + * + * @param mixed $data + * @param int $options + * @param int $depth + * + * @throws JsonEncodeException + */ + protected function sendJson($data, $options = 0, $depth = 100) + { + header('Content-Type: application/json'); + + if (defined('JSON_PARTIAL_OUTPUT_ON_ERROR')) { + $options |= JSON_PARTIAL_OUTPUT_ON_ERROR; + } + + $output = json_encode($data, $options, $depth); + if (! $output && json_last_error() !== null) { + throw new JsonEncodeException('JSON error: ' . json_last_error_msg()); + } + echo $output; + exit; + } + + protected function sendText($str, $script = null) + { + if ($this->isPlainTextRequest()) { + if ($script !== null) { + echo $this->view->render($this->getViewScript($script, true)); + } else { + echo $str; + } + exit; + } else { + $this->view->text = $str; + $this->view->partial = $script; + $this->setViewScript('format/text'); + } + } +} diff --git a/library/Eventdb/Hook/DetailviewExtensionHook.php b/library/Eventdb/Hook/DetailviewExtensionHook.php new file mode 100644 index 0000000..9fee702 --- /dev/null +++ b/library/Eventdb/Hook/DetailviewExtensionHook.php @@ -0,0 +1,124 @@ +init(); + } + + /** + * Overwrite this function for hook initialization, e.g. loading the hook's config + */ + protected function init() + { + } + + /** + * Shall return valid HTML to include in the detail view + * + * @param Event $event The event to generate HTML for + * + * @return string + */ + abstract public function getHtmlForEvent(Event $event); + + /** + * Shall return valid HTML to include in the multi-select view for events + * + * @param Event[] $events The events to generate HTML for + * + * @return string + */ + public function getHtmlForEvents($events) + { + return ''; + } + + /** + * Get {@link view} + * + * @return View + */ + public function getView() + { + return $this->view; + } + + /** + * Set {@link view} + * + * @param View $view + * + * @return $this + */ + public function setView($view) + { + $this->view = $view; + return $this; + } + + /** + * Get the module of the derived class + * + * @return Module + */ + public function getModule() + { + if ($this->module === null) { + $class = get_class($this); + if (ClassLoader::classBelongsToModule($class)) { + $this->module = Icinga::app()->getModuleManager()->getModule(ClassLoader::extractModuleName($class)); + } + } + + return $this->module; + } + + /** + * Set the module of the derived class + * + * @param Module $module + * + * @return $this + */ + public function setModule(Module $module) + { + $this->module = $module; + + return $this; + } +} diff --git a/library/Eventdb/ProvidedHook/Monitoring/DetailviewExtension.php b/library/Eventdb/ProvidedHook/Monitoring/DetailviewExtension.php new file mode 100644 index 0000000..e03f401 --- /dev/null +++ b/library/Eventdb/ProvidedHook/Monitoring/DetailviewExtension.php @@ -0,0 +1,81 @@ +hasPermission('eventdb/events')) { + return ''; + } + + $config = static::config(); + + if ($config->get('detailview_disable') === '1') { + return ''; + } + + $actions = clone EventdbActionHook::getActions($object); + if (! $actions->hasRenderableItems()) { + // no actions -> no EventDB + return ''; + } + + $htm = '

EventDB

'; + + $htm .= '
'; + $actions->setLayout(Navigation::LAYOUT_TABS); + $htm .= $actions->render(); + $htm .= '
'; + + $url = Url::fromPath('eventdb/events', array('host_name' => $object->host_name)); + + $customFilter = EventdbActionHook::getCustomFilter($object); + if ($customFilter === null) { + $customFilter = new FilterAnd; + } + $detailview_filter = $config->get('detailview_filter', 'ack=0'); + if ($detailview_filter !== null) { + $customFilter = $customFilter->andFilter(Filter::fromQueryString($detailview_filter)); + } + + $htm .= sprintf( + '
', + $url->with(array( + 'sort' => 'priority', + 'dir' => 'asc', + 'view' => 'compact', + 'limit' => 5, + ))->addFilter($customFilter) + ); + $htm .= '

' . mt('eventdb', 'Loading') . '...

'; + $htm .= '
'; + + return $htm; + } + + protected function eventDb() + { + return Eventdb::fromConfig(); + } + + protected static function config() + { + return Config::module('eventdb')->getSection('monitoring'); + } +} diff --git a/library/Eventdb/ProvidedHook/Monitoring/EventdbActionHook.php b/library/Eventdb/ProvidedHook/Monitoring/EventdbActionHook.php new file mode 100644 index 0000000..1eb968d --- /dev/null +++ b/library/Eventdb/ProvidedHook/Monitoring/EventdbActionHook.php @@ -0,0 +1,182 @@ +hasPermission('eventdb/events')) { + return null; + } + + $objectKey = static::getObjectKey($object); + + // check cache if the filter already have been rendered + if (static::$wantCache && array_key_exists($objectKey, self::$customFilters)) { + return self::$customFilters[$objectKey]; + } + + $config = static::config(); + $custom_var = $config->get('custom_var', null); + + $service = null; + $edb_filter = null; + if ($custom_var !== null && $object instanceof Service) { + $edb_filter = $object->{'_service_' . $custom_var . '_filter'}; + $service = $object->service_description; + } elseif ($custom_var !== null && $object instanceof Host) { + $edb_filter = $object->{'_host_' . $custom_var . '_filter'}; + } + + $customFilter = null; + if ($edb_filter !== null) { + if (LegacyFilterParser::isJsonFilter($edb_filter)) { + try { + $customFilter = LegacyFilterParser::parse( + $edb_filter, + $object->host_name, + $service + ); + } catch (InvalidPropertyException $e) { + Logger::warning($e->getMessage()); + } + } else { + try { + $customFilter = Filter::fromQueryString($edb_filter); + + if (! in_array('host_name', $customFilter->listFilteredColumns())) { + $customFilter = $customFilter->andFilter(Filter::expression('host_name', '=', $object->host_name)); + } + } catch (FilterParseException $e) { + Logger::warning('Could not parse custom EventDB filter: %s (%s)', $edb_filter, $e->getMessage()); + } + } + } + + return self::$customFilters[$objectKey] = $customFilter; + } + + /** + * @param MonitoredObject $object Host or Service to render for + * @param bool $no_cache Only for testing - to avoid caching + * + * @return array|Navigation + */ + public static function getActions(MonitoredObject $object) + { + if (! Auth::getInstance()->hasPermission('eventdb/events')) { + return array(); + } + + $objectKey = static::getObjectKey($object); + + // check cache if the buttons already have been rendered + if (static::$wantCache && array_key_exists($objectKey, self::$cachedNav)) { + return self::$cachedNav[$objectKey]; + } + + $nav = new Navigation(); + + $config = static::config(); + + $custom_var = $config->get('custom_var', null); + + $edb_cv = null; + $always_on = null; + + if ($custom_var !== null && $object instanceof Service) { + $edb_cv = $object->{'_service_' . $custom_var}; + $always_on = $config->get('always_on_service', 0); + } elseif ($custom_var !== null && $object instanceof Host) { + $edb_cv = $object->{'_host_' . $custom_var}; + $always_on = $config->get('always_on_host', 0); + } + + $customFilter = static::getCustomFilter($object); + if ($customFilter !== null) { + $params = UrlParams::fromQueryString($customFilter->toQueryString()); + $nav->addItem( + 'events_filtered', + array( + 'label' => mt('eventdb', 'Filtered events'), + 'url' => Url::fromPath('eventdb/events')->setParams($params), + 'icon' => 'tasks', + 'class' => 'action-link', + 'priority' => 1 + ) + ); + } + + // show access to all events, if (or) + // - custom_var is not configured + // - always_on is configured + // - custom_var is configured and set on object (to any value) + if ($custom_var === null || ! empty($edb_cv) || ! empty($always_on)) { + $nav->addItem( + 'events', + array( + 'label' => mt('eventdb', 'All events for host'), + 'url' => Url::fromPath( + 'eventdb/events', + array( + 'host_name' => $object->host_name, + ) + ), + 'icon' => 'tasks', + 'class' => 'action-link', + 'priority' => 99 + ) + ); + } + + return self::$cachedNav[$objectKey] = $nav; + } + + protected static function getObjectKey(MonitoredObject $object) + { + $type = $object->getType(); + $objectKey = sprintf('%!%', $type, $object->host_name); + if ($type === 'service') { + $objectKey .= '!' . $object->service_description; + } + return $objectKey; + } + + protected static function config() + { + return Config::module('eventdb')->getSection('monitoring'); + } +} diff --git a/library/Eventdb/ProvidedHook/Monitoring/HostActions.php b/library/Eventdb/ProvidedHook/Monitoring/HostActions.php new file mode 100644 index 0000000..caf33e3 --- /dev/null +++ b/library/Eventdb/ProvidedHook/Monitoring/HostActions.php @@ -0,0 +1,15 @@ +app(); + } + + protected function app() + { + if (self::$app === null) { + self::$app = Icinga::app(); + } + + return self::$app; + } +} diff --git a/library/Eventdb/Test/Bootstrap.php b/library/Eventdb/Test/Bootstrap.php new file mode 100644 index 0000000..848b360 --- /dev/null +++ b/library/Eventdb/Test/Bootstrap.php @@ -0,0 +1,35 @@ +getModuleManager() + ->loadModule('eventdb', $basedir) + ->loadModule('monitoring', $basedir . '/vendor/icingaweb2/modules/monitoring'); + + $user = new User('icingaadmin'); + $user->setPermissions(array('*')); + Auth::getInstance()->setAuthenticated($user); + } +} diff --git a/library/Eventdb/Test/PseudoHost.php b/library/Eventdb/Test/PseudoHost.php new file mode 100644 index 0000000..7ebcd8c --- /dev/null +++ b/library/Eventdb/Test/PseudoHost.php @@ -0,0 +1,15 @@ +properties = new \stdClass; + $this->hostVariables = $this->customvars = $vars; + return $this; + } +} diff --git a/library/Eventdb/Test/PseudoMonitoringBackend.php b/library/Eventdb/Test/PseudoMonitoringBackend.php new file mode 100644 index 0000000..3ad6de5 --- /dev/null +++ b/library/Eventdb/Test/PseudoMonitoringBackend.php @@ -0,0 +1,14 @@ +properties = new \stdClass; + $this->serviceVariables = $this->customvars = $vars; + $this->hostVariables = array(); + return $this; + } +} diff --git a/library/Eventdb/Web/EventdbOutputFormat.php b/library/Eventdb/Web/EventdbOutputFormat.php new file mode 100644 index 0000000..ceec1ce --- /dev/null +++ b/library/Eventdb/Web/EventdbOutputFormat.php @@ -0,0 +1,66 @@ +enable = $enable; + $disabled = array_merge(static::$disabledTypes, $disabled); + parent::__construct($disabled); + } + + /** + * {@inheritdoc} + */ + public function getSupportedTypes() + { + $supported = parent::getSupportedTypes(); + + if (in_array(self::TYPE_TEXT, $this->enable)) { + $supported[self::TYPE_TEXT] = array( + 'name' => 'text', + 'label' => mt('eventdb', 'Text'), + 'icon' => 'doc-text', + 'urlParams' => array('format' => 'text'), + ); + } + + return $supported; + } + + public function apply(Tabs $tabs) + { + parent::apply($tabs); + + if ($textTab = $tabs->get(self::TYPE_TEXT)) { + $textTab->setTargetBlank(false); + } + } +} -- cgit v1.2.3