$field_array) { // find our field name $form_field_name = str_replace('|field|', $field_name, $field_name_format); $form_array += [$form_field_name => $struct_graph[$field_name]]; // modifications to the default form array $form_array[$form_field_name]['value'] = ($values_array[$field_name] ?? ''); $form_array[$form_field_name]['form_id'] = ($values_array['id'] ?? '0'); unset($form_array[$form_field_name]['default']); if ($field_array['method'] == 'spacer') { unset($form_array[$form_field_name]); } elseif (isset($graph_template['t_' . $field_name]) && $graph_template['t_' . $field_name] != 'on') { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } elseif ((!empty($snmp_query_graph_id)) && (cacti_sizeof(db_fetch_assoc_prepared('SELECT id FROM snmp_query_graph_sv WHERE snmp_query_graph_id = ? AND field_name = ?', [$snmp_query_graph_id, $field_name])) > 0)) { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } else { if ($draw_any_items == false && $header_title != '') { print "
$header_title
"; } $draw_any_items = true; $num_fields_drawn++; } } // setup form options if ($alternate_colors == true) { $form_config_array = ['no_form_tag' => true]; } else { $form_config_array = ['no_form_tag' => true, 'force_row_color' => true]; } if (cacti_sizeof($form_array)) { draw_edit_form( [ 'config' => $form_config_array, 'fields' => $form_array ] ); } return $num_fields_drawn; } /** * Draws a form that consists of all non-templated graph item fields associated with a particular graph template * * This function fetches information about the graph template and modifies the default graph items array. * It then iterates through the input items, checks for SQL injection attempts, and constructs a form array * for each item. The form array is used to draw the edit form for the graph item fields. * * @param int $graph_template_id The ID of the graph template. * @param int $local_graph_id The ID of the local graph. * @param string $field_name_format The format for the field names. Default is '|field|_|id|'. * @param string $header_title The title for the header. Default is an empty string. * @param bool $alternate_colors Whether to alternate row colors. Default is true. * @param string $locked Whether the fields are locked. Default is 'false'. * * @return int The number of fields drawn. */ function draw_nontemplated_fields_graph_item(int $graph_template_id, int $local_graph_id, string $field_name_format = '|field|_|id|', string $header_title = '', bool $alternate_colors = true, string $locked = 'false') : int { global $struct_graph_item; $draw_any_items = false; $num_fields_drawn = 0; // fetch information about the graph template $input_item_list = db_fetch_assoc_prepared('SELECT * FROM graph_template_input WHERE graph_template_id = ? ORDER BY column_name, name', [$graph_template_id]); // modifications to the default graph items array if (!empty($local_graph_id)) { $host_id = db_fetch_cell_prepared('SELECT host_id FROM graph_local WHERE id = ?', [$local_graph_id]); $struct_graph_item['task_item_id']['method'] = 'drop_callback'; $struct_graph_item['task_item_id']['action'] = 'ajax_get_graphitem'; $struct_graph_item['task_item_id']['sql'] = "SELECT CONCAT_WS('', CASE WHEN host.description IS NULL THEN 'No Device - ' WHEN host.description IS NOT NULL THEN '' END, data_template_data.name_cache,' (',data_template_rrd.data_source_name,')') AS name, data_template_rrd.id FROM (data_template_data,data_template_rrd,data_local) LEFT JOIN host ON (data_local.host_id=host.id) WHERE data_template_rrd.local_data_id=data_local.id AND data_template_data.local_data_id=data_local.id " . (empty($host_id) ? '' : " AND data_local.host_id=$host_id") . ' ORDER BY name'; } if (cacti_sizeof($input_item_list)) { foreach ($input_item_list as $item) { if (!graph_template_input_column_is_allowed($item['column_name'])) { raise_message_javascript( __('Invalid Graph Template Input'), __('The graph template cannot be rendered'), __('A Graph Item Input contains an invalid Field Type.') ); cacti_log('ERROR: Graph rendering refused an invalid graph input field', false, 'SECURITY'); exit; } $form_array = []; if (!empty($local_graph_id)) { $current_def_value = db_fetch_row_prepared('SELECT gti.' . $item['column_name'] . ', gti.id FROM graph_templates_item AS gti INNER JOIN graph_template_input_defs AS gtid ON gtid.graph_template_item_id=gti.local_graph_template_item_id WHERE gtid.graph_template_input_id = ? AND gti.local_graph_id = ? LIMIT 1', [$item['id'], $local_graph_id]); } else { $current_def_value = db_fetch_row_prepared('SELECT gti.' . $item['column_name'] . ', gti.id FROM graph_templates_item AS gti INNER JOIN graph_template_input_defs AS gtid ON gtid.graph_template_item_id=gti.id WHERE gtid.graph_template_input_id = ? AND gti.graph_template_id = ? LIMIT 1', [$item['id'], $graph_template_id]); } // find our field name $form_field_name = str_replace('|field|', $item['column_name'], $field_name_format); $form_field_name = str_replace('|id|', $item['id'], $form_field_name); if (cacti_sizeof($current_def_value)) { $struct_graph_item[$item['column_name']]['id'] = $current_def_value[$item['column_name']]; $struct_graph_item['task_item_id']['action'] = 'ajax_graph_items' . (isset($host_id) ? '&host_id=' . $host_id : '') . '&rrd_id=' . $current_def_value[$item['column_name']]; } $form_array += [$form_field_name => $struct_graph_item[$item['column_name']]]; // modifications to the default form array $form_array[$form_field_name]['friendly_name'] = $item['name']; if (isset($current_def_value[$item['column_name']])) { $form_array[$form_field_name]['value'] = $current_def_value[$item['column_name']]; } else { $form_array[$form_field_name]['value'] = ''; } if ($locked == 'true') { if (str_contains($form_field_name, 'task_item_id')) { $form_array[$form_field_name]['method'] = 'value'; if (isset($current_def_value[$item['column_name']])) { $value = db_fetch_cell_prepared("SELECT CONCAT_WS('', CASE WHEN host.description IS NULL THEN 'No Device - ' ELSE '' END, data_template_data.name_cache, ' (', data_template_rrd.data_source_name, ')') AS name FROM (data_template_data,data_template_rrd,data_local) LEFT JOIN host ON (data_local.host_id=host.id) WHERE data_template_rrd.local_data_id=data_local.id AND data_template_data.local_data_id=data_local.id AND data_template_rrd.id = ?", [$current_def_value[$item['column_name']]]); $form_array[$form_field_name]['value'] = $value; } } } else { if (str_contains($form_field_name, 'task_item_id')) { if (isset($current_def_value[$item['column_name']])) { $value = db_fetch_cell_prepared("SELECT CONCAT_WS('', CASE WHEN host.description IS NULL THEN 'No Device - ' ELSE '' END, data_template_data.name_cache, ' (', data_template_rrd.data_source_name, ')') AS name FROM (data_template_data,data_template_rrd,data_local) LEFT JOIN host ON (data_local.host_id=host.id) WHERE data_template_rrd.local_data_id=data_local.id AND data_template_data.local_data_id=data_local.id AND data_template_rrd.id = ?", [$current_def_value[$item['column_name']]]); $form_array[$form_field_name]['value'] = $value; } } } /* if we are drawing the graph input list in the pre-graph stage we should omit the data source fields because they are basically meaningless at this point */ if (empty($local_graph_id) && $item['column_name'] == 'task_item_id') { unset($form_array[$form_field_name]); } else { if ($draw_any_items == false && $header_title != '') { print "
$header_title
\n"; } $draw_any_items = true; $num_fields_drawn++; } // setup form options if ($alternate_colors == true) { $form_config_array = ['no_form_tag' => true]; } else { $form_config_array = ['no_form_tag' => true, 'force_row_color' => true]; } if (cacti_sizeof($form_array)) { draw_edit_form( [ 'config' => $form_config_array, 'fields' => $form_array ] ); } } } return $num_fields_drawn; } /** * Draws a form that consists of all non-templated data source fields associated with a particular data template * * This function generates and displays form fields for a data source based on the provided data template and values. * It supports various options such as including hidden fields, alternating colors, and custom field name formats. * * @param int $data_template_id The ID of the data template to use. * @param int $local_data_id The ID of the local data source. * @param array &$values_array An array of values to populate the form fields. * @param string $field_name_format The format for field names, default is '|field|'. * @param string $header_title The title to display as a header, default is an empty string. * @param bool $alternate_colors Whether to alternate row colors, default is true. * @param bool $include_hidden_fields Whether to include hidden fields, default is true. * @param int $snmp_query_graph_id The ID of the SNMP query graph, default is 0. * * @global array $struct_data_source The structure of the data source fields. * * @return int The number of fields drawn. */ function draw_nontemplated_fields_data_source(int $data_template_id, int $local_data_id, array &$values_array, string $field_name_format = '|field|', string $header_title = '', bool $alternate_colors = true, bool $include_hidden_fields = true, int $snmp_query_graph_id = 0) : int { global $struct_data_source; $form_array = []; $draw_any_items = false; $num_fields_drawn = 0; // fetch information about the data template $data_template = db_fetch_row_prepared('SELECT * FROM data_template_data WHERE data_template_id = ? AND local_data_id = 0', [$data_template_id]); foreach ($struct_data_source as $field_name => $field_array) { // find our field name $form_field_name = str_replace('|field|', $field_name, $field_name_format); $form_array += [$form_field_name => $struct_data_source[$field_name]]; // modifications to the default form array $form_array[$form_field_name]['value'] = ($values_array[$field_name] ?? ''); $form_array[$form_field_name]['form_id'] = ($values_array['id'] ?? '0'); unset($form_array[$form_field_name]['default']); $current_flag = ($field_array['flags'] ?? ''); $current_template_flag = ($data_template['t_' . $field_name] ?? 'on'); if (($current_template_flag != 'on') || ($current_flag == 'ALWAYSTEMPLATE')) { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } elseif ((!empty($snmp_query_graph_id)) && (cacti_sizeof(db_fetch_assoc_prepared('SELECT id FROM snmp_query_graph_rrd_sv WHERE snmp_query_graph_id = ? AND data_template_id = ? AND field_name = ?', [$snmp_query_graph_id, $data_template_id, $field_name])) > 0)) { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } elseif ((empty($local_data_id)) && ($field_name == 'data_source_path')) { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } else { if ($draw_any_items == false && $header_title != '') { print "
$header_title
\n"; } $draw_any_items = true; $num_fields_drawn++; } } // setup form options if ($alternate_colors == true) { $form_config_array = ['no_form_tag' => true]; } else { $form_config_array = ['no_form_tag' => true, 'force_row_color' => true]; } if (cacti_sizeof($form_array)) { draw_edit_form( [ 'config' => $form_config_array, 'fields' => $form_array ] ); } return $num_fields_drawn; } /** * Draws a form that consists of all non-templated data source item fields associated with a particular data template * * @param int $data_template_id The ID of the data template. * @param array &$values_array Reference to the array of values. * @param string $field_name_format The format for the field names. Default is '|field_id|'. * @param string $header_title The title to display in the header. Default is an empty string. * @param bool $draw_title_for_each_item Whether to draw the title for each item. Default is true. * @param bool $alternate_colors Whether to alternate row colors. Default is true. * @param bool $include_hidden_fields Whether to include hidden fields. Default is true. * @param int $snmp_query_graph_id The ID of the SNMP query graph. Default is 0. * * @return int The number of fields drawn. */ function draw_nontemplated_fields_data_source_item(int $data_template_id, array &$values_array, string $field_name_format = '|field_id|', string $header_title = '', bool $draw_title_for_each_item = true, bool $alternate_colors = true, bool $include_hidden_fields = true, int $snmp_query_graph_id = 0) : int { global $struct_data_source_item; $form_array = []; $draw_any_items = false; $num_fields_drawn = 0; if (cacti_sizeof($values_array)) { foreach ($values_array as $rrd) { $form_array = []; /** * if the user specifies a title, we only want to draw that. if not, we should create our * own title for each data source item */ if ($draw_title_for_each_item == true) { $draw_any_items = false; } if (empty($rrd['local_data_id'])) { // this is a template $data_template_rrd = $rrd; } else { // this is not a template $data_template_rrd = db_fetch_row_prepared('SELECT * FROM data_template_rrd WHERE id = ?', [$rrd['local_data_template_rrd_id']]); } foreach ($struct_data_source_item as $field_name => $field_array) { // find our field name $form_field_name = str_replace('|field|', $field_name, $field_name_format); $form_field_name = str_replace('|id|', $rrd['id'], $form_field_name); $form_array += [$form_field_name => $struct_data_source_item[$field_name]]; // modifications to the default form array $form_array[$form_field_name]['value'] = ($rrd[$field_name] ?? ''); $form_array[$form_field_name]['form_id'] = ($rrd['id'] ?? '0'); unset($form_array[$form_field_name]['default']); // append the data source item name so the user will recognize it if ($draw_title_for_each_item == false) { $form_array[$form_field_name]['friendly_name'] .= ' [' . htmle($rrd['data_source_name']) . ']'; } if ($data_template_rrd['t_' . $field_name] != 'on') { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } elseif ((!empty($snmp_query_graph_id)) && (cacti_sizeof(db_fetch_assoc_prepared('SELECT id FROM snmp_query_graph_rrd_sv WHERE snmp_query_graph_id = ? AND data_template_id = ? AND field_name = ?', [$snmp_query_graph_id, $data_template_id, $field_name])) > 0)) { if ($include_hidden_fields == true) { $form_array[$form_field_name]['method'] = 'hidden'; } else { unset($form_array[$form_field_name]); } } else { if ($draw_any_items == false && $draw_title_for_each_item == false && $header_title != '') { print "
$header_title
\n"; } elseif ($draw_any_items == false && $draw_title_for_each_item == true && $header_title != '') { print "
$header_title [" . htmle($rrd['data_source_name']) . "]
\n"; } $draw_any_items = true; $num_fields_drawn++; /* if the 'Output field' appears here among the non-templated fields, the valid choices for the drop-down box must be fetched from the associated data input method */ if ($field_name == 'data_input_field_id') { $data_input_id = db_fetch_cell_prepared('SELECT data_input_id FROM data_template_data WHERE data_template_id = ? AND local_data_id = 0', [$rrd['data_template_id']]); $form_array[$form_field_name]['sql'] = "SELECT id, CONCAT(data_name,' - ',name) AS name FROM data_input_fields WHERE data_input_id=" . $data_input_id . " AND input_output = 'out' AND update_rra='on' ORDER BY data_name,name"; } } } // setup form options if ($alternate_colors == true) { $form_config_array = ['no_form_tag' => true]; } else { $form_config_array = ['no_form_tag' => true, 'force_row_color' => true]; } if (cacti_sizeof($form_array)) { draw_edit_form( [ 'config' => $form_config_array, 'fields' => $form_array ] ); } } } return $num_fields_drawn; } /** * Draws a form that consists of all non-templated custom data fields associated with a particular data template * * This function retrieves and displays input fields for a specified data template. * It supports various customization options such as field name formatting, header titles, * alternating row colors, and inclusion of hidden fields. * * @param int $data_template_data_id The ID of the data template data. * @param string $field_name_format The format for the field names. Default is '|field|'. * @param string $header_title The title to display as the header. Default is an empty string. * @param bool $alternate_colors Whether to alternate row colors. Default is true. * @param bool $include_hidden_fields Whether to include hidden fields. Default is true. * @param int $snmp_query_id The SNMP query ID. Default is 0. * * @return int The number of fields drawn. */ function draw_nontemplated_fields_custom_data(int $data_template_data_id, string $field_name_format = '|field|', string $header_title = '', bool $alternate_colors = true, bool $include_hidden_fields = true, int $snmp_query_id = 0) : int { $draw_any_items = false; $num_fields_drawn = 0; $data = db_fetch_row_prepared('SELECT id, data_input_id, data_template_id, name, local_data_id FROM data_template_data WHERE id = ?', [$data_template_data_id]); $host_id = db_fetch_cell_prepared('SELECT host.id FROM host INNER JOIN data_local ON data_local.host_id=host.id WHERE data_local.id = ?', [$data['local_data_id']]); $template_data = db_fetch_row_prepared('SELECT id, data_input_id FROM data_template_data WHERE data_template_id = ? AND local_data_id = 0', [$data['data_template_id']]); // get each INPUT field for this data input source $fields = db_fetch_assoc_prepared('SELECT * FROM data_input_fields WHERE data_input_id = ? AND input_output = "in" ORDER BY sequence', [$data['data_input_id']]); // loop through each field found if (cacti_sizeof($fields)) { foreach ($fields as $field) { $data_input_data = db_fetch_row_prepared('SELECT * FROM data_input_data WHERE data_template_data_id = ? AND data_input_field_id = ?', [$data['id'], $field['id']]); if (cacti_sizeof($data_input_data)) { $old_value = $data_input_data['value']; } else { $old_value = ''; } // if data template then get t_value from template, else always allow user input if (empty($data['data_template_id'])) { $can_template = 'on'; } else { $can_template = db_fetch_cell_prepared('SELECT t_value FROM data_input_data WHERE data_template_data_id = ? AND data_input_field_id = ?', [$template_data['id'], $field['id']]); } // find our field name $form_field_name = str_replace('|id|', $field['id'], $field_name_format); if ((!empty($host_id)) && (preg_match('/^' . VALID_HOST_FIELDS . '$/i', $field['type_code'])) && (empty($can_template))) { // no host fields if ($include_hidden_fields == true) { form_hidden_box($form_field_name, $old_value, ''); } } elseif ((!empty($snmp_query_id)) && (preg_match('/^(index_type|index_value|output_type)$/i', $field['type_code']))) { // no data query fields if ($include_hidden_fields == true) { form_hidden_box($form_field_name, $old_value, ''); } } elseif (empty($can_template)) { // no templated fields if ($include_hidden_fields == true) { form_hidden_box($form_field_name, $old_value, ''); } } else { if ($draw_any_items == false && $header_title != '') { print "
$header_title
\n"; } print "
\n"; print "
" . htmle($field['name']) . "
\n"; print "
"; draw_custom_data_row($form_field_name, $field['id'], $data['id'], $old_value); print '
'; print "
\n"; $draw_any_items = true; $num_fields_drawn++; } } } return $num_fields_drawn; } /** * Draws a single row representing 'custom data' for a single data input field. * this function is where additional logic can be applied to control how a certain field of custom * data is represented on the HTML form * * @param string $field_name The name of the form field. * @param int $data_input_field_id The ID of the data input field. * @param int $data_template_data_id The ID of the data template data. * @param mixed $current_value The current value of the field. * * @return void */ function draw_custom_data_row(string $field_name, int $data_input_field_id, int $data_template_data_id, mixed $current_value) : void { $field = db_fetch_row_prepared('SELECT data_name, type_code FROM data_input_fields WHERE id = ?', [$data_input_field_id]); $local_data = db_fetch_row_prepared('SELECT dl.* FROM data_template_data AS dtd INNER JOIN data_local AS dl ON dl.id=dtd.local_data_id WHERE dtd.id = ?', [$data_template_data_id]); if ($field['type_code'] == 'index_type' && cacti_sizeof($local_data)) { $index_type = db_fetch_assoc_prepared('SELECT DISTINCT hsc.field_name FROM host_snmp_cache AS hsc WHERE hsc.host_id = ? AND hsc.snmp_query_id = ?', [$local_data['host_id'], $local_data['snmp_query_id']]); if (cacti_sizeof($index_type) == 0) { print '' . __('Data Query Data Sources must be created through %s', "" . __('New Graphs') . '.') . "\n"; } else { form_dropdown($field_name, $index_type, 'field_name', 'field_name', $current_value, '', '', ''); } } elseif ($field['type_code'] == 'output_type' && cacti_sizeof($local_data)) { $output_type = db_fetch_assoc_prepared('SELECT id, name FROM snmp_query_graph AS sqg WHERE snmp_query_id = ? ORDER BY name', [$local_data['snmp_query_id']]); if (cacti_sizeof($output_type) == 0) { print '' . __('Data Query Data Sources must be created through %s', "" . __('New Graphs') . '.') . "\n"; } else { form_dropdown($field_name, $output_type, 'name', 'id', $current_value, '', '', ''); } } else { form_text_box($field_name, $current_value, '', ''); } }