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

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ui/include/items.inc.php')
-rw-r--r--ui/include/items.inc.php909
1 files changed, 624 insertions, 285 deletions
diff --git a/ui/include/items.inc.php b/ui/include/items.inc.php
index 14940303fe1..18a8dc6f86b 100644
--- a/ui/include/items.inc.php
+++ b/ui/include/items.inc.php
@@ -344,7 +344,6 @@ function orderItemsByStatus(array &$items, $sortorder = ZBX_SORT_UP) {
*/
function interfaceType2str($type) {
$interfaceGroupLabels = [
- INTERFACE_TYPE_OPT => _('None'),
INTERFACE_TYPE_AGENT => _('Agent'),
INTERFACE_TYPE_SNMP => _('SNMP'),
INTERFACE_TYPE_JMX => _('JMX'),
@@ -397,366 +396,290 @@ function interfaceIdsByType(array $interfaces) {
}
/**
- * Copies the given items to the given hosts or templates.
+ * Create copies of items from the given sources to the given destination hosts or templates.
*
- * @param array $src_itemids Items which will be copied to $dst_hostids.
- * @param array $dst_hostids Hosts and templates to whom add items.
+ * If source type is 'templateids' or 'hostids', only non-inherited items are copied.
+ *
+ * If source type is 'itemids', all the given items are copied.
+ *
+ * @param string $src_type
+ * @param array $src_ids
+ * @param bool $dst_is_template
+ * @param array $dst_hostids
*
* @return bool
*/
-function copyItemsToHosts($src_itemids, $dst_hostids) {
- $items = API::Item()->get([
- 'output' => ['type', 'snmp_oid', 'name', 'key_', 'delay', 'history', 'trends', 'status', 'value_type',
- 'trapper_hosts', 'units', 'logtimefmt', 'valuemapid', 'params', 'ipmi_sensor', 'authtype', 'username',
- 'password', 'publickey', 'privatekey', 'flags', 'description', 'inventory_link', 'jmx_endpoint',
- 'master_itemid', 'timeout', 'url', 'query_fields', 'posts', 'status_codes', 'follow_redirects',
- 'post_type', 'http_proxy', 'headers', 'retrieve_mode', 'request_method', 'output_format', 'ssl_cert_file',
- 'ssl_key_file', 'ssl_key_password', 'verify_peer', 'verify_host', 'allow_traps', 'parameters'
+function copyItemsToHosts(string $src_type, array $src_ids, bool $dst_is_template, array $dst_hostids): bool {
+ $options = in_array($src_type, ['templateids', 'hostids']) ? ['inherited' => false] : [];
+
+ $src_items = API::Item()->get([
+ 'output' => ['itemid', 'name', 'type', 'key_', 'value_type', 'units', 'history', 'trends',
+ 'valuemapid', 'inventory_link', 'logtimefmt', 'description', 'status',
+
+ // Type fields.
+ // The fields used for multiple item types.
+ 'interfaceid', 'authtype', 'username', 'password', 'params', 'timeout', 'delay', 'trapper_hosts',
+
+ // Dependent item type specific fields.
+ 'master_itemid',
+
+ // HTTP Agent item type specific fields.
+ 'url', 'query_fields', 'request_method', 'post_type', 'posts',
+ 'headers', 'status_codes', 'follow_redirects', 'retrieve_mode', 'output_format', 'http_proxy',
+ 'verify_peer', 'verify_host', 'ssl_cert_file', 'ssl_key_file', 'ssl_key_password', 'allow_traps',
+
+ // IPMI item type specific fields.
+ 'ipmi_sensor',
+
+ // JMX item type specific fields.
+ 'jmx_endpoint',
+
+ // Script item type specific fields.
+ 'parameters',
+
+ // SNMP item type specific fields.
+ 'snmp_oid',
+
+ // SSH item type specific fields.
+ 'publickey', 'privatekey'
],
'selectPreprocessing' => ['type', 'params', 'error_handler', 'error_handler_params'],
'selectTags' => ['tag', 'value'],
- 'itemids' => $src_itemids,
+ $src_type => $src_ids,
'preservekeys' => true
- ]);
-
- // Check if dependent items have master items in same selection. If not, those could be web items.
- $master_itemids = [];
+ ] + $options);
- foreach ($items as $itemid => $item) {
- if ($item['type'] == ITEM_TYPE_DEPENDENT && !array_key_exists($item['master_itemid'], $items)) {
- $master_itemids[$item['master_itemid']] = true;
- }
+ if (!$src_items) {
+ return true;
}
- // Find same master items (that includes web items) on destination host.
- $dst_master_items = [];
+ $src_itemids = array_fill_keys(array_keys($src_items), true);
+ $src_valuemapids = [];
+ $src_interfaceids = [];
+ $src_dep_items = [];
+ $dep_itemids = [];
- foreach (array_keys($master_itemids) as $master_itemid) {
- $same_master_item = get_same_item_for_host(['itemid' => $master_itemid], $dst_hostids);
-
- if ($same_master_item) {
- $dst_master_items[$master_itemid] = $same_master_item;
+ foreach ($src_items as $itemid => &$item) {
+ if ($item['valuemapid'] != 0) {
+ $src_valuemapids[$item['valuemapid']] = true;
}
- }
- $create_order = [];
- $src_itemid_to_key = [];
+ if ($item['interfaceid'] != 0) {
+ $src_interfaceids[$item['interfaceid']] = true;
+ }
- // Calculate dependency level between items so that master items are created before dependent items.
- foreach ($items as $itemid => $item) {
- $dependency_level = 0;
- $master_item = $item;
- $src_itemid_to_key[$itemid] = $item['key_'];
+ if ($item['type'] == ITEM_TYPE_DEPENDENT) {
+ if (array_key_exists($item['master_itemid'], $src_itemids)) {
+ $src_dep_items[$item['master_itemid']][] = $item;
- while ($master_item['type'] == ITEM_TYPE_DEPENDENT) {
- if (!array_key_exists($master_item['master_itemid'], $items)) {
- break;
+ unset($src_items[$itemid]);
+ }
+ else {
+ $dep_itemids[$item['master_itemid']][] = $item['itemid'];
}
-
- $master_item = $items[$master_item['master_itemid']];
- ++$dependency_level;
}
-
- $create_order[$itemid] = $dependency_level;
}
+ unset($item);
- asort($create_order);
-
- $dstHosts = API::Host()->get([
- 'output' => ['hostid', 'host', 'status'],
- 'selectInterfaces' => ['interfaceid', 'type', 'main'],
- 'hostids' => $dst_hostids,
- 'preservekeys' => true,
- 'nopermissions' => true,
- 'templated_hosts' => true
- ]);
-
- $src_valuemapids = array_column($items, 'valuemapid', 'valuemapid');
- unset($src_valuemapids[0]);
+ $valuemap_links = [];
if ($src_valuemapids) {
- $valuemapids_map = [];
$src_valuemaps = API::ValueMap()->get([
- 'output' => ['name'],
- 'valuemapids' => $src_valuemapids,
- 'preservekeys' => true
+ 'output' => ['valuemapid', 'name'],
+ 'valuemapids' => array_keys($src_valuemapids)
]);
+
$dst_valuemaps = API::ValueMap()->get([
- 'output' => ['name', 'hostid'],
+ 'output' => ['valuemapid', 'hostid', 'name'],
'hostids' => $dst_hostids,
- 'filter' => ['name' => array_column($src_valuemaps, 'name')],
- 'preservekeys' => true
+ 'filter' => ['name' => array_unique(array_column($src_valuemaps, 'name'))]
]);
- foreach ($src_valuemaps as $src_valuemapid => $src_valuemap) {
- foreach ($dst_valuemaps as $dst_valuemapid => $dst_valuemap) {
- if ($dst_valuemap['name'] === $src_valuemap['name']) {
- $valuemapids_map[$src_valuemapid][$dst_valuemap['hostid']] = $dst_valuemapid;
- }
- }
- }
- }
+ $dst_valuemapids = [];
- foreach ($dstHosts as $dstHost) {
- $interfaceids = [];
+ foreach ($dst_valuemaps as $dst_valuemap) {
+ $dst_valuemapids[$dst_valuemap['name']][$dst_valuemap['hostid']] = $dst_valuemap['valuemapid'];
+ }
- foreach ($dstHost['interfaces'] as $interface) {
- if ($interface['main'] == INTERFACE_PRIMARY) {
- $interfaceids[$interface['type']] = $interface['interfaceid'];
+ foreach ($src_valuemaps as $src_valuemap) {
+ if (array_key_exists($src_valuemap['name'], $dst_valuemapids)) {
+ foreach ($dst_valuemapids[$src_valuemap['name']] as $dst_hostid => $dst_valuemapid) {
+ $valuemap_links[$src_valuemap['valuemapid']][$dst_hostid] = $dst_valuemapid;
+ }
}
}
+ }
- $itemkey_to_id = [];
- $create_items = [];
- $current_dependency = reset($create_order);
+ $interface_links = [];
+ $dst_interfaceids = [];
- foreach ($create_order as $itemid => $dependency_level) {
- if ($current_dependency != $dependency_level) {
- $current_dependency = $dependency_level;
- $created_itemids = API::Item()->create($create_items);
+ if (!$dst_is_template) {
+ $src_interfaces = [];
- if (!$created_itemids) {
- return false;
- }
- $created_itemids = $created_itemids['itemids'];
+ if ($src_interfaceids) {
+ $src_hosts = API::Host()->get([
+ 'output' => [],
+ 'selectInterfaces' => ['interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port', 'details'],
+ $src_type => $src_ids
+ ]);
- foreach ($create_items as $index => $created_item) {
- $itemkey_to_id[$created_item['key_']] = $created_itemids[$index];
+ foreach ($src_hosts as $src_host) {
+ foreach ($src_host['interfaces'] as $src_interface) {
+ if (array_key_exists($src_interface['interfaceid'], $src_interfaceids)) {
+ $src_interfaces[$src_interface['interfaceid']] =
+ array_diff_key($src_interface, array_flip(['interfaceid']));
+ }
}
-
- $create_items = [];
}
+ }
- $item = $items[$itemid];
+ $dst_hosts = API::Host()->get([
+ 'output' => ['hostid'],
+ 'selectInterfaces' => ['interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port', 'details'],
+ 'hostids' => $dst_hostids
+ ]);
- if ($dstHost['status'] != HOST_STATUS_TEMPLATE) {
- $type = itemTypeInterface($item['type']);
+ foreach ($dst_hosts as $dst_host) {
+ foreach ($dst_host['interfaces'] as $dst_interface) {
+ $dst_interfaceid = $dst_interface['interfaceid'];
+ unset($dst_interface['interfaceid']);
- if ($type == INTERFACE_TYPE_ANY) {
- foreach (CItem::INTERFACE_TYPES_BY_PRIORITY as $itype) {
- if (array_key_exists($type, $interfaceids)) {
- $item['interfaceid'] = $interfaceids[$itype];
- break;
- }
+ foreach ($src_interfaces as $src_interfaceid => $src_interface) {
+ if ($src_interface == $dst_interface) {
+ $interface_links[$src_interfaceid][$dst_host['hostid']] = $dst_interfaceid;
}
}
- elseif ($type !== false && $type != INTERFACE_TYPE_OPT) {
- if (!isset($interfaceids[$type])) {
- error(_s('Cannot find host interface on "%1$s" for item key "%2$s".', $dstHost['host'],
- $item['key_']
- ));
-
- return false;
- }
- $item['interfaceid'] = $interfaceids[$type];
+ if ($dst_interface['main'] == INTERFACE_PRIMARY) {
+ $dst_interfaceids[$dst_host['hostid']][$dst_interface['type']] = $dst_interfaceid;
}
}
+ }
+ }
- unset($item['itemid']);
-
- if ($item['valuemapid'] != 0) {
- if (array_key_exists($item['valuemapid'], $valuemapids_map)
- && array_key_exists($dstHost['hostid'], $valuemapids_map[$item['valuemapid']])) {
- $item['valuemapid'] = $valuemapids_map[$item['valuemapid']][$dstHost['hostid']];
- }
- else {
- $item['valuemapid'] = 0;
- }
- }
-
- $item['hostid'] = $dstHost['hostid'];
-
- if ($item['type'] == ITEM_TYPE_DEPENDENT) {
- if (array_key_exists($item['master_itemid'], $items)) {
- $src_item_key = $src_itemid_to_key[$item['master_itemid']];
- $item['master_itemid'] = $itemkey_to_id[$src_item_key];
- }
- else {
- $item_found = false;
-
- if (array_key_exists($item['master_itemid'], $dst_master_items)) {
- foreach ($dst_master_items[$item['master_itemid']] as $dst_master_item) {
- if ($dst_master_item['hostid'] == $dstHost['hostid']) {
- // A matching item on destination host has been found.
+ $master_item_links = [];
- $item['master_itemid'] = $dst_master_item['itemid'];
- $item_found = true;
- }
- }
- }
+ if ($dep_itemids) {
+ $master_items = API::Item()->get([
+ 'output' => ['itemid', 'key_'],
+ 'itemids' => array_keys($dep_itemids)
+ ]);
- // Master item does not exist on destination host or has not been selected for copying.
- if (!$item_found) {
- error(_s('Item "%1$s" cannot be copied without its master item.', $item['name']));
+ $options = $dst_is_template ? ['templateids' => $dst_hostids] : ['hostids' => $dst_hostids];
- return false;
- }
- }
- }
- else {
- unset($item['master_itemid']);
- }
+ $dst_master_items = API::Item()->get([
+ 'output' => ['itemid', 'hostid', 'key_'],
+ 'filter' => ['key_' => array_unique(array_column($master_items, 'key_'))]
+ ] + $options);
- $create_items[] = $item;
- }
+ $dst_master_itemids = [];
- if ($create_items && !API::Item()->create($create_items)) {
- return false;
+ foreach ($dst_master_items as $item) {
+ $dst_master_itemids[$item['hostid']][$item['key_']] = $item['itemid'];
}
- }
- return true;
-}
+ foreach ($master_items as $item) {
+ foreach ($dst_hostids as $dst_hostid) {
+ if (array_key_exists($dst_hostid, $dst_master_itemids)
+ && array_key_exists($item['key_'], $dst_master_itemids[$dst_hostid])) {
+ $master_item_links[$item['itemid']][$dst_hostid] = $dst_master_itemids[$dst_hostid][$item['key_']];
+ }
+ else {
+ $src_itemid = reset($dep_itemids[$item['itemid']]);
-function copyItems($srcHostId, $dstHostId, $assign_opt_interface = false) {
- $srcItems = API::Item()->get([
- 'output' => ['type', 'snmp_oid', 'name', 'key_', 'delay', 'history', 'trends', 'status', 'value_type',
- 'trapper_hosts', 'units', 'logtimefmt', 'valuemapid', 'params', 'ipmi_sensor', 'authtype', 'username',
- 'password', 'publickey', 'privatekey', 'flags', 'interfaceid', 'description', 'inventory_link',
- 'jmx_endpoint', 'master_itemid', 'templateid', 'url', 'query_fields', 'timeout', 'posts', 'status_codes',
- 'follow_redirects', 'post_type', 'http_proxy', 'headers', 'retrieve_mode', 'request_method',
- 'output_format', 'ssl_cert_file', 'ssl_key_file', 'ssl_key_password', 'verify_peer', 'verify_host',
- 'allow_traps', 'parameters'
- ],
- 'selectTags' => ['tag', 'value'],
- 'selectPreprocessing' => ['type', 'params', 'error_handler', 'error_handler_params'],
- 'selectValueMap' => ['name'],
- 'hostids' => $srcHostId,
- 'webitems' => true,
- 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL],
- 'preservekeys' => true
- ]);
- $dstHosts = API::Host()->get([
- 'output' => ['hostid', 'host', 'status'],
- 'selectInterfaces' => ['interfaceid', 'type', 'main'],
- 'hostids' => $dstHostId,
- 'preservekeys' => true,
- 'nopermissions' => true,
- 'templated_hosts' => true
- ]);
- $dstHost = reset($dstHosts);
- $src_valuemap_names = [];
- $valuemap_map = [];
+ error(_s('Cannot copy item with key "%1$s" without its master item with key "%2$s".',
+ $src_items[$src_itemid]['key_'], $item['key_']
+ ));
- foreach ($srcItems as $src_item) {
- if ($src_item['valuemap'] && $src_item['templateid'] == 0) {
- $src_valuemap_names[] = $src_item['valuemap']['name'];
+ return false;
+ }
+ }
}
}
- if ($src_valuemap_names) {
- $valuemap_map = array_column(API::ValueMap()->get([
- 'output' => ['valuemapid', 'name'],
- 'hostids' => $dstHostId,
- 'filter' => ['name' => $src_valuemap_names]
- ]), 'valuemapid', 'name');
- }
-
- $create_order = [];
- $src_itemid_to_key = [];
- foreach ($srcItems as $itemid => $item) {
- $dependency_level = 0;
- $master_item = $item;
- $src_itemid_to_key[$itemid] = $item['key_'];
+ do {
+ $dst_items = [];
- while ($master_item['type'] == ITEM_TYPE_DEPENDENT) {
- $master_item = $srcItems[$master_item['master_itemid']];
- ++$dependency_level;
- }
+ foreach ($dst_hostids as $dst_hostid) {
+ foreach ($src_items as $src_item) {
+ $dst_item = array_diff_key($src_item, array_flip(['itemid']));
- $create_order[$itemid] = $dependency_level;
- }
- asort($create_order);
+ if ($src_item['valuemapid'] != 0) {
+ if (array_key_exists($src_item['valuemapid'], $valuemap_links)
+ && array_key_exists($dst_hostid, $valuemap_links[$src_item['valuemapid']])) {
+ $dst_item['valuemapid'] = $valuemap_links[$src_item['valuemapid']][$dst_hostid];
+ }
+ else {
+ $dst_item['valuemapid'] = 0;
+ }
+ }
- $itemkey_to_id = [];
- $create_items = [];
- $current_dependency = reset($create_order);
+ $dst_item['interfaceid'] = 0;
- foreach ($create_order as $itemid => $dependency_level) {
- $srcItem = $srcItems[$itemid];
+ if (!$dst_is_template) {
+ if (array_key_exists($src_item['interfaceid'], $interface_links)
+ && array_key_exists($dst_hostid, $interface_links[$src_item['interfaceid']])) {
+ $dst_item['interfaceid'] = $interface_links[$src_item['interfaceid']][$dst_hostid];
+ }
+ else {
+ $type = itemTypeInterface($src_item['type']);
+
+ if (in_array($type,
+ [INTERFACE_TYPE_AGENT, INTERFACE_TYPE_SNMP, INTERFACE_TYPE_JMX, INTERFACE_TYPE_IPMI]
+ )) {
+ if (array_key_exists($dst_hostid, $dst_interfaceids)
+ && array_key_exists($type, $dst_interfaceids[$dst_hostid])) {
+ $dst_item['interfaceid'] = $dst_interfaceids[$dst_hostid][$type];
+ }
+ else {
+ $hosts = API::Host()->get([
+ 'output' => ['host'],
+ 'hostids' => $dst_hostid
+ ]);
- // Skip creating web items. Those were created before.
- if ($srcItem['type'] == ITEM_TYPE_HTTPTEST) {
- continue;
- }
+ error(_s('Cannot find host interface on "%1$s" for item with key "%2$s".',
+ $hosts[0]['host'], $src_item['key_']
+ ));
- if ($current_dependency != $dependency_level && $create_items) {
- $current_dependency = $dependency_level;
- $created_itemids = API::Item()->create($create_items);
+ return false;
+ }
+ }
+ }
+ }
- if (!$created_itemids) {
- return false;
- }
- $created_itemids = $created_itemids['itemids'];
+ if ($src_item['type'] == ITEM_TYPE_DEPENDENT) {
+ $dst_item['master_itemid'] = $master_item_links[$src_item['master_itemid']][$dst_hostid];
+ }
- foreach ($create_items as $index => $created_item) {
- $itemkey_to_id[$created_item['key_']] = $created_itemids[$index];
+ $dst_items[] = ['hostid' => $dst_hostid] + $dst_item;
}
-
- $create_items = [];
}
- if ($srcItem['templateid'] != 0) {
- $srcItem = get_same_item_for_host($srcItem, $dstHost['hostid']);
+ $response = API::Item()->create($dst_items);
- if (!$srcItem) {
- return false;
- }
- $itemkey_to_id[$srcItem['key_']] = $srcItem['itemid'];
- continue;
- }
- else if ($srcItem['valuemapid'] != 0) {
- $srcItem['valuemapid'] = array_key_exists($srcItem['valuemap']['name'], $valuemap_map)
- ? $valuemap_map[$srcItem['valuemap']['name']]
- : 0;
+ if ($response === false) {
+ return false;
}
- if ($dstHost['status'] != HOST_STATUS_TEMPLATE) {
- $interface = CItem::findInterfaceForItem($srcItem['type'], $dstHost['interfaces']);
+ $_src_items = [];
- if ($interface === false && $assign_opt_interface
- && itemTypeInterface($srcItem['type']) == INTERFACE_TYPE_OPT
- && $srcItem['interfaceid'] != 0) {
- $interface = CItem::findInterfaceByPriority($dstHost['interfaces']);
- }
+ if ($src_dep_items) {
+ foreach ($dst_hostids as $dst_hostid) {
+ foreach ($src_items as $src_item) {
+ $dst_itemid = array_shift($response['itemids']);
- if ($interface) {
- $srcItem['interfaceid'] = $interface['interfaceid'];
- }
- elseif ($interface !== false) {
- error(_s('Cannot find host interface on "%1$s" for item key "%2$s".', $dstHost['host'], $srcItem['key_']));
- }
- }
- unset($srcItem['itemid']);
- unset($srcItem['templateid']);
- $srcItem['hostid'] = $dstHostId;
-
- if (!$srcItem['preprocessing']) {
- unset($srcItem['preprocessing']);
- }
+ if (array_key_exists($src_item['itemid'], $src_dep_items)) {
+ $master_item_links[$src_item['itemid']][$dst_hostid] = $dst_itemid;
- if ($srcItem['type'] == ITEM_TYPE_DEPENDENT) {
- if ($srcItems[$srcItem['master_itemid']]['type'] == ITEM_TYPE_HTTPTEST) {
- // Web items are outside the scope and are created before regular items.
- $web_item = get_same_item_for_host($srcItems[$srcItem['master_itemid']], $dstHost['hostid']);
- $srcItem['master_itemid'] = $web_item['itemid'];
- }
- else {
- $src_item_key = $src_itemid_to_key[$srcItem['master_itemid']];
- $srcItem['master_itemid'] = $itemkey_to_id[$src_item_key];
+ $_src_items = array_merge($_src_items, $src_dep_items[$src_item['itemid']]);
+ unset($src_dep_items[$src_item['itemid']]);
+ }
+ }
}
}
- else {
- unset($srcItem['master_itemid']);
- }
-
- $create_items[] = $srcItem;
- }
- if ($create_items && !API::Item()->create($create_items)) {
- return false;
- }
+ $src_items = $_src_items;
+ } while ($src_items);
return true;
}
@@ -1292,7 +1215,7 @@ function getInterfaceSelect(array $interfaces): CSelect {
/** @var CSelectOption[] $options_by_type */
$options_by_type = [];
- $interface_select->addOption(new CSelectOption(INTERFACE_TYPE_OPT, interfaceType2str(INTERFACE_TYPE_OPT)));
+ $interface_select->addOption(new CSelectOption(0, _('None')));
foreach ($interfaces as $interface) {
$option = new CSelectOption($interface['interfaceid'], getHostInterface($interface));
@@ -2228,10 +2151,426 @@ function normalizeItemPreprocessingSteps(array $preprocessing): array {
'error_handler_params' => ''
];
- // Remove fictional field that doesn't belong in DB and API.
- unset($step['sortorder']);
+ // Remove fictional fields that don't belong to DB and API.
+ unset($step['sortorder'], $step['on_fail']);
}
unset($step);
return $preprocessing;
}
+
+/**
+ * Check that the given key is not equal to the example value presented for a specific type.
+ *
+ * @param int $type
+ * @param string $key
+ *
+ * @return bool
+ */
+function isItemExampleKey(int $type, string $key): bool {
+ if (($type == ITEM_TYPE_DB_MONITOR && $key === ZBX_DEFAULT_KEY_DB_MONITOR)
+ || ($type == ITEM_TYPE_SSH && $key === ZBX_DEFAULT_KEY_SSH)
+ || ($type == ITEM_TYPE_TELNET && $key === ZBX_DEFAULT_KEY_TELNET)) {
+ error(_('Check the key, please. Default example was passed.'));
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Check the format of the given custom intervals. Unset the custom intervals with empty values.
+ *
+ * @param array $delay_flex
+ * @param bool $lldmacros
+ */
+function isValidCustomIntervals(array &$delay_flex, bool $lldmacros = false): bool {
+ if (!$delay_flex) {
+ return true;
+ }
+
+ $simple_interval_parser = new CSimpleIntervalParser([
+ 'usermacros' => true,
+ 'lldmacros' => $lldmacros
+ ]);
+
+ $time_period_parser = new CTimePeriodParser([
+ 'usermacros' => true,
+ 'lldmacros' => $lldmacros
+ ]);
+
+ $scheduling_interval_parser = new CSchedulingIntervalParser([
+ 'usermacros' => true,
+ 'lldmacros' => $lldmacros
+ ]);
+
+ foreach ($delay_flex as $i => $interval) {
+ if ($interval['type'] == ITEM_DELAY_FLEXIBLE) {
+ if ($interval['delay'] === '' && $interval['period'] === '') {
+ unset($delay_flex[$i]);
+ continue;
+ }
+
+ if ($simple_interval_parser->parse($interval['delay']) != CParser::PARSE_SUCCESS) {
+ error(_s('Invalid interval "%1$s".', $interval['delay']));
+
+ return false;
+ }
+ elseif ($time_period_parser->parse($interval['period']) != CParser::PARSE_SUCCESS) {
+ error(_s('Invalid interval "%1$s".', $interval['period']));
+
+ return false;
+ }
+ }
+ else {
+ if ($interval['schedule'] === '') {
+ unset($delay_flex[$i]);
+ continue;
+ }
+
+ if ($scheduling_interval_parser->parse($interval['schedule']) != CParser::PARSE_SUCCESS) {
+ error(_s('Invalid interval "%1$s".', $interval['schedule']));
+
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Get all given delay intervals as string in API format.
+ *
+ * @param string $delay
+ * @param array $delay_flex
+ *
+ * @return string
+ */
+function getDelayWithCustomIntervals(string $delay, array $delay_flex): string {
+ foreach ($delay_flex as $interval) {
+ if ($interval['type'] == ITEM_DELAY_FLEXIBLE) {
+ $delay .= ';'.$interval['delay'].'/'.$interval['period'];
+ }
+ else {
+ $delay .= ';'.$interval['schedule'];
+ }
+ }
+
+ return $delay;
+}
+
+/**
+ * Format tags received via form for API input.
+ *
+ * @param array $tags Array of item tags, as received from form submit.
+ *
+ * @return array
+ */
+function prepareItemTags(array $tags): array {
+ foreach ($tags as $key => $tag) {
+ if ($tag['tag'] === '' && $tag['value'] === '') {
+ unset($tags[$key]);
+ }
+ elseif (array_key_exists('type', $tag) && !($tag['type'] & ZBX_PROPERTY_OWN)) {
+ unset($tags[$key]);
+ }
+ else {
+ unset($tags[$key]['type']);
+ }
+ }
+
+ return $tags;
+}
+
+/**
+ * Format query fields received via form for API input.
+ *
+ * @param array $query_fields
+ *
+ * @return array
+ */
+function prepareItemQueryFields(array $query_fields): array {
+ if ($query_fields) {
+ $_query_fields = [];
+
+ foreach ($query_fields['name'] as $index => $key) {
+ $value = $query_fields['value'][$index];
+ $sortorder = $query_fields['sortorder'][$index];
+
+ if ($key !== '' || $value !== '') {
+ $_query_fields[$sortorder] = [$key => $value];
+ }
+ }
+
+ ksort($_query_fields);
+ $query_fields = array_values($_query_fields);
+ }
+
+ return $query_fields;
+}
+
+/**
+ * Format headers field received via form for API input.
+ *
+ * @param array $headers
+ *
+ * @return array
+ */
+function prepareItemHeaders(array $headers): array {
+ if ($headers) {
+ $_headers = [];
+
+ foreach ($headers['name'] as $i => $name) {
+ $value = $headers['value'][$i];
+
+ if ($name === '' && $value === '') {
+ continue;
+ }
+
+ $_headers[$name] = $value;
+ }
+
+ $headers = $_headers;
+ }
+
+ return $headers;
+}
+
+/**
+ * Format parameters field received via form for API input.
+ *
+ * @param array $parameters
+ *
+ * @return array
+ */
+function prepareItemParameters(array $parameters): array {
+ $_parameters = [];
+
+ if (is_array($parameters) && array_key_exists('name', $parameters)
+ && array_key_exists('value', $parameters)) {
+ foreach ($parameters['name'] as $index => $name) {
+ if (array_key_exists($index, $parameters['value'])
+ && ($name !== '' || $parameters['value'][$index] !== '')) {
+ $_parameters[] = [
+ 'name' => $name,
+ 'value' => $parameters['value'][$index]
+ ];
+ }
+ }
+ }
+
+ return $_parameters;
+}
+
+/**
+ * Get sanitized item fields of given input.
+ *
+ * @param array $input
+ * @param string $input['templateid']
+ * @param int $input['flags']
+ * @param int $input['type']
+ * @param string $input['key_']
+ * @param int $input['value_type']
+ * @param int $input['authtype']
+ * @param int $input['allow_traps']
+ * @param int $input['hosts'][0]['status']
+ *
+ * @return array
+ */
+function getSanitizedItemFields(array $input): array {
+ $field_names = getMainItemFieldNames($input);
+
+ if ($input['flags'] != ZBX_FLAG_DISCOVERY_CREATED) {
+ $field_names = array_merge($field_names, getTypeItemFieldNames($input));
+ $field_names = getConditionalItemFieldNames($field_names, $input);
+ }
+
+ return array_intersect_key($input, array_flip($field_names));
+}
+
+/**
+ * Get main item fields of given input.
+ *
+ * @param array $input
+ * @param string $input['templateid']
+ * @param int $input['flags']
+ *
+ * @return array
+ */
+function getMainItemFieldNames(array $input): array {
+ switch ($input['flags']) {
+ case ZBX_FLAG_DISCOVERY_NORMAL:
+ if ($input['templateid'] == 0) {
+ return ['name', 'type', 'key_', 'value_type', 'units', 'history', 'trends', 'valuemapid',
+ 'inventory_link', 'logtimefmt', 'description', 'status', 'tags', 'preprocessing'
+ ];
+ }
+ else {
+ return ['history', 'trends', 'inventory_link', 'description', 'status', 'tags'];
+ }
+
+ case ZBX_FLAG_DISCOVERY_PROTOTYPE:
+ if ($input['templateid'] == 0) {
+ return ['name', 'type', 'key_', 'value_type', 'units', 'history', 'trends', 'valuemapid', 'logtimefmt',
+ 'description', 'status', 'discover', 'tags', 'preprocessing'
+ ];
+ }
+ else {
+ return ['history', 'trends', 'description', 'status', 'discover', 'tags'];
+ }
+
+ case ZBX_FLAG_DISCOVERY_CREATED:
+ return ['status'];
+ }
+}
+
+/**
+ * Get item field names of the given type and template ID.
+ *
+ * @param array $input
+ * @param string $input['templateid']
+ * @param int $input['type']
+ */
+function getTypeItemFieldNames(array $input): array {
+ switch ($input['type']) {
+ case ITEM_TYPE_ZABBIX:
+ return ['interfaceid', 'delay'];
+
+ case ITEM_TYPE_TRAPPER:
+ return ['trapper_hosts'];
+
+ case ITEM_TYPE_SIMPLE:
+ return ['interfaceid', 'username', 'password', 'delay'];
+
+ case ITEM_TYPE_INTERNAL:
+ return ['delay'];
+
+ case ITEM_TYPE_ZABBIX_ACTIVE:
+ return ['delay'];
+
+ case ITEM_TYPE_EXTERNAL:
+ return ['interfaceid', 'delay'];
+
+ case ITEM_TYPE_DB_MONITOR:
+ return ['username', 'password', 'params', 'delay'];
+
+ case ITEM_TYPE_IPMI:
+ if ($input['templateid'] == 0) {
+ return ['interfaceid', 'ipmi_sensor', 'delay'];
+ }
+ else {
+ return ['interfaceid', 'delay'];
+ }
+
+ case ITEM_TYPE_SSH:
+ return ['interfaceid', 'authtype', 'username', 'publickey', 'privatekey', 'password', 'params', 'delay'];
+
+ case ITEM_TYPE_TELNET:
+ return ['interfaceid', 'username', 'password', 'params', 'delay'];
+
+ case ITEM_TYPE_CALCULATED:
+ return ['params', 'delay'];
+
+ case ITEM_TYPE_JMX:
+ if ($input['templateid'] == 0) {
+ return ['interfaceid', 'jmx_endpoint', 'username', 'password', 'delay'];
+ }
+ else {
+ return ['interfaceid', 'username', 'password', 'delay'];
+ }
+
+ case ITEM_TYPE_SNMPTRAP:
+ return ['interfaceid'];
+
+ case ITEM_TYPE_DEPENDENT:
+ return ['master_itemid'];
+
+ case ITEM_TYPE_HTTPAGENT:
+ if ($input['templateid'] == 0) {
+ return ['url', 'query_fields', 'request_method', 'post_type', 'posts', 'headers', 'status_codes',
+ 'follow_redirects', 'retrieve_mode', 'output_format', 'http_proxy', 'interfaceid', 'authtype',
+ 'username', 'password', 'verify_peer', 'verify_host', 'ssl_cert_file', 'ssl_key_file',
+ 'ssl_key_password', 'timeout', 'delay', 'allow_traps', 'trapper_hosts'
+ ];
+ }
+ else {
+ return ['interfaceid', 'delay', 'allow_traps', 'trapper_hosts'];
+ }
+
+ case ITEM_TYPE_SNMP:
+ if ($input['templateid'] == 0) {
+ return ['interfaceid', 'snmp_oid', 'delay'];
+ }
+ else {
+ return ['interfaceid', 'delay'];
+ }
+
+ case ITEM_TYPE_SCRIPT:
+ if ($input['templateid'] == 0) {
+ return ['parameters', 'params', 'timeout', 'delay'];
+ }
+ else {
+ return ['delay'];
+ }
+ }
+}
+
+/**
+ * Get item field names excluding those that don't match a specific conditions.
+ *
+ * @param array $field_names
+ * @param array $input
+ * @param int $input['type']
+ * @param string $input['key_']
+ * @param int $input['value_type']
+ * @param int $input['authtype']
+ * @param int $input['allow_traps']
+ * @param int $input['hosts'][0]['status']
+ *
+ * @return array
+ */
+function getConditionalItemFieldNames(array $field_names, array $input): array {
+ return array_filter($field_names, static function ($field_name) use ($input): bool {
+ switch ($field_name) {
+ case 'units':
+ case 'trends':
+ return in_array($input['value_type'], [ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64]);
+
+ case 'valuemapid':
+ return in_array($input['value_type'],
+ [ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_UINT64]
+ );
+
+ case 'inventory_link':
+ return in_array($input['value_type'],
+ [ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_TEXT]
+ );
+
+ case 'logtimefmt':
+ return $input['value_type'] == ITEM_VALUE_TYPE_LOG;
+
+ case 'interfaceid':
+ return in_array($input['hosts'][0]['status'], [HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED]);
+
+ case 'username':
+ case 'password':
+ return $input['type'] != ITEM_TYPE_HTTPAGENT || in_array($input['authtype'],
+ [HTTPTEST_AUTH_BASIC, HTTPTEST_AUTH_NTLM, HTTPTEST_AUTH_KERBEROS, HTTPTEST_AUTH_DIGEST]
+ );
+
+ case 'delay':
+ return $input['type'] != ITEM_TYPE_ZABBIX_ACTIVE || strncmp($input['key_'], 'mqtt.get', 8) != 0;
+
+ case 'trapper_hosts':
+ return $input['type'] != ITEM_TYPE_HTTPAGENT || $input['allow_traps'] == HTTPCHECK_ALLOW_TRAPS_ON;
+
+ case 'publickey':
+ case 'privatekey':
+ return $input['authtype'] == ITEM_AUTHTYPE_PUBLICKEY;
+ }
+
+ return true;
+ });
+}