1<?php 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22/** 23 * Convert windows events type constant in to the string representation 24 * 25 * @param int $logtype 26 * @return string 27 */ 28function get_item_logtype_description($logtype) { 29 switch ($logtype) { 30 case ITEM_LOGTYPE_INFORMATION: 31 return _('Information'); 32 case ITEM_LOGTYPE_WARNING: 33 return _('Warning'); 34 case ITEM_LOGTYPE_ERROR: 35 return _('Error'); 36 case ITEM_LOGTYPE_FAILURE_AUDIT: 37 return _('Failure Audit'); 38 case ITEM_LOGTYPE_SUCCESS_AUDIT: 39 return _('Success Audit'); 40 case ITEM_LOGTYPE_CRITICAL: 41 return _('Critical'); 42 case ITEM_LOGTYPE_VERBOSE: 43 return _('Verbose'); 44 default: 45 return _('Unknown'); 46 } 47} 48 49/** 50 * Convert windows events type constant in to the CSS style name 51 * 52 * @param int $logtype 53 * @return string 54 */ 55function get_item_logtype_style($logtype) { 56 switch ($logtype) { 57 case ITEM_LOGTYPE_INFORMATION: 58 case ITEM_LOGTYPE_SUCCESS_AUDIT: 59 case ITEM_LOGTYPE_VERBOSE: 60 return ZBX_STYLE_LOG_INFO_BG; 61 62 case ITEM_LOGTYPE_WARNING: 63 return ZBX_STYLE_LOG_WARNING_BG; 64 65 case ITEM_LOGTYPE_ERROR: 66 case ITEM_LOGTYPE_FAILURE_AUDIT: 67 return ZBX_STYLE_LOG_HIGH_BG; 68 69 case ITEM_LOGTYPE_CRITICAL: 70 return ZBX_STYLE_LOG_DISASTER_BG; 71 72 default: 73 return ZBX_STYLE_LOG_NA_BG; 74 } 75} 76 77/** 78 * Get item type string name by item type number, or array of all item types if null passed 79 * 80 * @param int|null $type 81 * @return array|string 82 */ 83function item_type2str($type = null) { 84 $types = [ 85 ITEM_TYPE_ZABBIX => _('Zabbix agent'), 86 ITEM_TYPE_ZABBIX_ACTIVE => _('Zabbix agent (active)'), 87 ITEM_TYPE_SIMPLE => _('Simple check'), 88 ITEM_TYPE_SNMPV1 => _('SNMPv1 agent'), 89 ITEM_TYPE_SNMPV2C => _('SNMPv2 agent'), 90 ITEM_TYPE_SNMPV3 => _('SNMPv3 agent'), 91 ITEM_TYPE_SNMPTRAP => _('SNMP trap'), 92 ITEM_TYPE_INTERNAL => _('Zabbix internal'), 93 ITEM_TYPE_TRAPPER => _('Zabbix trapper'), 94 ITEM_TYPE_AGGREGATE => _('Zabbix aggregate'), 95 ITEM_TYPE_EXTERNAL => _('External check'), 96 ITEM_TYPE_DB_MONITOR => _('Database monitor'), 97 ITEM_TYPE_IPMI => _('IPMI agent'), 98 ITEM_TYPE_SSH => _('SSH agent'), 99 ITEM_TYPE_TELNET => _('TELNET agent'), 100 ITEM_TYPE_JMX => _('JMX agent'), 101 ITEM_TYPE_CALCULATED => _('Calculated'), 102 ITEM_TYPE_HTTPTEST => _('Web monitoring') 103 ]; 104 if (is_null($type)) { 105 return $types; 106 } 107 elseif (isset($types[$type])) { 108 return $types[$type]; 109 } 110 else { 111 return _('Unknown'); 112 } 113} 114 115/** 116 * Returns human readable an item value type 117 * 118 * @param int $valueType 119 * 120 * @return string 121 */ 122function itemValueTypeString($valueType) { 123 switch ($valueType) { 124 case ITEM_VALUE_TYPE_UINT64: 125 return _('Numeric (unsigned)'); 126 case ITEM_VALUE_TYPE_FLOAT: 127 return _('Numeric (float)'); 128 case ITEM_VALUE_TYPE_STR: 129 return _('Character'); 130 case ITEM_VALUE_TYPE_LOG: 131 return _('Log'); 132 case ITEM_VALUE_TYPE_TEXT: 133 return _('Text'); 134 } 135 return _('Unknown'); 136} 137 138function item_data_type2str($type = null) { 139 $types = [ 140 ITEM_DATA_TYPE_BOOLEAN => _('Boolean'), 141 ITEM_DATA_TYPE_OCTAL => _('Octal'), 142 ITEM_DATA_TYPE_DECIMAL => _('Decimal'), 143 ITEM_DATA_TYPE_HEXADECIMAL => _('Hexadecimal') 144 ]; 145 if (is_null($type)) { 146 return $types; 147 } 148 elseif (isset($types[$type])) { 149 return $types[$type]; 150 } 151 else { 152 return _('Unknown'); 153 } 154} 155 156function item_status2str($type = null) { 157 $types = [ 158 ITEM_STATUS_ACTIVE => _('Enabled'), 159 ITEM_STATUS_DISABLED => _('Disabled') 160 ]; 161 if (is_null($type)) { 162 return $types; 163 } 164 elseif (isset($types[$type])) { 165 return $types[$type]; 166 } 167 else { 168 return _('Unknown'); 169 } 170} 171 172/** 173 * Returns the names of supported item states. 174 * 175 * If the $state parameter is passed, returns the name of the specific state, otherwise - returns an array of all 176 * supported states. 177 * 178 * @param string $state 179 * 180 * @return array|string 181 */ 182function itemState($state = null) { 183 $states = [ 184 ITEM_STATE_NORMAL => _('Normal'), 185 ITEM_STATE_NOTSUPPORTED => _('Not supported') 186 ]; 187 188 if ($state === null) { 189 return $states; 190 } 191 elseif (isset($states[$state])) { 192 return $states[$state]; 193 } 194 else { 195 return _('Unknown'); 196 } 197} 198 199/** 200 * Returns the text indicating the items status and state. If the $state parameter is not given, only the status of 201 * the item will be taken into account. 202 * 203 * @param int $status 204 * @param int $state 205 * 206 * @return string 207 */ 208function itemIndicator($status, $state = null) { 209 if ($status == ITEM_STATUS_ACTIVE) { 210 return ($state == ITEM_STATE_NOTSUPPORTED) ? _('Not supported') : _('Enabled'); 211 } 212 elseif ($status == ITEM_STATUS_DISABLED) { 213 return _('Disabled'); 214 } 215 216 return _('Unknown'); 217} 218 219/** 220 * Returns the CSS class for the items status and state indicator. If the $state parameter is not given, only the status of 221 * the item will be taken into account. 222 * 223 * @param int $status 224 * @param int $state 225 * 226 * @return string 227 */ 228function itemIndicatorStyle($status, $state = null) { 229 if ($status == ITEM_STATUS_ACTIVE) { 230 return ($state == ITEM_STATE_NOTSUPPORTED) ? 231 ZBX_STYLE_GREY : 232 ZBX_STYLE_GREEN; 233 } 234 elseif ($status == ITEM_STATUS_DISABLED) { 235 return ZBX_STYLE_RED; 236 } 237 238 return ZBX_STYLE_GREY; 239} 240 241/** 242 * Orders items by both status and state. Items are sorted in the following order: enabled, disabled, not supported. 243 * 244 * Keep in sync with orderTriggersByStatus(). 245 * 246 * @param array $items 247 * @param string $sortorder 248 */ 249function orderItemsByStatus(array &$items, $sortorder = ZBX_SORT_UP) { 250 $sort = []; 251 252 foreach ($items as $key => $item) { 253 if ($item['status'] == ITEM_STATUS_ACTIVE) { 254 $statusOrder = ($item['state'] == ITEM_STATE_NOTSUPPORTED) ? 2 : 0; 255 } 256 elseif ($item['status'] == ITEM_STATUS_DISABLED) { 257 $statusOrder = 1; 258 } 259 260 $sort[$key] = $statusOrder; 261 } 262 263 if ($sortorder == ZBX_SORT_UP) { 264 asort($sort); 265 } 266 else { 267 arsort($sort); 268 } 269 270 $sortedItems = []; 271 foreach ($sort as $key => $val) { 272 $sortedItems[$key] = $items[$key]; 273 } 274 $items = $sortedItems; 275} 276 277/** 278 * Returns the name of the given interface type. Items "status" and "state" properties must be defined. 279 * 280 * @param int $type 281 * 282 * @return null 283 */ 284function interfaceType2str($type) { 285 $interfaceGroupLabels = [ 286 INTERFACE_TYPE_AGENT => _('Agent'), 287 INTERFACE_TYPE_SNMP => _('SNMP'), 288 INTERFACE_TYPE_JMX => _('JMX'), 289 INTERFACE_TYPE_IPMI => _('IPMI'), 290 ]; 291 292 return isset($interfaceGroupLabels[$type]) ? $interfaceGroupLabels[$type] : null; 293} 294 295function itemTypeInterface($type = null) { 296 $types = [ 297 ITEM_TYPE_SNMPV1 => INTERFACE_TYPE_SNMP, 298 ITEM_TYPE_SNMPV2C => INTERFACE_TYPE_SNMP, 299 ITEM_TYPE_SNMPV3 => INTERFACE_TYPE_SNMP, 300 ITEM_TYPE_SNMPTRAP => INTERFACE_TYPE_SNMP, 301 ITEM_TYPE_IPMI => INTERFACE_TYPE_IPMI, 302 ITEM_TYPE_ZABBIX => INTERFACE_TYPE_AGENT, 303 ITEM_TYPE_SIMPLE => INTERFACE_TYPE_ANY, 304 ITEM_TYPE_EXTERNAL => INTERFACE_TYPE_ANY, 305 ITEM_TYPE_SSH => INTERFACE_TYPE_ANY, 306 ITEM_TYPE_TELNET => INTERFACE_TYPE_ANY, 307 ITEM_TYPE_JMX => INTERFACE_TYPE_JMX 308 ]; 309 if (is_null($type)) { 310 return $types; 311 } 312 elseif (isset($types[$type])) { 313 return $types[$type]; 314 } 315 else { 316 return false; 317 } 318} 319 320function update_item_status($itemids, $status) { 321 zbx_value2array($itemids); 322 $result = true; 323 324 $db_items = DBselect('SELECT i.* FROM items i WHERE '.dbConditionInt('i.itemid', $itemids)); 325 while ($item = DBfetch($db_items)) { 326 $old_status = $item['status']; 327 if ($status != $old_status) { 328 $result &= DBexecute( 329 'UPDATE items SET status='.zbx_dbstr($status).' WHERE itemid='.zbx_dbstr($item['itemid']) 330 ); 331 if ($result) { 332 $host = get_host_by_hostid($item['hostid']); 333 $item_new = get_item_by_itemid($item['itemid']); 334 add_audit_ext(AUDIT_ACTION_UPDATE, AUDIT_RESOURCE_ITEM, $item['itemid'], $host['host'].NAME_DELIMITER.$item['name'], 'items', $item, $item_new); 335 } 336 } 337 } 338 return $result; 339} 340 341function copyItemsToHosts($srcItemIds, $dstHostIds) { 342 $srcItems = API::Item()->get([ 343 'itemids' => $srcItemIds, 344 'output' => [ 345 'type', 'snmp_community', 'snmp_oid', 'name', 'key_', 'delay', 'history', 'trends', 'status', 'value_type', 346 'trapper_hosts', 'units', 'multiplier', 'delta', 'snmpv3_contextname', 'snmpv3_securityname', 347 'snmpv3_securitylevel', 'snmpv3_authprotocol', 'snmpv3_authpassphrase', 'snmpv3_privprotocol', 348 'snmpv3_privpassphrase', 'formula', 'logtimefmt', 'valuemapid', 'delay_flex', 'params', 'ipmi_sensor', 349 'data_type', 'authtype', 'username', 'password', 'publickey', 'privatekey', 'flags', 'port', 350 'description', 'inventory_link' 351 ], 352 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL], 353 'selectApplications' => ['applicationid'] 354 ]); 355 356 $dstHosts = API::Host()->get([ 357 'output' => ['hostid', 'host', 'status'], 358 'selectInterfaces' => ['interfaceid', 'type', 'main'], 359 'hostids' => $dstHostIds, 360 'preservekeys' => true, 361 'nopermissions' => true, 362 'templated_hosts' => true 363 ]); 364 365 foreach ($dstHosts as $dstHost) { 366 $interfaceids = []; 367 foreach ($dstHost['interfaces'] as $interface) { 368 if ($interface['main'] == 1) { 369 $interfaceids[$interface['type']] = $interface['interfaceid']; 370 } 371 } 372 foreach ($srcItems as &$srcItem) { 373 if ($dstHost['status'] != HOST_STATUS_TEMPLATE) { 374 $type = itemTypeInterface($srcItem['type']); 375 376 if ($type == INTERFACE_TYPE_ANY) { 377 foreach ([INTERFACE_TYPE_AGENT, INTERFACE_TYPE_SNMP, INTERFACE_TYPE_JMX, INTERFACE_TYPE_IPMI] as $itype) { 378 if (isset($interfaceids[$itype])) { 379 $srcItem['interfaceid'] = $interfaceids[$itype]; 380 break; 381 } 382 } 383 } 384 elseif ($type !== false) { 385 if (!isset($interfaceids[$type])) { 386 error(_s('Cannot find host interface on "%1$s" for item key "%2$s".', $dstHost['host'], $srcItem['key_'])); 387 return false; 388 } 389 $srcItem['interfaceid'] = $interfaceids[$type]; 390 } 391 } 392 unset($srcItem['itemid']); 393 $srcItem['hostid'] = $dstHost['hostid']; 394 $srcItem['applications'] = get_same_applications_for_host(zbx_objectValues($srcItem['applications'], 'applicationid'), $dstHost['hostid']); 395 } 396 unset($srcItem); 397 398 if (!API::Item()->create($srcItems)) { 399 return false; 400 } 401 } 402 return true; 403} 404 405function copyItems($srcHostId, $dstHostId) { 406 $srcItems = API::Item()->get([ 407 'hostids' => $srcHostId, 408 'output' => [ 409 'type', 'snmp_community', 'snmp_oid', 'name', 'key_', 'delay', 'history', 'trends', 'status', 'value_type', 410 'trapper_hosts', 'units', 'multiplier', 'delta', 'snmpv3_contextname', 'snmpv3_securityname', 411 'snmpv3_securitylevel', 'snmpv3_authprotocol', 'snmpv3_authpassphrase', 'snmpv3_privprotocol', 412 'snmpv3_privpassphrase', 'formula', 'logtimefmt', 'valuemapid', 'delay_flex', 'params', 'ipmi_sensor', 413 'data_type', 'authtype', 'username', 'password', 'publickey', 'privatekey', 'flags', 'port', 414 'description', 'inventory_link' 415 ], 416 'inherited' => false, 417 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL], 418 'selectApplications' => ['applicationid'] 419 ]); 420 $dstHosts = API::Host()->get([ 421 'output' => ['hostid', 'host', 'status'], 422 'selectInterfaces' => ['interfaceid', 'type', 'main'], 423 'hostids' => $dstHostId, 424 'preservekeys' => true, 425 'nopermissions' => true, 426 'templated_hosts' => true 427 ]); 428 $dstHost = reset($dstHosts); 429 430 foreach ($srcItems as &$srcItem) { 431 if ($dstHost['status'] != HOST_STATUS_TEMPLATE) { 432 // find a matching interface 433 $interface = CItem::findInterfaceForItem($srcItem, $dstHost['interfaces']); 434 if ($interface) { 435 $srcItem['interfaceid'] = $interface['interfaceid']; 436 } 437 // no matching interface found, throw an error 438 elseif ($interface !== false) { 439 error(_s('Cannot find host interface on "%1$s" for item key "%2$s".', $dstHost['host'], $srcItem['key_'])); 440 } 441 } 442 unset($srcItem['itemid']); 443 unset($srcItem['templateid']); 444 $srcItem['hostid'] = $dstHostId; 445 $srcItem['applications'] = get_same_applications_for_host(zbx_objectValues($srcItem['applications'], 'applicationid'), $dstHostId); 446 } 447 unset($srcItem); 448 449 return API::Item()->create($srcItems); 450} 451 452/** 453 * Copy applications to a different host. 454 * 455 * @param string $source_hostid 456 * @param string $destination_hostid 457 * 458 * @return bool 459 */ 460function copyApplications($source_hostid, $destination_hostid) { 461 $applications_to_create = API::Application()->get([ 462 'output' => ['name'], 463 'hostids' => [$source_hostid], 464 'inherited' => false, 465 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL] 466 ]); 467 468 if (!$applications_to_create) { 469 return true; 470 } 471 472 foreach ($applications_to_create as &$application) { 473 $application['hostid'] = $destination_hostid; 474 unset($application['applicationid'], $application['templateid']); 475 } 476 unset($application); 477 478 return (bool) API::Application()->create($applications_to_create); 479} 480 481function activate_item($itemids) { 482 zbx_value2array($itemids); 483 484 // first update status for child items 485 $child_items = []; 486 $db_items = DBselect('SELECT i.itemid,i.hostid FROM items i WHERE '.dbConditionInt('i.templateid', $itemids)); 487 while ($item = DBfetch($db_items)) { 488 $child_items[$item['itemid']] = $item['itemid']; 489 } 490 if (!empty($child_items)) { 491 activate_item($child_items); // Recursion !!! 492 } 493 return update_item_status($itemids, ITEM_STATUS_ACTIVE); 494} 495 496function disable_item($itemids) { 497 zbx_value2array($itemids); 498 499 // first update status for child items 500 $chd_items = []; 501 $db_tmp_items = DBselect('SELECT i.itemid,i.hostid FROM items i WHERE '.dbConditionInt('i.templateid', $itemids)); 502 while ($db_tmp_item = DBfetch($db_tmp_items)) { 503 $chd_items[$db_tmp_item['itemid']] = $db_tmp_item['itemid']; 504 } 505 if (!empty($chd_items)) { 506 disable_item($chd_items); // Recursion !!! 507 } 508 return update_item_status($itemids, ITEM_STATUS_DISABLED); 509} 510 511function get_item_by_itemid($itemid) { 512 $db_items = DBfetch(DBselect('SELECT i.* FROM items i WHERE i.itemid='.zbx_dbstr($itemid))); 513 if ($db_items) { 514 return $db_items; 515 } 516 error(_s('No item with itemid="%1$s".', $itemid)); 517 return false; 518} 519 520function get_item_by_itemid_limited($itemid) { 521 $row = DBfetch(DBselect( 522 'SELECT i.itemid,i.interfaceid,i.name,i.key_,i.hostid,i.delay,i.history,i.status,i.type,i.lifetime,'. 523 'i.snmp_community,i.snmp_oid,i.value_type,i.data_type,i.trapper_hosts,i.port,i.units,i.multiplier,'. 524 'i.delta,i.snmpv3_contextname,i.snmpv3_securityname,i.snmpv3_securitylevel,i.snmpv3_authprotocol,'. 525 'i.snmpv3_authpassphrase,i.snmpv3_privprotocol,i.snmpv3_privpassphrase,i.formula,i.trends,i.logtimefmt,'. 526 'i.valuemapid,i.delay_flex,i.params,i.ipmi_sensor,i.templateid,i.authtype,i.username,i.password,'. 527 'i.publickey,i.privatekey,i.flags,i.description,i.inventory_link'. 528 ' FROM items i'. 529 ' WHERE i.itemid='.zbx_dbstr($itemid))); 530 if ($row) { 531 return $row; 532 } 533 error(_s('No item with itemid "%1$s".', $itemid)); 534 return false; 535} 536 537/** 538 * Description: 539 * Replace items for specified host 540 * 541 * Comments: 542 * $error= true : rise Error if item doesn't exist (error generated), false: special processing (NO error generated) 543 */ 544function get_same_item_for_host($item, $dest_hostids) { 545 $return_array = is_array($dest_hostids); 546 zbx_value2array($dest_hostids); 547 548 if (!is_array($item)) { 549 $itemid = $item; 550 } 551 elseif (isset($item['itemid'])) { 552 $itemid = $item['itemid']; 553 } 554 555 $same_item = null; 556 $same_items = []; 557 558 if (isset($itemid)) { 559 $db_items = DBselect( 560 'SELECT src.*'. 561 ' FROM items src,items dest'. 562 ' WHERE dest.itemid='.zbx_dbstr($itemid). 563 ' AND src.key_=dest.key_'. 564 ' AND '.dbConditionInt('src.hostid', $dest_hostids) 565 ); 566 while ($db_item = DBfetch($db_items)) { 567 if (is_array($item)) { 568 $same_item = $db_item; 569 $same_items[$db_item['itemid']] = $db_item; 570 } 571 else { 572 $same_item = $db_item['itemid']; 573 $same_items[$db_item['itemid']] = $db_item['itemid']; 574 } 575 } 576 if ($return_array) { 577 return $same_items; 578 } 579 else { 580 return $same_item; 581 } 582 } 583 return false; 584} 585 586function get_realhost_by_itemid($itemid) { 587 $item = get_item_by_itemid($itemid); 588 if ($item['templateid'] <> 0) { 589 return get_realhost_by_itemid($item['templateid']); // attention recursion! 590 } 591 return get_host_by_itemid($itemid); 592} 593 594function fillItemsWithChildTemplates(&$items) { 595 $processSecondLevel = false; 596 $dbItems = DBselect('SELECT i.itemid,i.templateid FROM items i WHERE '.dbConditionInt('i.itemid', zbx_objectValues($items, 'templateid'))); 597 while ($dbItem = DBfetch($dbItems)) { 598 foreach ($items as $itemid => $item) { 599 if ($item['templateid'] == $dbItem['itemid'] && !empty($dbItem['templateid'])) { 600 $items[$itemid]['templateid'] = $dbItem['templateid']; 601 $processSecondLevel = true; 602 } 603 } 604 } 605 if ($processSecondLevel) { 606 fillItemsWithChildTemplates($items); // attention recursion! 607 } 608} 609 610function get_realrule_by_itemid_and_hostid($itemid, $hostid) { 611 $item = get_item_by_itemid($itemid); 612 if (bccomp($hostid,$item['hostid']) == 0) { 613 return $item['itemid']; 614 } 615 if ($item['templateid'] <> 0) { 616 return get_realrule_by_itemid_and_hostid($item['templateid'], $hostid); 617 } 618 return $item['itemid']; 619} 620 621/** 622 * Retrieve overview table object for items. 623 * 624 * @param array $hostIds 625 * @param array|null $applicationIds IDs of applications to filter items by 626 * @param int $viewMode 627 * 628 * @return CTableInfo 629 */ 630function getItemsDataOverview($hostIds, array $applicationIds = null, $viewMode) { 631 $sqlFrom = ''; 632 $sqlWhere = ''; 633 634 if ($applicationIds !== null) { 635 $sqlFrom = 'items_applications ia,'; 636 $sqlWhere = ' AND i.itemid=ia.itemid AND '.dbConditionInt('ia.applicationid', $applicationIds); 637 } 638 639 $dbItems = DBfetchArray(DBselect( 640 'SELECT DISTINCT h.hostid,h.name AS hostname,i.itemid,i.key_,i.value_type,i.units,'. 641 'i.name,t.priority,i.valuemapid,t.value AS tr_value,t.triggerid'. 642 ' FROM hosts h,'.$sqlFrom.'items i'. 643 ' LEFT JOIN functions f ON f.itemid=i.itemid'. 644 ' LEFT JOIN triggers t ON t.triggerid=f.triggerid AND t.status='.TRIGGER_STATUS_ENABLED. 645 ' WHERE '.dbConditionInt('h.hostid', $hostIds). 646 ' AND h.status='.HOST_STATUS_MONITORED. 647 ' AND h.hostid=i.hostid'. 648 ' AND i.status='.ITEM_STATUS_ACTIVE. 649 ' AND '.dbConditionInt('i.flags', [ZBX_FLAG_DISCOVERY_NORMAL, ZBX_FLAG_DISCOVERY_CREATED]). 650 $sqlWhere 651 )); 652 653 $dbItems = CMacrosResolverHelper::resolveItemNames($dbItems); 654 655 CArrayHelper::sort($dbItems, [ 656 ['field' => 'name_expanded', 'order' => ZBX_SORT_UP], 657 ['field' => 'itemid', 'order' => ZBX_SORT_UP] 658 ]); 659 660 // fetch latest values 661 $history = Manager::History()->getLast(zbx_toHash($dbItems, 'itemid'), 1, ZBX_HISTORY_PERIOD); 662 663 // fetch data for the host JS menu 664 $hosts = API::Host()->get([ 665 'output' => ['name', 'hostid', 'status'], 666 'monitored_hosts' => true, 667 'hostids' => $hostIds, 668 'with_monitored_items' => true, 669 'preservekeys' => true, 670 'selectGraphs' => API_OUTPUT_COUNT, 671 'selectScreens' => ($viewMode == STYLE_LEFT) ? API_OUTPUT_COUNT : null 672 ]); 673 674 $items = []; 675 $item_counter = []; 676 $host_items = []; 677 foreach ($dbItems as $dbItem) { 678 $item_name = $dbItem['name_expanded']; 679 $host_name = $dbItem['hostname']; 680 $hostNames[$dbItem['hostid']] = $host_name; 681 682 if (!array_key_exists($host_name, $item_counter)) { 683 $item_counter[$host_name] = []; 684 } 685 686 if (!array_key_exists($item_name, $item_counter[$host_name])) { 687 $item_counter[$host_name][$item_name] = 0; 688 } 689 690 if (!array_key_exists($item_name, $host_items) || !array_key_exists($host_name, $host_items[$item_name])) { 691 $host_items[$item_name][$host_name] = []; 692 } 693 694 // a little tricky check for attempt to overwrite active trigger (value=1) with 695 // inactive or active trigger with lower priority. 696 if (!array_key_exists($dbItem['itemid'], $host_items[$item_name][$host_name]) 697 || (($host_items[$item_name][$host_name][$dbItem['itemid']]['tr_value'] == TRIGGER_VALUE_FALSE && $dbItem['tr_value'] == TRIGGER_VALUE_TRUE) 698 || (($host_items[$item_name][$host_name][$dbItem['itemid']]['tr_value'] == TRIGGER_VALUE_FALSE || $dbItem['tr_value'] == TRIGGER_VALUE_TRUE) 699 && $dbItem['priority'] > $host_items[$item_name][$host_name][$dbItem['itemid']]['severity']))) { 700 701 if (array_key_exists($dbItem['itemid'], $host_items[$item_name][$host_name])) { 702 $item_place = $host_items[$item_name][$host_name][$dbItem['itemid']]['item_place']; 703 } 704 else { 705 $item_place = $item_counter[$host_name][$item_name]; 706 $item_counter[$host_name][$item_name]++; 707 } 708 709 $items[$item_name][$item_place][$host_name] = [ 710 'itemid' => $dbItem['itemid'], 711 'value_type' => $dbItem['value_type'], 712 'value' => isset($history[$dbItem['itemid']]) ? $history[$dbItem['itemid']][0]['value'] : null, 713 'units' => $dbItem['units'], 714 'valuemapid' => $dbItem['valuemapid'], 715 'severity' => $dbItem['priority'], 716 'tr_value' => $dbItem['tr_value'], 717 'triggerid' => $dbItem['triggerid'], 718 'item_place' => $item_place 719 ]; 720 721 $host_items[$item_name][$host_name][$dbItem['itemid']] = $items[$item_name][$item_place][$host_name]; 722 } 723 } 724 725 $table = new CTableInfo(); 726 if (empty($hostNames)) { 727 return $table; 728 } 729 $table->makeVerticalRotation(); 730 731 order_result($hostNames); 732 733 if ($viewMode == STYLE_TOP) { 734 $header = [_('Items')]; 735 foreach ($hostNames as $hostName) { 736 $header[] = (new CColHeader($hostName))->addClass('vertical_rotation'); 737 } 738 $table->setHeader($header); 739 740 foreach ($items as $item_name => $item_data) { 741 foreach ($item_data as $ithosts) { 742 $tableRow = [nbsp($item_name)]; 743 foreach ($hostNames as $hostName) { 744 $tableRow = getItemDataOverviewCells($tableRow, $ithosts, $hostName); 745 } 746 $table->addRow($tableRow); 747 } 748 } 749 } 750 else { 751 $scripts = API::Script()->getScriptsByHosts(zbx_objectValues($hosts, 'hostid')); 752 753 $header = [_('Hosts')]; 754 foreach ($items as $item_name => $item_data) { 755 foreach ($item_data as $ithosts) { 756 $header[] = (new CColHeader($item_name))->addClass('vertical_rotation'); 757 } 758 } 759 $table->setHeader($header); 760 761 foreach ($hostNames as $hostId => $hostName) { 762 $host = $hosts[$hostId]; 763 764 $name = (new CSpan($host['name'])) 765 ->addClass(ZBX_STYLE_LINK_ACTION) 766 ->setMenuPopup(CMenuPopupHelper::getHost($host, $scripts[$hostId])); 767 768 $tableRow = [(new CCol($name))->addClass(ZBX_STYLE_NOWRAP)]; 769 foreach ($items as $item_data) { 770 foreach ($item_data as $ithosts) { 771 $tableRow = getItemDataOverviewCells($tableRow, $ithosts, $hostName); 772 } 773 } 774 $table->addRow($tableRow); 775 } 776 } 777 778 return $table; 779} 780 781function getItemDataOverviewCells($tableRow, $ithosts, $hostName) { 782 $ack = null; 783 $css = ''; 784 $value = UNKNOWN_VALUE; 785 786 if (isset($ithosts[$hostName])) { 787 $item = $ithosts[$hostName]; 788 789 if ($item['tr_value'] == TRIGGER_VALUE_TRUE) { 790 $css = getSeverityStyle($item['severity']); 791 792 // Display event acknowledgement. 793 $config = select_config(); 794 if ($config['event_ack_enable']) { 795 $ack = get_last_event_by_triggerid($item['triggerid']); 796 $ack = ($ack['acknowledged'] == 1) 797 ? [SPACE, (new CSpan())->addClass(ZBX_STYLE_ICON_ACKN)] 798 : null; 799 } 800 } 801 802 if ($item['value'] !== null) { 803 $value = formatHistoryValue($item['value'], $item); 804 } 805 } 806 807 if ($value != UNKNOWN_VALUE) { 808 $value = $value; 809 } 810 811 $column = (new CCol([$value, $ack]))->addClass($css); 812 813 if (isset($ithosts[$hostName])) { 814 $column 815 ->setMenuPopup(CMenuPopupHelper::getHistory($item)) 816 ->addClass(ZBX_STYLE_CURSOR_POINTER) 817 ->addClass(ZBX_STYLE_NOWRAP); 818 } 819 820 $tableRow[] = $column; 821 822 return $tableRow; 823} 824 825/** 826 * Get same application IDs on destination host and return array with keys as source application IDs 827 * and values as destination application IDs. 828 * 829 * Comments: !!! Don't forget sync code with C !!! 830 * 831 * @param array $applicationIds 832 * @param string $hostId 833 * 834 * @return array 835 */ 836function get_same_applications_for_host(array $applicationIds, $hostId) { 837 $applications = []; 838 839 $dbApplications = DBselect( 840 'SELECT a1.applicationid AS dstappid,a2.applicationid AS srcappid'. 841 ' FROM applications a1,applications a2'. 842 ' WHERE a1.name=a2.name'. 843 ' AND a1.hostid='.zbx_dbstr($hostId). 844 ' AND '.dbConditionInt('a2.applicationid', $applicationIds) 845 ); 846 847 while ($dbApplication = DBfetch($dbApplications)) { 848 $applications[$dbApplication['srcappid']] = $dbApplication['dstappid']; 849 } 850 851 return $applications; 852} 853 854/****************************************************************************** 855 * * 856 * Comments: !!! Don't forget sync code with C !!! * 857 * * 858 ******************************************************************************/ 859function get_applications_by_itemid($itemids, $field = 'applicationid') { 860 zbx_value2array($itemids); 861 $result = []; 862 $db_applications = DBselect( 863 'SELECT DISTINCT app.'.$field.' AS result'. 864 ' FROM applications app,items_applications ia'. 865 ' WHERE app.applicationid=ia.applicationid'. 866 ' AND '.dbConditionInt('ia.itemid', $itemids) 867 ); 868 while ($db_application = DBfetch($db_applications)) { 869 array_push($result, $db_application['result']); 870 } 871 872 return $result; 873} 874 875/** 876 * Clear item history and trends by provided item IDs. 877 * 878 * @param array $itemIds 879 * 880 * @return bool 881 */ 882function deleteHistoryByItemIds(array $itemIds) { 883 $result = DBexecute('DELETE FROM trends WHERE '.dbConditionInt('itemid', $itemIds)); 884 $result = ($result && DBexecute('DELETE FROM trends_uint WHERE '.dbConditionInt('itemid', $itemIds))); 885 $result = ($result && DBexecute('DELETE FROM history_text WHERE '.dbConditionInt('itemid', $itemIds))); 886 $result = ($result && DBexecute('DELETE FROM history_log WHERE '.dbConditionInt('itemid', $itemIds))); 887 $result = ($result && DBexecute('DELETE FROM history_uint WHERE '.dbConditionInt('itemid', $itemIds))); 888 $result = ($result && DBexecute('DELETE FROM history_str WHERE '.dbConditionInt('itemid', $itemIds))); 889 $result = ($result && DBexecute('DELETE FROM history WHERE '.dbConditionInt('itemid', $itemIds))); 890 891 return $result; 892} 893 894/** 895 * Format history value. 896 * First format the value according to the configuration of the item. Then apply the value mapping to the formatted (!) 897 * value. 898 * 899 * @param mixed $value 900 * @param array $item 901 * @param int $item['value_type'] type of the value: ITEM_VALUE_TYPE_FLOAT, ITEM_VALUE_TYPE_UINT64, ... 902 * @param string $item['units'] units of item 903 * @param int $item['valuemapid'] id of mapping set of values 904 * @param bool $trim 905 * 906 * @return string 907 */ 908function formatHistoryValue($value, array $item, $trim = true) { 909 $mapping = false; 910 911 // format value 912 if ($item['value_type'] == ITEM_VALUE_TYPE_FLOAT || $item['value_type'] == ITEM_VALUE_TYPE_UINT64) { 913 $value = convert_units([ 914 'value' => $value, 915 'units' => $item['units'] 916 ]); 917 } 918 elseif ($item['value_type'] != ITEM_VALUE_TYPE_STR 919 && $item['value_type'] != ITEM_VALUE_TYPE_TEXT 920 && $item['value_type'] != ITEM_VALUE_TYPE_LOG) { 921 922 $value = _('Unknown value type'); 923 } 924 925 // apply value mapping 926 switch ($item['value_type']) { 927 case ITEM_VALUE_TYPE_STR: 928 $mapping = getMappedValue($value, $item['valuemapid']); 929 // break; is not missing here 930 case ITEM_VALUE_TYPE_TEXT: 931 case ITEM_VALUE_TYPE_LOG: 932 if ($trim && mb_strlen($value) > 20) { 933 $value = mb_substr($value, 0, 20).'...'; 934 } 935 936 if ($mapping !== false) { 937 $value = $mapping.' ('.$value.')'; 938 } 939 break; 940 default: 941 $value = applyValueMap($value, $item['valuemapid']); 942 } 943 944 return $value; 945} 946 947/** 948 * Retrieves from DB historical data for items and applies functional calculations. 949 * If fails for some reason, returns UNRESOLVED_MACRO_STRING. 950 * 951 * @param array $item 952 * @param string $item['value_type'] type of item, allowed: ITEM_VALUE_TYPE_FLOAT and ITEM_VALUE_TYPE_UINT64 953 * @param string $item['itemid'] ID of item 954 * @param string $item['units'] units of item 955 * @param string $function function to apply to time period from param, allowed: min, max and avg 956 * @param string $parameter formatted parameter for function, example: "2w" meaning 2 weeks 957 * 958 * @return string item functional value from history 959 */ 960function getItemFunctionalValue($item, $function, $parameter) { 961 // check whether function is allowed 962 if (!in_array($function, ['min', 'max', 'avg']) || $parameter === '') { 963 return UNRESOLVED_MACRO_STRING; 964 } 965 966 $parameter = convertFunctionValue($parameter); 967 968 if (bccomp($parameter, 0) == 0) { 969 return UNRESOLVED_MACRO_STRING; 970 } 971 972 // allowed item types for min, max and avg function 973 $historyTables = [ITEM_VALUE_TYPE_FLOAT => 'history', ITEM_VALUE_TYPE_UINT64 => 'history_uint']; 974 975 if (!isset($historyTables[$item['value_type']])) { 976 return UNRESOLVED_MACRO_STRING; 977 } 978 else { 979 // search for item function data in DB corresponding history table 980 $result = DBselect( 981 'SELECT '.$function.'(value) AS value'. 982 ' FROM '.$historyTables[$item['value_type']]. 983 ' WHERE clock>'.(time() - $parameter). 984 ' AND itemid='.zbx_dbstr($item['itemid']). 985 ' HAVING COUNT(*)>0' // necessary because DBselect() return 0 if empty data set, for graph templates 986 ); 987 if ($row = DBfetch($result)) { 988 return convert_units(['value' => $row['value'], 'units' => $item['units']]); 989 } 990 // no data in history 991 else { 992 return UNRESOLVED_MACRO_STRING; 993 } 994 } 995} 996 997/** 998 * Returns the history value of the item at the given time. If no value exists at the given time, the function 999 * will return the previous value. 1000 * 1001 * The $db_item parameter must have the value_type and itemid properties set. 1002 * 1003 * @param array $db_item 1004 * @param int $clock 1005 * @param int $ns 1006 * 1007 * @return string 1008 */ 1009function item_get_history($db_item, $clock, $ns) { 1010 $value = null; 1011 1012 $table = CHistoryManager::getTableName($db_item['value_type']); 1013 1014 $sql = 'SELECT value'. 1015 ' FROM '.$table. 1016 ' WHERE itemid='.zbx_dbstr($db_item['itemid']). 1017 ' AND clock='.zbx_dbstr($clock). 1018 ' AND ns='.zbx_dbstr($ns); 1019 if (null != ($row = DBfetch(DBselect($sql, 1)))) { 1020 $value = $row['value']; 1021 } 1022 if ($value != null) { 1023 return $value; 1024 } 1025 1026 $max_clock = 0; 1027 1028 $sql = 'SELECT DISTINCT clock'. 1029 ' FROM '.$table. 1030 ' WHERE itemid='.zbx_dbstr($db_item['itemid']). 1031 ' AND clock='.zbx_dbstr($clock). 1032 ' AND ns<'.zbx_dbstr($ns); 1033 if (null != ($row = DBfetch(DBselect($sql)))) { 1034 $max_clock = $row['clock']; 1035 } 1036 if ($max_clock == 0) { 1037 $sql = 'SELECT MAX(clock) AS clock'. 1038 ' FROM '.$table. 1039 ' WHERE itemid='.zbx_dbstr($db_item['itemid']). 1040 ' AND clock<'.zbx_dbstr($clock). 1041 (ZBX_HISTORY_PERIOD ? ' AND clock>='.zbx_dbstr($clock - ZBX_HISTORY_PERIOD) : ''); 1042 if (null != ($row = DBfetch(DBselect($sql)))) { 1043 $max_clock = $row['clock']; 1044 } 1045 } 1046 if ($max_clock == 0) { 1047 return $value; 1048 } 1049 1050 if ($clock == $max_clock) { 1051 $sql = 'SELECT value'. 1052 ' FROM '.$table. 1053 ' WHERE itemid='.zbx_dbstr($db_item['itemid']). 1054 ' AND clock='.zbx_dbstr($clock). 1055 ' AND ns<'.zbx_dbstr($ns); 1056 } 1057 else { 1058 $sql = 'SELECT value'. 1059 ' FROM '.$table. 1060 ' WHERE itemid='.zbx_dbstr($db_item['itemid']). 1061 ' AND clock='.zbx_dbstr($max_clock). 1062 ' ORDER BY itemid,clock desc,ns desc'; 1063 } 1064 1065 if (null != ($row = DBfetch(DBselect($sql, 1)))) { 1066 $value = $row['value']; 1067 } 1068 1069 return $value; 1070} 1071 1072/** 1073 * Check if current time is within the given period. 1074 * 1075 * @param string $period time period format: "wd[-wd2],hh:mm-hh:mm" 1076 * @param int $now current timestamp 1077 * 1078 * @return bool true - within period, false - out of period 1079 */ 1080function checkTimePeriod($period, $now) { 1081 if (sscanf($period, '%d-%d,%d:%d-%d:%d', $d1, $d2, $h1, $m1, $h2, $m2) != 6) { 1082 if (sscanf($period, '%d,%d:%d-%d:%d', $d1, $h1, $m1, $h2, $m2) != 5) { 1083 // delay period format is wrong - skip 1084 return false; 1085 } 1086 $d2 = $d1; 1087 } 1088 1089 $tm = localtime($now, true); 1090 $day = ($tm['tm_wday'] == 0) ? 7 : $tm['tm_wday']; 1091 $sec = SEC_PER_HOUR * $tm['tm_hour'] + SEC_PER_MIN * $tm['tm_min'] + $tm['tm_sec']; 1092 1093 $sec1 = SEC_PER_HOUR * $h1 + SEC_PER_MIN * $m1; 1094 $sec2 = SEC_PER_HOUR * $h2 + SEC_PER_MIN * $m2; 1095 1096 return $d1 <= $day && $day <= $d2 && $sec1 <= $sec && $sec < $sec2; 1097} 1098 1099/** 1100 * Get item minimum delay. 1101 * 1102 * @param string $delay 1103 * @param array $flexible_intervals 1104 * 1105 * @return string 1106 */ 1107function getItemDelay($delay, array $flexible_intervals) { 1108 if ($delay != 0 || !$flexible_intervals) { 1109 return $delay; 1110 } 1111 1112 $min_delay = SEC_PER_YEAR; 1113 1114 foreach ($flexible_intervals as $flexible_interval) { 1115 $flexible_interval_parts = explode('/', $flexible_interval); 1116 $flexible_delay = (int) $flexible_interval_parts[0]; 1117 1118 $min_delay = min($min_delay, $flexible_delay); 1119 } 1120 1121 return $min_delay; 1122} 1123 1124/** 1125 * Return delay value that is currently applicable 1126 * 1127 * @param int $delay default delay 1128 * @param array $flexible_intervals array of intervals in format: "d/wd[-wd2],hh:mm-hh:mm" 1129 * @param int $now current timestamp 1130 * 1131 * @return int delay for a current timestamp 1132 */ 1133function getCurrentDelay($delay, array $flexible_intervals, $now) { 1134 if (!$flexible_intervals) { 1135 return $delay; 1136 } 1137 1138 $current_delay = -1; 1139 1140 foreach ($flexible_intervals as $flexible_interval) { 1141 list($flexible_delay, $flexible_period) = explode('/', $flexible_interval); 1142 $flexible_delay = (int) $flexible_delay; 1143 1144 if (($current_delay == -1 || $flexible_delay < $current_delay) && checkTimePeriod($flexible_period, $now)) { 1145 $current_delay = $flexible_delay; 1146 } 1147 } 1148 1149 if ($current_delay == -1) { 1150 return $delay; 1151 } 1152 1153 return $current_delay; 1154} 1155 1156/** 1157 * Return time of next flexible interval 1158 * 1159 * @param array $flexible_intervals array of intervals in format: "d/wd[-wd2],hh:mm-hh:mm" 1160 * @param int $now current timestamp 1161 * @param int $next_interval timestamp of a next interval 1162 * 1163 * @return bool false if no flexible intervals defined 1164 */ 1165function getNextDelayInterval(array $flexible_intervals, $now, &$next_interval) { 1166 if (!$flexible_intervals) { 1167 return false; 1168 } 1169 1170 $next = 0; 1171 $tm = localtime($now, true); 1172 $day = ($tm['tm_wday'] == 0) ? 7 : $tm['tm_wday']; 1173 $sec = SEC_PER_HOUR * $tm['tm_hour'] + SEC_PER_MIN * $tm['tm_min'] + $tm['tm_sec']; 1174 1175 foreach ($flexible_intervals as $flexible_interval) { 1176 $flexible_interval_parts = explode('/', $flexible_interval); 1177 1178 if (sscanf($flexible_interval_parts[1], '%d-%d,%d:%d-%d:%d', $d1, $d2, $h1, $m1, $h2, $m2) != 6) { 1179 if (sscanf($flexible_interval_parts[1], '%d,%d:%d-%d:%d', $d1, $h1, $m1, $h2, $m2) != 5) { 1180 continue; 1181 } 1182 $d2 = $d1; 1183 } 1184 1185 $sec1 = SEC_PER_HOUR * $h1 + SEC_PER_MIN * $m1; 1186 $sec2 = SEC_PER_HOUR * $h2 + SEC_PER_MIN * $m2; 1187 1188 // current period 1189 if ($d1 <= $day && $day <= $d2 && $sec1 <= $sec && $sec < $sec2) { 1190 if ($next == 0 || $next > $now - $sec + $sec2) { 1191 // the next second after the current interval's upper bound 1192 $next = $now - $sec + $sec2; 1193 } 1194 } 1195 // will be active today 1196 elseif ($d1 <= $day && $d2 >= $day && $sec < $sec1) { 1197 if ($next == 0 || $next > $now - $sec + $sec1) { 1198 $next = $now - $sec + $sec1; 1199 } 1200 } 1201 else { 1202 $nextDay = ($day + 1 <= 7) ? $day + 1 : 1; 1203 1204 // will be active tomorrow 1205 if ($d1 <= $nextDay && $nextDay <= $d2) { 1206 if ($next == 0 || $next > $now - $sec + SEC_PER_DAY + $sec1) { 1207 $next = $now - $sec + SEC_PER_DAY + $sec1; 1208 } 1209 } 1210 // later in the future 1211 else { 1212 $dayDiff = -1; 1213 1214 if ($day < $d1) { 1215 $dayDiff = $d1 - $day; 1216 } 1217 if ($day >= $d2) { 1218 $dayDiff = ($d1 + 7) - $day; 1219 } 1220 if ($d1 <= $day && $day < $d2) { 1221 // should never happen, could not deduce day difference 1222 $dayDiff = -1; 1223 } 1224 if ($dayDiff != -1 && ($next == 0 || $next > $now - $sec + SEC_PER_DAY * $dayDiff + $sec1)) { 1225 $next = $now - $sec + SEC_PER_DAY * $dayDiff + $sec1; 1226 } 1227 } 1228 } 1229 } 1230 1231 if ($next != 0) { 1232 $next_interval = $next; 1233 } 1234 1235 return ($next != 0); 1236} 1237 1238/** 1239 * Calculate nextcheck timestamp for an item using flexible intervals. 1240 * 1241 * the parameter $flexible_intervals is an array if strings that are in the following format: 1242 * 1243 * +------------[;]<----------+ 1244 * | | 1245 * ->+-[d/wd[-wd2],hh:mm-hh:mm]-+ 1246 * 1247 * d - delay (0-n) 1248 * wd, wd2 - day of week (1-7) 1249 * hh - hours (0-24) 1250 * mm - minutes (0-59) 1251 * 1252 * @param int $seed seed value applied to delay to spread item checks over the delay period 1253 * @param string $delay default delay, can be overridden 1254 * @param array $flexible_intervals array of flexible intervals 1255 * @param int $now current timestamp 1256 * 1257 * @return int 1258 */ 1259function calculateItemNextCheck($seed, $delay, $flexible_intervals, $now) { 1260 /* 1261 * Try to find the nearest 'nextcheck' value with condition 'now' < 'nextcheck' < 'now' + SEC_PER_YEAR 1262 * If it is not possible to check the item within a year, fail. 1263 */ 1264 1265 $t = $now; 1266 $tMax = $now + SEC_PER_YEAR; 1267 $try = 0; 1268 1269 while ($t < $tMax) { 1270 // Calculate 'nextcheck' value for the current interval. 1271 $currentDelay = getCurrentDelay($delay, $flexible_intervals, $t); 1272 1273 if ($currentDelay != 0) { 1274 $nextCheck = $currentDelay * floor($t / $currentDelay) + ($seed % $currentDelay); 1275 1276 if ($try == 0) { 1277 while ($nextCheck <= $t) { 1278 $nextCheck += $currentDelay; 1279 } 1280 } 1281 else { 1282 while ($nextCheck < $t) { 1283 $nextCheck += $currentDelay; 1284 } 1285 } 1286 } 1287 else { 1288 $nextCheck = ZBX_JAN_2038; 1289 } 1290 1291 /* 1292 * Is 'nextcheck' < end of the current interval and the end of the current interval 1293 * is the beginning of the next interval - 1. 1294 */ 1295 if (getNextDelayInterval($flexible_intervals, $t, $nextInterval) && $nextCheck >= $nextInterval) { 1296 // 'nextcheck' is beyond the current interval. 1297 $t = $nextInterval; 1298 $try++; 1299 } 1300 else { 1301 break; 1302 } 1303 } 1304 1305 return $nextCheck; 1306} 1307 1308/* 1309 * Description: 1310 * Function returns true if http items exists in the $items array. 1311 * The array should contain a field 'type' 1312 */ 1313function httpItemExists($items) { 1314 foreach ($items as $item) { 1315 if ($item['type'] == ITEM_TYPE_HTTPTEST) { 1316 return true; 1317 } 1318 } 1319 return false; 1320} 1321 1322function getParamFieldNameByType($itemType) { 1323 switch ($itemType) { 1324 case ITEM_TYPE_SSH: 1325 case ITEM_TYPE_TELNET: 1326 case ITEM_TYPE_JMX: 1327 return 'params_es'; 1328 case ITEM_TYPE_DB_MONITOR: 1329 return 'params_ap'; 1330 case ITEM_TYPE_CALCULATED: 1331 return 'params_f'; 1332 default: 1333 return 'params'; 1334 } 1335} 1336 1337function getParamFieldLabelByType($itemType) { 1338 switch ($itemType) { 1339 case ITEM_TYPE_SSH: 1340 case ITEM_TYPE_TELNET: 1341 case ITEM_TYPE_JMX: 1342 return _('Executed script'); 1343 case ITEM_TYPE_DB_MONITOR: 1344 return _('SQL query'); 1345 case ITEM_TYPE_CALCULATED: 1346 return _('Formula'); 1347 default: 1348 return 'params'; 1349 } 1350} 1351 1352/* 1353 * Quoting $param if it contain special characters. 1354 * 1355 * @param string $param 1356 * @param bool $forced 1357 * 1358 * @return string 1359 */ 1360function quoteItemKeyParam($param, $forced = false) { 1361 if (!$forced) { 1362 if (!isset($param[0]) || ($param[0] != '"' && false === strpbrk($param, ',]'))) { 1363 return $param; 1364 } 1365 } 1366 1367 return '"'.str_replace('"', '\\"', $param).'"'; 1368} 1369