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 sysmap_element_types($type = null) { 23 $types = [ 24 SYSMAP_ELEMENT_TYPE_HOST => _('Host'), 25 SYSMAP_ELEMENT_TYPE_HOST_GROUP => _('Host group'), 26 SYSMAP_ELEMENT_TYPE_TRIGGER => _('Trigger'), 27 SYSMAP_ELEMENT_TYPE_MAP => _('Map'), 28 SYSMAP_ELEMENT_TYPE_IMAGE => _('Image') 29 ]; 30 31 if (is_null($type)) { 32 natsort($types); 33 return $types; 34 } 35 elseif (isset($types[$type])) { 36 return $types[$type]; 37 } 38 else { 39 return _('Unknown'); 40 } 41} 42 43function sysmapElementLabel($label = null) { 44 $labels = [ 45 MAP_LABEL_TYPE_LABEL => _('Label'), 46 MAP_LABEL_TYPE_IP => _('IP address'), 47 MAP_LABEL_TYPE_NAME => _('Element name'), 48 MAP_LABEL_TYPE_STATUS => _('Status only'), 49 MAP_LABEL_TYPE_NOTHING => _('Nothing'), 50 MAP_LABEL_TYPE_CUSTOM => _('Custom label') 51 ]; 52 53 if (is_null($label)) { 54 return $labels; 55 } 56 elseif (isset($labels[$label])) { 57 return $labels[$label]; 58 } 59 else { 60 return false; 61 } 62} 63 64/** 65 * Get actions (data for popup menu) for map elements. 66 * 67 * @param array $sysmap 68 * @param array $sysmap['selements'] 69 * @param array $options Options used to retrieve actions. 70 * @param int $options['severity_min'] Minimal severity used. 71 * 72 * @return array 73 */ 74function getActionsBySysmap(array $sysmap, array $options = []) { 75 $actions = []; 76 $severity_min = array_key_exists('severity_min', $options) 77 ? $options['severity_min'] 78 : TRIGGER_SEVERITY_NOT_CLASSIFIED; 79 80 foreach ($sysmap['selements'] as $selementid => $elem) { 81 if ($elem['permission'] < PERM_READ) { 82 continue; 83 } 84 85 $hostid = ($elem['elementtype_orig'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 86 && $elem['elementsubtype_orig'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) 87 ? $elem['elements'][0]['hostid'] 88 : 0; 89 90 $map = CMenuPopupHelper::getMapElement($sysmap['sysmapid'], $elem, $severity_min, $hostid); 91 92 $actions[$selementid] = CJs::encodeJson($map); 93 } 94 95 return $actions; 96} 97 98function get_png_by_selement($info) { 99 $image = get_image_by_imageid($info['iconid']); 100 101 return $image['image'] ? imagecreatefromstring($image['image']) : get_default_image(); 102} 103 104function get_map_elements($db_element, &$elements) { 105 switch ($db_element['elementtype']) { 106 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 107 $elements['hosts_groups'][] = $db_element['elements'][0]['groupid']; 108 break; 109 case SYSMAP_ELEMENT_TYPE_HOST: 110 $elements['hosts'][] = $db_element['elements'][0]['hostid']; 111 break; 112 case SYSMAP_ELEMENT_TYPE_TRIGGER: 113 foreach ($db_element['elements'] as $db_element) { 114 $elements['triggers'][] = $db_element['triggerid']; 115 } 116 break; 117 case SYSMAP_ELEMENT_TYPE_MAP: 118 $map = API::Map()->get([ 119 'output' => [], 120 'selectSelements' => ['selementid', 'elements', 'elementtype'], 121 'sysmapids' => $db_element['elements'][0]['sysmapid'], 122 'nopermissions' => true 123 ]); 124 125 if ($map) { 126 $map = reset($map); 127 128 foreach ($map['selements'] as $db_mapelement) { 129 get_map_elements($db_mapelement, $elements); 130 } 131 } 132 break; 133 } 134} 135 136/** 137 * Adds names to elements. Adds expression for SYSMAP_ELEMENT_TYPE_TRIGGER elements. 138 * 139 * @param array $selements 140 * @param array $selements[]['elements'] 141 * @param int $selements[]['elementtype'] 142 * @param int $selements[]['iconid_off'] 143 * @param int $selements[]['permission'] 144 */ 145function addElementNames(array &$selements) { 146 $hostids = []; 147 $triggerids = []; 148 $sysmapids = []; 149 $groupids = []; 150 $imageids = []; 151 152 foreach ($selements as $selement) { 153 if ($selement['permission'] < PERM_READ) { 154 continue; 155 } 156 157 switch ($selement['elementtype']) { 158 case SYSMAP_ELEMENT_TYPE_HOST: 159 $hostids[$selement['elements'][0]['hostid']] = $selement['elements'][0]['hostid']; 160 break; 161 162 case SYSMAP_ELEMENT_TYPE_MAP: 163 $sysmapids[$selement['elements'][0]['sysmapid']] = $selement['elements'][0]['sysmapid']; 164 break; 165 166 case SYSMAP_ELEMENT_TYPE_TRIGGER: 167 foreach ($selement['elements'] as $element) { 168 $triggerids[$element['triggerid']] = $element['triggerid']; 169 } 170 break; 171 172 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 173 $groupids[$selement['elements'][0]['groupid']] = $selement['elements'][0]['groupid']; 174 break; 175 176 case SYSMAP_ELEMENT_TYPE_IMAGE: 177 $imageids[$selement['iconid_off']] = $selement['iconid_off']; 178 break; 179 } 180 } 181 182 $hosts = $hostids 183 ? API::Host()->get([ 184 'output' => ['name'], 185 'hostids' => $hostids, 186 'preservekeys' => true 187 ]) 188 : []; 189 190 $maps = $sysmapids 191 ? API::Map()->get([ 192 'output' => ['name'], 193 'sysmapids' => $sysmapids, 194 'preservekeys' => true 195 ]) 196 : []; 197 198 $triggers = $triggerids 199 ? API::Trigger()->get([ 200 'output' => ['description', 'expression', 'priority'], 201 'selectHosts' => ['name'], 202 'triggerids' => $triggerids, 203 'preservekeys' => true 204 ]) 205 : []; 206 $triggers = CMacrosResolverHelper::resolveTriggerNames($triggers); 207 208 $groups = $groupids 209 ? API::HostGroup()->get([ 210 'output' => ['name'], 211 'hostgroupids' => $groupids, 212 'preservekeys' => true 213 ]) 214 : []; 215 216 $images = $imageids 217 ? API::Image()->get([ 218 'output' => ['name'], 219 'imageids' => $imageids, 220 'preservekeys' => true 221 ]) 222 : []; 223 224 foreach ($selements as $snum => &$selement) { 225 if ($selement['permission'] < PERM_READ) { 226 continue; 227 } 228 229 switch ($selement['elementtype']) { 230 case SYSMAP_ELEMENT_TYPE_HOST: 231 $selements[$snum]['elements'][0]['elementName'] = $hosts[$selement['elements'][0]['hostid']]['name']; 232 break; 233 234 case SYSMAP_ELEMENT_TYPE_MAP: 235 $selements[$snum]['elements'][0]['elementName'] = $maps[$selement['elements'][0]['sysmapid']]['name']; 236 break; 237 238 case SYSMAP_ELEMENT_TYPE_TRIGGER: 239 foreach ($selement['elements'] as $enum => &$element) { 240 if (array_key_exists($element['triggerid'], $triggers)) { 241 $trigger = $triggers[$element['triggerid']]; 242 $element['elementName'] = $trigger['hosts'][0]['name'].NAME_DELIMITER.$trigger['description']; 243 $element['elementExpressionTrigger'] = $trigger['expression']; 244 $element['priority'] = $trigger['priority']; 245 } 246 else { 247 unset($selement['elements'][$enum]); 248 } 249 } 250 unset($element); 251 $selement['elements'] = array_values($selement['elements']); 252 break; 253 254 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 255 $selements[$snum]['elements'][0]['elementName'] = $groups[$selement['elements'][0]['groupid']]['name']; 256 break; 257 258 case SYSMAP_ELEMENT_TYPE_IMAGE: 259 if (array_key_exists($selement['iconid_off'], $images)) { 260 $selements[$snum]['elements'][0]['elementName'] = $images[$selement['iconid_off']]['name']; 261 } 262 break; 263 } 264 } 265 unset($selement); 266} 267 268/** 269 * Returns trigger element icon rendering parameters. 270 * 271 * @param $selement 272 * @param $i 273 * @param $showUnack map "problem display" parameter 274 * 275 * @return array 276 */ 277function getTriggersInfo($selement, $i, $showUnack) { 278 $info = [ 279 'latelyChanged' => $i['latelyChanged'], 280 'ack' => $i['ack'], 281 'priority' => $i['priority'], 282 'info' => [], 283 'iconid' => $selement['iconid_off'] 284 ]; 285 286 if ($i['problem'] && ($i['problem_unack'] && $showUnack == EXTACK_OPTION_UNACK 287 || in_array($showUnack, [EXTACK_OPTION_ALL, EXTACK_OPTION_BOTH]))) { 288 // Number of problems. 289 if ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER) { 290 if ($i['problem'] == 1) { 291 $msg = _('PROBLEM'); 292 } 293 else { 294 $msg = $i['problem'].' '._('Problems'); 295 } 296 } 297 // Expand single problem. 298 elseif ($i['expandproblem'] == SYSMAP_SINGLE_PROBLEM) { 299 $msg = $i['problem_title']; 300 } 301 // Number of problems and expand most critical one. 302 elseif ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER_CRITICAL) { 303 $msg = $i['problem_title']; 304 305 if ($i['problem'] > 1) { 306 $msg .= "\n".$i['problem'].' '._('Problems'); 307 } 308 } 309 310 $info['info']['unack'] = [ 311 'msg' => $msg, 312 'color' => getSelementLabelColor(true, !$i['problem_unack']) 313 ]; 314 315 if (!array_key_exists('maintenance_title', $i)) { 316 $info['iconid'] = $selement['iconid_on']; 317 $info['icon_type'] = SYSMAP_ELEMENT_ICON_ON; 318 319 return $info; 320 } 321 } 322 323 if (array_key_exists('maintenance_title', $i)) { 324 $info['iconid'] = $selement['iconid_maintenance']; 325 $info['icon_type'] = SYSMAP_ELEMENT_ICON_MAINTENANCE; 326 $info['info']['maintenance'] = [ 327 'msg' => _('MAINTENANCE').' ('.$i['maintenance_title'].')', 328 'color' => 'EE9600' 329 ]; 330 } 331 elseif ($i['trigger_disabled']) { 332 $info['iconid'] = $selement['iconid_disabled']; 333 $info['icon_type'] = SYSMAP_ELEMENT_ICON_DISABLED; 334 $info['info']['status'] = [ 335 'msg' => _('DISABLED'), 336 'color' => '960000' 337 ]; 338 } 339 else { 340 $info['iconid'] = $selement['iconid_off']; 341 $info['icon_type'] = SYSMAP_ELEMENT_ICON_OFF; 342 $info['info']['ok'] = [ 343 'msg' => _('OK'), 344 'color' => getSelementLabelColor(false, $i['ack']) 345 ]; 346 } 347 348 return $info; 349} 350 351/** 352 * Returns host element icon rendering parameters. 353 * 354 * @param $selement 355 * @param $i 356 * @param $show_unack map "problem display" parameter 357 * 358 * @return array 359 */ 360function getHostsInfo($selement, $i, $show_unack) { 361 $info = [ 362 'latelyChanged' => $i['latelyChanged'], 363 'ack' => $i['ack'], 364 'priority' => $i['priority'], 365 'info' => [], 366 'iconid' => $selement['iconid_off'] 367 ]; 368 $hasProblem = false; 369 370 if ($i['problem']) { 371 if (in_array($show_unack, [EXTACK_OPTION_ALL, EXTACK_OPTION_BOTH])) { 372 // Number of problems. 373 if ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER) { 374 if ($i['problem'] == 1) { 375 $msg = _('PROBLEM'); 376 } 377 else { 378 $msg = $i['problem'].' '._('Problems'); 379 } 380 } 381 // Expand single problem. 382 elseif ($i['expandproblem'] == SYSMAP_SINGLE_PROBLEM) { 383 $msg = $i['problem_title']; 384 } 385 // Number of problems and expand most critical one. 386 elseif ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER_CRITICAL) { 387 $msg = $i['problem_title']; 388 389 if ($i['problem'] > 1) { 390 $msg .= "\n".$i['problem'].' '._('Problems'); 391 } 392 } 393 394 $info['info']['problem'] = [ 395 'msg' => $msg, 396 'color' => getSelementLabelColor(true, !$i['problem_unack']) 397 ]; 398 } 399 400 if (in_array($show_unack, [EXTACK_OPTION_UNACK, EXTACK_OPTION_BOTH]) && $i['problem_unack']) { 401 $info['info']['unack'] = [ 402 'msg' => $i['problem_unack'].' '._('Unacknowledged'), 403 'color' => getSelementLabelColor(true, false) 404 ]; 405 } 406 407 // set element to problem state if it has problem events 408 if ($info['info']) { 409 $info['iconid'] = $selement['iconid_on']; 410 $info['icon_type'] = SYSMAP_ELEMENT_ICON_ON; 411 $hasProblem = true; 412 } 413 } 414 415 if (array_key_exists('maintenance_title', $i)) { 416 $info['iconid'] = $selement['iconid_maintenance']; 417 $info['icon_type'] = SYSMAP_ELEMENT_ICON_MAINTENANCE; 418 $info['info']['maintenance'] = [ 419 'msg' => _('MAINTENANCE').' ('.$i['maintenance_title'].')', 420 'color' => 'EE9600' 421 ]; 422 } 423 elseif ($i['disabled']) { 424 $info['iconid'] = $selement['iconid_disabled']; 425 $info['icon_type'] = SYSMAP_ELEMENT_ICON_DISABLED; 426 $info['info']['status'] = [ 427 'msg' => _('DISABLED'), 428 'color' => '960000' 429 ]; 430 } 431 elseif (!$hasProblem) { 432 $info['iconid'] = $selement['iconid_off']; 433 $info['icon_type'] = SYSMAP_ELEMENT_ICON_OFF; 434 $info['info']['ok'] = [ 435 'msg' => _('OK'), 436 'color' => getSelementLabelColor(false, $i['ack']) 437 ]; 438 } 439 440 return $info; 441} 442 443/** 444 * Returns host groups element icon rendering parameters. 445 * 446 * @param $selement 447 * @param $i 448 * @param $show_unack map "problem display" parameter 449 * 450 * @return array 451 */ 452function getHostGroupsInfo($selement, $i, $show_unack) { 453 $info = [ 454 'latelyChanged' => $i['latelyChanged'], 455 'ack' => $i['ack'], 456 'priority' => $i['priority'], 457 'info' => [], 458 'iconid' => $selement['iconid_off'] 459 ]; 460 $hasProblem = false; 461 $hasStatus = false; 462 463 if ($i['problem']) { 464 if (in_array($show_unack, [EXTACK_OPTION_ALL, EXTACK_OPTION_BOTH])) { 465 // Number of problems. 466 if ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER) { 467 if ($i['problem'] == 1) { 468 $msg = _('PROBLEM'); 469 } 470 else { 471 $msg = $i['problem'].' '._('Problems'); 472 } 473 } 474 // Expand single problem. 475 elseif ($i['expandproblem'] == SYSMAP_SINGLE_PROBLEM) { 476 $msg = $i['problem_title']; 477 } 478 // Number of problems and expand most critical one. 479 elseif ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER_CRITICAL) { 480 $msg = $i['problem_title']; 481 482 if ($i['problem'] > 1) { 483 $msg .= "\n".$i['problem'].' '._('Problems'); 484 } 485 } 486 487 $info['info']['problem'] = [ 488 'msg' => $msg, 489 'color' => getSelementLabelColor(true, !$i['problem_unack']) 490 ]; 491 } 492 493 if (in_array($show_unack, [EXTACK_OPTION_UNACK, EXTACK_OPTION_BOTH]) && $i['problem_unack']) { 494 $info['info']['unack'] = [ 495 'msg' => $i['problem_unack'].' '._('Unacknowledged'), 496 'color' => getSelementLabelColor(true, false) 497 ]; 498 } 499 500 // set element to problem state if it has problem events 501 if ($info['info']) { 502 $info['iconid'] = $selement['iconid_on']; 503 $info['icon_type'] = SYSMAP_ELEMENT_ICON_ON; 504 $hasProblem = true; 505 } 506 } 507 508 if ($i['maintenance']) { 509 $info['iconid'] = $selement['iconid_maintenance']; 510 $info['icon_type'] = SYSMAP_ELEMENT_ICON_MAINTENANCE; 511 $info['info']['maintenance'] = [ 512 'msg' => $i['maintenance'].' '._('Maintenance'), 513 'color' => 'EE9600' 514 ]; 515 $hasStatus = true; 516 } 517 518 if (!$hasStatus && !$hasProblem) { 519 $info['icon_type'] = SYSMAP_ELEMENT_ICON_OFF; 520 $info['iconid'] = $selement['iconid_off']; 521 $info['info']['ok'] = [ 522 'msg' => _('OK'), 523 'color' => getSelementLabelColor(false, $i['ack']) 524 ]; 525 } 526 527 return $info; 528} 529 530/** 531 * Returns maps groups element icon rendering parameters. 532 * 533 * @param $selement 534 * @param $i 535 * @param $show_unack map "problem display" parameter 536 * 537 * @return array 538 */ 539function getMapsInfo($selement, $i, $show_unack) { 540 $info = [ 541 'latelyChanged' => $i['latelyChanged'], 542 'ack' => $i['ack'], 543 'priority' => $i['priority'], 544 'info' => [], 545 'iconid' => $selement['iconid_off'] 546 ]; 547 548 $hasProblem = false; 549 $hasStatus = false; 550 551 if ($i['problem']) { 552 if (in_array($show_unack, [EXTACK_OPTION_ALL, EXTACK_OPTION_BOTH])) { 553 // Number of problems. 554 if ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER) { 555 if ($i['problem'] == 1) { 556 $msg = _('PROBLEM'); 557 } 558 else { 559 $msg = $i['problem'].' '._('Problems'); 560 } 561 } 562 // Expand single problem. 563 elseif ($i['expandproblem'] == SYSMAP_SINGLE_PROBLEM) { 564 $msg = $i['problem_title']; 565 } 566 // Number of problems and expand most critical one. 567 elseif ($i['expandproblem'] == SYSMAP_PROBLEMS_NUMBER_CRITICAL) { 568 $msg = $i['problem_title']; 569 570 if ($i['problem'] > 1) { 571 $msg .= "\n".$i['problem'].' '._('Problems'); 572 } 573 } 574 575 $info['info']['problem'] = [ 576 'msg' => $msg, 577 'color' => getSelementLabelColor(true, !$i['problem_unack']) 578 ]; 579 } 580 581 if (in_array($show_unack, [EXTACK_OPTION_UNACK, EXTACK_OPTION_BOTH]) && $i['problem_unack']) { 582 $info['info']['unack'] = [ 583 'msg' => $i['problem_unack'].' '._('Unacknowledged'), 584 'color' => getSelementLabelColor(true, false) 585 ]; 586 } 587 588 if ($info['info']) { 589 $info['iconid'] = $selement['iconid_on']; 590 $info['icon_type'] = SYSMAP_ELEMENT_ICON_ON; 591 $hasProblem = true; 592 } 593 } 594 595 if ($i['maintenance']) { 596 if (!$hasProblem) { 597 $info['iconid'] = $selement['iconid_maintenance']; 598 $info['icon_type'] = SYSMAP_ELEMENT_ICON_MAINTENANCE; 599 } 600 $info['info']['maintenance'] = [ 601 'msg' => $i['maintenance'].' '._('Maintenance'), 602 'color' => 'EE9600' 603 ]; 604 $hasStatus = true; 605 } 606 607 if (!$hasStatus && !$hasProblem) { 608 $info['icon_type'] = SYSMAP_ELEMENT_ICON_OFF; 609 $info['iconid'] = $selement['iconid_off']; 610 $info['info']['ok'] = [ 611 'msg' => _('OK'), 612 'color' => getSelementLabelColor(false, $i['ack']) 613 ]; 614 } 615 616 return $info; 617} 618 619function getImagesInfo($selement) { 620 return [ 621 'iconid' => $selement['iconid_off'], 622 'icon_type' => SYSMAP_ELEMENT_ICON_OFF, 623 'name' => _('Image'), 624 'latelyChanged' => false 625 ]; 626} 627 628/** 629 * Prepare map elements data. 630 * Calculate problem triggers and priorities. Populate map elements with automatic icon mapping, acknowledging and 631 * recent change markers. 632 * 633 * @param array $sysmap 634 * @param array $options 635 * @param int $options['severity_min'] Minimum severity, default value is maximal (Disaster) 636 * 637 * @return array 638 */ 639function getSelementsInfo(array $sysmap, array $options = []) { 640 if (!isset($options['severity_min'])) { 641 $options['severity_min'] = TRIGGER_SEVERITY_NOT_CLASSIFIED; 642 } 643 644 $triggerIdToSelementIds = []; 645 $subSysmapTriggerIdToSelementIds = []; 646 $hostGroupIdToSelementIds = []; 647 $hostIdToSelementIds = []; 648 649 if ($sysmap['sysmapid']) { 650 $iconMap = API::IconMap()->get([ 651 'output' => API_OUTPUT_EXTEND, 652 'selectMappings' => API_OUTPUT_EXTEND, 653 'sysmapids' => $sysmap['sysmapid'] 654 ]); 655 $iconMap = reset($iconMap); 656 } 657 $hostsToGetInventories = []; 658 659 $selements = $sysmap['selements']; 660 $selementIdToSubSysmaps = []; 661 foreach ($selements as $selementId => &$selement) { 662 $selement['hosts'] = []; 663 $selement['triggers'] = []; 664 665 if ($selement['permission'] < PERM_READ) { 666 continue; 667 } 668 669 switch ($selement['elementtype']) { 670 case SYSMAP_ELEMENT_TYPE_MAP: 671 $sysmapIds = [$selement['elements'][0]['sysmapid']]; 672 673 while (!empty($sysmapIds)) { 674 $subSysmaps = API::Map()->get([ 675 'output' => ['sysmapid'], 676 'selectSelements' => ['elementtype', 'elements', 'application'], 677 'sysmapids' => $sysmapIds, 678 'preservekeys' => true 679 ]); 680 681 if(!isset($selementIdToSubSysmaps[$selementId])) { 682 $selementIdToSubSysmaps[$selementId] = []; 683 } 684 $selementIdToSubSysmaps[$selementId] += $subSysmaps; 685 686 $sysmapIds = []; 687 foreach ($subSysmaps as $subSysmap) { 688 foreach ($subSysmap['selements'] as $subSysmapSelement) { 689 switch ($subSysmapSelement['elementtype']) { 690 case SYSMAP_ELEMENT_TYPE_MAP: 691 $sysmapIds[] = $subSysmapSelement['elements'][0]['sysmapid']; 692 break; 693 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 694 $hostGroupIdToSelementIds[$subSysmapSelement['elements'][0]['groupid']][$selementId] 695 = $selementId; 696 break; 697 case SYSMAP_ELEMENT_TYPE_HOST: 698 $hostIdToSelementIds[$subSysmapSelement['elements'][0]['hostid']][$selementId] 699 = $selementId; 700 break; 701 case SYSMAP_ELEMENT_TYPE_TRIGGER: 702 foreach ($subSysmapSelement['elements'] as $element) { 703 $subSysmapTriggerIdToSelementIds[$element['triggerid']][$selementId] 704 = $selementId; 705 } 706 break; 707 } 708 } 709 } 710 } 711 break; 712 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 713 $hostGroupId = $selement['elements'][0]['groupid']; 714 $hostGroupIdToSelementIds[$hostGroupId][$selementId] = $selementId; 715 break; 716 case SYSMAP_ELEMENT_TYPE_HOST: 717 $hostId = $selement['elements'][0]['hostid']; 718 $hostIdToSelementIds[$hostId][$selementId] = $selementId; 719 720 /** 721 * If we have icon map applied, we need to get inventories for all hosts, where automatic icon 722 * selection is enabled. 723 */ 724 if ($sysmap['iconmapid'] && $selement['use_iconmap']) { 725 $hostsToGetInventories[] = $hostId; 726 } 727 break; 728 case SYSMAP_ELEMENT_TYPE_TRIGGER: 729 foreach ($selement['elements'] as $element) { 730 $triggerIdToSelementIds[$element['triggerid']][$selementId] = $selementId; 731 } 732 break; 733 } 734 } 735 unset($selement); 736 737 // get host inventories 738 if ($sysmap['iconmapid']) { 739 $hostInventories = API::Host()->get([ 740 'output' => ['hostid'], 741 'selectInventory' => API_OUTPUT_EXTEND, 742 'hostids' => $hostsToGetInventories, 743 'preservekeys' => true 744 ]); 745 } 746 747 $allHosts = []; 748 if ($hostIdToSelementIds) { 749 $hosts = API::Host()->get([ 750 'output' => ['name', 'status', 'maintenance_status', 'maintenanceid'], 751 'hostids' => array_keys($hostIdToSelementIds), 752 'preservekeys' => true 753 ]); 754 $allHosts = array_merge($allHosts, $hosts); 755 foreach ($hosts as $hostId => $host) { 756 foreach ($hostIdToSelementIds[$hostId] as $selementId) { 757 $selements[$selementId]['hosts'][$hostId] = $hostId; 758 } 759 } 760 } 761 762 $hostsFromHostGroups = []; 763 if ($hostGroupIdToSelementIds) { 764 $hostsFromHostGroups = API::Host()->get([ 765 'output' => ['name', 'status', 'maintenance_status', 'maintenanceid'], 766 'selectGroups' => ['groupid'], 767 'groupids' => array_keys($hostGroupIdToSelementIds), 768 'preservekeys' => true 769 ]); 770 771 foreach ($hostsFromHostGroups as $hostId => $host) { 772 foreach ($host['groups'] as $group) { 773 $groupId = $group['groupid']; 774 775 if (isset($hostGroupIdToSelementIds[$groupId])) { 776 foreach ($hostGroupIdToSelementIds[$groupId] as $selementId) { 777 $selement =& $selements[$selementId]; 778 779 $selement['hosts'][$hostId] = $hostId; 780 781 // Add hosts to hosts_map for trigger selection. 782 if (!isset($hostIdToSelementIds[$hostId])) { 783 $hostIdToSelementIds[$hostId] = []; 784 } 785 $hostIdToSelementIds[$hostId][$selementId] = $selementId; 786 787 unset($selement); 788 } 789 } 790 } 791 } 792 793 $allHosts = array_merge($allHosts, $hostsFromHostGroups); 794 } 795 796 $allHosts = zbx_toHash($allHosts, 'hostid'); 797 798 // Get triggers data, triggers from current map and from submaps, select all. 799 if ($triggerIdToSelementIds || $subSysmapTriggerIdToSelementIds) { 800 $all_triggerid_to_selementids = []; 801 802 foreach ([$triggerIdToSelementIds, $subSysmapTriggerIdToSelementIds] as $triggerid_to_selementids) { 803 foreach ($triggerid_to_selementids as $triggerid => $selementids) { 804 if (!array_key_exists($triggerid, $all_triggerid_to_selementids)) { 805 $all_triggerid_to_selementids[$triggerid] = $selementids; 806 } 807 else { 808 $all_triggerid_to_selementids[$triggerid] += $selementids; 809 } 810 } 811 } 812 813 $triggers = API::Trigger()->get([ 814 'output' => ['triggerid', 'status', 'value', 'priority', 'description', 'expression'], 815 'selectHosts' => ['maintenance_status', 'maintenanceid'], 816 'triggerids' => array_keys($all_triggerid_to_selementids), 817 'filter' => ['state' => null], 818 'preservekeys' => true 819 ]); 820 821 $monitored_triggers = API::Trigger()->get([ 822 'output' => [], 823 'triggerids' => array_keys($triggers), 824 'monitored' => true, 825 'skipDependent' => true, 826 'preservekeys' => true 827 ]); 828 829 foreach ($triggers as $trigger) { 830 if (!array_key_exists($trigger['triggerid'], $monitored_triggers)) { 831 $trigger['status'] = TRIGGER_STATUS_DISABLED; 832 } 833 834 foreach ($all_triggerid_to_selementids[$trigger['triggerid']] as $belongs_to_sel) { 835 $selements[$belongs_to_sel]['triggers'][$trigger['triggerid']] = $trigger; 836 } 837 } 838 unset($triggers, $monitored_triggers); 839 } 840 841 $monitored_hostids = []; 842 foreach ($allHosts as $hostid => $host) { 843 if ($host['status'] == HOST_STATUS_MONITORED) { 844 $monitored_hostids[$hostid] = true; 845 } 846 } 847 848 // triggers from all hosts/hostgroups, skip dependent 849 if ($monitored_hostids) { 850 $triggers = API::Trigger()->get([ 851 'output' => ['triggerid', 'status', 'value', 'priority', 'description', 'expression'], 852 'selectHosts' => ['hostid'], 853 'selectItems' => ['itemid'], 854 'hostids' => array_keys($monitored_hostids), 855 'filter' => ['state' => null], 856 'monitored' => true, 857 'skipDependent' => true, 858 'only_true' => true, 859 'preservekeys' => true 860 ]); 861 862 foreach ($triggers as $trigger) { 863 foreach ($trigger['hosts'] as $host) { 864 if (array_key_exists($host['hostid'], $hostIdToSelementIds)) { 865 foreach ($hostIdToSelementIds[$host['hostid']] as $belongs_to_sel) { 866 $selements[$belongs_to_sel]['triggers'][$trigger['triggerid']] = $trigger; 867 } 868 } 869 } 870 } 871 872 $subSysmapHostApplicationFilters = getSelementHostApplicationFilters($selements, $selementIdToSubSysmaps, 873 $hostsFromHostGroups 874 ); 875 $selements = filterSysmapTriggers($selements, $subSysmapHostApplicationFilters, $triggers, 876 $subSysmapTriggerIdToSelementIds 877 ); 878 } 879 880 // Get problems by triggerids. 881 $triggerids = []; 882 foreach ($selements as $selement) { 883 foreach ($selement['triggers'] as $trigger) { 884 if ($trigger['status'] == TRIGGER_STATUS_ENABLED) { 885 $triggerids[$trigger['triggerid']] = true; 886 } 887 } 888 } 889 890 $problems = API::Problem()->get([ 891 'output' => ['eventid', 'objectid', 'name', 'acknowledged', 'clock', 'r_clock', 'severity'], 892 'objectids' => array_keys($triggerids), 893 'recent' => true, 894 'suppressed' => ($sysmap['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_FALSE) ? false : null 895 ]); 896 897 foreach ($selements as $snum => $selement) { 898 foreach ($problems as $problem) { 899 if (array_key_exists($problem['objectid'], $selement['triggers']) 900 && $options['severity_min'] <= $problem['severity']) { 901 $selements[$snum]['triggers'][$problem['objectid']]['problems'][] = $problem; 902 } 903 } 904 } 905 906 $config = select_config(); 907 908 $info = []; 909 foreach ($selements as $selementId => $selement) { 910 $i = [ 911 'disabled' => 0, 912 'maintenance' => 0, 913 'problem' => 0, 914 'problem_unack' => 0, 915 'priority' => 0, 916 'trigger_disabled' => 0, 917 'latelyChanged' => false, 918 'ack' => true 919 ]; 920 $info[$selementId]['aria_label'] = ''; 921 922 /* 923 * If user has no rights to see the details of particular selement, add only info that is needed to render map 924 * icons. 925 */ 926 if (PERM_READ > $selement['permission']) { 927 switch ($selement['elementtype']) { 928 case SYSMAP_ELEMENT_TYPE_MAP: 929 $info[$selementId] = getMapsInfo(['iconid_off' => $selement['iconid_off']], $i, null); 930 break; 931 932 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 933 $info[$selementId] = getHostGroupsInfo(['iconid_off' => $selement['iconid_off']], $i, null); 934 break; 935 936 case SYSMAP_ELEMENT_TYPE_HOST: 937 $info[$selementId] = getHostsInfo(['iconid_off' => $selement['iconid_off']], $i, null); 938 break; 939 940 case SYSMAP_ELEMENT_TYPE_TRIGGER: 941 $info[$selementId] = getTriggersInfo(['iconid_off' => $selement['iconid_off']], $i, null); 942 break; 943 944 case SYSMAP_ELEMENT_TYPE_IMAGE: 945 $info[$selementId] = getImagesInfo(['iconid_off' => $selement['iconid_off']]); 946 break; 947 } 948 949 continue; 950 } 951 952 foreach ($selement['hosts'] as $hostId) { 953 $host = $allHosts[$hostId]; 954 $last_hostid = $hostId; 955 956 if ($host['status'] == HOST_STATUS_NOT_MONITORED) { 957 $i['disabled']++; 958 } 959 elseif ($host['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) { 960 $i['maintenance']++; 961 } 962 } 963 964 $critical_problem = []; 965 $trigger_order = ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_TRIGGER) 966 ? zbx_objectValues($selement['elements'], 'triggerid') 967 : []; 968 $lately_changed = 0; 969 970 foreach ($selement['triggers'] as $trigger) { 971 if ($trigger['status'] == TRIGGER_STATUS_DISABLED && $options['severity_min'] <= $trigger['priority']) { 972 $i['trigger_disabled']++; 973 continue; 974 } 975 976 if (array_key_exists('problems', $trigger)) { 977 foreach ($trigger['problems'] as $problem) { 978 if ($problem['r_clock'] == 0) { 979 $i['problem']++; 980 981 if ($problem['acknowledged'] == EVENT_NOT_ACKNOWLEDGED) { 982 $i['problem_unack']++; 983 } 984 985 if (!$critical_problem || $critical_problem['severity'] < $problem['severity']) { 986 $critical_problem = $problem; 987 } 988 elseif ($critical_problem['severity'] === $problem['severity']) { 989 if ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_TRIGGER) { 990 if ($problem['objectid'] === $critical_problem['objectid'] 991 && $critical_problem['eventid'] < $problem['eventid']) { 992 $critical_problem = $problem; 993 } 994 elseif (array_search($critical_problem['objectid'], $trigger_order) 995 > array_search($problem['objectid'], $trigger_order)) { 996 $critical_problem = $problem; 997 } 998 } 999 elseif ($critical_problem['eventid'] < $problem['eventid']) { 1000 $critical_problem = $problem; 1001 } 1002 } 1003 } 1004 1005 if ($problem['r_clock'] > $lately_changed) { 1006 $lately_changed = $problem['r_clock']; 1007 } 1008 elseif ($problem['clock'] > $lately_changed) { 1009 $lately_changed = $problem['clock']; 1010 } 1011 } 1012 } 1013 1014 $i['latelyChanged'] |= ((time() - $lately_changed) < timeUnitToSeconds($config['blink_period'])); 1015 } 1016 1017 if ($critical_problem) { 1018 $i['priority'] = $critical_problem['severity']; 1019 } 1020 1021 $i['ack'] = !$i['problem_unack']; 1022 1023 // Number of problems. 1024 if ($sysmap['expandproblem'] == SYSMAP_PROBLEMS_NUMBER) { 1025 $i['expandproblem'] = SYSMAP_PROBLEMS_NUMBER; 1026 } 1027 // Expand single problem. 1028 elseif ($sysmap['expandproblem'] == SYSMAP_SINGLE_PROBLEM && $i['problem']) { 1029 $i['problem_title'] = $critical_problem['name']; 1030 $i['expandproblem'] = SYSMAP_SINGLE_PROBLEM; 1031 } 1032 // Number of problems and expand most critical one. 1033 elseif ($sysmap['expandproblem'] == SYSMAP_PROBLEMS_NUMBER_CRITICAL && $i['problem']) { 1034 $i['problem_title'] = $critical_problem['name']; 1035 $i['expandproblem'] = SYSMAP_PROBLEMS_NUMBER_CRITICAL; 1036 } 1037 1038 // replace default icons 1039 if (!$selement['iconid_on']) { 1040 $selement['iconid_on'] = $selement['iconid_off']; 1041 } 1042 if (!$selement['iconid_maintenance']) { 1043 $selement['iconid_maintenance'] = $selement['iconid_off']; 1044 } 1045 if (!$selement['iconid_disabled']) { 1046 $selement['iconid_disabled'] = $selement['iconid_off']; 1047 } 1048 1049 switch ($selement['elementtype']) { 1050 case SYSMAP_ELEMENT_TYPE_MAP: 1051 $info[$selementId] = getMapsInfo($selement, $i, $sysmap['show_unack']); 1052 break; 1053 1054 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 1055 $info[$selementId] = getHostGroupsInfo($selement, $i, $sysmap['show_unack']); 1056 break; 1057 1058 case SYSMAP_ELEMENT_TYPE_HOST: 1059 if ($i['maintenance'] == 1) { 1060 $mnt = get_maintenance_by_maintenanceid($allHosts[$last_hostid]['maintenanceid']); 1061 $i['maintenance_title'] = $mnt['name']; 1062 } 1063 1064 $info[$selementId] = getHostsInfo($selement, $i, $sysmap['show_unack']); 1065 if ($sysmap['iconmapid'] && $selement['use_iconmap']) { 1066 $info[$selementId]['iconid'] = getIconByMapping($iconMap, 1067 $hostInventories[$selement['elements'][0]['hostid']] 1068 ); 1069 } 1070 break; 1071 1072 case SYSMAP_ELEMENT_TYPE_TRIGGER: 1073 foreach ($selement['triggers'] as $trigger) { 1074 foreach ($trigger['hosts'] as $host) { 1075 if (array_key_exists('maintenance_status', $host) 1076 && $host['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) { 1077 $maintenance = get_maintenance_by_maintenanceid($host['maintenanceid']); 1078 $i['maintenance_title'] = $maintenance['name']; 1079 1080 break; 1081 } 1082 } 1083 } 1084 1085 $info[$selementId] = getTriggersInfo($selement, $i, $sysmap['show_unack']); 1086 break; 1087 1088 case SYSMAP_ELEMENT_TYPE_IMAGE: 1089 $info[$selementId] = getImagesInfo($selement); 1090 break; 1091 } 1092 1093 if ($i['problem'] > 0) { 1094 $info[$selementId]['aria_label'] = ($i['problem'] > 1) 1095 ? _n('%1$s problem', '%1$s problems', $i['problem']) 1096 : $critical_problem['name']; 1097 } 1098 1099 $info[$selementId]['problems_total'] = $i['problem']; 1100 } 1101 1102 if ($sysmap['label_format'] == SYSMAP_LABEL_ADVANCED_OFF) { 1103 $hlabel = $hglabel = $tlabel = $mlabel = ($sysmap['label_type'] == MAP_LABEL_TYPE_NAME); 1104 } 1105 else { 1106 $hlabel = ($sysmap['label_type_host'] == MAP_LABEL_TYPE_NAME); 1107 $hglabel = ($sysmap['label_type_hostgroup'] == MAP_LABEL_TYPE_NAME); 1108 $tlabel = ($sysmap['label_type_trigger'] == MAP_LABEL_TYPE_NAME); 1109 $mlabel = ($sysmap['label_type_map'] == MAP_LABEL_TYPE_NAME); 1110 } 1111 1112 // get names if needed 1113 $elems = separateMapElements($sysmap); 1114 1115 if ($elems['sysmaps'] && $mlabel) { 1116 $sysmapids = []; 1117 1118 foreach ($elems['sysmaps'] as $selement) { 1119 if ($selement['permission'] >= PERM_READ) { 1120 $sysmapids[$selement['elements'][0]['sysmapid']] = true; 1121 } 1122 } 1123 1124 $db_sysmaps = API::Map()->get([ 1125 'output' => ['name'], 1126 'sysmapids' => array_keys($sysmapids), 1127 'preservekeys' => true 1128 ]); 1129 1130 foreach ($elems['sysmaps'] as $selement) { 1131 if ($selement['permission'] >= PERM_READ) { 1132 $info[$selement['selementid']]['name'] = 1133 array_key_exists($selement['elements'][0]['sysmapid'], $db_sysmaps) 1134 ? $db_sysmaps[$selement['elements'][0]['sysmapid']]['name'] 1135 : ''; 1136 } 1137 } 1138 } 1139 1140 if ($elems['hostgroups'] && $hglabel) { 1141 $groupids = []; 1142 1143 foreach ($elems['hostgroups'] as $selement) { 1144 if ($selement['permission'] >= PERM_READ) { 1145 $groupids[$selement['elements'][0]['groupid']] = true; 1146 } 1147 } 1148 1149 $db_groups = $groupids 1150 ? API::HostGroup()->get([ 1151 'output' => ['name'], 1152 'groupids' => array_keys($groupids), 1153 'preservekeys' => true 1154 ]) 1155 : []; 1156 1157 foreach ($elems['hostgroups'] as $selement) { 1158 if ($selement['permission'] >= PERM_READ) { 1159 $info[$selement['selementid']]['name'] = 1160 array_key_exists($selement['elements'][0]['groupid'], $db_groups) 1161 ? $db_groups[$selement['elements'][0]['groupid']]['name'] 1162 : ''; 1163 } 1164 } 1165 } 1166 1167 if ($elems['triggers'] && $tlabel) { 1168 $selements = zbx_toHash($selements, 'selementid'); 1169 foreach ($elems['triggers'] as $selementid => $selement) { 1170 foreach ($selement['elements'] as $element) { 1171 if ($selement['permission'] >= PERM_READ) { 1172 $trigger = array_key_exists($element['triggerid'], $selements[$selementid]['triggers']) 1173 ? $selements[$selementid]['triggers'][$element['triggerid']] 1174 : null; 1175 $info[$selement['selementid']]['name'] = ($trigger != null) 1176 ? CMacrosResolverHelper::resolveTriggerName($trigger) 1177 : ''; 1178 } 1179 } 1180 } 1181 } 1182 1183 if ($elems['hosts'] && $hlabel) { 1184 foreach ($elems['hosts'] as $selement) { 1185 if ($selement['permission'] >= PERM_READ) { 1186 $info[$selement['selementid']]['name'] = array_key_exists($selement['elements'][0]['hostid'], $allHosts) 1187 ? $allHosts[$selement['elements'][0]['hostid']]['name'] 1188 : []; 1189 } 1190 } 1191 } 1192 1193 return $info; 1194} 1195 1196/** 1197 * Takes sysmap selements array, applies filtering by application to triggers and returns sysmap selements array. 1198 * 1199 * @param array $selements selements of current sysmap 1200 * @param array $selementHostApplicationFilters a list of application filters applied to each host under each element 1201 * @see getSelementHostApplicationFilters() 1202 * @param array $triggersFromMonitoredHosts triggers that are relevant to filtering 1203 * @param array $subSysmapTriggerIdToSelementIds a map of triggers in sysmaps to selement IDs 1204 * 1205 * @return array 1206 */ 1207function filterSysmapTriggers(array $selements, array $selementHostApplicationFilters, 1208 array $triggersFromMonitoredHosts, array $subSysmapTriggerIdToSelementIds) { 1209 // pick only host, host group or map selements 1210 $filterableSelements = []; 1211 foreach ($selements as $selementId => $selement) { 1212 if ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST 1213 || $selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 1214 || $selement['elementtype'] == SYSMAP_ELEMENT_TYPE_MAP) { 1215 $filterableSelements[$selementId] = $selement; 1216 } 1217 } 1218 // calculate list of triggers that might get removed from $selement['triggers'] 1219 $triggersToFilter = []; 1220 foreach ($filterableSelements as $selementId => $selement) { 1221 foreach ($selement['triggers'] as $trigger) { 1222 if (!isset($triggersFromMonitoredHosts[$trigger['triggerid']])) { 1223 continue; 1224 } 1225 $trigger = $triggersFromMonitoredHosts[$trigger['triggerid']]; 1226 foreach ($trigger['hosts'] as $host) { 1227 $hostId = $host['hostid']; 1228 if (isset($selementHostApplicationFilters[$selementId][$hostId])) { 1229 $triggersToFilter[$trigger['triggerid']] = $trigger; 1230 } 1231 } 1232 } 1233 } 1234 1235 // if there are no triggers to filter 1236 if (!$triggersToFilter) { 1237 return $selements; 1238 } 1239 1240 // produce mapping of trigger to application names it is related to and produce mapping of host to triggers 1241 $itemIds = []; 1242 foreach ($triggersToFilter as $trigger) { 1243 foreach ($trigger['items'] as $item) { 1244 $itemIds[$item['itemid']] = $item['itemid']; 1245 } 1246 } 1247 $items = API::Item()->get([ 1248 'output' => ['itemid'], 1249 'selectApplications' => ['name'], 1250 'itemids' => $itemIds, 1251 'webitems' => true, 1252 'preservekeys' => true 1253 ]); 1254 1255 $triggerApplications = []; 1256 $hostIdToTriggers = []; 1257 foreach ($triggersToFilter as $trigger) { 1258 $triggerId = $trigger['triggerid']; 1259 1260 foreach ($trigger['items'] as $item) { 1261 foreach ($items[$item['itemid']]['applications'] as $application) { 1262 $triggerApplications[$triggerId][$application['name']] = true; 1263 } 1264 } 1265 1266 foreach ($trigger['hosts'] as $host) { 1267 $hostIdToTriggers[$host['hostid']][$triggerId] = $trigger; 1268 } 1269 } 1270 1271 foreach ($filterableSelements as $selementId => &$selement) { 1272 // walk through each host of a submap and apply its filters to all its triggers 1273 foreach ($selement['hosts'] as $hostId) { 1274 // skip hosts that don't have any filters or triggers to filter 1275 if (!isset($hostIdToTriggers[$hostId]) || !isset($selementHostApplicationFilters[$selementId][$hostId])) { 1276 continue; 1277 } 1278 1279 // remove the triggers that don't have applications or don't match the filter 1280 $filteredApplicationNames = $selementHostApplicationFilters[$selementId][$hostId]; 1281 foreach ($hostIdToTriggers[$hostId] as $trigger) { 1282 $triggerId = $trigger['triggerid']; 1283 1284 // skip if this trigger is standalone trigger and those are not filtered 1285 if (isset($subSysmapTriggerIdToSelementIds[$triggerId]) 1286 && isset($subSysmapTriggerIdToSelementIds[$triggerId][$selementId])) { 1287 continue; 1288 } 1289 1290 $applicationNamesForTrigger = isset($triggerApplications[$triggerId]) 1291 ? array_keys($triggerApplications[$triggerId]) 1292 : []; 1293 1294 if (!array_intersect($applicationNamesForTrigger, $filteredApplicationNames)) { 1295 unset($selement['triggers'][$triggerId]); 1296 } 1297 } 1298 } 1299 } 1300 unset($selement); 1301 1302 // put back updated selements 1303 foreach ($filterableSelements as $selementId => $selement) { 1304 $selements[$selementId] = $selement; 1305 } 1306 1307 return $selements; 1308} 1309 1310/** 1311 * Returns a list of application filters applied to each host under each element. 1312 * 1313 * @param array $selements selements of current sysmap 1314 * @param array $selementIdToSubSysmaps all sub-sysmaps used in current sysmap, indexed by selementId 1315 * @param array $hostsFromHostGroups collection of hosts that get included via host groups 1316 * 1317 * @return array a two-dimensional array with selement IDs as the primary key, host IDs as the secondary key 1318 * application names as values 1319 */ 1320function getSelementHostApplicationFilters(array $selements, array $selementIdToSubSysmaps, 1321 array $hostsFromHostGroups) { 1322 $hostIdsForHostGroupId = []; 1323 foreach ($hostsFromHostGroups as $host) { 1324 $hostId = $host['hostid']; 1325 foreach ($host['groups'] as $group) { 1326 $hostIdsForHostGroupId[$group['groupid']][$hostId] = $hostId; 1327 } 1328 } 1329 1330 $selementHostApplicationFilters = []; 1331 foreach ($selements as $selementId => $selement) { 1332 switch ($selement['elementtype']) { 1333 case SYSMAP_ELEMENT_TYPE_HOST: 1334 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 1335 // skip host and host group elements with an empty filter 1336 if ($selement['application'] === '') { 1337 continue 2; 1338 } 1339 1340 foreach ($selement['hosts'] as $hostId) { 1341 $selementHostApplicationFilters[$selementId][$hostId][] = $selement['application']; 1342 } 1343 1344 break; 1345 1346 case SYSMAP_ELEMENT_TYPE_MAP: 1347 if (array_key_exists($selementId, $selementIdToSubSysmaps)) { 1348 foreach ($selementIdToSubSysmaps[$selementId] as $subSysmap) { 1349 // add all filters set for host elements 1350 foreach ($subSysmap['selements'] as $subSysmapSelement) { 1351 if ($subSysmapSelement['elementtype'] != SYSMAP_ELEMENT_TYPE_HOST 1352 || $subSysmapSelement['application'] === '') { 1353 1354 continue; 1355 } 1356 1357 $hostId = $subSysmapSelement['elements'][0]['hostid']; 1358 $selementHostApplicationFilters[$selementId][$hostId][] = $subSysmapSelement['application']; 1359 } 1360 1361 // Find all selements with host groups and sort them into two arrays: 1362 // - with application filter 1363 // - without application filter 1364 $hostGroupSelementsWithApplication = []; 1365 $hostGroupSelementsWithoutApplication = []; 1366 foreach ($subSysmap['selements'] as $subSysmapSelement) { 1367 if ($subSysmapSelement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP) { 1368 if ($subSysmapSelement['application'] !== '') { 1369 $hostGroupSelementsWithApplication[] = $subSysmapSelement; 1370 } 1371 else { 1372 $hostGroupSelementsWithoutApplication[] = $subSysmapSelement; 1373 } 1374 } 1375 } 1376 1377 // Combine application filters for hosts from host group selements with 1378 // application filters set. 1379 foreach ($hostGroupSelementsWithApplication as $hostGroupSelement) { 1380 $hostGroupId = $hostGroupSelement['elements'][0]['groupid']; 1381 1382 if (isset($hostIdsForHostGroupId[$hostGroupId])) { 1383 foreach ($hostIdsForHostGroupId[$hostGroupId] as $hostId) { 1384 $selementHostApplicationFilters[$selementId][$hostId][] 1385 = $hostGroupSelement['application']; 1386 } 1387 } 1388 } 1389 1390 // Unset all application filters for hosts in host group selements without any filters. 1391 // This might reset application filters set by previous foreach. 1392 foreach ($hostGroupSelementsWithoutApplication AS $hostGroupSelement) { 1393 $hostGroupId = $hostGroupSelement['elements'][0]['groupid']; 1394 1395 if (isset($hostIdsForHostGroupId[$hostGroupId])) { 1396 foreach ($hostIdsForHostGroupId[$hostGroupId] as $hostId) { 1397 unset($selementHostApplicationFilters[$selementId][$hostId]); 1398 } 1399 } 1400 } 1401 } 1402 } 1403 break; 1404 } 1405 } 1406 1407 return $selementHostApplicationFilters; 1408} 1409 1410function separateMapElements($sysmap) { 1411 $elements = [ 1412 'sysmaps' => [], 1413 'hostgroups' => [], 1414 'hosts' => [], 1415 'triggers' => [], 1416 'images' => [] 1417 ]; 1418 1419 foreach ($sysmap['selements'] as $selement) { 1420 switch ($selement['elementtype']) { 1421 case SYSMAP_ELEMENT_TYPE_MAP: 1422 $elements['sysmaps'][$selement['selementid']] = $selement; 1423 break; 1424 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 1425 $elements['hostgroups'][$selement['selementid']] = $selement; 1426 break; 1427 case SYSMAP_ELEMENT_TYPE_HOST: 1428 $elements['hosts'][$selement['selementid']] = $selement; 1429 break; 1430 case SYSMAP_ELEMENT_TYPE_TRIGGER: 1431 $elements['triggers'][$selement['selementid']] = $selement; 1432 break; 1433 case SYSMAP_ELEMENT_TYPE_IMAGE: 1434 default: 1435 $elements['images'][$selement['selementid']] = $selement; 1436 } 1437 } 1438 return $elements; 1439} 1440 1441/** 1442 * For each host group which is area for hosts virtual elements as hosts from that host group are created. 1443 * 1444 * @param array $map Map data. 1445 * @param array $theme Theme used to create missing elements (like hostgroup frame). 1446 * 1447 * @return array Areas with area coordinates and selementids. 1448 */ 1449function populateFromMapAreas(array &$map, array $theme) { 1450 $areas = []; 1451 $new_selementid = ((count($map['selements']) > 0) ? (int) max(array_keys($map['selements'])) : 0) + 1; 1452 $new_linkid = ((count($map['links']) > 0) ? (int) max(array_keys($map['links'])) : 0) + 1; 1453 1454 foreach ($map['selements'] as $selement) { 1455 if ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 1456 && $selement['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) { 1457 $area = ['selementids' => []]; 1458 $origSelement = $selement; 1459 1460 $hosts = API::Host()->get([ 1461 'output' => ['hostid'], 1462 'groupids' => $selement['elements'][0]['groupid'], 1463 'sortfield' => 'name', 1464 'preservekeys' => true 1465 ]); 1466 1467 if (!$hosts) { 1468 continue; 1469 } 1470 1471 if ($selement['areatype'] == SYSMAP_ELEMENT_AREA_TYPE_CUSTOM) { 1472 $area['width'] = $selement['width']; 1473 $area['height'] = $selement['height']; 1474 $area['x'] = $selement['x']; 1475 $area['y'] = $selement['y']; 1476 1477 $map['shapes'][] = [ 1478 'sysmap_shapeid' => 'e-' . $selement['selementid'], 1479 'type' => SYSMAP_SHAPE_TYPE_RECTANGLE, 1480 'x' => $selement['x'], 1481 'y' => $selement['y'], 1482 'width' => $selement['width'], 1483 'height' => $selement['height'], 1484 'border_type' => SYSMAP_SHAPE_BORDER_TYPE_SOLID, 1485 'border_width' => 3, 1486 'border_color' => $theme['maingridcolor'], 1487 'background_color' => '', 1488 'zindex' => -1 1489 ]; 1490 } 1491 else { 1492 $area['width'] = $map['width']; 1493 $area['height'] = $map['height']; 1494 $area['x'] = 0; 1495 $area['y'] = 0; 1496 } 1497 1498 foreach ($hosts as $host) { 1499 $selement['elementtype'] = SYSMAP_ELEMENT_TYPE_HOST; 1500 $selement['elementsubtype'] = SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP; 1501 $selement['elements'][0]['hostid'] = $host['hostid']; 1502 1503 while (array_key_exists($new_selementid, $map['selements'])) { 1504 $new_selementid += 1; 1505 } 1506 $selement['selementid'] = -$new_selementid; 1507 1508 $area['selementids'][$new_selementid] = $new_selementid; 1509 $map['selements'][$new_selementid] = $selement; 1510 } 1511 1512 $areas[] = $area; 1513 1514 $selements = zbx_toHash($map['selements'], 'selementid'); 1515 1516 foreach ($map['links'] as $link) { 1517 // Do not multiply links between two areas. 1518 $id1 = $link['selementid1']; 1519 $id2 = $link['selementid2']; 1520 1521 if ($selements[$id1]['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 1522 && $selements[$id1]['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS 1523 && $selements[$id2]['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 1524 && $selements[$id2]['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) { 1525 continue; 1526 } 1527 1528 $id_number = null; 1529 1530 if ($id1 == $origSelement['selementid']) { 1531 $id_number = 'selementid1'; 1532 } 1533 elseif ($id2 == $origSelement['selementid']) { 1534 $id_number = 'selementid2'; 1535 } 1536 1537 if ($id_number) { 1538 foreach ($area['selementids'] as $selement_id) { 1539 while (array_key_exists($new_linkid, $map['links'])) { 1540 $new_linkid += 1; 1541 } 1542 1543 $link['linkid'] = -$new_linkid; 1544 $link[$id_number] = -$selement_id; 1545 $map['links'][$new_linkid] = $link; 1546 } 1547 } 1548 } 1549 } 1550 } 1551 1552 $selements = []; 1553 1554 foreach ($map['selements'] as $key => $element) { 1555 if ($element['elementtype'] != SYSMAP_ELEMENT_TYPE_HOST_GROUP 1556 || $element['elementsubtype'] != SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS) { 1557 $selements[$key] = $element; 1558 } 1559 } 1560 1561 $map['selements'] = $selements; 1562 1563 return $areas; 1564} 1565 1566/** 1567 * Calculates coordinates from elements inside areas 1568 * 1569 * @param array $map 1570 * @param array $areas 1571 * @param array $mapInfo 1572 */ 1573function processAreasCoordinates(array &$map, array $areas, array $mapInfo) { 1574 foreach ($areas as $area) { 1575 $rowPlaceCount = ceil(sqrt(count($area['selementids']))); 1576 1577 // offset from area borders 1578 $area['x'] += 5; 1579 $area['y'] += 5; 1580 $area['width'] -= 5; 1581 $area['height'] -= 5; 1582 1583 $xOffset = floor($area['width'] / $rowPlaceCount); 1584 $yOffset = floor($area['height'] / $rowPlaceCount); 1585 1586 $colNum = 0; 1587 $rowNum = 0; 1588 // some offset is required so that icon highlights are not drawn outside area 1589 $borderOffset = 20; 1590 foreach ($area['selementids'] as $selementId) { 1591 $selement = $map['selements'][$selementId]; 1592 1593 $image = get_png_by_selement($mapInfo[$selementId]); 1594 $iconX = imagesx($image); 1595 $iconY = imagesy($image); 1596 1597 $labelLocation = (is_null($selement['label_location']) || ($selement['label_location'] < 0)) 1598 ? $map['label_location'] : $selement['label_location']; 1599 switch ($labelLocation) { 1600 case MAP_LABEL_LOC_TOP: 1601 $newX = $area['x'] + ($xOffset / 2) - ($iconX / 2); 1602 $newY = $area['y'] + $yOffset - $iconY - ($iconY >= $iconX ? 0 : abs($iconX - $iconY) / 2) - $borderOffset; 1603 break; 1604 case MAP_LABEL_LOC_LEFT: 1605 $newX = $area['x'] + $xOffset - $iconX - $borderOffset; 1606 $newY = $area['y'] + ($yOffset / 2) - ($iconY / 2); 1607 break; 1608 case MAP_LABEL_LOC_RIGHT: 1609 $newX = $area['x'] + $borderOffset; 1610 $newY = $area['y'] + ($yOffset / 2) - ($iconY / 2); 1611 break; 1612 case MAP_LABEL_LOC_BOTTOM: 1613 $newX = $area['x'] + ($xOffset / 2) - ($iconX / 2); 1614 $newY = $area['y'] + abs($iconX - $iconY) / 2 + $borderOffset; 1615 break; 1616 } 1617 1618 $map['selements'][$selementId]['x'] = $newX + ($colNum * $xOffset); 1619 $map['selements'][$selementId]['y'] = $newY + ($rowNum * $yOffset); 1620 1621 $colNum++; 1622 if ($colNum == $rowPlaceCount) { 1623 $colNum = 0; 1624 $rowNum++; 1625 } 1626 } 1627 } 1628} 1629 1630/** 1631 * Calculates area connector point on area perimeter 1632 * 1633 * @param int $ax x area coordinate 1634 * @param int $ay y area coordinate 1635 * @param int $aWidth area width 1636 * @param int $aHeight area height 1637 * @param int $x2 x coordinate of connector second element 1638 * @param int $y2 y coordinate of connector second element 1639 * 1640 * @return array contains two values, x and y coordinates of new area connector point 1641 */ 1642function calculateMapAreaLinkCoord($ax, $ay, $aWidth, $aHeight, $x2, $y2) { 1643 $dY = abs($y2 - $ay); 1644 $dX = abs($x2 - $ax); 1645 1646 $halfHeight = $aHeight / 2; 1647 $halfWidth = $aWidth / 2; 1648 1649 if ($dY == 0) { 1650 $ay = $y2; 1651 $ax = ($x2 < $ax) ? $ax - $halfWidth : $ax + $halfWidth; 1652 } 1653 elseif ($dX == 0) { 1654 $ay = ($y2 > $ay) ? $ay + $halfHeight : $ay - $halfHeight; 1655 $ax = $x2; 1656 } 1657 else { 1658 $koef = $halfHeight / $dY; 1659 1660 $c = $dX * $koef; 1661 1662 // If point is further than area diagonal, we should use calculations with width instead of height. 1663 if (($halfHeight / $c) > ($halfHeight / $halfWidth)) { 1664 $ay = ($y2 > $ay) ? $ay + $halfHeight : $ay - $halfHeight; 1665 $ax = ($x2 < $ax) ? $ax - $c : $ax + $c; 1666 } 1667 else { 1668 $koef = $halfWidth / $dX; 1669 1670 $c = $dY * $koef; 1671 1672 $ay = ($y2 > $ay) ? $ay + $c : $ay - $c; 1673 $ax = ($x2 < $ax) ? $ax - $halfWidth : $ax + $halfWidth; 1674 } 1675 } 1676 1677 return [$ax, $ay]; 1678} 1679 1680/** 1681 * Get icon id by mapping. 1682 * 1683 * @param array $iconMap 1684 * @param array $inventory 1685 * 1686 * @return int 1687 */ 1688function getIconByMapping($iconMap, $inventory) { 1689 if ($inventory['inventory']['inventory_mode'] != HOST_INVENTORY_DISABLED) { 1690 $inventories = getHostInventories(); 1691 1692 foreach ($iconMap['mappings'] as $mapping) { 1693 try { 1694 $expr = new CGlobalRegexp($mapping['expression']); 1695 if ($expr->match($inventory['inventory'][$inventories[$mapping['inventory_link']]['db_field']])) { 1696 return $mapping['iconid']; 1697 } 1698 } 1699 catch(Exception $e) { 1700 continue; 1701 } 1702 } 1703 } 1704 1705 return $iconMap['default_iconid']; 1706} 1707 1708/** 1709 * Get parent maps for current map. 1710 * 1711 * @param int $sysmapid 1712 * 1713 * @return array 1714 */ 1715function get_parent_sysmaps($sysmapid) { 1716 $db_sysmaps_elements = DBselect( 1717 'SELECT DISTINCT se.sysmapid'. 1718 ' FROM sysmaps_elements se'. 1719 ' WHERE '.dbConditionInt('se.elementtype', [SYSMAP_ELEMENT_TYPE_MAP]). 1720 ' AND '.dbConditionInt('se.elementid', [$sysmapid]) 1721 ); 1722 1723 $sysmapids = []; 1724 1725 while ($db_sysmaps_element = DBfetch($db_sysmaps_elements)) { 1726 $sysmapids[] = $db_sysmaps_element['sysmapid']; 1727 } 1728 1729 if ($sysmapids) { 1730 $sysmaps = API::Map()->get([ 1731 'output' => ['sysmapid', 'name'], 1732 'sysmapids' => $sysmapids 1733 ]); 1734 1735 CArrayHelper::sort($sysmaps, ['name']); 1736 1737 return $sysmaps; 1738 } 1739 1740 return []; 1741} 1742 1743/** 1744 * Get labels for map elements. 1745 * 1746 * @param array $map Sysmap data array. 1747 * @param array $map_info Array of selements (@see getSelementsInfo). 1748 * 1749 * @return array 1750 */ 1751function getMapLabels($map, $map_info) { 1752 if ($map['label_type'] == MAP_LABEL_TYPE_NOTHING && $map['label_format'] == SYSMAP_LABEL_ADVANCED_OFF) { 1753 return; 1754 } 1755 1756 $selements = $map['selements']; 1757 1758 // set label type and custom label text for all selements 1759 foreach ($selements as $selementId => $selement) { 1760 if ($selement['permission'] < PERM_READ) { 1761 continue; 1762 } 1763 1764 $selements[$selementId]['label_type'] = $map['label_type']; 1765 1766 if ($map['label_format'] == SYSMAP_LABEL_ADVANCED_OFF) { 1767 continue; 1768 } 1769 1770 switch ($selement['elementtype']) { 1771 case SYSMAP_ELEMENT_TYPE_HOST_GROUP: 1772 $selements[$selementId]['label_type'] = $map['label_type_hostgroup']; 1773 if ($map['label_type_hostgroup'] == MAP_LABEL_TYPE_CUSTOM) { 1774 $selements[$selementId]['label'] = $map['label_string_hostgroup']; 1775 } 1776 break; 1777 1778 case SYSMAP_ELEMENT_TYPE_HOST: 1779 $selements[$selementId]['label_type'] = $map['label_type_host']; 1780 if ($map['label_type_host'] == MAP_LABEL_TYPE_CUSTOM) { 1781 $selements[$selementId]['label'] = $map['label_string_host']; 1782 } 1783 break; 1784 1785 case SYSMAP_ELEMENT_TYPE_TRIGGER: 1786 $selements[$selementId]['label_type'] = $map['label_type_trigger']; 1787 if ($map['label_type_trigger'] == MAP_LABEL_TYPE_CUSTOM) { 1788 $selements[$selementId]['label'] = $map['label_string_trigger']; 1789 } 1790 break; 1791 1792 case SYSMAP_ELEMENT_TYPE_MAP: 1793 $selements[$selementId]['label_type'] = $map['label_type_map']; 1794 if ($map['label_type_map'] == MAP_LABEL_TYPE_CUSTOM) { 1795 $selements[$selementId]['label'] = $map['label_string_map']; 1796 } 1797 break; 1798 1799 case SYSMAP_ELEMENT_TYPE_IMAGE: 1800 $selements[$selementId]['label_type'] = $map['label_type_image']; 1801 if ($map['label_type_image'] == MAP_LABEL_TYPE_CUSTOM) { 1802 $selements[$selementId]['label'] = $map['label_string_image']; 1803 } 1804 break; 1805 } 1806 } 1807 1808 $labelLines = []; 1809 $statusLines = []; 1810 1811 foreach ($selements as $selementId => $selement) { 1812 if ($selement['permission'] < PERM_READ) { 1813 continue; 1814 } 1815 1816 $labelLines[$selementId] = []; 1817 $statusLines[$selementId] = []; 1818 1819 $msgs = explode("\n", CMacrosResolverHelper::resolveMapLabelMacrosAll($selement)); 1820 foreach ($msgs as $msg) { 1821 $labelLines[$selementId][] = ['content' => $msg]; 1822 } 1823 1824 $elementInfo = $map_info[$selementId]; 1825 1826 foreach (['problem', 'unack', 'maintenance', 'ok', 'status'] as $caption) { 1827 if (!isset($elementInfo['info'][$caption]) || zbx_empty($elementInfo['info'][$caption]['msg'])) { 1828 continue; 1829 } 1830 1831 $msgs = explode("\n", $elementInfo['info'][$caption]['msg']); 1832 1833 foreach ($msgs as $msg) { 1834 $statusLines[$selementId][] = [ 1835 'content' => $msg, 1836 'attributes' => [ 1837 'fill' => '#' . $elementInfo['info'][$caption]['color'] 1838 ] 1839 ]; 1840 } 1841 } 1842 } 1843 1844 $elementsHostIds = []; 1845 foreach ($selements as $selement) { 1846 if ($selement['permission'] < PERM_READ) { 1847 continue; 1848 } 1849 1850 if ($selement['label_type'] != MAP_LABEL_TYPE_IP) { 1851 continue; 1852 } 1853 if ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST) { 1854 $elementsHostIds[] = $selement['elements'][0]['hostid']; 1855 } 1856 } 1857 1858 if (!empty($elementsHostIds)) { 1859 $mapHosts = API::Host()->get([ 1860 'output' => ['hostid'], 1861 'selectInterfaces' => API_OUTPUT_EXTEND, 1862 'hostids' => $elementsHostIds 1863 ]); 1864 $mapHosts = zbx_toHash($mapHosts, 'hostid'); 1865 } 1866 1867 $labels = []; 1868 foreach ($selements as $selementId => $selement) { 1869 if ($selement['permission'] < PERM_READ) { 1870 continue; 1871 } 1872 1873 if (empty($selement) || $selement['label_type'] == MAP_LABEL_TYPE_NOTHING) { 1874 $labels[$selementId] = []; 1875 continue; 1876 } 1877 1878 $elementInfo = $map_info[$selementId]; 1879 1880 $hl_color = null; 1881 $st_color = null; 1882 1883 if (!isset($_REQUEST['noselements']) && ($map['highlight'] % 2) == SYSMAP_HIGHLIGHT_ON) { 1884 if ($elementInfo['icon_type'] == SYSMAP_ELEMENT_ICON_ON) { 1885 $hl_color = true; 1886 } 1887 if ($elementInfo['icon_type'] == SYSMAP_ELEMENT_ICON_MAINTENANCE) { 1888 $st_color = true; 1889 } 1890 if ($elementInfo['icon_type'] == SYSMAP_ELEMENT_ICON_DISABLED) { 1891 $st_color = true; 1892 } 1893 } 1894 1895 if (in_array($selement['elementtype'], [SYSMAP_ELEMENT_TYPE_HOST_GROUP, SYSMAP_ELEMENT_TYPE_MAP]) 1896 && !is_null($hl_color)) { 1897 $st_color = null; 1898 } 1899 elseif (!is_null($st_color)) { 1900 $hl_color = null; 1901 } 1902 1903 $label = []; 1904 1905 if ($selement['label_type'] == MAP_LABEL_TYPE_IP && $selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST) { 1906 $interface = reset($mapHosts[$selement['elements'][0]['hostid']]['interfaces']); 1907 1908 $label[] = ['content' => $interface['ip']]; 1909 $label = array_merge($label, $statusLines[$selementId]); 1910 } 1911 elseif ($selement['label_type'] == MAP_LABEL_TYPE_STATUS) { 1912 $label = $statusLines[$selementId]; 1913 } 1914 elseif ($selement['label_type'] == MAP_LABEL_TYPE_NAME) { 1915 $label[] = ['content' => $elementInfo['name']]; 1916 $label = array_merge($label, $statusLines[$selementId]); 1917 } 1918 else { 1919 $label = array_merge($labelLines[$selementId], $statusLines[$selementId]); 1920 } 1921 1922 $labels[$selementId] = $label; 1923 } 1924 1925 return $labels; 1926} 1927 1928/** 1929 * Get map element highlights (information about elements with marks or background). 1930 * 1931 * @param array $map Sysmap data array. 1932 * @param array $map_info Array of selements (@see getSelementsInfo). 1933 * 1934 * @return array 1935 */ 1936function getMapHighligts(array $map, array $map_info) { 1937 $highlights = []; 1938 1939 foreach ($map['selements'] as $id => $selement) { 1940 if ((($map['highlight'] % 2) != SYSMAP_HIGHLIGHT_ON) || (array_key_exists('elementtype', $selement) 1941 && $selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 1942 && array_key_exists('elementsubtype', $selement) 1943 && $selement['elementsubtype'] == SYSMAP_ELEMENT_SUBTYPE_HOST_GROUP_ELEMENTS)) { 1944 $highlights[$id] = null; 1945 continue; 1946 } 1947 1948 $hl_color = null; 1949 $st_color = null; 1950 $element_info = $map_info[$id]; 1951 1952 switch ($element_info['icon_type']) { 1953 case SYSMAP_ELEMENT_ICON_ON: 1954 $hl_color = getSeverityColor($element_info['priority']); 1955 break; 1956 1957 case SYSMAP_ELEMENT_ICON_MAINTENANCE: 1958 $st_color = 'FF9933'; 1959 break; 1960 1961 case SYSMAP_ELEMENT_ICON_DISABLED: 1962 $st_color = '999999'; 1963 break; 1964 } 1965 1966 if (array_key_exists('elementtype', $selement) 1967 && ($selement['elementtype'] == SYSMAP_ELEMENT_TYPE_HOST_GROUP 1968 || $selement['elementtype'] == SYSMAP_ELEMENT_TYPE_MAP) && $hl_color !== null) { 1969 $st_color = null; 1970 } 1971 elseif ($st_color !== null) { 1972 $hl_color = null; 1973 } 1974 1975 $highlights[$id] = [ 1976 'st' => $st_color, 1977 'hl' => $hl_color, 1978 'ack' => ($hl_color !== null && array_key_exists('ack', $element_info) && $element_info['ack']) 1979 ]; 1980 } 1981 1982 return $highlights; 1983} 1984 1985/** 1986 * Get trigger data for all linktriggers. 1987 * 1988 * @param array $sysmap 1989 * @param array $sysmap['show_suppressed'] Whether to show suppressed problems. 1990 * @param array $sysmap['show_unack'] Property specified in sysmap's 'Problem display' field. Used to determine 1991 * whether to show unacknowledged problems only. 1992 * @param array $options Options used to retrieve actions. 1993 * @param int $options['severity_min'] Minimal severity used. 1994 * 1995 * @return array 1996 */ 1997function getMapLinkTriggerInfo($sysmap, $options) { 1998 if (!array_key_exists('severity_min', $options)) { 1999 $options['severity_min'] = TRIGGER_SEVERITY_NOT_CLASSIFIED; 2000 } 2001 2002 $triggerids = []; 2003 2004 foreach ($sysmap['links'] as $link) { 2005 foreach ($link['linktriggers'] as $linktrigger) { 2006 $triggerids[$linktrigger['triggerid']] = true; 2007 } 2008 } 2009 2010 $trigger_options = [ 2011 'output' => ['status', 'value', 'priority'], 2012 'triggerids' => array_keys($triggerids), 2013 'monitored' => true, 2014 'preservekeys' => true 2015 ]; 2016 2017 $problem_options = [ 2018 'show_suppressed' => $sysmap['show_suppressed'], 2019 'acknowledged' => ($sysmap['show_unack'] == EXTACK_OPTION_UNACK) ? false : null 2020 ]; 2021 2022 return getTriggersWithActualSeverity($trigger_options, $problem_options); 2023} 2024 2025/** 2026 * Get map selement label color based on problem and acknowledgement state 2027 * as well as taking custom event status color settings into account. 2028 * 2029 * @throws APIException if the given table does not exist 2030 * 2031 * @param bool $is_problem 2032 * @param bool $is_ack 2033 * 2034 * @return string 2035 */ 2036function getSelementLabelColor($is_problem, $is_ack) { 2037 static $config = null; 2038 static $schema = null; 2039 2040 if ($config === null) { 2041 $config = select_config(); 2042 $schema = DB::getSchema('config'); 2043 } 2044 2045 $ack_unack = $is_ack ? 'ack' : 'unack'; 2046 $ok_problem = $is_problem ? 'problem' : 'ok'; 2047 2048 if ($config['custom_color'] === '1') { 2049 return $config[$ok_problem . '_' . $ack_unack . '_color']; 2050 } 2051 2052 return $schema['fields'][$ok_problem . '_' . $ack_unack . '_color']['default']; 2053} 2054