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.

710 lines
23 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 value maps.
*/
class CValueMap extends CApiService {
public const ACCESS_RULES = [
'get' => ['min_user_type' => USER_TYPE_ZABBIX_USER],
'create' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN],
'update' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN],
'delete' => ['min_user_type' => USER_TYPE_ZABBIX_ADMIN]
];
protected $tableName = 'valuemap';
protected $tableAlias = 'vm';
protected $sortColumns = ['valuemapid', 'name'];
/**
* Get value maps.
*
* @param array $options
*
* @return array
*/
public function get($options = []) {
$api_input_rules = ['type' => API_OBJECT, 'fields' => [
// filter
'valuemapids' => ['type' => API_IDS, 'flags' => API_ALLOW_NULL | API_NORMALIZE, 'default' => null],
'hostids' => ['type' => API_IDS, 'flags' => API_ALLOW_NULL | API_NORMALIZE, 'default' => null],
'filter' => ['type' => API_FILTER, 'flags' => API_ALLOW_NULL, 'default' => null, 'fields' => ['valuemapid', 'hostid', 'name']],
'search' => ['type' => API_FILTER, 'flags' => API_ALLOW_NULL, 'default' => null, 'fields' => ['name']],
'searchByAny' => ['type' => API_BOOLEAN, 'default' => false],
'startSearch' => ['type' => API_FLAG, 'default' => false],
'excludeSearch' => ['type' => API_FLAG, 'default' => false],
'searchWildcardsEnabled' => ['type' => API_BOOLEAN, 'default' => false],
// output
'output' => ['type' => API_OUTPUT, 'in' => implode(',', ['valuemapid', 'uuid', 'name', 'hostid']), 'default' => API_OUTPUT_EXTEND],
'selectMappings' => ['type' => API_OUTPUT, 'flags' => API_ALLOW_NULL | API_ALLOW_COUNT, 'in' => implode(',', ['type', 'value', 'newvalue']), 'default' => null],
'countOutput' => ['type' => API_FLAG, 'default' => false],
// sort and limit
'sortfield' => ['type' => API_STRINGS_UTF8, 'flags' => API_NORMALIZE, 'in' => implode(',', $this->sortColumns), 'uniq' => true, 'default' => []],
'sortorder' => ['type' => API_SORTORDER, 'default' => []],
'limit' => ['type' => API_INT32, 'flags' => API_ALLOW_NULL, 'in' => '1:'.ZBX_MAX_INT32, 'default' => null],
// flags
'editable' => ['type' => API_BOOLEAN, 'default' => false],
'preservekeys' => ['type' => API_BOOLEAN, 'default' => false]
]];
if (!CApiInputValidator::validate($api_input_rules, $options, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
$db_valuemaps = [];
$sql_parts = $this->createSelectQueryParts($this->tableName(), $this->tableAlias(), $options);
// Permission check.
if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
$permission = $options['editable'] ? PERM_READ_WRITE : PERM_READ;
$userGroups = getUserGroupsByUserId(self::$userData['userid']);
$sql_parts['where'][] = 'EXISTS ('.
'SELECT NULL'.
' FROM hosts_groups hgg'.
' JOIN rights r'.
' ON r.id=hgg.groupid'.
' AND '.dbConditionInt('r.groupid', $userGroups).
' WHERE vm.hostid=hgg.hostid'.
' GROUP BY hgg.hostid'.
' HAVING MIN(r.permission)>'.PERM_DENY.
' AND MAX(r.permission)>='.zbx_dbstr($permission).
')';
}
// hostids
if ($options['hostids'] !== null) {
$sql_parts['where']['hostid'] = dbConditionInt('vm.hostid', $options['hostids']);
}
$result = DBselect(self::createSelectQueryFromParts($sql_parts), $options['limit']);
while ($row = DBfetch($result)) {
if ($options['countOutput']) {
return $row['rowscount'];
}
$db_valuemaps[$row['valuemapid']] = $row;
}
if ($db_valuemaps) {
$db_valuemaps = $this->addRelatedObjects($options, $db_valuemaps);
$db_valuemaps = $this->unsetExtraFields($db_valuemaps, ['valuemapid'], $options['output']);
if (!$options['preservekeys']) {
$db_valuemaps = zbx_cleanHashes($db_valuemaps);
}
}
return $db_valuemaps;
}
/**
* @param array $valuemaps
*
* @return array
*
* @throws APIException
*/
public function create(array $valuemaps) {
$this->validateCreate($valuemaps);
$valuemapids = DB::insert('valuemap', $valuemaps);
$mappings = [];
foreach ($valuemaps as $index => &$valuemap) {
$valuemap['valuemapid'] = $valuemapids[$index];
$sortorder = 0;
foreach ($valuemap['mappings'] as $mapping) {
$mappings[] = [
'type' => array_key_exists('type', $mapping) ? $mapping['type'] : VALUEMAP_MAPPING_TYPE_EQUAL,
'valuemapid' => $valuemap['valuemapid'],
'value' => array_key_exists('value', $mapping) ? $mapping['value'] : '',
'newvalue' => $mapping['newvalue'],
'sortorder' => $sortorder++
];
}
}
unset($valuemap);
DB::insert('valuemap_mapping', $mappings);
$this->addAuditBulk(CAudit::ACTION_ADD, CAudit::RESOURCE_VALUE_MAP, $valuemaps);
return ['valuemapids' => $valuemapids];
}
/**
* @param array $valuemap
*
* @return array
*/
public function update(array $valuemaps) {
$this->validateUpdate($valuemaps, $db_valuemaps);
$upd_valuemaps = [];
$valuemaps_mappings = [];
foreach ($valuemaps as $valuemap) {
$valuemapid = $valuemap['valuemapid'];
$db_valuemap = $db_valuemaps[$valuemapid];
if (array_key_exists('name', $valuemap) && $valuemap['name'] !== $db_valuemap['name']) {
$upd_valuemaps[] = [
'values' => ['name' => $valuemap['name']],
'where' => ['valuemapid' => $valuemap['valuemapid']]
];
}
if (array_key_exists('uuid', $valuemap) && $valuemap['uuid'] !== $db_valuemap['uuid']) {
$upd_valuemaps[] = [
'values' => ['uuid' => $valuemap['uuid'], 'name' => $valuemap['name']],
'where' => ['valuemapid' => $valuemap['valuemapid']]
];
}
if (array_key_exists('mappings', $valuemap)) {
$valuemaps_mappings[$valuemapid] = [];
$sortorder = 0;
foreach ($valuemap['mappings'] as $mapping) {
$mapping += ['type' => VALUEMAP_MAPPING_TYPE_EQUAL, 'value' => ''];
$valuemaps_mappings[$valuemapid][] = [
'type' => $mapping['type'],
'value' => $mapping['value'],
'newvalue' => $mapping['newvalue'],
'sortorder' => $sortorder++
];
}
}
}
if ($upd_valuemaps) {
DB::update('valuemap', $upd_valuemaps);
}
if ($valuemaps_mappings) {
$db_mappings = DB::select('valuemap_mapping', [
'output' => ['valuemap_mappingid', 'valuemapid', 'type', 'value', 'newvalue', 'sortorder'],
'filter' => ['valuemapid' => array_keys($valuemaps_mappings)]
]);
CArrayHelper::sort($db_mappings, [['field' => 'sortorder', 'order' => ZBX_SORT_UP]]);
$ins_mapings = [];
$upd_mapings = [];
$del_mapingids = [];
$valuemapid_db_mappings = array_fill_keys(array_keys($valuemaps_mappings), []);
foreach ($db_mappings as $db_mapping) {
$valuemapid_db_mappings[$db_mapping['valuemapid']][] = $db_mapping;
}
foreach ($valuemaps_mappings as $valuemapid => $mappings) {
$db_mappings = &$valuemapid_db_mappings[$valuemapid];
foreach ($mappings as $mapping) {
$exists = false;
foreach ($db_mappings as $i => $db_mapping) {
if ($db_mapping['type'] == $mapping['type'] && $db_mapping['value'] == $mapping['value']) {
$exists = true;
break;
}
}
if (!$exists) {
$ins_mapings[] = ['valuemapid' => $valuemapid] + $mapping;
continue;
}
$update_fields = array_diff_assoc($mapping, $db_mapping);
if ($update_fields) {
$upd_mapings[] = [
'values' => $update_fields,
'where' => ['valuemap_mappingid' => $db_mapping['valuemap_mappingid']]
];
}
unset($db_mappings[$i]);
}
}
unset($db_mappings);
foreach ($valuemapid_db_mappings as $db_mappings) {
if ($db_mappings) {
$del_mapingids = array_merge($del_mapingids, array_column($db_mappings, 'valuemap_mappingid'));
}
}
if ($del_mapingids) {
DB::delete('valuemap_mapping', ['valuemap_mappingid' => $del_mapingids]);
}
if ($upd_mapings) {
DB::update('valuemap_mapping', $upd_mapings);
}
if ($ins_mapings) {
DB::insert('valuemap_mapping', $ins_mapings);
}
}
$this->addAuditBulk(CAudit::ACTION_UPDATE, CAudit::RESOURCE_VALUE_MAP, $valuemaps, $db_valuemaps);
return ['valuemapids' => array_column($valuemaps, 'valuemapid')];
}
/**
* @param array $valuemapids
*
* @return array
*/
public function delete(array $valuemapids) {
$api_input_rules = ['type' => API_IDS, 'flags' => API_NOT_EMPTY, 'uniq' => true];
if (!CApiInputValidator::validate($api_input_rules, $valuemapids, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
$db_valuemaps = $this->get([
'output' => ['valuemapid', 'name'],
'valuemapids' => $valuemapids,
'editable' => true,
'preservekeys' => true
]);
foreach ($valuemapids as $valuemapid) {
if (!array_key_exists($valuemapid, $db_valuemaps)) {
self::exception(ZBX_API_ERROR_PERMISSIONS,
_('No permissions to referred object or it does not exist!')
);
}
}
DB::update('items', [[
'values' => ['valuemapid' => 0],
'where' => ['valuemapid' => $valuemapids]
]]);
$this->deleteByIds($valuemapids);
$this->addAuditBulk(CAudit::ACTION_DELETE, CAudit::RESOURCE_VALUE_MAP, $db_valuemaps);
return ['valuemapids' => $valuemapids];
}
/**
* Check for duplicated value maps.
*
* @param array $names_by_hostid
*
* @throws APIException if value map already exists.
*/
private function checkDuplicates(array $names_by_hostid) {
$sql_where = [];
foreach ($names_by_hostid as $hostid => $names) {
$sql_where[] = '(vm.hostid='.$hostid.' AND '.dbConditionString('vm.name', $names).')';
}
$db_valuemaps = DBfetchArray(
DBselect('SELECT vm.name FROM valuemap vm WHERE '.implode(' OR ', $sql_where), 1)
);
if ($db_valuemaps) {
self::exception(ZBX_API_ERROR_PARAMETERS,
_s('Value map "%1$s" already exists.', $db_valuemaps[0]['name'])
);
}
}
/**
* @param array $valuemaps
*
* @throws APIException if the input is invalid.
*/
private function validateCreate(array &$valuemaps) {
$api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'uniq' => [['hostid', 'name']], 'fields' => [
'hostid' => ['type' => API_ID, 'flags' => API_REQUIRED],
'uuid' => ['type' => API_ANY],
'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('valuemap', 'name')],
'mappings' => ['type' => API_OBJECTS, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'fields' => [
'type' => ['type' => API_INT32, 'default' => VALUEMAP_MAPPING_TYPE_EQUAL, 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_EQUAL, VALUEMAP_MAPPING_TYPE_GREATER_EQUAL, VALUEMAP_MAPPING_TYPE_LESS_EQUAL, VALUEMAP_MAPPING_TYPE_IN_RANGE, VALUEMAP_MAPPING_TYPE_REGEXP, VALUEMAP_MAPPING_TYPE_DEFAULT])],
'value' => ['type' => API_MULTIPLE, 'rules' => [
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_EQUAL])],
'type' => API_STRING_UTF8,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_GREATER_EQUAL, VALUEMAP_MAPPING_TYPE_LESS_EQUAL])],
'type' => API_FLOAT,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_IN_RANGE])],
'type' => API_NUMERIC_RANGES,
'flags' => API_NOT_EMPTY,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_REGEXP])],
'type' => API_REGEX,
'flags' => API_NOT_EMPTY,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_DEFAULT])],
'type' => API_STRING_UTF8
]
]],
'newvalue' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('valuemap_mapping', 'newvalue')]
]]
]];
if (!CApiInputValidator::validate($api_input_rules, $valuemaps, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
$this->validateValuemapMappings($valuemaps);
$hostids = [];
foreach ($valuemaps as $valuemap) {
$hostids[$valuemap['hostid']] = true;
}
$db_hosts = API::Host()->get([
'output' => ['status'],
'hostids' => array_keys($hostids),
'templated_hosts' => true,
'editable' => true,
'preservekeys' => true
]);
$names_by_hostid = [];
foreach ($valuemaps as $valuemap) {
// check permissions by hostid
if (!array_key_exists($valuemap['hostid'], $db_hosts)) {
self::exception(ZBX_API_ERROR_PERMISSIONS,
_('No permissions to referred object or it does not exist!')
);
}
$names_by_hostid[$valuemap['hostid']][] = $valuemap['name'];
}
self::validateUuid($valuemaps, $db_hosts);
self::addUuid($valuemaps, $db_hosts);
self::checkUuidDuplicates($valuemaps);
$this->checkDuplicates($names_by_hostid);
}
/**
* @param array $valuemaps
* @param array $db_hosts
*
* @throws APIException
*/
private static function validateUuid(array $valuemaps, array $db_hosts): void {
foreach ($valuemaps as &$valuemap) {
$valuemap['host_status'] = $db_hosts[$valuemap['hostid']]['status'];
}
unset($valuemap);
$api_input_rules = ['type' => API_OBJECTS, 'flags' => API_ALLOW_UNEXPECTED, 'uniq' => [['uuid']], 'fields' => [
'host_status' => ['type' => API_ANY],
'uuid' => ['type' => API_MULTIPLE, 'rules' => [
['if' => ['field' => 'host_status', 'in' => HOST_STATUS_TEMPLATE], 'type' => API_UUID],
['else' => true, 'type' => API_STRING_UTF8, 'in' => DB::getDefault('valuemap', 'uuid'), 'unset' => true]
]]
]];
if (!CApiInputValidator::validate($api_input_rules, $valuemaps, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
}
/**
* Add the UUID to those of the given value maps that belong to a template and don't have the 'uuid' parameter set.
*
* @param array $valuemaps
* @param array $db_hosts
*/
private static function addUuid(array &$valuemaps, array $db_hosts): void {
foreach ($valuemaps as &$valuemap) {
if ($db_hosts[$valuemap['hostid']]['status'] == HOST_STATUS_TEMPLATE
&& !array_key_exists('uuid', $valuemap)) {
$valuemap['uuid'] = generateUuidV4();
}
}
unset($valuemap);
}
/**
* Verify value map UUIDs are not repeated.
*
* @param array $valuemaps
* @param array|null $db_valuemaps
*
* @throws APIException
*/
private static function checkUuidDuplicates(array $valuemaps, array $db_valuemaps = null): void {
$valuemap_indexes = [];
foreach ($valuemaps as $i => $valuemap) {
if (!array_key_exists('uuid', $valuemap) || $valuemap['uuid'] === '') {
continue;
}
if ($db_valuemaps === null || $valuemap['uuid'] !== $db_valuemaps[$valuemap['valuemapid']]['uuid']) {
$valuemap_indexes[$valuemap['uuid']] = $i;
}
}
if (!$valuemap_indexes) {
return;
}
$duplicates = DB::select('valuemap', [
'output' => ['uuid'],
'filter' => [
'uuid' => array_keys($valuemap_indexes)
],
'limit' => 1
]);
if ($duplicates) {
self::exception(ZBX_API_ERROR_PARAMETERS,
_s('Invalid parameter "%1$s": %2$s.', '/'.($valuemap_indexes[$duplicates[0]['uuid']] + 1),
_('value map with the same UUID already exists')
)
);
}
}
/**
* @param array $valuemaps
* @param array $db_valuemaps
*
* @throws APIException if the input is invalid.
*/
private function validateUpdate(array &$valuemaps, array &$db_valuemaps = null) {
$api_input_rules = ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY | API_NORMALIZE, 'uniq' => [['valuemapid']], 'fields' => [
'uuid' => ['type' => API_ANY],
'valuemapid' => ['type' => API_ID, 'flags' => API_REQUIRED],
'name' => ['type' => API_STRING_UTF8, 'flags' => API_NOT_EMPTY, 'length' => DB::getFieldLength('valuemap', 'name')],
'mappings' => ['type' => API_OBJECTS, 'flags' => API_NOT_EMPTY, 'fields' => [
'type' => ['type' => API_INT32, 'default' => VALUEMAP_MAPPING_TYPE_EQUAL, 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_EQUAL, VALUEMAP_MAPPING_TYPE_GREATER_EQUAL, VALUEMAP_MAPPING_TYPE_LESS_EQUAL, VALUEMAP_MAPPING_TYPE_IN_RANGE, VALUEMAP_MAPPING_TYPE_REGEXP, VALUEMAP_MAPPING_TYPE_DEFAULT])],
'value' => ['type' => API_MULTIPLE, 'rules' => [
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_EQUAL])],
'type' => API_STRING_UTF8,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_GREATER_EQUAL, VALUEMAP_MAPPING_TYPE_LESS_EQUAL])],
'type' => API_FLOAT,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_IN_RANGE])],
'type' => API_NUMERIC_RANGES,
'flags' => API_NOT_EMPTY,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_REGEXP])],
'type' => API_REGEX,
'flags' => API_NOT_EMPTY,
'length' => DB::getFieldLength('valuemap_mapping', 'value')
],
[
'if' => ['field' => 'type', 'in' => implode(',', [VALUEMAP_MAPPING_TYPE_DEFAULT])],
'type' => API_STRING_UTF8
]
]],
'newvalue' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => DB::getFieldLength('valuemap_mapping', 'newvalue')]
]]
]];
if (!CApiInputValidator::validate($api_input_rules, $valuemaps, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
$this->validateValuemapMappings($valuemaps);
$db_valuemaps = $this->get([
'output' => ['uuid', 'valuemapid', 'hostid', 'name'],
'valuemapids' => array_column($valuemaps, 'valuemapid'),
'editable' => true,
'preservekeys' => true
]);
foreach ($valuemaps as $valuemap) {
if (!array_key_exists($valuemap['valuemapid'], $db_valuemaps)) {
self::exception(ZBX_API_ERROR_PERMISSIONS,
_('No permissions to referred object or it does not exist!')
);
}
}
$valuemaps = $this->extendObjectsByKey($valuemaps, $db_valuemaps, 'valuemapid', ['hostid']);
$api_input_rules = ['type' => API_OBJECTS, 'uniq' => [['hostid', 'name']], 'fields' => [
'hostid' => ['type' => API_ID],
'name' => ['type' => API_STRING_UTF8]
]];
if (!CApiInputValidator::validateUniqueness($api_input_rules, $valuemaps, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
$db_hosts = DB::select('hosts', [
'output' => ['status'],
'hostids' => array_unique(array_column($db_valuemaps, 'hostid')),
'preservekeys' => true
]);
self::validateUuid($valuemaps, $db_hosts);
self::checkUuidDuplicates($valuemaps, $db_valuemaps);
$names_by_hostid = [];
foreach ($valuemaps as $valuemap) {
$db_valuemap = $db_valuemaps[$valuemap['valuemapid']];
if (array_key_exists('name', $valuemap) && $valuemap['name'] !== $db_valuemap['name']) {
$names_by_hostid[$valuemap['hostid']][] = $valuemap['name'];
}
}
if ($names_by_hostid) {
$this->checkDuplicates($names_by_hostid);
}
}
/**
* Validate uniqueness of mapping value in value maps, type VALUEMAP_MAPPING_TYPE_DEFAULT can be defined only once
* per value map mappings.
*
* @param array $valuemaps Array of valuemaps
*
* @throws Exception when non unique
*/
protected function validateValuemapMappings(array $valuemaps) {
$i = 0;
$error = '';
foreach ($valuemaps as $valuemap) {
$i++;
if (!array_key_exists('mappings', $valuemap)) {
continue;
}
$type_uniq = array_fill_keys([VALUEMAP_MAPPING_TYPE_EQUAL, VALUEMAP_MAPPING_TYPE_GREATER_EQUAL,
VALUEMAP_MAPPING_TYPE_LESS_EQUAL, VALUEMAP_MAPPING_TYPE_IN_RANGE, VALUEMAP_MAPPING_TYPE_REGEXP
], []
);
$has_default = false;
foreach (array_values($valuemap['mappings']) as $j => $mapping) {
$type = array_key_exists('type', $mapping) ? $mapping['type'] : VALUEMAP_MAPPING_TYPE_EQUAL;
$value = array_key_exists('value', $mapping) ? (string) $mapping['value'] : '';
if ($has_default && $type == VALUEMAP_MAPPING_TYPE_DEFAULT) {
$error = _s('value %1$s already exists', '(type)=('.VALUEMAP_MAPPING_TYPE_DEFAULT.')');
}
elseif (!array_key_exists('value', $mapping) && $type != VALUEMAP_MAPPING_TYPE_DEFAULT) {
$error = _s('the parameter "%1$s" is missing', 'value');
}
elseif ($value !== '' && $type == VALUEMAP_MAPPING_TYPE_DEFAULT) {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Invalid parameter "%1$s": %2$s.',
sprintf('/%1$s/mappings/%2$s/value', $i, $j + 1),
_('should be empty')
));
}
elseif ($type != VALUEMAP_MAPPING_TYPE_DEFAULT && array_key_exists($value, $type_uniq[$type])) {
$error = _s('value %1$s already exists', '(value)=('.$value.')');
}
if ($error !== '') {
self::exception(ZBX_API_ERROR_PARAMETERS, _s('Invalid parameter "%1$s": %2$s.',
sprintf('/%1$s/mappings/%2$s', $i, $j + 1),
$error
));
}
$has_default = ($has_default || $type == VALUEMAP_MAPPING_TYPE_DEFAULT);
$type_uniq[$type][$value] = true;
}
}
}
protected function addRelatedObjects(array $options, array $db_valuemaps) {
$db_valuemaps = parent::addRelatedObjects($options, $db_valuemaps);
// Select mappings for value map.
if ($options['selectMappings'] !== null) {
$def_mappings = ($options['selectMappings'] == API_OUTPUT_COUNT) ? '0' : [];
foreach ($db_valuemaps as $valuemapid => $db_valuemap) {
$db_valuemaps[$valuemapid]['mappings'] = $def_mappings;
}
if ($options['selectMappings'] == API_OUTPUT_COUNT) {
$db_mappings = DBselect(
'SELECT m.valuemapid,COUNT(*) AS cnt'.
' FROM valuemap_mapping m'.
' WHERE '.dbConditionInt('m.valuemapid', array_keys($db_valuemaps)).
' GROUP BY m.valuemapid'
);
while ($db_mapping = DBfetch($db_mappings)) {
$db_valuemaps[$db_mapping['valuemapid']]['mappings'] = $db_mapping['cnt'];
}
}
else {
$db_mappings = API::getApiService()->select('valuemap_mapping', [
'output' => $this->outputExtend($options['selectMappings'], ['valuemapid',
'valuemap_mappingid', 'sortorder'
]),
'filter' => ['valuemapid' => array_keys($db_valuemaps)]
]);
CArrayHelper::sort($db_mappings, [['field' => 'sortorder', 'order' => ZBX_SORT_UP]]);
foreach ($db_mappings as $db_mapping) {
$valuemapid = $db_mapping['valuemapid'];
unset($db_mapping['valuemap_mappingid'], $db_mapping['valuemapid'], $db_mapping['sortorder']);
$db_valuemaps[$valuemapid]['mappings'][] = $db_mapping;
}
}
}
return $db_valuemaps;
}
}