<?php
/*
 +-------------------------------------------------------------------------+
 | Copyright (C) 2004-2025 The Cacti Group                                 |
 |                                                                         |
 | This program is free software; you can redistribute it and/or           |
 | modify it under the terms of the GNU General Public License             |
 | as published by the Free Software Foundation; either version 2          |
 | of the License, or (at your option) any later version.                  |
 |                                                                         |
 | This program is distributed in the hope that it will be useful,         |
 | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
 | GNU General Public License for more details.                            |
 +-------------------------------------------------------------------------+
 | Cacti: The Complete RRDtool-based Graphing Solution                     |
 +-------------------------------------------------------------------------+
 | This code is designed, written, and maintained by the Cacti Group. See  |
 | about.php and/or the AUTHORS file for specific developer information.   |
 +-------------------------------------------------------------------------+
 | http://www.cacti.net/                                                   |
 +-------------------------------------------------------------------------+
*/

require('./include/auth.php');
require_once(CACTI_PATH_LIBRARY . '/api_graph.php');
require_once(CACTI_PATH_LIBRARY . '/api_tree.php');
require_once(CACTI_PATH_LIBRARY . '/api_data_source.php');
require_once(CACTI_PATH_LIBRARY . '/api_aggregate.php');
require_once(CACTI_PATH_LIBRARY . '/data_query.php');
require_once(CACTI_PATH_LIBRARY . '/html_tree.php');
require_once(CACTI_PATH_LIBRARY . '/html_form_template.php');
require_once(CACTI_PATH_LIBRARY . '/poller.php');
require_once(CACTI_PATH_LIBRARY . '/reports.php');
require_once(CACTI_PATH_LIBRARY . '/rrd.php');
require_once(CACTI_PATH_LIBRARY . '/template.php');
require_once(CACTI_PATH_LIBRARY . '/utility.php');

aggregate_prune_graphs();

$actions = [
	1 => __('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 (get_request_var('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=' . get_filter_request_var('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=' . get_filter_request_var('local_graph_id'));

		break;
	case 'item_moveup':
		item_moveup();

		header('Location: aggregate_graphs.php?action=edit&id=' . get_filter_request_var('local_graph_id'));

		break;
	default:
		top_header();
		aggregate_graph();
		bottom_footer();

		break;
}

function add_tree_names_to_actions_array() {
	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() {
	if (!isset_request_var('save_component_graph') && !isset_request_var('save_component_input')) {
		header('Location: aggregate_graphs.php?action=edit&id=' . get_nfilter_request_var('id'));

		return null;
	}

	if (isset_request_var('save_component_graph')) {
		/* remember some often used values */
		$local_graph_id        = get_nfilter_request_var('local_graph_id', 0);
		$graph_template_id     = get_nfilter_request_var('graph_template_id', 0);
		$aggregate_template_id = get_nfilter_request_var('aggregate_template_id', 0);
		$graph_title           = form_input_validate(get_nfilter_request_var('title_format'), 'title_format', '', false, 3);

		if (is_error_message()) {
			raise_message(2);
			header('Location: aggregate_graphs.php?action=edit&id=' . $local_graph_id);

			return null;
		}

		/* 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 (!isset_request_var('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);

			return null;
		}

		/* 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 (!isset_request_var('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']         = get_nfilter_request_var('gprint_prefix');
			$save['gprint_format']         = isset_request_var('gprint_format') ? 'on' : '';
			$save['total_prefix']          = get_nfilter_request_var('total_prefix');

			$save['total']                 = get_filter_request_var('total');
			$save['graph_type']            = get_filter_request_var('graph_type');
			$save['total_type']            = get_filter_request_var('total_type');
			$save['order_type']            = get_filter_request_var('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) {
					push_out_aggregates(0, $local_graph_id);
				}
			}
		}

		raise_message(1);

		header('Location: aggregate_graphs.php?action=edit&id=' . $local_graph_id);
	} elseif (isset_request_var('save_component_item')) {
		global $graph_item_types;

		$items[0] = [];

		// handle saving aggregate graph items in separate function
		if (get_request_var('aggregate_template_id') > 0 || get_request_var('aggregate_graph_id') > 0) {
			form_save_aggregate();
		}

		if ($graph_item_types[get_request_var('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',
					'graph_type_id'             => '9',
					'consolidation_function_id' => '4',
					'text_format'               => 'Current:',
					'hard_return'               => ''
					],
				1 => [
					'color_id'                  => '0',
					'graph_type_id'             => '9',
					'consolidation_function_id' => '1',
					'text_format'               => 'Average:',
					'hard_return'               => ''
					],
				2 => [
					'color_id'                  => '0',
					'graph_type_id'             => '9',
					'consolidation_function_id' => '3',
					'text_format'               => 'Maximum:',
					'hard_return'               => 'on'
					]];
		}

		foreach ($items as $item) {
			/* generate a new sequence if needed */
			if (isempty_request_var('sequence')) {
				$sequence = get_filter_request_var('sequence');
				set_request_var('sequence', get_sequence($sequence, 'sequence', 'graph_templates_item', 'local_graph_id=' . get_request_var('local_graph_id')));
			}
			$save['id']                           = get_filter_request_var('graph_template_item_id');
			$save['graph_template_id']            = get_filter_request_var('graph_template_id');
			$save['local_graph_template_item_id'] = get_filter_request_var('local_graph_template_item_id');
			$save['local_graph_id']               = get_filter_request_var('local_graph_id');
			$save['task_item_id']                 = form_input_validate(get_filter_request_var('task_item_id'), 'task_item_id', '', true, 3);
			$save['color_id']                     = form_input_validate((isset($item['color_id']) ? $item['color_id'] : get_filter_request_var('color_id')), 'color_id', '', true, 3);

			/* if alpha is disabled, use invisible_alpha instead */
			if (!isset_request_var('alpha')) {
				set_request_var('alpha', get_nfilter_request_var('invisible_alpha'));
			}

			$save['alpha']                        = form_input_validate((isset($item['alpha']) ? $item['alpha'] : get_nfilter_request_var('alpha')), 'alpha', '', true, 3);
			$save['graph_type_id']                = form_input_validate((isset($item['graph_type_id']) ? $item['graph_type_id'] : get_filter_request_var('graph_type_id')), 'graph_type_id', '', true, 3);
			$save['cdef_id']                      = form_input_validate(get_filter_request_var('cdef_id'), 'cdef_id', '', true, 3);
			$save['consolidation_function_id']    = form_input_validate((isset($item['consolidation_function_id']) ? $item['consolidation_function_id'] : get_filter_request_var('consolidation_function_id')), 'consolidation_function_id', '', true, 3);
			$save['text_format']                  = form_input_validate((isset($item['text_format']) ? $item['text_format'] : get_nfilter_request_var('text_format')), 'text_format', '', true, 3);
			$save['value']                        = form_input_validate(get_nfilter_request_var('value'), 'value', '', true, 3);
			$save['hard_return']                  = form_input_validate(((isset($item['hard_return']) ? $item['hard_return'] : (isset_request_var('hard_return') ? get_nfilter_request_var('hard_return') : ''))), 'hard_return', '', true, 3);
			$save['gprint_id']                    = form_input_validate(get_filter_request_var('gprint_id'), 'gprint_id', '', true, 3);
			$save['sequence']                     = get_filter_request_var('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);
				}
			}

			set_request_var('sequence', 0);
		}

		if (is_error_message()) {
			header('Location: ' . CACTI_PATH_URL . 'aggregate_graphs.php?action=item_edit&graph_template_item_id=' . (empty($graph_template_item_id) ? get_filter_request_var('graph_template_item_id') : $graph_template_item_id) . '&id=' . get_filter_request_var('local_graph_id'));

			exit;
		} else {
			header('Location: ' . CACTI_PATH_URL . 'aggregate_graphs.php?action=edit&id=' . get_filter_request_var('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() {
	if (!isset_request_var('save_component_item')) {
		return;
	}

	// 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=' . get_filter_request_var('aggregate_template_id');
	$location_failure = 'aggregate_graphs.php?action=item_edit&aggregate_template_id=' . get_filter_request_var('aggregate_template_id') . '&id=' . get_filter_request_var('graph_template_item_id');

	if (get_filter_request_var('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=' . get_filter_request_var('local_graph_id');
		$location_failure = 'aggregate_graphs.php?action=item_edit&aggregate_graph_id=' . get_filter_request_var('aggregate_graph_id') . '&id=' . get_filter_request_var('graph_template_item_id');
	}

	// only some properties can be saved here
	$save                    = [];
	$save['t_graph_type_id'] = form_input_validate((isset_request_var('t_graph_type_id') ? get_nfilter_request_var('t_graph_type_id') : ''), 't_graph_type_id', '', true, 3);
	$save['graph_type_id']   = form_input_validate((($save['t_graph_type_id']) ? get_filter_request_var('graph_type_id') : 0), 'graph_type_id', '', true, 3);
	$save['t_cdef_id']       = form_input_validate((isset_request_var('t_cdef_id') ? get_nfilter_request_var('t_cdef_id') : ''), 't_cdef_id', '', true, 3);
	$save['cdef_id']         = form_input_validate((($save['t_cdef_id']) ? get_filter_request_var('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 = ' . get_filter_request_var('graph_template_item_id') . ' AND ';

		if ($save_to == 'aggregate_graph_templates_item') {
			$sql_where .= 'aggregate_template_id=' . get_filter_request_var('aggregate_template_id');
		} else {
			$sql_where .= 'aggregate_graph_id=' . get_filter_request_var('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') {
			push_out_aggregates(0, get_filter_request_var('local_graph_id'));
		} elseif ($save_to == 'aggregate_graph_templates_item') {
			push_out_aggregates(get_filter_request_var('aggregate_template_id'));
		}
	}

	if (is_error_message()) {
		header('Location: ' . CACTI_PATH_URL . $location_failure);

		exit;
	} else {
		header('Location: ' . CACTI_PATH_URL . $location_success);

		exit;
	}
}

function item_movedown() {
	global $graph_item_types;

	/* ================= input validation ================= */
	get_filter_request_var('id');
	get_filter_request_var('local_graph_id');
	/* ==================================================== */

	$arr     = get_graph_group(get_request_var('id'));
	$next_id = get_graph_parent(get_request_var('id'), 'next');

	if ((!empty($next_id)) && (isset($arr[get_request_var('id')]))) {
		move_graph_group(get_request_var('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 = ?', [get_request_var('id')])])) {
		move_item_down('graph_templates_item', get_request_var('id'), 'local_graph_id=' . get_request_var('local_graph_id'));
	}
}

function item_moveup() {
	global $graph_item_types;

	/* ================= input validation ================= */
	get_filter_request_var('id');
	get_filter_request_var('local_graph_id');
	/* ==================================================== */

	$arr         = get_graph_group(get_request_var('id'));
	$previous_id = get_graph_parent(get_request_var('id'), 'previous');

	if ((!empty($previous_id)) && (isset($arr[get_request_var('id')]))) {
		move_graph_group(get_request_var('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 = ?', [get_request_var('id')])])) {
		move_item_up('graph_templates_item', get_request_var('id'), 'local_graph_id=' . get_request_var('local_graph_id'));
	}
}

function item_remove() {
	/* ================= input validation ================= */
	get_filter_request_var('id');
	/* ==================================================== */

	db_execute_prepared('DELETE FROM graph_templates_item WHERE id = ?', [get_request_var('id')]);
}

function item_edit() {
	global $struct_graph_item, $graph_item_types, $consolidation_functions;

	// Remove filter item
	unset($struct_graph_item['data_template_id']);

	/* ================= input validation ================= */
	get_filter_request_var('id');
	get_filter_request_var('local_graph_id');
	get_filter_request_var('aggregate_graph_id');
	get_filter_request_var('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 = (!isempty_request_var('id') ? '&id=' . get_request_var('id') : '');

	/* this editor can work on aggregate template graph item or aggregate item */
	if (!isempty_request_var('aggregate_graph_id')) {
		$id_field   = 'aggregate_graph_id';
		$table_name = 'aggregate_graphs_graph_item';
		$page_name  = 'aggregate_graphs.php';
	} elseif (!isempty_request_var('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);
	}

	if (!isempty_request_var('id')) {
		$template_item = db_fetch_row_prepared('SELECT *
			FROM graph_templates_item
			WHERE id = ?',
			[get_request_var('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 = ?",
		[get_request_var($id_field), get_request_var('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                 => get_request_var($id_field),
			'graph_templates_item_id' => get_request_var('id'),
			'sequence'                => $template_item['sequence']
		];

		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 = ?",
			[get_request_var($id_field), get_request_var('id')]);
	}

	foreach (array_keys($template_item) as $field_name) {
		if (!array_key_exists($field_name, $item_overrides)) {
			continue;
		}

		# t_<field_name> 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') . '<br>',
				'value'         => ($item_overrides['t_'.$field_name] == 'on' ? 'on' : ''),
				'on_change'     => 'toggleFieldEnabled(this.id);'
			];
		}

		$form_array[$field_name]['value']   = (isset($template_item) ? $template_item[$field_name] : '');
		$form_array[$field_name]['form_id'] = (isset($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', get_request_var('local_graph_id'), '0');
	form_hidden_box('graph_template_item_id', (isset($template_item) ? $template_item['id'] : '0'), '');
	form_hidden_box('local_graph_template_item_id', (isset($template_item) ? $template_item['local_graph_template_item_id'] : '0'), '');
	form_hidden_box('graph_template_id', (isset($template_item) ? $template_item['graph_template_id'] : '0'), '');
	form_hidden_box('sequence', (isset($template_item) ? $template_item['sequence'] : '0'), '');
	form_hidden_box('_graph_type_id', (isset($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', get_request_var('aggregate_graph_id'), '0');
	form_hidden_box('aggregate_template_id', get_request_var('aggregate_template_id'), '0');

	html_end_box(true, true);

	form_save_button(CACTI_PATH_URL . "$page_name?action=edit&id=" . get_request_var('local_graph_id'));

	//Now we need some javascript to make it dynamic
	?>
	<script type='text/javascript'>

	$(function() {
		dynamic();
		setFieldsDisabled();
	});

	function dynamic() {
		$('#alpha').prop('disabled', true);
		if ($('#color_id').val() != 0) {
			$('#alpha').prop('disabled', true);
		}
	}

	function changeColorId() {
		if ($('#color_id').attr('selectedIndex') != 0) {
			$('#alpha').prop('disabled', true);
		}
	}

	// disable all items with sub-checkboxes except
	// where sub-checkbox checked
	function setFieldsDisabled() {
		$('input[id^="t_"]').each(function() {
			if (!$(this).is(':checked')) {
				var fieldId = $(this).attr('id').substr(2);

				$('#'+fieldId).prop('disabled', true);
				$('#'+fieldId).addClass('ui-state-disabled');

				if ($('#'+fieldId).selectmenu('instance')) {
					$('#'+fieldId).selectmenu('disable');
				}
			}
		});
	}

	// enable or disable form field based on state of corresponding checkbox
	function toggleFieldEnabled(toggleFieldId) {
		fieldId  = toggleFieldId.substr(2);

		if ($('#'+fieldId).hasClass('ui-state-disabled')) {
			$('#'+fieldId).prop('disabled', false).removeClass('ui-state-disabled');

			if ($('#'+fieldId).selectmenu('instance')) {
				$('#'+fieldId).selectmenu('enable');
			}
		} else {
			$('#'+fieldId).prop('disabled', true).addClass('ui-state-disabled');

			if ($('#'+fieldId).selectmenu('instance')) {
				$('#'+fieldId).selectmenu('disable');
			}
		}
	}

	</script>
	<?php
}

function form_actions() {
	global $actions, $agg_item_actions;
	global $alignment, $graph_timespans;

	/* ================= input validation ================= */
	get_filter_request_var('drp_action', FILTER_VALIDATE_REGEXP, ['options' => ['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 (isset_request_var('selected_items')) {
		$selected_items = sanitize_unserialize_selected_items(get_nfilter_request_var('selected_items'));

		if ($selected_items != false) {
			if (get_request_var('drp_action') == '1') { // delete
				api_aggregate_remove_multi($selected_items);
			} elseif (get_request_var('drp_action') == '2') { // migrate to template
				api_aggregate_convert_template($selected_items);
			} elseif (get_request_var('drp_action') == '3') { // create aggregate from aggregate
				$aggregate_name = get_request_var('aggregate_name');
				api_aggregate_create($aggregate_name, $selected_items);
			} elseif (get_request_var('drp_action') == '4') { // add graphs to report
				$good = true;

				for ($i = 0; ($i < cacti_count($selected_items)); $i++) {
					if (!reports_add_graphs(get_filter_request_var('report_id'), $selected_items[$i], get_request_var('timespan'), get_request_var('align'))) {
						raise_message('reports_add_error');
						$good = false;

						break;
					}
				}

				if ($good) {
					raise_message('reports_graphs_added');
				}
			} elseif (get_request_var('drp_action') == '5') { // Convert to a normal graph
				api_aggregate_convert_to_graph($selected_items);

				header('Location: aggregate_graphs.php');

				exit;
			} elseif (get_request_var('drp_action') == '10') { // associate with aggregate
				$local_graph_id = get_filter_request_var('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 (get_request_var('drp_action') == '11') { // dis-associate with aggregate
				$local_graph_id = get_filter_request_var('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]+)$/', get_request_var('drp_action'), $matches)) { // place on tree
				get_filter_request_var('tree_id');
				get_filter_request_var('tree_item_id');

				for ($i = 0; ($i < cacti_count($selected_items)); $i++) {
					api_tree_item_save(0, get_nfilter_request_var('tree_id'), TREE_ITEM_TYPE_GRAPH, get_nfilter_request_var('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 .= '<li>' . html_escape(get_graph_title($matches[1])) . '</li>';

				$iarray[] = $matches[1];
			}
		}

		if (cacti_sizeof($iarray)) {
			if (get_request_var('drp_action') == '2') {
				/* 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];
					}
				}

				$lgid = implode(',', $local_graph_ids);

				/**
				 * 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("SELECT DISTINCT task_item_id
					FROM graph_templates_item
					WHERE local_graph_id IN($lgid)"), 'task_item_id', 'task_item_id');

				if (cacti_sizeof($task_items)) {
					$task_items = implode(',', $task_items);

					$graph_templates = db_fetch_assoc("SELECT DISTINCT graph_template_id
						FROM graph_templates_item
						WHERE task_item_id IN ($task_items) AND graph_template_id>0");
				} else {
					$graph_templates = [];
				}

				if (cacti_sizeof($graph_templates) > 1) {
					$message = '<p>' . __('The selected Aggregate Graphs represent elements from more than one Graph Template.') . '</p>
						<p>' . __('In order to migrate the Aggregate Graphs below to a Template based Aggregate, they must only be using one Graph Template.') . "</p>
						<div class='itemlist'><ul>$ilist</ul></div>";

					raise_message('nonmatch_templates', $message, MESSAGE_LEVEL_ERROR);
					header('Location: aggregate_graphs.php');

					exit;
				}

				if (cacti_sizeof($graph_templates) == 0) {
					$message = '<p>' . __('The selected Aggregate Graphs does not appear to have any matching Aggregate Templates.') . '</p>
						<p>' . __('In order to migrate the Aggregate Graphs below use an Aggregate Template, one must already exist.') . "</p>
						<div class='itemlist'><ul>$ilist</ul></div>";

					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 = '<p>' . __('There are currently no Aggregate Templates defined for the selected Legacy Aggregates.') . '</p>
							<p>' . __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) . "</p>
							<div class='itemlist'><ul>$ilist</ul></div>";

						raise_message('nonmatch_templates', $message, MESSAGE_LEVEL_ERROR);
						header('Location: aggregate_graphs.php');

						exit;
					}
				}
			} elseif (get_request_var('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 = '<p>' . __('You currently have no reports defined.') . '</p>';

					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'  => isset_request_var('local_graph_id') ? get_filter_request_var('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'    => [
						'title_format' => [
							'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'    => [
						'title_format' => [
							'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() {
	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 ================= */
	get_filter_request_var('id');
	/* ==================================================== */

	/* purge any old graphs */
	aggregate_prune_graphs(get_request_var('id'));

	if (isset_request_var('reset')) {
		$_SESSION['aggregate_referer'] = 'aggregate_graphs.php';
	} elseif (isset($_SERVER['HTTP_REFERER']) && !substr_count($_SERVER['HTTP_REFERER'], 'aggregate_graphs.php')) {
		$_SESSION['aggregate_referer'] = $_SERVER['HTTP_REFERER'];
	} elseif (isset($_SERVER['HTTP_REFERER']) && !isset($_SESSION['aggregate_referer'])) {
		$_SESSION['aggregate_referer'] = $_SERVER['HTTP_REFERER'];
	}

	$referer = isset($_SESSION['aggregate_referer']) ? $_SESSION['aggregate_referer'] : 'aggregate_graphs.php';

	$use_graph_template = false;
	$aginfo             = [];
	$graphs             = [];

	if (!isempty_request_var('id')) {
		$graphs = db_fetch_row_prepared('SELECT *
			FROM graph_templates_graph
			WHERE local_graph_id = ?',
			[get_request_var('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(get_request_var('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 Graphs Accessed does not Exist'), MESSAGE_LEVEL_ERROR);

		if (isset($_SERVER['HTTP_REFERER'])) {
			$referer = $_SERVER['HTTP_REFERER'];
			header('Location: ' . $referer);
		} else {
			header('Location: aggregate_graphs.php');
		}

		exit;
	}

	/* ================= input validation and session storage ================= */
	if (isset_request_var('tab')) {
		switch (get_nfilter_request_var('tab')) {
			case 'details':
			case 'items':
			case 'preview':
				$_SESSION['agg_tab'] = get_nfilter_request_var('tab');
				set_request_var('tab', get_nfilter_request_var('tab'));

				break;
			default:
				if (isset($_SESSION['agg_tab'])) {
					set_request_var('tab', $_SESSION['agg_tab']);
				} else {
					$_SESSION['agg_tab'] = 'details';
					set_request_var('tab', 'details');
				}
		}
	} elseif (isset($_SESSION['agg_tab'])) {
		set_request_var('tab', $_SESSION['agg_tab']);
	} else {
		set_request_var('tab', 'details');
	}
	/* ================= input validation ================= */

	$current_tab = get_nfilter_request_var('tab');

	/* draw the categories tabs on the top of the page */
	print "<div class='tabs'>";
	print "<div class='aggtabs'><nav><ul role='tablist'>";

	if (cacti_sizeof($aggregate_tabs)) {
		foreach ($aggregate_tabs as $id => $name) {
			if ($id == 'details' || (!isempty_request_var('id'))) {
				print "<li class='subTab'><a id='agg_" . $id . "' class='tab " . ($id == $current_tab ? "selected'" : "'") .
					" href='" . html_escape(CACTI_PATH_URL . 'aggregate_graphs.php?action=edit&id=' . get_request_var('id') . "&tab=$id") .
					"'>" . html_escape($name) . '</a></li>';
			}
		}
	}

	print '</ul>';

	/* handle debug mode */
	if (isset_request_var('debug')) {
		if (get_filter_request_var('debug') == '0') {
			kill_session_var('graph_debug_mode');
		} elseif (get_filter_request_var('debug') == '1') {
			$_SESSION['graph_debug_mode'] = true;
		}
	}

	if (isset($_SESSION['graph_debug_mode'])) {
		$message = __('Turn Off Graph Debug Mode');
	} else {
		$message = __('Turn On Graph Debug Mode');
	}

	if (!isempty_request_var('id') && $current_tab == 'preview') {
		print "<ul style='float:right;'><li><a class='pic' href='" . html_escape('aggregate_graphs.php?action=edit&id=' . get_request_var('id') . '&tab=' . get_request_var('tab') .  '&debug=' . (isset($_SESSION['graph_debug_mode']) ? '0' : '1')) . "'>" . $message . '</a></li></ul></nav></div></div>';
	} elseif (!isempty_request_var('id') && $current_tab == 'details' && (!cacti_sizeof($template))) {
		print "<ul style='float:right;'><li><a id='toggle_items' class='pic' href='#'>" . __('Show Item Details') . '</a></li></ul></nav></div></div>';
	} else {
		print '</nav></div></div>';
	}

	if (!isempty_request_var('id') && $current_tab == 'preview') {
		$graph = db_fetch_row_prepared('SELECT *
			FROM graph_local
			WHERE id = ?',
			[get_request_var('id')]
		);

		if (!cacti_sizeof($graph)) {
			html_start_box(__('Aggregate Preview Does Not Exist'), '100%', false, 3, 'center', '');
			print "<tr><td id='imagewindow' class='center'>" . __('Aggregate Graph does not Exist') . '</tr></tr>';
			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', '');
		?>
		<tr>
			<td id='imagewindow' class='center'>
				<img src='<?php print html_escape(CACTI_PATH_URL . 'graph_image.php?action=edit&disable_cache=1&local_graph_id=' . get_request_var('id') . '&rra_id=' . read_user_setting('default_rra_id') . '&random=' . mt_rand()); ?>' alt=''>
				<script type='text/javascript'>
					$(function() {
						$('#agg_preview').show();
					});
				</script>
			</td>
		</tr>
		<?php
		if (isset($_SESSION['graph_debug_mode']) && isset_request_var('id')) {
			$graph_data_array['output_flag']  = RRDTOOL_OUTPUT_STDERR;
			$graph_data_array['print_source'] = 1;

			$null_param = [];
			?>
			<tr>
				<td id='rrdtoolinfo' class='left' style='padding-left:15px;max-width:900px;overflow:scroll'>
					<div style='overflow:auto;'>
						<span class='textInfo'><?php print __('RRDtool Command:'); ?></span><br>
						<?php print @rrdtool_function_graph(get_request_var('id'), 1, $graph_data_array, '', $null_param, $_SESSION[SESS_USER_ID]); ?>
						<span class='textInfo'><?php print __('RRDtool Says:'); ?></span><br><?php unset($graph_data_array['print_source']); ?>
						<pre class='monoSpace tableRow left'><?php print(POLLER_ID == 1 ? @rrdtool_function_graph(get_request_var('id'), 1, $graph_data_array, '', $null_param, $_SESSION[SESS_USER_ID]) : __esc('Not Checked')); ?></pre>
					</div>
					<script type='text/javascript'>
						$(function() {
							var rrdwidth = $(window).width() - $('.cactiConsoleNavigationArea').width();
							$('#rrdtoolinfo, #imagewindow').css('max-width', rrdwidth);
						});
					</script>
				</td>
			</tr>
			<?php
		}

		html_end_box(false);
	}

	if (!isempty_request_var('id') && $current_tab == 'items') {
		aggregate_items();
		bottom_footer();

		exit;
	}

	form_start('aggregate_graphs.php', 'template_edit');

	/* we will show the templated representation only when there is a template and propagation is enabled */
	if (!isempty_request_var('id') && $current_tab == 'details') {
		if (cacti_sizeof($template)) {
			print "<div id='templated'>";

			html_start_box(__('Aggregate Graph %s', $header_label), '100%', true, 3, 'center', '');

			$helper_string = '|host_description|';

			if (isset($template)) {
				$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, (isset($aginfo) ? $aginfo : []))
				]
			);

			html_end_box(true, true);

			if (isset($template)) {
				draw_aggregate_graph_items_list(0, $template['graph_template_id'], $aginfo);
			}

			form_hidden_box('save_component_template', '1', '');

			?>
			<script type='text/javascript'>
				var templated_selectors = [
					'#gprint_prefix',
					'#gprint_format',
					'#graph_type',
					'#total',
					'#total_type',
					'#total_prefix',
					'#order_type',
					'select[id^="agg_color"]',
					'input[id^="agg_total"]',
					'input[id^="agg_skip"]',
					'#image_format_id',
					'#height',
					'#width',
					'#slope_mode',
					'#auto_scale',
					'#auto_scale_opts',
					'#auto_scale_log',
					'#scale_log_units',
					'#auto_scale_rigid',
					'#auto_padding',
					'#export',
					'#upper_limit',
					'#lower_limit',
					'#base_value',
					'#unit_value',
					'#unit_exponent_value',
					'#alt_y_grid',
					'#right_axis',
					'#right_axis_label',
					'#right_axis_format',
					'#right_axis_formatter',
					'#left_axis_format',
					'#left_axis_formatter',
					'#no_gridfit',
					'#unit_length',
					'#tab_width',
					'#dynamic_labels',
					'#force_rules_legend',
					'#legend_position',
					'#legend_direction',
					'#vertical_label'
				];

				$(function() {
					if (!$('input[id^="agg_total"]').is(':checked') && !$('#template_propogation').is(':checked')) {
						$('#agg_preview').hide();
					}

					if ($('#template_propogation').is(':checked')) {
						for (var i = 0; i < templated_selectors.length; i++) {
							$(templated_selectors[i]).prop('disabled', true).addClass('ui-state-disabled');
							if ($(templated_selectors[i]).selectmenu('instance')) {
								$(templated_selectors[i]).selectmenu('disable');
							}
						}
					} else {
						$('#row_template_propogation').hide();
						$('#row_spacer0').hide();
					}

					$('input[id^="agg_total"], input[id^="agg_skip"]').click(function() {
						id = $(this).attr('id');

						if (id.indexOf('skip') > 0) {
							altId = id.replace('skip', 'total');
						} else {
							altId = id.replace('total', 'skip');
						}

						if ($('#' + id).is(':checked')) {
							$('#' + altId).prop('checked', false);
						} else {
							$('#' + altId).prop('checked', true);
						}

						changeTotals();

						updateSaveButton();
					});

					$('#total').change(function() {
						changeTotals();
					});

					$('#total_type').change(function() {
						changeTotalsType();
					});

					$('#template_propogation').change(function() {
						if (!$('#template_propogation').is(':checked')) {
							for (var i = 0; i < templated_selectors.length; i++) {
								$(templated_selectors[i]).prop('disabled', false);
							}
						} else {
							for (var i = 0; i < templated_selectors.length; i++) {
								$(templated_selectors[i]).prop('disabled', true);
							}
						}
					});

					updateSaveButton();
				});

				function updateSaveButton() {
					if ($('input[id^="agg_total"]').is(':checked')) {
						$('#submit').prop('disabled', false);

						if ($('#submit').button('instance')) {
							$('#submit').button('enable');
						}
					} else {
						$('#submit').prop('disabled', true);

						if ($('#submit').button('instance')) {
							$('#submit').button('disable');
						}
					}
				}

				function changeTotals() {
					var totalMode = $('#total').val();
					var showField = totalMode != <?= AGGREGATE_ORDER_NONE ?>;

					toggleFields({
						total_type: showField,
						total_prefix: showField,
						order_type: showField,
					});

					changeTotalsType();
				}

				function changeTotalsType() {
					if ($('#total_type').val() == '<?php print AGGREGATE_TOTAL_TYPE_SIMILAR; ?>') {
						if ($('#total_prefix').val() == '' && $('#id').val() == 0) {
							$('#total_prefix').attr('value', '<?php print __('Total'); ?>');
						}
					} else if ($('#total_type').val() == '<?php print AGGREGATE_TOTAL_TYPE_ALL; ?>') {
						if ($('#total_prefix').val() == '' && $('#id').val() == 0) {
							if ($('#total_prefix').val() == '') {
								$('#total_prefix').attr('value', '<?php print __('All Items'); ?>');
							}
						}
					}
				}
			</script>
			<?php
			print '</div>';
		}

		/* we will show the classic representation only when we are not templating */
		print "<div id='classic'>";

		?>
		<input type='hidden' id='graph_template_graph_id' name='graph_template_graph_id' value='<?php print(isset($graphs) ? $graphs['id'] : '0'); ?>'>
		<input type='hidden' id='local_graph_template_graph_id' name='local_graph_template_graph_id' value='<?php print(isset($graphs) ? $graphs['local_graph_template_graph_id'] : '0'); ?>'>
		<?php

		if (empty($graphs['graph_template_id'])) {
			html_start_box(__('Graph Configuration'), '100%', true, 3, 'center', '');

			$form_array = [];

			foreach ($struct_graph as $field_name => $field_array) {
				if ($field_array['method'] != 'spacer') {
					if ($field_name != 'title') {
						$form_array += [$field_name => $struct_graph[$field_name]];

						$form_array[$field_name]['value']   = (isset($graphs) ? $graphs[$field_name] : '');
						$form_array[$field_name]['form_id'] = (isset($graphs) ? $graphs['id'] : '0');

						if (!(($use_graph_template == false) || ($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 '</div>';

		?>
		<script type='text/javascript'>
			$(function() {
				dynamic();
				if (!$('#templated')) {
					$('#local_graph_template_graph_id').next('table').css('display', 'none');
				}
			});

			$('#toggle_items').click(function() {
				if ($('#toggle_items').is(":contains('<?php print __('Show'); ?>')")) {
					$('#local_graph_template_graph_id').next('table').css('display', '');
					$('#toggle_items').text('<?php print __('Hide Item Details'); ?>');
				} else {
					$('#local_graph_template_graph_id').next('table').css('display', 'none');
					$('#toggle_items').text('<?php print __('Show Item Details'); ?>');
				}
			});

			function dynamic() {
				if ($('#scale_log_units')) {
					$('#scale_log_units').prop('disabled', true);
					if (($('#rrdtool_version').val() != '1.0.0') &&
						($('#auto_scale_log').is(':checked'))) {
						$('#scale_log_units').prop('disabled', true);
					}
				}
			}

			function changeScaleLog() {
				if ($('#scale_log_units')) {
					$('#scale_log_units').prop('disabled', true);
					if (($('#rrdtool_version').val() != '1.0.0') &&
						($('#auto_scale_log').is(':checked'))) {
						$('#scale_log_units').prop('disabled', false);
					}
				}
			}
		</script>
	<?php
	}
}

function aggregate_items() {
	global $agg_item_actions, $item_rows;

	/* ================= input validation and session storage ================= */
	$filters = [
		'rows' => [
			'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_CALLBACK,
			'default' => 'on',
			'options' => ['options' => 'sanitize_search_string']
		],
		'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 (get_request_var('rows') == -1) {
		$rows = read_config_option('num_rows_table');
	} else {
		$rows = get_request_var('rows');
	}

	/* form the 'where' clause for our main sql query */
	if (get_request_var('rfilter') == '') {
		$sql_where = '';
	} elseif (validate_is_regex(get_request_var('rfilter'))) {
		$sql_where = "WHERE gtg.title_cache RLIKE '" . get_request_var('rfilter') . "'";
	} else {
		$filters   = explode(' ', get_request_var('rfilter'));
		$sql_where = '';
		$sql_where = aggregate_make_sql_where($sql_where, $filters, 'gtg.title_cache');
	}

	if (get_request_var('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 = ?',
		[get_request_var('id')]
	);

	$aggregate_id = db_fetch_cell_prepared('SELECT id
		FROM aggregate_graphs
		WHERE local_graph_id = ?',
		[get_request_var('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=$graph_template)";
	}

	if (get_request_var('local_graph_ids') != '') {
		$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . ' agi.local_graph_id IN(' . get_request_var('local_graph_ids') . ')';
	}

	$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=$aggregate_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, [], 'aggregate_graph');

	$sql_order = get_order_string();
	$sql_limit = ' LIMIT ' . ($rows * (get_request_var('page') - 1)) . ',' . $rows;

	$graph_list = db_fetch_assoc("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=$aggregate_id) AS agi
		ON gtg.local_graph_id=agi.local_graph_id
		$sql_where
		$sql_order
		$sql_limit");

	?>
	<script type='text/javascript'>
		var totalItems = <?php print $total_items; ?>;

		function applyFilter() {
			strURL = 'aggregate_graphs.php' +
				'?action=edit&tab=items&id=' + $('#id').val() +
				'&rows=' + $('#rows').val() +
				'&rfilter=' + base64_encode($('#rfilter').val()) +
				'&matching=' + $('#matching').is(':checked');
			loadUrl({
				url: strURL
			})
		}

		function clearFilter() {
			strURL = 'aggregate_graphs.php?action=edit&tab=items&id=' + $('#id').val() + '&clear=true';
			loadUrl({
				url: strURL
			})
		}

		$(function() {
			if (totalItems == 0) {
				$('#agg_preview').hide();
			}

			$('#clear').click(function() {
				clearFilter();
			});

			$('#rfilter').change(function() {
				applyFilter();
			});

			$('#forms').submit(function(event) {
				event.preventDefault();
				applyFilter();
			});
		});
	</script>
	<?php

	html_filter_start_box(__('Matching Graphs'));

	?>
	<tr class='even'>
		<td>
			<form id='forms' action='aggregate_graphs.php'>
				<table class='filterTable'>
					<tr>
						<td>
							<?php print __('Search'); ?>
						</td>
						<td>
							<input type='text' class='ui-state-default ui-corner-all' id='rfilter' size='45' onChange='applyFilter()' value='<?php print get_request_var('rfilter'); ?>'>
						</td>
						<td>
							<?php print __('Graphs'); ?>
						</td>
						<td>
							<select id='rows' onChange='applyFilter()' data-defaultLabel='<?php print __('Graphs');?>'>
								<option value='-1' <?php print (get_request_var('rows') == '-1' ? ' selected>' : '>') . __('Default'); ?></option>
								<?php
								if (cacti_sizeof($item_rows) > 0) {
									foreach ($item_rows as $key => $value) {
										print "<option value='" . $key . "'";

										if (get_request_var('rows') == $key) {
											print ' selected';
										}
										print '>' . html_escape($value) . '</option>';
									}
								}
	?>
							</select>
						</td>
						<td>
							<span>
								<input type='checkbox' id='matching' onChange='applyFilter()' <?php print(get_request_var('matching') == 'on' || get_request_var('matching') == 'true' ? ' checked' : ''); ?>>
								<label for='matching'><?php print __('Part of Aggregate'); ?></label>
							</span>
						</td>
						<td>
							<span>
								<button type='submit' class='ui-button ui-corner-all ui-widget ui-state-active' id='go' value='go' title='<?php print __esc('Set/Refresh Filters'); ?>'><?php print __esc('Go'); ?></button>
								<button type='button' class='ui-button ui-corner-all ui-widget' id='clear' onClick='clearFilter()' value='clear' title='<?php print __esc('Clear Filters'); ?>'><?php print __esc('Clear'); ?></button>
							</span>
						</td>
					</tr>
				</table>
				<input type='hidden' name='action' value='edit'>
				<input type='hidden' name='tab' value='items'>
				<input type='hidden' id='id' value='<?php print get_request_var('id'); ?>'>
			</form>
		</td>
	</tr>
	<?php

	html_end_box(false);

	/* 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=' . get_request_var('id'), MAX_DISPLAY_PAGES, get_request_var('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, get_request_var('sort_column'), get_request_var('sort_direction'), false, 'aggregate_graphs.php?action=edit&id=' . get_request_var('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(get_request_var('rfilter'))) {
				form_selectable_cell(filter_value($graph['title_cache'], get_request_var('rfilter')), $graph['local_graph_id']);
			} else {
				form_selectable_ecell(get_request_var('rfilter') != '' ? aggregate_format_text($graph['title_cache'], get_request_var('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'] != '' ? "<span class='associated'>" . __('Yes') . '</span>' : "<span class='notAssociated'>" . __('No') . '</span>'), $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 '<tr class="tableRow odd"><td colspan="4"><em>' . __('No Graphs Found') . '</em></td></tr>';
	}

	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', get_request_var('id'), '');

	draw_actions_dropdown($agg_item_actions);

	form_end();
}

function aggregate_make_sql_where($sql_where, $items, $field) {
	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 (strtolower($i) == 'and') {
					$sql_where .= ' AND ';
				} elseif (strtolower($i) == 'or') {
					$sql_where .= ' OR ';
				} else {
					$sql_where .= ($termcount > 0 ? ' OR ' : '') . $field . " LIKE '%" . 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($text, $filter) {
	$items = explode(' ', $filter);
	$tags  = [];

	foreach ($items as $i) {
		$i = trim($i);
		$i = str_replace('(', '', $i);
		$i = str_replace(')', '', $i);

		if (strtolower($i) == 'and' || strtolower($i) == 'or') {
			continue;
		}

		if (substr_count($text, $i) !== false) {
			$tagno        = rand();
			$tags[$tagno] = $i;
			$text         = str_replace($i, "<<$tagno>>", $text);
		}
	}

	if (cacti_sizeof($tags)) {
		foreach ($tags as $k => $t) {
			$text = str_replace("<<$k>>", "<span class='filteredValue'>" . html_escape($t) . '</span>', $text);
		}
	}

	return $text;
}

function create_aggregate_filter() {
	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($render = false) {
	$filters = create_aggregate_filter();

	$header = __('Aggregate Graphs') . (get_request_var('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() {
	global $actions, $item_rows;

	draw_aggregate_filter(true);

	if (get_request_var('rows') == -1) {
		$rows = read_config_option('num_rows_table');
	} else {
		$rows = get_request_var('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 (get_request_var('filter') != '') {
		$sql_where .= ($sql_where != '' ? ' AND ':'WHERE ') . '(gtg.title_cache LIKE ? OR ag.title_format LIKE ?)';

		$sql_params[] = '%' . get_request_var('filter') . '%';
		$sql_params[] = '%' . get_request_var('filter') . '%';
	}

	if (get_request_var('template_id') == '0') {
		$sql_where   .= ($sql_where != '' ? ' AND ':'WHERE ') . '(ag.aggregate_template_id = 0 OR ag.aggregate_template_id IS NULL)';
	} elseif (get_request_var('template_id') > 0) {
		$sql_where   .= ($sql_where != '' ? ' AND ':'WHERE ') . 'ag.aggregate_template_id= ?';
		$sql_params[] = get_request_var('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 * (get_request_var('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, get_request_var('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, get_request_var('sort_column'), get_request_var('sort_direction'), false, 'aggregate_graphs.php?filter=' . get_request_var('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 = html_escape($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')), get_request_var('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']) ? '<em>' . __('None') . '</em>' : filter_value($template_name, get_request_var('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 '<tr class="tableRow odd"><td colspan="' . (cacti_sizeof($display_text) + 1) . '"><em>' . __('No Aggregate Graphs Found') . '</em></td></tr>';
	}

	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() {
	/* 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('DELETE FROM aggregate_graphs_items
			WHERE local_graph_id IN (' . implode(',', $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)) {
		db_execute('DELETE FROM graph_templates_item
			WHERE local_graph_id IN (' . implode(',', $old_aggregates) . ')
			AND local_graph_id > 0');

		db_execute('DELETE FROM graph_templates_graph
			WHERE local_graph_id IN (' . implode(',', $old_aggregates) . ')
			AND local_graph_id > 0');

		db_execute('DELETE FROM aggregate_graphs
			WHERE local_graph_id IN (' . implode(',', $old_aggregates) . ')');
	}

	if (cacti_sizeof($old_agg_ids)) {
		db_execute('DELETE FROM aggregate_graphs_items
			WHERE aggregate_graph_id IN (' . implode(',', $old_agg_ids) . ')');
	}
}
