__('Delete'),
];
if (filter_layouts_can_manage_global()) {
$actions[2] = __('Make Global');
$actions[3] = __('Make Local');
}
set_default_action();
switch (get_nfilter_request_var('action')) {
case 'actions':
layouts_form_actions();
break;
default:
top_header();
layouts_manage();
bottom_footer();
break;
}
/**
* Apply a bulk action (Delete, Make Global, Make Local) to the layouts selected
* on the management list, showing the standard confirmation first.
*
* @return void
*/
function layouts_form_actions() : void {
global $actions;
// ================= input validation =================
get_filter_request_var('drp_action', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^([a-zA-Z0-9_]+)$/']]);
// ====================================================
$user_id = isset($_SESSION['sess_user_id']) ? (int) $_SESSION['sess_user_id'] : 0;
if (isset_request_var('selected_items')) {
$selected_items = sanitize_unserialize_selected_items(get_nfilter_request_var('selected_items'));
if ($selected_items != false) {
$selected_items = array_values(array_map('intval', $selected_items));
switch (get_nfilter_request_var('drp_action')) {
case '1': // delete
foreach ($selected_items as $id) {
filter_layouts_delete($id);
}
break;
case '2': // make global (publish to all users)
foreach ($selected_items as $id) {
filter_layouts_publish($id);
}
break;
case '3': // make local to the current user
foreach ($selected_items as $id) {
filter_layouts_unpublish($id, $user_id);
}
break;
}
}
cacti_redirect('layouts.php');
}
$ilist = '';
$iarray = [];
foreach ($_POST as $var => $val) {
if (preg_match('/^chk_([0-9]+)$/', $var, $matches)) {
// ==== input validation ====
input_validate_input_number($matches[1], 'chk[1]');
// ==========================
$ilist .= '
' . htmle(db_fetch_cell_prepared('SELECT name FROM user_layouts WHERE id = ?', [$matches[1]])) . '';
$iarray[] = $matches[1];
}
}
$form_data = [
'general' => [
'page' => 'layouts.php',
'actions' => $actions,
'optvar' => 'drp_action',
'item_array' => $iarray,
'item_list' => $ilist
],
'options' => [
1 => [
'smessage' => __('Click \'Continue\' to Delete the following Layout.'),
'pmessage' => __('Click \'Continue\' to Delete the following Layouts.'),
'scont' => __('Delete Layout'),
'pcont' => __('Delete Layouts')
],
2 => [
'smessage' => __('Click \'Continue\' to make the following Layout Global to all users.'),
'pmessage' => __('Click \'Continue\' to make the following Layouts Global to all users.'),
'scont' => __('Make Layout Global'),
'pcont' => __('Make Layouts Global')
],
3 => [
'smessage' => __('Click \'Continue\' to make the following Layout Local to you.'),
'pmessage' => __('Click \'Continue\' to make the following Layouts Local to you.'),
'scont' => __('Make Layout Local'),
'pcont' => __('Make Layouts Local')
]
]
];
form_continue_confirmation($form_data);
}
/**
* Render the Layouts management list with the standard preset filter bar and a
* checkbox-driven actions dropdown. Administrators holding the Settings/Utilities
* realm manage every user's layouts; other users manage only their own.
*
* @return void
*/
function layouts_manage() : void {
global $actions;
$is_admin = filter_layouts_can_manage_global();
$user_id = isset($_SESSION['sess_user_id']) ? (int) $_SESSION['sess_user_id'] : 0;
$pageFilter = new CactiTableFilter(__('Layouts'), 'layouts.php', 'form_layouts', 'sess_layouts');
$pageFilter->rows_label = __('Layouts');
$pageFilter->render();
$rows = (grv('rows') == '-1') ? read_config_option('num_rows_table') : grv('rows');
$rows = (int) $rows;
$page = (int) grv('page');
$sql_where = '';
$sql_params = [];
if (grv('filter') != '') {
$sql_where = 'WHERE ul.name LIKE ?';
$sql_params[] = '%' . grv('filter') . '%';
}
if (!$is_admin) {
$sql_where .= ($sql_where != '' ? ' AND ' : 'WHERE ') . 'ul.user_id = ?';
$sql_params[] = $user_id;
}
$total_rows = db_fetch_cell_prepared("SELECT COUNT(*)
FROM user_layouts AS ul
$sql_where", $sql_params);
$sql_order = get_order_string();
$sql_limit = ' LIMIT ' . (($page - 1) * $rows) . ', ' . $rows;
$layouts = db_fetch_assoc_prepared("SELECT ul.id, ul.user_id, ul.page, ul.name, ul.data, ua.username
FROM user_layouts AS ul
LEFT JOIN user_auth AS ua
ON ua.id = ul.user_id
$sql_where
$sql_order
$sql_limit", $sql_params);
$nav = html_nav_bar('layouts.php?filter=' . grv('filter'), MAX_DISPLAY_PAGES, grv('page'), $rows, $total_rows, 5, __('Layouts'), 'page', 'main');
form_start('layouts.php', 'chk');
print $nav;
html_start_box('', '100%', false, 3, 'center', '');
$display_text = [
'name' => [
'display' => __('Name'),
'align' => 'left',
'sort' => 'ASC',
'tip' => __('The name of this Layout.')
],
'nosort' => [
'display' => __('Page'),
'align' => 'left',
'tip' => __('The page this Layout applies to.')
],
'nosort2' => [
'display' => __('Owner'),
'align' => 'left',
'tip' => __('The owner of this Layout, or Global when shared with all users.')
],
'nosort3' => [
'display' => __('Filter'),
'align' => 'left',
'tip' => __('The stored filter this Layout applies.')
]
];
html_header_sort_checkbox($display_text, grv('sort_column'), grv('sort_direction'), false);
if (cacti_sizeof($layouts)) {
foreach ($layouts as $layout) {
if ($layout['user_id'] == 0) {
$owner = __('Global');
} elseif (!empty($layout['username'])) {
$owner = html_escape($layout['username']);
} else {
$owner = __('User %d', $layout['user_id']);
}
$document = filter_layouts_decode($layout['data']);
$summary = $document !== false ? filter_layouts_document_url($document) : '';
if ($summary != '') {
$sep = (strpos($summary, '?') !== false) ? '&' : '?';
$edit_url = $summary . $sep . 'filter_layout=' . $layout['id'];
} else {
$edit_url = '';
}
form_alternate_row('line' . $layout['id'], true);
form_selectable_cell(filter_value($layout['name'], grv('filter'), $edit_url), $layout['id']);
form_selectable_cell(html_escape(layouts_page_name($layout['page'])), $layout['id']);
form_selectable_cell($owner, $layout['id']);
form_selectable_cell(html_escape($summary), $layout['id']);
form_checkbox_cell($layout['name'], $layout['id']);
form_end_row();
}
} else {
print "| " . __('No Layouts Found') . ' |
';
}
html_end_box(false);
if (cacti_sizeof($layouts)) {
print $nav;
}
draw_actions_dropdown($actions);
form_end();
}
/**
* Resolve a layout's stored page basename to the friendly name the user sees in
* the Console navigation (e.g. 'host.php' becomes 'Devices'), falling back to the
* raw basename when the page is not registered.
*
* @param string $page The stored page basename.
*
* @return string
*/
function layouts_page_name(string $page) : string {
global $navigation;
if (isset($navigation[$page . ':']['title']) && $navigation[$page . ':']['title'] != '') {
return $navigation[$page . ':']['title'];
}
return $page;
}