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 22require_once dirname(__FILE__).'/include/config.inc.php'; 23require_once dirname(__FILE__).'/include/hosts.inc.php'; 24require_once dirname(__FILE__).'/include/screens.inc.php'; 25require_once dirname(__FILE__).'/include/forms.inc.php'; 26require_once dirname(__FILE__).'/include/ident.inc.php'; 27 28if (hasRequest('action') && getRequest('action') == 'template.export' && hasRequest('templates')) { 29 $exportData = true; 30 31 $page['type'] = detect_page_type(PAGE_TYPE_XML); 32 $page['file'] = 'zbx_export_templates.xml'; 33} 34else { 35 $exportData = false; 36 37 $page['type'] = detect_page_type(PAGE_TYPE_HTML); 38 $page['title'] = _('Configuration of templates'); 39 $page['file'] = 'templates.php'; 40 $page['scripts'] = ['multiselect.js']; 41} 42 43require_once dirname(__FILE__).'/include/page_header.php'; 44 45// VAR TYPE OPTIONAL FLAGS VALIDATION EXCEPTION 46$fields = [ 47 'hosts' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 48 'groups' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 49 'clear_templates' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 50 'templates' => [T_ZBX_INT, O_OPT, null, DB_ID, null], 51 'add_templates' => [T_ZBX_INT, O_OPT, null, DB_ID, null], 52 'add_template' => [T_ZBX_STR, O_OPT, null, null, null], 53 'templateid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, 'isset({form}) && {form} == "update"'], 54 'template_name' => [T_ZBX_STR, O_OPT, null, NOT_EMPTY, 'isset({add}) || isset({update})', _('Template name')], 55 'visiblename' => [T_ZBX_STR, O_OPT, null, null, 'isset({add}) || isset({update})'], 56 'groupid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 57 'twb_groupid' => [T_ZBX_INT, O_OPT, P_SYS, DB_ID, null], 58 'newgroup' => [T_ZBX_STR, O_OPT, null, null, null], 59 'description' => [T_ZBX_STR, O_OPT, null, null, null], 60 'macros' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 61 'show_inherited_macros' => [T_ZBX_INT, O_OPT, null, IN([0,1]), null], 62 // actions 63 'action' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, 64 IN('"template.export","template.massdelete","template.massdeleteclear"'), 65 null 66 ], 67 'unlink' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 68 'unlink_and_clear' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 69 'add' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 70 'update' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 71 'clone' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 72 'full_clone' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 73 'delete' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 74 'delete_and_clear' => [T_ZBX_STR, O_OPT, P_SYS|P_ACT, null, null], 75 'cancel' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 76 'form' => [T_ZBX_STR, O_OPT, P_SYS, null, null], 77 'form_refresh' => [T_ZBX_INT, O_OPT, null, null, null], 78 // sort and sortorder 79 'sort' => [T_ZBX_STR, O_OPT, P_SYS, IN('"name"'), null], 80 'sortorder' => [T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'), null] 81]; 82check_fields($fields); 83 84/* 85 * Permissions 86 */ 87if (getRequest('groupid') && !API::HostGroup()->isWritable([$_REQUEST['groupid']])) { 88 access_deny(); 89} 90if (getRequest('templateid') && !API::Template()->isWritable([$_REQUEST['templateid']])) { 91 access_deny(); 92} 93 94$templateIds = getRequest('templates', []); 95 96if ($exportData) { 97 $export = new CConfigurationExport(['templates' => $templateIds]); 98 $export->setBuilder(new CConfigurationExportBuilder()); 99 $export->setWriter(CExportWriterFactory::getWriter(CExportWriterFactory::XML)); 100 $exportData = $export->export(); 101 102 if (hasErrorMesssages()) { 103 show_messages(); 104 } 105 else { 106 print($exportData); 107 } 108 109 exit; 110} 111 112// remove inherited macros data (actions: 'add', 'update' and 'form') 113if (hasRequest('macros')) { 114 $_REQUEST['macros'] = cleanInheritedMacros($_REQUEST['macros']); 115 116 // remove empty new macro lines 117 foreach ($_REQUEST['macros'] as $idx => $macro) { 118 if (!array_key_exists('hostmacroid', $macro) && $macro['macro'] === '' && $macro['value'] === '') { 119 unset($_REQUEST['macros'][$idx]); 120 } 121 } 122} 123 124/* 125 * Actions 126 */ 127if (isset($_REQUEST['add_template']) && isset($_REQUEST['add_templates'])) { 128 $_REQUEST['templates'] = array_merge($templateIds, $_REQUEST['add_templates']); 129} 130if (hasRequest('unlink') || hasRequest('unlink_and_clear')) { 131 $unlinkTemplates = []; 132 133 if (hasRequest('unlink') && is_array(getRequest('unlink'))) { 134 $unlinkTemplates = array_keys(getRequest('unlink')); 135 } 136 elseif (hasRequest('unlink_and_clear') && is_array(getRequest('unlink_and_clear'))) { 137 $unlinkTemplates = array_keys(getRequest('unlink_and_clear')); 138 $_REQUEST['clear_templates'] = array_merge($unlinkTemplates, getRequest('clear_templates', [])); 139 } 140 141 foreach ($unlinkTemplates as $id) { 142 unset($_REQUEST['templates'][array_search($id, $_REQUEST['templates'])]); 143 } 144} 145elseif (isset($_REQUEST['clone']) && isset($_REQUEST['templateid'])) { 146 $_REQUEST['form'] = 'clone'; 147 unset($_REQUEST['templateid'], $_REQUEST['hosts']); 148} 149elseif (isset($_REQUEST['full_clone']) && isset($_REQUEST['templateid'])) { 150 $_REQUEST['form'] = 'full_clone'; 151 $_REQUEST['hosts'] = []; 152} 153elseif (hasRequest('add') || hasRequest('update')) { 154 try { 155 DBstart(); 156 157 $templateId = getRequest('templateid', 0); 158 $cloneTemplateId = 0; 159 160 if (getRequest('form') === 'full_clone') { 161 $cloneTemplateId = $templateId; 162 $templateId = 0; 163 } 164 165 if ($templateId == 0) { 166 $messageSuccess = _('Template added'); 167 $messageFailed = _('Cannot add template'); 168 $auditAction = AUDIT_ACTION_ADD; 169 } 170 else { 171 $messageSuccess = _('Template updated'); 172 $messageFailed = _('Cannot update template'); 173 $auditAction = AUDIT_ACTION_UPDATE; 174 } 175 176 // groups 177 $groups = getRequest('groups', []); 178 $groups = zbx_toObject($groups, 'groupid'); 179 180 // create new group 181 $newGroup = getRequest('newgroup'); 182 183 if (!zbx_empty($newGroup)) { 184 $result = API::HostGroup()->create([ 185 'name' => $newGroup 186 ]); 187 188 if (!$result) { 189 throw new Exception(); 190 } 191 192 $newGroup = API::HostGroup()->get([ 193 'groupids' => $result['groupids'], 194 'output' => API_OUTPUT_EXTEND 195 ]); 196 197 if ($newGroup) { 198 $groups = array_merge($groups, $newGroup); 199 } 200 else { 201 throw new Exception(); 202 } 203 } 204 205 // linked templates 206 $linkedTemplates = getRequest('templates', []); 207 $templates = []; 208 foreach ($linkedTemplates as $linkedTemplateId) { 209 $templates[] = ['templateid' => $linkedTemplateId]; 210 } 211 212 $templatesClear = getRequest('clear_templates', []); 213 $templatesClear = zbx_toObject($templatesClear, 'templateid'); 214 215 // discovered hosts 216 $dbHosts = API::Host()->get([ 217 'output' => ['hostid'], 218 'hostids' => getRequest('hosts', []), 219 'templated_hosts' => true, 220 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL] 221 ]); 222 223 $templateName = getRequest('template_name', ''); 224 225 // create / update template 226 $template = [ 227 'host' => $templateName, 228 'name' => getRequest('visiblename', ''), 229 'groups' => $groups, 230 'templates' => $templates, 231 'hosts' => $dbHosts, 232 'macros' => getRequest('macros', []), 233 'description' => getRequest('description', '') 234 ]; 235 236 if ($templateId == 0) { 237 $result = API::Template()->create($template); 238 239 if ($result) { 240 $templateId = reset($result['templateids']); 241 } 242 else { 243 throw new Exception(); 244 } 245 } 246 else { 247 $template['templateid'] = $templateId; 248 $template['templates_clear'] = $templatesClear; 249 250 $result = API::Template()->update($template); 251 252 if (!$result) { 253 throw new Exception(); 254 } 255 } 256 257 // full clone 258 if ($cloneTemplateId != 0 && getRequest('form') === 'full_clone') { 259 if (!copyApplications($cloneTemplateId, $templateId)) { 260 throw new Exception(); 261 } 262 263 if (!copyItems($cloneTemplateId, $templateId)) { 264 throw new Exception(); 265 } 266 267 // copy web scenarios 268 if (!copyHttpTests($cloneTemplateId, $templateId)) { 269 throw new Exception(); 270 } 271 272 // copy triggers 273 $dbTriggers = API::Trigger()->get([ 274 'output' => ['triggerid'], 275 'hostids' => $cloneTemplateId, 276 'inherited' => false 277 ]); 278 279 if ($dbTriggers) { 280 $result &= copyTriggersToHosts(zbx_objectValues($dbTriggers, 'triggerid'), 281 $templateId, $cloneTemplateId); 282 283 if (!$result) { 284 throw new Exception(); 285 } 286 } 287 288 // copy graphs 289 $dbGraphs = API::Graph()->get([ 290 'output' => ['graphid'], 291 'hostids' => $cloneTemplateId, 292 'inherited' => false 293 ]); 294 295 foreach ($dbGraphs as $dbGraph) { 296 copyGraphToHost($dbGraph['graphid'], $templateId); 297 } 298 299 // copy discovery rules 300 $dbDiscoveryRules = API::DiscoveryRule()->get([ 301 'output' => ['itemid'], 302 'hostids' => $cloneTemplateId, 303 'inherited' => false 304 ]); 305 306 if ($dbDiscoveryRules) { 307 $result &= API::DiscoveryRule()->copy([ 308 'discoveryids' => zbx_objectValues($dbDiscoveryRules, 'itemid'), 309 'hostids' => [$templateId] 310 ]); 311 312 if (!$result) { 313 throw new Exception(); 314 } 315 } 316 317 // copy template screens 318 $dbTemplateScreens = API::TemplateScreen()->get([ 319 'output' => ['screenid'], 320 'templateids' => $cloneTemplateId, 321 'preservekeys' => true, 322 'inherited' => false 323 ]); 324 325 if ($dbTemplateScreens) { 326 $result &= API::TemplateScreen()->copy([ 327 'screenIds' => zbx_objectValues($dbTemplateScreens, 'screenid'), 328 'templateIds' => $templateId 329 ]); 330 331 if (!$result) { 332 throw new Exception(); 333 } 334 } 335 } 336 337 if ($result) { 338 add_audit_ext($auditAction, AUDIT_RESOURCE_TEMPLATE, $templateId, $templateName, 'hosts', null, null); 339 } 340 341 unset($_REQUEST['form'], $_REQUEST['templateid']); 342 $result = DBend($result); 343 344 if ($result) { 345 uncheckTableRows(); 346 } 347 show_messages($result, $messageSuccess, $messageFailed); 348 } 349 catch (Exception $e) { 350 DBend(false); 351 show_error_message($messageFailed); 352 } 353} 354elseif (isset($_REQUEST['delete']) && isset($_REQUEST['templateid'])) { 355 DBstart(); 356 357 $result = API::Template()->massUpdate([ 358 'templates' => zbx_toObject($_REQUEST['templateid'], 'templateid'), 359 'hosts' => [] 360 ]); 361 if ($result) { 362 $result = API::Template()->delete([getRequest('templateid')]); 363 } 364 365 $result = DBend($result); 366 367 if ($result) { 368 unset($_REQUEST['form'], $_REQUEST['templateid']); 369 uncheckTableRows(); 370 } 371 unset($_REQUEST['delete']); 372 show_messages($result, _('Template deleted'), _('Cannot delete template')); 373} 374elseif (isset($_REQUEST['delete_and_clear']) && isset($_REQUEST['templateid'])) { 375 DBstart(); 376 377 $result = API::Template()->delete([getRequest('templateid')]); 378 379 $result = DBend($result); 380 381 if ($result) { 382 unset($_REQUEST['form'], $_REQUEST['templateid']); 383 uncheckTableRows(); 384 } 385 unset($_REQUEST['delete']); 386 show_messages($result, _('Template deleted'), _('Cannot delete template')); 387} 388elseif (hasRequest('action') && str_in_array(getRequest('action'), ['template.massdelete', 'template.massdeleteclear']) && hasRequest('templates')) { 389 $templates = getRequest('templates'); 390 391 DBstart(); 392 393 $result = true; 394 395 if (getRequest('action') === 'template.massdelete') { 396 $result = API::Template()->massUpdate([ 397 'templates' => zbx_toObject($templates, 'templateid'), 398 'hosts' => [] 399 ]); 400 } 401 402 if ($result) { 403 $result = API::Template()->delete($templates); 404 } 405 406 $result = DBend($result); 407 408 if ($result) { 409 uncheckTableRows(); 410 } 411 show_messages($result, _('Template deleted'), _('Cannot delete template')); 412} 413 414/* 415 * Display 416 */ 417$templateWidget = (new CWidget())->setTitle(_('Templates')); 418 419$pageFilter = new CPageFilter([ 420 'config' => [ 421 'individual' => 1 422 ], 423 'groups' => [ 424 'templated_hosts' => true, 425 'editable' => true 426 ], 427 'groupid' => getRequest('groupid') 428]); 429$_REQUEST['groupid'] = $pageFilter->groupid; 430 431if (hasRequest('form')) { 432 433 if ($templateId = getRequest('templateid', 0)) { 434 $templateWidget->addItem(get_header_host_table('', $templateId)); 435 } 436 437 $data = [ 438 'form' => getRequest('form'), 439 'groupId' => getRequest('groupid', 0), 440 'groupIds' => getRequest('groups', []), 441 'show_inherited_macros' => getRequest('show_inherited_macros', 0) 442 ]; 443 444 if ($templateId) { 445 $dbTemplates = API::Template()->get([ 446 'templateids' => $templateId, 447 'selectGroups' => API_OUTPUT_EXTEND, 448 'selectParentTemplates' => ['templateid', 'name'], 449 'selectMacros' => API_OUTPUT_EXTEND, 450 'output' => API_OUTPUT_EXTEND 451 ]); 452 $data['dbTemplate'] = reset($dbTemplates); 453 454 $data['original_templates'] = []; 455 foreach ($data['dbTemplate']['parentTemplates'] as $parentTemplate) { 456 $data['original_templates'][$parentTemplate['templateid']] = $parentTemplate['templateid']; 457 } 458 } 459 else { 460 $data['original_templates'] = []; 461 } 462 463 // description 464 $data['description'] = ($templateId && !hasRequest('form_refresh')) 465 ? $data['dbTemplate']['description'] 466 : getRequest('description'); 467 468 $templateids = getRequest('templates', hasRequest('form_refresh') ? [] : $data['original_templates']); 469 470 // Get linked templates. 471 $data['linkedTemplates'] = API::Template()->get([ 472 'output' => ['templateid', 'name'], 473 'templateids' => $templateids, 474 'preservekeys' => true 475 ]); 476 477 $data['writable_templates'] = API::Template()->get([ 478 'output' => ['templateid'], 479 'templateids' => $templateids, 480 'editable' => true, 481 'preservekeys' => true 482 ]); 483 484 CArrayHelper::sort($data['linkedTemplates'], ['name']); 485 486 // Get user allowed host groups and sort them by name. 487 $data['groupsAllowed'] = API::HostGroup()->get([ 488 'output' => ['groupid', 'name'], 489 'editable' => true, 490 'preservekeys' => true 491 ]); 492 CArrayHelper::sort($data['groupsAllowed'], ['name']); 493 494 // Get other host groups that user has also read permissions and sort by name. 495 $data['groupsAll'] = API::HostGroup()->get([ 496 'output' => ['groupid', 'name'], 497 'preservekeys' => true 498 ]); 499 CArrayHelper::sort($data['groupsAll'], ['name']); 500 501 // "Other | group" tweenbox selector for hosts and templates 502 $data['twb_groupid'] = getRequest('twb_groupid', 0); 503 if ($data['twb_groupid'] == 0) { 504 $group = reset($data['groupsAllowed']); 505 $data['twb_groupid'] = $group['groupid']; 506 } 507 508 // Get allowed hosts from selected twb_groupid combobox. 509 $data['hostsAllowedToAdd'] = API::Host()->get([ 510 'output' => ['hostid', 'name'], 511 'groupids' => $data['twb_groupid'], 512 'templated_hosts' => true, 513 'editable' => true, 514 'preservekeys' => true, 515 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL] 516 ]); 517 CArrayHelper::sort($data['hostsAllowedToAdd'], ['name']); 518 519 if ($templateId != 0 && !hasRequest('form_refresh')) { 520 $data['groupIds'] = zbx_objectValues($data['dbTemplate']['groups'], 'groupid'); 521 522 // Get template hosts from DB. 523 $hostIdsLinkedTo = API::Host()->get([ 524 'output' => ['hostid'], 525 'templateids' => $templateId, 526 'templated_hosts' => true, 527 'preservekeys' => true 528 ]); 529 $hostIdsLinkedTo = array_keys($hostIdsLinkedTo); 530 } 531 else { 532 if (!hasRequest('form_refresh') && $data['groupId'] != 0 && !$data['groupIds']) { 533 $data['groupIds'][] = $data['groupId']; 534 } 535 $hostIdsLinkedTo = getRequest('hosts', []); 536 } 537 538 if ($data['groupIds']) { 539 $data['groupIds'] = array_combine($data['groupIds'], $data['groupIds']); 540 } 541 542 if ($hostIdsLinkedTo) { 543 $hostIdsLinkedTo = array_combine($hostIdsLinkedTo, $hostIdsLinkedTo); 544 } 545 546 // Select allowed selected hosts. 547 $data['hostsAllowed'] = API::Host()->get([ 548 'output' => ['hostid', 'name', 'flags'], 549 'hostids' => $hostIdsLinkedTo, 550 'templated_hosts' => true, 551 'editable' => true, 552 'preservekeys' => true, 553 'filter' => ['flags' => ZBX_FLAG_DISCOVERY_NORMAL] 554 ]); 555 CArrayHelper::sort($data['hostsAllowed'], ['name']); 556 557 // Select selected hosts including read only. 558 $data['hostsAll'] = API::Host()->get([ 559 'output' => ['hostid', 'name', 'flags'], 560 'hostids' => $hostIdsLinkedTo, 561 'templated_hosts' => true 562 ]); 563 CArrayHelper::sort($data['hostsAll'], ['name']); 564 565 $data['hostIdsLinkedTo'] = $hostIdsLinkedTo; 566 $data['templateId'] = $templateId; 567 568 $templateForm = new CView('configuration.template.edit', $data); 569 $templateWidget->addItem($templateForm->render()); 570} 571else { 572 $sortField = getRequest('sort', CProfile::get('web.'.$page['file'].'.sort', 'name')); 573 $sortOrder = getRequest('sortorder', CProfile::get('web.'.$page['file'].'.sortorder', ZBX_SORT_UP)); 574 575 CProfile::update('web.'.$page['file'].'.sort', $sortField, PROFILE_TYPE_STR); 576 CProfile::update('web.'.$page['file'].'.sortorder', $sortOrder, PROFILE_TYPE_STR); 577 578 $config = select_config(); 579 580 $templateWidget->setControls((new CForm('get')) 581 ->cleanItems() 582 ->addItem((new CList()) 583 ->addItem([ 584 new CLabel(_('Group'), 'groupid'), 585 (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN), 586 $pageFilter->getGroupsCB() 587 ]) 588 ->addItem(new CSubmit('form', _('Create template'))) 589 ->addItem( 590 (new CButton('form', _('Import'))) 591 ->onClick('redirect("conf.import.php?rules_preset=template")') 592 ) 593 ) 594 ); 595 596 $form = (new CForm())->setName('templates'); 597 598 $table = (new CTableInfo()) 599 ->setHeader([ 600 (new CColHeader( 601 (new CCheckBox('all_templates'))->onClick("checkAll('".$form->getName()."', 'all_templates', 'templates');") 602 ))->addClass(ZBX_STYLE_CELL_WIDTH), 603 make_sorting_header(_('Templates'), 'name', $sortField, $sortOrder), 604 _('Applications'), 605 _('Items'), 606 _('Triggers'), 607 _('Graphs'), 608 _('Screens'), 609 _('Discovery'), 610 _('Web'), 611 _('Linked templates'), 612 _('Linked to') 613 ]); 614 615 // get templates 616 $templates = []; 617 618 if ($pageFilter->groupsSelected) { 619 $templates = API::Template()->get([ 620 'output' => ['templateid', $sortField], 621 'groupids' => ($pageFilter->groupid > 0) ? $pageFilter->groupid : null, 622 'editable' => true, 623 'sortfield' => $sortField, 624 'limit' => $config['search_limit'] + 1 625 ]); 626 } 627 628 // sorting && paging 629 order_result($templates, $sortField, $sortOrder); 630 631 $url = (new CUrl('templates.php')) 632 ->setArgument('groupid', getRequest('groupid', 0)); 633 634 $paging = getPagingLine($templates, $sortOrder, $url); 635 636 $templates = API::Template()->get([ 637 'templateids' => zbx_objectValues($templates, 'templateid'), 638 'editable' => true, 639 'output' => ['name', 'proxy_hostid'], 640 'selectHosts' => ['hostid', 'name', 'status'], 641 'selectTemplates' => ['templateid', 'name', 'status'], 642 'selectParentTemplates' => ['templateid', 'name', 'status'], 643 'selectItems' => API_OUTPUT_COUNT, 644 'selectTriggers' => API_OUTPUT_COUNT, 645 'selectGraphs' => API_OUTPUT_COUNT, 646 'selectApplications' => API_OUTPUT_COUNT, 647 'selectDiscoveries' => API_OUTPUT_COUNT, 648 'selectScreens' => API_OUTPUT_COUNT, 649 'selectHttpTests' => API_OUTPUT_COUNT, 650 'nopermissions' => true 651 ]); 652 653 order_result($templates, $sortField, $sortOrder); 654 655 // Select writable template IDs. 656 $linked_templateids = []; 657 $writable_templates = []; 658 $linked_hostids = []; 659 $writable_hosts = []; 660 661 foreach ($templates as $template) { 662 $linked_templateids = array_merge($linked_templateids, 663 zbx_objectValues($template['parentTemplates'], 'templateid'), 664 zbx_objectValues($template['templates'], 'templateid') 665 ); 666 667 $linked_hostids = array_merge($linked_hostids, zbx_objectValues($template['hosts'], 'hostid')); 668 } 669 670 if ($linked_templateids) { 671 $writable_templates = API::Template()->get([ 672 'output' => ['templateid'], 673 'templateids' => array_keys(array_flip($linked_templateids)), 674 'editable' => true, 675 'preservekeys' => true 676 ]); 677 } 678 679 if ($linked_hostids) { 680 $writable_hosts = API::Host()->get([ 681 'output' => ['hostid'], 682 'hostsids' => array_keys(array_flip($linked_hostids)), 683 'editable' => true, 684 'preservekeys' => true 685 ]); 686 } 687 688 foreach ($templates as $template) { 689 $templatesOutput = []; 690 691 if ($template['proxy_hostid']) { 692 $proxy = get_host_by_hostid($template['proxy_hostid']); 693 694 $templatesOutput[] = $proxy['host'].NAME_DELIMITER; 695 } 696 697 $templatesOutput[] = new CLink($template['name'], 'templates.php?form=update&templateid='.$template['templateid'].url_param('groupid')); 698 699 $linkedTemplatesOutput = []; 700 $linkedToOutput = []; 701 702 $i = 0; 703 704 order_result($template['parentTemplates'], 'name'); 705 706 foreach ($template['parentTemplates'] as $parentTemplate) { 707 $i++; 708 709 if ($i > $config['max_in_table']) { 710 $linkedTemplatesOutput[] = ' …'; 711 712 break; 713 } 714 715 if ($linkedTemplatesOutput) { 716 $linkedTemplatesOutput[] = ', '; 717 } 718 719 if (array_key_exists($parentTemplate['templateid'], $writable_templates)) { 720 $url = 'templates.php?form=update&templateid='.$parentTemplate['templateid'].url_param('groupid'); 721 722 $linkedTemplatesOutput[] = (new CLink($parentTemplate['name'], $url)) 723 ->addClass(ZBX_STYLE_LINK_ALT) 724 ->addClass(ZBX_STYLE_GREY); 725 } 726 else { 727 $linkedTemplatesOutput[] = (new CSpan($parentTemplate['name']))->addClass(ZBX_STYLE_GREY); 728 } 729 } 730 731 $i = 0; 732 733 $linkedToObjects = array_merge($template['hosts'], $template['templates']); 734 order_result($linkedToObjects, 'name'); 735 736 foreach ($linkedToObjects as $linkedToObject) { 737 $i++; 738 739 if ($i > $config['max_in_table']) { 740 $linkedToOutput[] = ' …'; 741 742 break; 743 } 744 745 if ($linkedToOutput) { 746 $linkedToOutput[] = ', '; 747 } 748 749 if ($linkedToObject['status'] == HOST_STATUS_TEMPLATE) { 750 if (array_key_exists($linkedToObject['templateid'], $writable_templates)) { 751 $url = 'templates.php?form=update&templateid='.$linkedToObject['templateid'].url_param('groupid'); 752 $link = (new CLink($linkedToObject['name'], $url)) 753 ->addClass(ZBX_STYLE_LINK_ALT) 754 ->addClass(ZBX_STYLE_GREY); 755 } 756 else { 757 $link = (new CSpan($linkedToObject['name']))->addClass(ZBX_STYLE_GREY); 758 } 759 } 760 else { 761 if (array_key_exists($linkedToObject['hostid'], $writable_hosts)) { 762 $url = 'hosts.php?form=update&hostid='.$linkedToObject['hostid'].url_param('groupid'); 763 $link = (new CLink($linkedToObject['name'], $url))->addClass(ZBX_STYLE_LINK_ALT); 764 } 765 else { 766 $link = new CSpan($linkedToObject['name']); 767 } 768 769 $link->addClass($linkedToObject['status'] == HOST_STATUS_MONITORED ? ZBX_STYLE_GREEN : ZBX_STYLE_RED); 770 } 771 772 $linkedToOutput[] = $link; 773 } 774 775 $table->addRow([ 776 new CCheckBox('templates['.$template['templateid'].']', $template['templateid']), 777 (new CCol($templatesOutput))->addClass(ZBX_STYLE_NOWRAP), 778 [ 779 new CLink(_('Applications'), 'applications.php?hostid='.$template['templateid'].url_param('groupid')), 780 CViewHelper::showNum($template['applications']) 781 ], 782 [ 783 new CLink(_('Items'), 'items.php?filter_set=1&hostid='.$template['templateid'].url_param('groupid')), 784 CViewHelper::showNum($template['items']) 785 ], 786 [ 787 new CLink(_('Triggers'), 'triggers.php?hostid='.$template['templateid'].url_param('groupid')), 788 CViewHelper::showNum($template['triggers']) 789 ], 790 [ 791 new CLink(_('Graphs'), 'graphs.php?hostid='.$template['templateid'].url_param('groupid')), 792 CViewHelper::showNum($template['graphs']) 793 ], 794 [ 795 new CLink(_('Screens'), 'screenconf.php?templateid='.$template['templateid']), 796 CViewHelper::showNum($template['screens']) 797 ], 798 [ 799 new CLink(_('Discovery'), 'host_discovery.php?hostid='.$template['templateid']), 800 CViewHelper::showNum($template['discoveries']) 801 ], 802 [ 803 new CLink(_('Web'), 'httpconf.php?hostid='.$template['templateid'].url_param('groupid')), 804 CViewHelper::showNum($template['httpTests']) 805 ], 806 $linkedTemplatesOutput, 807 $linkedToOutput 808 ]); 809 } 810 811 $footer = new CActionButtonList('action', 'templates', [ 812 'template.export' => ['name' => _('Export')], 813 'template.massdelete' => ['name' => _('Delete'), 'confirm' => _('Delete selected templates?')], 814 'template.massdeleteclear' => ['name' => _('Delete and clear'), 815 'confirm' => _('Delete and clear selected templates? (Warning: all linked hosts will be cleared!)') 816 ] 817 ]); 818 819 $form->addItem([$table, $paging, $footer]); 820 $templateWidget->addItem($form); 821} 822 823$templateWidget->show(); 824 825require_once dirname(__FILE__).'/include/page_footer.php'; 826