__('Delete'), 5 => __('Convert to Normal Graph'), 4 => __('Place Graphs on Report'), 2 => __('Migrate Aggregate to use a Template'), 3 => __('Create New Aggregate from Aggregates') ]; $agg_item_actions = [ 10 => __('Associate with Aggregate'), 11 => __('Disassociate with Aggregate') ]; // set default action set_default_action(); switch (grv('action')) { case 'save': form_save(); break; case 'actions': form_actions(); break; case 'edit': top_header(); graph_edit(); bottom_footer(); break; case 'item_remove': item_remove(); header('Location: aggregate_graphs.php?action=edit&id=' . gfrv('local_graph_id')); break; case 'item_edit': top_header(); item_edit(); bottom_footer(); break; case 'item_movedown': item_movedown(); header('Location: aggregate_graphs.php?action=edit&id=' . gfrv('local_graph_id')); break; case 'item_moveup': item_moveup(); header('Location: aggregate_graphs.php?action=edit&id=' . gfrv('local_graph_id')); break; default: top_header(); aggregate_graph(); bottom_footer(); break; } function add_tree_names_to_actions_array() : void { global $actions; // add a list of tree names to the actions dropdown $trees = db_fetch_assoc('SELECT id, name FROM graph_tree ORDER BY name'); if (cacti_sizeof($trees)) { foreach ($trees as $tree) { $actions['tr_' . $tree['id']] = __('Place on a Tree (%s)', $tree['name']); } } } function form_save() : void { if (!isrv('save_component_graph') && !isrv('save_component_input') && !isrv('save_component_item')) { header('Location: aggregate_graphs.php?action=edit&id=' . gfrv('id')); exit(); } if (isrv('save_component_graph')) { // remember some often used values $local_graph_id = gnrv('local_graph_id', 0); $graph_template_id = gnrv('graph_template_id', 0); $aggregate_template_id = gnrv('aggregate_template_id', 0); $graph_title = form_input_validate(gnrv('title_format'), 'title_format', '', false, 3); if (is_error_message()) { raise_message(2); header('Location: aggregate_graphs.php?action=edit&id=' . $local_graph_id); exit(); } // get the aggregate graph id $aggregate_graph_id = db_fetch_cell_prepared('SELECT id FROM aggregate_graphs WHERE local_graph_id = ?', [$local_graph_id]); // if user disabled template propagation we need to get graph data from form if (!isrv('template_propogation')) { $aggregate_template_id = 0; $new_data = aggregate_validate_graph_params($_POST, false); } else { $new_data = []; } if (is_error_message()) { raise_message(2); header('Location: aggregate_graphs.php?action=edit&id=' . $local_graph_id); exit(); } // save graph data to cacti tables $graph_templates_graph_id = aggregate_graph_templates_graph_save( $local_graph_id, $graph_template_id, $graph_title, $aggregate_template_id, $new_data ); // update title in aggregate graphs table db_execute_prepared('UPDATE aggregate_graphs SET title_format = ? WHERE id = ?', [$graph_title, $aggregate_graph_id] ); /* next lets see if any of the aggregate has changed and save as applicable * if the graph is templates, we can simply ignore. A simple check will * determine if aggregation propagation is enabled */ if (!isrv('template_propogation')) { // template propagation is disabled $save = []; $save['id'] = $aggregate_graph_id; $save['aggregate_template_id'] = $aggregate_template_id; $save['template_propogation'] = ''; $save['gprint_prefix'] = gnrv('gprint_prefix'); $save['gprint_format'] = isrv('gprint_format') ? 'on' : ''; $save['total_prefix'] = gnrv('total_prefix'); $save['total'] = gfrv('total'); $save['graph_type'] = gfrv('graph_type'); $save['total_type'] = gfrv('total_type'); $save['order_type'] = gfrv('order_type'); // see if anything changed, if so, we will have to push out the aggregate if (!empty($aggregate_graph_id)) { $old = db_fetch_row_prepared('SELECT * FROM aggregate_graphs WHERE id = ?', [$aggregate_graph_id] ); $save_me = 0; $save_me += ($old['aggregate_template_id'] != $save['aggregate_template_id']); $save_me += ($old['template_propogation'] != $save['template_propogation']); $save_me += ($old['gprint_prefix'] != $save['gprint_prefix']); $save_me += ($old['gprint_format'] != $save['gprint_format']); $save_me += ($old['graph_type'] != $save['graph_type']); $save_me += ($old['total'] != $save['total']); $save_me += ($old['total_type'] != $save['total_type']); $save_me += ($old['total_prefix'] != $save['total_prefix']); $save_me += ($old['order_type'] != $save['order_type']); if ($save_me) { $aggregate_graph_id = sql_save($save, 'aggregate_graphs'); } // save the template items now // get existing item ids and sequences from graph template $graph_templates_items = array_rekey( db_fetch_assoc_prepared('SELECT id, sequence FROM graph_templates_item WHERE local_graph_id = 0 AND graph_template_id = ? ORDER BY sequence', [$graph_template_id]), 'id', ['sequence'] ); // get existing aggregate template items $aggregate_graph_items_old = array_rekey( db_fetch_assoc_prepared('SELECT * FROM aggregate_graphs_graph_item WHERE aggregate_graph_id = ? ORDER BY sequence', [$aggregate_graph_id]), 'graph_templates_item_id', ['aggregate_graph_id', 'graph_templates_item_id', 'sequence', 'color_template', 't_graph_type_id', 'graph_type_id', 't_cdef_id', 'cdef_id', 'item_skip', 'item_total'] ); // update graph template item values with posted values aggregate_validate_graph_items($_POST, $graph_templates_items); $items_changed = false; $items_to_save = []; $sequence = 1; foreach ($graph_templates_items as $item_id => $data) { $item_new = []; $item_new['aggregate_graph_id'] = $aggregate_graph_id; $item_new['graph_templates_item_id'] = $item_id; $item_new['color_template'] = isset($data['color_template']) ? $data['color_template'] : 0; $item_new['item_skip'] = isset($data['item_skip']) ? 'on' : ''; $item_new['item_total'] = isset($data['item_total']) ? 'on' : ''; $item_new['sequence'] = $sequence; // compare with old item to see if we need to push out. if (!isset($aggregate_graph_items_old[$item_id])) { // this item does not yet exist $items_changed = true; } else { // compare data from user to data from DB foreach ($item_new as $field => $new_value) { if ($aggregate_graph_items_old[$item_id][$field] != $new_value) { $items_changed = true; } } // fill in missing fields with db values $item_new = array_merge($aggregate_graph_items_old[$item_id], $item_new); } $items_to_save[] = $item_new; $sequence++; } if ($items_changed) { aggregate_graph_items_save($items_to_save, 'aggregate_graphs_graph_item'); } if ($save_me || $items_changed) { if (!push_out_aggregates(0, $local_graph_id)) { raise_message(2); } } } } // Save helpers mutate the global message registry; PHPStan cannot observe that side effect. /** @phpstan-ignore booleanNot.alwaysTrue */ if (!is_error_message()) { raise_message(1); } header('Location: aggregate_graphs.php?action=edit&id=' . $local_graph_id); } elseif (isrv('save_component_item')) { global $graph_item_types; $items[0] = []; // handle saving aggregate graph items in separate function if (grv('aggregate_template_id') > 0 || grv('aggregate_graph_id') > 0) { form_save_aggregate(); } if ($graph_item_types[grv('graph_type_id')] == 'LEGEND') { /* this can be a major time saver when creating lots of graphs with the typical GPRINT LAST/AVERAGE/MAX legends */ $items = [ 0 => [ 'color_id' => '0', 'color2_id' => '0', 'alpha' => '0', 'alpha2' => '0', 'graph_type_id' => '9', 'consolidation_function_id' => '4', 'text_format' => 'Current:', 'hard_return' => '' ], 1 => [ 'color_id' => '0', 'color2_id' => '0', 'alpha' => '0', 'graph_type_id' => '9', 'consolidation_function_id' => '1', 'text_format' => 'Average:', 'hard_return' => '' ], 2 => [ 'color_id' => '0', 'color2_id' => '0', 'alpha' => '0', 'graph_type_id' => '9', 'consolidation_function_id' => '3', 'text_format' => 'Maximum:', 'hard_return' => 'on' ] ]; } $graph_template_item_id = null; foreach ($items as $item) { // generate a new sequence if needed if (ierv('sequence')) { $sequence = gfrv('sequence'); srv('sequence', get_sequence($sequence, 'sequence', 'graph_templates_item', ['local_graph_id' => gfrv('local_graph_id')])); } $save['id'] = gfrv('graph_template_item_id'); $save['graph_template_id'] = gfrv('graph_template_id'); $save['local_graph_template_item_id'] = gfrv('local_graph_template_item_id'); $save['local_graph_id'] = gfrv('local_graph_id'); $save['task_item_id'] = form_input_validate(gfrv('task_item_id'), 'task_item_id', '', true, 3); $save['color_id'] = form_input_validate((isset($item['color_id']) ? $item['color_id'] : gfrv('color_id')), 'color_id', '', true, 3); // if alpha is disabled, use invisible_alpha instead if (!isrv('alpha')) { srv('alpha', gnrv('invisible_alpha')); } $save['alpha'] = form_input_validate((isset($item['alpha']) ? $item['alpha'] : gnrv('alpha')), 'alpha', '', true, 3); $save['graph_type_id'] = form_input_validate((isset($item['graph_type_id']) ? $item['graph_type_id'] : gfrv('graph_type_id')), 'graph_type_id', '', true, 3); $save['cdef_id'] = form_input_validate(gfrv('cdef_id'), 'cdef_id', '', true, 3); $save['consolidation_function_id'] = form_input_validate((isset($item['consolidation_function_id']) ? $item['consolidation_function_id'] : gfrv('consolidation_function_id')), 'consolidation_function_id', '', true, 3); $save['text_format'] = form_input_validate((isset($item['text_format']) ? $item['text_format'] : gnrv('text_format')), 'text_format', '', true, 3); $save['value'] = form_input_validate(gnrv('value'), 'value', '', true, 3); $save['hard_return'] = form_input_validate(((isset($item['hard_return']) ? $item['hard_return'] : (isrv('hard_return') ? gnrv('hard_return') : ''))), 'hard_return', '', true, 3); $save['gprint_id'] = form_input_validate(gfrv('gprint_id'), 'gprint_id', '', true, 3); $save['sequence'] = gfrv('sequence'); if (!is_error_message()) { $graph_template_item_id = sql_save($save, 'graph_templates_item'); if ($graph_template_item_id) { raise_message(1); } else { raise_message(2); } } srv('sequence', 0); } if (is_error_message()) { header('Location: ' . CACTI_PATH_URL . 'aggregate_graphs.php?action=item_edit&graph_template_item_id=' . ($graph_template_item_id === null ? gfrv('graph_template_item_id') : $graph_template_item_id) . '&id=' . gfrv('local_graph_id')); exit; } else { header('Location: ' . CACTI_PATH_URL . 'aggregate_graphs.php?action=edit&id=' . gfrv('local_graph_id')); exit; } } } /** * form_save_aggregate - save aggregate graph item * This saves any overrides to item properties from graph template item. * Inserting new items here is not possible. Just editing existing ones. */ function form_save_aggregate() : mixed { if (!isrv('save_component_item')) { return false; } // two possible tables to save to - aggregate template or aggregate graph // with different key column combination $save_to = 'aggregate_graph_templates_item'; $key_cols = ['aggregate_template_id', 'graph_templates_item_id']; $location_success = 'aggregate_templates.php?action=edit&id=' . gfrv('aggregate_template_id'); $location_failure = 'aggregate_graphs.php?action=item_edit&aggregate_template_id=' . gfrv('aggregate_template_id') . '&id=' . gfrv('graph_template_item_id'); if (gfrv('aggregate_graph_id') > 0) { $save_to = 'aggregate_graphs_graph_item'; $key_cols = ['aggregate_graph_id', 'graph_templates_item_id']; $location_success = 'aggregate_graphs.php?action=edit&id=' . gfrv('local_graph_id'); $location_failure = 'aggregate_graphs.php?action=item_edit&aggregate_graph_id=' . gfrv('aggregate_graph_id') . '&id=' . gfrv('graph_template_item_id'); } // only some properties can be saved here $save = []; $save['t_graph_type_id'] = form_input_validate((isrv('t_graph_type_id') ? gnrv('t_graph_type_id') : ''), 't_graph_type_id', '', true, 3); $save['graph_type_id'] = form_input_validate((($save['t_graph_type_id']) ? gfrv('graph_type_id') : 0), 'graph_type_id', '', true, 3); $save['t_cdef_id'] = form_input_validate((isrv('t_cdef_id') ? gnrv('t_cdef_id') : ''), 't_cdef_id', '', true, 3); $save['cdef_id'] = form_input_validate((($save['t_cdef_id']) ? gfrv('cdef_id') : 0), 'cdef_id', '', true, 3); if (!is_error_message()) { // sql_save will not give useful return values when row key is // composed from multiple columns. need to manually build query $sql_set = 'SET '; foreach ($save as $key => $value) { $sql_set .= $key . '=' . db_qstr($value) . ', '; } $sql_set = substr($sql_set, 0, -2); $sql_where = 'graph_templates_item_id = ' . gfrv('graph_template_item_id') . ' AND '; if ($save_to == 'aggregate_graph_templates_item') { $sql_where .= 'aggregate_template_id=' . gfrv('aggregate_template_id'); } else { $sql_where .= 'aggregate_graph_id=' . gfrv('aggregate_graph_id'); } $sql = "UPDATE $save_to $sql_set WHERE $sql_where LIMIT 1"; $success = db_execute($sql); if ($success) { raise_message(1); } else { raise_message(2); } // update existing graphs with the changes to this item if ($save_to == 'aggregate_graphs_graph_item') { if (!push_out_aggregates(0, gfrv('local_graph_id'))) { raise_message(2); } } elseif ($save_to == 'aggregate_graph_templates_item') { if (!push_out_aggregates(gfrv('aggregate_template_id'))) { raise_message(2); } } } if (is_error_message()) { header('Location: ' . CACTI_PATH_URL . $location_failure); exit; } else { header('Location: ' . CACTI_PATH_URL . $location_success); exit; } } function item_movedown() : void { global $graph_item_types; // ================= input validation ================= gfrv('id'); gfrv('local_graph_id'); // ==================================================== $arr = get_graph_group(grv('id')); $next_id = get_graph_parent(grv('id'), 'next'); if ((!empty($next_id)) && (isset($arr[grv('id')]))) { move_graph_group(grv('id'), $arr, $next_id, 'next'); } elseif (preg_match('/(GPRINT|VRULE|HRULE|COMMENT)/', $graph_item_types[db_fetch_cell_prepared('SELECT graph_type_id FROM graph_templates_item WHERE id = ?', [grv('id')])])) { move_item_down('graph_templates_item', grv('id'), 'local_graph_id=' . grv('local_graph_id')); } } function item_moveup() : void { global $graph_item_types; // ================= input validation ================= gfrv('id'); gfrv('local_graph_id'); // ==================================================== $arr = get_graph_group(grv('id')); $previous_id = get_graph_parent(grv('id'), 'previous'); if ((!empty($previous_id)) && (isset($arr[grv('id')]))) { move_graph_group(grv('id'), $arr, $previous_id, 'previous'); } elseif (preg_match('/(GPRINT|VRULE|HRULE|COMMENT)/', $graph_item_types[db_fetch_cell_prepared('SELECT graph_type_id FROM graph_templates_item WHERE id = ?', [grv('id')])])) { move_item_up('graph_templates_item', grv('id'), 'local_graph_id=' . grv('local_graph_id')); } } function item_remove() : void { // ================= input validation ================= gfrv('id'); // ==================================================== db_execute_prepared('DELETE FROM graph_templates_item WHERE id = ?', [grv('id')]); } function item_edit() : void { global $struct_graph_item, $graph_item_types, $consolidation_functions; // Remove filter item unset($struct_graph_item['data_template_id']); // ================= input validation ================= gfrv('id'); gfrv('local_graph_id'); gfrv('aggregate_graph_id'); gfrv('aggregate_template_id'); // ==================================================== // remember these search fields in session vars so we don't have to keep passing them around load_current_session_value('local_graph_id', 'sess_local_graph_id', ''); $id = (!ierv('id') ? '&id=' . gfrv('id') : ''); // this editor can work on aggregate template graph item or aggregate item if (!ierv('aggregate_graph_id')) { $id_field = 'aggregate_graph_id'; $table_name = 'aggregate_graphs_graph_item'; $page_name = 'aggregate_graphs.php'; } elseif (!ierv('aggregate_template_id')) { $id_field = 'aggregate_template_id'; $table_name = 'aggregate_graph_templates_item'; $page_name = 'aggregate_templates.php'; } else { // TODO redirect somewhere and show an error message, rather than die die('We should have redirected somewhere but we ended up here instead' . PHP_EOL); } $template_item = []; if (!ierv('id')) { $template_item = db_fetch_row_prepared('SELECT * FROM graph_templates_item WHERE id = ?', [grv('id')]); } // override some template_item values from aggregate tables $item_overrides = db_fetch_row_prepared("SELECT * FROM $table_name WHERE $id_field = ? AND graph_templates_item_id = ?", [grv($id_field), grv('id')]); if (cacti_sizeof($item_overrides) == 0) { /* this item is not currently in aggregate tables * item editor will not work in this case, so let's * save it now */ $item_new = [ $id_field => grv($id_field), 'graph_templates_item_id' => grv('id'), 'sequence' => $template_item['sequence'] ?? 1 ]; aggregate_graph_items_save([$item_new], $table_name); $item_overrides = db_fetch_row_prepared("SELECT * FROM $table_name WHERE $id_field = ? AND graph_templates_item_id = ?", [grv($id_field), grv('id')]); } if (cacti_sizeof($template_item)) { foreach (array_keys($template_item) as $field_name) { if (!array_key_exists($field_name, $item_overrides)) { continue; } // t_ column in aggregate table must be "on" to override if (array_key_exists('t_' . $field_name, $item_overrides) && $item_overrides['t_' . $field_name] == 'on') { $template_item[$field_name] = $item_overrides[$field_name]; } } } html_start_box(__('Override Values for Graph Item'), '100%', true, 3, 'center', ''); $form_array = []; foreach ($struct_graph_item as $field_name => $field_array) { $form_array += [$field_name => $struct_graph_item[$field_name]]; // should we draw an override checkbox if (array_key_exists('t_' . $field_name, $item_overrides)) { $form_array[$field_name]['sub_checkbox'] = [ 'name' => 't_' . $field_name, 'friendly_name' => __esc('Override this Value') . '
', 'value' => ($item_overrides['t_' . $field_name] == 'on' ? 'on' : ''), 'on_change' => 'toggleFieldEnabled(this.id);' ]; } $form_array[$field_name]['value'] = (cacti_sizeof($template_item) ? $template_item[$field_name] : ''); $form_array[$field_name]['form_id'] = (cacti_sizeof($template_item) ? $template_item['id'] : '0'); } draw_edit_form( [ 'config' => [ 'post_to' => CACTI_PATH_URL . 'aggregate_graphs.php' ], 'fields' => $form_array ] ); form_hidden_box('local_graph_id', grv('local_graph_id'), '0'); form_hidden_box('graph_template_item_id', (cacti_sizeof($template_item) ? $template_item['id'] : '0'), ''); form_hidden_box('local_graph_template_item_id', (cacti_sizeof($template_item) ? $template_item['local_graph_template_item_id'] : '0'), ''); form_hidden_box('graph_template_id', (cacti_sizeof($template_item) ? $template_item['graph_template_id'] : '0'), ''); form_hidden_box('sequence', (cacti_sizeof($template_item) ? $template_item['sequence'] : '0'), ''); form_hidden_box('_graph_type_id', (cacti_sizeof($template_item) ? $template_item['graph_type_id'] : '0'), ''); form_hidden_box('save_component_item', '1', ''); form_hidden_box('invisible_alpha', $form_array['alpha']['value'], 'FF'); form_hidden_box('rrdtool_version', get_rrdtool_version(), ''); form_hidden_box('aggregate_graph_id', grv('aggregate_graph_id'), '0'); form_hidden_box('aggregate_template_id', grv('aggregate_template_id'), '0'); html_end_box(true, true); form_save_button(CACTI_PATH_URL . "$page_name?action=edit&id=" . gfrv('local_graph_id')); // Now we need some javascript to make it dynamic ?> ['regexp' => '/^([a-zA-Z0-9_]+)$/']]); // ==================================================== // we are performing two set's of actions here $actions += $agg_item_actions; // if we are to save this form, instead of display it if (isrv('selected_items')) { $selected_items = sanitize_unserialize_selected_items(gnrv('selected_items')); if ($selected_items != false) { if (grv('drp_action') == '1') { // delete api_aggregate_remove_multi($selected_items); } elseif (grv('drp_action') == '2') { // migrate to template api_aggregate_convert_template($selected_items); } elseif (grv('drp_action') == '3') { // create aggregate from aggregate $aggregate_name = form_input_validate(grv('aggregate_name'), 'aggregate_name', '', false, 3); if (!is_error_message()) { api_aggregate_create($aggregate_name, $selected_items); } } elseif (grv('drp_action') == '4') { // add graphs to report $good = true; for ($i = 0; ($i < cacti_count($selected_items)); $i++) { if (!reports_add_graphs(gfrv('report_id'), $selected_items[$i], grv('timespan'), grv('align'))) { raise_message('reports_add_error'); $good = false; break; } } if ($good) { raise_message('reports_graphs_added'); } } elseif (grv('drp_action') == '5') { // Convert to a normal graph api_aggregate_convert_to_graph($selected_items); header('Location: aggregate_graphs.php'); exit; } elseif (grv('drp_action') == '10') { // associate with aggregate $local_graph_id = gfrv('local_graph_id'); api_aggregate_associate($local_graph_id, $selected_items); header('Location: aggregate_graphs.php?action=edit&tab=items&id=' . $local_graph_id); exit; } elseif (grv('drp_action') == '11') { // dis-associate with aggregate $local_graph_id = gfrv('local_graph_id'); api_aggregate_disassociate($local_graph_id, $selected_items); header('Location: aggregate_graphs.php?action=edit&tab=items&id=' . $local_graph_id); exit; } elseif (preg_match('/^tr_([0-9]+)$/', grv('drp_action'), $matches)) { // place on tree gfrv('tree_id'); gfrv('tree_item_id'); for ($i = 0; ($i < cacti_count($selected_items)); $i++) { api_tree_item_save(0, gnrv('tree_id'), TREE_ITEM_TYPE_GRAPH, gnrv('tree_item_id'), '', $selected_items[$i], 0, 0, 0, 0, false); } } } header('Location: aggregate_graphs.php'); exit; } else { $ilist = ''; $iarray = []; // default form variables $aggregate_templates = []; $reports = []; // loop through each of the graphs selected on the previous page and get more info about them foreach ($_POST as $var => $val) { if (preg_match('/^chk_([0-9]+)$/', $var, $matches)) { // ================= input validation ================= input_validate_input_number($matches[1], 'chk[1]'); // ==================================================== $ilist .= '
  • ' . htmle(get_graph_title(intval($matches[1]))) . '
  • '; $iarray[] = $matches[1]; } } if (cacti_sizeof($iarray)) { if (grv('drp_action') == '2') { $local_graph_ids = []; // determine the common graph template if any foreach ($_POST as $var => $val) { if (preg_match('/^chk_([0-9]+)$/', $var, $matches)) { $local_graph_ids[] = $matches[1]; } } /** * for whatever reason, subquery performance in mysql is sub-optimal. * Therefore, let's do this as a few queries instead. */ $task_items = array_rekey(db_fetch_assoc_prepared('SELECT DISTINCT task_item_id FROM graph_templates_item WHERE local_graph_id IN (' . trim(str_repeat('?, ', cacti_sizeof($local_graph_ids)), ', ') . ')', $local_graph_ids), 'task_item_id', 'task_item_id'); if (cacti_sizeof($task_items)) { $graph_templates = db_fetch_assoc_prepared('SELECT DISTINCT graph_template_id FROM graph_templates_item WHERE task_item_id IN (' . trim(str_repeat('?, ', cacti_sizeof($task_items)), ', ') . ') AND graph_template_id>0', array_values($task_items)); } else { $graph_templates = []; } if (cacti_sizeof($graph_templates) > 1) { $message = '

    ' . __('The selected Aggregate Graphs represent elements from more than one Graph Template.') . '

    ' . __('In order to migrate the Aggregate Graphs below to a Template based Aggregate, they must only be using one Graph Template.') . "

    "; raise_message('nonmatch_templates', $message, MESSAGE_LEVEL_ERROR); header('Location: aggregate_graphs.php'); exit; } if (cacti_sizeof($graph_templates) == 0) { $message = '

    ' . __('The selected Aggregate Graphs does not appear to have any matching Aggregate Templates.') . '

    ' . __('In order to migrate the Aggregate Graphs below use an Aggregate Template, one must already exist.') . "

    "; raise_message('nonmatch_templates', $message, MESSAGE_LEVEL_ERROR); header('Location: aggregate_graphs.php'); exit; } else { $graph_template = $graph_templates[0]['graph_template_id']; $aggregate_templates = array_rekey( db_fetch_assoc_prepared('SELECT id, name FROM aggregate_graph_templates WHERE graph_template_id = ? ORDER BY name', [$graph_template]), 'id', 'name' ); if (!cacti_sizeof($aggregate_templates)) { $name = db_fetch_cell_prepared('SELECT name FROM graph_templates WHERE id = ?', [$graph_template]); $message = '

    ' . __('There are currently no Aggregate Templates defined for the selected Legacy Aggregates.') . '

    ' . __esc('In order to migrate the Aggregate Graphs below to a Template based Aggregate, first create an Aggregate Template for the Graph Template \'%s\'.', $name) . "

    "; raise_message('nonmatch_templates', $message, MESSAGE_LEVEL_ERROR); header('Location: aggregate_graphs.php'); exit; } } } elseif (grv('drp_action') == '4') { $reports = db_fetch_assoc_prepared('SELECT id, name FROM reports WHERE user_id = ? ORDER BY name', [$_SESSION[SESS_USER_ID]]); if (cacti_sizeof($reports)) { $reports = array_rekey($reports, 'id', 'name'); } else { $message = '

    ' . __('You currently have no reports defined.') . '

    '; raise_message('nonmatch_templates', $message, MESSAGE_LEVEL_ERROR); header('Location: aggregate_graphs.php'); exit; } } } $form_data = [ 'general' => [ 'page' => 'aggregate_graphs.php', 'actions' => $actions, 'optvar' => 'drp_action', 'item_array' => $iarray, 'item_list' => $ilist, 'eaction' => 'local_graph_id', 'eactionid' => isrv('local_graph_id') ? gfrv('local_graph_id') : '0' ], 'options' => [ 1 => [ 'smessage' => __('Click \'Continue\' to Delete the following Aggregate Graph.'), 'pmessage' => __('Click \'Continue\' to Delete following Aggregate Graphs.'), 'scont' => __('Delete Aggregate Graph'), 'pcont' => __('Delete Aggregate Graphs') ], 2 => [ 'smessage' => __('Click \'Continue\' to Migrate the following Legacy Aggregate to a Templated Aggregate Graph.'), 'pmessage' => __('Click \'Continue\' to Migrate the following Legacy Aggregates to Templated Aggregate Graphs.'), 'scont' => __('Migrate to Aggregate Graph'), 'pcont' => __('Migrate to Aggregate Graphs'), 'extra' => [ 'aggregate_template_id' => [ 'method' => 'drop_array', 'array' => $aggregate_templates, 'title' => __('Aggregate Template'), 'default' => array_key_first($aggregate_templates) ] ] ], 3 => [ 'message' => __('Click \'Continue\' to Combine the following Aggregates into an Aggregate Graph.'), 'cont' => __('Combine Aggregate Graphs'), 'extra' => [ 'aggregate_name' => [ 'method' => 'textbox', 'title' => __('Aggregate Name'), 'default' => __('New Aggregate'), 'width' => 40, 'size' => 40 ] ] ], 4 => [ 'smessage' => __('Click \'Continue\' to Place the following Aggregate Graph on a Report.'), 'pmessage' => __('Click \'Continue\' to Place the following Aggregate Graphs on a Report.'), 'scont' => __('Place Aggregate Graph on Report'), 'pcont' => __('Place Aggregate Graphs on Report'), 'extra' => [ 'report_id' => [ 'method' => 'drop_array', 'title' => __('Report Name'), 'array' => $reports, 'default' => array_key_first($reports) ], 'timespan' => [ 'method' => 'drop_array', 'title' => __('Timespan'), 'array' => $graph_timespans, 'default' => read_user_setting('default_timespan') ], 'align' => [ 'method' => 'drop_array', 'title' => __('Align'), 'array' => $alignment, 'default' => REPORTS_ALIGN_CENTER ] ] ], 5 => [ 'smessage' => __('Click \'Continue\' to Convert the following Aggregate Graph to a Normal Graph.'), 'pmessage' => __('Click \'Continue\' to Convert the following Aggregate Graphs to Normal Graphs.'), 'scont' => __('Convert Aggregate Graph'), 'pcont' => __('Convert Aggregate Graphs') ], 10 => [ 'smessage' => __('Click \'Continue\' to Associate the following Graph with the Aggregate Graph.'), 'pmessage' => __('Click \'Continue\' to Associate the following Graphs with the Aggregate Graph.'), 'scont' => __('Associate Graph with Aggregate'), 'pcont' => __('Associate Graphs with Aggregate') ], 11 => [ 'smessage' => __('Click \'Continue\' to Disassociate the following Graph from the Aggregate Graph.'), 'pmessage' => __('Click \'Continue\' to Disassociate the following Graphs from the Aggregate Graph.'), 'scont' => __('Disassociate Graph with Aggregate'), 'pcont' => __('Disassociate Graphs with Aggregate') ], ] ]; $trees = db_fetch_assoc('SELECT id, name FROM graph_tree ORDER BY name'); if (cacti_sizeof($trees)) { foreach ($trees as $tree) { $form_data['options']['tr_' . $tree['id']] = [ 'smessage' => __esc('Click \'Continue\' to Place the following Aggregate Graph on Tree %s.', $tree['name']), 'pmessage' => __esc('Click \'Continue\' to Duplicate following Aggregate Graphs on Tree %s.', $tree['name']), 'scont' => __('Place Aggregate Graph on Tree'), 'pcont' => __('Place Aggregate Graphs on Tree'), 'extra' => [ 'tree_item_id' => [ 'method' => 'drop_branch', 'title' => __('Destination Branch:'), 'id' => $tree['id'] ] ], 'eaction' => 'tree_id', 'eactionid' => $tree['id'], ]; } } form_continue_confirmation($form_data); } } function graph_edit() : bool { global $struct_graph, $struct_aggregate_graph, $image_types; global $consolidation_functions, $graph_item_types, $struct_graph_item; // Remove filter item unset($struct_graph_item['data_template_id']); // ================= input validation ================= gfrv('id'); // ==================================================== // purge any old graphs aggregate_prune_graphs(grv('id')); if (isrv('reset')) { $_SESSION['aggregate_referer'] = 'aggregate_graphs.php'; } elseif (isset($_SERVER['HTTP_REFERER'])) { if (!isset($_SESSION['aggregate_referer'])) { $_SESSION['aggregate_referer'] = validate_redirect_url($_SERVER['HTTP_REFERER'], 'aggregate_graphs.php'); } } else { $_SESSION['aggregate_referer'] = 'aggregate_graphs.php'; } $referer = $_SESSION['aggregate_referer']; $use_graph_template = false; $aginfo = []; $graphs = []; if (!ierv('id')) { $graphs = db_fetch_row_prepared('SELECT * FROM graph_templates_graph WHERE local_graph_id = ?', [grv('id')] ); if (cacti_sizeof($graphs)) { $aginfo = db_fetch_row_prepared('SELECT * FROM aggregate_graphs WHERE local_graph_id = ?', [$graphs['local_graph_id']] ); if ($aginfo['title_format'] == '') { $aginfo['title_format'] = get_graph_title($graphs['local_graph_id']); } $header_label = __esc('[edit: %s]', get_graph_title(grv('id'))); } else { $header_label = __('Aggregate Graph does not Exist'); } } $aggregate_tabs = [ 'details' => __('Details'), 'items' => __('Items'), 'preview' => __('Preview') ]; if (cacti_sizeof($aginfo)) { if ($aginfo['aggregate_template_id'] > 0) { $template = db_fetch_row_prepared('SELECT * FROM aggregate_graph_templates WHERE id = ?', [$aginfo['aggregate_template_id']] ); } else { $template = $aginfo; } } elseif (cacti_sizeof($graphs)) { $template = []; } else { raise_message('missing_aggregate', __('Aggregate Graph Accessed does not exist'), MESSAGE_LEVEL_ERROR); $referer = validate_redirect_url($_SERVER['HTTP_REFERER'] ?? '', 'aggregate_graphs.php'); header('Location: ' . $referer); exit; } // ================= input validation and session storage ================= if (isrv('tab')) { switch (gnrv('tab')) { case 'details': case 'items': case 'preview': $_SESSION['agg_tab'] = gnrv('tab'); srv('tab', gnrv('tab')); break; default: if (isset($_SESSION['agg_tab'])) { srv('tab', $_SESSION['agg_tab']); } else { $_SESSION['agg_tab'] = 'details'; srv('tab', 'details'); } } } elseif (isset($_SESSION['agg_tab'])) { srv('tab', $_SESSION['agg_tab']); } else { srv('tab', 'details'); } // ================= input validation ================= $current_tab = gnrv('tab'); // draw the categories tabs on the top of the page print "
    "; print "
    '; } elseif (!ierv('id') && $current_tab == 'details' && (!cacti_sizeof($template))) { print "'; } else { print ''; } if (!ierv('id') && $current_tab == 'preview') { $graph = db_fetch_row_prepared('SELECT * FROM graph_local WHERE id = ?', [grv('id')] ); if (!cacti_sizeof($graph)) { html_start_box(__('Aggregate Preview Does Not Exist'), '100%', false, 3, 'center', ''); print "" . __('Aggregate Graph does not Exist') . ''; html_end_box(false); raise_message('noaggregate', __('Aggregate Graph does not Exist'), MESSAGE_LEVEL_ERROR); return false; } html_start_box(__('Aggregate Preview %s', $header_label), '100%', false, 3, 'center', ''); ?>


    "; html_start_box(__('Aggregate Graph %s', $header_label), '100%', true, 3, 'center', ''); $helper_string = '|host_description|'; $data_query = db_fetch_cell_prepared('SELECT snmp_query_id FROM snmp_query_graph WHERE graph_template_id = ?', [$template['graph_template_id']] ); if ($data_query > 0) { $data_query_info = get_data_query_array($data_query); foreach ($data_query_info['fields'] as $field_name => $field_array) { if ($field_array['direction'] == 'input' || $field_array['direction'] == 'input-output') { $helper_string .= ($helper_string != '' ? ', ' : '') . '|query_' . $field_name . '|'; } } } // Append the helper string $struct_aggregate_graph['suggestions'] = [ 'method' => 'other', 'friendly_name' => __('Prefix Replacement Values'), 'description' => __('You may use these replacement values for the Prefix in the Aggregate Graph'), 'value' => $helper_string ]; // add template propagation to the structure draw_edit_form( [ 'config' => ['no_form_tag' => true], 'fields' => inject_form_variables($struct_aggregate_graph, $aginfo) ] ); html_end_box(true, true); draw_aggregate_graph_items_list(0, $template['graph_template_id'], $aginfo); form_hidden_box('save_component_template', '1', ''); ?> '; } // we will show the classic representation only when we are not templating print "
    "; ?> '> '> $field_array) { if ($field_array['method'] != 'spacer') { if ($field_name != 'title') { $form_array += [$field_name => $struct_graph[$field_name]]; $form_array[$field_name]['value'] = (cacti_sizeof($graphs) ? $graphs[$field_name] : ''); $form_array[$field_name]['form_id'] = (cacti_sizeof($graphs) ? $graphs['id'] : '0'); if ($use_graph_template && $graphs['t_' . $field_name] != 'on') { $form_array[$field_name]['method'] = 'template_' . $form_array[$field_name]['method']; $form_array[$field_name]['description'] = ''; } } } else { $form_array += [$field_name => $struct_graph[$field_name]]; } } draw_edit_form( [ 'config' => ['no_form_tag' => true], 'fields' => $form_array ] ); html_end_box(true, true); } form_hidden_box('save_component_graph', '1', ''); form_hidden_box('save_component_input', '1', ''); form_hidden_box('rrdtool_version', get_rrdtool_version(), ''); form_save_button($referer, 'return', 'id'); print '
    '; ?> [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' ], 'template_id' => [ 'filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1' ], 'rfilter' => [ 'filter' => FILTER_VALIDATE_IS_REGEX, 'pageset' => true, 'default' => '' ], 'page' => [ 'filter' => FILTER_VALIDATE_INT, 'default' => '1' ], 'matching' => [ 'filter' => FILTER_VALIDATE_REGEXP, 'default' => 'on', 'pageset' => true, 'options' => ['options' => ['regexp' => '/^(on|true|false)$/']] ], 'sort_column' => [ 'filter' => FILTER_CALLBACK, 'default' => 'title_cache', 'options' => ['options' => 'sanitize_search_string'] ], 'sort_direction' => [ 'filter' => FILTER_CALLBACK, 'default' => 'ASC', 'options' => ['options' => 'sanitize_search_string'] ], 'custom' => [ 'filter' => FILTER_VALIDATE_REGEXP, 'options' => ['options' => ['regexp' => '(true|false)']], 'pageset' => true, 'default' => '' ], 'local_graph_ids' => [ 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'pageset' => true, 'default' => '' ] ]; validate_store_request_vars($filters, 'sess_agraph_item'); // ================= input validation ================= if (grv('rows') == -1) { $rows = read_config_option('num_rows_table'); } else { $rows = grv('rows'); } // form the 'where' clause for our main sql query $sql_where_params = []; if (grv('rfilter') == '') { $sql_where = ''; } elseif (validate_is_regex(grv('rfilter')) === true) { $sql_where = 'WHERE gtg.title_cache RLIKE ?'; $sql_where_params[] = grv('rfilter'); } else { $filters = explode(' ', grv('rfilter')); $sql_where = ''; $sql_where = aggregate_make_sql_where($sql_where, $filters, 'gtg.title_cache'); } if (grv('matching') != 'false') { $sql_where .= ($sql_where != '' ? ' AND' : 'WHERE') . ' (agi.local_graph_id IS NOT NULL)'; } $graph_template = db_fetch_cell_prepared('SELECT graph_template_id FROM aggregate_graphs AS ag WHERE ag.local_graph_id = ?', [grv('id')] ); $aggregate_id = db_fetch_cell_prepared('SELECT id FROM aggregate_graphs WHERE local_graph_id = ?', [grv('id')] ); $total_items = db_fetch_cell_prepared('SELECT COUNT(*) FROM aggregate_graphs_items WHERE aggregate_graph_id = ?', [$aggregate_id] ); if (!empty($graph_template)) { $sql_where .= ($sql_where != '' ? ' AND' : 'WHERE') . ' (gtg.graph_template_id=?)'; $sql_where_params[] = $graph_template; } if (grv('local_graph_ids') != '') { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . db_in_clause('agi.local_graph_id', grv('local_graph_ids')); } $sql_params = array_merge([$aggregate_id], $sql_where_params); $sql = "SELECT COUNT(DISTINCT gl.id) AS total FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gtg.local_graph_id=gl.id LEFT JOIN ( SELECT DISTINCT local_graph_id FROM aggregate_graphs_items WHERE aggregate_graph_id=?) AS agi ON gtg.local_graph_id=agi.local_graph_id $sql_where"; $total_rows = get_total_row_data($_SESSION[SESS_USER_ID], $sql, $sql_params, 'aggregate_graph'); $sql_order = get_order_string(); $sql_limit = ' LIMIT ' . ($rows * (grv('page') - 1)) . ',' . $rows; $graph_list = db_fetch_assoc_prepared("SELECT gtg.id, gtg.local_graph_id, gtg.height, gtg.width, gtg.title_cache, agi.local_graph_id AS agg_graph_id FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gtg.local_graph_id=gl.id LEFT JOIN ( SELECT DISTINCT local_graph_id FROM aggregate_graphs_items WHERE aggregate_graph_id=?) AS agi ON gtg.local_graph_id=agi.local_graph_id $sql_where $sql_order $sql_limit", $sql_params ); ?> [ [ 'rfilter' => [ 'method' => 'textbox', 'friendly_name' => __('Search'), 'filter' => FILTER_VALIDATE_IS_REGEX, 'placeholder' => __('Enter a search term'), 'size' => '45', 'default' => '', 'pageset' => true, 'max_length' => '120', 'value' => '' ], 'rows' => [ 'method' => 'drop_array', 'friendly_name' => __('Graphs'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'pageset' => true, 'array' => $item_rows, 'value' => '-1' ], 'matching' => [ 'method' => 'filter_checkbox', 'friendly_name' => __('Part of Aggregate'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(on|true|false)$/']], 'default' => 'on', 'value' => gnrv('matching') ] ] ], 'buttons' => [ 'go' => [ 'method' => 'submit', 'display' => __('Go'), 'title' => __('Apply filter to table'), ], 'clear' => [ 'method' => 'button', 'display' => __('Clear'), 'title' => __('Reset filter to default values'), ] ], 'sort' => [ 'sort_column' => 'title_cache', 'sort_direction' => 'ASC' ] ]; $pageFilter = new CactiTableFilter(__('Matching Graphs'), 'aggregate_graphs.php?action=edit&tab=items&id=' . grv('id'), 'form_aggregate_items', 'sess_agraph_item', '', '', false); $pageFilter->set_filter_array($filter_array); $pageFilter->render(); // print checkbox form for validation form_start('aggregate_graphs.php', 'chk'); html_start_box('', '100%', false, 3, 'center', ''); $nav = html_nav_bar('aggregate_graphs.php?action=edit&tab=items&id=' . gfrv('id'), MAX_DISPLAY_PAGES, (int) grv('page'), $rows, $total_rows, 5, __('Graphs'), 'page', 'main'); print $nav; $display_text = [ 'title_cache' => [ 'display' => __('Graph Title'), 'align' => 'left', 'sort' => 'ASC' ], 'local_graph_id' => [ 'display' => __('ID'), 'align' => 'right', 'sort' => 'ASC' ], 'agg_graph_id' => [ 'display' => __('Included in Aggregate'), 'align' => 'left', 'sort' => 'ASC' ], 'height' => [ 'display' => __('Size'), 'align' => 'right', 'sort' => 'ASC' ] ]; html_header_sort_checkbox($display_text, grv('sort_column'), grv('sort_direction'), false, 'aggregate_graphs.php?action=edit&id=' . gfrv('id')); if (cacti_sizeof($graph_list) > 0) { foreach ($graph_list as $graph) { // we're escaping strings here, so no need to escape them on form_selectable_cell form_alternate_row('line' . $graph['local_graph_id'], true); if (validate_is_regex(grv('rfilter')) === true) { form_selectable_cell(filter_value($graph['title_cache'], grv('rfilter')), $graph['local_graph_id']); } else { form_selectable_ecell(grv('rfilter') != '' ? aggregate_format_text($graph['title_cache'], grv('rfilter')) : $graph['title_cache'], $graph['local_graph_id']); } form_selectable_cell($graph['local_graph_id'], $graph['local_graph_id'], '', 'right'); form_selectable_cell(($graph['agg_graph_id'] != '' ? "" . __('Yes') . '' : "" . __('No') . ''), $graph['local_graph_id']); form_selectable_ecell($graph['height'] . 'x' . $graph['width'], $graph['local_graph_id'], '', 'right'); form_checkbox_cell($graph['title_cache'], $graph['local_graph_id']); form_end_row(); } } else { print '' . __('No Graphs Found') . ''; } html_end_box(false); // put the nav bar on the bottom as well print $nav; // add a list of tree names to the actions dropdown add_tree_names_to_actions_array(); // draw the dropdown containing a list of available actions for this form form_hidden_box('local_graph_id', grv('id'), ''); draw_actions_dropdown($agg_item_actions); form_end(); } function aggregate_make_sql_where(string $sql_where, array $items, string $field) : string { if ($sql_where != '') { $sql_where .= ' AND ('; } else { $sql_where = 'WHERE ('; } $indentation = 0; $termcount = 0; if (cacti_sizeof($items)) { foreach ($items as $i) { $i = trim($i); while (substr($i, 0, 1) == '(') { $indentation++; $termcount = 0; $sql_where .= '('; $i = substr($i, 1); } $split = strpos($i, ')'); if ($split !== false) { $end = trim(substr($i, $split)); $i = substr($i, 0, $split); } else { $end = ''; } if ($i != '') { if (cacti_strtolower($i) == 'and') { $sql_where .= ' AND '; } elseif (cacti_strtolower($i) == 'or') { $sql_where .= ' OR '; } else { $sql_where .= ($termcount > 0 ? ' OR ' : '') . $field . ' LIKE ' . db_qstr('%' . trim($i) . '%'); $termcount++; } } if ($end != '') { while (substr($end, 0, 1) == ')') { $indentation--; $termcount = 0; $sql_where .= ')'; $end = trim(substr($end, 1)); } } } } $sql_where .= ')'; return trim($sql_where); } function aggregate_format_text(string $text, string $filter) : string { $items = explode(' ', $filter); $tags = []; foreach ($items as $i) { $i = trim($i); $i = str_replace('(', '', $i); $i = str_replace(')', '', $i); if (cacti_strtolower($i) == 'and' || cacti_strtolower($i) == 'or') { continue; } if (substr_count($text, $i) > 0) { $tagno = rand(); $tags[$tagno] = $i; $text = str_replace($i, "<<$tagno>>", $text); } } if (cacti_sizeof($tags)) { foreach ($tags as $k => $t) { $text = str_replace("<<$k>>", "" . htmle($t) . '', $text); } } return $text; } function create_aggregate_filter() : array { global $item_rows; $any = ['-1' => __('Any')]; $none = ['0' => __('None')]; $templates = array_rekey( db_fetch_assoc('SELECT DISTINCT at.id, at.name FROM aggregate_graph_templates AS at INNER JOIN aggregate_graphs AS ag ON ag.aggregate_template_id=at.id ORDER BY name'), 'id', 'name' ); $templates = $any + $none + $templates; return [ 'rows' => [ [ 'filter' => [ 'method' => 'textbox', 'friendly_name' => __('Search'), 'filter' => FILTER_DEFAULT, 'placeholder' => __('Enter a search term'), 'size' => '30', 'default' => '', 'pageset' => true, 'max_length' => '120', 'value' => '' ], 'template_id' => [ 'method' => 'drop_array', 'friendly_name' => __('Template'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'pageset' => true, 'array' => $templates, 'value' => '-1' ], 'rows' => [ 'method' => 'drop_array', 'friendly_name' => __('Graphs'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'pageset' => true, 'array' => $item_rows, 'value' => '-1' ], 'local_graph_ids' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'pageset' => true, 'default' => '' ] ] ], 'buttons' => [ 'go' => [ 'method' => 'submit', 'display' => __('Go'), 'title' => __('Apply Filter to Table'), ], 'clear' => [ 'method' => 'button', 'display' => __('Clear'), 'title' => __('Reset Filter to Default Values'), ] ], 'sort' => [ 'sort_column' => 'title_cache', 'sort_direction' => 'ASC' ], 'javascript' => [ 'global' => '', 'ready' => '' ] ]; } function draw_aggregate_filter(bool $render = false) : void { $filters = create_aggregate_filter(); $header = __('Aggregate Graphs') . (grv('local_graph_ids') != '' ? __(' [ Custom Graphs List Applied - Clear to Reset ]') : ''); // create the page filter $pageFilter = new CactiTableFilter($header, 'aggregate_graphs.php', 'forms', 'sess_agraph'); $pageFilter->set_filter_array($filters); if ($render) { $pageFilter->render(); } else { $pageFilter->sanitize(); } } function aggregate_graph() : void { global $actions, $item_rows; draw_aggregate_filter(true); if (grv('rows') == -1) { $rows = read_config_option('num_rows_table'); } else { $rows = grv('rows'); } $sql_where = 'WHERE (gtg.graph_template_id = 0 AND gl.host_id = 0)'; $sql_params = []; // form the 'where' clause for our main sql query if (grv('filter') != '') { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . '(gtg.title_cache LIKE ? OR ag.title_format LIKE ?'; $sql_params[] = '%' . grv('filter') . '%'; $sql_params[] = '%' . grv('filter') . '%'; if (ctype_digit(grv('filter'))) { $sql_where .= ' OR gl.id = ?'; $sql_params[] = (int) grv('filter'); } $sql_where .= ')'; } if (grv('template_id') == '0') { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . '(ag.aggregate_template_id = 0 OR ag.aggregate_template_id IS NULL)'; } elseif (grv('template_id') > 0) { $sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'ag.aggregate_template_id= ?'; $sql_params[] = grv('template_id'); } $sql = "SELECT COUNT(DISTINCT gl.id) AS total FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gtg.local_graph_id=gl.id INNER JOIN aggregate_graphs AS ag ON gtg.local_graph_id = ag.local_graph_id LEFT JOIN aggregate_graph_templates AS agt ON agt.id = ag.aggregate_template_id $sql_where"; $total_rows = get_total_row_data($_SESSION[SESS_USER_ID], $sql, $sql_params, 'aggregate_graph'); $sql_order = get_order_string(); $sql_limit = ' LIMIT ' . ($rows * (grv('page') - 1)) . ',' . $rows; $graph_list = db_fetch_assoc_prepared("SELECT gtg.id, gtg.local_graph_id, gtg.height, gtg.width, gtg.title_cache, agt.name FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gtg.local_graph_id = gl.id INNER JOIN aggregate_graphs AS ag ON gl.id = ag.local_graph_id LEFT JOIN aggregate_graph_templates AS agt ON agt.id = ag.aggregate_template_id $sql_where AND ag.id IS NOT NULL $sql_order $sql_limit", $sql_params); $display_text = [ 'title_cache' => [ 'display' => __('Graph Title'), 'align' => 'left', 'sort' => 'ASC', 'tip' => __('The title for the Aggregate Graphs') ], 'local_graph_id' => [ 'display' => __('ID'), 'align' => 'right', 'sort' => 'ASC', 'tip' => __('The internal database identifier for this object') ], 'name' => [ 'display' => __('Aggregate Template'), 'align' => 'left', 'sort' => 'ASC', 'tip' => __('The Aggregate Template that this Aggregate Graphs is based upon') ], 'height' => [ 'display' => __('Size'), 'align' => 'right', 'sort' => 'ASC' ] ]; $nav = html_nav_bar('aggregate_graphs.php', MAX_DISPLAY_PAGES, (int) grv('page'), $rows, $total_rows, 5, __('Aggregate Graphs'), 'page', 'main'); form_start('aggregate_graphs.php', 'chk'); print $nav; html_start_box('', '100%', false, 3, 'center', ''); html_header_sort_checkbox($display_text, grv('sort_column'), grv('sort_direction'), false, 'aggregate_graphs.php?filter=' . rawurlencode(grv('filter'))); if (cacti_sizeof($graph_list)) { foreach ($graph_list as $graph) { // we're escaping strings here, so no need to escape them on form_selectable_cell $template_name = htmle($graph['name']); form_alternate_row('line' . $graph['local_graph_id'], true); form_selectable_cell(filter_value(title_trim($graph['title_cache'], read_config_option('max_title_length')), grv('filter'), 'aggregate_graphs.php?action=edit&id=' . $graph['local_graph_id']), $graph['local_graph_id']); form_selectable_cell($graph['local_graph_id'], $graph['local_graph_id'], '', 'right'); form_selectable_cell((empty($graph['name']) ? '' . __('None') . '' : filter_value($template_name, grv('filter'))), $graph['local_graph_id']); form_selectable_ecell($graph['height'] . 'x' . $graph['width'], $graph['local_graph_id'], '', 'right'); form_checkbox_cell($graph['title_cache'], $graph['local_graph_id']); form_end_row(); } } else { print '' . __('No Aggregate Graphs Found') . ''; } html_end_box(false); if (cacti_sizeof($graph_list)) { print $nav; } // add a list of tree names to the actions dropdown add_tree_names_to_actions_array(); // draw the dropdown containing a list of available actions for this form draw_actions_dropdown($actions); // remove old graphs purge_old_graphs(); form_end(); } function purge_old_graphs() : void { // workaround to handle purged graphs $old_graphs = array_rekey(db_fetch_assoc('SELECT DISTINCT local_graph_id FROM aggregate_graphs_items AS pagi LEFT JOIN graph_local AS gl ON pagi.local_graph_id = gl.id WHERE gl.id IS NULL AND local_graph_id > 0'), 'local_graph_id', 'local_graph_id'); if (cacti_sizeof($old_graphs)) { db_execute_prepared('DELETE FROM aggregate_graphs_items WHERE local_graph_id IN (' . trim(str_repeat('?, ', cacti_sizeof($old_graphs)), ', ') . ')', array_values($old_graphs)); } $old_aggregates = array_rekey(db_fetch_assoc('SELECT DISTINCT local_graph_id FROM aggregate_graphs AS pag LEFT JOIN graph_local AS gl ON pag.local_graph_id = gl.id WHERE gl.id IS NULL AND local_graph_id>0'), 'local_graph_id', 'local_graph_id'); $old_agg_ids = array_rekey(db_fetch_assoc('SELECT DISTINCT pag.id FROM aggregate_graphs AS pag LEFT JOIN graph_local AS gl ON pag.local_graph_id = gl.id WHERE gl.id IS NULL'), 'id', 'id'); if (cacti_sizeof($old_aggregates)) { $placeholders = trim(str_repeat('?, ', cacti_sizeof($old_aggregates)), ', '); $aggregate_ids = array_values($old_aggregates); db_execute_prepared("DELETE FROM graph_templates_item WHERE local_graph_id IN ($placeholders) AND local_graph_id > 0", $aggregate_ids); db_execute_prepared("DELETE FROM graph_templates_graph WHERE local_graph_id IN ($placeholders) AND local_graph_id > 0", $aggregate_ids); db_execute_prepared("DELETE FROM aggregate_graphs WHERE local_graph_id IN ($placeholders)", $aggregate_ids); } if (cacti_sizeof($old_agg_ids)) { db_execute_prepared('DELETE FROM aggregate_graphs_items WHERE aggregate_graph_id IN (' . trim(str_repeat('?, ', cacti_sizeof($old_agg_ids)), ', ') . ')', array_values($old_agg_ids)); } }