Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ui/widgets/geomap/actions/WidgetView.php')
-rw-r--r--ui/widgets/geomap/actions/WidgetView.php296
1 files changed, 296 insertions, 0 deletions
diff --git a/ui/widgets/geomap/actions/WidgetView.php b/ui/widgets/geomap/actions/WidgetView.php
new file mode 100644
index 00000000000..895bd55d149
--- /dev/null
+++ b/ui/widgets/geomap/actions/WidgetView.php
@@ -0,0 +1,296 @@
+<?php declare(strict_types = 0);
+/*
+** Zabbix
+** Copyright (C) 2001-2022 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+namespace Widgets\Geomap\Actions;
+
+use API,
+ CControllerDashboardWidgetView,
+ CControllerResponseData,
+ CGeomapCoordinatesParser,
+ CParser,
+ CProfile,
+ CSettingsHelper,
+ CSeverityHelper;
+
+class WidgetView extends CControllerDashboardWidgetView {
+
+ private const NO_PROBLEMS_MARKER_COLOR = '#009900';
+
+ protected string $widgetid;
+
+ /**
+ * Global geomap configuration.
+ *
+ * @param array
+ */
+ protected array $geomap_config;
+
+ protected function init(): void {
+ parent::init();
+
+ $this->addValidationRules([
+ 'initial_load' => 'in 0,1',
+ 'widgetid' => 'db widget.widgetid',
+ 'unique_id' => 'required|string'
+ ]);
+ }
+
+ protected function doAction(): void {
+ $this->widgetid = $this->getInput('widgetid', 0);
+
+ $data = [
+ 'name' => $this->getInput('name', $this->widget->getDefaultName()),
+ 'hosts' => self::convertToRFC7946($this->getHosts()),
+ 'user' => [
+ 'debug_mode' => $this->getDebugMode()
+ ],
+ 'unique_id' => $this->getInput('unique_id')
+ ];
+
+ if ($this->getInput('initial_load', 0)) {
+ $this->geomap_config = self::getMapConfig();
+
+ $data['config'] = $this->geomap_config + $this->getMapCenter() + [
+ 'filter' => $this->getUserProfileFilter(),
+ 'colors' => self::getSeveritySettings()
+ ];
+ }
+
+ $this->setResponse(new CControllerResponseData($data));
+ }
+
+ /**
+ * Get hosts and their properties to show on the map as markers.
+ */
+ private function getHosts(): array {
+ $filter_groupids = $this->fields_values['groupids'] ? getSubGroups($this->fields_values['groupids']) : null;
+
+ $hosts = API::Host()->get([
+ 'output' => ['hostid', 'name'],
+ 'selectInventory' => ['location_lat', 'location_lon'],
+ 'groupids' => $filter_groupids,
+ 'hostids' => $this->fields_values['hostids'] ?: null,
+ 'evaltype' => $this->fields_values['evaltype'],
+ 'tags' => $this->fields_values['tags'],
+ 'filter' => [
+ 'inventory_mode' => [HOST_INVENTORY_MANUAL, HOST_INVENTORY_AUTOMATIC]
+ ],
+ 'monitored_hosts' => true,
+ 'preservekeys' => true
+ ]);
+
+ $hosts = array_filter($hosts, static function ($host) {
+ $lat = $host['inventory']['location_lat'];
+ $lng = $host['inventory']['location_lon'];
+
+ return (is_numeric($lat) && $lat >= GEOMAP_LAT_MIN && $lat <= GEOMAP_LAT_MAX
+ && is_numeric($lng) && $lng >= GEOMAP_LNG_MIN && $lng <= GEOMAP_LNG_MAX);
+ });
+
+ // Get triggers.
+ $triggers = API::Trigger()->get([
+ 'output' => [],
+ 'selectHosts' => ['hostid'],
+ 'hostids' => array_keys($hosts),
+ 'filter' => [
+ 'value' => TRIGGER_VALUE_TRUE
+ ],
+ 'monitored' => true,
+ 'preservekeys' => true
+ ]);
+
+ // Get problems.
+ $problems = API::Problem()->get([
+ 'output' => ['objectid', 'severity'],
+ 'selectHosts' => ['hostid'],
+ 'objectids' => array_keys($triggers)
+ ]);
+
+ // Group problems by hosts.
+ $problems_by_host = [];
+ foreach ($problems as $problem) {
+ foreach ($triggers[$problem['objectid']]['hosts'] as $trigger_host) {
+ if (!array_key_exists($trigger_host['hostid'], $problems_by_host)) {
+ $problems_by_host[$trigger_host['hostid']] = [
+ TRIGGER_SEVERITY_DISASTER => 0,
+ TRIGGER_SEVERITY_HIGH => 0,
+ TRIGGER_SEVERITY_AVERAGE => 0,
+ TRIGGER_SEVERITY_WARNING => 0,
+ TRIGGER_SEVERITY_INFORMATION => 0,
+ TRIGGER_SEVERITY_NOT_CLASSIFIED => 0
+ ];
+ }
+
+ $problems_by_host[$trigger_host['hostid']][$problem['severity']]++;
+ }
+ }
+
+ // Filter hosts by severity filter.
+ $severity_filter = CProfile::get('web.dashboard.widget.geomap.severity_filter', '', $this->widgetid);
+ $severity_filter = ($severity_filter !== '') ? array_flip(explode(',', $severity_filter)) : [];
+
+ if ($severity_filter && count($severity_filter) != 7) {
+ $hosts = array_filter($hosts, static function ($host) use ($severity_filter, $problems_by_host) {
+ return array_key_exists($host['hostid'], $problems_by_host)
+ ? (bool) array_intersect_key(array_filter($problems_by_host[$host['hostid']]), $severity_filter)
+ : array_key_exists(-1, $severity_filter);
+ });
+ }
+
+ $result_hosts = [];
+ foreach ($hosts as $host) {
+ $problems = array_key_exists($host['hostid'], $problems_by_host)
+ ? $problems_by_host[$host['hostid']]
+ : [
+ TRIGGER_SEVERITY_DISASTER => 0,
+ TRIGGER_SEVERITY_HIGH => 0,
+ TRIGGER_SEVERITY_AVERAGE => 0,
+ TRIGGER_SEVERITY_WARNING => 0,
+ TRIGGER_SEVERITY_INFORMATION => 0,
+ TRIGGER_SEVERITY_NOT_CLASSIFIED => 0
+ ];
+
+ $result_hosts[] = $host + ['problems' => $problems];
+ }
+
+ return $result_hosts;
+ }
+
+ /**
+ * Get initial map center point, zoom level and coordinates to center when clicking on navigate home button.
+ */
+ private function getMapCenter(): array {
+ $geoloc_parser = new CGeomapCoordinatesParser();
+ $home_coords = [];
+ $center = [];
+
+ $user_default_view = CProfile::get('web.dashboard.widget.geomap.default_view', '', $this->widgetid);
+ if ($user_default_view !== '' && $geoloc_parser->parse($user_default_view) == CParser::PARSE_SUCCESS) {
+ $home_coords['default'] = true;
+ $center = $geoloc_parser->result;
+ $center['zoom'] = min($this->geomap_config['max_zoom'], $center['zoom']);
+ }
+
+ if (array_key_exists('default_view', $this->fields_values)
+ && $this->fields_values['default_view'] !== ''
+ && $geoloc_parser->parse($this->fields_values['default_view']) == CParser::PARSE_SUCCESS) {
+ $initial_view = $geoloc_parser->result;
+
+ if (array_key_exists('zoom', $initial_view)) {
+ $initial_view['zoom'] = min($this->geomap_config['max_zoom'], $initial_view['zoom']);
+ }
+ else {
+ $initial_view['zoom'] = ceil($this->geomap_config['max_zoom'] / 2);
+ }
+
+ $home_coords['initial'] = $initial_view;
+ if (!$center) {
+ $center = $home_coords['initial'];
+ }
+ }
+
+ $defaults = [
+ 'latitude' => 0,
+ 'longitude' => 0,
+ 'zoom' => 1
+ ];
+
+ return [
+ 'center' => $center ?: $defaults,
+ 'home_coords' => $home_coords
+ ];
+ }
+
+ private function getUserProfileFilter(): array {
+ return [
+ 'severity' => CProfile::get('web.dashboard.widget.geomap.severity_filter', [], $this->widgetid)
+ ];
+ }
+
+ /**
+ * Get global map configuration.
+ */
+ private static function getMapConfig(): array {
+ if (CSettingsHelper::get(CSettingsHelper::GEOMAPS_TILE_PROVIDER) === '') {
+ return [
+ 'tile_url' => CSettingsHelper::get(CSettingsHelper::GEOMAPS_TILE_URL),
+ 'max_zoom' => CSettingsHelper::get(CSettingsHelper::GEOMAPS_MAX_ZOOM),
+ 'attribution' => CSettingsHelper::get(CSettingsHelper::GEOMAPS_ATTRIBUTION)
+ ];
+ }
+
+ $tile_provider = getTileProviders()[CSettingsHelper::get(CSettingsHelper::GEOMAPS_TILE_PROVIDER)];
+
+ return [
+ 'tile_url' => $tile_provider['geomaps_tile_url'],
+ 'max_zoom' => $tile_provider['geomaps_max_zoom'],
+ 'attribution' => $tile_provider['geomaps_attribution']
+ ];
+ }
+
+ /**
+ * Create an array of problem severity colors.
+ */
+ private static function getSeveritySettings(): array {
+ $severity_config = [
+ -1 => self::NO_PROBLEMS_MARKER_COLOR
+ ];
+
+ for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) {
+ $severity_config[$severity] = '#'.CSeverityHelper::getColor($severity);
+ }
+
+ return $severity_config;
+ }
+
+ /**
+ * Convert array of hosts to valid GeoJSON (RFC7946) object.
+ */
+ private static function convertToRFC7946(array $hosts) : array {
+ $geo_json = [];
+
+ foreach ($hosts as $host) {
+ $problems = array_filter($host['problems']);
+ $severities = array_keys($problems);
+ $top_severity = reset($severities);
+
+ $geo_json[] = [
+ 'type' => 'Feature',
+ 'geometry' => [
+ 'type' => 'Point',
+ 'coordinates' => [
+ $host['inventory']['location_lon'],
+ $host['inventory']['location_lat'],
+ 0
+ ]
+ ],
+ 'properties' => [
+ 'hostid' => $host['hostid'],
+ 'name' => $host['name'],
+ 'severity' => ($top_severity === false) ? -1 : $top_severity,
+ 'problems' => $problems
+ ]
+ ];
+ }
+
+ return $geo_json;
+ }
+}