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 22function condition_operator2str($operator) { 23 $operators = [ 24 CONDITION_OPERATOR_EQUAL => _('equals'), 25 CONDITION_OPERATOR_NOT_EQUAL => _('does not equal'), 26 CONDITION_OPERATOR_LIKE => _('contains'), 27 CONDITION_OPERATOR_NOT_LIKE => _('does not contain'), 28 CONDITION_OPERATOR_IN => _('in'), 29 CONDITION_OPERATOR_MORE_EQUAL => _('is greater than or equals'), 30 CONDITION_OPERATOR_LESS_EQUAL => _('is less than or equals'), 31 CONDITION_OPERATOR_NOT_IN => _('not in'), 32 CONDITION_OPERATOR_YES => _('Yes'), 33 CONDITION_OPERATOR_NO => _('No'), 34 CONDITION_OPERATOR_REGEXP => _('matches'), 35 CONDITION_OPERATOR_NOT_REGEXP => _('does not match') 36 ]; 37 38 return $operators[$operator]; 39} 40 41function condition_type2str($type) { 42 $types = [ 43 CONDITION_TYPE_SUPPRESSED => _('Problem is suppressed'), 44 CONDITION_TYPE_TRIGGER_NAME => _('Trigger name'), 45 CONDITION_TYPE_TRIGGER_SEVERITY => _('Trigger severity'), 46 CONDITION_TYPE_TRIGGER => _('Trigger'), 47 CONDITION_TYPE_HOST_NAME => _('Host name'), 48 CONDITION_TYPE_HOST_GROUP => _('Host group'), 49 CONDITION_TYPE_TEMPLATE => _('Template'), 50 CONDITION_TYPE_HOST => _('Host'), 51 CONDITION_TYPE_TIME_PERIOD => _('Time period'), 52 CONDITION_TYPE_DRULE => _('Discovery rule'), 53 CONDITION_TYPE_DCHECK => _('Discovery check'), 54 CONDITION_TYPE_DOBJECT => _('Discovery object'), 55 CONDITION_TYPE_DHOST_IP => _('Host IP'), 56 CONDITION_TYPE_DSERVICE_TYPE => _('Service type'), 57 CONDITION_TYPE_DSERVICE_PORT => _('Service port'), 58 CONDITION_TYPE_DSTATUS => _('Discovery status'), 59 CONDITION_TYPE_DUPTIME => _('Uptime/Downtime'), 60 CONDITION_TYPE_DVALUE => _('Received value'), 61 CONDITION_TYPE_EVENT_ACKNOWLEDGED => _('Event acknowledged'), 62 CONDITION_TYPE_PROXY => _('Proxy'), 63 CONDITION_TYPE_EVENT_TYPE => _('Event type'), 64 CONDITION_TYPE_HOST_METADATA => _('Host metadata'), 65 CONDITION_TYPE_EVENT_TAG => _('Tag name'), 66 CONDITION_TYPE_EVENT_TAG_VALUE => _('Tag value') 67 ]; 68 69 return $types[$type]; 70} 71 72function discovery_object2str($object = null) { 73 $objects = [ 74 EVENT_OBJECT_DHOST => _('Device'), 75 EVENT_OBJECT_DSERVICE => _('Service') 76 ]; 77 78 if ($object === null) { 79 return $objects; 80 } 81 82 return $objects[$object]; 83} 84 85/** 86 * Converts numerical action condition values to their corresponding string values according to action condition type. 87 * 88 * For action condition types such as: hosts, host groups, templates, proxies, triggers, discovery rules 89 * and discovery checks, action condition values contain IDs. All unique IDs are first collected and then queried. 90 * For other action condition types values are returned as they are or converted using simple string conversion 91 * functions according to action condition type. 92 * 93 * @param array $actions array of actions 94 * @param array $action['filter'] array containing arrays of action conditions and other data 95 * @param array $action['filter']['conditions'] array of action conditions 96 * 97 * @return array returns an array of actions condition string values 98 */ 99function actionConditionValueToString(array $actions) { 100 $result = []; 101 102 $groupIds = []; 103 $triggerIds = []; 104 $hostIds = []; 105 $templateIds = []; 106 $proxyIds = []; 107 $dRuleIds = []; 108 $dCheckIds = []; 109 110 foreach ($actions as $i => $action) { 111 $result[$i] = []; 112 113 foreach ($action['filter']['conditions'] as $j => $condition) { 114 // unknown types and all of the default values for other types are 'Unknown' 115 $result[$i][$j] = _('Unknown'); 116 117 switch ($condition['conditiontype']) { 118 case CONDITION_TYPE_HOST_GROUP: 119 $groupIds[$condition['value']] = $condition['value']; 120 break; 121 122 case CONDITION_TYPE_TRIGGER: 123 $triggerIds[$condition['value']] = $condition['value']; 124 break; 125 126 case CONDITION_TYPE_HOST: 127 $hostIds[$condition['value']] = $condition['value']; 128 break; 129 130 case CONDITION_TYPE_TEMPLATE: 131 $templateIds[$condition['value']] = $condition['value']; 132 break; 133 134 case CONDITION_TYPE_PROXY: 135 $proxyIds[$condition['value']] = $condition['value']; 136 break; 137 138 // return values as is for following condition types 139 case CONDITION_TYPE_TRIGGER_NAME: 140 case CONDITION_TYPE_HOST_METADATA: 141 case CONDITION_TYPE_HOST_NAME: 142 case CONDITION_TYPE_TIME_PERIOD: 143 case CONDITION_TYPE_DHOST_IP: 144 case CONDITION_TYPE_DSERVICE_PORT: 145 case CONDITION_TYPE_DUPTIME: 146 case CONDITION_TYPE_DVALUE: 147 case CONDITION_TYPE_EVENT_TAG: 148 case CONDITION_TYPE_EVENT_TAG_VALUE: 149 $result[$i][$j] = $condition['value']; 150 break; 151 152 case CONDITION_TYPE_EVENT_ACKNOWLEDGED: 153 $result[$i][$j] = $condition['value'] ? _('Ack') : _('Not Ack'); 154 break; 155 156 case CONDITION_TYPE_TRIGGER_SEVERITY: 157 $result[$i][$j] = getSeverityName($condition['value']); 158 break; 159 160 case CONDITION_TYPE_DRULE: 161 $dRuleIds[$condition['value']] = $condition['value']; 162 break; 163 164 case CONDITION_TYPE_DCHECK: 165 $dCheckIds[$condition['value']] = $condition['value']; 166 break; 167 168 case CONDITION_TYPE_DOBJECT: 169 $result[$i][$j] = discovery_object2str($condition['value']); 170 break; 171 172 case CONDITION_TYPE_DSERVICE_TYPE: 173 $result[$i][$j] = discovery_check_type2str($condition['value']); 174 break; 175 176 case CONDITION_TYPE_DSTATUS: 177 $result[$i][$j] = discovery_object_status2str($condition['value']); 178 break; 179 180 case CONDITION_TYPE_EVENT_TYPE: 181 $result[$i][$j] = eventType($condition['value']); 182 break; 183 } 184 } 185 } 186 187 $groups = []; 188 $triggers = []; 189 $hosts = []; 190 $templates = []; 191 $proxies = []; 192 $dRules = []; 193 $dChecks = []; 194 195 if ($groupIds) { 196 $groups = API::HostGroup()->get([ 197 'output' => ['name'], 198 'groupids' => $groupIds, 199 'preservekeys' => true 200 ]); 201 } 202 203 if ($triggerIds) { 204 $triggers = API::Trigger()->get([ 205 'output' => ['description'], 206 'triggerids' => $triggerIds, 207 'expandDescription' => true, 208 'selectHosts' => ['name'], 209 'preservekeys' => true 210 ]); 211 } 212 213 if ($hostIds) { 214 $hosts = API::Host()->get([ 215 'output' => ['name'], 216 'hostids' => $hostIds, 217 'preservekeys' => true 218 ]); 219 } 220 221 if ($templateIds) { 222 $templates = API::Template()->get([ 223 'output' => ['name'], 224 'templateids' => $templateIds, 225 'preservekeys' => true 226 ]); 227 } 228 229 if ($proxyIds) { 230 $proxies = API::Proxy()->get([ 231 'output' => ['host'], 232 'proxyids' => $proxyIds, 233 'preservekeys' => true 234 ]); 235 } 236 237 if ($dRuleIds) { 238 $dRules = API::DRule()->get([ 239 'output' => ['name'], 240 'druleids' => $dRuleIds, 241 'preservekeys' => true 242 ]); 243 } 244 245 if ($dCheckIds) { 246 $dChecks = API::DCheck()->get([ 247 'output' => ['type', 'key_', 'ports'], 248 'dcheckids' => $dCheckIds, 249 'selectDRules' => ['name'], 250 'preservekeys' => true 251 ]); 252 } 253 254 if ($groups || $triggers || $hosts || $templates || $proxies || $dRules || $dChecks) { 255 foreach ($actions as $i => $action) { 256 foreach ($action['filter']['conditions'] as $j => $condition) { 257 $id = $condition['value']; 258 259 switch ($condition['conditiontype']) { 260 case CONDITION_TYPE_HOST_GROUP: 261 if (isset($groups[$id])) { 262 $result[$i][$j] = $groups[$id]['name']; 263 } 264 break; 265 266 case CONDITION_TYPE_TRIGGER: 267 if (isset($triggers[$id])) { 268 $host = reset($triggers[$id]['hosts']); 269 $result[$i][$j] = $host['name'].NAME_DELIMITER.$triggers[$id]['description']; 270 } 271 break; 272 273 case CONDITION_TYPE_HOST: 274 if (isset($hosts[$id])) { 275 $result[$i][$j] = $hosts[$id]['name']; 276 } 277 break; 278 279 case CONDITION_TYPE_TEMPLATE: 280 if (isset($templates[$id])) { 281 $result[$i][$j] = $templates[$id]['name']; 282 } 283 break; 284 285 case CONDITION_TYPE_PROXY: 286 if (isset($proxies[$id])) { 287 $result[$i][$j] = $proxies[$id]['host']; 288 } 289 break; 290 291 case CONDITION_TYPE_DRULE: 292 if (isset($dRules[$id])) { 293 $result[$i][$j] = $dRules[$id]['name']; 294 } 295 break; 296 297 case CONDITION_TYPE_DCHECK: 298 if (isset($dChecks[$id])) { 299 $drule = reset($dChecks[$id]['drules']); 300 $type = $dChecks[$id]['type']; 301 $key_ = $dChecks[$id]['key_']; 302 $ports = $dChecks[$id]['ports']; 303 304 $dCheck = discovery_check2str($type, $key_, $ports); 305 306 $result[$i][$j] = $drule['name'].NAME_DELIMITER.$dCheck; 307 } 308 break; 309 } 310 } 311 } 312 } 313 314 return $result; 315} 316 317/** 318 * Returns the HTML representation of an action condition and action operation condition. 319 * 320 * @param string $condition_type 321 * @param string $operator 322 * @param string $value 323 * @param string $value2 324 * 325 * @return array 326 */ 327function getConditionDescription($condition_type, $operator, $value, $value2) { 328 if ($condition_type == CONDITION_TYPE_EVENT_TAG_VALUE) { 329 $description = [_('Value of tag')]; 330 $description[] = ' '; 331 $description[] = italic(CHtml::encode($value2)); 332 $description[] = ' '; 333 } 334 elseif ($condition_type == CONDITION_TYPE_SUPPRESSED) { 335 return ($operator == CONDITION_OPERATOR_YES) 336 ? [_('Problem is suppressed')] 337 : [_('Problem is not suppressed')]; 338 } 339 elseif ($condition_type == CONDITION_TYPE_EVENT_ACKNOWLEDGED) { 340 return $value ? _('Event is acknowledged') : _('Event is not acknowledged'); 341 } 342 else { 343 $description = [condition_type2str($condition_type)]; 344 $description[] = ' '; 345 } 346 347 $description[] = condition_operator2str($operator); 348 $description[] = ' '; 349 $description[] = italic(CHtml::encode($value)); 350 351 return $description; 352} 353 354/** 355 * Gathers media types, user groups, users, host groups, hosts and templates for actions and their operations, and 356 * returns the HTML representation of action operation values according to action operation type. 357 * 358 * @param array $actions Array of actions 359 * @param int $type Operations recovery type (ACTION_OPERATION or ACTION_RECOVERY_OPERATION) 360 * 361 * @return array Returns an array of actions operation descriptions. 362 */ 363function getActionOperationDescriptions(array $actions, $type) { 364 $result = []; 365 366 $media_typeids = []; 367 $userids = []; 368 $usr_grpids = []; 369 $hostids = []; 370 $groupids = []; 371 $templateids = []; 372 $scriptids = []; 373 374 foreach ($actions as $i => $action) { 375 $result[$i] = []; 376 377 if ($type == ACTION_OPERATION) { 378 foreach ($action['operations'] as $j => $operation) { 379 $result[$i][$j] = []; 380 381 switch ($operation['operationtype']) { 382 case OPERATION_TYPE_MESSAGE: 383 $media_typeid = $operation['opmessage']['mediatypeid']; 384 385 if ($media_typeid != 0) { 386 $media_typeids[$media_typeid] = $media_typeid; 387 } 388 389 if (array_key_exists('opmessage_usr', $operation) && $operation['opmessage_usr']) { 390 foreach ($operation['opmessage_usr'] as $users) { 391 $userids[$users['userid']] = $users['userid']; 392 } 393 } 394 395 if (array_key_exists('opmessage_grp', $operation) && $operation['opmessage_grp']) { 396 foreach ($operation['opmessage_grp'] as $user_groups) { 397 $usr_grpids[$user_groups['usrgrpid']] = $user_groups['usrgrpid']; 398 } 399 } 400 break; 401 402 case OPERATION_TYPE_COMMAND: 403 if (array_key_exists('opcommand_hst', $operation) && $operation['opcommand_hst']) { 404 foreach ($operation['opcommand_hst'] as $host) { 405 if ($host['hostid'] != 0) { 406 $hostids[$host['hostid']] = $host['hostid']; 407 } 408 } 409 } 410 411 if (array_key_exists('opcommand_grp', $operation) && $operation['opcommand_grp']) { 412 foreach ($operation['opcommand_grp'] as $host_group) { 413 $groupids[$host_group['groupid']] = true; 414 } 415 } 416 417 $scriptids[$operation['opcommand']['scriptid']] = true; 418 break; 419 420 case OPERATION_TYPE_GROUP_ADD: 421 case OPERATION_TYPE_GROUP_REMOVE: 422 foreach ($operation['opgroup'] as $groupid) { 423 $groupids[$groupid['groupid']] = true; 424 } 425 break; 426 427 case OPERATION_TYPE_TEMPLATE_ADD: 428 case OPERATION_TYPE_TEMPLATE_REMOVE: 429 foreach ($operation['optemplate'] as $templateid) { 430 $templateids[$templateid['templateid']] = true; 431 } 432 break; 433 } 434 } 435 } 436 else { 437 $operations_key = ($type == ACTION_RECOVERY_OPERATION) 438 ? 'recovery_operations' 439 : 'ack_operations'; 440 441 foreach ($action[$operations_key] as $j => $operation) { 442 $result[$i][$j] = []; 443 444 switch ($operation['operationtype']) { 445 case OPERATION_TYPE_MESSAGE: 446 $media_typeid = $operation['opmessage']['mediatypeid']; 447 448 if ($media_typeid != 0) { 449 $media_typeids[$media_typeid] = $media_typeid; 450 } 451 452 if (array_key_exists('opmessage_usr', $operation) && $operation['opmessage_usr']) { 453 foreach ($operation['opmessage_usr'] as $users) { 454 $userids[$users['userid']] = $users['userid']; 455 } 456 } 457 458 if (array_key_exists('opmessage_grp', $operation) && $operation['opmessage_grp']) { 459 foreach ($operation['opmessage_grp'] as $user_groups) { 460 $usr_grpids[$user_groups['usrgrpid']] = $user_groups['usrgrpid']; 461 } 462 } 463 break; 464 465 case OPERATION_TYPE_COMMAND: 466 if (array_key_exists('opcommand_hst', $operation) && $operation['opcommand_hst']) { 467 foreach ($operation['opcommand_hst'] as $host) { 468 if ($host['hostid'] != 0) { 469 $hostids[$host['hostid']] = $host['hostid']; 470 } 471 } 472 } 473 474 if (array_key_exists('opcommand_grp', $operation) && $operation['opcommand_grp']) { 475 foreach ($operation['opcommand_grp'] as $host_group) { 476 $groupids[$host_group['groupid']] = true; 477 } 478 } 479 480 $scriptids[$operation['opcommand']['scriptid']] = true; 481 break; 482 } 483 } 484 } 485 } 486 487 $media_types = []; 488 $users = []; 489 $user_groups = []; 490 $hosts = []; 491 $host_groups = []; 492 $templates = []; 493 $scripts = []; 494 495 if ($media_typeids) { 496 $media_types = API::Mediatype()->get([ 497 'output' => ['name'], 498 'mediatypeids' => $media_typeids, 499 'preservekeys' => true 500 ]); 501 } 502 503 if ($userids) { 504 $fullnames = []; 505 506 $users = API::User()->get([ 507 'output' => ['userid', 'username', 'name', 'surname'], 508 'userids' => $userids 509 ]); 510 511 foreach ($users as $user) { 512 $fullnames[$user['userid']] = getUserFullname($user); 513 } 514 } 515 516 if ($usr_grpids) { 517 $user_groups = API::UserGroup()->get([ 518 'output' => ['name'], 519 'usrgrpids' => $usr_grpids, 520 'preservekeys' => true 521 ]); 522 } 523 524 if ($hostids) { 525 $hosts = API::Host()->get([ 526 'output' => ['name'], 527 'hostids' => $hostids, 528 'preservekeys' => true 529 ]); 530 } 531 532 if ($groupids) { 533 $host_groups = API::HostGroup()->get([ 534 'output' => ['name'], 535 'groupids' => array_keys($groupids), 536 'preservekeys' => true 537 ]); 538 } 539 540 if ($templateids) { 541 $templates = API::Template()->get([ 542 'output' => ['name'], 543 'templateids' => array_keys($templateids), 544 'preservekeys' => true 545 ]); 546 } 547 548 if ($scriptids) { 549 $scripts = API::Script()->get([ 550 'output' => ['name'], 551 'scriptids' => array_keys($scriptids), 552 'filter' => ['scope' => ZBX_SCRIPT_SCOPE_ACTION], 553 'preservekeys' => true 554 ]); 555 } 556 557 // Format the HTML output. 558 foreach ($actions as $i => $action) { 559 if ($type == ACTION_OPERATION) { 560 foreach ($action['operations'] as $j => $operation) { 561 switch ($operation['operationtype']) { 562 case OPERATION_TYPE_MESSAGE: 563 $media_type = _('all media'); 564 $media_typeid = $operation['opmessage']['mediatypeid']; 565 566 if ($media_typeid != 0 && isset($media_types[$media_typeid])) { 567 $media_type = $media_types[$media_typeid]['name']; 568 } 569 570 if (array_key_exists('opmessage_usr', $operation) && $operation['opmessage_usr']) { 571 $user_names_list = []; 572 573 foreach ($operation['opmessage_usr'] as $user) { 574 if (isset($fullnames[$user['userid']])) { 575 $user_names_list[] = $fullnames[$user['userid']]; 576 } 577 } 578 579 order_result($user_names_list); 580 581 $result[$i][$j][] = bold(_('Send message to users').': '); 582 $result[$i][$j][] = [implode(', ', $user_names_list), SPACE, _('via'), SPACE, 583 $media_type 584 ]; 585 $result[$i][$j][] = BR(); 586 } 587 588 if (array_key_exists('opmessage_grp', $operation) && $operation['opmessage_grp']) { 589 $user_groups_list = []; 590 591 foreach ($operation['opmessage_grp'] as $userGroup) { 592 if (isset($user_groups[$userGroup['usrgrpid']])) { 593 $user_groups_list[] = $user_groups[$userGroup['usrgrpid']]['name']; 594 } 595 } 596 597 order_result($user_groups_list); 598 599 $result[$i][$j][] = bold(_('Send message to user groups').': '); 600 $result[$i][$j][] = [implode(', ', $user_groups_list), SPACE, _('via'), SPACE, 601 $media_type 602 ]; 603 $result[$i][$j][] = BR(); 604 } 605 break; 606 607 case OPERATION_TYPE_COMMAND: 608 $scriptid = $operation['opcommand']['scriptid']; 609 610 if (array_key_exists('opcommand_hst', $operation) && $operation['opcommand_hst']) { 611 $host_list = []; 612 613 foreach ($operation['opcommand_hst'] as $host) { 614 if ($host['hostid'] == 0) { 615 $result[$i][$j][] = [ 616 bold(_s('Run script "%1$s" on current host', $scripts[$scriptid]['name'])), 617 BR() 618 ]; 619 } 620 elseif (isset($hosts[$host['hostid']])) { 621 $host_list[] = $hosts[$host['hostid']]['name']; 622 } 623 } 624 625 if ($host_list) { 626 order_result($host_list); 627 628 $result[$i][$j][] = bold( 629 _s('Run script "%1$s" on hosts', $scripts[$scriptid]['name']).': ' 630 ); 631 $result[$i][$j][] = [implode(', ', $host_list), BR()]; 632 } 633 } 634 635 if (array_key_exists('opcommand_grp', $operation) && $operation['opcommand_grp']) { 636 $host_group_list = []; 637 638 foreach ($operation['opcommand_grp'] as $host_group) { 639 if (isset($host_groups[$host_group['groupid']])) { 640 $host_group_list[] = $host_groups[$host_group['groupid']]['name']; 641 } 642 } 643 644 order_result($host_group_list); 645 646 $result[$i][$j][] = bold( 647 _s('Run script "%1$s" on host groups', $scripts[$scriptid]['name']).': ' 648 ); 649 $result[$i][$j][] = [implode(', ', $host_group_list), BR()]; 650 } 651 break; 652 653 case OPERATION_TYPE_HOST_ADD: 654 $result[$i][$j][] = [bold(_('Add host')), BR()]; 655 break; 656 657 case OPERATION_TYPE_HOST_REMOVE: 658 $result[$i][$j][] = [bold(_('Remove host')), BR()]; 659 break; 660 661 case OPERATION_TYPE_HOST_ENABLE: 662 $result[$i][$j][] = [bold(_('Enable host')), BR()]; 663 break; 664 665 case OPERATION_TYPE_HOST_DISABLE: 666 $result[$i][$j][] = [bold(_('Disable host')), BR()]; 667 break; 668 669 case OPERATION_TYPE_GROUP_ADD: 670 case OPERATION_TYPE_GROUP_REMOVE: 671 $host_group_list = []; 672 673 foreach ($operation['opgroup'] as $groupid) { 674 if (array_key_exists($groupid['groupid'], $host_groups)) { 675 $host_group_list[] = $host_groups[$groupid['groupid']]['name']; 676 } 677 } 678 679 order_result($host_group_list); 680 681 if ($operation['operationtype'] == OPERATION_TYPE_GROUP_ADD) { 682 $result[$i][$j][] = bold(_('Add to host groups').': '); 683 } 684 else { 685 $result[$i][$j][] = bold(_('Remove from host groups').': '); 686 } 687 688 $result[$i][$j][] = [implode(', ', $host_group_list), BR()]; 689 break; 690 691 case OPERATION_TYPE_TEMPLATE_ADD: 692 case OPERATION_TYPE_TEMPLATE_REMOVE: 693 $template_list = []; 694 695 foreach ($operation['optemplate'] as $templateid) { 696 if (array_key_exists($templateid['templateid'], $templates)) { 697 $template_list[] = $templates[$templateid['templateid']]['name']; 698 } 699 } 700 701 order_result($template_list); 702 703 if ($operation['operationtype'] == OPERATION_TYPE_TEMPLATE_ADD) { 704 $result[$i][$j][] = bold(_('Link to templates').': '); 705 } 706 else { 707 $result[$i][$j][] = bold(_('Unlink from templates').': '); 708 } 709 710 $result[$i][$j][] = [implode(', ', $template_list), BR()]; 711 break; 712 713 case OPERATION_TYPE_HOST_INVENTORY: 714 $host_inventory_modes = getHostInventoryModes(); 715 $result[$i][$j][] = bold(operation_type2str(OPERATION_TYPE_HOST_INVENTORY).': '); 716 $result[$i][$j][] = [ 717 $host_inventory_modes[$operation['opinventory']['inventory_mode']], 718 BR() 719 ]; 720 break; 721 } 722 } 723 } 724 else { 725 $operations_key = ($type == ACTION_RECOVERY_OPERATION) 726 ? 'recovery_operations' 727 : 'ack_operations'; 728 729 foreach ($action[$operations_key] as $j => $operation) { 730 switch ($operation['operationtype']) { 731 case OPERATION_TYPE_MESSAGE: 732 $media_type = _('all media'); 733 $media_typeid = $operation['opmessage']['mediatypeid']; 734 735 if ($media_typeid != 0 && isset($media_types[$media_typeid])) { 736 $media_type = $media_types[$media_typeid]['name']; 737 } 738 739 if (array_key_exists('opmessage_usr', $operation) && $operation['opmessage_usr']) { 740 $user_names_list = []; 741 742 foreach ($operation['opmessage_usr'] as $user) { 743 if (isset($fullnames[$user['userid']])) { 744 $user_names_list[] = $fullnames[$user['userid']]; 745 } 746 } 747 748 order_result($user_names_list); 749 750 $result[$i][$j][] = bold(_('Send message to users').': '); 751 $result[$i][$j][] = [implode(', ', $user_names_list), SPACE, _('via'), SPACE, 752 $media_type 753 ]; 754 $result[$i][$j][] = BR(); 755 } 756 757 if (array_key_exists('opmessage_grp', $operation) && $operation['opmessage_grp']) { 758 $user_groups_list = []; 759 760 foreach ($operation['opmessage_grp'] as $userGroup) { 761 if (isset($user_groups[$userGroup['usrgrpid']])) { 762 $user_groups_list[] = $user_groups[$userGroup['usrgrpid']]['name']; 763 } 764 } 765 766 order_result($user_groups_list); 767 768 $result[$i][$j][] = bold(_('Send message to user groups').': '); 769 $result[$i][$j][] = [implode(', ', $user_groups_list), SPACE, _('via'), SPACE, 770 $media_type 771 ]; 772 $result[$i][$j][] = BR(); 773 } 774 break; 775 776 case OPERATION_TYPE_COMMAND: 777 $scriptid = $operation['opcommand']['scriptid']; 778 779 if (array_key_exists('opcommand_hst', $operation) && $operation['opcommand_hst']) { 780 $host_list = []; 781 782 foreach ($operation['opcommand_hst'] as $host) { 783 if ($host['hostid'] == 0) { 784 $result[$i][$j][] = [ 785 bold(_s('Run script "%1$s" on current host', $scripts[$scriptid]['name'])), 786 BR() 787 ]; 788 } 789 elseif (isset($hosts[$host['hostid']])) { 790 $host_list[] = $hosts[$host['hostid']]['name']; 791 } 792 } 793 794 if ($host_list) { 795 order_result($host_list); 796 797 $result[$i][$j][] = bold( 798 _s('Run script "%1$s" on hosts', $scripts[$scriptid]['name']).': ' 799 ); 800 $result[$i][$j][] = [implode(', ', $host_list), BR()]; 801 } 802 } 803 804 if (array_key_exists('opcommand_grp', $operation) && $operation['opcommand_grp']) { 805 $host_group_list = []; 806 807 foreach ($operation['opcommand_grp'] as $host_group) { 808 if (isset($host_groups[$host_group['groupid']])) { 809 $host_group_list[] = $host_groups[$host_group['groupid']]['name']; 810 } 811 } 812 813 order_result($host_group_list); 814 815 $result[$i][$j][] = bold( 816 _s('Run script "%1$s" on host groups', $scripts[$scriptid]['name']).': ' 817 ); 818 $result[$i][$j][] = [implode(', ', $host_group_list), BR()]; 819 } 820 break; 821 822 case OPERATION_TYPE_RECOVERY_MESSAGE: 823 case OPERATION_TYPE_ACK_MESSAGE: 824 $result[$i][$j][] = bold(_('Notify all involved')); 825 break; 826 } 827 } 828 } 829 } 830 831 return $result; 832} 833 834/** 835 * Return an array of action conditions supported by the given event source. 836 * 837 * @param int $eventsource 838 * 839 * @return mixed 840 */ 841function get_conditions_by_eventsource($eventsource) { 842 $conditions[EVENT_SOURCE_TRIGGERS] = [ 843 CONDITION_TYPE_TRIGGER_NAME, 844 CONDITION_TYPE_TRIGGER, 845 CONDITION_TYPE_TRIGGER_SEVERITY, 846 CONDITION_TYPE_HOST, 847 CONDITION_TYPE_HOST_GROUP, 848 CONDITION_TYPE_SUPPRESSED, 849 CONDITION_TYPE_EVENT_TAG, 850 CONDITION_TYPE_EVENT_TAG_VALUE, 851 CONDITION_TYPE_TEMPLATE, 852 CONDITION_TYPE_TIME_PERIOD 853 ]; 854 $conditions[EVENT_SOURCE_DISCOVERY] = [ 855 CONDITION_TYPE_DHOST_IP, 856 CONDITION_TYPE_DCHECK, 857 CONDITION_TYPE_DOBJECT, 858 CONDITION_TYPE_DRULE, 859 CONDITION_TYPE_DSTATUS, 860 CONDITION_TYPE_PROXY, 861 CONDITION_TYPE_DVALUE, 862 CONDITION_TYPE_DSERVICE_PORT, 863 CONDITION_TYPE_DSERVICE_TYPE, 864 CONDITION_TYPE_DUPTIME 865 ]; 866 $conditions[EVENT_SOURCE_AUTOREGISTRATION] = [ 867 CONDITION_TYPE_HOST_NAME, 868 CONDITION_TYPE_HOST_METADATA, 869 CONDITION_TYPE_PROXY 870 ]; 871 $conditions[EVENT_SOURCE_INTERNAL] = [ 872 CONDITION_TYPE_EVENT_TYPE, 873 CONDITION_TYPE_HOST, 874 CONDITION_TYPE_HOST_GROUP, 875 CONDITION_TYPE_EVENT_TAG, 876 CONDITION_TYPE_EVENT_TAG_VALUE, 877 CONDITION_TYPE_TEMPLATE 878 ]; 879 880 if (isset($conditions[$eventsource])) { 881 return $conditions[$eventsource]; 882 } 883 884 return $conditions[EVENT_SOURCE_TRIGGERS]; 885} 886 887function get_opconditions_by_eventsource($eventsource) { 888 $conditions = [ 889 EVENT_SOURCE_TRIGGERS => [CONDITION_TYPE_EVENT_ACKNOWLEDGED], 890 EVENT_SOURCE_DISCOVERY => [] 891 ]; 892 893 if (isset($conditions[$eventsource])) { 894 return $conditions[$eventsource]; 895 } 896} 897 898/** 899 * Return allowed operations types. 900 * 901 * @param int $eventsource 902 * 903 * @return array 904 */ 905function getAllowedOperations($eventsource) { 906 if ($eventsource == EVENT_SOURCE_TRIGGERS) { 907 $operations = [ 908 ACTION_OPERATION => [ 909 OPERATION_TYPE_MESSAGE, 910 OPERATION_TYPE_COMMAND 911 ], 912 ACTION_RECOVERY_OPERATION => [ 913 OPERATION_TYPE_MESSAGE, 914 OPERATION_TYPE_COMMAND, 915 OPERATION_TYPE_RECOVERY_MESSAGE 916 ], 917 ACTION_ACKNOWLEDGE_OPERATION => [ 918 OPERATION_TYPE_MESSAGE, 919 OPERATION_TYPE_COMMAND, 920 OPERATION_TYPE_ACK_MESSAGE 921 ] 922 ]; 923 } 924 925 if ($eventsource == EVENT_SOURCE_DISCOVERY) { 926 $operations[ACTION_OPERATION] = [ 927 OPERATION_TYPE_MESSAGE, 928 OPERATION_TYPE_COMMAND, 929 OPERATION_TYPE_HOST_ADD, 930 OPERATION_TYPE_HOST_REMOVE, 931 OPERATION_TYPE_GROUP_ADD, 932 OPERATION_TYPE_GROUP_REMOVE, 933 OPERATION_TYPE_TEMPLATE_ADD, 934 OPERATION_TYPE_TEMPLATE_REMOVE, 935 OPERATION_TYPE_HOST_ENABLE, 936 OPERATION_TYPE_HOST_DISABLE, 937 OPERATION_TYPE_HOST_INVENTORY 938 ]; 939 } 940 941 if ($eventsource == EVENT_SOURCE_AUTOREGISTRATION) { 942 $operations[ACTION_OPERATION] = [ 943 OPERATION_TYPE_MESSAGE, 944 OPERATION_TYPE_COMMAND, 945 OPERATION_TYPE_HOST_ADD, 946 OPERATION_TYPE_HOST_REMOVE, 947 OPERATION_TYPE_GROUP_ADD, 948 OPERATION_TYPE_GROUP_REMOVE, 949 OPERATION_TYPE_TEMPLATE_ADD, 950 OPERATION_TYPE_TEMPLATE_REMOVE, 951 OPERATION_TYPE_HOST_ENABLE, 952 OPERATION_TYPE_HOST_DISABLE, 953 OPERATION_TYPE_HOST_INVENTORY 954 ]; 955 } 956 957 if ($eventsource == EVENT_SOURCE_INTERNAL) { 958 $operations = [ 959 ACTION_OPERATION => [OPERATION_TYPE_MESSAGE], 960 ACTION_RECOVERY_OPERATION => [ 961 OPERATION_TYPE_MESSAGE, 962 OPERATION_TYPE_RECOVERY_MESSAGE 963 ] 964 ]; 965 } 966 967 return $operations; 968} 969 970/** 971 * Get operation type text label according $type value. If $type is equal null array of all available operation types 972 * will be returned. 973 * 974 * @param int|null $type Operation type, one of OPERATION_TYPE_* constant or null. 975 * 976 * @return string|array 977 */ 978function operation_type2str($type) { 979 $types = [ 980 OPERATION_TYPE_MESSAGE => _('Send message'), 981 OPERATION_TYPE_COMMAND => _('Remote command'), 982 OPERATION_TYPE_HOST_ADD => _('Add host'), 983 OPERATION_TYPE_HOST_REMOVE => _('Remove host'), 984 OPERATION_TYPE_HOST_ENABLE => _('Enable host'), 985 OPERATION_TYPE_HOST_DISABLE => _('Disable host'), 986 OPERATION_TYPE_GROUP_ADD => _('Add to host group'), 987 OPERATION_TYPE_GROUP_REMOVE => _('Remove from host group'), 988 OPERATION_TYPE_TEMPLATE_ADD => _('Link to template'), 989 OPERATION_TYPE_TEMPLATE_REMOVE => _('Unlink from template'), 990 OPERATION_TYPE_HOST_INVENTORY => _('Set host inventory mode'), 991 OPERATION_TYPE_RECOVERY_MESSAGE => _('Notify all involved'), 992 OPERATION_TYPE_ACK_MESSAGE => _('Notify all involved') 993 ]; 994 995 if (is_null($type)) { 996 return order_result($types); 997 } 998 elseif (isset($types[$type])) { 999 return $types[$type]; 1000 } 1001 else { 1002 return _('Unknown'); 1003 } 1004} 1005 1006function sortOperations($eventsource, &$operations) { 1007 if ($eventsource == EVENT_SOURCE_TRIGGERS || $eventsource == EVENT_SOURCE_INTERNAL) { 1008 $esc_step_from = []; 1009 $esc_step_to = []; 1010 $esc_period = []; 1011 $operationTypes = []; 1012 1013 $simple_interval_parser = new CSimpleIntervalParser(); 1014 1015 foreach ($operations as $key => $operation) { 1016 $esc_step_from[$key] = $operation['esc_step_from']; 1017 $esc_step_to[$key] = $operation['esc_step_to']; 1018 // Try to sort by "esc_period" in seconds, otherwise sort as string in case it's a macro or something invalid. 1019 $esc_period[$key] = ($simple_interval_parser->parse($operation['esc_period']) == CParser::PARSE_SUCCESS) 1020 ? timeUnitToSeconds($operation['esc_period']) 1021 : $operation['esc_period']; 1022 1023 $operationTypes[$key] = $operation['operationtype']; 1024 } 1025 array_multisort($esc_step_from, SORT_ASC, $esc_step_to, SORT_ASC, $esc_period, SORT_ASC, $operationTypes, SORT_ASC, $operations); 1026 } 1027 else { 1028 CArrayHelper::sort($operations, ['operationtype']); 1029 } 1030} 1031 1032/** 1033 * Return an array of operators supported by the given action condition. 1034 * 1035 * @param int $conditiontype 1036 * 1037 * @return array 1038 */ 1039function get_operators_by_conditiontype($conditiontype) { 1040 $operators[CONDITION_TYPE_HOST_GROUP] = [ 1041 CONDITION_OPERATOR_EQUAL, 1042 CONDITION_OPERATOR_NOT_EQUAL 1043 ]; 1044 $operators[CONDITION_TYPE_TEMPLATE] = [ 1045 CONDITION_OPERATOR_EQUAL, 1046 CONDITION_OPERATOR_NOT_EQUAL 1047 ]; 1048 $operators[CONDITION_TYPE_HOST] = [ 1049 CONDITION_OPERATOR_EQUAL, 1050 CONDITION_OPERATOR_NOT_EQUAL 1051 ]; 1052 $operators[CONDITION_TYPE_TRIGGER] = [ 1053 CONDITION_OPERATOR_EQUAL, 1054 CONDITION_OPERATOR_NOT_EQUAL 1055 ]; 1056 $operators[CONDITION_TYPE_TRIGGER_NAME] = [ 1057 CONDITION_OPERATOR_LIKE, 1058 CONDITION_OPERATOR_NOT_LIKE 1059 ]; 1060 $operators[CONDITION_TYPE_TRIGGER_SEVERITY] = [ 1061 CONDITION_OPERATOR_EQUAL, 1062 CONDITION_OPERATOR_NOT_EQUAL, 1063 CONDITION_OPERATOR_MORE_EQUAL, 1064 CONDITION_OPERATOR_LESS_EQUAL 1065 ]; 1066 $operators[CONDITION_TYPE_TIME_PERIOD] = [ 1067 CONDITION_OPERATOR_IN, 1068 CONDITION_OPERATOR_NOT_IN 1069 ]; 1070 $operators[CONDITION_TYPE_SUPPRESSED] = [ 1071 CONDITION_OPERATOR_NO, 1072 CONDITION_OPERATOR_YES 1073 ]; 1074 $operators[CONDITION_TYPE_DRULE] = [ 1075 CONDITION_OPERATOR_EQUAL, 1076 CONDITION_OPERATOR_NOT_EQUAL 1077 ]; 1078 $operators[CONDITION_TYPE_DCHECK] = [ 1079 CONDITION_OPERATOR_EQUAL, 1080 CONDITION_OPERATOR_NOT_EQUAL 1081 ]; 1082 $operators[CONDITION_TYPE_DOBJECT] = [ 1083 CONDITION_OPERATOR_EQUAL 1084 ]; 1085 $operators[CONDITION_TYPE_PROXY] = [ 1086 CONDITION_OPERATOR_EQUAL, 1087 CONDITION_OPERATOR_NOT_EQUAL 1088 ]; 1089 $operators[CONDITION_TYPE_DHOST_IP] = [ 1090 CONDITION_OPERATOR_EQUAL, 1091 CONDITION_OPERATOR_NOT_EQUAL 1092 ]; 1093 $operators[CONDITION_TYPE_DSERVICE_TYPE] = [ 1094 CONDITION_OPERATOR_EQUAL, 1095 CONDITION_OPERATOR_NOT_EQUAL 1096 ]; 1097 $operators[CONDITION_TYPE_DSERVICE_PORT] = [ 1098 CONDITION_OPERATOR_EQUAL, 1099 CONDITION_OPERATOR_NOT_EQUAL 1100 ]; 1101 $operators[CONDITION_TYPE_DSTATUS] = [ 1102 CONDITION_OPERATOR_EQUAL 1103 ]; 1104 $operators[CONDITION_TYPE_DUPTIME] = [ 1105 CONDITION_OPERATOR_MORE_EQUAL, 1106 CONDITION_OPERATOR_LESS_EQUAL 1107 ]; 1108 $operators[CONDITION_TYPE_DVALUE] = [ 1109 CONDITION_OPERATOR_EQUAL, 1110 CONDITION_OPERATOR_NOT_EQUAL, 1111 CONDITION_OPERATOR_MORE_EQUAL, 1112 CONDITION_OPERATOR_LESS_EQUAL, 1113 CONDITION_OPERATOR_LIKE, 1114 CONDITION_OPERATOR_NOT_LIKE 1115 ]; 1116 $operators[CONDITION_TYPE_EVENT_ACKNOWLEDGED] = [ 1117 CONDITION_OPERATOR_EQUAL 1118 ]; 1119 $operators[CONDITION_TYPE_HOST_NAME] = [ 1120 CONDITION_OPERATOR_LIKE, 1121 CONDITION_OPERATOR_NOT_LIKE, 1122 CONDITION_OPERATOR_REGEXP, 1123 CONDITION_OPERATOR_NOT_REGEXP 1124 ]; 1125 $operators[CONDITION_TYPE_EVENT_TYPE] = [ 1126 CONDITION_OPERATOR_EQUAL 1127 ]; 1128 $operators[CONDITION_TYPE_HOST_METADATA] = [ 1129 CONDITION_OPERATOR_LIKE, 1130 CONDITION_OPERATOR_NOT_LIKE, 1131 CONDITION_OPERATOR_REGEXP, 1132 CONDITION_OPERATOR_NOT_REGEXP 1133 ]; 1134 $operators[CONDITION_TYPE_EVENT_TAG] = [ 1135 CONDITION_OPERATOR_EQUAL, 1136 CONDITION_OPERATOR_NOT_EQUAL, 1137 CONDITION_OPERATOR_LIKE, 1138 CONDITION_OPERATOR_NOT_LIKE 1139 ]; 1140 $operators[CONDITION_TYPE_EVENT_TAG_VALUE] = [ 1141 CONDITION_OPERATOR_EQUAL, 1142 CONDITION_OPERATOR_NOT_EQUAL, 1143 CONDITION_OPERATOR_LIKE, 1144 CONDITION_OPERATOR_NOT_LIKE 1145 ]; 1146 1147 if (isset($operators[$conditiontype])) { 1148 return $operators[$conditiontype]; 1149 } 1150 1151 return []; 1152} 1153 1154function count_operations_delay($operations, $def_period) { 1155 $delays = [1 => 0]; 1156 $periods = []; 1157 $max_step = 0; 1158 1159 $simple_interval_parser = new CSimpleIntervalParser(); 1160 1161 $def_period = CMacrosResolverHelper::resolveTimeUnitMacros( 1162 [['def_period' => $def_period]], ['def_period'] 1163 )[0]['def_period']; 1164 1165 $def_period = ($simple_interval_parser->parse($def_period) == CParser::PARSE_SUCCESS) 1166 ? timeUnitToSeconds($def_period) 1167 : null; 1168 1169 $operations = CMacrosResolverHelper::resolveTimeUnitMacros($operations, ['esc_period']); 1170 1171 foreach ($operations as $operation) { 1172 $esc_period = ($simple_interval_parser->parse($operation['esc_period']) == CParser::PARSE_SUCCESS) 1173 ? timeUnitToSeconds($operation['esc_period']) 1174 : null; 1175 1176 $esc_period = ($esc_period === null || $esc_period != 0) ? $esc_period : $def_period; 1177 $step_to = ($operation['esc_step_to'] != 0) ? $operation['esc_step_to'] : 9999; 1178 1179 if ($max_step < $operation['esc_step_from']) { 1180 $max_step = $operation['esc_step_from']; 1181 } 1182 1183 for ($i = $operation['esc_step_from']; $i <= $step_to; $i++) { 1184 if (!array_key_exists($i, $periods) || $esc_period === null || $periods[$i] > $esc_period) { 1185 $periods[$i] = $esc_period; 1186 } 1187 } 1188 } 1189 1190 for ($i = 1; $i <= $max_step; $i++) { 1191 $esc_period = array_key_exists($i, $periods) ? $periods[$i] : $def_period; 1192 $delays[$i + 1] = ($esc_period !== null && $delays[$i] !== null) ? $delays[$i] + $esc_period : null; 1193 } 1194 1195 return $delays; 1196} 1197 1198/** 1199 * Returns the names of the "Event type" action condition values. 1200 * 1201 * If the $type parameter is passed, returns the name of the specific value, otherwise - returns an array of all 1202 * supported values. 1203 * 1204 * @param string $type 1205 * 1206 * @return array|string 1207 */ 1208function eventType($type = null) { 1209 $types = [ 1210 EVENT_TYPE_ITEM_NOTSUPPORTED => _('Item in "not supported" state'), 1211 EVENT_TYPE_LLDRULE_NOTSUPPORTED => _('Low-level discovery rule in "not supported" state'), 1212 EVENT_TYPE_TRIGGER_UNKNOWN => _('Trigger in "unknown" state') 1213 ]; 1214 1215 if (is_null($type)) { 1216 return $types; 1217 } 1218 1219 return $types[$type]; 1220} 1221 1222/** 1223 * Get data required to create messages, severity changes, actions icon with popup with event actions. 1224 * 1225 * @param array $events Array with event objects with acknowledges. 1226 * @param array $triggers Array of triggers. 1227 * 1228 * @return array 1229 */ 1230function getEventsActionsIconsData(array $events, array $triggers) { 1231 $messages = getEventsMessages($events); 1232 $severities = getEventsSeverityChanges($events, $triggers); 1233 $actions = getEventsAlertsOverview($events); 1234 1235 return [ 1236 'data' => [ 1237 'messages' => $messages['data'], 1238 'severities' => $severities['data'], 1239 'actions' => $actions 1240 ], 1241 'userids' => $messages['userids'] + $severities['userids'] 1242 ]; 1243} 1244 1245/** 1246 * Get data, required to create messages icon with popup with event messages. 1247 * 1248 * @param array $events Array with event objects with acknowledges. 1249 * @param string $events[]['eventid'] Problem event ID. 1250 * @param array $events[]['acknowledges'] Array with manual updates to problem. 1251 * @param string $events[]['acknowledges'][]['action'] Action that was performed by problem update. 1252 * @param string $events[]['acknowledges'][]['message'] Message text. 1253 * @param string $events[]['acknowledges'][]['clock'] Time when message was added. 1254 * @param string $events[]['acknowledges'][]['userid'] Author's userid. 1255 * 1256 * @return array 1257 */ 1258function getEventsMessages(array $events) { 1259 $messages = []; 1260 $userids = []; 1261 1262 // Create array of messages for each event 1263 foreach ($events as $event) { 1264 $event_messages = []; 1265 1266 foreach ($event['acknowledges'] as $ack) { 1267 if (($ack['action'] & ZBX_PROBLEM_UPDATE_MESSAGE) == ZBX_PROBLEM_UPDATE_MESSAGE) { 1268 $event_messages[] = [ 1269 'message' => $ack['message'], 1270 'userid' => $ack['userid'], 1271 'clock' => $ack['clock'] 1272 ]; 1273 1274 $userids[$ack['userid']] = true; 1275 } 1276 } 1277 1278 CArrayHelper::sort($event_messages, [['field' => 'clock', 'order' => ZBX_SORT_DOWN]]); 1279 1280 $messages[$event['eventid']] = [ 1281 'messages' => array_values($event_messages), 1282 'count' => count($event_messages) 1283 ]; 1284 } 1285 1286 return [ 1287 'data' => $messages, 1288 'userids' => $userids 1289 ]; 1290} 1291 1292/** 1293 * Get data, required to create severity changes icon with popup with event severity changes. 1294 * 1295 * @param array $events Array with event objects with acknowledges. 1296 * @param string $events[]['eventid'] Problem event ID. 1297 * @param string $events[]['severity'] Current event severity. 1298 * @param string $events[]['objectid'] Related trigger ID. 1299 * @param array $events[]['acknowledges'] Array with manual updates to problem. 1300 * @param string $events[]['acknowledges'][]['action'] Action that was performed by problem update. 1301 * @param string $events[]['acknowledges'][]['clock'] Time when severity was changed. 1302 * @param string $events[]['acknowledges'][]['old_severity'] Severity before the change. 1303 * @param string $events[]['acknowledges'][]['new_severity'] Severity after the change. 1304 * @param string $events[]['acknowledges'][]['userid'] Responsible user's userid. 1305 * @param array $triggers Related trigger data. 1306 * @param string $triggers[]['priority'] Severity of trigger. 1307 * 1308 * @return array 1309 */ 1310function getEventsSeverityChanges(array $events, array $triggers) { 1311 $severities = []; 1312 $userids = []; 1313 1314 // Create array of messages for each event. 1315 foreach ($events as $event) { 1316 $event_severities = []; 1317 1318 foreach ($event['acknowledges'] as $ack) { 1319 if (($ack['action'] & ZBX_PROBLEM_UPDATE_SEVERITY) == ZBX_PROBLEM_UPDATE_SEVERITY) { 1320 $event_severities[] = [ 1321 'old_severity' => $ack['old_severity'], 1322 'new_severity' => $ack['new_severity'], 1323 'userid' => $ack['userid'], 1324 'clock' => $ack['clock'] 1325 ]; 1326 1327 $userids[$ack['userid']] = true; 1328 } 1329 } 1330 1331 CArrayHelper::sort($event_severities, [['field' => 'clock', 'order' => ZBX_SORT_DOWN]]); 1332 1333 $severities[$event['eventid']] = [ 1334 'severities' => array_values($event_severities), 1335 'count' => count($event_severities), 1336 'original_severity' => $triggers[$event['objectid']]['priority'], 1337 'current_severity' => $event['severity'] 1338 ]; 1339 } 1340 1341 return [ 1342 'data' => $severities, 1343 'userids' => $userids 1344 ]; 1345} 1346 1347/** 1348 * Get data, required to create actions icon. 1349 * 1350 * @param array $events Array with event objects with acknowledges. 1351 * @param string $events[]['eventid'] Problem event ID. 1352 * @param string $events[]['r_eventid'] OK event ID. 1353 * 1354 * @return array List indexed by eventid containing overview on event alerts. 1355 */ 1356function getEventsAlertsOverview(array $events): array { 1357 $alert_eventids = []; 1358 $actions = []; 1359 $event_alert_state = []; 1360 1361 foreach ($events as $event) { 1362 // Get alerts for event. 1363 $alert_eventids[$event['eventid']] = true; 1364 1365 // Get alerts for related recovery events. 1366 if ($event['r_eventid'] != 0) { 1367 $alert_eventids[$event['r_eventid']] = true; 1368 } 1369 } 1370 1371 if ($alert_eventids) { 1372 $event_alert_state = array_combine(array_keys($alert_eventids), array_fill(0, count($alert_eventids), [ 1373 'failed_cnt' => 0, 1374 'in_progress_cnt' => 0, 1375 'total_cnt' => 0 1376 ])); 1377 1378 $alerts = API::Alert()->get([ 1379 'groupCount' => true, 1380 'countOutput' => true, 1381 'filter' => ['status' => ALERT_STATUS_FAILED], 1382 'eventids' => array_keys($alert_eventids) 1383 ]); 1384 1385 foreach ($alerts as $alert) { 1386 $event_alert_state[$alert['eventid']]['failed_cnt'] = (int) $alert['rowscount']; 1387 } 1388 1389 $alerts = API::Alert()->get([ 1390 'groupCount' => true, 1391 'countOutput' => true, 1392 'filter' => ['status' => [ALERT_STATUS_NEW, ALERT_STATUS_NOT_SENT]], 1393 'eventids' => array_keys($alert_eventids) 1394 ]); 1395 1396 foreach ($alerts as $alert) { 1397 $event_alert_state[$alert['eventid']]['in_progress_cnt'] = (int) $alert['rowscount']; 1398 } 1399 1400 $alerts = API::Alert()->get([ 1401 'groupCount' => true, 1402 'countOutput' => true, 1403 'eventids' => array_keys($alert_eventids) 1404 ]); 1405 1406 foreach ($alerts as $alert) { 1407 $event_alert_state[$alert['eventid']]['total_cnt'] = (int) $alert['rowscount']; 1408 } 1409 } 1410 1411 // Create array of actions for each event. 1412 foreach ($events as $event) { 1413 $event_actions = $event_alert_state[$event['eventid']]; 1414 if ($event['r_eventid']) { 1415 $r_event_actions = $event_alert_state[$event['r_eventid']]; 1416 $event_actions['failed_cnt'] += $r_event_actions['failed_cnt']; 1417 $event_actions['total_cnt'] += $r_event_actions['total_cnt']; 1418 $event_actions['in_progress_cnt'] += $r_event_actions['in_progress_cnt']; 1419 } 1420 1421 $actions[$event['eventid']] = [ 1422 'count' => $event_actions['total_cnt'] + count($event['acknowledges']), 1423 'has_uncomplete_action' => (bool) $event_actions['in_progress_cnt'], 1424 'has_failed_action' => (bool) $event_actions['failed_cnt'] 1425 ]; 1426 } 1427 1428 return $actions; 1429} 1430 1431/** 1432 * Get data, required to create table with all (automatic and manual) actions for Event details page. 1433 * 1434 * @param array $event Event object with acknowledges. 1435 * @param string $event['eventid'] Problem event ID. 1436 * @param string $event['r_eventid'] OK event ID. 1437 * 1438 * @return array 1439 */ 1440function getEventDetailsActions(array $event) { 1441 $r_events = []; 1442 1443 // Select eventids for alert retrieval. 1444 $alert_eventids = [$event['eventid']]; 1445 1446 if ($event['r_eventid'] != 0) { 1447 $alert_eventids[] = $event['r_eventid']; 1448 1449 $r_events = API::Event()->get([ 1450 'output' => ['clock'], 1451 'eventids' => $event['r_eventid'], 1452 'preservekeys' => true 1453 ]); 1454 } 1455 1456 $search_limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT); 1457 1458 // Get automatic actions (alerts). 1459 $alerts = API::Alert()->get([ 1460 'output' => ['alerttype', 'clock', 'error', 'eventid', 'esc_step', 'mediatypeid', 'message', 'retries', 1461 'sendto', 'status', 'subject', 'userid', 'p_eventid', 'acknowledgeid' 1462 ], 1463 'eventids' => $alert_eventids, 1464 'config' => $search_limit 1465 ]); 1466 1467 $actions = getSingleEventActions($event, $r_events, $alerts); 1468 1469 return [ 1470 'actions' => $actions['actions'], 1471 'mediatypeids' => $actions['mediatypeids'], 1472 'userids' => $actions['userids'], 1473 'count' => $actions['count'] 1474 ]; 1475} 1476 1477/** 1478 * Get array with all actions for single event. 1479 * 1480 * @param array $event Event objects with acknowledges. 1481 * @param string $event['eventid'] Problem event ID. 1482 * @param string $event['r_eventid'] OK event ID. 1483 * @param string $event['clock'] Time when event occurred. 1484 * @param array $event['acknowledges'] Array with manual updates to problem. 1485 * @param string $event['acknowledges'][]['userid'] User ID. 1486 * @param array $r_events Recovery event data for all requested events. 1487 * @param string $r_events[]['clock'] Recovery event creation time. 1488 * @param array $alerts Alert data for all requested alerts. 1489 * @param string $alerts[]['eventid'] If of problem event for which this alert was generated. 1490 * @param string $alerts[]['mediatypeid'] ID for mediatype used for alert. 1491 * @param string $alerts[]['alerttype'] Type of alert. 1492 * @param string $alerts[]['status'] Alert status. 1493 * @param string $alerts[]['userid'] ID of alert recipient. 1494 * 1495 * @return array 1496 */ 1497function getSingleEventActions(array $event, array $r_events, array $alerts) { 1498 $action_count = 0; 1499 $has_uncomplete_action = false; 1500 $has_failed_action = false; 1501 $mediatypeids = []; 1502 $userids = []; 1503 1504 // Create array of automatically and manually performed actions combined. 1505 $actions = []; 1506 1507 // Add row for problem generation event. 1508 $actions[] = [ 1509 'action_type' => ZBX_EVENT_HISTORY_PROBLEM_EVENT, 1510 'clock' => $event['clock'] 1511 ]; 1512 1513 // Add row for problem recovery event. 1514 if (array_key_exists($event['r_eventid'], $r_events)) { 1515 $actions[] = [ 1516 'action_type' => ZBX_EVENT_HISTORY_RECOVERY_EVENT, 1517 'clock' => $r_events[$event['r_eventid']]['clock'] 1518 ]; 1519 } 1520 1521 // Add manual operations. 1522 foreach ($event['acknowledges'] as $ack) { 1523 $ack['action_type'] = ZBX_EVENT_HISTORY_MANUAL_UPDATE; 1524 $actions[] = $ack; 1525 1526 $action_count++; 1527 $userids[$ack['userid']] = true; 1528 } 1529 1530 // Add alerts. 1531 foreach ($alerts as $alert) { 1532 // Add only alerts, related to current event. 1533 if (bccomp($alert['eventid'], $event['eventid']) == 0 1534 || bccomp($alert['eventid'], $event['r_eventid']) == 0) { 1535 $alert['action_type'] = ZBX_EVENT_HISTORY_ALERT; 1536 $actions[] = $alert; 1537 1538 $action_count++; 1539 1540 if ($alert['alerttype'] == ALERT_TYPE_MESSAGE) { 1541 if ($alert['mediatypeid'] != 0) { 1542 $mediatypeids[$alert['mediatypeid']] = true; 1543 } 1544 1545 if ($alert['userid'] != 0) { 1546 $userids[$alert['userid']] = true; 1547 } 1548 } 1549 1550 if ($alert['status'] == ALERT_STATUS_NEW || $alert['status'] == ALERT_STATUS_NOT_SENT) { 1551 $has_uncomplete_action = true; 1552 } 1553 elseif ($alert['status'] == ALERT_STATUS_FAILED) { 1554 $has_failed_action = true; 1555 } 1556 } 1557 } 1558 1559 // Sort by action_type is done to put Recovery event before actions, resulted from it. Same for other action_type. 1560 CArrayHelper::sort($actions, [ 1561 ['field' => 'clock', 'order' => ZBX_SORT_DOWN], 1562 ['field' => 'action_type', 'order' => ZBX_SORT_DOWN] 1563 ]); 1564 1565 return [ 1566 'actions' => array_values($actions), 1567 'count' => $action_count, 1568 'has_uncomplete_action' => $has_uncomplete_action, 1569 'has_failed_action' => $has_failed_action, 1570 'mediatypeids' => $mediatypeids, 1571 'userids' => $userids 1572 ]; 1573} 1574 1575/** 1576 * Get data required to create history list in problem update page. 1577 * 1578 * @param array $event Array with event objects with acknowledges. 1579 * @param array $event['acknowledges'] Array with manual updates to problem. 1580 * @param string $event['acknowledges'][]['clock'] Time when severity was changed. 1581 * @param string $event['acknowledges'][]['userid'] Responsible user's userid. 1582 * 1583 * @return array 1584 */ 1585function getEventUpdates(array $event) { 1586 $userids = []; 1587 1588 foreach ($event['acknowledges'] as $ack) { 1589 $userids[$ack['userid']] = true; 1590 } 1591 1592 CArrayHelper::sort($event['acknowledges'], [['field' => 'clock', 'order' => ZBX_SORT_DOWN]]); 1593 1594 return [ 1595 'data' => array_values($event['acknowledges']), 1596 'userids' => $userids 1597 ]; 1598} 1599 1600/** 1601 * Make icons (messages, severity changes, actions) for actions column. 1602 * 1603 * @param string $eventid Id for event, for which icons are created. 1604 * @param array $actions Array of actions data. 1605 * @param array $actions['messages'] Messages icon data. 1606 * @param array $actions['severities'] Severity change icon data. 1607 * @param array $actions['actions'] Actions icon data. 1608 * @param array $users User name, surname and username. 1609 * 1610 * @return CCol|string 1611 */ 1612function makeEventActionsIcons($eventid, $actions, $users) { 1613 $messages_icon = makeEventMessagesIcon($actions['messages'][$eventid], $users); 1614 $severities_icon = makeEventSeverityChangesIcon($actions['severities'][$eventid], $users); 1615 $actions_icon = makeEventActionsIcon($actions['actions'][$eventid], $eventid); 1616 1617 $action_icons = []; 1618 if ($messages_icon !== null) { 1619 $action_icons[] = $messages_icon; 1620 } 1621 if ($severities_icon !== null) { 1622 $action_icons[] = $severities_icon; 1623 } 1624 if ($actions_icon !== null) { 1625 $action_icons[] = $actions_icon; 1626 } 1627 1628 return $action_icons ? (new CCol($action_icons))->addClass(ZBX_STYLE_NOWRAP) : ''; 1629} 1630 1631/** 1632 * Create icon with hintbox for event messages. 1633 * 1634 * @param array $data 1635 * @param array $data['messages'] Array of messages. 1636 * @param string $data['messages'][]['message'] Message text. 1637 * @param string $data['messages'][]['clock'] Message creation time. 1638 * @param array $users User name, surname and username. 1639 * 1640 * @return CButton|null 1641 */ 1642function makeEventMessagesIcon(array $data, array $users): ?CButton { 1643 $total = $data['count']; 1644 1645 $table = (new CTableInfo())->setHeader([_('Time'), _('User'), _('Message')]); 1646 1647 for ($i = 0; $i < $total && $i < ZBX_WIDGET_ROWS; $i++) { 1648 $message = $data['messages'][$i]; 1649 1650 // Added in order to reuse makeActionTableUser(). 1651 $message['action_type'] = ZBX_EVENT_HISTORY_MANUAL_UPDATE; 1652 1653 $table->addRow([ 1654 zbx_date2str(DATE_TIME_FORMAT_SECONDS, $message['clock']), 1655 makeActionTableUser($message, $users), 1656 zbx_nl2br($message['message']) 1657 ]); 1658 } 1659 1660 return $total 1661 ? makeActionIcon([ 1662 'icon' => ZBX_STYLE_ACTION_ICON_MSGS, 1663 'button' => true, 1664 'hint' => [ 1665 $table, 1666 ($total > ZBX_WIDGET_ROWS) 1667 ? (new CDiv( 1668 (new CDiv( 1669 (new CDiv(_s('Displaying %1$s of %2$s found', ZBX_WIDGET_ROWS, $total))) 1670 ->addClass(ZBX_STYLE_TABLE_STATS) 1671 ))->addClass(ZBX_STYLE_PAGING_BTN_CONTAINER) 1672 ))->addClass(ZBX_STYLE_TABLE_PAGING) 1673 : null 1674 ], 1675 'num' => $total, 1676 'aria-label' => _xn('%1$s message', '%1$s messages', $total, 'screen reader', $total) 1677 ]) 1678 : null; 1679} 1680 1681/** 1682 * Create icon with hintbox for event severity changes. 1683 * 1684 * @param array $data 1685 * @param array $data['severities'] Array of severities. 1686 * @param string $data['severities'][]['old_severity'] Event severity before change. 1687 * @param string $data['severities'][]['new_severity'] Event severity after change. 1688 * @param string $data['severities'][]['clock'] Severity change time. 1689 * @param string $data['original_severity'] Severity before change. 1690 * @param string $data['current_severity'] Current severity. 1691 * @param int $data['count'] Total number of severity changes. 1692 * @param array $users User name, surname and username. 1693 * 1694 * @return CButton|null 1695 */ 1696function makeEventSeverityChangesIcon(array $data, array $users): ?CButton { 1697 $total = $data['count']; 1698 1699 $table = (new CTableInfo())->setHeader([_('Time'), _('User'), _('Severity changes')]); 1700 1701 for ($i = 0; $i < $total && $i < ZBX_WIDGET_ROWS; $i++) { 1702 $severity = $data['severities'][$i]; 1703 1704 // Added in order to reuse makeActionTableUser(). 1705 $severity['action_type'] = ZBX_EVENT_HISTORY_MANUAL_UPDATE; 1706 1707 // severity changes 1708 $old_severity_name = getSeverityName($severity['old_severity']); 1709 $new_severity_name = getSeverityName($severity['new_severity']); 1710 1711 $table->addRow([ 1712 zbx_date2str(DATE_TIME_FORMAT_SECONDS, $severity['clock']), 1713 makeActionTableUser($severity, $users), 1714 $old_severity_name.' ⇒ '.$new_severity_name 1715 ]); 1716 } 1717 1718 // select icon 1719 if ($data['original_severity'] > $data['current_severity']) { 1720 $icon_style = ZBX_STYLE_ACTION_ICON_SEV_DOWN; 1721 $aria_label = _x('Severity decreased', 'screen reader'); 1722 } 1723 elseif ($data['original_severity'] < $data['current_severity']) { 1724 $icon_style = ZBX_STYLE_ACTION_ICON_SEV_UP; 1725 $aria_label = _x('Severity increased', 'screen reader'); 1726 } 1727 else { 1728 $icon_style = ZBX_STYLE_ACTION_ICON_SEV_CHANGED; 1729 $aria_label = _x('Severity changed', 'screen reader'); 1730 } 1731 1732 return $total 1733 ? makeActionIcon([ 1734 'button' => true, 1735 'icon' => $icon_style, 1736 'hint' => [ 1737 $table, 1738 ($total > ZBX_WIDGET_ROWS) 1739 ? (new CDiv( 1740 (new CDiv( 1741 (new CDiv(_s('Displaying %1$s of %2$s found', ZBX_WIDGET_ROWS, $total))) 1742 ->addClass(ZBX_STYLE_TABLE_STATS) 1743 ))->addClass(ZBX_STYLE_PAGING_BTN_CONTAINER) 1744 ))->addClass(ZBX_STYLE_TABLE_PAGING) 1745 : null 1746 ], 1747 'aria-label' => $aria_label 1748 ]) 1749 : null; 1750} 1751 1752/** 1753 * @param array $actions Array with all actions sorted by clock. 1754 * @param int $actions[]['action_type'] Type of action table entry (ZBX_EVENT_HISTORY_*). 1755 * @param string $actions[]['clock'] Time, when action was performed. 1756 * @param string $actions[]['message'] Message sent by alert, or written by manual update, or remote command text. 1757 * @param string $actions[]['action'] Flag with problem update operation performed (only for ZBX_EVENT_HISTORY_MANUAL_UPDATE). 1758 * @param string $actions[]['alerttype'] Type of alert (only for ZBX_EVENT_HISTORY_ALERT). 1759 * @param string $actions[]['mediatypeid'] Id for mediatype, where alert message was sent (only for ZBX_EVENT_HISTORY_ALERT). 1760 * @param string $actions[]['error'] Error message in case of failed alert (only for ZBX_EVENT_HISTORY_ALERT). 1761 * @param array $users User name, surname and username. 1762 * @param array $mediatypes Mediatypes with maxattempts value and name. 1763 * @param string $mediatypes[]['name'] Mediatype name. 1764 * @param string $mediatypes[]['maxattempts'] Maximum attempts for this mediatype. 1765 * 1766 * @return CTableInfo 1767 */ 1768function makeEventActionsTable(array $actions, array $users, array $mediatypes): CTableInfo { 1769 $action_count = count($actions); 1770 1771 $table = (new CTableInfo())->setHeader([ 1772 _('Time'), _('User/Recipient'), _('Action'), _('Message/Command'), _('Status'), _('Info') 1773 ]); 1774 1775 for ($i = 0; $i < $action_count && $i < ZBX_WIDGET_ROWS; $i++) { 1776 $action = $actions[$i]; 1777 1778 $message = ''; 1779 if ($action['action_type'] == ZBX_EVENT_HISTORY_MANUAL_UPDATE 1780 && ($action['action'] & ZBX_PROBLEM_UPDATE_MESSAGE) == ZBX_PROBLEM_UPDATE_MESSAGE) { 1781 $message = zbx_nl2br($action['message']); 1782 } 1783 elseif ($action['action_type'] == ZBX_EVENT_HISTORY_ALERT) { 1784 if ($action['alerttype'] == ALERT_TYPE_COMMAND) { 1785 $message = _('Remote command'); 1786 } 1787 elseif ($action['alerttype'] == ALERT_TYPE_MESSAGE) { 1788 $message = array_key_exists($action['mediatypeid'], $mediatypes) 1789 ? $mediatypes[$action['mediatypeid']]['name'] 1790 : ''; 1791 } 1792 } 1793 1794 $table->addRow([ 1795 zbx_date2str(DATE_TIME_FORMAT_SECONDS, $action['clock']), 1796 makeActionTableUser($action, $users), 1797 makeActionTableIcon($action), 1798 $message, 1799 makeActionTableStatus($action), 1800 makeActionTableInfo($action, $mediatypes) 1801 ]); 1802 } 1803 1804 return $table; 1805} 1806 1807/** 1808 * Create icon with hintbox for event actions. 1809 * 1810 * @param array $data 1811 * @param int $data['count'] Number of actions. 1812 * @param bool $data['has_uncomplete_action'] Does the event have at least one uncompleted alert action. 1813 * @param bool $data['has_failed_action'] Does the event have at least one failed alert action. 1814 * @param string $eventid 1815 * 1816 * @return CButton|null 1817 */ 1818function makeEventActionsIcon(array $data, $eventid): ?CButton { 1819 // Number of meaningful actions. 1820 $total = $data['count']; 1821 1822 // select icon 1823 if ($data['has_failed_action']) { 1824 $icon_style = ZBX_STYLE_ACTIONS_NUM_RED; 1825 } 1826 elseif ($data['has_uncomplete_action']) { 1827 $icon_style = ZBX_STYLE_ACTIONS_NUM_YELLOW; 1828 } 1829 else { 1830 $icon_style = ZBX_STYLE_ACTIONS_NUM_GRAY; 1831 } 1832 1833 return $total 1834 ? makeActionIcon([ 1835 'icon' => $icon_style, 1836 'button' => true, 1837 'num' => $total, 1838 'aria-label' => _xn('%1$s action', '%1$s actions', $total, 'screen reader', $total) 1839 ])->setAjaxHint([ 1840 'type' => 'eventactions', 1841 'data' => ['eventid' => $eventid] 1842 ]) 1843 : null; 1844} 1845 1846/** 1847 * Get table with list of event actions for event details page. 1848 * 1849 * @param array $data 1850 * @param array $data['actions'] Array with all actions sorted by clock. 1851 * @param int $data['actions'][]['action_type'] Type of action table entry (ZBX_EVENT_HISTORY_*). 1852 * @param string $data['actions'][]['clock'] Time, when action was performed. 1853 * @param string $data['actions'][]['message'] Message sent by alert, or written by manual update, or remote command text. 1854 * @param string $data['actions'][]['alerttype'] Type of alert (only for ZBX_EVENT_HISTORY_ALERT). 1855 * @param string $data['actions'][]['esc_step'] Alert escalation step (only for ZBX_EVENT_HISTORY_ALERT). 1856 * @param string $data['actions'][]['subject'] Message alert subject (only for ZBX_EVENT_HISTORY_ALERT). 1857 * @param string $data['actions'][]['p_eventid'] Problem eventid that was reason for alert (only for ZBX_EVENT_HISTORY_ALERT). 1858 * @param string $data['actions'][]['acknowledgeid'] Problem update action that was reason for alert (only for ZBX_EVENT_HISTORY_ALERT). 1859 * @param array $users User name, surname and username. 1860 * @param array $mediatypes Mediatypes with maxattempts value. 1861 * 1862 * @return CTableInfo 1863 */ 1864function makeEventDetailsActionsTable(array $data, array $users, array $mediatypes) { 1865 $table = (new CTableInfo())->setHeader([ 1866 _('Step'), _('Time'), _('User/Recipient'), _('Action'), _('Message/Command'), _('Status'), _('Info') 1867 ]); 1868 1869 foreach ($data['actions'] as $action) { 1870 $esc_step = ''; 1871 1872 if ($action['action_type'] == ZBX_EVENT_HISTORY_ALERT && $action['p_eventid'] == 0 1873 && $action['acknowledgeid'] == 0) { 1874 /* 1875 * Escalation step should be displayed, only if alert is caused by problem event. 1876 * Escalation step should not be displayed, if alert is caused by resolve event, or by problem update. 1877 */ 1878 $esc_step = $action['esc_step']; 1879 } 1880 1881 $message = ''; 1882 if ($action['action_type'] == ZBX_EVENT_HISTORY_ALERT && $action['alerttype'] == ALERT_TYPE_MESSAGE) { 1883 $message = [bold($action['subject']), BR(), BR(), zbx_nl2br($action['message'])]; 1884 } 1885 elseif (($action['action_type'] == ZBX_EVENT_HISTORY_ALERT && $action['alerttype'] == ALERT_TYPE_COMMAND) 1886 || $action['action_type'] == ZBX_EVENT_HISTORY_MANUAL_UPDATE) { 1887 $message = [ 1888 bold(_('Command').':'), 1889 BR(), 1890 zbx_nl2br($action['message']) 1891 ]; 1892 } 1893 1894 $table->addRow([ 1895 $esc_step, 1896 zbx_date2str(DATE_TIME_FORMAT_SECONDS, $action['clock']), 1897 makeEventDetailsTableUser($action, $users), 1898 makeActionTableIcon($action), 1899 $message, 1900 makeActionTableStatus($action), 1901 makeActionTableInfo($action, $mediatypes) 1902 ]); 1903 } 1904 1905 return $table; 1906} 1907 1908/** 1909 * Get table with list of event updates for update event page. 1910 * 1911 * @param array $actions Array with all actions sorted by clock. 1912 * @param string $actions[]['clock'] Time, when action was performed. 1913 * @param string $actions[]['message'] Message sent by alert, or written by manual update, or remote command text. 1914 * @param array $users User name, surname and username. 1915 * 1916 * @return CTable 1917 */ 1918function makeEventHistoryTable(array $actions, array $users) { 1919 $table = (new CTable()) 1920 ->addStyle('width: 100%;') 1921 ->setHeader([_('Time'), _('User'), _('User action'), _('Message')]); 1922 1923 foreach ($actions as $action) { 1924 // Added in order to reuse makeActionTableUser() and makeActionTableIcon() 1925 $action['action_type'] = ZBX_EVENT_HISTORY_MANUAL_UPDATE; 1926 1927 $table->addRow([ 1928 zbx_date2str(DATE_TIME_FORMAT_SECONDS, $action['clock']), 1929 makeActionTableUser($action, $users), 1930 makeActionTableIcon($action), 1931 (new CCol(zbx_nl2br($action['message'])))->addClass(ZBX_STYLE_TABLE_FORMS_OVERFLOW_BREAK) 1932 ]); 1933 } 1934 1935 return $table; 1936} 1937 1938/** 1939 * Creates username for message author or alert receiver. 1940 * 1941 * @param array $action Array of action data. 1942 * @param int $action['action_type'] Type of event table action (ZBX_EVENT_HISTORY_*). 1943 * @param string $action['alerttype'] Type of alert. 1944 * @param string $action['userid'] ID of message author, or alert receiver. 1945 * @param array $users Array with user data - username, name, surname. 1946 * 1947 * @return string 1948 */ 1949function makeActionTableUser(array $action, array $users) { 1950 if (($action['action_type'] == ZBX_EVENT_HISTORY_ALERT && $action['alerttype'] == ALERT_TYPE_MESSAGE) 1951 || $action['action_type'] == ZBX_EVENT_HISTORY_MANUAL_UPDATE) { 1952 return array_key_exists($action['userid'], $users) 1953 ? getUserFullname($users[$action['userid']]) 1954 : _('Inaccessible user'); 1955 } 1956 else { 1957 return ''; 1958 } 1959} 1960 1961/** 1962 * Creates username for message author or alert receiver. Also contains 'sendto' for message actions. 1963 * 1964 * @param array $action 1965 * @param int $action['action_type'] Type of event table action (ZBX_EVENT_HISTORY_*). 1966 * @param string $action['alerttype'] Type of alert. 1967 * @param array $action['userid'] ID of message author, or alert receiver. 1968 * @param array $action['sendto'] Receiver media address for automatic action. 1969 * @param array $users Array with user data - username, name, surname. 1970 * 1971 * @return string 1972 */ 1973function makeEventDetailsTableUser(array $action, array $users) { 1974 if ($action['action_type'] == ZBX_EVENT_HISTORY_ALERT && $action['alerttype'] == ALERT_TYPE_MESSAGE) { 1975 return array_key_exists($action['userid'], $users) 1976 ? [getUserFullname($users[$action['userid']]), BR(), italic(zbx_nl2br($action['sendto']))] 1977 : _('Inaccessible user'); 1978 } 1979 elseif ($action['action_type'] == ZBX_EVENT_HISTORY_MANUAL_UPDATE) { 1980 return array_key_exists($action['userid'], $users) 1981 ? getUserFullname($users[$action['userid']]) 1982 : _('Inaccessible user'); 1983 } 1984 else { 1985 return ''; 1986 } 1987} 1988 1989/** 1990 * Make appropriate icon for event action. 1991 * 1992 * @param array $action Array with actions table data. 1993 * @param int $action['action_type'] Type of action table entry (ZBX_EVENT_HISTORY_*). 1994 * @param int $action['action'] Flag with problem update operation performed. (only for ZBX_EVENT_HISTORY_MANUAL_UPDATE) 1995 * @param int $action['old_severity'] Severity before problem update. (only for ZBX_EVENT_HISTORY_MANUAL_UPDATE) 1996 * @param int $action['new_severity'] Severity after problem update. (only for ZBX_EVENT_HISTORY_MANUAL_UPDATE) 1997 * @param int $action['alerttype'] Type of alert. (only for ZBX_EVENT_HISTORY_ALERT) 1998 * 1999 * @return CSpan 2000 */ 2001function makeActionTableIcon(array $action) { 2002 switch ($action['action_type']) { 2003 case ZBX_EVENT_HISTORY_PROBLEM_EVENT: 2004 return makeActionIcon(['icon' => ZBX_STYLE_PROBLEM_GENERATED, 'title' => _('Problem created')]); 2005 2006 case ZBX_EVENT_HISTORY_RECOVERY_EVENT: 2007 return makeActionIcon(['icon' => ZBX_STYLE_PROBLEM_RECOVERY, 'title' => _('Problem resolved')]); 2008 2009 case ZBX_EVENT_HISTORY_MANUAL_UPDATE: 2010 $action_icons = []; 2011 2012 if (($action['action'] & ZBX_PROBLEM_UPDATE_CLOSE) == ZBX_PROBLEM_UPDATE_CLOSE) { 2013 $action_icons[] = makeActionIcon([ 2014 'icon' => ZBX_STYLE_ACTION_ICON_CLOSE, 2015 'title' => _('Manually closed') 2016 ]); 2017 } 2018 2019 if (($action['action'] & ZBX_PROBLEM_UPDATE_ACKNOWLEDGE) == ZBX_PROBLEM_UPDATE_ACKNOWLEDGE) { 2020 $action_icons[] = makeActionIcon(['icon' => ZBX_STYLE_ACTION_ICON_ACK, 'title' => _('Acknowledged')]); 2021 } 2022 2023 if (($action['action'] & ZBX_PROBLEM_UPDATE_UNACKNOWLEDGE) == ZBX_PROBLEM_UPDATE_UNACKNOWLEDGE) { 2024 $action_icons[] = makeActionIcon(['icon' => ZBX_STYLE_ACTION_ICON_UNACK, 'title' => _('Unacknowledged')]); 2025 } 2026 2027 if (($action['action'] & ZBX_PROBLEM_UPDATE_MESSAGE) == ZBX_PROBLEM_UPDATE_MESSAGE) { 2028 $action_icons[] = makeActionIcon(['icon' => ZBX_STYLE_ACTION_ICON_MSG, 'title' => _('Message')]); 2029 } 2030 2031 if (($action['action'] & ZBX_PROBLEM_UPDATE_SEVERITY) == ZBX_PROBLEM_UPDATE_SEVERITY) { 2032 $action_type = ($action['new_severity'] > $action['old_severity']) 2033 ? ZBX_STYLE_ACTION_ICON_SEV_UP 2034 : ZBX_STYLE_ACTION_ICON_SEV_DOWN; 2035 2036 $old_severity_name = getSeverityName($action['old_severity']); 2037 $new_severity_name = getSeverityName($action['new_severity']); 2038 $hint = $old_severity_name.' ⇒ '.$new_severity_name; 2039 2040 $action_icons[] = makeActionIcon(['button' => true, 'icon' => $action_type, 'hint' => $hint]); 2041 } 2042 2043 return (new CCol($action_icons))->addClass(ZBX_STYLE_NOWRAP); 2044 2045 case ZBX_EVENT_HISTORY_ALERT: 2046 $action_icon = ($action['alerttype'] == ALERT_TYPE_COMMAND) 2047 ? ZBX_STYLE_ACTION_COMMAND 2048 : ZBX_STYLE_ACTION_MESSAGE; 2049 $title = ($action['alerttype'] == ALERT_TYPE_COMMAND) 2050 ? _('Remote command') 2051 : _('Alert message'); 2052 2053 return makeActionIcon(['icon' => $action_icon, 'title' => $title]); 2054 } 2055} 2056 2057/** 2058 * Creates span with alert status text. 2059 * 2060 * @param array $action 2061 * @param int $action['action_type'] Type of event table action (ZBX_EVENT_HISTORY_*). 2062 * @param string $action['status'] Alert status. 2063 * @param string $action['alerttype'] Type of alert. 2064 * 2065 * @return CSpan|string 2066 */ 2067function makeActionTableStatus(array $action) { 2068 if ($action['action_type'] == ZBX_EVENT_HISTORY_ALERT) { 2069 switch ($action['status']) { 2070 case ALERT_STATUS_SENT: 2071 $status_label = ($action['alerttype'] == ALERT_TYPE_COMMAND) 2072 ? _('Executed') 2073 : _('Sent'); 2074 $status_color = ZBX_STYLE_GREEN; 2075 break; 2076 2077 case ALERT_STATUS_NEW: 2078 case ALERT_STATUS_NOT_SENT: 2079 $status_label = _('In progress'); 2080 $status_color = ZBX_STYLE_YELLOW; 2081 break; 2082 2083 default: 2084 $status_label = _('Failed'); 2085 $status_color = ZBX_STYLE_RED; 2086 break; 2087 } 2088 2089 return (new CSpan($status_label))->addClass($status_color); 2090 } 2091 else { 2092 return ''; 2093 } 2094} 2095 2096/** 2097 * Creates div with alert info icons. 2098 * 2099 * @param array $action 2100 * @param int $action['action_type'] Type of event table action (ZBX_EVENT_HISTORY_*). 2101 * @param string $action['status'] Alert status. 2102 * @param string $action['alerttype'] Type of alert. 2103 * @param string $action['mediatypeid'] ID for mediatype, where alert message was sent. 2104 * @param string $action['retries'] How many retries was done for pending alert message. 2105 * @param array $mediatypes Array of media type data. 2106 * @param array $mediatypes[]['maxattempts'] Maximum attempts for this mediatype. 2107 * 2108 * @return CDiv|string 2109 */ 2110function makeActionTableInfo(array $action, array $mediatypes) { 2111 if ($action['action_type'] == ZBX_EVENT_HISTORY_ALERT) { 2112 $info_icons = []; 2113 2114 if ($action['alerttype'] == ALERT_TYPE_MESSAGE 2115 && ($action['status'] == ALERT_STATUS_NEW || $action['status'] == ALERT_STATUS_NOT_SENT)) { 2116 $info_icons[] = makeWarningIcon(array_key_exists($action['mediatypeid'], $mediatypes) 2117 ? _n('%1$s retry left', '%1$s retries left', 2118 $mediatypes[$action['mediatypeid']]['maxattempts'] - $action['retries'] 2119 ) 2120 : '' 2121 ); 2122 } 2123 elseif ($action['error'] !== '') { 2124 $info_icons[] = makeErrorIcon($action['error']); 2125 } 2126 2127 return makeInformationList($info_icons); 2128 } 2129 else { 2130 return ''; 2131 } 2132} 2133