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 italic($str) { 23 if (is_array($str)) { 24 foreach ($str as $key => $val) { 25 if (is_string($val)) { 26 $em = new CTag('em', true); 27 $em->addItem($val); 28 $str[$key] = $em; 29 } 30 } 31 } 32 elseif (is_string($str)) { 33 $em = new CTag('em', true, ''); 34 $em->addItem($str); 35 $str = $em; 36 } 37 return $str; 38} 39 40function bold($str) { 41 if (is_array($str)) { 42 foreach ($str as $key => $val) { 43 if (is_string($val)) { 44 $str[$key] = new CTag('b', true, $val); 45 } 46 } 47 48 return $str; 49 } 50 51 return new CTag('b', true, $str); 52} 53 54function make_decoration($haystack, $needle, $class = null) { 55 $result = $haystack; 56 57 $tmpHaystack = mb_strtolower($haystack); 58 $tmpNeedle = mb_strtolower($needle); 59 $pos = mb_strpos($tmpHaystack, $tmpNeedle); 60 61 if ($pos !== false) { 62 $start = CHtml::encode(mb_substr($haystack, 0, $pos)); 63 $end = CHtml::encode(mb_substr($haystack, $pos + mb_strlen($needle))); 64 $found = CHtml::encode(mb_substr($haystack, $pos, mb_strlen($needle))); 65 66 if (is_null($class)) { 67 $result = [$start, bold($found), $end]; 68 } 69 else { 70 $result = [$start, (new CSpan($found))->addClass($class), $end]; 71 } 72 } 73 74 return $result; 75} 76 77function prepareUrlParam($value, $name = null) { 78 if (is_array($value)) { 79 $result = ''; 80 81 foreach ($value as $key => $param) { 82 $result .= prepareUrlParam($param, isset($name) ? $name.'['.$key.']' : $key); 83 } 84 } 85 else { 86 $result = '&'.$name.'='.urlencode($value); 87 } 88 89 return $result; 90} 91 92/** 93 * Get ready for url params. 94 * 95 * @param mixed $param param name or array with data depend from $getFromRequest 96 * @param bool $getFromRequest detect data source - input array or $_REQUEST variable 97 * @param string $name if $_REQUEST variable is used this variable not used 98 * 99 * @return string 100 */ 101function url_param($param, $getFromRequest = true, $name = null) { 102 if (is_array($param)) { 103 if ($getFromRequest) { 104 fatal_error(_('URL parameter cannot be array.')); 105 } 106 } 107 else { 108 if (is_null($name)) { 109 if (!$getFromRequest) { 110 fatal_error(_('URL parameter name is empty.')); 111 } 112 113 $name = $param; 114 } 115 } 116 117 if ($getFromRequest) { 118 $value =& $_REQUEST[$param]; 119 } 120 else { 121 $value =& $param; 122 } 123 124 return isset($value) ? prepareUrlParam($value, $name) : ''; 125} 126 127function url_params(array $params) { 128 $result = ''; 129 130 foreach ($params as $param) { 131 $result .= url_param($param); 132 } 133 134 return $result; 135} 136 137function BR() { 138 return new CTag('br'); 139} 140 141function get_icon($type, $params = []) { 142 switch ($type) { 143 case 'favourite': 144 if (CFavorite::exists($params['fav'], $params['elid'], $params['elname'])) { 145 $icon = (new CRedirectButton(SPACE, null)) 146 ->addClass(ZBX_STYLE_BTN_REMOVE_FAV) 147 ->setTitle(_('Remove from favourites')) 148 ->onClick('rm4favorites("'.$params['elname'].'", "'.$params['elid'].'");'); 149 } 150 else { 151 $icon = (new CRedirectButton(SPACE, null)) 152 ->addClass(ZBX_STYLE_BTN_ADD_FAV) 153 ->setTitle(_('Add to favourites')) 154 ->onClick('add2favorites("'.$params['elname'].'", "'.$params['elid'].'");'); 155 } 156 $icon->setId('addrm_fav'); 157 158 return $icon; 159 160 case 'fullscreen': 161 switch (CView::getLayoutMode()) { 162 case ZBX_LAYOUT_KIOSKMODE: 163 $icon = (new CButton(null, ' ')) 164 ->setTitle(_('Normal view')) 165 ->setAttribute('data-layout-mode', ZBX_LAYOUT_NORMAL) 166 ->addClass(ZBX_LAYOUT_MODE) 167 ->addClass(ZBX_STYLE_BTN_DASHBRD_NORMAL) 168 ->addClass(ZBX_STYLE_BTN_MIN); 169 break; 170 171 case ZBX_LAYOUT_FULLSCREEN: 172 $icon = (new CButton(null, ' ')) 173 ->setTitle(_('Kiosk mode')) 174 ->setAttribute('data-layout-mode', ZBX_LAYOUT_KIOSKMODE) 175 ->addClass(ZBX_LAYOUT_MODE) 176 ->addClass(ZBX_STYLE_BTN_KIOSK); 177 break; 178 179 default: 180 $icon = (new CButton(null, ' ')) 181 ->setTitle(_('Fullscreen')) 182 ->setAttribute('data-layout-mode', ZBX_LAYOUT_FULLSCREEN) 183 ->addClass(ZBX_LAYOUT_MODE) 184 ->addClass(ZBX_STYLE_BTN_MAX); 185 } 186 187 return $icon; 188 189 case 'screenconf': 190 return (new CRedirectButton(SPACE, null)) 191 ->addClass(ZBX_STYLE_BTN_CONF) 192 ->setTitle(_('Refresh interval')); 193 194 case 'overviewhelp': 195 return (new CRedirectButton(SPACE, null)) 196 ->addClass(ZBX_STYLE_BTN_INFO); 197 } 198} 199 200/** 201 * Create CDiv with host/template information and references to it's elements 202 * 203 * @param string $currentElement 204 * @param int $hostid 205 * @param int $lld_ruleid 206 * 207 * @return object 208 */ 209function get_header_host_table($current_element, $hostid, $lld_ruleid = 0) { 210 $options = [ 211 'output' => [ 212 'hostid', 'status', 'name', 'maintenance_status', 'flags', 'available', 'snmp_available', 213 'jmx_available', 'ipmi_available', 'error', 'snmp_error', 'jmx_error', 'ipmi_error' 214 ], 215 'selectHostDiscovery' => ['ts_delete'], 216 'hostids' => [$hostid], 217 'editable' => true 218 ]; 219 if ($lld_ruleid == 0) { 220 $options['selectApplications'] = API_OUTPUT_COUNT; 221 $options['selectItems'] = API_OUTPUT_COUNT; 222 $options['selectTriggers'] = API_OUTPUT_COUNT; 223 $options['selectGraphs'] = API_OUTPUT_COUNT; 224 $options['selectDiscoveries'] = API_OUTPUT_COUNT; 225 $options['selectHttpTests'] = API_OUTPUT_COUNT; 226 } 227 228 // get hosts 229 $db_host = API::Host()->get($options); 230 231 if (!$db_host) { 232 $options = [ 233 'output' => ['templateid', 'name', 'flags'], 234 'templateids' => [$hostid], 235 'editable' => true 236 ]; 237 if ($lld_ruleid == 0) { 238 $options['selectApplications'] = API_OUTPUT_COUNT; 239 $options['selectItems'] = API_OUTPUT_COUNT; 240 $options['selectTriggers'] = API_OUTPUT_COUNT; 241 $options['selectGraphs'] = API_OUTPUT_COUNT; 242 $options['selectScreens'] = API_OUTPUT_COUNT; 243 $options['selectDiscoveries'] = API_OUTPUT_COUNT; 244 $options['selectHttpTests'] = API_OUTPUT_COUNT; 245 } 246 247 // get templates 248 $db_host = API::Template()->get($options); 249 250 $is_template = true; 251 } 252 else { 253 $is_template = false; 254 } 255 256 if (!$db_host) { 257 return null; 258 } 259 260 $db_host = reset($db_host); 261 262 // get lld-rules 263 if ($lld_ruleid != 0) { 264 $db_discovery_rule = API::DiscoveryRule()->get([ 265 'output' => ['name'], 266 'selectItems' => API_OUTPUT_COUNT, 267 'selectTriggers' => API_OUTPUT_COUNT, 268 'selectGraphs' => API_OUTPUT_COUNT, 269 'selectHostPrototypes' => API_OUTPUT_COUNT, 270 'itemids' => [$lld_ruleid], 271 'editable' => true 272 ]); 273 $db_discovery_rule = reset($db_discovery_rule); 274 } 275 276 /* 277 * list and host (template) name 278 */ 279 $list = (new CList()) 280 ->addClass(ZBX_STYLE_OBJECT_GROUP) 281 ->addClass(ZBX_STYLE_FILTER_BREADCRUMB); 282 283 $breadcrumbs = (new CListItem(null)) 284 ->setAttribute('role', 'navigation') 285 ->setAttribute('aria-label', _x('Hierarchy', 'screen reader')); 286 287 if ($is_template) { 288 $template = new CSpan( 289 new CLink($db_host['name'], 'templates.php?form=update&templateid='.$db_host['templateid']) 290 ); 291 292 if ($current_element === '') { 293 $template->addClass(ZBX_STYLE_SELECTED); 294 } 295 296 $breadcrumbs->addItem([ 297 new CSpan( 298 new CLink(_('All templates'), 'templates.php?templateid='.$db_host['templateid'].url_param('groupid')) 299 ), 300 '/', 301 $template 302 ]); 303 304 $db_host['hostid'] = $db_host['templateid']; 305 $list->addItem($breadcrumbs); 306 } 307 else { 308 switch ($db_host['status']) { 309 case HOST_STATUS_MONITORED: 310 if ($db_host['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON) { 311 $status = (new CSpan(_('In maintenance')))->addClass(ZBX_STYLE_ORANGE); 312 } 313 else { 314 $status = (new CSpan(_('Enabled')))->addClass(ZBX_STYLE_GREEN); 315 } 316 break; 317 case HOST_STATUS_NOT_MONITORED: 318 $status = (new CSpan(_('Disabled')))->addClass(ZBX_STYLE_RED); 319 break; 320 default: 321 $status = _('Unknown'); 322 break; 323 } 324 325 $host = new CSpan(new CLink(CHtml::encode($db_host['name']), 326 'hosts.php?form=update&hostid='.$db_host['hostid'] 327 )); 328 329 if ($current_element === '') { 330 $host->addClass(ZBX_STYLE_SELECTED); 331 } 332 333 $breadcrumbs->addItem([ 334 new CSpan(new CLink(_('All hosts'), 'hosts.php?hostid='.$db_host['hostid'].url_param('groupid'))), 335 '/', 336 $host 337 ]); 338 $list->addItem($breadcrumbs); 339 $list->addItem($status); 340 $list->addItem(getHostAvailabilityTable($db_host)); 341 342 if ($db_host['flags'] == ZBX_FLAG_DISCOVERY_CREATED && $db_host['hostDiscovery']['ts_delete'] != 0) { 343 $info_icons = [getHostLifetimeIndicator(time(), $db_host['hostDiscovery']['ts_delete'])]; 344 $list->addItem(makeInformationList($info_icons)); 345 } 346 } 347 348 $content_menu = (new CList()) 349 ->setAttribute('role', 'navigation') 350 ->setAttribute('aria-label', _('Content menu')); 351 /* 352 * the count of rows 353 */ 354 if ($lld_ruleid == 0) { 355 // applications 356 $applications = new CSpan([ 357 new CLink(_('Applications'), 'applications.php?hostid='.$db_host['hostid']), 358 CViewHelper::showNum($db_host['applications']) 359 ]); 360 if ($current_element == 'applications') { 361 $applications->addClass(ZBX_STYLE_SELECTED); 362 } 363 $content_menu->addItem($applications); 364 365 // items 366 $items = new CSpan([ 367 new CLink(_('Items'), 'items.php?filter_set=1&hostid='.$db_host['hostid']), 368 CViewHelper::showNum($db_host['items']) 369 ]); 370 if ($current_element == 'items') { 371 $items->addClass(ZBX_STYLE_SELECTED); 372 } 373 $content_menu->addItem($items); 374 375 // triggers 376 $triggers = new CSpan([ 377 new CLink(_('Triggers'), 'triggers.php?hostid='.$db_host['hostid']), 378 CViewHelper::showNum($db_host['triggers']) 379 ]); 380 if ($current_element == 'triggers') { 381 $triggers->addClass(ZBX_STYLE_SELECTED); 382 } 383 $content_menu->addItem($triggers); 384 385 // graphs 386 $graphs = new CSpan([ 387 new CLink(_('Graphs'), 'graphs.php?hostid='.$db_host['hostid']), 388 CViewHelper::showNum($db_host['graphs']) 389 ]); 390 if ($current_element == 'graphs') { 391 $graphs->addClass(ZBX_STYLE_SELECTED); 392 } 393 $content_menu->addItem($graphs); 394 395 // screens 396 if ($is_template) { 397 $screens = new CSpan([ 398 new CLink(_('Screens'), 'screenconf.php?templateid='.$db_host['hostid']), 399 CViewHelper::showNum($db_host['screens']) 400 ]); 401 if ($current_element == 'screens') { 402 $screens->addClass(ZBX_STYLE_SELECTED); 403 } 404 $content_menu->addItem($screens); 405 } 406 407 // discovery rules 408 $lld_rules = new CSpan([ 409 new CLink(_('Discovery rules'), 'host_discovery.php?hostid='.$db_host['hostid']), 410 CViewHelper::showNum($db_host['discoveries']) 411 ]); 412 if ($current_element == 'discoveries') { 413 $lld_rules->addClass(ZBX_STYLE_SELECTED); 414 } 415 $content_menu->addItem($lld_rules); 416 417 // web scenarios 418 $http_tests = new CSpan([ 419 new CLink(_('Web scenarios'), 'httpconf.php?hostid='.$db_host['hostid']), 420 CViewHelper::showNum($db_host['httpTests']) 421 ]); 422 if ($current_element == 'web') { 423 $http_tests->addClass(ZBX_STYLE_SELECTED); 424 } 425 $content_menu->addItem($http_tests); 426 } 427 else { 428 $discovery_rule = (new CSpan())->addItem( 429 new CLink( 430 CHtml::encode($db_discovery_rule['name']), 431 'host_discovery.php?form=update&itemid='.$db_discovery_rule['itemid'] 432 ) 433 ); 434 435 if ($current_element == 'discoveries') { 436 $discovery_rule->addClass(ZBX_STYLE_SELECTED); 437 } 438 439 $list->addItem([ 440 (new CSpan())->addItem( 441 new CLink(_('Discovery list'), 'host_discovery.php?hostid='.$db_host['hostid'].url_param('groupid')) 442 ), 443 '/', 444 $discovery_rule 445 ]); 446 447 // item prototypes 448 $item_prototypes = new CSpan([ 449 new CLink(_('Item prototypes'), 'disc_prototypes.php?parent_discoveryid='.$db_discovery_rule['itemid']), 450 CViewHelper::showNum($db_discovery_rule['items']) 451 ]); 452 if ($current_element == 'items') { 453 $item_prototypes->addClass(ZBX_STYLE_SELECTED); 454 } 455 $content_menu->addItem($item_prototypes); 456 457 // trigger prototypes 458 $trigger_prototypes = new CSpan([ 459 new CLink(_('Trigger prototypes'), 460 'trigger_prototypes.php?parent_discoveryid='.$db_discovery_rule['itemid'] 461 ), 462 CViewHelper::showNum($db_discovery_rule['triggers']) 463 ]); 464 if ($current_element == 'triggers') { 465 $trigger_prototypes->addClass(ZBX_STYLE_SELECTED); 466 } 467 $content_menu->addItem($trigger_prototypes); 468 469 // graph prototypes 470 $graph_prototypes = new CSpan([ 471 new CLink(_('Graph prototypes'), 'graphs.php?parent_discoveryid='.$db_discovery_rule['itemid']), 472 CViewHelper::showNum($db_discovery_rule['graphs']) 473 ]); 474 if ($current_element == 'graphs') { 475 $graph_prototypes->addClass(ZBX_STYLE_SELECTED); 476 } 477 $content_menu->addItem($graph_prototypes); 478 479 // host prototypes 480 if ($db_host['flags'] == ZBX_FLAG_DISCOVERY_NORMAL) { 481 $host_prototypes = new CSpan([ 482 new CLink(_('Host prototypes'), 'host_prototypes.php?parent_discoveryid='.$db_discovery_rule['itemid']), 483 CViewHelper::showNum($db_discovery_rule['hostPrototypes']) 484 ]); 485 if ($current_element == 'hosts') { 486 $host_prototypes->addClass(ZBX_STYLE_SELECTED); 487 } 488 $content_menu->addItem($host_prototypes); 489 } 490 } 491 492 $list->addItem($content_menu); 493 494 return $list; 495} 496 497/** 498 * Create breadcrumbs header object with sysmap parents information. 499 * 500 * @param int $sysmapid Used as value for sysmaid in map link generation. 501 * @param string $name Used as label for map link generation. 502 * @param int $severity_min Used as value for severity_min in map link generation. 503 * 504 * @return object 505 */ 506function get_header_sysmap_table($sysmapid, $name, $severity_min) { 507 $list = (new CList()) 508 ->setAttribute('role', 'navigation') 509 ->setAttribute('aria-label', _x('Hierarchy', 'screen reader')) 510 ->addClass(ZBX_STYLE_OBJECT_GROUP) 511 ->addClass(ZBX_STYLE_FILTER_BREADCRUMB) 512 ->addItem([ 513 (new CSpan())->addItem(new CLink(_('All maps'), new CUrl('sysmaps.php'))), 514 '/', 515 (new CSpan()) 516 ->addClass(ZBX_STYLE_SELECTED) 517 ->addItem( 518 new CLink($name, (new CUrl('zabbix.php')) 519 ->setArgument('action', 'map.view') 520 ->setArgument('sysmapid', $sysmapid) 521 ->setArgument('severity_min', $severity_min) 522 ) 523 ) 524 ]); 525 526 // get map parent maps 527 $parent_sysmaps = get_parent_sysmaps($sysmapid); 528 if ($parent_sysmaps) { 529 $parent_maps = (new CList()) 530 ->setAttribute('role', 'navigation') 531 ->setAttribute('aria-label', _('Upper level maps')) 532 ->addClass(ZBX_STYLE_FILTER_BREADCRUMB) 533 ->addClass(ZBX_STYLE_OBJECT_GROUP) 534 ->addItem((new CSpan())->addItem(_('Upper level maps').':')); 535 536 foreach ($parent_sysmaps as $parent_sysmap) { 537 $parent_maps->addItem((new CSpan())->addItem( 538 new CLink($parent_sysmap['name'], (new CUrl('zabbix.php')) 539 ->setArgument('action', 'map.view') 540 ->setArgument('sysmapid', $parent_sysmap['sysmapid']) 541 ->setArgument('severity_min', $severity_min) 542 )) 543 ); 544 } 545 546 return new CHorList([$list, $parent_maps]); 547 } 548 549 return $list; 550} 551 552/** 553 * Renders a form footer with the given buttons. 554 * 555 * @param CButtonInterface $main_button main button that will be displayed on the left 556 * @param CButtonInterface[] $other_buttons 557 * 558 * @return CDiv 559 * 560 * @throws InvalidArgumentException if an element of $other_buttons contain something other than CButtonInterface 561 */ 562function makeFormFooter(CButtonInterface $main_button = null, array $other_buttons = []) { 563 foreach ($other_buttons as $other_button) { 564 $other_button->addClass(ZBX_STYLE_BTN_ALT); 565 } 566 567 if ($main_button !== null) { 568 array_unshift($other_buttons, $main_button); 569 } 570 571 return (new CList()) 572 ->addClass(ZBX_STYLE_TABLE_FORMS) 573 ->addItem([ 574 (new CDiv())->addClass(ZBX_STYLE_TABLE_FORMS_TD_LEFT), 575 (new CDiv($other_buttons)) 576 ->addClass(ZBX_STYLE_TABLE_FORMS_TD_RIGHT) 577 ->addClass('tfoot-buttons') 578 ]); 579} 580 581/** 582 * Returns zbx, snmp, jmx, ipmi availability status icons and the discovered host lifetime indicator. 583 * 584 * @param array $host an array of host data 585 * 586 * @return CDiv 587 */ 588function getHostAvailabilityTable($host) { 589 $container = (new CDiv())->addClass(ZBX_STYLE_STATUS_CONTAINER); 590 591 foreach (['zbx' => '', 'snmp' => 'snmp_', 'jmx' => 'jmx_', 'ipmi' => 'ipmi_'] as $type => $prefix) { 592 switch ($host[$prefix.'available']) { 593 case HOST_AVAILABLE_TRUE: 594 $ai = (new CSpan($type))->addClass(ZBX_STYLE_STATUS_GREEN); 595 break; 596 case HOST_AVAILABLE_FALSE: 597 $ai = (new CSpan($type))->addClass(ZBX_STYLE_STATUS_RED); 598 599 if ($host[$prefix.'error'] !== '') { 600 $ai 601 ->addClass(ZBX_STYLE_CURSOR_POINTER) 602 ->setHint($host[$prefix.'error'], ZBX_STYLE_RED); 603 } 604 605 break; 606 case HOST_AVAILABLE_UNKNOWN: 607 $ai = (new CSpan($type))->addClass(ZBX_STYLE_STATUS_GREY); 608 break; 609 } 610 $container->addItem($ai); 611 } 612 613 return $container; 614} 615 616/** 617 * Returns the discovered host group lifetime indicator. 618 * 619 * @param string $current_time current Unix timestamp 620 * @param array $ts_delete deletion timestamp of the host group 621 * 622 * @return CDiv 623 */ 624function getHostGroupLifetimeIndicator($current_time, $ts_delete) { 625 // Check if the element should've been deleted in the past. 626 if ($current_time > $ts_delete) { 627 $warning = _( 628 'The host group is not discovered anymore and will be deleted the next time discovery rule is processed.' 629 ); 630 } 631 else { 632 $warning = _s( 633 'The host group is not discovered anymore and will be deleted in %1$s (on %2$s at %3$s).', 634 zbx_date2age($current_time, $ts_delete), 635 zbx_date2str(DATE_FORMAT, $ts_delete), 636 zbx_date2str(TIME_FORMAT, $ts_delete) 637 ); 638 } 639 640 return makeWarningIcon($warning); 641} 642 643/** 644 * Returns the discovered host lifetime indicator. 645 * 646 * @param string $current_time current Unix timestamp 647 * @param array $ts_delete deletion timestamp of the host 648 * 649 * @return CDiv 650 */ 651function getHostLifetimeIndicator($current_time, $ts_delete) { 652 // Check if the element should've been deleted in the past. 653 if ($current_time > $ts_delete) { 654 $warning = _( 655 'The host is not discovered anymore and will be deleted the next time discovery rule is processed.' 656 ); 657 } 658 else { 659 $warning = _s( 660 'The host is not discovered anymore and will be deleted in %1$s (on %2$s at %3$s).', 661 zbx_date2age($current_time, $ts_delete), 662 zbx_date2str(DATE_FORMAT, $ts_delete), 663 zbx_date2str(TIME_FORMAT, $ts_delete) 664 ); 665 } 666 667 return makeWarningIcon($warning); 668} 669 670/** 671 * Returns the discovered application lifetime indicator. 672 * 673 * @param string $current_time current Unix timestamp 674 * @param array $ts_delete deletion timestamp of the application 675 * 676 * @return CDiv 677 */ 678function getApplicationLifetimeIndicator($current_time, $ts_delete) { 679 // Check if the element should've been deleted in the past. 680 if ($current_time > $ts_delete) { 681 $warning = _( 682 'The application is not discovered anymore and will be deleted the next time discovery rule is processed.' 683 ); 684 } 685 else { 686 $warning = _s( 687 'The application is not discovered anymore and will be deleted in %1$s (on %2$s at %3$s).', 688 zbx_date2age($current_time, $ts_delete), 689 zbx_date2str(DATE_FORMAT, $ts_delete), 690 zbx_date2str(TIME_FORMAT, $ts_delete) 691 ); 692 } 693 694 return makeWarningIcon($warning); 695} 696 697/** 698 * Returns the discovered item lifetime indicator. 699 * 700 * @param string $current_time current Unix timestamp 701 * @param array $ts_delete deletion timestamp of the item 702 * 703 * @return CDiv 704 */ 705function getItemLifetimeIndicator($current_time, $ts_delete) { 706 // Check if the element should've been deleted in the past. 707 if ($current_time > $ts_delete) { 708 $warning = _( 709 'The item is not discovered anymore and will be deleted the next time discovery rule is processed.' 710 ); 711 } 712 else { 713 $warning = _s( 714 'The item is not discovered anymore and will be deleted in %1$s (on %2$s at %3$s).', 715 zbx_date2age($current_time, $ts_delete), 716 zbx_date2str(DATE_FORMAT, $ts_delete), 717 zbx_date2str(TIME_FORMAT, $ts_delete) 718 ); 719 } 720 721 return makeWarningIcon($warning); 722} 723 724/** 725 * Renders a page footer. 726 * 727 * @param bool $with_version 728 * 729 * @return CDiv 730 */ 731function makePageFooter($with_version = true) { 732 return (new CTag('footer', true, CBrandHelper::getFooterContent($with_version)))->setAttribute('role', 'contentinfo'); 733} 734 735/** 736 * Renders a drop-down menu for the Administration->General section. 737 * 738 * @param string $selected 739 * 740 * @return CComboBox 741 */ 742function makeAdministrationGeneralMenu($selected) { 743 return new CComboBox('configDropDown', $selected, 'redirect(this.options[this.selectedIndex].value);', [ 744 'adm.gui.php' => _('GUI'), 745 'adm.housekeeper.php' => _('Housekeeping'), 746 'adm.images.php' => _('Images'), 747 'adm.iconmapping.php' => _('Icon mapping'), 748 'adm.regexps.php' => _('Regular expressions'), 749 'adm.macros.php' => _('Macros'), 750 'adm.valuemapping.php' => _('Value mapping'), 751 'adm.workingtime.php' => _('Working time'), 752 'adm.triggerseverities.php' => _('Trigger severities'), 753 'adm.triggerdisplayoptions.php' => _('Trigger displaying options'), 754 'adm.other.php' => _('Other') 755 ]); 756} 757 758/** 759 * Renders an icon list. 760 * 761 * @param array $info_icons The list of information icons. 762 * 763 * @return CDiv|string 764 */ 765function makeInformationList($info_icons) { 766 return $info_icons ? (new CDiv($info_icons))->addClass(ZBX_STYLE_REL_CONTAINER) : ''; 767} 768 769/** 770 * Renders an information icon like green [i] with message. 771 * 772 * @param string $message 773 * 774 * @return CSpan 775 */ 776function makeInformationIcon($message) { 777 return (new CSpan()) 778 ->addClass(ZBX_STYLE_ICON_INFO) 779 ->addClass(ZBX_STYLE_STATUS_GREEN) 780 ->setHint($message); 781} 782 783/** 784 * Renders an icon for host in maintenance. 785 * 786 * @param int $type Type of the maintenance. 787 * @param string $name Name of the maintenance. 788 * @param string $description Description of the maintenance. 789 * 790 * @return CSpan 791 */ 792function makeMaintenanceIcon($type, $name, $description) { 793 $hint = $name.' ['.($type 794 ? _('Maintenance without data collection') 795 : _('Maintenance with data collection')).']'; 796 797 if ($description !== '') { 798 $hint .= "\n".$description; 799 } 800 801 return (new CSpan()) 802 ->addClass(ZBX_STYLE_ICON_MAINT) 803 ->addClass(ZBX_STYLE_CURSOR_POINTER) 804 ->setHint($hint); 805} 806 807/** 808 * Renders an icon for suppressed problem. 809 * 810 * @param array $icon_data 811 * @param string $icon_data[]['suppress_until'] Time until the problem is suppressed. 812 * @param string $icon_data[]['maintenance_name'] Name of the maintenance. 813 * 814 * @return CSpan 815 */ 816function makeSuppressedProblemIcon(array $icon_data) { 817 $suppress_until = max(zbx_objectValues($icon_data, 'suppress_until')); 818 819 CArrayHelper::sort($icon_data, ['maintenance_name']); 820 $maintenance_names = implode(', ', zbx_objectValues($icon_data, 'maintenance_name')); 821 822 return (new CSpan()) 823 ->addClass(ZBX_STYLE_ICON_INVISIBLE) 824 ->addClass(ZBX_STYLE_CURSOR_POINTER) 825 ->setHint( 826 _s('Suppressed till: %1$s', ($suppress_until < strtotime('tomorrow')) 827 ? zbx_date2str(TIME_FORMAT, $suppress_until) 828 : zbx_date2str(DATE_TIME_FORMAT, $suppress_until) 829 ). 830 "\n". 831 _s('Maintenance: %1$s', $maintenance_names) 832 ); 833} 834 835/** 836 * Renders an action icon. 837 * 838 * @param array $icon_data 839 * @param string $icon_data[icon] Icon style. 840 * @param array $icon_data[hint] Hintbox content (optional). 841 * @param int $icon_data[num] Number displayed over the icon (optional). 842 * 843 * @return CSpan 844 */ 845function makeActionIcon(array $icon_data) { 846 $icon = (new CSpan())->addClass($icon_data['icon']); 847 848 if (array_key_exists('num', $icon_data)) { 849 if ($icon_data['num'] > 99) { 850 $icon_data['num'] = '99+'; 851 } 852 $icon->setAttribute('data-count', $icon_data['num']); 853 } 854 855 if (array_key_exists('hint', $icon_data)) { 856 $icon->setHint($icon_data['hint'], '', true, 'max-width: '.ZBX_ACTIONS_POPUP_MAX_WIDTH.'px;'); 857 } 858 elseif (array_key_exists('title', $icon_data)) { 859 $icon->setTitle($icon_data['title']); 860 } 861 862 if (array_key_exists('aria-label', $icon_data)) { 863 $icon 864 ->addItem($icon_data['aria-label']) 865 ->addClass(ZBX_STYLE_INLINE_SR_ONLY); 866 } 867 868 return $icon; 869} 870 871/** 872 * Renders an error icon like red [i] with error message 873 * 874 * @param string $error 875 * 876 * @return CSpan 877 */ 878function makeErrorIcon($error) { 879 return (new CSpan()) 880 ->addClass(ZBX_STYLE_ICON_INFO) 881 ->addClass(ZBX_STYLE_STATUS_RED) 882 ->setHint($error, ZBX_STYLE_RED); 883} 884 885/** 886 * Renders an unknown icon like grey [i] with error message 887 * 888 * @param string $error 889 * 890 * @return CSpan 891 */ 892function makeUnknownIcon($error) { 893 return (new CSpan()) 894 ->addClass(ZBX_STYLE_ICON_INFO) 895 ->addClass(ZBX_STYLE_STATUS_DARK_GREY) 896 ->setHint($error, ZBX_STYLE_RED); 897} 898 899/** 900 * Renders a warning icon like yellow [i] with error message 901 * 902 * @param string $error 903 * 904 * @return CSpan 905 */ 906function makeWarningIcon($error) { 907 return (new CSpan()) 908 ->addClass(ZBX_STYLE_ICON_INFO) 909 ->addClass(ZBX_STYLE_STATUS_YELLOW) 910 ->setHint($error); 911} 912 913/** 914 * Renders a debug button 915 * 916 * @return CButton 917 */ 918function makeDebugButton() { 919 return (new CDiv( 920 (new CLink(_('Debug'), '#debug')) 921 ->onClick("javascript: if (!isset('state', this)) { this.state = 'none'; }". 922 "this.state = (this.state == 'none' ? 'block' : 'none');". 923 "jQuery(this)". 924 ".text(this.state == 'none' ? ".CJs::encodeJson(_('Debug'))." : ".CJs::encodeJson(_('Hide debug')).")". 925 ".blur();". 926 "showHideByName('zbx_debug_info', this.state);" 927 ) 928 ))->addClass(ZBX_STYLE_BTN_DEBUG); 929} 930 931/** 932 * Returns css for trigger severity backgrounds. 933 * 934 * @param array $config 935 * @param array $config[severity_color_0] 936 * @param array $config[severity_color_1] 937 * @param array $config[severity_color_2] 938 * @param array $config[severity_color_3] 939 * @param array $config[severity_color_4] 940 * @param array $config[severity_color_5] 941 * 942 * @return string 943 */ 944function getTriggerSeverityCss($config) { 945 $css = ''; 946 947 $severities = [ 948 ZBX_STYLE_NA_BG => $config['severity_color_0'], 949 ZBX_STYLE_INFO_BG => $config['severity_color_1'], 950 ZBX_STYLE_WARNING_BG => $config['severity_color_2'], 951 ZBX_STYLE_AVERAGE_BG => $config['severity_color_3'], 952 ZBX_STYLE_HIGH_BG => $config['severity_color_4'], 953 ZBX_STYLE_DISASTER_BG => $config['severity_color_5'] 954 ]; 955 956 foreach ($severities as $class => $color) { 957 $css .= '.'.$class.', .'.$class.' input[type="radio"]:checked + label, .'.$class.':before, .flh-'.$class. 958 ', .status-'.$class.' { background-color: #'.$color.' }'."\n"; 959 } 960 961 return $css; 962} 963 964/** 965 * Returns css for trigger status colors, if those are customized. 966 * 967 * @param array $config 968 * @param array $config[custom_color] 969 * @param array $config[problem_unack_color] 970 * @param array $config[problem_ack_color] 971 * @param array $config[ok_unack_color] 972 * @param array $config[ok_ack_color] 973 * 974 * @return string 975 */ 976function getTriggerStatusCss($config) { 977 $css = ''; 978 979 if ($config['custom_color'] == EVENT_CUSTOM_COLOR_ENABLED) { 980 $event_statuses = [ 981 ZBX_STYLE_PROBLEM_UNACK_FG => $config['problem_unack_color'], 982 ZBX_STYLE_PROBLEM_ACK_FG => $config['problem_ack_color'], 983 ZBX_STYLE_OK_UNACK_FG => $config['ok_unack_color'], 984 ZBX_STYLE_OK_ACK_FG => $config['ok_ack_color'] 985 ]; 986 987 foreach ($event_statuses as $class => $color) { 988 $css .= '.' . $class . ' {color: #' . $color . ';}' . "\n"; 989 } 990 } 991 992 return $css; 993} 994