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.
2855 lines
93 KiB
2855 lines
93 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 containing methods for operations with maps.
|
|
*/
|
|
class CMap extends CMapElement {
|
|
|
|
public const ACCESS_RULES = [
|
|
'get' => ['min_user_type' => USER_TYPE_ZABBIX_USER],
|
|
'create' => ['min_user_type' => USER_TYPE_ZABBIX_USER, 'action' => CRoleHelper::ACTIONS_EDIT_MAPS],
|
|
'update' => ['min_user_type' => USER_TYPE_ZABBIX_USER, 'action' => CRoleHelper::ACTIONS_EDIT_MAPS],
|
|
'delete' => ['min_user_type' => USER_TYPE_ZABBIX_USER, 'action' => CRoleHelper::ACTIONS_EDIT_MAPS]
|
|
];
|
|
|
|
protected $tableName = 'sysmaps';
|
|
protected $tableAlias = 's';
|
|
protected $sortColumns = ['name', 'width', 'height'];
|
|
|
|
private $defOptions = [
|
|
'sysmapids' => null,
|
|
'userids' => null,
|
|
'editable' => false,
|
|
'nopermissions' => null,
|
|
// filter
|
|
'filter' => null,
|
|
'search' => null,
|
|
'searchByAny' => null,
|
|
'startSearch' => false,
|
|
'excludeSearch' => false,
|
|
'searchWildcardsEnabled' => null,
|
|
// output
|
|
'output' => API_OUTPUT_EXTEND,
|
|
'selectSelements' => null,
|
|
'selectShapes' => null,
|
|
'selectLines' => null,
|
|
'selectLinks' => null,
|
|
'selectIconMap' => null,
|
|
'selectUrls' => null,
|
|
'selectUsers' => null,
|
|
'selectUserGroups' => null,
|
|
'countOutput' => false,
|
|
'expandUrls' => null,
|
|
'preservekeys' => false,
|
|
'sortfield' => '',
|
|
'sortorder' => '',
|
|
'limit' => null
|
|
];
|
|
|
|
/**
|
|
* Get map data.
|
|
*
|
|
* @param array $options
|
|
* @param array $options['sysmapids'] Map IDs.
|
|
* @param bool $options['output'] List of map parameters to return.
|
|
* @param array $options['selectSelements'] List of map element properties to return.
|
|
* @param array $options['selectShapes'] List of map shape properties to return.
|
|
* @param array $options['selectLines'] List of map line properties to return.
|
|
* @param array $options['selectLinks'] List of map link properties to return.
|
|
* @param array $options['selectIconMap'] List of map icon map properties to return.
|
|
* @param array $options['selectUrls'] List of map URL properties to return.
|
|
* @param array $options['selectUsers'] List of users that the map is shared with.
|
|
* @param array $options['selectUserGroups'] List of user groups that the map is shared with.
|
|
* @param bool $options['countOutput'] Return the count of records, instead of actual results.
|
|
* @param array $options['userids'] Map owner user IDs.
|
|
* @param bool $options['editable'] Return with read-write permission only. Ignored for
|
|
* SuperAdmins.
|
|
* @param bool $options['nopermissions'] Return requested maps even if user has no permissions to
|
|
* them.
|
|
* @param array $options['filter'] List of field and exactly matched value pairs by which maps
|
|
* need to be filtered.
|
|
* @param array $options['search'] List of field-value pairs by which maps need to be searched.
|
|
* @param array $options['expandUrls'] Adds global map URLs to the corresponding map elements and
|
|
* expands macros in all map element URLs.
|
|
* @param bool $options['searchByAny']
|
|
* @param bool $options['startSearch']
|
|
* @param bool $options['excludeSearch']
|
|
* @param bool $options['searchWildcardsEnabled']
|
|
* @param array $options['preservekeys'] Use IDs as keys in the resulting array.
|
|
* @param int $options['limit'] Limit selection.
|
|
* @param string $options['sortorder']
|
|
* @param string $options['sortfield']
|
|
*
|
|
* @return array|integer Requested map data as array or the count of retrieved objects, if the countOutput
|
|
* parameter has been used.
|
|
*/
|
|
public function get(array $options = []) {
|
|
$options = zbx_array_merge($this->defOptions, $options);
|
|
|
|
$limit = $options['limit'];
|
|
$options['limit'] = null;
|
|
|
|
if ($options['countOutput']) {
|
|
$count_output = true;
|
|
$options['output'] = ['sysmapid'];
|
|
$options['countOutput'] = false;
|
|
}
|
|
else {
|
|
$count_output = false;
|
|
}
|
|
|
|
$result = $this->getMaps($options);
|
|
|
|
if ($result && self::$userData['type'] != USER_TYPE_SUPER_ADMIN && !$options['nopermissions']) {
|
|
$sysmapids = array_flip($this->checkPermissions(array_keys($result), (bool) $options['editable']));
|
|
|
|
foreach ($result as $sysmapid => $foo) {
|
|
if (!array_key_exists($sysmapid, $sysmapids)) {
|
|
unset($result[$sysmapid]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($count_output) {
|
|
return (string) count($result);
|
|
}
|
|
|
|
if ($limit !== null) {
|
|
$result = array_slice($result, 0, $limit, true);
|
|
}
|
|
|
|
if ($result) {
|
|
$result = $this->addRelatedObjects($options, $result);
|
|
}
|
|
|
|
// removing keys (hash -> array)
|
|
if (!$options['preservekeys']) {
|
|
$result = zbx_cleanHashes($result);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Returns maps without checking permissions to the elements.
|
|
*/
|
|
private function getMaps(array $options) {
|
|
$sql_parts = [
|
|
'select' => ['sysmaps' => 's.sysmapid'],
|
|
'from' => ['sysmaps' => 'sysmaps s'],
|
|
'where' => [],
|
|
'order' => [],
|
|
'limit' => null
|
|
];
|
|
|
|
// Editable + permission check.
|
|
if (self::$userData['type'] < USER_TYPE_ZABBIX_ADMIN && !$options['nopermissions']) {
|
|
$public_maps = '';
|
|
|
|
if ($options['editable']) {
|
|
$permission = PERM_READ_WRITE;
|
|
}
|
|
else {
|
|
$permission = PERM_READ;
|
|
$public_maps = ' OR s.private='.PUBLIC_SHARING;
|
|
}
|
|
|
|
$user_groups = getUserGroupsByUserId(self::$userData['userid']);
|
|
|
|
$sql_parts['where'][] = '(EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM sysmap_user su'.
|
|
' WHERE s.sysmapid=su.sysmapid'.
|
|
' AND su.userid='.self::$userData['userid'].
|
|
' AND su.permission>='.$permission.
|
|
')'.
|
|
' OR EXISTS ('.
|
|
'SELECT NULL'.
|
|
' FROM sysmap_usrgrp sg'.
|
|
' WHERE s.sysmapid=sg.sysmapid'.
|
|
' AND '.dbConditionInt('sg.usrgrpid', $user_groups).
|
|
' AND sg.permission>='.$permission.
|
|
')'.
|
|
' OR s.userid='.self::$userData['userid'].
|
|
$public_maps.
|
|
')';
|
|
}
|
|
|
|
// sysmapids
|
|
if ($options['sysmapids'] !== null) {
|
|
zbx_value2array($options['sysmapids']);
|
|
$sql_parts['where']['sysmapid'] = dbConditionInt('s.sysmapid', $options['sysmapids']);
|
|
}
|
|
|
|
// userids
|
|
if ($options['userids'] !== null) {
|
|
zbx_value2array($options['userids']);
|
|
|
|
$sql_parts['where'][] = dbConditionInt('s.userid', $options['userids']);
|
|
}
|
|
|
|
// search
|
|
if ($options['search'] !== null) {
|
|
zbx_db_search('sysmaps s', $options, $sql_parts);
|
|
}
|
|
|
|
// filter
|
|
if ($options['filter'] !== null) {
|
|
$this->dbFilter('sysmaps s', $options, $sql_parts);
|
|
}
|
|
|
|
// limit
|
|
if (zbx_ctype_digit($options['limit']) && $options['limit']) {
|
|
$sql_parts['limit'] = $options['limit'];
|
|
}
|
|
|
|
$result = [];
|
|
|
|
$sql_parts = $this->applyQueryOutputOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts);
|
|
$sql_parts = $this->applyQuerySortOptions($this->tableName(), $this->tableAlias(), $options, $sql_parts);
|
|
$sysmaps = DBselect(self::createSelectQueryFromParts($sql_parts), $sql_parts['limit']);
|
|
|
|
while ($sysmap = DBfetch($sysmaps)) {
|
|
$result[$sysmap['sysmapid']] = $sysmap;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Returns maps with selected permission level.
|
|
*
|
|
* @param array $sysmapids
|
|
* @param bool $editable
|
|
*
|
|
* @return array
|
|
*/
|
|
private function checkPermissions(array $sysmapids, $editable) {
|
|
$sysmaps_r = [];
|
|
foreach ($sysmapids as $sysmapid) {
|
|
$sysmaps_r[$sysmapid] = true;
|
|
}
|
|
|
|
$selement_maps = [];
|
|
|
|
// Populating the map tree $selement_maps and list of shared maps $sysmaps_r.
|
|
do {
|
|
$selements = self::getSelements($sysmapids, SYSMAP_ELEMENT_TYPE_MAP);
|
|
|
|
$sysmapids = [];
|
|
|
|
foreach ($selements as $sysmapid => $selement) {
|
|
if (!array_key_exists($sysmapid, $sysmaps_r)) {
|
|
$sysmapids[$sysmapid] = true;
|
|
}
|
|
}
|
|
|
|
$sysmapids = array_keys($sysmapids);
|
|
$selement_maps += $selements;
|
|
|
|
if ($sysmapids) {
|
|
$db_sysmaps = $this->getMaps([
|
|
'output' => [],
|
|
'sysmapids' => $sysmapids,
|
|
'preservekeys' => true
|
|
] + $this->defOptions);
|
|
|
|
foreach ($sysmapids as $i => $sysmapid) {
|
|
if (array_key_exists($sysmapid, $db_sysmaps)) {
|
|
$sysmaps_r[$sysmapid] = true;
|
|
}
|
|
else {
|
|
unset($sysmapids[$i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while ($sysmapids);
|
|
|
|
$sysmaps_rw = $editable ? $sysmaps_r : [];
|
|
|
|
foreach ($sysmaps_r as &$sysmap_r) {
|
|
$sysmap_r = ['permission' => PERM_NONE, 'has_elements' => false];
|
|
}
|
|
unset($sysmap_r);
|
|
|
|
self::setHasElements($sysmaps_r, $selement_maps);
|
|
|
|
// Setting PERM_READ permission for maps with at least one image.
|
|
$selement_images = self::getSelements(array_keys($sysmaps_r), SYSMAP_ELEMENT_TYPE_IMAGE);
|
|
self::setMapPermissions($sysmaps_r, $selement_images, [0 => []], $selement_maps);
|
|
self::setHasElements($sysmaps_r, $selement_images);
|
|
|
|
$sysmapids = self::getSysmapIds($sysmaps_r, $sysmaps_rw);
|
|
|
|
// Check permissions to the host groups.
|
|
if ($sysmapids) {
|
|
$selement_groups = self::getSelements($sysmapids, SYSMAP_ELEMENT_TYPE_HOST_GROUP);
|
|
|
|
$db_groups = API::HostGroup()->get([
|
|
'output' => [],
|
|
'groupids' => array_keys($selement_groups),
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
if ($editable) {
|
|
self::unsetMapsByElements($sysmaps_rw, $selement_groups, $db_groups);
|
|
}
|
|
self::setMapPermissions($sysmaps_r, $selement_groups, $db_groups, $selement_maps);
|
|
self::setHasElements($sysmaps_r, $selement_groups);
|
|
|
|
$sysmapids = self::getSysmapIds($sysmaps_r, $sysmaps_rw);
|
|
}
|
|
|
|
// Check permissions to the hosts.
|
|
if ($sysmapids) {
|
|
$selement_hosts = self::getSelements($sysmapids, SYSMAP_ELEMENT_TYPE_HOST);
|
|
|
|
$db_hosts = API::Host()->get([
|
|
'output' => [],
|
|
'hostids' => array_keys($selement_hosts),
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
if ($editable) {
|
|
self::unsetMapsByElements($sysmaps_rw, $selement_hosts, $db_hosts);
|
|
}
|
|
self::setMapPermissions($sysmaps_r, $selement_hosts, $db_hosts, $selement_maps);
|
|
self::setHasElements($sysmaps_r, $selement_hosts);
|
|
|
|
$sysmapids = self::getSysmapIds($sysmaps_r, $sysmaps_rw);
|
|
}
|
|
|
|
// Check permissions to the triggers.
|
|
if ($sysmapids) {
|
|
$selement_triggers = self::getSelements($sysmapids, SYSMAP_ELEMENT_TYPE_TRIGGER);
|
|
$link_triggers = self::getLinkTriggers($sysmapids);
|
|
|
|
$db_triggers = API::Trigger()->get([
|
|
'output' => [],
|
|
'triggerids' => array_keys($selement_triggers + $link_triggers),
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
if ($editable) {
|
|
self::unsetMapsByElements($sysmaps_rw, $selement_triggers, $db_triggers);
|
|
self::unsetMapsByElements($sysmaps_rw, $link_triggers, $db_triggers);
|
|
}
|
|
self::setMapPermissions($sysmaps_r, $selement_triggers, $db_triggers, $selement_maps);
|
|
self::setMapPermissions($sysmaps_r, $link_triggers, $db_triggers, $selement_maps);
|
|
self::setHasElements($sysmaps_r, $selement_triggers);
|
|
self::setHasElements($sysmaps_r, $link_triggers);
|
|
}
|
|
|
|
foreach ($sysmaps_r as $sysmapid => $sysmap_r) {
|
|
if (!$sysmap_r['has_elements']) {
|
|
self::setMapPermission($sysmaps_r, $selement_maps, $sysmapid);
|
|
}
|
|
}
|
|
|
|
foreach ($sysmaps_r as $sysmapid => $sysmap_r) {
|
|
if ($sysmap_r['permission'] == PERM_NONE) {
|
|
unset($sysmaps_r[$sysmapid]);
|
|
}
|
|
}
|
|
|
|
if ($editable) {
|
|
self::unsetMapsByTree($sysmaps_rw, $sysmaps_r, $selement_maps);
|
|
}
|
|
|
|
return array_keys($editable ? $sysmaps_rw : $sysmaps_r);
|
|
}
|
|
|
|
/**
|
|
* Returns map elements for selected maps.
|
|
*/
|
|
private static function getSelements(array $sysmapids, $elementtype) {
|
|
$selements = [];
|
|
|
|
switch ($elementtype) {
|
|
case SYSMAP_ELEMENT_TYPE_IMAGE:
|
|
$sql = 'SELECT se.sysmapid,0 AS elementid'.
|
|
' FROM sysmaps_elements se'.
|
|
' WHERE '.dbConditionInt('se.sysmapid', $sysmapids).
|
|
' AND '.dbConditionInt('se.elementtype', [$elementtype]);
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_HOST_GROUP:
|
|
case SYSMAP_ELEMENT_TYPE_HOST:
|
|
case SYSMAP_ELEMENT_TYPE_MAP:
|
|
$sql = 'SELECT se.sysmapid,se.elementid'.
|
|
' FROM sysmaps_elements se'.
|
|
' WHERE '.dbConditionInt('se.sysmapid', $sysmapids).
|
|
' AND '.dbConditionInt('se.elementtype', [$elementtype]);
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_TRIGGER:
|
|
$sql = 'SELECT se.sysmapid,st.triggerid AS elementid'.
|
|
' FROM sysmaps_elements se,sysmap_element_trigger st'.
|
|
' WHERE se.selementid=st.selementid'.
|
|
' AND '.dbConditionInt('se.sysmapid', $sysmapids).
|
|
' AND '.dbConditionInt('se.elementtype', [$elementtype]);
|
|
break;
|
|
}
|
|
$db_selements = DBSelect($sql);
|
|
|
|
while ($db_selement = DBfetch($db_selements)) {
|
|
$selements[$db_selement['elementid']][] = ['sysmapid' => $db_selement['sysmapid']];
|
|
}
|
|
|
|
return $selements;
|
|
}
|
|
|
|
/**
|
|
* Returns map links for selected maps.
|
|
*/
|
|
private static function getLinkTriggers(array $sysmapids) {
|
|
$link_triggers = [];
|
|
|
|
$db_links = DBSelect(
|
|
'SELECT sl.sysmapid,slt.triggerid'.
|
|
' FROM sysmaps_links sl,sysmaps_link_triggers slt'.
|
|
' WHERE sl.linkid=slt.linkid'.
|
|
' AND '.dbConditionInt('sl.sysmapid', $sysmapids)
|
|
);
|
|
|
|
while ($db_link = DBfetch($db_links)) {
|
|
$link_triggers[$db_link['triggerid']][] = ['sysmapid' => $db_link['sysmapid']];
|
|
}
|
|
|
|
return $link_triggers;
|
|
}
|
|
|
|
/**
|
|
* Removes all inaccessible maps by map tree.
|
|
*
|
|
* @param array $sysmaps_rw[<sysmapids>] The list of writable maps.
|
|
* @param array $sysmaps_r[<sysmapids>] The list of readable maps.
|
|
* @param array $selement_maps The map tree.
|
|
* @param array $selement_maps[<sysmapid>][]['sysmapid'] Parent map ID.
|
|
*/
|
|
private static function unsetMapsByTree(array &$sysmaps_rw, array $sysmaps_r, array $selement_maps) {
|
|
foreach ($selement_maps as $child_sysmapid => $selements) {
|
|
if (!array_key_exists($child_sysmapid, $sysmaps_r)) {
|
|
foreach ($selements as $selement) {
|
|
unset($sysmaps_rw[$selement['sysmapid']]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes all inaccessible maps by inaccessible elements.
|
|
*
|
|
* @param array $sysmaps_rw[<sysmapids>] The list of writable maps.
|
|
* @param array $elements The map elements.
|
|
* @param array $elements[<elementid>][]['sysmapid'] Map ID.
|
|
* @param array $db_elements The list of readable elements.
|
|
* @param array $db_elements[<elementid>]
|
|
*/
|
|
private static function unsetMapsByElements(array &$sysmaps_rw, array $elements, array $db_elements) {
|
|
foreach ($elements as $elementid => $selements) {
|
|
if (!array_key_exists($elementid, $db_elements)) {
|
|
foreach ($selements as $selement) {
|
|
unset($sysmaps_rw[$selement['sysmapid']]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set PERM_READ permission for map and all parent maps.
|
|
*
|
|
* @param array $sysmaps_r[<sysmapids>] The list of readable maps.
|
|
* @param array $selement_maps The map elements.
|
|
* @param array $selement_maps[<sysmapid>][]['sysmapid'] Map ID.
|
|
* @param string $sysmapid
|
|
*/
|
|
private static function setMapPermission(array &$sysmaps_r, array $selement_maps, $sysmapid) {
|
|
if (array_key_exists($sysmapid, $selement_maps)) {
|
|
foreach ($selement_maps[$sysmapid] as $selement) {
|
|
self::setMapPermission($sysmaps_r, $selement_maps, $selement['sysmapid']);
|
|
}
|
|
}
|
|
$sysmaps_r[$sysmapid]['permission'] = PERM_READ;
|
|
}
|
|
|
|
/**
|
|
* Setting PERM_READ permissions for maps with at least one available element.
|
|
*
|
|
* @param array $sysmaps_r[<sysmapids>] The list of readable maps.
|
|
* @param array $elements The map elements.
|
|
* @param array $elements[<elementid>][]['sysmapid'] Map ID.
|
|
* @param array $db_elements The list of readable elements.
|
|
* @param array $db_elements[<elementid>]
|
|
* @param array $selement_maps The map elements.
|
|
* @param array $selement_maps[<sysmapid>][]['sysmapid'] Map ID.
|
|
*/
|
|
private static function setMapPermissions(array &$sysmaps_r, array $elements, array $db_elements,
|
|
array $selement_maps) {
|
|
foreach ($elements as $elementid => $selements) {
|
|
if (array_key_exists($elementid, $db_elements)) {
|
|
foreach ($selements as $selement) {
|
|
self::setMapPermission($sysmaps_r, $selement_maps, $selement['sysmapid']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setting "has_elements" flag for maps.
|
|
*
|
|
* @param array $sysmaps_r[<sysmapids>] The list of readable maps.
|
|
* @param array $elements The map elements.
|
|
* @param array $elements[<elementid>]
|
|
*/
|
|
private static function setHasElements(array &$sysmaps_r, array $elements) {
|
|
foreach ($elements as $elementid => $selements) {
|
|
foreach ($selements as $selement) {
|
|
$sysmaps_r[$selement['sysmapid']]['has_elements'] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns map ids which will be checked for permissions.
|
|
*
|
|
* @param array $sysmaps_r
|
|
* @param array $sysmaps_r[<sysmapid>]['permission']
|
|
* @param array $sysmaps_rw
|
|
* @param array $sysmaps_rw[<sysmapid>]
|
|
*/
|
|
private static function getSysmapIds(array $sysmaps_r, array $sysmaps_rw) {
|
|
$sysmapids = $sysmaps_rw;
|
|
|
|
foreach ($sysmaps_r as $sysmapid => $sysmap) {
|
|
if ($sysmap['permission'] == PERM_NONE) {
|
|
$sysmapids[$sysmapid] = true;
|
|
}
|
|
}
|
|
|
|
return array_keys($sysmapids);
|
|
}
|
|
|
|
/**
|
|
* Validates the input parameters for the delete() method.
|
|
*
|
|
* @param array $sysmapids
|
|
* @param array $db_maps
|
|
*
|
|
* @throws APIException if the input is invalid.
|
|
*/
|
|
protected function validateDelete(array $sysmapids, array &$db_maps = null) {
|
|
if (!$sysmapids) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.'));
|
|
}
|
|
|
|
$db_maps = $this->get([
|
|
'output' => ['sysmapid', 'name'],
|
|
'sysmapids' => $sysmapids,
|
|
'editable' => true,
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
foreach ($sysmapids as $sysmapid) {
|
|
if (!array_key_exists($sysmapid, $db_maps)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate the input parameters for the create() method.
|
|
*
|
|
* @param array $maps maps data array
|
|
*
|
|
* @throws APIException if the input is invalid.
|
|
*/
|
|
protected function validateCreate(array $maps) {
|
|
if (!$maps) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.'));
|
|
}
|
|
|
|
$user_data = self::$userData;
|
|
|
|
$map_db_fields = [
|
|
'name' => null,
|
|
'width' => null,
|
|
'height' => null,
|
|
'urls' => [],
|
|
'selements' => [],
|
|
'links' => []
|
|
];
|
|
|
|
// Validate mandatory fields and map name.
|
|
foreach ($maps as $map) {
|
|
if (!check_db_fields($map_db_fields, $map)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect fields for sysmap.'));
|
|
}
|
|
}
|
|
|
|
// Check for duplicate names.
|
|
$duplicate = CArrayHelper::findDuplicate($maps, 'name');
|
|
if ($duplicate) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Duplicate "name" value "%1$s" for map.', $duplicate['name'])
|
|
);
|
|
}
|
|
|
|
// Check if map already exists.
|
|
$db_maps = $this->get([
|
|
'output' => ['name'],
|
|
'filter' => ['name' => zbx_objectValues($maps, 'name')],
|
|
'nopermissions' => true,
|
|
'limit' => 1
|
|
]);
|
|
|
|
if ($db_maps) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Map "%1$s" already exists.', $db_maps[0]['name']));
|
|
}
|
|
|
|
$private_validator = new CLimitedSetValidator([
|
|
'values' => [PUBLIC_SHARING, PRIVATE_SHARING]
|
|
]);
|
|
|
|
$permission_validator = new CLimitedSetValidator([
|
|
'values' => [PERM_READ, PERM_READ_WRITE]
|
|
]);
|
|
|
|
$show_suppressed_types = [ZBX_PROBLEM_SUPPRESSED_FALSE, ZBX_PROBLEM_SUPPRESSED_TRUE];
|
|
$show_suppressed_validator = new CLimitedSetValidator(['values' => $show_suppressed_types]);
|
|
|
|
$expandproblem_types = [SYSMAP_PROBLEMS_NUMBER, SYSMAP_SINGLE_PROBLEM, SYSMAP_PROBLEMS_NUMBER_CRITICAL];
|
|
$expandproblem_validator = new CLimitedSetValidator(['values' => $expandproblem_types]);
|
|
|
|
// Continue to check 2 more mandatory fields and other optional fields.
|
|
foreach ($maps as $map_index => $map) {
|
|
// Check mandatory fields "width" and "height".
|
|
if ($map['width'] > 65535 || $map['width'] < 1) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect "width" value for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
if ($map['height'] > 65535 || $map['height'] < 1) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect "height" value for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
// Check if owner can be set.
|
|
if (array_key_exists('userid', $map)) {
|
|
if ($map['userid'] === '' || $map['userid'] === null || $map['userid'] === false) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Map owner cannot be empty.'));
|
|
}
|
|
elseif ($map['userid'] != $user_data['userid'] && $user_data['type'] != USER_TYPE_SUPER_ADMIN
|
|
&& $user_data['type'] != USER_TYPE_ZABBIX_ADMIN) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Only administrators can set map owner.'));
|
|
}
|
|
}
|
|
|
|
// Check for invalid "private" values.
|
|
if (array_key_exists('private', $map)) {
|
|
if (!$private_validator->validate($map['private'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect "private" value "%1$s" for map "%2$s".', $map['private'], $map['name'])
|
|
);
|
|
}
|
|
}
|
|
|
|
// Check for invalid "show_suppressed" values.
|
|
if (array_key_exists('show_suppressed', $map)
|
|
&& !$show_suppressed_validator->validate($map['show_suppressed'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.',
|
|
'show_suppressed', _s('value must be one of %1$s', implode(', ', $show_suppressed_types))
|
|
));
|
|
}
|
|
|
|
if (array_key_exists('expandproblem', $map) && !$expandproblem_validator->validate($map['expandproblem'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 'expandproblem',
|
|
_s('value must be one of %1$s', implode(', ', $expandproblem_types))
|
|
));
|
|
}
|
|
|
|
$userids = [];
|
|
|
|
// Map user shares.
|
|
if (array_key_exists('users', $map)) {
|
|
if (!is_array($map['users'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
|
|
$required_fields = ['userid', 'permission'];
|
|
|
|
foreach ($map['users'] as $share) {
|
|
// Check required parameters.
|
|
$missing_keys = array_diff($required_fields, array_keys($share));
|
|
|
|
if ($missing_keys) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'User sharing is missing parameters: %1$s for map "%2$s".',
|
|
implode(', ', $missing_keys),
|
|
$map['name']
|
|
));
|
|
}
|
|
else {
|
|
foreach ($required_fields as $field) {
|
|
if ($share[$field] === '' || $share[$field] === null) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Sharing option "%1$s" is missing a value for map "%2$s".',
|
|
$field,
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$permission_validator->validate($share['permission'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect "permission" value "%1$s" in users for map "%2$s".',
|
|
$share['permission'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if (array_key_exists('private', $map) && $map['private'] == PUBLIC_SHARING
|
|
&& $share['permission'] == PERM_READ) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Map "%1$s" is public and read-only sharing is disallowed.', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (array_key_exists($share['userid'], $userids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Duplicate userid "%1$s" in users for map "%2$s".', $share['userid'], $map['name'])
|
|
);
|
|
}
|
|
|
|
$userids[$share['userid']] = $share['userid'];
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('userid', $map) && $map['userid']) {
|
|
$userids[$map['userid']] = $map['userid'];
|
|
}
|
|
|
|
// Users validation.
|
|
if ($userids) {
|
|
$db_users = API::User()->get([
|
|
'userids' => $userids,
|
|
'countOutput' => true
|
|
]);
|
|
|
|
if (count($userids) != $db_users) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect user ID specified for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
}
|
|
|
|
// Map user group shares.
|
|
if (array_key_exists('userGroups', $map)) {
|
|
if (!is_array($map['userGroups'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
|
|
$shared_user_groupids = [];
|
|
$required_fields = ['usrgrpid', 'permission'];
|
|
|
|
foreach ($map['userGroups'] as $share) {
|
|
// Check required parameters.
|
|
$missing_keys = array_diff($required_fields, array_keys($share));
|
|
|
|
if ($missing_keys) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'User group sharing is missing parameters: %1$s for map "%2$s".',
|
|
implode(', ', $missing_keys),
|
|
$map['name']
|
|
));
|
|
}
|
|
else {
|
|
foreach ($required_fields as $field) {
|
|
if ($share[$field] === '' || $share[$field] === null) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Field "%1$s" is missing a value for map "%2$s".',
|
|
$field,
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$permission_validator->validate($share['permission'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect "permission" value "%1$s" in user groups for map "%2$s".',
|
|
$share['permission'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if (array_key_exists('private', $map) && $map['private'] == PUBLIC_SHARING
|
|
&& $share['permission'] == PERM_READ) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Map "%1$s" is public and read-only sharing is disallowed.', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (array_key_exists($share['usrgrpid'], $shared_user_groupids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Duplicate "usrgrpid" "%1$s" in user groups for map "%2$s".',
|
|
$share['usrgrpid'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
$shared_user_groupids[$share['usrgrpid']] = $share['usrgrpid'];
|
|
}
|
|
|
|
if ($shared_user_groupids) {
|
|
$db_user_groups = API::UserGroup()->get([
|
|
'usrgrpids' => $shared_user_groupids,
|
|
'countOutput' => true
|
|
]);
|
|
|
|
if (count($shared_user_groupids) != $db_user_groups) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect user group ID specified for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
}
|
|
|
|
unset($shared_user_groupids);
|
|
}
|
|
|
|
// Map labels.
|
|
$map_labels = ['label_type' => ['typeName' => _('icon')]];
|
|
|
|
if (array_key_exists('label_format', $map) && $map['label_format'] == SYSMAP_LABEL_ADVANCED_ON) {
|
|
$map_labels['label_type_hostgroup'] = [
|
|
'string' => 'label_string_hostgroup',
|
|
'typeName' => _('host group')
|
|
];
|
|
$map_labels['label_type_host'] = [
|
|
'string' => 'label_string_host',
|
|
'typeName' => _('host')
|
|
];
|
|
$map_labels['label_type_trigger'] = [
|
|
'string' => 'label_string_trigger',
|
|
'typeName' => _('trigger')
|
|
];
|
|
$map_labels['label_type_map'] = [
|
|
'string' => 'label_string_map',
|
|
'typeName' => _('map')
|
|
];
|
|
$map_labels['label_type_image'] = [
|
|
'string' => 'label_string_image',
|
|
'typeName' => _('image')
|
|
];
|
|
}
|
|
|
|
foreach ($map_labels as $label_name => $label_data) {
|
|
if (!array_key_exists($label_name, $map)) {
|
|
continue;
|
|
}
|
|
|
|
if (sysmapElementLabel($map[$label_name]) === false) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect %1$s label type value for map "%2$s".', $label_data['typeName'], $map['name'])
|
|
);
|
|
}
|
|
|
|
if ($map[$label_name] == MAP_LABEL_TYPE_CUSTOM) {
|
|
if (!array_key_exists('string', $label_data)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect %1$s label type value for map "%2$s".', $label_data['typeName'], $map['name'])
|
|
);
|
|
}
|
|
|
|
if (!array_key_exists($label_data['string'], $map) || zbx_empty($map[$label_data['string']])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Custom label for map "%2$s" elements of type "%1$s" may not be empty.',
|
|
$label_data['typeName'],
|
|
$map['name']
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
if ($label_name == 'label_type_image' && $map[$label_name] == MAP_LABEL_TYPE_STATUS) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect %1$s label type value for map "%2$s".', $label_data['typeName'], $map['name'])
|
|
);
|
|
}
|
|
|
|
if ($label_name === 'label_type' || $label_name === 'label_type_host') {
|
|
continue;
|
|
}
|
|
|
|
if ($map[$label_name] == MAP_LABEL_TYPE_IP) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect %1$s label type value for map "%2$s".', $label_data['typeName'], $map['name'])
|
|
);
|
|
}
|
|
}
|
|
|
|
// Validating grid options.
|
|
$possibleGridSizes = [20, 40, 50, 75, 100];
|
|
|
|
// Grid size.
|
|
if (array_key_exists('grid_size', $map) && !in_array($map['grid_size'], $possibleGridSizes)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Value "%1$s" is invalid for parameter "grid_show". Choices are: "%2$s".',
|
|
$map['grid_size'],
|
|
implode('", "', $possibleGridSizes)
|
|
));
|
|
}
|
|
|
|
// Grid auto align.
|
|
if (array_key_exists('grid_align', $map) && $map['grid_align'] != SYSMAP_GRID_ALIGN_ON
|
|
&& $map['grid_align'] != SYSMAP_GRID_ALIGN_OFF) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Value "%1$s" is invalid for parameter "grid_align". Choices are: "%2$s" and "%3$s"',
|
|
$map['grid_align'],
|
|
SYSMAP_GRID_ALIGN_ON,
|
|
SYSMAP_GRID_ALIGN_OFF
|
|
));
|
|
}
|
|
|
|
// Grid show.
|
|
if (array_key_exists('grid_show', $map) && $map['grid_show'] != SYSMAP_GRID_SHOW_ON
|
|
&& $map['grid_show'] != SYSMAP_GRID_SHOW_OFF) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Value "%1$s" is invalid for parameter "grid_show". Choices are: "%2$s" and "%3$s".',
|
|
$map['grid_show'],
|
|
SYSMAP_GRID_SHOW_ON,
|
|
SYSMAP_GRID_SHOW_OFF
|
|
));
|
|
}
|
|
|
|
// Urls.
|
|
if (array_key_exists('urls', $map) && $map['urls']) {
|
|
$url_names = zbx_toHash($map['urls'], 'name');
|
|
|
|
foreach ($map['urls'] as $url) {
|
|
if ($url['name'] === '' || $url['url'] === '') {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('URL should have both "name" and "url" fields for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (!array_key_exists($url['name'], $url_names)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('URL name should be unique for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
$url_validate_options = ['allow_user_macro' => false];
|
|
if ($url['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST) {
|
|
$url_validate_options['allow_inventory_macro'] = INVENTORY_URL_MACRO_HOST;
|
|
}
|
|
elseif ($url['elementtype'] == SYSMAP_ELEMENT_TYPE_TRIGGER) {
|
|
$url_validate_options['allow_inventory_macro'] = INVENTORY_URL_MACRO_TRIGGER;
|
|
}
|
|
else {
|
|
$url_validate_options['allow_inventory_macro'] = INVENTORY_URL_MACRO_NONE;
|
|
}
|
|
|
|
if (!CHtmlUrlValidator::validate($url['url'], $url_validate_options)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Wrong value for "url" field.'));
|
|
}
|
|
|
|
unset($url_names[$url['name']]);
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('selements', $map)) {
|
|
if (!is_array($map['selements'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
elseif (!CMapHelper::checkSelementPermissions($map['selements'])) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS,
|
|
_('No permissions to referred object or it does not exist!')
|
|
);
|
|
}
|
|
|
|
foreach (array_values($map['selements']) as $selement_index => $selement) {
|
|
$this->validateSelementTags($selement, '/'.($map_index + 1).'/selements/'.($selement_index + 1));
|
|
}
|
|
}
|
|
|
|
// Map selement links.
|
|
if (array_key_exists('links', $map) && $map['links']) {
|
|
$selementids = zbx_objectValues($map['selements'], 'selementid');
|
|
|
|
foreach ($map['links'] as $link) {
|
|
if (!in_array($link['selementid1'], $selementids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Link "selementid1" field is pointing to a nonexistent map selement ID "%1$s" for map "%2$s".',
|
|
$link['selementid1'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if (!in_array($link['selementid2'], $selementids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Link "selementid2" field is pointing to a nonexistent map selement ID "%1$s" for map "%2$s".',
|
|
$link['selementid2'],
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate the input parameters for the update() method.
|
|
*
|
|
* @param array $maps maps data array
|
|
* @param array $db_maps db maps data array
|
|
*
|
|
* @throws APIException if the input is invalid.
|
|
*/
|
|
protected function validateUpdate(array $maps, array $db_maps) {
|
|
if (!$maps) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Empty input parameter.'));
|
|
}
|
|
|
|
$user_data = self::$userData;
|
|
|
|
// Validate given IDs.
|
|
$this->checkObjectIds($maps, 'sysmapid',
|
|
_('No "%1$s" given for map.'),
|
|
_('Empty map ID.'),
|
|
_('Incorrect map ID.')
|
|
);
|
|
|
|
$check_names = [];
|
|
|
|
foreach ($maps as $map) {
|
|
// Check if this map exists and user has write permissions.
|
|
if (!array_key_exists($map['sysmapid'], $db_maps)) {
|
|
self::exception(ZBX_API_ERROR_PERMISSIONS,
|
|
_('No permissions to referred object or it does not exist!')
|
|
);
|
|
}
|
|
|
|
// Validate "name" field.
|
|
if (array_key_exists('name', $map)) {
|
|
if (is_array($map['name'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
elseif ($map['name'] === '' || $map['name'] === null || $map['name'] === false) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Map name cannot be empty.'));
|
|
}
|
|
|
|
if ($db_maps[$map['sysmapid']]['name'] !== $map['name']) {
|
|
$check_names[] = $map;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($check_names) {
|
|
// Check for duplicate names.
|
|
$duplicate = CArrayHelper::findDuplicate($check_names, 'name');
|
|
if ($duplicate) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Duplicate "name" value "%1$s" for map.', $duplicate['name'])
|
|
);
|
|
}
|
|
|
|
$db_map_names = $this->get([
|
|
'output' => ['sysmapid', 'name'],
|
|
'filter' => ['name' => zbx_objectValues($check_names, 'name')],
|
|
'nopermissions' => true
|
|
]);
|
|
$db_map_names = zbx_toHash($db_map_names, 'name');
|
|
|
|
// Check for existing names.
|
|
foreach ($check_names as $map) {
|
|
if (array_key_exists($map['name'], $db_map_names)
|
|
&& bccomp($db_map_names[$map['name']]['sysmapid'], $map['sysmapid']) != 0) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Map "%1$s" already exists.', $map['name'])
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
$private_validator = new CLimitedSetValidator([
|
|
'values' => [PUBLIC_SHARING, PRIVATE_SHARING]
|
|
]);
|
|
|
|
$permission_validator = new CLimitedSetValidator([
|
|
'values' => [PERM_READ, PERM_READ_WRITE]
|
|
]);
|
|
|
|
$show_suppressed_types = [ZBX_PROBLEM_SUPPRESSED_FALSE, ZBX_PROBLEM_SUPPRESSED_TRUE];
|
|
$show_suppressed_validator = new CLimitedSetValidator(['values' => $show_suppressed_types]);
|
|
|
|
$expandproblem_types = [SYSMAP_PROBLEMS_NUMBER, SYSMAP_SINGLE_PROBLEM, SYSMAP_PROBLEMS_NUMBER_CRITICAL];
|
|
$expandproblem_validator = new CLimitedSetValidator(['values' => $expandproblem_types]);
|
|
|
|
foreach ($maps as $map_index => $map) {
|
|
// Check if owner can be set.
|
|
if (array_key_exists('userid', $map)) {
|
|
if ($map['userid'] === '' || $map['userid'] === null || $map['userid'] === false) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Map owner cannot be empty.'));
|
|
}
|
|
elseif ($map['userid'] != $user_data['userid'] && $user_data['type'] != USER_TYPE_SUPER_ADMIN
|
|
&& $user_data['type'] != USER_TYPE_ZABBIX_ADMIN) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Only administrators can set map owner.'));
|
|
}
|
|
}
|
|
|
|
// Unset extra field.
|
|
unset($db_maps[$map['sysmapid']]['userid']);
|
|
|
|
$map = array_merge($db_maps[$map['sysmapid']], $map);
|
|
|
|
// Check "width" and "height" fields.
|
|
if ($map['width'] > 65535 || $map['width'] < 1) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect "width" value for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
if ($map['height'] > 65535 || $map['height'] < 1) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect "height" value for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (!$private_validator->validate($map['private'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect "private" value "%1$s" for map "%2$s".', $map['private'], $map['name'])
|
|
);
|
|
}
|
|
|
|
// Check for invalid "show_suppressed" values.
|
|
if (array_key_exists('show_suppressed', $map)
|
|
&& !$show_suppressed_validator->validate($map['show_suppressed'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.',
|
|
'show_suppressed', _s('value must be one of %1$s', implode(', ', $show_suppressed_types))
|
|
));
|
|
}
|
|
|
|
if (array_key_exists('expandproblem', $map) && !$expandproblem_validator->validate($map['expandproblem'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Incorrect value for field "%1$s": %2$s.', 'expandproblem',
|
|
_s('value must be one of %1$s', implode(', ', $expandproblem_types))
|
|
));
|
|
}
|
|
|
|
$userids = [];
|
|
|
|
// Map user shares.
|
|
if (array_key_exists('users', $map)) {
|
|
if (!is_array($map['users'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
|
|
$required_fields = ['userid', 'permission'];
|
|
|
|
foreach ($map['users'] as $share) {
|
|
// Check required parameters.
|
|
$missing_keys = array_diff($required_fields, array_keys($share));
|
|
|
|
if ($missing_keys) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'User sharing is missing parameters: %1$s for map "%2$s".',
|
|
implode(', ', $missing_keys),
|
|
$map['name']
|
|
));
|
|
}
|
|
else {
|
|
foreach ($required_fields as $field) {
|
|
if ($share[$field] === '' || $share[$field] === null) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Sharing option "%1$s" is missing a value for map "%2$s".',
|
|
$field,
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$permission_validator->validate($share['permission'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect "permission" value "%1$s" in users for map "%2$s".',
|
|
$share['permission'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if ($map['private'] == PUBLIC_SHARING && $share['permission'] == PERM_READ) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Map "%1$s" is public and read-only sharing is disallowed.', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (array_key_exists($share['userid'], $userids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Duplicate userid "%1$s" in users for map "%2$s".', $share['userid'], $map['name'])
|
|
);
|
|
}
|
|
|
|
$userids[$share['userid']] = $share['userid'];
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('userid', $map) && $map['userid']) {
|
|
$userids[$map['userid']] = $map['userid'];
|
|
}
|
|
|
|
// Users validation.
|
|
if ($userids) {
|
|
$db_users = API::User()->get([
|
|
'userids' => $userids,
|
|
'countOutput' => true
|
|
]);
|
|
|
|
if (count($userids) != $db_users) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect user ID specified for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
}
|
|
|
|
// Map user group shares.
|
|
if (array_key_exists('userGroups', $map)) {
|
|
if (!is_array($map['userGroups'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
|
|
$shared_user_groupids = [];
|
|
$required_fields = ['usrgrpid', 'permission'];
|
|
|
|
foreach ($map['userGroups'] as $share) {
|
|
// Check required parameters.
|
|
$missing_keys = array_diff($required_fields, array_keys($share));
|
|
|
|
if ($missing_keys) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'User group sharing is missing parameters: %1$s for map "%2$s".',
|
|
implode(', ', $missing_keys),
|
|
$map['name'])
|
|
);
|
|
}
|
|
else {
|
|
foreach ($required_fields as $field) {
|
|
if ($share[$field] === '' || $share[$field] === null) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Sharing option "%1$s" is missing a value for map "%2$s".',
|
|
$field,
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$permission_validator->validate($share['permission'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect "permission" value "%1$s" in user groups for map "%2$s".',
|
|
$share['permission'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if ($map['private'] == PUBLIC_SHARING && $share['permission'] == PERM_READ) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Map "%1$s" is public and read-only sharing is disallowed.', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (array_key_exists($share['usrgrpid'], $shared_user_groupids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Duplicate "usrgrpid" "%1$s" in user groups for map "%2$s".',
|
|
$share['usrgrpid'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
$shared_user_groupids[$share['usrgrpid']] = $share['usrgrpid'];
|
|
}
|
|
|
|
if ($shared_user_groupids) {
|
|
$db_user_groups = API::UserGroup()->get([
|
|
'usrgrpids' => $shared_user_groupids,
|
|
'countOutput' => true
|
|
]);
|
|
|
|
if (count($shared_user_groupids) != $db_user_groups) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Incorrect user group ID specified for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
}
|
|
|
|
unset($shared_user_groupids);
|
|
}
|
|
|
|
// Map labels.
|
|
$map_labels = ['label_type' => ['typeName' => _('icon')]];
|
|
|
|
if (array_key_exists('label_format', $map)
|
|
&& $map['label_format'] == SYSMAP_LABEL_ADVANCED_ON) {
|
|
$map_labels['label_type_hostgroup'] = [
|
|
'string' => 'label_string_hostgroup',
|
|
'typeName' => _('host group')
|
|
];
|
|
$map_labels['label_type_host'] = [
|
|
'string' => 'label_string_host',
|
|
'typeName' => _('host')
|
|
];
|
|
$map_labels['label_type_trigger'] = [
|
|
'string' => 'label_string_trigger',
|
|
'typeName' => _('trigger')
|
|
];
|
|
$map_labels['label_type_map'] = [
|
|
'string' => 'label_string_map',
|
|
'typeName' => _('map')
|
|
];
|
|
$map_labels['label_type_image'] = [
|
|
'string' => 'label_string_image',
|
|
'typeName' => _('image')
|
|
];
|
|
}
|
|
|
|
foreach ($map_labels as $label_name => $labelData) {
|
|
if (!array_key_exists($label_name, $map)) {
|
|
continue;
|
|
}
|
|
|
|
if (sysmapElementLabel($map[$label_name]) === false) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect %1$s label type value for map "%2$s".',
|
|
$labelData['typeName'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if ($map[$label_name] == MAP_LABEL_TYPE_CUSTOM) {
|
|
if (!array_key_exists('string', $labelData)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect %1$s label type value for map "%2$s".',
|
|
$labelData['typeName'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if (!array_key_exists($labelData['string'], $map) || zbx_empty($map[$labelData['string']])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Custom label for map "%2$s" elements of type "%1$s" may not be empty.',
|
|
$labelData['typeName'],
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
|
|
if ($label_name === 'label_type_image' && $map[$label_name] == MAP_LABEL_TYPE_STATUS) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect %1$s label type value for map "%2$s".',
|
|
$labelData['typeName'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if ($label_name === 'label_type' || $label_name === 'label_type_host') {
|
|
continue;
|
|
}
|
|
|
|
if ($map[$label_name] == MAP_LABEL_TYPE_IP) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Incorrect %1$s label type value for map "%2$s".',
|
|
$labelData['typeName'],
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
|
|
// Validating grid options.
|
|
$possibleGridSizes = [20, 40, 50, 75, 100];
|
|
|
|
// Grid size.
|
|
if (array_key_exists('grid_size', $map) && !in_array($map['grid_size'], $possibleGridSizes)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Value "%1$s" is invalid for parameter "grid_show". Choices are: "%2$s".',
|
|
$map['grid_size'],
|
|
implode('", "', $possibleGridSizes)
|
|
));
|
|
}
|
|
|
|
// Grid auto align.
|
|
if (array_key_exists('grid_align', $map) && $map['grid_align'] != SYSMAP_GRID_ALIGN_ON
|
|
&& $map['grid_align'] != SYSMAP_GRID_ALIGN_OFF) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Value "%1$s" is invalid for parameter "grid_align". Choices are: "%2$s" and "%3$s"',
|
|
$map['grid_align'],
|
|
SYSMAP_GRID_ALIGN_ON,
|
|
SYSMAP_GRID_ALIGN_OFF
|
|
));
|
|
}
|
|
|
|
// Grid show.
|
|
if (array_key_exists('grid_show', $map) && $map['grid_show'] != SYSMAP_GRID_SHOW_ON
|
|
&& $map['grid_show'] != SYSMAP_GRID_SHOW_OFF) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Value "%1$s" is invalid for parameter "grid_show". Choices are: "%2$s" and "%3$s".',
|
|
$map['grid_show'],
|
|
SYSMAP_GRID_SHOW_ON,
|
|
SYSMAP_GRID_SHOW_OFF
|
|
));
|
|
}
|
|
|
|
// Urls.
|
|
if (array_key_exists('urls', $map) && !empty($map['urls'])) {
|
|
$urlNames = zbx_toHash($map['urls'], 'name');
|
|
|
|
foreach ($map['urls'] as $url) {
|
|
if ($url['name'] === '' || $url['url'] === '') {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('URL should have both "name" and "url" fields for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
if (!array_key_exists($url['name'], $urlNames)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('URL name should be unique for map "%1$s".', $map['name'])
|
|
);
|
|
}
|
|
|
|
$url_validate_options = ['allow_user_macro' => false];
|
|
if ($url['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST) {
|
|
$url_validate_options['allow_inventory_macro'] = INVENTORY_URL_MACRO_HOST;
|
|
}
|
|
elseif ($url['elementtype'] == SYSMAP_ELEMENT_TYPE_TRIGGER) {
|
|
$url_validate_options['allow_inventory_macro'] = INVENTORY_URL_MACRO_TRIGGER;
|
|
}
|
|
else {
|
|
$url_validate_options['allow_inventory_macro'] = INVENTORY_URL_MACRO_NONE;
|
|
}
|
|
|
|
if (!CHtmlUrlValidator::validate($url['url'], $url_validate_options)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Wrong value for "url" field.'));
|
|
}
|
|
|
|
unset($urlNames[$url['name']]);
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('selements', $map) && !is_array($map['selements'])) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('Incorrect arguments passed to function.'));
|
|
}
|
|
|
|
if (array_key_exists('selements', $map)) {
|
|
foreach (array_values($map['selements']) as $selement_index => $selement) {
|
|
$this->validateSelementTags($selement, '/'.($map_index + 1).'/selements/'.($selement_index + 1));
|
|
}
|
|
}
|
|
|
|
// Map selement links.
|
|
if (array_key_exists('links', $map) && $map['links']) {
|
|
$selementids = zbx_objectValues($map['selements'], 'selementid');
|
|
|
|
foreach ($map['links'] as $link) {
|
|
if (!in_array($link['selementid1'], $selementids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Link "selementid1" field is pointing to a nonexistent map selement ID "%1$s" for map "%2$s".',
|
|
$link['selementid1'],
|
|
$map['name']
|
|
));
|
|
}
|
|
|
|
if (!in_array($link['selementid2'], $selementids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _s(
|
|
'Link "selementid2" field is pointing to a nonexistent map selement ID "%1$s" for map "%2$s".',
|
|
$link['selementid2'],
|
|
$map['name']
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate circular reference.
|
|
foreach ($maps as &$map) {
|
|
$map = array_merge($db_maps[$map['sysmapid']], $map);
|
|
$this->cref_maps[$map['sysmapid']] = $map;
|
|
}
|
|
unset($map);
|
|
|
|
$this->validateCircularReference($maps);
|
|
}
|
|
|
|
/**
|
|
* Validate Map element tag properties.
|
|
*
|
|
* @param array $selement['evaltype']
|
|
* @param array $selement['tags']
|
|
* @param string $selement['tags'][]['tag']
|
|
* @param string $selement['tags'][]['value']
|
|
* @param int $selement['tags'][]['operator']
|
|
* @param string $path
|
|
*
|
|
* @throws APIException if input is invalid.
|
|
*/
|
|
protected function validateSelementTags(array $selement, string $path): void {
|
|
if (!array_key_exists('tags', $selement)) {
|
|
return;
|
|
}
|
|
|
|
$api_input_rules = ['type' => API_OBJECT, 'fields' => [
|
|
'evaltype' => ['type' => API_INT32, 'in' => implode(',', [CONDITION_EVAL_TYPE_AND_OR, CONDITION_EVAL_TYPE_OR]), 'default' => DB::getDefault('sysmaps_elements', 'evaltype')],
|
|
'tags' => ['type' => API_OBJECTS, 'uniq' => [['tag', 'value']], 'fields' => [
|
|
'tag' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('sysmaps_element_tag', 'tag')],
|
|
'value' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmaps_element_tag', 'value'), 'default' => DB::getDefault('sysmaps_element_tag', 'value')],
|
|
'operator' => ['type' => API_STRING_UTF8, 'in' => implode(',', [TAG_OPERATOR_LIKE, TAG_OPERATOR_EQUAL, TAG_OPERATOR_NOT_LIKE, TAG_OPERATOR_NOT_EQUAL, TAG_OPERATOR_EXISTS, TAG_OPERATOR_NOT_EXISTS]), 'default' => DB::getDefault('sysmaps_element_tag', 'operator')]
|
|
]]
|
|
]];
|
|
|
|
$data = array_intersect_key($selement, $api_input_rules['fields']);
|
|
if (!CApiInputValidator::validate($api_input_rules, $data, $path, $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hash of maps data for circular reference validation. Map id is used as key.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $cref_maps;
|
|
|
|
/**
|
|
* Validate maps for circular reference.
|
|
*
|
|
* @param array $maps Array of maps to be validated for circular reference.
|
|
*
|
|
* @throws APIException if input is invalid.
|
|
*/
|
|
protected function validateCircularReference(array $maps) {
|
|
foreach ($maps as $map) {
|
|
if (!array_key_exists('selements', $map) || !$map['selements']) {
|
|
continue;
|
|
}
|
|
$cref_mapids = array_key_exists('sysmapid', $map) ? [$map['sysmapid']] : [];
|
|
|
|
foreach ($map['selements'] as $selement) {
|
|
if (!$this->validateCircularReferenceRecursive($selement, $cref_mapids)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_s('Cannot add map element of the map "%1$s" due to circular reference.', $map['name'])
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recursive map element circular reference validation.
|
|
*
|
|
* @param array $selement Map selement data array.
|
|
* @param array $cref_mapids Array of map ids for current recursion step.
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function validateCircularReferenceRecursive(array $selement, &$cref_mapids) {
|
|
if ($selement['elementtype'] != SYSMAP_ELEMENT_TYPE_MAP) {
|
|
return true;
|
|
}
|
|
|
|
$sysmapid = $selement['elements'][0]['sysmapid'];
|
|
|
|
if ($sysmapid !== null && !array_key_exists($sysmapid, $this->cref_maps)) {
|
|
$db_maps = DB::select($this->tableName, [
|
|
'output' => ['name'],
|
|
'filter' => ['sysmapid' => $sysmapid]
|
|
]);
|
|
|
|
if ($db_maps) {
|
|
$db_map = $db_maps[0];
|
|
$db_map['selements'] = [];
|
|
$selements = DB::select('sysmaps_elements', [
|
|
'output' => ['elementid'],
|
|
'filter' => [
|
|
'sysmapid' => $sysmapid,
|
|
'elementtype' => SYSMAP_ELEMENT_TYPE_MAP
|
|
]
|
|
]);
|
|
|
|
foreach ($selements as $selement) {
|
|
$db_map['selements'][] = [
|
|
'elementtype' => SYSMAP_ELEMENT_TYPE_MAP,
|
|
'elements' => [
|
|
['sysmapid' => $selement['elementid']]
|
|
]
|
|
];
|
|
}
|
|
|
|
$this->cref_maps[$sysmapid] = $db_map;
|
|
unset($selements);
|
|
}
|
|
else {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, _('No permissions to referred object or it does not exist!'));
|
|
}
|
|
}
|
|
|
|
if (in_array($sysmapid, $cref_mapids)) {
|
|
$cref_mapids[] = $sysmapid;
|
|
return false;
|
|
}
|
|
|
|
// Find maps that reference the current element, and if one has selements, check all of them recursively.
|
|
if ($sysmapid !== null && array_key_exists('selements', $this->cref_maps[$sysmapid])
|
|
&& is_array($this->cref_maps[$sysmapid]['selements'])) {
|
|
$cref_mapids[] = $sysmapid;
|
|
|
|
foreach ($this->cref_maps[$sysmapid]['selements'] as $selement) {
|
|
if (!$this->validateCircularReferenceRecursive($selement, $cref_mapids)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
array_pop($cref_mapids);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Add map.
|
|
*
|
|
* @param array $maps
|
|
* @param string $maps['name']
|
|
* @param array $maps['width']
|
|
* @param int $maps['height']
|
|
* @param string $maps['backgroundid']
|
|
* @param string $maps['highlight']
|
|
* @param array $maps['label_type']
|
|
* @param int $maps['label_location']
|
|
* @param int $maps['grid_size'] size of one grid cell. 100 refers to 100x100 and so on.
|
|
* @param int $maps['grid_show'] does grid need to be shown. Constants: SYSMAP_GRID_SHOW_ON / SYSMAP_GRID_SHOW_OFF
|
|
* @param int $maps['grid_align'] do elements need to be aligned to the grid. Constants: SYSMAP_GRID_ALIGN_ON / SYSMAP_GRID_ALIGN_OFF
|
|
*
|
|
* @return array
|
|
*/
|
|
public function create($maps) {
|
|
$maps = zbx_toArray($maps);
|
|
|
|
$this->validateCreate($maps);
|
|
|
|
foreach ($maps as &$map) {
|
|
$map['userid'] = array_key_exists('userid', $map) ? $map['userid'] : self::$userData['userid'];
|
|
}
|
|
unset($map);
|
|
|
|
$sysmapids = DB::insert('sysmaps', $maps);
|
|
|
|
foreach ($maps as $key => &$map) {
|
|
$map['sysmapid'] = $sysmapids[$key];
|
|
}
|
|
unset($map);
|
|
|
|
$shared_users = [];
|
|
$shared_user_groups = [];
|
|
$urls = [];
|
|
$shapes = [];
|
|
$selements = [];
|
|
$links = [];
|
|
$api_shape_rules = ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'fields' => [
|
|
'type' => ['type' => API_INT32, 'flags' => API_REQUIRED, 'in' => implode(',', [SYSMAP_SHAPE_TYPE_RECTANGLE, SYSMAP_SHAPE_TYPE_ELLIPSE])],
|
|
'x' => ['type' => API_INT32],
|
|
'y' => ['type' => API_INT32],
|
|
'width' => ['type' => API_INT32],
|
|
'height' => ['type' => API_INT32],
|
|
'font' => ['type' => API_INT32, 'in' => '0:12'],
|
|
'font_size' => ['type' => API_INT32, 'in' => '1:250'],
|
|
'text_halign' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_LABEL_HALIGN_CENTER, SYSMAP_SHAPE_LABEL_HALIGN_LEFT, SYSMAP_SHAPE_LABEL_HALIGN_RIGHT])],
|
|
'text_valign' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_LABEL_VALIGN_MIDDLE, SYSMAP_SHAPE_LABEL_VALIGN_TOP, SYSMAP_SHAPE_LABEL_VALIGN_BOTTOM])],
|
|
'border_type' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_BORDER_TYPE_NONE, SYSMAP_SHAPE_BORDER_TYPE_SOLID, SYSMAP_SHAPE_BORDER_TYPE_DOTTED, SYSMAP_SHAPE_BORDER_TYPE_DASHED])],
|
|
'border_width' => ['type' => API_INT32, 'in' => '0:50'],
|
|
'border_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'border_color')],
|
|
'background_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'background_color')],
|
|
'font_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'font_color')],
|
|
'text' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'text')],
|
|
'zindex' => ['type' => API_INT32]
|
|
]];
|
|
$api_line_rules = ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'fields' => [
|
|
'x1' => ['type' => API_INT32],
|
|
'y1' => ['type' => API_INT32],
|
|
'x2' => ['type' => API_INT32],
|
|
'y2' => ['type' => API_INT32],
|
|
'line_type' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_BORDER_TYPE_NONE, SYSMAP_SHAPE_BORDER_TYPE_SOLID, SYSMAP_SHAPE_BORDER_TYPE_DOTTED, SYSMAP_SHAPE_BORDER_TYPE_DASHED])],
|
|
'line_width' => ['type' => API_INT32, 'in' => '0:50'],
|
|
'line_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'border_color')],
|
|
'zindex' => ['type' => API_INT32]
|
|
]];
|
|
$default_shape_width = DB::getDefault('sysmap_shape', 'width');
|
|
$default_shape_height = DB::getDefault('sysmap_shape', 'height');
|
|
|
|
foreach ($sysmapids as $key => $sysmapid) {
|
|
// Map user shares.
|
|
if (array_key_exists('users', $maps[$key])) {
|
|
foreach ($maps[$key]['users'] as $user) {
|
|
$shared_users[] = [
|
|
'sysmapid' => $sysmapid,
|
|
'userid' => $user['userid'],
|
|
'permission' => $user['permission']
|
|
];
|
|
}
|
|
}
|
|
|
|
// Map user group shares.
|
|
if (array_key_exists('userGroups', $maps[$key])) {
|
|
foreach ($maps[$key]['userGroups'] as $user_group) {
|
|
$shared_user_groups[] = [
|
|
'sysmapid' => $sysmapid,
|
|
'usrgrpid' => $user_group['usrgrpid'],
|
|
'permission' => $user_group['permission']
|
|
];
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('urls', $maps[$key])) {
|
|
foreach ($maps[$key]['urls'] as $url) {
|
|
$url['sysmapid'] = $sysmapid;
|
|
$urls[] = $url;
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('selements', $maps[$key])) {
|
|
foreach ($maps[$key]['selements'] as $snum => $selement) {
|
|
$maps[$key]['selements'][$snum]['sysmapid'] = $sysmapid;
|
|
}
|
|
|
|
$selements = array_merge($selements, $maps[$key]['selements']);
|
|
}
|
|
|
|
if (array_key_exists('shapes', $maps[$key])) {
|
|
$path = '/'.($key + 1).'/shape';
|
|
$api_shape_rules['fields']['x']['in'] = '0:'.$maps[$key]['width'];
|
|
$api_shape_rules['fields']['y']['in'] = '0:'.$maps[$key]['height'];
|
|
$api_shape_rules['fields']['width']['in'] = '1:'.$maps[$key]['width'];
|
|
$api_shape_rules['fields']['height']['in'] = '1:'.$maps[$key]['height'];
|
|
|
|
foreach ($maps[$key]['shapes'] as &$shape) {
|
|
$shape['width'] = array_key_exists('width', $shape) ? $shape['width'] : $default_shape_width;
|
|
$shape['height'] = array_key_exists('height', $shape) ? $shape['height'] : $default_shape_height;
|
|
}
|
|
unset($shape);
|
|
|
|
if (!CApiInputValidator::validate($api_shape_rules, $maps[$key]['shapes'], $path, $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
foreach ($maps[$key]['shapes'] as $snum => $shape) {
|
|
$maps[$key]['shapes'][$snum]['sysmapid'] = $sysmapid;
|
|
}
|
|
|
|
$shapes = array_merge($shapes, $maps[$key]['shapes']);
|
|
}
|
|
|
|
if (array_key_exists('lines', $maps[$key])) {
|
|
$path = '/'.($key + 1).'/line';
|
|
$api_line_rules['fields']['x1']['in'] = '0:'.$maps[$key]['width'];
|
|
$api_line_rules['fields']['y1']['in'] = '0:'.$maps[$key]['height'];
|
|
$api_line_rules['fields']['x2']['in'] = '0:'.$maps[$key]['width'];
|
|
$api_line_rules['fields']['y2']['in'] = '0:'.$maps[$key]['height'];
|
|
|
|
foreach ($maps[$key]['lines'] as &$line) {
|
|
$line['x2'] = array_key_exists('x2', $line) ? $line['x2'] : $default_shape_width;
|
|
$line['y2'] = array_key_exists('y2', $line) ? $line['y2'] : $default_shape_height;
|
|
}
|
|
unset($line);
|
|
|
|
if (!CApiInputValidator::validate($api_line_rules, $maps[$key]['lines'], $path, $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
foreach ($maps[$key]['lines'] as $line) {
|
|
$shape = CMapHelper::convertLineToShape($line);
|
|
$shape['sysmapid'] = $sysmapid;
|
|
$shapes[] = $shape;
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('links', $maps[$key])) {
|
|
foreach ($maps[$key]['links'] as $lnum => $link) {
|
|
$maps[$key]['links'][$lnum]['sysmapid'] = $sysmapid;
|
|
}
|
|
|
|
$links = array_merge($links, $maps[$key]['links']);
|
|
}
|
|
}
|
|
|
|
DB::insert('sysmap_user', $shared_users);
|
|
DB::insert('sysmap_usrgrp', $shared_user_groups);
|
|
DB::insert('sysmap_url', $urls);
|
|
|
|
if ($selements) {
|
|
$selementids = $this->createSelements($selements);
|
|
|
|
if ($links) {
|
|
$map_virt_selements = [];
|
|
foreach ($selementids['selementids'] as $key => $selementid) {
|
|
$map_virt_selements[$selements[$key]['selementid']] = $selementid;
|
|
}
|
|
|
|
foreach ($links as $key => $link) {
|
|
$links[$key]['selementid1'] = $map_virt_selements[$link['selementid1']];
|
|
$links[$key]['selementid2'] = $map_virt_selements[$link['selementid2']];
|
|
}
|
|
unset($map_virt_selements);
|
|
|
|
$linkids = $this->createLinks($links);
|
|
|
|
$link_triggers = [];
|
|
foreach ($linkids['linkids'] as $key => $linkId) {
|
|
if (!array_key_exists('linktriggers', $links[$key])) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($links[$key]['linktriggers'] as $link_trigger) {
|
|
$link_trigger['linkid'] = $linkId;
|
|
$link_triggers[] = $link_trigger;
|
|
}
|
|
}
|
|
|
|
if ($link_triggers) {
|
|
$this->createLinkTriggers($link_triggers);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($shapes) {
|
|
$this->createShapes($shapes);
|
|
}
|
|
|
|
$this->addAuditBulk(CAudit::ACTION_ADD, CAudit::RESOURCE_MAP, $maps);
|
|
|
|
return ['sysmapids' => $sysmapids];
|
|
}
|
|
|
|
/**
|
|
* Update map.
|
|
*
|
|
* @param array $maps multidimensional array with Hosts data
|
|
* @param string $maps['sysmapid']
|
|
* @param string $maps['name']
|
|
* @param array $maps['width']
|
|
* @param int $maps['height']
|
|
* @param string $maps['backgroundid']
|
|
* @param array $maps['label_type']
|
|
* @param int $maps['label_location']
|
|
* @param int $maps['grid_size'] size of one grid cell. 100 refers to 100x100 and so on.
|
|
* @param int $maps['grid_show'] does grid need to be shown. Constants: SYSMAP_GRID_SHOW_ON / SYSMAP_GRID_SHOW_OFF
|
|
* @param int $maps['grid_align'] do elements need to be aligned to the grid. Constants: SYSMAP_GRID_ALIGN_ON / SYSMAP_GRID_ALIGN_OFF
|
|
*
|
|
* @return array
|
|
*/
|
|
public function update(array $maps) {
|
|
$maps = zbx_toArray($maps);
|
|
$sysmapids = zbx_objectValues($maps, 'sysmapid');
|
|
|
|
$db_maps = $this->get([
|
|
'output' => API_OUTPUT_EXTEND,
|
|
'sysmapids' => zbx_objectValues($maps, 'sysmapid'),
|
|
'selectLinks' => API_OUTPUT_EXTEND,
|
|
'selectSelements' => API_OUTPUT_EXTEND,
|
|
'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', 'y1', 'x2', 'y2', 'line_type', 'line_width', 'line_color',
|
|
'zindex'
|
|
],
|
|
'selectUrls' => ['sysmapid', 'sysmapurlid', 'name', 'url', 'elementtype'],
|
|
'selectUsers' => ['sysmapuserid', 'sysmapid', 'userid', 'permission'],
|
|
'selectUserGroups' => ['sysmapusrgrpid', 'sysmapid', 'usrgrpid', 'permission'],
|
|
'editable' => true,
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$this->validateUpdate($maps, $db_maps);
|
|
|
|
$update_maps = [];
|
|
$url_ids_to_delete = [];
|
|
$urls_to_update = [];
|
|
$urls_to_add = [];
|
|
$selements_to_delete = [];
|
|
$selements_to_update = [];
|
|
$selements_to_add = [];
|
|
$shapes_to_delete = [];
|
|
$shapes_to_update = [];
|
|
$shapes_to_add = [];
|
|
$links_to_delete = [];
|
|
$links_to_update = [];
|
|
$links_to_add = [];
|
|
$shared_userids_to_delete = [];
|
|
$shared_users_to_update = [];
|
|
$shared_users_to_add = [];
|
|
$shared_user_groupids_to_delete = [];
|
|
$shared_user_groups_to_update = [];
|
|
$shared_user_groups_to_add = [];
|
|
$api_shape_rules = ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'fields' => [
|
|
'sysmap_shapeid' => ['type' => API_ID],
|
|
'type' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_TYPE_RECTANGLE, SYSMAP_SHAPE_TYPE_ELLIPSE])],
|
|
'x' => ['type' => API_INT32],
|
|
'y' => ['type' => API_INT32],
|
|
'width' => ['type' => API_INT32],
|
|
'height' => ['type' => API_INT32],
|
|
'font' => ['type' => API_INT32, 'in' => '0:12'],
|
|
'font_size' => ['type' => API_INT32, 'in' => '1:250'],
|
|
'text_halign' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_LABEL_HALIGN_CENTER, SYSMAP_SHAPE_LABEL_HALIGN_LEFT, SYSMAP_SHAPE_LABEL_HALIGN_RIGHT])],
|
|
'text_valign' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_LABEL_VALIGN_MIDDLE, SYSMAP_SHAPE_LABEL_VALIGN_TOP, SYSMAP_SHAPE_LABEL_VALIGN_BOTTOM])],
|
|
'border_type' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_BORDER_TYPE_NONE, SYSMAP_SHAPE_BORDER_TYPE_SOLID, SYSMAP_SHAPE_BORDER_TYPE_DOTTED, SYSMAP_SHAPE_BORDER_TYPE_DASHED])],
|
|
'border_width' => ['type' => API_INT32, 'in' => '0:50'],
|
|
'border_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'border_color')],
|
|
'background_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'background_color')],
|
|
'font_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'font_color')],
|
|
'text' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'text')],
|
|
'zindex' => ['type' => API_INT32]
|
|
]];
|
|
$api_line_rules = ['type' => API_OBJECTS, 'flags' => API_NORMALIZE, 'fields' => [
|
|
'sysmap_shapeid' => ['type' => API_ID],
|
|
'x1' => ['type' => API_INT32],
|
|
'y1' => ['type' => API_INT32],
|
|
'x2' => ['type' => API_INT32],
|
|
'y2' => ['type' => API_INT32],
|
|
'line_type' => ['type' => API_INT32, 'in' => implode(',', [SYSMAP_SHAPE_BORDER_TYPE_NONE, SYSMAP_SHAPE_BORDER_TYPE_SOLID, SYSMAP_SHAPE_BORDER_TYPE_DOTTED, SYSMAP_SHAPE_BORDER_TYPE_DASHED])],
|
|
'line_width' => ['type' => API_INT32, 'in' => '0:50'],
|
|
'line_color' => ['type' => API_STRING_UTF8, 'length' => DB::getFieldLength('sysmap_shape', 'border_color')],
|
|
'zindex' => ['type' => API_INT32]
|
|
]];
|
|
$default_shape_width = DB::getDefault('sysmap_shape', 'width');
|
|
$default_shape_height = DB::getDefault('sysmap_shape', 'height');
|
|
|
|
foreach ($maps as $index => $map) {
|
|
$update_maps[] = [
|
|
'values' => $map,
|
|
'where' => ['sysmapid' => $map['sysmapid']]
|
|
];
|
|
|
|
$db_map = $db_maps[$map['sysmapid']];
|
|
|
|
// Map user shares.
|
|
if (array_key_exists('users', $map)) {
|
|
$user_shares_diff = zbx_array_diff($map['users'], $db_map['users'], 'userid');
|
|
|
|
foreach ($user_shares_diff['both'] as $update_user_share) {
|
|
$shared_users_to_update[] = [
|
|
'values' => $update_user_share,
|
|
'where' => ['userid' => $update_user_share['userid'], 'sysmapid' => $map['sysmapid']]
|
|
];
|
|
}
|
|
|
|
foreach ($user_shares_diff['first'] as $new_shared_user) {
|
|
$new_shared_user['sysmapid'] = $map['sysmapid'];
|
|
$shared_users_to_add[] = $new_shared_user;
|
|
}
|
|
|
|
$shared_userids_to_delete = array_merge($shared_userids_to_delete,
|
|
zbx_objectValues($user_shares_diff['second'], 'sysmapuserid')
|
|
);
|
|
}
|
|
|
|
// Map user group shares.
|
|
if (array_key_exists('userGroups', $map)) {
|
|
$user_group_shares_diff = zbx_array_diff($map['userGroups'], $db_map['userGroups'],
|
|
'usrgrpid'
|
|
);
|
|
|
|
foreach ($user_group_shares_diff['both'] as $update_user_share) {
|
|
$shared_user_groups_to_update[] = [
|
|
'values' => $update_user_share,
|
|
'where' => ['usrgrpid' => $update_user_share['usrgrpid'], 'sysmapid' => $map['sysmapid']]
|
|
];
|
|
}
|
|
|
|
foreach ($user_group_shares_diff['first'] as $new_shared_user_group) {
|
|
$new_shared_user_group['sysmapid'] = $map['sysmapid'];
|
|
$shared_user_groups_to_add[] = $new_shared_user_group;
|
|
}
|
|
|
|
$shared_user_groupids_to_delete = array_merge($shared_user_groupids_to_delete,
|
|
zbx_objectValues($user_group_shares_diff['second'], 'sysmapusrgrpid')
|
|
);
|
|
}
|
|
|
|
// Urls.
|
|
if (array_key_exists('urls', $map)) {
|
|
$url_diff = zbx_array_diff($map['urls'], $db_map['urls'], 'name');
|
|
|
|
foreach ($url_diff['both'] as $updateUrl) {
|
|
$urls_to_update[] = [
|
|
'values' => $updateUrl,
|
|
'where' => ['name' => $updateUrl['name'], 'sysmapid' => $map['sysmapid']]
|
|
];
|
|
}
|
|
|
|
foreach ($url_diff['first'] as $new_url) {
|
|
$new_url['sysmapid'] = $map['sysmapid'];
|
|
$urls_to_add[] = $new_url;
|
|
}
|
|
|
|
$url_ids_to_delete = array_merge($url_ids_to_delete,
|
|
zbx_objectValues($url_diff['second'], 'sysmapurlid')
|
|
);
|
|
}
|
|
|
|
// Map elements.
|
|
if (array_key_exists('selements', $map)) {
|
|
$selement_diff = zbx_array_diff($map['selements'], $db_map['selements'], 'selementid');
|
|
|
|
// We need sysmapid for add operations.
|
|
foreach ($selement_diff['first'] as $new_selement) {
|
|
$new_selement['sysmapid'] = $map['sysmapid'];
|
|
$selements_to_add[] = $new_selement;
|
|
}
|
|
|
|
foreach ($selement_diff['both'] as &$selement) {
|
|
$selement['sysmapid'] = $map['sysmapid'];
|
|
}
|
|
unset($selement);
|
|
|
|
$selements_to_update = array_merge($selements_to_update, $selement_diff['both']);
|
|
$selements_to_delete = array_merge($selements_to_delete, $selement_diff['second']);
|
|
}
|
|
|
|
$map_width = array_key_exists('width', $map) ? $map['width'] : $db_map['width'];
|
|
$map_height = array_key_exists('height', $map) ? $map['height'] : $db_map['height'];
|
|
|
|
// Map shapes.
|
|
if (array_key_exists('shapes', $map)) {
|
|
$map['shapes'] = array_values($map['shapes']);
|
|
|
|
foreach ($map['shapes'] as &$shape) {
|
|
$shape['width'] = array_key_exists('width', $shape) ? $shape['width'] : $default_shape_width;
|
|
$shape['height'] = array_key_exists('height', $shape) ? $shape['height'] : $default_shape_height;
|
|
}
|
|
unset($shape);
|
|
|
|
$shape_diff = zbx_array_diff($map['shapes'], $db_map['shapes'], 'sysmap_shapeid');
|
|
|
|
$path = '/'.($index + 1).'/shape';
|
|
foreach ($shape_diff['first'] as $new_shape) {
|
|
if (array_key_exists('sysmap_shapeid', $new_shape)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_('No permissions to referred object or it does not exist!')
|
|
);
|
|
}
|
|
}
|
|
|
|
unset($api_shape_rules['fields']['sysmap_shapeid']);
|
|
$api_shape_rules['fields']['type']['flags'] = API_REQUIRED;
|
|
$api_shape_rules['fields']['x']['in'] = '0:'.$map_width;
|
|
$api_shape_rules['fields']['y']['in'] = '0:'.$map_height;
|
|
$api_shape_rules['fields']['width']['in'] = '1:'.$map_width;
|
|
$api_shape_rules['fields']['height']['in'] = '1:'.$map_height;
|
|
|
|
if (!CApiInputValidator::validate($api_shape_rules, $shape_diff['first'], $path, $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
$api_shape_rules['fields']['sysmap_shapeid'] = ['type' => API_ID, 'flags' => API_REQUIRED];
|
|
$api_shape_rules['fields']['type']['flags'] = 0;
|
|
if (!CApiInputValidator::validate($api_shape_rules, $shape_diff['both'], $path, $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
$shapes_to_update = array_merge($shapes_to_update, $shape_diff['both']);
|
|
$shapes_to_delete = array_merge($shapes_to_delete, $shape_diff['second']);
|
|
|
|
// We need sysmapid for add operations.
|
|
foreach ($shape_diff['first'] as $new_shape) {
|
|
$new_shape['sysmapid'] = $map['sysmapid'];
|
|
$shapes_to_add[] = $new_shape;
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('lines', $map)) {
|
|
$map['lines'] = array_values($map['lines']);
|
|
$shapes = [];
|
|
|
|
$api_line_rules['fields']['x1']['in'] = '0:'.$map_width;
|
|
$api_line_rules['fields']['y1']['in'] = '0:'.$map_height;
|
|
$api_line_rules['fields']['x2']['in'] = '0:'.$map_width;
|
|
$api_line_rules['fields']['y2']['in'] = '0:'.$map_height;
|
|
|
|
$path = '/'.($index + 1).'/line';
|
|
|
|
foreach ($map['lines'] as &$line) {
|
|
$line['x2'] = array_key_exists('x2', $line) ? $line['x2'] : $default_shape_width;
|
|
$line['y2'] = array_key_exists('y2', $line) ? $line['y2'] : $default_shape_height;
|
|
}
|
|
unset($line);
|
|
|
|
if (!CApiInputValidator::validate($api_line_rules, $map['lines'], $path, $error)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
|
|
}
|
|
|
|
foreach ($map['lines'] as $line) {
|
|
$shapes[] = CMapHelper::convertLineToShape($line);
|
|
}
|
|
|
|
$line_diff = zbx_array_diff($shapes, $db_map['lines'], 'sysmap_shapeid');
|
|
|
|
foreach ($line_diff['first'] as $new_line) {
|
|
if (array_key_exists('sysmap_shapeid', $new_line)) {
|
|
self::exception(ZBX_API_ERROR_PARAMETERS,
|
|
_('No permissions to referred object or it does not exist!')
|
|
);
|
|
}
|
|
}
|
|
|
|
$shapes_to_update = array_merge($shapes_to_update, $line_diff['both']);
|
|
$shapes_to_delete = array_merge($shapes_to_delete, $line_diff['second']);
|
|
|
|
// We need sysmapid for add operations.
|
|
foreach ($line_diff['first'] as $new_shape) {
|
|
$new_shape['sysmapid'] = $map['sysmapid'];
|
|
$shapes_to_add[] = $new_shape;
|
|
}
|
|
}
|
|
|
|
// Links.
|
|
if (array_key_exists('links', $map)) {
|
|
$link_diff = zbx_array_diff($map['links'], $db_map['links'], 'linkid');
|
|
|
|
// We need sysmapId for add operations.
|
|
foreach ($link_diff['first'] as $newLink) {
|
|
$newLink['sysmapid'] = $map['sysmapid'];
|
|
|
|
$links_to_add[] = $newLink;
|
|
}
|
|
|
|
$links_to_update = array_merge($links_to_update, $link_diff['both']);
|
|
$links_to_delete = array_merge($links_to_delete, $link_diff['second']);
|
|
}
|
|
}
|
|
|
|
DB::update('sysmaps', $update_maps);
|
|
|
|
// User shares.
|
|
DB::insert('sysmap_user', $shared_users_to_add);
|
|
DB::update('sysmap_user', $shared_users_to_update);
|
|
|
|
if ($shared_userids_to_delete) {
|
|
DB::delete('sysmap_user', ['sysmapuserid' => $shared_userids_to_delete]);
|
|
}
|
|
|
|
// User group shares.
|
|
DB::insert('sysmap_usrgrp', $shared_user_groups_to_add);
|
|
DB::update('sysmap_usrgrp', $shared_user_groups_to_update);
|
|
|
|
if ($shared_user_groupids_to_delete) {
|
|
DB::delete('sysmap_usrgrp', ['sysmapusrgrpid' => $shared_user_groupids_to_delete]);
|
|
}
|
|
|
|
// Urls.
|
|
DB::insert('sysmap_url', $urls_to_add);
|
|
DB::update('sysmap_url', $urls_to_update);
|
|
|
|
if ($url_ids_to_delete) {
|
|
DB::delete('sysmap_url', ['sysmapurlid' => $url_ids_to_delete]);
|
|
}
|
|
|
|
// Selements.
|
|
$new_selementids = ['selementids' => []];
|
|
if ($selements_to_add) {
|
|
$new_selementids = $this->createSelements($selements_to_add);
|
|
}
|
|
|
|
if ($selements_to_update) {
|
|
$this->updateSelements($selements_to_update);
|
|
}
|
|
|
|
if ($selements_to_delete) {
|
|
$this->deleteSelements($selements_to_delete);
|
|
}
|
|
|
|
if ($shapes_to_add) {
|
|
$this->createShapes($shapes_to_add);
|
|
}
|
|
|
|
if ($shapes_to_update) {
|
|
$this->updateShapes($shapes_to_update);
|
|
}
|
|
|
|
if ($shapes_to_delete) {
|
|
$this->deleteShapes($shapes_to_delete);
|
|
}
|
|
|
|
// Links.
|
|
if ($links_to_add || $links_to_update) {
|
|
$selements_names = [];
|
|
foreach ($new_selementids['selementids'] as $key => $selementId) {
|
|
$selements_names[$selements_to_add[$key]['selementid']] = $selementId;
|
|
}
|
|
|
|
foreach ($selements_to_update as $selement) {
|
|
$selements_names[$selement['selementid']] = $selement['selementid'];
|
|
}
|
|
|
|
foreach ($links_to_add as $key => $link) {
|
|
if (array_key_exists($link['selementid1'], $selements_names)) {
|
|
$links_to_add[$key]['selementid1'] = $selements_names[$link['selementid1']];
|
|
}
|
|
if (array_key_exists($link['selementid2'], $selements_names)) {
|
|
$links_to_add[$key]['selementid2'] = $selements_names[$link['selementid2']];
|
|
}
|
|
}
|
|
|
|
foreach ($links_to_update as $key => $link) {
|
|
if (array_key_exists($link['selementid1'], $selements_names)) {
|
|
$links_to_update[$key]['selementid1'] = $selements_names[$link['selementid1']];
|
|
}
|
|
if (array_key_exists($link['selementid2'], $selements_names)) {
|
|
$links_to_update[$key]['selementid2'] = $selements_names[$link['selementid2']];
|
|
}
|
|
}
|
|
|
|
unset($selements_names);
|
|
}
|
|
|
|
$new_linkids = ['linkids' => []];
|
|
$update_linkids = ['linkids' => []];
|
|
|
|
if ($links_to_add) {
|
|
$new_linkids = $this->createLinks($links_to_add);
|
|
}
|
|
|
|
if ($links_to_update) {
|
|
$update_linkids = $this->updateLinks($links_to_update);
|
|
}
|
|
|
|
if ($links_to_delete) {
|
|
$this->deleteLinks($links_to_delete);
|
|
}
|
|
|
|
// Link triggers.
|
|
$link_triggers_to_delete = [];
|
|
$link_triggers_to_update = [];
|
|
$link_triggers_to_add = [];
|
|
|
|
foreach ($new_linkids['linkids'] as $key => $linkid) {
|
|
if (!array_key_exists('linktriggers', $links_to_add[$key])) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($links_to_add[$key]['linktriggers'] as $link_trigger) {
|
|
$link_trigger['linkid'] = $linkid;
|
|
$link_triggers_to_add[] = $link_trigger;
|
|
}
|
|
}
|
|
|
|
$db_links = [];
|
|
|
|
$link_trigger_resource = DBselect(
|
|
'SELECT slt.* FROM sysmaps_link_triggers slt WHERE '.dbConditionInt('slt.linkid', $update_linkids['linkids'])
|
|
);
|
|
while ($db_link_trigger = DBfetch($link_trigger_resource)) {
|
|
zbx_subarray_push($db_links, $db_link_trigger['linkid'], $db_link_trigger);
|
|
}
|
|
|
|
foreach ($update_linkids['linkids'] as $key => $linkid) {
|
|
if (!array_key_exists('linktriggers', $links_to_update[$key])) {
|
|
continue;
|
|
}
|
|
|
|
$db_link_triggers = array_key_exists($linkid, $db_links) ? $db_links[$linkid] : [];
|
|
$db_link_triggers_diff = zbx_array_diff($links_to_update[$key]['linktriggers'],
|
|
$db_link_triggers, 'linktriggerid'
|
|
);
|
|
|
|
foreach ($db_link_triggers_diff['first'] as $new_link_trigger) {
|
|
$new_link_trigger['linkid'] = $linkid;
|
|
$link_triggers_to_add[] = $new_link_trigger;
|
|
}
|
|
|
|
$link_triggers_to_update = array_merge($link_triggers_to_update, $db_link_triggers_diff['both']);
|
|
$link_triggers_to_delete = array_merge($link_triggers_to_delete, $db_link_triggers_diff['second']);
|
|
}
|
|
|
|
if ($link_triggers_to_delete) {
|
|
$this->deleteLinkTriggers($link_triggers_to_delete);
|
|
}
|
|
|
|
if ($link_triggers_to_add) {
|
|
$this->createLinkTriggers($link_triggers_to_add);
|
|
}
|
|
|
|
if ($link_triggers_to_update) {
|
|
$this->updateLinkTriggers($link_triggers_to_update);
|
|
}
|
|
|
|
$this->addAuditBulk(CAudit::ACTION_UPDATE, CAudit::RESOURCE_MAP, $maps, $db_maps);
|
|
|
|
return ['sysmapids' => $sysmapids];
|
|
}
|
|
|
|
/**
|
|
* Delete Map.
|
|
*
|
|
* @param array $sysmapids
|
|
*
|
|
* @return array
|
|
*/
|
|
public function delete(array $sysmapids) {
|
|
$this->validateDelete($sysmapids, $db_maps);
|
|
|
|
DB::delete('sysmaps_elements', [
|
|
'elementid' => $sysmapids,
|
|
'elementtype' => SYSMAP_ELEMENT_TYPE_MAP
|
|
]);
|
|
DB::delete('profiles', [
|
|
'idx' => 'web.maps.sysmapid',
|
|
'value_id' => $sysmapids
|
|
]);
|
|
DB::delete('profiles', [
|
|
'idx' => 'web.favorite.sysmapids',
|
|
'source' => 'sysmapid',
|
|
'value_id' => $sysmapids
|
|
]);
|
|
DB::delete('sysmaps', ['sysmapid' => $sysmapids]);
|
|
|
|
$this->addAuditBulk(CAudit::ACTION_DELETE, CAudit::RESOURCE_MAP, $db_maps);
|
|
|
|
return ['sysmapids' => $sysmapids];
|
|
}
|
|
|
|
protected function addRelatedObjects(array $options, array $result) {
|
|
$result = parent::addRelatedObjects($options, $result);
|
|
|
|
$sysmapIds = array_keys($result);
|
|
|
|
// adding elements
|
|
if ($options['selectSelements'] !== null && $options['selectSelements'] != API_OUTPUT_COUNT) {
|
|
$selements = API::getApiService()->select('sysmaps_elements', [
|
|
'output' => $this->outputExtend($options['selectSelements'], ['selementid', 'sysmapid', 'elementtype',
|
|
'elementid', 'elementsubtype'
|
|
]),
|
|
'filter' => ['sysmapid' => $sysmapIds],
|
|
'preservekeys' => true
|
|
]);
|
|
$relation_map = $this->createRelationMap($selements, 'sysmapid', 'selementid');
|
|
|
|
if ($this->outputIsRequested('elements', $options['selectSelements']) && $selements) {
|
|
foreach ($selements as &$selement) {
|
|
$selement['elements'] = [];
|
|
}
|
|
unset($selement);
|
|
|
|
$selement_triggers = DBselect(
|
|
'SELECT st.selementid,st.triggerid,st.selement_triggerid'.
|
|
' FROM sysmap_element_trigger st,triggers tr'.
|
|
' WHERE '.dbConditionInt('st.selementid', array_keys($selements)).
|
|
' AND st.triggerid=tr.triggerid'.
|
|
' ORDER BY tr.priority DESC,st.selement_triggerid'
|
|
);
|
|
while ($selement_trigger = DBfetch($selement_triggers)) {
|
|
$selements[$selement_trigger['selementid']]['elements'][] = [
|
|
'triggerid' => $selement_trigger['triggerid']
|
|
];
|
|
if ($selements[$selement_trigger['selementid']]['elementid'] == 0) {
|
|
$selements[$selement_trigger['selementid']]['elementid'] = $selement_trigger['triggerid'];
|
|
}
|
|
}
|
|
|
|
$single_element_types = [SYSMAP_ELEMENT_TYPE_HOST, SYSMAP_ELEMENT_TYPE_MAP,
|
|
SYSMAP_ELEMENT_TYPE_HOST_GROUP
|
|
];
|
|
|
|
foreach ($selements as &$selement) {
|
|
if (in_array($selement['elementtype'], $single_element_types)) {
|
|
switch ($selement['elementtype']) {
|
|
case SYSMAP_ELEMENT_TYPE_HOST_GROUP:
|
|
$field = 'groupid';
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_HOST:
|
|
$field = 'hostid';
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_MAP:
|
|
$field = 'sysmapid';
|
|
break;
|
|
}
|
|
$selement['elements'][] = [$field => $selement['elementid']];
|
|
}
|
|
}
|
|
unset($selement);
|
|
}
|
|
|
|
// add selement URLs
|
|
if ($this->outputIsRequested('urls', $options['selectSelements'])) {
|
|
foreach ($selements as &$selement) {
|
|
$selement['urls'] = [];
|
|
}
|
|
unset($selement);
|
|
|
|
if (!is_null($options['expandUrls'])) {
|
|
$dbMapUrls = DBselect(
|
|
'SELECT su.sysmapurlid,su.sysmapid,su.name,su.url,su.elementtype'.
|
|
' FROM sysmap_url su'.
|
|
' WHERE '.dbConditionInt('su.sysmapid', $sysmapIds)
|
|
);
|
|
while ($mapUrl = DBfetch($dbMapUrls)) {
|
|
foreach ($selements as $snum => $selement) {
|
|
if (bccomp($selement['sysmapid'], $mapUrl['sysmapid']) == 0
|
|
&& (($selement['elementtype'] == $mapUrl['elementtype']
|
|
&& $selement['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP
|
|
)
|
|
|| ($selement['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS
|
|
&& $mapUrl['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST)
|
|
)) {
|
|
$selements[$snum]['urls'][] = $mapUrl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$dbSelementUrls = DBselect(
|
|
'SELECT seu.sysmapelementurlid,seu.selementid,seu.name,seu.url'.
|
|
' FROM sysmap_element_url seu'.
|
|
' WHERE '.dbConditionInt('seu.selementid', array_keys($selements))
|
|
);
|
|
while ($selementUrl = DBfetch($dbSelementUrls)) {
|
|
$selements[$selementUrl['selementid']]['urls'][] = $selementUrl;
|
|
}
|
|
|
|
if (!is_null($options['expandUrls'])) {
|
|
$resolve_opt = ['resolve_element_urls' => true];
|
|
$selements = CMacrosResolverHelper::resolveMacrosInMapElements($selements, $resolve_opt);
|
|
}
|
|
}
|
|
|
|
if ($this->outputIsRequested('tags', $options['selectSelements']) && $selements) {
|
|
$db_tags = DBselect(
|
|
'SELECT selementid,tag,value,operator'.
|
|
' FROM sysmaps_element_tag'.
|
|
' WHERE '.dbConditionInt('selementid', array_keys($selements))
|
|
);
|
|
|
|
array_walk($selements, function (&$selement) {
|
|
$selement['tags'] = [];
|
|
});
|
|
|
|
while ($db_tag = DBfetch($db_tags)) {
|
|
$selements[$db_tag['selementid']]['tags'][] = [
|
|
'tag' => $db_tag['tag'],
|
|
'value' => $db_tag['value'],
|
|
'operator' => $db_tag['operator']
|
|
];
|
|
}
|
|
}
|
|
|
|
if ($this->outputIsRequested('permission', $options['selectSelements']) && $selements) {
|
|
if ($options['editable']) {
|
|
foreach ($selements as &$selement) {
|
|
$selement['permission'] = PERM_READ_WRITE;
|
|
}
|
|
unset($selement);
|
|
}
|
|
elseif (self::$userData['type'] == USER_TYPE_SUPER_ADMIN) {
|
|
foreach ($selements as &$selement) {
|
|
$selement['permission'] = PERM_READ;
|
|
}
|
|
unset($selement);
|
|
}
|
|
else {
|
|
$ids = [
|
|
SYSMAP_ELEMENT_TYPE_HOST_GROUP => [],
|
|
SYSMAP_ELEMENT_TYPE_HOST => [],
|
|
SYSMAP_ELEMENT_TYPE_TRIGGER => [],
|
|
SYSMAP_ELEMENT_TYPE_MAP => []
|
|
];
|
|
$trigger_selementids = [];
|
|
|
|
foreach ($selements as &$selement) {
|
|
switch ($selement['elementtype']) {
|
|
case SYSMAP_ELEMENT_TYPE_HOST_GROUP:
|
|
case SYSMAP_ELEMENT_TYPE_HOST:
|
|
case SYSMAP_ELEMENT_TYPE_MAP:
|
|
$ids[$selement['elementtype']][$selement['elementid']][] = $selement['selementid'];
|
|
$selement['permission'] = PERM_NONE;
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_TRIGGER:
|
|
$trigger_selementids[$selement['selementid']] = true;
|
|
$selement['permission'] = PERM_NONE;
|
|
break;
|
|
|
|
case SYSMAP_ELEMENT_TYPE_IMAGE:
|
|
$selement['permission'] = PERM_READ;
|
|
break;
|
|
}
|
|
}
|
|
unset($selement);
|
|
|
|
$db[SYSMAP_ELEMENT_TYPE_HOST_GROUP] = $ids[SYSMAP_ELEMENT_TYPE_HOST_GROUP]
|
|
? API::HostGroup()->get([
|
|
'output' => [],
|
|
'groupids' => array_keys($ids[SYSMAP_ELEMENT_TYPE_HOST_GROUP]),
|
|
'preservekeys' => true
|
|
])
|
|
: [];
|
|
|
|
$db[SYSMAP_ELEMENT_TYPE_HOST] = $ids[SYSMAP_ELEMENT_TYPE_HOST]
|
|
? API::Host()->get([
|
|
'output' => [],
|
|
'hostids' => array_keys($ids[SYSMAP_ELEMENT_TYPE_HOST]),
|
|
'preservekeys' => true
|
|
])
|
|
: [];
|
|
|
|
$db[SYSMAP_ELEMENT_TYPE_MAP] = $ids[SYSMAP_ELEMENT_TYPE_MAP]
|
|
? API::Map()->get([
|
|
'output' => [],
|
|
'sysmapids' => array_keys($ids[SYSMAP_ELEMENT_TYPE_MAP]),
|
|
'preservekeys' => true
|
|
])
|
|
: [];
|
|
|
|
if ($trigger_selementids) {
|
|
$db_selement_triggers = DBselect(
|
|
'SELECT st.selementid,st.triggerid'.
|
|
' FROM sysmap_element_trigger st'.
|
|
' WHERE '.dbConditionInt('st.selementid', array_keys($trigger_selementids))
|
|
);
|
|
|
|
while ($db_selement_trigger = DBfetch($db_selement_triggers)) {
|
|
$ids[SYSMAP_ELEMENT_TYPE_TRIGGER][$db_selement_trigger['triggerid']][] =
|
|
$db_selement_trigger['selementid'];
|
|
}
|
|
}
|
|
|
|
$db[SYSMAP_ELEMENT_TYPE_TRIGGER] = $ids[SYSMAP_ELEMENT_TYPE_TRIGGER]
|
|
? API::Trigger()->get([
|
|
'output' => [],
|
|
'triggerids' => array_keys($ids[SYSMAP_ELEMENT_TYPE_TRIGGER]),
|
|
'preservekeys' => true
|
|
])
|
|
: [];
|
|
|
|
foreach ($ids as $elementtype => $elementids) {
|
|
foreach ($elementids as $elementid => $selementids) {
|
|
if (array_key_exists($elementid, $db[$elementtype])) {
|
|
foreach ($selementids as $selementid) {
|
|
$selements[$selementid]['permission'] = PERM_READ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($selements as &$selement) {
|
|
unset($selement['elementid']);
|
|
}
|
|
unset($selement);
|
|
|
|
$selements = $this->unsetExtraFields($selements,
|
|
['sysmapid', 'selementid', 'elementtype', 'elementsubtype'],
|
|
$options['selectSelements']
|
|
);
|
|
$result = $relation_map->mapMany($result, $selements, 'selements');
|
|
}
|
|
|
|
$shape_types = [];
|
|
if ($options['selectShapes'] !== null && $options['selectShapes'] != API_OUTPUT_COUNT) {
|
|
$shape_types = [SYSMAP_SHAPE_TYPE_RECTANGLE, SYSMAP_SHAPE_TYPE_ELLIPSE];
|
|
}
|
|
|
|
if ($options['selectLines'] !== null && $options['selectLines'] != API_OUTPUT_COUNT) {
|
|
$shape_types[] = SYSMAP_SHAPE_TYPE_LINE;
|
|
}
|
|
|
|
// Adding shapes.
|
|
if ($shape_types) {
|
|
$fields = API_OUTPUT_EXTEND;
|
|
|
|
if ($options['selectShapes'] != API_OUTPUT_EXTEND && $options['selectLines'] != API_OUTPUT_EXTEND) {
|
|
$fields = ['sysmap_shapeid', 'sysmapid', 'type'];
|
|
$mapping = [
|
|
'x1' => 'x',
|
|
'y1' => 'y',
|
|
'x2' => 'width',
|
|
'y2' => 'height',
|
|
'line_type' => 'border_type',
|
|
'line_width' => 'border_width',
|
|
'line_color' => 'border_color'
|
|
];
|
|
|
|
if (is_array($options['selectLines'])) {
|
|
foreach ($mapping as $source_field => $target_field) {
|
|
if (in_array($source_field, $options['selectLines'])) {
|
|
$fields[] = $target_field;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_array($options['selectShapes'])) {
|
|
$fields = array_merge($fields, $options['selectShapes']);
|
|
}
|
|
}
|
|
|
|
$db_shapes = API::getApiService()->select('sysmap_shape', [
|
|
'output' => $fields,
|
|
'filter' => ['sysmapid' => $sysmapIds, 'type' => $shape_types],
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$shapes = [];
|
|
$lines = [];
|
|
foreach ($db_shapes as $key => $db_shape) {
|
|
if ($db_shape['type'] == SYSMAP_SHAPE_TYPE_LINE) {
|
|
$lines[$key] = CMapHelper::convertShapeToLine($db_shape);
|
|
}
|
|
else {
|
|
$shapes[$key] = $db_shape;
|
|
}
|
|
}
|
|
|
|
$relation_map = $this->createRelationMap($db_shapes, 'sysmapid', 'sysmap_shapeid');
|
|
|
|
if ($options['selectShapes'] !== null && $options['selectShapes'] != API_OUTPUT_COUNT) {
|
|
$shapes = $this->unsetExtraFields($shapes, ['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'
|
|
], $options['selectShapes']);
|
|
$shapes = $this->unsetExtraFields($shapes, ['sysmapid'], null);
|
|
|
|
$result = $relation_map->mapMany($result, $shapes, 'shapes');
|
|
}
|
|
|
|
if ($options['selectLines'] !== null && $options['selectLines'] != API_OUTPUT_COUNT) {
|
|
$lines = $this->unsetExtraFields($lines, ['sysmap_shapeid', 'x1', 'x2', 'y1', 'y2', 'line_type',
|
|
'line_width', 'line_color', 'zindex'
|
|
], $options['selectLines']);
|
|
$lines = $this->unsetExtraFields($lines, ['sysmapid', 'type'], null);
|
|
|
|
$result = $relation_map->mapMany($result, $lines, 'lines');
|
|
}
|
|
}
|
|
|
|
// adding icon maps
|
|
if ($options['selectIconMap'] !== null && $options['selectIconMap'] != API_OUTPUT_COUNT) {
|
|
$iconMaps = API::getApiService()->select($this->tableName(), [
|
|
'output' => ['sysmapid', 'iconmapid'],
|
|
'filter' => ['sysmapid' => $sysmapIds]
|
|
]);
|
|
|
|
$relation_map = $this->createRelationMap($iconMaps, 'sysmapid', 'iconmapid');
|
|
|
|
$iconMaps = API::IconMap()->get([
|
|
'output' => $this->outputExtend($options['selectIconMap'], ['iconmapid']),
|
|
'iconmapids' => zbx_objectValues($iconMaps, 'iconmapid'),
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$iconMaps = $this->unsetExtraFields($iconMaps, ['iconmapid'], $options['selectIconMap']);
|
|
|
|
$result = $relation_map->mapOne($result, $iconMaps, 'iconmap');
|
|
}
|
|
|
|
// adding links
|
|
if ($options['selectLinks'] !== null && $options['selectLinks'] != API_OUTPUT_COUNT) {
|
|
$links = API::getApiService()->select('sysmaps_links', [
|
|
'output' => $this->outputExtend($options['selectLinks'], ['sysmapid', 'linkid']),
|
|
'filter' => ['sysmapid' => $sysmapIds],
|
|
'preservekeys' => true
|
|
]);
|
|
$relation_map = $this->createRelationMap($links, 'sysmapid', 'linkid');
|
|
|
|
// add link triggers
|
|
if ($this->outputIsRequested('linktriggers', $options['selectLinks'])) {
|
|
$linkTriggers = DBFetchArrayAssoc(DBselect(
|
|
'SELECT DISTINCT slt.*'.
|
|
' FROM sysmaps_link_triggers slt'.
|
|
' WHERE '.dbConditionInt('slt.linkid', $relation_map->getRelatedIds())
|
|
), 'linktriggerid');
|
|
$linkTriggerRelationMap = $this->createRelationMap($linkTriggers, 'linkid', 'linktriggerid');
|
|
$links = $linkTriggerRelationMap->mapMany($links, $linkTriggers, 'linktriggers');
|
|
}
|
|
|
|
if ($this->outputIsRequested('permission', $options['selectLinks']) && $links) {
|
|
if ($options['editable']) {
|
|
foreach ($links as &$link) {
|
|
$link['permission'] = PERM_READ_WRITE;
|
|
}
|
|
unset($link);
|
|
}
|
|
elseif (self::$userData['type'] == USER_TYPE_SUPER_ADMIN) {
|
|
foreach ($links as &$link) {
|
|
$link['permission'] = PERM_READ;
|
|
}
|
|
unset($link);
|
|
}
|
|
else {
|
|
$db_link_triggers = DBselect(
|
|
'SELECT slt.linkid,slt.triggerid'.
|
|
' FROM sysmaps_link_triggers slt'.
|
|
' WHERE '.dbConditionInt('slt.linkid', array_keys($links))
|
|
);
|
|
|
|
$triggerids = [];
|
|
$has_triggers = [];
|
|
|
|
while ($db_link_trigger = DBfetch($db_link_triggers)) {
|
|
$triggerids[$db_link_trigger['triggerid']][] = $db_link_trigger['linkid'];
|
|
$has_triggers[$db_link_trigger['linkid']] = true;
|
|
}
|
|
|
|
foreach ($links as &$link) {
|
|
$link['permission'] = array_key_exists($link['linkid'], $has_triggers) ? PERM_NONE : PERM_READ;
|
|
}
|
|
unset($link);
|
|
|
|
$db_triggers = $triggerids
|
|
? API::Trigger()->get([
|
|
'output' => [],
|
|
'triggerids' => array_keys($triggerids),
|
|
'preservekeys' => true
|
|
])
|
|
: [];
|
|
|
|
foreach ($triggerids as $triggerid => $linkids) {
|
|
if (array_key_exists($triggerid, $db_triggers)) {
|
|
foreach ($linkids as $linkid) {
|
|
$links[$linkid]['permission'] = PERM_READ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$links = $this->unsetExtraFields($links, ['sysmapid', 'linkid'], $options['selectLinks']);
|
|
$result = $relation_map->mapMany($result, $links, 'links');
|
|
}
|
|
|
|
// adding urls
|
|
if ($options['selectUrls'] !== null && $options['selectUrls'] != API_OUTPUT_COUNT) {
|
|
$links = API::getApiService()->select('sysmap_url', [
|
|
'output' => $this->outputExtend($options['selectUrls'], ['sysmapid', 'sysmapurlid']),
|
|
'filter' => ['sysmapid' => $sysmapIds],
|
|
'preservekeys' => true
|
|
]);
|
|
$relation_map = $this->createRelationMap($links, 'sysmapid', 'sysmapurlid');
|
|
|
|
$links = $this->unsetExtraFields($links, ['sysmapid', 'sysmapurlid'], $options['selectUrls']);
|
|
$result = $relation_map->mapMany($result, $links, 'urls');
|
|
}
|
|
|
|
// Adding user shares.
|
|
if ($options['selectUsers'] !== null && $options['selectUsers'] != API_OUTPUT_COUNT) {
|
|
$userids = [];
|
|
$relation_map = $this->createRelationMap($result, 'sysmapid', 'userid', 'sysmap_user');
|
|
$related_ids = $relation_map->getRelatedIds();
|
|
|
|
if ($related_ids) {
|
|
// Get all allowed users.
|
|
$users = API::User()->get([
|
|
'output' => ['userid'],
|
|
'userids' => $related_ids,
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$userids = zbx_objectValues($users, 'userid');
|
|
}
|
|
|
|
if ($userids) {
|
|
$users = API::getApiService()->select('sysmap_user', [
|
|
'output' => $this->outputExtend($options['selectUsers'], ['sysmapid', 'userid']),
|
|
'filter' => ['sysmapid' => $sysmapIds, 'userid' => $userids],
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$relation_map = $this->createRelationMap($users, 'sysmapid', 'sysmapuserid');
|
|
|
|
$users = $this->unsetExtraFields($users, ['sysmapuserid', 'userid', 'permission'],
|
|
$options['selectUsers']
|
|
);
|
|
|
|
foreach ($users as &$user) {
|
|
unset($user['sysmapid']);
|
|
}
|
|
unset($user);
|
|
|
|
$result = $relation_map->mapMany($result, $users, 'users');
|
|
}
|
|
else {
|
|
foreach ($result as &$row) {
|
|
$row['users'] = [];
|
|
}
|
|
unset($row);
|
|
}
|
|
}
|
|
|
|
// Adding user group shares.
|
|
if ($options['selectUserGroups'] !== null && $options['selectUserGroups'] != API_OUTPUT_COUNT) {
|
|
$groupids = [];
|
|
$relation_map = $this->createRelationMap($result, 'sysmapid', 'usrgrpid', 'sysmap_usrgrp');
|
|
$related_ids = $relation_map->getRelatedIds();
|
|
|
|
if ($related_ids) {
|
|
// Get all allowed groups.
|
|
$groups = API::UserGroup()->get([
|
|
'output' => ['usrgrpid'],
|
|
'usrgrpids' => $related_ids,
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$groupids = zbx_objectValues($groups, 'usrgrpid');
|
|
}
|
|
|
|
if ($groupids) {
|
|
$user_groups = API::getApiService()->select('sysmap_usrgrp', [
|
|
'output' => $this->outputExtend($options['selectUserGroups'], ['sysmapid', 'usrgrpid']),
|
|
'filter' => ['sysmapid' => $sysmapIds, 'usrgrpid' => $groupids],
|
|
'preservekeys' => true
|
|
]);
|
|
|
|
$relation_map = $this->createRelationMap($user_groups, 'sysmapid', 'sysmapusrgrpid');
|
|
|
|
$user_groups = $this->unsetExtraFields($user_groups, ['sysmapusrgrpid', 'usrgrpid', 'permission'],
|
|
$options['selectUserGroups']
|
|
);
|
|
|
|
foreach ($user_groups as &$user_group) {
|
|
unset($user_group['sysmapid']);
|
|
}
|
|
unset($user_group);
|
|
|
|
$result = $relation_map->mapMany($result, $user_groups, 'userGroups');
|
|
}
|
|
else {
|
|
foreach ($result as &$row) {
|
|
$row['userGroups'] = [];
|
|
}
|
|
unset($row);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|