You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
717 lines
22 KiB
717 lines
22 KiB
<?php
|
|
/*
|
|
** Zabbix
|
|
** Copyright (C) 2001-2023 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.
|
|
**/
|
|
|
|
|
|
class CMapHelper {
|
|
|
|
/**
|
|
* Get map data with resolved element / link states.
|
|
*
|
|
* @param array $sysmapids Map IDs.
|
|
* @param array $options Options used to retrieve actions.
|
|
* @param int $options['severity_min'] Minimum severity.
|
|
* @param int $options['unique_id']
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get($sysmapids, array $options = []) {
|
|
$maps = API::Map()->get([
|
|
'output' => ['sysmapid', 'name', 'width', 'height', 'backgroundid', 'label_type', 'label_location',
|
|
'highlight', 'expandproblem', 'markelements', 'show_unack', 'label_format', 'label_type_host',
|
|
'label_type_hostgroup', 'label_type_trigger', 'label_type_map', 'label_type_image', 'label_string_host',
|
|
'label_string_hostgroup', 'label_string_trigger', 'label_string_map', 'label_string_image', 'iconmapid',
|
|
'severity_min', 'show_suppressed'
|
|
],
|
|
'selectShapes' => ['sysmap_shapeid', 'type', 'x', 'y', 'width', 'height', 'text', 'font', 'font_size',
|
|
'font_color', 'text_halign', 'text_valign', 'border_type', 'border_width', 'border_color',
|
|
'background_color', 'zindex'
|
|
],
|
|
'selectLines' => ['sysmap_shapeid', 'x1', 'x2', 'y1', 'y2', 'line_type', 'line_width', 'line_color',
|
|
'zindex'
|
|
],
|
|
'selectSelements' => ['selementid', 'elements', 'elementtype', 'iconid_off', 'iconid_on', 'label',
|
|
'label_location', 'x', 'y', 'iconid_disabled', 'iconid_maintenance', 'elementsubtype', 'areatype',
|
|
'width', 'height', 'viewtype', 'use_iconmap', 'permission', 'evaltype', 'tags'
|
|
],
|
|
'selectLinks' => ['linkid', 'selementid1', 'selementid2', 'drawtype', 'color', 'label', 'linktriggers',
|
|
'permission'
|
|
],
|
|
'sysmapids' => $sysmapids,
|
|
'preservekeys' => true
|
|
]);
|
|
$map = reset($maps);
|
|
|
|
$theme = getUserGraphTheme();
|
|
|
|
if (!$map) {
|
|
$map = [
|
|
'sysmapid' => -1,
|
|
'width' => 320,
|
|
'height' => 150,
|
|
'backgroundid' => null,
|
|
'severity_min' => 0,
|
|
'show_unack' => EXTACK_OPTION_ALL,
|
|
'label_location' => MAP_LABEL_LOC_BOTTOM,
|
|
'selements' => [],
|
|
'links' => [],
|
|
'shapes' => [[
|
|
'type' => SYSMAP_SHAPE_TYPE_RECTANGLE,
|
|
'x' => 0,
|
|
'y' => 0,
|
|
'width' => 320,
|
|
'height' => 150,
|
|
'font' => 9,
|
|
'font_size' => 11,
|
|
'font_color' => 'FF0000',
|
|
'text' => _('No permissions to referred object or it does not exist!')
|
|
]],
|
|
'aria_label' => ''
|
|
];
|
|
}
|
|
else {
|
|
if (array_key_exists('severity_min', $options)) {
|
|
$map['severity_min'] = $options['severity_min'];
|
|
}
|
|
else {
|
|
$options['severity_min'] = $map['severity_min'];
|
|
}
|
|
|
|
// Populate host group elements of subtype 'SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS' with hosts.
|
|
$areas = self::populateHostGroupsWithHosts($map, $theme);
|
|
|
|
// Apply inherited label options.
|
|
$map = self::applyMapElementLabelProperties($map);
|
|
|
|
// Resolve macros in map element labels.
|
|
$resolve_opt = ['resolve_element_label' => true];
|
|
$map['selements'] = CMacrosResolverHelper::resolveMacrosInMapElements($map['selements'], $resolve_opt);
|
|
|
|
self::resolveMapState($map, $areas, $options);
|
|
}
|
|
|
|
return [
|
|
'id' => $map['sysmapid'],
|
|
'theme' => $theme,
|
|
'canvas' => [
|
|
'width' => $map['width'],
|
|
'height' => $map['height']
|
|
],
|
|
'refresh' => 'map.php?sysmapid='.$map['sysmapid'].'&severity_min='.$map['severity_min']
|
|
.(array_key_exists('unique_id', $options) ? '&unique_id='.$options['unique_id'] : ''),
|
|
'background' => $map['backgroundid'],
|
|
'label_location' => $map['label_location'],
|
|
'elements' => array_values($map['selements']),
|
|
'links' => array_values($map['links']),
|
|
'shapes' => array_values($map['shapes']),
|
|
'aria_label' => $map['aria_label'],
|
|
'timestamp' => zbx_date2str(DATE_TIME_FORMAT_SECONDS)
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Function applies element labels inherited from map properties.
|
|
*
|
|
* @param array $sysmap Map data.
|
|
* @param array $sysmap[selements] Array of map elements.
|
|
* @param int $sysmap[selements][][elementtype] Map element type.
|
|
* @param int $sysmap[label_format] Map label format property.
|
|
* @param int $sysmap[label_type] Map label type property.
|
|
* @param int $sysmap[label_type_hostgroup] Map host group element label type.
|
|
* @param string $sysmap[label_string_hostgroup] Map host group element custom label.
|
|
* @param int $sysmap[label_type_host] Map host element label type.
|
|
* @param string $sysmap[label_string_host] Map host element custom label.
|
|
* @param int $sysmap[label_type_trigger] Map trigger element label type.
|
|
* @param string $sysmap[label_string_trigger] Map trigger element custom label.
|
|
* @param int $sysmap[label_type_map] Map submap element label type.
|
|
* @param string $sysmap[label_string_map] Map submap element custom label.
|
|
* @param int $sysmap[label_type_image] Map image element label type.
|
|
* @param string $sysmap[label_string_image] Map image element custom label.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function applyMapElementLabelProperties(array $sysmap) {
|
|
// Define which $sysmap property holds value for each type of element.
|
|
$label_properties = [
|
|
SYSMAP_ELEMENT_TYPE_HOST_GROUP => [
|
|
'field_label_type' => 'label_type_hostgroup',
|
|
'field_custom_label' => 'label_string_hostgroup'
|
|
],
|
|
SYSMAP_ELEMENT_TYPE_HOST => [
|
|
'field_label_type' => 'label_type_host',
|
|
'field_custom_label' => 'label_string_host'
|
|
],
|
|
SYSMAP_ELEMENT_TYPE_TRIGGER => [
|
|
'field_label_type' => 'label_type_trigger',
|
|
'field_custom_label' => 'label_string_trigger'
|
|
],
|
|
SYSMAP_ELEMENT_TYPE_MAP => [
|
|
'field_label_type' => 'label_type_map',
|
|
'field_custom_label' => 'label_string_map'
|
|
],
|
|
SYSMAP_ELEMENT_TYPE_IMAGE => [
|
|
'field_label_type' => 'label_type_image',
|
|
'field_custom_label' => 'label_string_image'
|
|
]
|
|
];
|
|
|
|
// Apply properties to each sysmap element.
|
|
foreach ($sysmap['selements'] as &$selement) {
|
|
$prop = $label_properties[$selement['elementtype']];
|
|
$elmnt_label_type = ($sysmap['label_format'] == SYSMAP_LABEL_ADVANCED_ON)
|
|
? $sysmap[$prop['field_label_type']]
|
|
: $sysmap['label_type'];
|
|
$inherited_label = null;
|
|
|
|
if ($elmnt_label_type == MAP_LABEL_TYPE_NOTHING) {
|
|
$inherited_label = '';
|
|
}
|
|
elseif ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST && $elmnt_label_type == MAP_LABEL_TYPE_IP) {
|
|
$inherited_label = '{HOST.IP}';
|
|
}
|
|
elseif ($sysmap['label_format'] == SYSMAP_LABEL_ADVANCED_ON
|
|
&& $sysmap[$prop['field_label_type']] == MAP_LABEL_TYPE_CUSTOM) {
|
|
$inherited_label = $sysmap[$prop['field_custom_label']];
|
|
}
|
|
|
|
$selement['label_type'] = $elmnt_label_type;
|
|
if ($inherited_label !== null) {
|
|
$selement['label'] = $inherited_label;
|
|
}
|
|
}
|
|
unset($selement);
|
|
|
|
return $sysmap;
|
|
}
|
|
|
|
/**
|
|
* Resolve map element (selements and links) state.
|
|
*
|
|
* @param array $sysmap Map data.
|
|
* @param array $areas Areas representing array containing host group element IDs and dimension
|
|
* properties of area.
|
|
* @param array $options Options used to retrieve actions.
|
|
* @param int $options['severity_min'] Minimum severity.
|
|
* @param int $options['unique_id']
|
|
*/
|
|
protected static function resolveMapState(array &$sysmap, array $areas, array $options) {
|
|
$map_info = getSelementsInfo($sysmap, ['severity_min' => $options['severity_min']]);
|
|
processAreasCoordinates($sysmap, $areas, $map_info);
|
|
|
|
// Adding element names and removing inaccessible triggers from readable elements.
|
|
addElementNames($sysmap['selements']);
|
|
|
|
foreach ($sysmap['selements'] as $id => &$element) {
|
|
if ($element['permission'] < PERM_READ) {
|
|
continue;
|
|
}
|
|
|
|
switch ($element['elementtype']) {
|
|
case SYSMAP_ELEMENT_TYPE_IMAGE:
|
|
$map_info[$id]['name'] = _('Image');
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_TRIGGER:
|
|
// Move the trigger with problem and highest priority to the beginning of the trigger list.
|
|
if (array_key_exists('triggerid', $map_info[$id])) {
|
|
$trigger_pos = 0;
|
|
|
|
foreach ($element['elements'] as $i => $trigger) {
|
|
if ($trigger['triggerid'] == $map_info[$id]['triggerid']) {
|
|
$trigger_pos = $i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($trigger_pos > 0) {
|
|
$trigger = $element['elements'][$trigger_pos];
|
|
unset($element['elements'][$trigger_pos]);
|
|
array_unshift($element['elements'], $trigger);
|
|
}
|
|
}
|
|
// break; is not missing here
|
|
|
|
default:
|
|
$map_info[$id]['name'] = $element['elements'][0]['elementName'];
|
|
}
|
|
}
|
|
unset($element);
|
|
|
|
$labels = getMapLabels($sysmap, $map_info);
|
|
$highlights = getMapHighligts($sysmap, $map_info);
|
|
$actions = getActionsBySysmap($sysmap, $options);
|
|
$link_triggers_info = getMapLinkTriggerInfo($sysmap, $options);
|
|
|
|
$problems_total = 0;
|
|
$status_problems = [];
|
|
$status_other = [];
|
|
|
|
foreach ($sysmap['selements'] as $id => &$element) {
|
|
$element['icon'] = (array_key_exists($id, $map_info) && array_key_exists('iconid', $map_info[$id]))
|
|
? $map_info[$id]['iconid']
|
|
: null;
|
|
|
|
unset($element['width'], $element['height']);
|
|
|
|
if ($element['permission'] >= PERM_READ) {
|
|
$label = str_replace(['.', ','], ' ', $element['label']);
|
|
|
|
if ($map_info[$id]['problems_total'] > 0) {
|
|
$problems_total += $map_info[$id]['problems_total'];
|
|
$problem_desc = str_replace(['.', ','], ' ', $map_info[$id]['aria_label']);
|
|
$status_problems[] = sprintf('%1$s, %2$s, %3$s, %4$s. ',
|
|
sysmap_element_types($element['elementtype']), _('Status problem'), $label, $problem_desc
|
|
);
|
|
}
|
|
else {
|
|
$element_status = _('Status ok');
|
|
|
|
if (array_key_exists('info', $map_info[$id])
|
|
&& array_key_exists('maintenance', $map_info[$id]['info'])) {
|
|
$element_status = _('Status maintenance');
|
|
}
|
|
elseif (array_key_exists('info', $map_info[$id])
|
|
&& array_key_exists('status', $map_info[$id]['info'])) {
|
|
$element_status = _('Status disabled');
|
|
}
|
|
|
|
$status_other[] = sprintf('%1$s, %2$s, %3$s. ', sysmap_element_types($element['elementtype']),
|
|
$element_status, $label
|
|
);
|
|
}
|
|
|
|
$element['highlight'] = $highlights[$id];
|
|
$element['actions'] = $actions[$id];
|
|
$element['label'] = $labels[$id];
|
|
}
|
|
else {
|
|
$element['highlight'] = '';
|
|
$element['actions'] = null;
|
|
$element['label'] = '';
|
|
}
|
|
|
|
if ($sysmap['markelements']) {
|
|
$element['latelyChanged'] = $map_info[$id]['latelyChanged'];
|
|
}
|
|
}
|
|
unset($element);
|
|
|
|
$sysmap['aria_label'] = str_replace(['.', ','], ' ', $sysmap['name']).', '.
|
|
_n('%1$s of %2$s element in problem state', '%1$s of %2$s elements in problem state',
|
|
count($status_problems), count($sysmap['selements'])).
|
|
', '.
|
|
_n('%1$s problem in total', '%1$s problems in total', $problems_total).
|
|
'. '.
|
|
implode('', array_merge($status_problems, $status_other));
|
|
|
|
$sysmap['shapes'] = CMacrosResolverHelper::resolveMapShapeLabelMacros($sysmap['name'], $sysmap['shapes']);
|
|
$sysmap['links'] = CMacrosResolverHelper::resolveMapLinkLabelMacros($sysmap['links']);
|
|
|
|
foreach ($sysmap['lines'] as $line) {
|
|
$sysmap['shapes'][] = self::convertLineToShape($line);
|
|
}
|
|
|
|
foreach ($sysmap['links'] as &$link) {
|
|
if ($link['permission'] >= PERM_READ && $link['linktriggers']) {
|
|
$link_triggers = array_filter($link['linktriggers'],
|
|
function ($link_trigger) use ($link_triggers_info, $options) {
|
|
return (array_key_exists($link_trigger['triggerid'], $link_triggers_info)
|
|
&& $link_triggers_info[$link_trigger['triggerid']]['status'] == TRIGGER_STATUS_ENABLED
|
|
&& $link_triggers_info[$link_trigger['triggerid']]['value'] == TRIGGER_VALUE_TRUE
|
|
&& $link_triggers_info[$link_trigger['triggerid']]['priority'] >= $options['severity_min']
|
|
);
|
|
}
|
|
);
|
|
|
|
// Link-trigger with highest severity or lower triggerid defines link color and drawtype.
|
|
if ($link_triggers) {
|
|
$link_triggers = array_map(function ($link_trigger) use ($link_triggers_info) {
|
|
return [
|
|
'priority' => $link_triggers_info[$link_trigger['triggerid']]['priority']
|
|
] + $link_trigger;
|
|
}, $link_triggers);
|
|
|
|
CArrayHelper::sort($link_triggers, [
|
|
['field' => 'priority', 'order' => ZBX_SORT_DOWN],
|
|
['field' => 'triggerid', 'order' => ZBX_SORT_UP]
|
|
]);
|
|
|
|
$styling_link_triggers = reset($link_triggers);
|
|
|
|
$link['color'] = $styling_link_triggers['color'];
|
|
$link['drawtype'] = $styling_link_triggers['drawtype'];
|
|
}
|
|
}
|
|
}
|
|
unset($link);
|
|
}
|
|
|
|
/**
|
|
* Convert map shape to line (apply mapping to attribute set).
|
|
*
|
|
* @param array $shape Map shape.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function convertShapeToLine($shape) {
|
|
$mapping = [
|
|
'sysmap_shapeid',
|
|
'zindex',
|
|
'x' => 'x1',
|
|
'y' => 'y1',
|
|
'width' => 'x2',
|
|
'height' => 'y2',
|
|
'border_type' => 'line_type',
|
|
'border_width' => 'line_width',
|
|
'border_color' => 'line_color'
|
|
];
|
|
|
|
$line = [];
|
|
|
|
foreach ($mapping as $source_key => $target_key) {
|
|
$source_key = (is_numeric($source_key)) ? $target_key : $source_key;
|
|
|
|
if (array_key_exists($source_key, $shape)) {
|
|
$line[$target_key] = $shape[$source_key];
|
|
}
|
|
}
|
|
|
|
return $line;
|
|
}
|
|
|
|
/**
|
|
* Convert map line to shape (apply mapping to attribute set).
|
|
*
|
|
* @param array $line Map line.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function convertLineToShape($line) {
|
|
$mapping = [
|
|
'sysmap_shapeid',
|
|
'zindex',
|
|
'x1' => 'x',
|
|
'y1' => 'y',
|
|
'x2' => 'width',
|
|
'y2' => 'height',
|
|
'line_type' => 'border_type',
|
|
'line_width' => 'border_width',
|
|
'line_color' => 'border_color'
|
|
];
|
|
|
|
$shape = [];
|
|
|
|
foreach ($mapping as $source_key => $target_key) {
|
|
$source_key = (is_numeric($source_key)) ? $target_key : $source_key;
|
|
|
|
if (array_key_exists($source_key, $line)) {
|
|
$shape[$target_key] = $line[$source_key];
|
|
}
|
|
}
|
|
|
|
$shape['type'] = SYSMAP_SHAPE_TYPE_LINE;
|
|
|
|
return $shape;
|
|
}
|
|
|
|
/**
|
|
* Checks that the user has read permissions to objects used in the map elements.
|
|
*
|
|
* @param array $selements selements to check
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function checkSelementPermissions(array $selements) {
|
|
$groupids = [];
|
|
$hostids = [];
|
|
$triggerids = [];
|
|
$sysmapids = [];
|
|
|
|
foreach ($selements as $selement) {
|
|
switch ($selement['elementtype']) {
|
|
case SYSMAP_ELEMENT_TYPE_HOST_GROUP:
|
|
$groupids[$selement['elements'][0]['groupid']] = true;
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_HOST:
|
|
$hostids[$selement['elements'][0]['hostid']] = true;
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_TRIGGER:
|
|
foreach ($selement['elements'] as $element) {
|
|
$triggerids[$element['triggerid']] = true;
|
|
}
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_MAP:
|
|
$sysmapids[$selement['elements'][0]['sysmapid']] = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return self::checkHostGroupsPermissions(array_keys($groupids))
|
|
&& self::checkHostsPermissions(array_keys($hostids))
|
|
&& self::checkTriggersPermissions(array_keys($triggerids))
|
|
&& self::checkMapsPermissions(array_keys($sysmapids));
|
|
}
|
|
|
|
/**
|
|
* Checks if the current user has access to the given host groups.
|
|
*
|
|
* @param array $groupids
|
|
*
|
|
* @return boolean
|
|
*/
|
|
private static function checkHostGroupsPermissions(array $groupids) {
|
|
if ($groupids) {
|
|
$count = API::HostGroup()->get([
|
|
'countOutput' => true,
|
|
'groupids' => $groupids
|
|
]);
|
|
|
|
return ($count == count($groupids));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks if the current user has access to the given hosts.
|
|
*
|
|
* @param array $hostids
|
|
*
|
|
* @return boolean
|
|
*/
|
|
private static function checkHostsPermissions(array $hostids) {
|
|
if ($hostids) {
|
|
$count = API::Host()->get([
|
|
'countOutput' => true,
|
|
'hostids' => $hostids
|
|
]);
|
|
|
|
return ($count == count($hostids));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks if the current user has access to the given triggers.
|
|
*
|
|
* @param array $triggerids
|
|
*
|
|
* @return boolean
|
|
*/
|
|
private static function checkTriggersPermissions(array $triggerids) {
|
|
if ($triggerids) {
|
|
$count = API::Trigger()->get([
|
|
'countOutput' => true,
|
|
'triggerids' => $triggerids
|
|
]);
|
|
|
|
return ($count == count($triggerids));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks if the current user has access to the given maps.
|
|
*
|
|
* @param array $sysmapids
|
|
*
|
|
* @return boolean
|
|
*/
|
|
private static function checkMapsPermissions(array $sysmapids) {
|
|
if ($sysmapids) {
|
|
$count = API::Map()->get([
|
|
'countOutput' => true,
|
|
'sysmapids' => $sysmapids
|
|
]);
|
|
|
|
return ($count == count($sysmapids));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Replace host groups of subtype = SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP by hosts that belongs to group.
|
|
*
|
|
* @param array $sysmap Map data.
|
|
* @param array $theme Theme used to create missing elements (like hostgroup frame).
|
|
*
|
|
* @return array Array representing areas with area coordinates and selementids.
|
|
*/
|
|
protected static function populateHostGroupsWithHosts(array &$sysmap, array $theme) {
|
|
// Collect host groups to populate with hosts.
|
|
$groupids = [];
|
|
foreach ($sysmap['selements'] as &$selement) {
|
|
$selement['selementid_orig'] = $selement['selementid'];
|
|
$selement['elementtype_orig'] = $selement['elementtype'];
|
|
$selement['elementsubtype_orig'] = $selement['elementsubtype'];
|
|
|
|
if ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP
|
|
&& $selement['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) {
|
|
if ($selement['permission'] >= PERM_READ) {
|
|
$groupids[$selement['elements'][0]['groupid']] = true;
|
|
}
|
|
else {
|
|
// If user has no access to whole host group, always show it as a SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP.
|
|
$selement['elementsubtype'] = SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP;
|
|
}
|
|
}
|
|
}
|
|
unset($selement);
|
|
|
|
$areas = [];
|
|
|
|
if ($groupids) {
|
|
$groups = API::HostGroup()->get([
|
|
'output' => [],
|
|
'selectHosts' => ['hostid', 'name'],
|
|
'groupids' => array_keys($groupids),
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$new_selementid = (count($sysmap['selements']) > 0)
|
|
? (int) max(zbx_objectValues($sysmap['selements'], 'selementid'))
|
|
: 0;
|
|
|
|
$new_linkid = (count($sysmap['links']) > 0) ? (int) max(array_keys($sysmap['links'])) : 0;
|
|
|
|
foreach ($sysmap['selements'] as $selement_key => &$selement) {
|
|
if ($selement['elementtype'] != SYSMAP_ELEMENT_TYPE_HOST_GROUP
|
|
|| $selement['elementsubtype'] != SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) {
|
|
continue;
|
|
}
|
|
|
|
$groupid = $selement['elements'][0]['groupid'];
|
|
$group = $groups[$groupid];
|
|
$original_selement = $selement;
|
|
|
|
// Jump to the next host group if current host group doesn't contain accessible hosts.
|
|
if (!$group['hosts']) {
|
|
continue;
|
|
}
|
|
|
|
// Sort hosts by name.
|
|
CArrayHelper::sort($group['hosts'], ['field' => 'name', 'order' => ZBX_SORT_UP]);
|
|
|
|
// Define area in which to locate hosts.
|
|
if ($selement['areatype'] == SYSMAP_ELEMENT_AREA_TYPE_CUSTOM) {
|
|
$area = [
|
|
'selementids' => [],
|
|
'width' => $selement['width'],
|
|
'height' => $selement['height'],
|
|
'x' => $selement['x'],
|
|
'y' => $selement['y']
|
|
];
|
|
|
|
$sysmap['shapes'][] = [
|
|
'sysmap_shapeid' => 'e-'.$selement['selementid'],
|
|
'type' => SYSMAP_SHAPE_TYPE_RECTANGLE,
|
|
'x' => $selement['x'],
|
|
'y' => $selement['y'],
|
|
'width' => $selement['width'],
|
|
'height' => $selement['height'],
|
|
'border_type' => SYSMAP_SHAPE_BORDER_TYPE_SOLID,
|
|
'border_width' => 3,
|
|
'border_color' => $theme['maingridcolor'],
|
|
'background_color' => '',
|
|
'text' => '',
|
|
'zindex' => -1
|
|
];
|
|
}
|
|
else {
|
|
$area = [
|
|
'selementids' => [],
|
|
'width' => $sysmap['width'],
|
|
'height' => $sysmap['height'],
|
|
'x' => 0,
|
|
'y' => 0
|
|
];
|
|
}
|
|
|
|
// Add selected hosts as map selements.
|
|
foreach ($group['hosts'] as $host) {
|
|
$new_selementid++;
|
|
|
|
$area['selementids'][] = $new_selementid;
|
|
$sysmap['selements'][$new_selementid] = [
|
|
'elementtype' => SYSMAP_ELEMENT_TYPE_HOST,
|
|
'elementsubtype' => SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP,
|
|
'elements' => [
|
|
['hostid' => $host['hostid']]
|
|
],
|
|
'selementid' => $new_selementid
|
|
] + $selement;
|
|
}
|
|
|
|
$areas[] = $area;
|
|
|
|
// Make links.
|
|
$selements = zbx_toHash($sysmap['selements'], 'selementid');
|
|
|
|
foreach ($sysmap['links'] as $link) {
|
|
// Do not multiply links between two areas.
|
|
$id1 = $link['selementid1'];
|
|
$id2 = $link['selementid2'];
|
|
|
|
if ($selements[$id1]['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP
|
|
&& $selements[$id1]['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS
|
|
&& $selements[$id2]['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP
|
|
&& $selements[$id2]['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) {
|
|
continue;
|
|
}
|
|
|
|
if ($id1 == $original_selement['selementid']) {
|
|
$id_number = 'selementid1';
|
|
}
|
|
elseif ($id2 == $original_selement['selementid']) {
|
|
$id_number = 'selementid2';
|
|
}
|
|
else {
|
|
continue;
|
|
}
|
|
|
|
foreach ($area['selementids'] as $selement_id) {
|
|
$new_linkid++;
|
|
$link['linkid'] = -$new_linkid;
|
|
$link[$id_number] = $selement_id;
|
|
$sysmap['links'][$new_linkid] = $link;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove host group elements that are replaced by hosts.
|
|
$selements = [];
|
|
foreach ($sysmap['selements'] as $key => $element) {
|
|
if ($element['elementtype'] != SYSMAP_ELEMENT_TYPE_HOST_GROUP
|
|
|| $element['elementsubtype'] != SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) {
|
|
$selements[$key] = $element;
|
|
}
|
|
}
|
|
$sysmap['selements'] = $selements;
|
|
|
|
return $areas;
|
|
}
|
|
}
|