element. * @param string $selected_tree_item_id The ID of the tree item to be selected by default. * @param int $tier The current tier level in the tree. Default is 0. * * @return void */ function grow_dropdown_tree(int $tree_id, mixed $parent = 0, string $form_name = '', string $selected_tree_item_id = '', int $tier = 0) : void { $tier++; $branches = db_fetch_assoc_prepared('SELECT gti.id, gti.title, parent FROM graph_tree_items AS gti WHERE gti.graph_tree_id = ? AND gti.host_id = 0 AND gti.local_graph_id = 0 AND parent = ? ORDER BY parent, position', [$tree_id, $parent]); if ($parent == 0) { print "'; } } /** * Generates and displays the DHTML trees * * @return void */ function grow_dhtml_trees() : void { include_once(CACTI_PATH_LIBRARY . '/data_query.php'); draw_tree_filter(); $default_tree_id = read_user_setting('default_tree_id'); if (empty($default_tree_id)) { $user = db_fetch_row_prepared('SELECT policy_trees FROM user_auth WHERE id = ?', [$_SESSION[SESS_USER_ID]]); if ($user['policy_trees'] == 1) { $default_tree_id = db_fetch_cell_prepared('SELECT graph_tree.id FROM graph_tree LEFT JOIN user_auth_perms ON user_auth_perms.item_id = graph_tree.id AND user_auth_perms.type = 2 AND user_auth_perms.user_id = ? WHERE user_auth_perms.item_id IS NULL AND graph_tree.enabled = "on" ORDER BY graph_tree.id LIMIT 1', [$_SESSION[SESS_USER_ID]]); } else { $default_tree_id = db_fetch_cell_prepared('SELECT graph_tree.id FROM graph_tree INNER JOIN user_auth_perms ON user_auth_perms.item_id = graph_tree.id AND user_auth_perms.type = 2 AND user_auth_perms.user_id = ? WHERE graph_tree.enabled = "on" ORDER BY graph_tree.id LIMIT 1', [$_SESSION[SESS_USER_ID]]); } } else { $default_tree_id = db_fetch_cell('SELECT id FROM graph_tree ORDER BY sequence LIMIT 1'); } print "
" . __('Search') . "
\n"; $dhtml_tree = create_dhtml_tree(); if (cacti_sizeof($dhtml_tree)) { print "
\n"; } ?> 0) { $nstack .= '-site-' . grv('site_id'); $nnodes[] = $nstack; if (isrv('gti')) { $nstack .= '-gts'; $nnodes[] = $nstack; } else { if (grv('host_template_id') > 0) { $nstack .= '-ht-' . grv('host_template_id'); $nnodes[] = $nstack; } if (grv('host_id') > 0) { $nstack .= '-host-' . grv('host_id'); $nnodes[] = $nstack; } } } else { $nnodes[] = $nstack; } if (isrv('hgd')) { $parts = explode(':', grv('hgd')); switch($parts[0]) { case 'gt': $nnodes[] = $nstack . '-gt-' . $parts[1]; break; case 'dq': $nnodes[] = $nstack . '-dq-' . $parts[1]; break; case 'dqi': $nnodes[] = $nstack . '-dqi-' . $parts[1] . '-' . $parts[2]; $nnodes[] = $nstack . '-dq-' . $parts[1]; break; default: break; } } while (true) { if ($linknode['parent'] > 0) { $rnodes[] = 'tbranch-' . $linknode['parent']; $linknode = db_fetch_row_prepared('SELECT * FROM graph_tree_items WHERE id = ?', [$linknode['parent']]); } else { break; } } } if (cacti_sizeof($rnodes)) { $rnodes = array_reverse($rnodes); $nodes = array_merge($nodes, $rnodes); } if (cacti_sizeof($nnodes)) { $nodes = array_merge($nodes, $nnodes); } } elseif (str_contains(grv('node'), 'tree_anchor')) { $parts = explode('-', grv('node')); $nodes[] = 'tree_anchor-' . $parts[1] . '_anchor'; } return $nodes; } else { return []; } } /** * Get the CSS class for a device based on its status. * * @param int $host_id The ID of the host device. * @return string The CSS class name corresponding to the device's status. * * @return string */ function get_device_leaf_class(int $host_id) : string { $status = db_fetch_cell_prepared('SELECT status FROM host WHERE id = ?', [$host_id]); switch($status) { case HOST_DOWN: $class = 'deviceDown'; break; case HOST_RECOVERING: $class = 'deviceRecovering'; break; case HOST_UP: $class = 'deviceUp'; break; case HOST_UNKNOWN: $class = 'deviceUnknown'; break; case HOST_ERROR: $class = 'deviceError'; break; default: $class = ''; } return $class; } /** * Draws a DHTML tree level for a given tree ID and parent node. * * @param int $tree_id The ID of the tree to draw. * @param int $parent The ID of the parent node (default is 0). * @param bool $editing Whether the tree is in editing mode (default is false). * * @return array An array of HTML strings representing the DHTML tree level. */ function draw_dhtml_tree_level(int $tree_id, int $parent = 0, bool $editing = false) : array { $dhtml_tree = []; $hierarchy = get_allowed_tree_level($tree_id, $parent, $editing); if (cacti_sizeof($hierarchy)) { $dhtml_tree[] = "\t\t\t\n"; } return $dhtml_tree; } /** * Draws a DHTML tree level for graphing. * * This function generates the HTML structure for a DHTML tree based on the given tree ID and parent node. * It includes branches for sites, hosts, and other elements, and returns the generated HTML as an array of strings. * * @param int $tree_id The ID of the tree to draw. * @param int $parent The ID of the parent node. Defaults to 0. * * @return array The generated HTML structure as an array of strings. */ function draw_dhtml_tree_level_graphing(int $tree_id, int $parent = 0) : array { include_once(CACTI_PATH_LIBRARY . '/data_query.php'); $hierarchy = get_allowed_tree_content($tree_id, $parent); $dhtml_tree = []; if (cacti_sizeof($hierarchy)) { if ($tree_id > 0) { $dhtml_tree[] = "\t\t\t\n"; } else { $dhtml_tree[] = "\n"; } } return $dhtml_tree; } /** * Creates a site branch in the DHTML tree structure. * * This function generates a hierarchical tree structure for a given site, * including its devices and graph templates. * * @param array $leaf An associative array containing site information. * * @return array An array of strings representing the DHTML tree structure. */ function create_site_branch(array $leaf) : array { global $unique_id; $unique_id++; $dhtml_tree = []; $dhtml_tree[] = "\t\t\t\t
  • ' . htmle($leaf['sitename']) . "\n"; $devices = get_allowed_site_devices($leaf['site_id'], '', 'ht.name ASC, h1.description ASC'); $ht_name = ''; if (cacti_sizeof($devices)) { $dhtml_tree[] = "\t\t\t\t\t
  • \n"; } $dhtml_tree[] = "\t\t\t\t\t\t
  • " . htmle($d['host_template_name']) . "
  • \n"; $dhtml_tree[] = "\t\t\t\t\t\n"; } // suppress total rows collection $total_rows = -1; $graph_templates = get_allowed_graph_templates('h.site_id=' . $leaf['site_id'], 'name', '', $total_rows); if (cacti_sizeof($graph_templates)) { $dhtml_tree[] = "\t\t\t\t\t\t\n"; } $dhtml_tree[] = "\t\t\t\t\n"; return $dhtml_tree; } /** * Creates a branch in the DHTML tree structure. * * This function generates a list item (`
  • `) element for a given leaf node * in the tree. It checks if the leaf node has children and assigns the appropriate * CSS class to indicate whether the node is closed or not. The function also * constructs a URL for the leaf node and escapes it for HTML output. * * @param array $leaf An associative array representing the leaf node. It should * * @return array An array containing the generated HTML for the leaf node. */ function create_branch(array $leaf) : array { $dhtml_tree = []; $children = db_fetch_cell_prepared('SELECT COUNT(*) FROM graph_tree_items WHERE parent = ? AND local_graph_id=0', [$leaf['id']]); $dhtml_tree[] = "\t\t\t\t
  • 0 ? "class='jstree-closed'" : '') . '>' . htmle($leaf['title']) . "
  • \n"; return $dhtml_tree; } /** * Creates a host branch in the DHTML tree structure. * * @param array $leaf The leaf node containing host information. * @param int $site_id The site ID associated with the host (default is -1). * @param int $ht The host template ID (default is -1). * * @return array The DHTML tree structure with the host branch added. */ function create_host_branch(array $leaf, int $site_id = -1, int $ht = -1) : array { global $unique_id; $unique_id++; if (isset($leaf['host_id']) && $leaf['host_id'] > 0) { $class = get_device_leaf_class($leaf['host_id']); } else { $class = ''; } $dhtml_tree[] = "\t\t\t\t
  • 0 ? '-site-' . $site_id : '') . ($ht > 0 ? '-ht-' . $ht : '') . '-host-' . $leaf['host_id'] . '-uid-' . $unique_id . "' data-jstree='{ \"type\" : \"device\" }'>' . htmle(strip_domain($leaf['hostname'])) . "\n"; if (read_user_setting('expand_hosts') == 'on') { if ($leaf['host_grouping_type'] == HOST_GROUPING_DATA_QUERY_INDEX) { $dhtml_tree[] = "\t\t\t\t\t\n"; } elseif ($leaf['host_grouping_type'] == HOST_GROUPING_GRAPH_TEMPLATE) { $dhtml_tree[] = "\t\t\t\t\t\n"; } else { $dhtml_tree[] = "\t\t\t\t\t\n"; $dhtml_tree[] = "\t\t\t\t\t\n"; } } $dhtml_tree[] = "\t\t\t\t
  • \n"; return $dhtml_tree; } /** * Creates a branch of graph templates for a given host in a DHTML tree structure. * * @param array $leaf An associative array containing information about the host. * @param int $site_id Optional. The ID of the site. Default is -1. * @param int $ht Optional. The ID of the host template. Default is -1. * * @return array An array of HTML list items representing the graph templates. */ function create_graph_template_branch(array $leaf, int $site_id = -1, int $ht = -1) : array { global $unique_id; $dhtml_tree = []; // suppress total rows collection $total_rows = -1; $graph_templates = get_allowed_graph_templates('gl.host_id=' . $leaf['host_id'], 'name', '', $total_rows); if (cacti_sizeof($graph_templates)) { foreach ($graph_templates as $graph_template) { $unique_id++; $dhtml_tree[] = "\t\t\t\t\t\t
  • 0 ? '-site-' . $site_id . ($ht > 0 ? '-ht-' . $ht : '') . '-host-' . $leaf['host_id'] : '') . '-gt-' . $graph_template['id'] . "-uid-$unique_id' data-jstree='{ \"type\" : \"graph_template\" }'>" . htmle($graph_template['name']) . "
  • \n"; } } return $dhtml_tree; } /** * Creates a data query branch for a given leaf and site. * * This function generates a hierarchical tree structure for data queries * associated with a specific host. It supports both query-based and non-query-based * data sources and includes options for sorting and filtering based on user settings. * * @param array $leaf The leaf node containing host information. * @param int $site_id The site ID (default is -1). * @param int $ht The host template ID (default is -1). * * @return array The generated DHTML tree structure. */ function create_data_query_branch(array $leaf, int $site_id = -1, int $ht = -1) : array { global $unique_id; $dhtml_tree = []; $data_queries = db_fetch_assoc_prepared('SELECT sq.id, sq.name FROM graph_local AS gl INNER JOIN snmp_query AS sq ON gl.snmp_query_id=sq.id AND gl.host_id = ? GROUP BY sq.id ORDER BY sq.name', [$leaf['host_id']]); array_push($data_queries, [ 'id' => '0', 'name' => __('Non Query Based') ]); if (cacti_sizeof($data_queries)) { if ($leaf['host_id'] > 0) { if (read_config_option('dsstats_enable') == 'on' && grv('graph_source') != '' && grv('graph_order') != '') { $sql_order = [ 'data_source' => grv('graph_source'), 'order' => grv('graph_order'), 'start_time' => get_current_graph_start(), 'end_time' => get_current_graph_end(), 'cf' => grv('cf'), 'measure' => grv('measure') ]; } else { $sql_order = 'gtg.title_cache'; } $ntg = get_allowed_graphs('gl.host_id=' . $leaf['host_id'] . ' AND gl.snmp_query_id=0', $sql_order); if (read_user_setting('show_aggregates', 'on') == 'on') { $agg = get_allowed_aggregate_graphs('gl.host_id=' . $leaf['host_id'] . ' AND gl.snmp_query_id=0'); } else { $agg = []; } } else { if (read_config_option('dsstats_enable') == 'on' && grv('graph_source') != '' && grv('graph_order') != '') { $sql_order = [ 'data_source' => grv('graph_source'), 'order' => grv('graph_order'), 'start_time' => get_current_graph_start(), 'end_time' => get_current_graph_end(), 'cf' => grv('cf'), 'measure' => grv('measure') ]; } else { $sql_order = 'gtg.title_cache'; } $ntg = get_allowed_graphs('gl.snmp_query_id=0', $sql_order); if (read_user_setting('show_aggregates', 'on') == 'on') { $agg = get_allowed_aggregate_graphs('gl.snmp_query_id=0'); } else { $agg = []; } } $ntg = array_merge($ntg, $agg); foreach ($data_queries as $data_query) { if ($data_query['id'] == 0) { $non_tg = $ntg; $sfd = []; } else { $non_tg = []; // fetch a list of field names that are sorted by the preferred sort field $sfd = get_formatted_data_query_indexes($leaf['host_id'], $data_query['id']); } if (($data_query['id'] == 0 && cacti_sizeof($non_tg)) || ($data_query['id'] > 0 && cacti_sizeof($sfd))) { $unique_id++; if ($data_query['name'] != __('Non Query Based')) { $dhtml_tree[] = "\t\t\t\t\t\t
  • 0 ? '-site-' . $site_id . ($ht > 0 ? '-ht-' . $ht : '') . '-host-' . $leaf['host_id'] : '') . '-dq-' . $data_query['id'] . "-uid-$unique_id' data-jstree='{ \"type\" : \"data_query\" }'>' . htmle($data_query['name']) . "\n"; } else { $dhtml_tree[] = "\t\t\t\t\t\t
  • 0 ? '-site-' . $site_id . ($ht > 0 ? '-ht-' . $ht : '') . '-host-' . $leaf['host_id'] : '') . '-dq-' . $data_query['id'] . "-uid-$unique_id' data-jstree='{ \"type\" : \"data_query\" }'>' . htmle($data_query['name']) . "\n"; } if ($data_query['id'] > 0) { $dhtml_tree[] = "\t\t\t\t\t\t\t\n"; $dhtml_tree[] = "\t\t\t\t\t\t
  • \n"; } } } } $dhtml_tree[] = "\t\t\t\t\t\t\n"; return $dhtml_tree; } /** * Creates a DHTML tree structure. * * This function generates a DHTML tree structure by retrieving a list of allowed trees * and marking each tree as true in the resulting array. * * @return array An associative array where the keys are tree identifiers prefixed with 'tree:' * and the values are set to true. */ function create_dhtml_tree() : array { $dhtml_tree = []; $tree_list = get_allowed_trees(); if (cacti_sizeof($tree_list)) { foreach ($tree_list as $tree) { $dhtml_tree['tree:' . $tree['id']] = true; } } return $dhtml_tree; } function create_tree_filter() : array { global $item_rows; $all = ['-1' => __('All')]; $any = ['-1' => __('Any')]; $none = ['0' => __('None')]; // unset the ordering if we have a setup that does not support ordering if (isrv('graph_template_id')) { if (str_contains(gnrv('graph_template_id'), ',') || gnrv('graph_template_id') <= 0) { srv('graph_order', ''); srv('graph_source', ''); } } if (gfrv('host_id') == 0) { $templates = get_allowed_graph_templates_normalized('gl.host_id=0', 'name', '', $total_rows); } elseif (gfrv('host_id') > 0) { $templates = get_allowed_graph_templates_normalized('gl.host_id=' . gfrv('host_id'), 'name', '', $total_rows); } elseif (gfrv('host_template_id') > 0) { // Site Branch drilled into by Device Template: limit the Graph Templates to // those present on that Device Template's devices (within the Site when set) $device_where = 'host_template_id=' . gfrv('host_template_id'); if (gfrv('site_id') > 0) { $device_where .= ' AND site_id=' . gfrv('site_id'); } $templates = get_allowed_graph_templates_normalized('gl.host_id IN (SELECT id FROM host WHERE ' . $device_where . ')', 'name', '', $total_rows); } else { $templates = get_allowed_graph_templates_normalized('', 'name', '', $total_rows); } $normalized_templates = []; if (cacti_sizeof($templates)) { foreach ($templates as $t) { $normalized_templates[$t['id']] = $t['name']; } } $columns = [ '1' => __('%d Column', 1), '2' => __('%d Columns', 2), '3' => __('%d Columns', 3), '4' => __('%d Columns', 4), '5' => __('%d Columns', 5), '6' => __('%d Columns', 6) ]; $normalized_templates = $all + $none + $normalized_templates; $metrics_array = html_graph_order_filter_array(); if (isrv('business_hours')) { $business_hours = gnrv('business_hours'); } else { $business_hours = read_user_setting('show_business_hours') == 'on' ? 'true' : 'false'; } if (isrv('thumbnails')) { $thumbnails = gnrv('thumbnails'); } else { $thumbnails = read_user_setting('thumbnail_section_tree') == 'on' ? 'true' : 'false'; } $filters = [ 'rows' => [ [ 'rfilter' => [ 'method' => 'textbox', 'friendly_name' => __('Search'), 'filter' => FILTER_VALIDATE_IS_REGEX, 'placeholder' => __('Enter a search term'), 'size' => '55', 'default' => '', 'pageset' => true, 'max_length' => '120', 'value' => '' ] ], [ 'graph_template_id' => [ 'method' => 'drop_multi', 'bar' => true, 'friendly_name' => __('Template'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)(,(cg_[0-9]+|dq_[0-9]+|-?[0-9]+))*$/']], 'default' => '-1', 'dynamic' => false, 'class' => 'select2-multi-count', 'select_all_text' => __('All Graph Templates'), 'select_count_text' => __('Templates Selected'), 'select_all_value' => '-1', 'pageset' => true, 'array' => $normalized_templates, 'value' => gnrv('graph_template_id') ], ], [ 'graphs' => [ 'method' => 'drop_array', 'friendly_name' => __('Graphs'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'pageset' => true, 'array' => $item_rows, 'value' => '' ], 'columns' => [ 'method' => 'drop_array', 'friendly_name' => __('Columns'), 'filter' => FILTER_VALIDATE_INT, 'default' => read_user_setting('num_columns_tree', '2'), 'pageset' => true, 'array' => $columns, 'value' => read_user_setting('num_columns_tree', '2') ], 'thumbnails' => [ 'method' => 'filter_checkbox', 'friendly_name' => __('Thumbnails'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(true|false)$/']], 'default' => read_user_setting('thumbnail_section_tree') == 'on' ? 'true' : 'false', 'value' => $thumbnails ], 'business_hours' => [ 'method' => 'filter_checkbox', 'friendly_name' => __('Business Hours'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(true|false)$/']], 'default' => read_user_setting('show_business_hours') == 'on' ? 'true' : 'false', 'value' => $business_hours ] ], [ 'timespan' => [ 'method' => 'timespan', 'refresh' => true, 'clear' => true, 'shifter' => true, ], 'node' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/([_\-a-z:0-9#]+)/']], 'pageset' => true, 'default' => '' ], 'site_id' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_INT, 'default' => '-1' ], 'host_id' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_INT, 'default' => '-1' ], 'host_template_id' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_INT, 'default' => '-1' ], 'hgd' => [ 'method' => 'validate', 'filter' => FILTER_CALLBACK, 'filter_options' => ['options' => 'sanitize_search_string'], 'pageset' => true, 'default' => '', ], ] ], 'buttons' => [ 'go' => [ 'method' => 'submit', 'display' => __('Go'), 'title' => __('Apply filter to table'), 'callback' => 'applyGraphFilter()' ], 'clear' => [ 'method' => 'button', 'display' => __('Clear'), 'title' => __('Reset filter to default values'), 'callback' => 'clearGraphFilter()' ] ] ]; if (cacti_sizeof($metrics_array)) { $filters['rows'][1] += $metrics_array; } if (is_view_allowed('graph_settings')) { $filters['buttons']['save'] = [ 'method' => 'button', 'display' => __('Save'), 'title' => __('Save filter to the database'), 'callback' => 'saveGraphFilter("treeview")' ]; } return $filters; } function draw_tree_filter(bool $render = false) : void { $header = __('Graph Tree Filters') . (gnrv('rfilter') != '' ? ' [ ' . __('Filter') . " '" . htmlerv('rfilter') . "' " . __('Applied') . ' ]' : ''); // create the page filter $filters = create_tree_filter(); $pageFilter = new CactiTableFilter($header, 'graph_view.php', 'form_graph_view', 'sess_tview', '', false, false); $pageFilter->rows_label = __('Graphs'); $pageFilter->set_filter_array($filters); $pageFilter->inject_content = inject_realtime_form(); if ($render) { $pageFilter->render(); } else { $pageFilter->sanitize(); } } /** * Generates the right pane tree structure for the given tree and leaf IDs. * * This function constructs the right pane tree structure for a given tree and leaf ID, * including various filters and options for graph templates, host templates, sites, and more. * It also handles the display of graph filters, timespan selectors, and other UI elements. * * @param int $tree_id The ID of the tree to generate the right pane for. * @param int $leaf_id The ID of the leaf to generate the right pane for. * @param string $host_group_data The host group data string, which can include graph template IDs, data query IDs, and data query indexes. * * @return void */ function grow_right_pane_tree(int $tree_id, int $leaf_id, string $host_group_data) : void { global $current_user, $graphs_per_page, $graph_timeshifts; include(CACTI_PATH_INCLUDE . '/global_arrays.php'); include_once(CACTI_PATH_LIBRARY . '/data_query.php'); include_once(CACTI_PATH_LIBRARY . '/html_utility.php'); if (empty($tree_id)) { return; } draw_tree_filter(true); if (empty($leaf_id)) { $leaf_id = 0; } $sql_where = ''; $sql_join = ''; $title = ''; $host_name = ''; $site_name = ''; $host_template_name = ''; $title_delimiter = ''; $host_group_data_name = ''; $graph_template_id = '-1'; $data_query_id = '-1'; $data_query_index = ''; $leaf_names = []; $leaf = db_fetch_row_prepared('SELECT title, host_id, site_id, host_grouping_type, parent FROM graph_tree_items WHERE id = ?', [$leaf_id]); $leaf_type = api_tree_get_item_type($leaf_id); // get information for the headers $tree_name = db_fetch_cell_prepared('SELECT name FROM graph_tree WHERE id = ?', [$tree_id]); if (isset($leaf['title']) && $leaf['title'] != '') { $leaf_names[] = $leaf['title']; } if (($leaf_type == 'site' || $leaf_type == 'host') && $leaf['parent'] != 0) { $parent = $leaf['parent']; $leaf_names = []; while ($parent != 0) { $pleaf = db_fetch_row_prepared('SELECT * FROM graph_tree_items WHERE id = ?', [$parent]); if (cacti_sizeof($pleaf)) { $leaf_names[] = $pleaf['title']; $parent = $pleaf['parent']; } else { break; } } } if (!empty($leaf_id)) { $host_name = db_fetch_cell_prepared('SELECT description FROM host WHERE id = ?', [$leaf['host_id']]); $site_name = db_fetch_cell_prepared('SELECT name FROM sites WHERE id = ?', [$leaf['site_id']]); } if (isrv('host_id') && gfrv('host_id') > 0 && $host_name == '') { $host_name = db_fetch_cell_prepared('SELECT description FROM host WHERE id = ?', [grv('host_id')]); } if (isrv('site_id') && gfrv('site_id') > 0 && $site_name == '') { $site_name = db_fetch_cell_prepared('SELECT name FROM sites WHERE id = ?', [grv('site_id')]); } if (isrv('host_template_id') && gfrv('host_template_id') > 0) { $host_template_name = db_fetch_cell_prepared('SELECT name FROM host_template WHERE id = ?', [grv('host_template_id')]); } $host_group_data_array = explode(':', $host_group_data); if ($host_group_data_array[0] == 'gt') { $name = db_fetch_cell_prepared('SELECT name FROM graph_templates WHERE id = ?', [$host_group_data_array[1]]); $host_group_data_name = '' . __('Graph Template:') . ' ' . htmle($name); $graph_template_id = $host_group_data_array[1]; } elseif ($host_group_data_array[0] == 'dq') { $name = db_fetch_cell_prepared('SELECT name FROM snmp_query WHERE id = ?', [$host_group_data_array[1]]); $host_group_data_name = '' . __('Graph Template:') . ' ' . (empty($host_group_data_array[1]) ? __('Non Query Based') : htmle($name)); $data_query_id = intval($host_group_data_array[1]); } elseif ($host_group_data_array[0] == 'dqi') { $name = db_fetch_cell_prepared('SELECT name FROM snmp_query WHERE id = ?', [$host_group_data_array[1]]); $host_group_data_name = '' . __('Graph Template:') . ' ' . (empty($host_group_data_array[1]) ? __('Non Query Based') : htmle($name)) . '-> ' . (empty($host_group_data_array[2]) ? __('Template Based') : htmle(get_formatted_data_query_index($leaf['host_id'], intval($host_group_data_array[1]), $host_group_data_array[2]))); $data_query_id = intval($host_group_data_array[1]); $data_query_index = $host_group_data_array[2]; } if ($tree_name != '') { $title .= $title_delimiter . '' . __('Tree:') . ' ' . htmle($tree_name); $title_delimiter = ' > '; } if ($site_name != '') { $title .= $title_delimiter . '' . __('Site:') . ' ' . htmle($site_name); $title_delimiter = ' > '; } if (cacti_sizeof($leaf_names)) { foreach ($leaf_names as $leaf_name) { $title .= $title_delimiter . '' . __('Leaf:') . ' ' . htmle($leaf_name); $title_delimiter = ' > '; } } if ($host_template_name != '') { $title .= $title_delimiter . '' . __('Device Template:') . ' ' . htmle($host_template_name); $title_delimiter = ' > '; } if ($host_name != '') { $title .= $title_delimiter . '' . __('Device:') . ' ' . htmle($host_name); $title_delimiter = ' > '; } if ($host_group_data_name != '') { $title .= $title_delimiter . ' ' . $host_group_data_name; $title_delimiter = ' > '; } if (grv('graphs') == '-1') { $graph_rows = read_user_setting('treeview_graphs_per_page', read_config_option('treeview_graphs_per_page') ?? 10); } else { $graph_rows = grv('graphs'); } ?> $tree_id, 'leafid' => $leaf_id, 'mode' => 'tree', 'timespan' => $_SESSION['sess_current_timespan'], 'starttime' => get_current_graph_start(), 'endtime' => get_current_graph_end() ] ); $graph_list = []; if (($leaf_type == 'header') || (empty($leaf_id))) { $sql_where = ''; if (grv('rfilter') != '') { $sql_where .= ' (gtg.title_cache RLIKE ' . db_qstr(grv('rfilter')) . ' OR gtg.title RLIKE ' . db_qstr(grv('rfilter')) . ')'; } if (isrv('graph_template_id') && grv('graph_template_id') != '' && grv('graph_template_id') != -1) { $graph_templates = html_transform_graph_template_ids(grv('graph_template_id')); $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' ' . db_in_clause('gl.graph_template_id', $graph_templates); } $graph_list = get_allowed_tree_header_graphs($tree_id, $leaf_id, $sql_where); } elseif ($leaf_type == 'host') { if ($graph_template_id == '-1') { $graph_template_id = grv('graph_template_id'); } $graph_list = get_host_graph_list($leaf['host_id'], $graph_template_id, $data_query_id, $leaf['host_grouping_type'], $data_query_index); } elseif ($leaf_type == 'site') { $sql_where = ''; if (isrv('site_id') && gfrv('site_id') > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'h.site_id = ' . grv('site_id'); } if (isrv('host_template_id') && gfrv('host_template_id') > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'h.host_template_id = ' . grv('host_template_id'); } if (isrv('host_id') && gfrv('host_id') > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.host_id = ' . grv('host_id'); } if (isrv('hgd')) { $parts = explode(':', grv('hgd')); switch($parts[0]) { case 'gt': input_validate_input_number($parts[1], 'hgd-gt'); $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.graph_template_id = ' . $parts[1]; break; case 'dq': input_validate_input_number($parts[1], 'hgd-dq'); $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.snmp_query_id = ' . $parts[1]; break; case 'dqi': input_validate_input_number($parts[1], 'hgd-dqi'); $dqi = db_qstr($parts[2]); $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.snmp_query_id = ' . $parts[1] . ' AND snmp_index = ' . $dqi; break; default: break; } } if (grv('rfilter') != '') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . '(gtg.title_cache RLIKE ' . db_qstr(grv('rfilter')) . ')'; } if (isrv('graph_template_id') && grv('graph_template_id') != '') { $graph_templates = html_transform_graph_template_ids(grv('graph_template_id')); $sql_where .= ($sql_where != '' ? ' AND ' : '') . db_in_clause('gl.graph_template_id', $graph_templates); } if (read_config_option('dsstats_enable') == 'on' && grv('graph_source') != '' && grv('graph_order') != '') { $sql_order = [ 'data_source' => grv('graph_source'), 'order' => grv('graph_order'), 'start_time' => get_current_graph_start(), 'end_time' => get_current_graph_end(), 'cf' => grv('cf'), 'measure' => grv('measure') ]; } else { $sql_order = 'gtg.title_cache'; } $graphs = get_allowed_graphs($sql_where, $sql_order); if (read_user_setting('show_aggregates', 'on') == 'on') { $agg = get_allowed_aggregate_graphs($sql_where); } else { $agg = []; } $graphs = array_merge($graphs, $agg); // let's sort the graphs naturally usort($graphs, 'naturally_sort_graphs'); if (cacti_sizeof($graphs)) { foreach ($graphs as $graph) { array_push($graph_list, $graph); } } } $total_rows = cacti_sizeof($graph_list); // generate page list $nav = html_nav_bar(CACTI_PATH_URL . 'graph_view.php?action=tree_content&tree_id=' . $tree_id . '&leaf_id=' . $leaf_id . '&node=' . grv('node') . '&hgd=' . $host_group_data, MAX_DISPLAY_PAGES, grv('page'), $graph_rows, $total_rows, grv('columns'), __('Graphs'), 'page', 'main'); print $nav; html_start_box('', '100%', false, 3, 'center', ''); // start graph display print "
    $title
    "; $i = $graph_rows * (grv('page') - 1); $last_graph = $i + $graph_rows; $new_graph_list = []; while ($i < $total_rows && $i < $last_graph) { $new_graph_list[] = $graph_list[$i]; $i++; } if (grv('thumbnails') == 'true' || grv('thumbnails') == 'on') { html_graph_thumbnail_area($new_graph_list, '', 'view_type=tree&graph_start=' . get_current_graph_start() . '&graph_end=' . get_current_graph_end(), '', grv('columns'), $tree_id, $leaf_id); } else { html_graph_area($new_graph_list, '', 'view_type=tree&graph_start=' . get_current_graph_start() . '&graph_end=' . get_current_graph_end(), '', grv('columns'), $tree_id, $leaf_id); } if (!empty($leaf_id)) { api_plugin_hook_function('tree_after', $host_name . ',' . gnrv('leaf_id')); } api_plugin_hook_function('tree_view_page_end'); html_end_box(false, true); if ($total_rows) { print $nav; } } /** * Retrieves a list of graphs for a given host, graph template, and data query. * * @param int $host_id The ID of the host. * @param string $graph_template_id The ID(s) of the graph template(s). * @param int $data_query_id The ID of the data query. * @param string $host_grouping_type The type of host grouping (optional). * @param string $data_query_index The index of the data query (optional). * * @return array An array of graphs for the specified host, graph template, and data query. */ function get_host_graph_list(int $host_id, string $graph_template_id, int $data_query_id, string $host_grouping_type = '', string $data_query_index = '') : array { $graph_list = []; $sql_where = ''; // graph template grouping if ($host_grouping_type == HOST_GROUPING_GRAPH_TEMPLATE) { if ($host_id > 0) { $sql_where = 'gl.host_id=' . $host_id; } $graph_template_id = html_transform_graph_template_ids($graph_template_id); if ($graph_template_id != '' && $graph_template_id != '-1' && $graph_template_id != '0') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' (gl.graph_template_id IN (' . $graph_template_id . '))'; } elseif ($graph_template_id == 0) { $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' (gl.graph_template_id IN (' . $graph_template_id . '))'; } // suppress total rows collection $total_rows = -1; $graph_templates = get_allowed_graph_templates($sql_where, 'name', '', $total_rows); $final_templates = []; if ($graph_template_id != '' && $graph_template_id != '-1' && $graph_template_id != '0') { $templates = explode(',', $graph_template_id); foreach ($templates as $id) { $ptemplates[$id]['id'] = $id; } foreach ($graph_templates as $template) { if (isset($ptemplates[$template['id']])) { $final_templates[$template['id']]['id'] = $template['id']; $final_templates[$template['id']]['name'] = $template['name']; } } } elseif ($graph_template_id == '0') { $final_templates = []; } else { $final_templates = $graph_templates; } // for graphs without a template array_push( $final_templates, [ 'id' => '0', 'name' => __('(Non Graph Template)') ] ); if (cacti_sizeof($final_templates)) { $sql_where = ''; if (grv('rfilter') != '') { $sql_where .= ' (gtg.title_cache RLIKE ' . db_qstr(grv('rfilter')) . ')'; } if ($host_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.host_id = ' . $host_id; } $graph_template_ids = []; foreach ($final_templates as $graph_template) { array_push($graph_template_ids, $graph_template['id']); } $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.graph_template_id IN (' . implode(', ', $graph_template_ids) . ')'; if (grv('graph_source') != '-1' && read_config_option('dsstats_enable') == 'on' && grv('graph_source') != '' && grv('graph_order') != '') { $sql_order = [ 'data_source' => grv('graph_source'), 'order' => grv('graph_order'), 'start_time' => get_current_graph_start(), 'end_time' => get_current_graph_end(), 'cf' => grv('cf'), 'measure' => grv('measure') ]; } else { $sql_order = 'gtg.title_cache'; } $graphs = get_allowed_graphs($sql_where, $sql_order); if (read_user_setting('show_aggregates', 'on') == 'on') { $agg = get_allowed_aggregate_graphs($sql_where); } else { $agg = []; } $graphs = array_merge($graphs, $agg); // let's sort the graphs naturally usort($graphs, 'naturally_sort_graphs'); if (cacti_sizeof($graphs)) { foreach ($graphs as $graph) { $graph['graph_template_name'] = $graph_template['name']; array_push($graph_list, $graph); } } } } elseif ($host_grouping_type == HOST_GROUPING_DATA_QUERY_INDEX) { // data query index grouping if ($host_id > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'gl.host_id=' . $host_id; } if ($data_query_id >= 0) { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'sq.id=' . $data_query_id; } $data_queries = db_fetch_assoc("SELECT sq.id, sq.name FROM graph_local AS gl INNER JOIN snmp_query AS sq ON gl.snmp_query_id=sq.id $sql_where GROUP BY sq.id ORDER BY sq.name"); // for graphs without a data query if ($data_query_id <= 0) { array_push($data_queries, [ 'id' => '0', 'name' => __('Non Query Based') ] ); } if (cacti_sizeof($data_queries)) { foreach ($data_queries as $data_query) { $sql_where = ''; // fetch a list of field names that are sorted by the preferred sort field $sfd = get_formatted_data_query_indexes($host_id, $data_query['id']); if (grv('rfilter') != '') { $sql_where = ' (gtg.title_cache RLIKE ' . db_qstr(grv('rfilter')) . ')'; } // grab a list of all graphs for this host/data query combination $sql_where .= ($sql_where != '' ? ' AND ' : '') . 'gl.snmp_query_id=' . $data_query['id'] . ($host_id > 0 ? ' AND gl.host_id=' . $host_id : '') . ' ' . ($data_query_index != '' ? ' AND gl.snmp_index = ' . db_qstr($data_query_index) : ''); if (read_config_option('dsstats_enable') == 'on' && grv('graph_source') != '' && grv('graph_order') != '') { $sql_order = [ 'data_source' => grv('graph_source'), 'order' => grv('graph_order'), 'start_time' => get_current_graph_start(), 'end_time' => get_current_graph_end(), 'cf' => grv('cf'), 'measure' => grv('measure') ]; } else { $sql_order = 'gtg.title_cache'; } $graphs = get_allowed_graphs($sql_where, $sql_order); if (read_user_setting('show_aggregates', 'on') == 'on') { $agg = get_allowed_aggregate_graphs($sql_where); } else { $agg = []; } $graphs = array_merge($graphs, $agg); // re-key the results on data query index $snmp_index_to_graph = []; if (cacti_sizeof($graphs)) { // let's sort the graphs naturally usort($graphs, 'naturally_sort_graphs'); foreach ($graphs as $graph) { $snmp_index_to_graph[$graph['snmp_index']][$graph['local_graph_id']] = $graph['title_cache']; $graphs_height[$graph['local_graph_id']] = $graph['height']; $graphs_width[$graph['local_graph_id']] = $graph['width']; } } // using the sorted data as they key; grab each snmp index from the master list foreach ($sfd as $snmp_index => $sort_field_value) { // render each graph for the current data query index if (isset($snmp_index_to_graph[$snmp_index])) { foreach ($snmp_index_to_graph[$snmp_index] as $local_graph_id => $graph_title) { // reformat the array so it's compatible with the html_graph* area functions array_push($graph_list, [ 'data_query_name' => $data_query['name'], 'sort_field_value' => $sort_field_value, 'local_graph_id' => $local_graph_id, 'title_cache' => $graph_title, 'height' => $graphs_height[$local_graph_id] ?? intval(read_config_option('default_graph_height')), 'width' => $graphs_width[$local_graph_id] ?? intval(read_config_option('default_graph_width')) ]); } } } } } } return $graph_list; } /** * Retrieves a list of tree branches that match a search string and returns * them as a JSON object to the page for filtering the tree list by matching * branch object. * * @return void */ function get_matching_nodes() : void { $my_matches = []; $match = []; $filter = '%' . gnrv('str') . '%'; if (gnrv('str') != '') { $matching = db_fetch_assoc_prepared('SELECT gti.parent, gti.graph_tree_id FROM graph_tree_items AS gti LEFT JOIN host AS h ON h.id = gti.host_id LEFT JOIN ( SELECT DISTINCT site_id FROM host WHERE description LIKE ? OR hostname LIKE ? ) AS h2 ON h2.site_id = gti.site_id LEFT JOIN ( SELECT local_graph_id FROM graph_templates_graph WHERE local_graph_id > 0 AND title_cache LIKE ? ) AS gtg ON gtg.local_graph_id = gti.local_graph_id LEFT JOIN ( SELECT id FROM sites WHERE name LIKE ? ) AS site ON site.id = gti.site_id WHERE (gti.title LIKE ?) OR (h.description LIKE ? AND (gti.host_id > 0 OR gti.site_id > 0)) OR (h.hostname LIKE ? AND (gti.host_id > 0 OR gti.site_id > 0)) OR (h2.site_id > 0) OR (gtg.local_graph_id > 0) OR (site.id > 0)', [$filter, $filter, $filter, $filter, $filter, $filter, $filter]); } else { $matching = db_fetch_assoc('SELECT parent, graph_tree_id FROM graph_tree_items'); } if (cacti_sizeof($matching)) { foreach ($matching as $row) { while ($row['parent'] != '0') { $match[] = 'tbranch-' . $row['parent']; $row = db_fetch_row_prepared('SELECT parent, graph_tree_id FROM graph_tree_items WHERE id = ?', [$row['parent']]); if (!cacti_sizeof($row)) { break; } } if (cacti_sizeof($row)) { $match[] = 'tree_anchor-' . $row['graph_tree_id']; $my_matches[] = array_reverse($match); $match = []; } } // Now flatten the list of nodes $final_array = []; $level = 0; while (true) { $found = 0; foreach ($my_matches as $match) { if (isset($match[$level])) { if ($level == 0) { $final_array[$match[$level]][$match[$level]] = 1; } else { $final_array[$match[0]][$match[$level]] = 1; } $found++; } } $level++; if ($found == 0) { break; } } $fa = []; if (cacti_sizeof($final_array)) { foreach ($final_array as $matches) { foreach ($matches as $branch => $dnc) { $fa[] = $branch; } } } header('Content-Type: application/json; charset=utf-8'); print json_encode($fa); } } function html_tree_init() : void { draw_tree_filter(); if (isrv('tree_id')) { $_SESSION['sess_tree_id'] = gfrv('tree_id'); } top_graph_header(); ?> 0) { $ndata = explode('-', gnrv('id')); $tree_id = $ndata[1]; input_validate_input_number($tree_id, 'tree_id'); } } else { $tree_id = read_user_setting('default_tree_id'); } if (isrv('id') && gnrv('id') != '#') { if (substr_count(gnrv('id'), 'tree_anchor')) { $parent = -1; } else { $ndata = explode('_', gnrv('id')); foreach ($ndata as $node) { $pnode = explode('-', $node); if ($pnode[0] == 'tbranch') { $parent = $pnode[1]; input_validate_input_number($parent, 'parent'); $tree_id = db_fetch_cell_prepared('SELECT graph_tree_id FROM graph_tree_items WHERE id = ?', [$parent]); break; } } } } api_tree_get_main($tree_id, $parent); } function html_tree_get_content() : void { draw_tree_filter(); top_graph_header(); if (!is_view_allowed('show_tree')) { header('Location: permission_denied.php'); exit; } if (!ierv('node')) { $_SESSION['sess_graph_node'] = sanitize_search_string(gnrv('node')); if (!ierv('hgd')) { $_SESSION['sess_graph_hgd'] = sanitize_search_string(gnrv('hgd')); } else { $_SESSION['sess_graph_hgd'] = ''; } } elseif (isset($_SESSION['sess_graph_node'])) { srv('node', $_SESSION['sess_graph_node']); srv('hgd', $_SESSION['sess_graph_hgd']); } ?> 0) { if (!is_tree_allowed($tree_id)) { header('Location: permission_denied.php'); exit; } grow_right_pane_tree($tree_id, $node_id, $hgdata); } bottom_footer(); }