From 79f6c3fe3107301093a34a07cf8c3f2681af6fe1 Mon Sep 17 00:00:00 2001 From: Cacti Group Date: Mon, 5 Oct 2026 08:15:27 -0400 Subject: [PATCH 1/2] Add theme-appropriate colors for QuickTree graph action glyphs The add-to-QuickTree and remove-from-QuickTree action glyphs reused the core deviceUp/deviceDown classes and were only styled via core. Give QuickTree its own .quicktreeAdd/.quicktreeRemove glyph classes with default colors in the base stylesheet and per-theme overrides for each packaged Cacti theme (classic, modern, paw as light; dark, midwinter, sunrise, paper-plane brightened for dark backgrounds). Load the base and theme stylesheets on every page via page_head so the glyph colors also apply on the graph view page where the add glyph is rendered. --- css/classic.css | 32 ++++++++++++++++++++++++++++++++ css/dark.css | 32 ++++++++++++++++++++++++++++++++ css/midwinter.css | 32 ++++++++++++++++++++++++++++++++ css/modern.css | 32 ++++++++++++++++++++++++++++++++ css/paper-plane.css | 32 ++++++++++++++++++++++++++++++++ css/paw.css | 32 ++++++++++++++++++++++++++++++++ css/quicktree.css | 10 ++++++++++ css/sunrise.css | 32 ++++++++++++++++++++++++++++++++ quicktree.php | 6 +++--- setup.php | 19 +++++++++++-------- 10 files changed, 248 insertions(+), 11 deletions(-) create mode 100644 css/classic.css create mode 100644 css/dark.css create mode 100644 css/midwinter.css create mode 100644 css/modern.css create mode 100644 css/paper-plane.css create mode 100644 css/paw.css create mode 100644 css/sunrise.css diff --git a/css/classic.css b/css/classic.css new file mode 100644 index 0000000..521cd5b --- /dev/null +++ b/css/classic.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #2e7d32; +} + +.quicktreeRemove { + color: #c62828; +} diff --git a/css/dark.css b/css/dark.css new file mode 100644 index 0000000..03ac479 --- /dev/null +++ b/css/dark.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #4caf50; +} + +.quicktreeRemove { + color: #e06666; +} diff --git a/css/midwinter.css b/css/midwinter.css new file mode 100644 index 0000000..03ac479 --- /dev/null +++ b/css/midwinter.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #4caf50; +} + +.quicktreeRemove { + color: #e06666; +} diff --git a/css/modern.css b/css/modern.css new file mode 100644 index 0000000..521cd5b --- /dev/null +++ b/css/modern.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #2e7d32; +} + +.quicktreeRemove { + color: #c62828; +} diff --git a/css/paper-plane.css b/css/paper-plane.css new file mode 100644 index 0000000..03ac479 --- /dev/null +++ b/css/paper-plane.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #4caf50; +} + +.quicktreeRemove { + color: #e06666; +} diff --git a/css/paw.css b/css/paw.css new file mode 100644 index 0000000..521cd5b --- /dev/null +++ b/css/paw.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #2e7d32; +} + +.quicktreeRemove { + color: #c62828; +} diff --git a/css/quicktree.css b/css/quicktree.css index 19fc19a..3a4037b 100644 --- a/css/quicktree.css +++ b/css/quicktree.css @@ -75,3 +75,13 @@ padding: 20px; } +/* Default QuickTree graph action glyph colors; the per-theme stylesheets in + this directory override these for each packaged Cacti theme. */ +.quicktreeAdd { + color: #2e7d32; +} + +.quicktreeRemove { + color: #c62828; +} + diff --git a/css/sunrise.css b/css/sunrise.css new file mode 100644 index 0000000..03ac479 --- /dev/null +++ b/css/sunrise.css @@ -0,0 +1,32 @@ +/* + +-------------------------------------------------------------------------+ + | Copyright (C) 2010-2022 Howard Jones | + | Copyright (C) 2022-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/ | + +-------------------------------------------------------------------------+ +*/ + +/* QuickTree graph action glyphs */ +.quicktreeAdd { + color: #4caf50; +} + +.quicktreeRemove { + color: #e06666; +} diff --git a/quicktree.php b/quicktree.php index c56d3b6..7c33a6d 100644 --- a/quicktree.php +++ b/quicktree.php @@ -350,8 +350,8 @@ ['' . __('Save To Branch', 'quicktree') . '', __('Save your selection as a branch to an existing tree so that they appear in a specific section of an existing tree.', 'quicktree')], ['' . __('Clear all graphs', 'quicktree') . '', __('Clear the Graphs on this page from the Graphs Queue so that you have a blank QuickTree ready for new selections', 'quicktree')], ['
' . __('You can manage the individual graphs that appear here by clicking:', 'quicktree')], - ['' . __('Add', 'quicktree'), __('This icon is next to a Graph on the %s tab.', '' . __('Graph View Page', 'quicktree') . '', 'quicktree')], - ['' . __('Delete', 'quicktree'), __('This icon next to the Graphs below to remove them from the QuickTree Queue.', 'quicktree')], + ['' . __('Add', 'quicktree'), __('This icon is next to a Graph on the %s tab.', '' . __('Graph View Page', 'quicktree') . '', 'quicktree')], + ['' . __('Delete', 'quicktree'), __('This icon next to the Graphs below to remove them from the QuickTree Queue.', 'quicktree')], ['
' . __('Note:', 'quicktree') . '
'], [__('Adding, removing or clearing on this page does not affect any other parts of Cacti (only Creating/Saving does)', 'quicktree')] ]; @@ -394,7 +394,7 @@ print ''; print '
' . $graph_title; print '  '; + . '" title="' . __esc('Remove This Graph From QuickTree', 'quicktree') . '">'; print '
'; diff --git a/setup.php b/setup.php index fefe5d6..b6269aa 100644 --- a/setup.php +++ b/setup.php @@ -216,7 +216,7 @@ function quicktree_graph_buttons($data): void { $local_graph_id = $data[1]['local_graph_id']; $rra_id = $data[1]['rra']; - print "
"; + print "
"; } } @@ -245,9 +245,12 @@ function quicktree_config_arrays(): void { /** * Hook implementation for Cacti's 'page_head' filter. Includes this - * plugin's JavaScript on every page, and its stylesheet specifically on - * quicktree.php. Called by Cacti core via api_plugin_hook('page_head', ...) - * while rendering the page section. + * plugin's JavaScript and stylesheets on every page. The base stylesheet + * and, when present, a stylesheet matching the user's selected theme are + * both loaded on every page because QuickTree's action glyphs are rendered + * on the graph view page as well as on quicktree.php. Called by Cacti core + * via api_plugin_hook('page_head', ...) while rendering the page + * section. * * @return void Outputs HTML directly. * @@ -257,12 +260,12 @@ function quicktree_config_arrays(): void { function quicktree_page_head(): void { global $config; - $page = get_current_page(); - print get_md5_include_js('plugins/quicktree/js/quicktree.js'); - if (strstr($page, 'quicktree.php') !== false) { - print get_md5_include_css('plugins/quicktree/css/quicktree.css'); + print get_md5_include_css('plugins/quicktree/css/quicktree.css'); + + if (file_exists($config['base_path'] . '/plugins/quicktree/css/' . get_selected_theme() . '.css')) { + print get_md5_include_css('plugins/quicktree/css/' . get_selected_theme() . '.css'); } } From f4514aca14665fa7a46da3f1a850bdcfefbe57dd Mon Sep 17 00:00:00 2001 From: Cacti Group Date: Mon, 5 Oct 2026 08:27:27 -0400 Subject: [PATCH 2/2] Add unit coverage for graph_buttons and page_head glyph changes The theme-glyph change touched quicktree_graph_buttons() (setup.php:219) and quicktree_page_head() (setup.php:265-268), which the patch-coverage gate flagged as uncovered. Add QuicktreeGraphButtonsTest and QuicktreePageHeadTest, plus get_md5_include_js/get_md5_include_css/get_selected_theme stubs in the unit bootstrap, to exercise both hooks. --- CHANGELOG.md | 1 + tests/Unit/QuicktreeGraphButtonsTest.php | 40 ++++++++++++ tests/Unit/QuicktreePageHeadTest.php | 77 ++++++++++++++++++++++++ tests/bootstrap-unit.php | 26 ++++++++ 4 files changed, 144 insertions(+) create mode 100644 tests/Unit/QuicktreeGraphButtonsTest.php create mode 100644 tests/Unit/QuicktreePageHeadTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b45a2be..a7bc205 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - issue: Fix quicktree_show_tab() building an invalid `?location=tabtab`/`?location=tabconsole` URL, an undefined-variable text-domain typo in the QuickTree page's "no graph specified" message, and a misspelled `qucktree` text domain - security: Migrate quicktree SQL helpers to prepared statements, normalize location handling, and ensure redirects terminate execution - test: Migrate test suite to Pest with a Cacti-provided test harness and CI workflow +- feature: Give the QuickTree add/remove graph glyphs their own theme-appropriate colors across every packaged Cacti theme, instead of reusing the core deviceUp/deviceDown classes --- 2.0 --- diff --git a/tests/Unit/QuicktreeGraphButtonsTest.php b/tests/Unit/QuicktreeGraphButtonsTest.php new file mode 100644 index 0000000..d74a8f7 --- /dev/null +++ b/tests/Unit/QuicktreeGraphButtonsTest.php @@ -0,0 +1,40 @@ + array('local_graph_id' => 42, 'rra' => 7))); + $output = ob_get_clean(); + + expect($output)->toContain('quicktreeAdd'); + expect($output)->toContain('fa-plus-circle'); + expect($output)->toContain('addQuickTree(42, 7)'); +}); + +it('prints nothing when the user is not authorized for the quicktree realm', function () { + $GLOBALS['__test_realm_auth'] = false; + + ob_start(); + quicktree_graph_buttons(array(1 => array('local_graph_id' => 42, 'rra' => 7))); + $output = ob_get_clean(); + + expect($output)->toBe(''); +}); diff --git a/tests/Unit/QuicktreePageHeadTest.php b/tests/Unit/QuicktreePageHeadTest.php new file mode 100644 index 0000000..377ca7d --- /dev/null +++ b/tests/Unit/QuicktreePageHeadTest.php @@ -0,0 +1,77 @@ +toContain('plugins/quicktree/js/quicktree.js'); + expect($output)->toContain('plugins/quicktree/css/quicktree.css'); +}); + +it('includes the theme stylesheet when a matching theme file exists', function () { + $base = sys_get_temp_dir() . '/qt_theme_' . uniqid(); + mkdir($base . '/plugins/quicktree/css', 0777, true); + file_put_contents($base . '/plugins/quicktree/css/modern.css', '/* test */'); + + $GLOBALS['__qt_tmp_base'] = $base; + $GLOBALS['config']['base_path'] = $base; + $GLOBALS['__test_selected_theme'] = 'modern'; + + ob_start(); + quicktree_page_head(); + $output = ob_get_clean(); + + expect($output)->toContain('plugins/quicktree/css/modern.css'); +}); + +it('omits the theme stylesheet when no matching theme file exists', function () { + $base = sys_get_temp_dir() . '/qt_theme_' . uniqid(); + mkdir($base . '/plugins/quicktree/css', 0777, true); + + $GLOBALS['__qt_tmp_base'] = $base; + $GLOBALS['config']['base_path'] = $base; + $GLOBALS['__test_selected_theme'] = 'no-such-theme'; + + ob_start(); + quicktree_page_head(); + $output = ob_get_clean(); + + expect($output)->not->toContain('no-such-theme'); + expect($output)->toContain('plugins/quicktree/css/quicktree.css'); +}); diff --git a/tests/bootstrap-unit.php b/tests/bootstrap-unit.php index e13c4e8..9a3fd9b 100644 --- a/tests/bootstrap-unit.php +++ b/tests/bootstrap-unit.php @@ -388,3 +388,29 @@ function form_end() { $GLOBALS['__form_wrapper_events'][] = 'form_end'; } } + +/* + * quicktree_page_head() emits the plugin's JS/CSS includes and selects a + * theme-specific stylesheet. These stubs return the asset paths verbatim so + * specs can assert which includes were printed, and let the selected theme be + * controlled per test. + */ +if (!function_exists('get_md5_include_js')) { + function get_md5_include_js($path) { + return ""; + } +} + +if (!function_exists('get_md5_include_css')) { + function get_md5_include_css($path) { + return ""; + } +} + +$GLOBALS['__test_selected_theme'] = 'modern'; + +if (!function_exists('get_selected_theme')) { + function get_selected_theme() { + return $GLOBALS['__test_selected_theme']; + } +}