From 60fd4060f0d9e39a3b5730708d609463fa65ef15 Mon Sep 17 00:00:00 2001 From: TheWitness Date: Wed, 7 Oct 2026 09:29:40 -0400 Subject: [PATCH 1/4] servcheck: keep legend chips equal width using the longest label The status legend already used the chip design but with min-width:0, so chips could shrink below their labels (overflow) when the row got tight. servcheck_legend() now computes the longest label and emits it as a --servcheck-chip-min CSS variable (calc(ch + 1.5rem)); css/common.css uses it as a shared min-width (falling back to max-content), matching the Monitor/Thold/Syslog legends so chips stay equal width as the legend wraps. Added includes/functions.php to the coverage with no-op html_start_box/html_end_box bootstrap stubs and a new ServcheckLegendTest so the changed renderer lines are covered by the patch-coverage gate. --- CHANGELOG.md | 1 + css/common.css | 2 +- includes/functions.php | 8 ++++++- phpunit.xml | 1 + tests/Unit/ServcheckLegendTest.php | 38 ++++++++++++++++++++++++++++++ tests/bootstrap-unit.php | 10 ++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/Unit/ServcheckLegendTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 54c7d24..a73fbe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ --- develop --- +* dev: Keep the status-legend chips equal width (sized to the longest label) as the legend wraps responsively * dev: Measure CI coverage with xdebug instead of pcov so the plugin's own sources are instrumented (pcov auto-scopes to the Composer root and skipped cacti/plugins/, leaving the patch-coverage gate with nothing to measure) * dev: Enforce patch coverage of changed lines in CI and remove the inert COMPOSER_ROOT_VERSION env from the Pest step * feature: Add a configurable User-Agent setting for HTTP/HTTPS and other cURL based service checks, so outdated-browser blocking no longer rejects the plugin's requests diff --git a/css/common.css b/css/common.css index 14f75ea..84ec09e 100644 --- a/css/common.css +++ b/css/common.css @@ -79,7 +79,7 @@ .servcheck_legend .servcheck_legend_item { flex: 1 1 0; - min-width: 0; + min-width: var(--servcheck-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/includes/functions.php b/includes/functions.php index 66f8ba0..f75cd71 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -342,8 +342,14 @@ function servcheck_legend(): void { html_start_box('', '100%', false, 3, 'center', ''); + $chip_min = 0; + + foreach ($servcheck_states as $state) { + $chip_min = max($chip_min, mb_strlen($state)); + } + print ''; - print '
'; + print '
'; foreach ($servcheck_states as $index => $state) { print '
' . $state . '
'; diff --git a/phpunit.xml b/phpunit.xml index 20c6af8..9b0a582 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -28,6 +28,7 @@ setup.php + includes/functions.php diff --git a/tests/Unit/ServcheckLegendTest.php b/tests/Unit/ServcheckLegendTest.php new file mode 100644 index 0000000..0104fcf --- /dev/null +++ b/tests/Unit/ServcheckLegendTest.php @@ -0,0 +1,38 @@ +toContain('
' . $state . '
'); + } +}); diff --git a/tests/bootstrap-unit.php b/tests/bootstrap-unit.php index f831bba..6ef38d4 100644 --- a/tests/bootstrap-unit.php +++ b/tests/bootstrap-unit.php @@ -361,6 +361,16 @@ function form_input_validate($value, $name, $regex, $optional, $error) { } } +if (!function_exists('html_start_box')) { + function html_start_box($title = '', $width = '100%', $div = '', $cell_padding = 3, $align = 'center', $add_text = '') { + } +} + +if (!function_exists('html_end_box')) { + function html_end_box($trailing_br = true, $resizable = false) { + } +} + if (!function_exists('is_error_message')) { function is_error_message() { return false; From d6db7ec6130a60349c9cf3d7156071e909cc0cce Mon Sep 17 00:00:00 2001 From: TheWitness Date: Wed, 7 Oct 2026 10:17:12 -0400 Subject: [PATCH 2/4] servcheck: use CSS Grid for truly equal-width legend chips; assert exact chip min Follow-up on the longest-label chip work: the flex: 1 1 0 + flex-wrap layout distributes free space per wrapped line, so a partial last row stretched its chips wider than full rows. Switch .servcheck_legend to a grid (repeat(auto-fill, minmax(var(--servcheck-chip-min), 1fr))) so every chip shares an equal column across all rows. The test now asserts the exact calc(Nch + 1.5rem) value instead of just the calc( prefix. --- CHANGELOG.md | 4 ++-- css/common.css | 16 ++++++++-------- tests/Unit/ServcheckLegendTest.php | 7 ++++++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a73fbe5..efecf16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -# ChangeLog +# ChangeLog --- develop --- -* dev: Keep the status-legend chips equal width (sized to the longest label) as the legend wraps responsively +* dev: Keep the status-legend chips equal width (sized to the longest label, laid out as a CSS grid so chips stay equal across wrapped rows) as the legend wraps responsively * dev: Measure CI coverage with xdebug instead of pcov so the plugin's own sources are instrumented (pcov auto-scopes to the Composer root and skipped cacti/plugins/, leaving the patch-coverage gate with nothing to measure) * dev: Enforce patch coverage of changed lines in CI and remove the inert COMPOSER_ROOT_VERSION env from the Pest step * feature: Add a configurable User-Agent setting for HTTP/HTTPS and other cURL based service checks, so outdated-browser blocking no longer rejects the plugin's requests diff --git a/css/common.css b/css/common.css index 84ec09e..1925581 100644 --- a/css/common.css +++ b/css/common.css @@ -65,21 +65,21 @@ } /* - * Status legend footer. The items are laid out as an evenly sized, wrapping - * flex row (flex: 1 1 0 gives every chip the same width). A legend is a colour - * key, so the chips use their own solid, opaque colours with white text so they - * stay legible on every theme rather than inheriting the subtle row tints. + * Status legend footer. The items are laid out as a wrapping CSS grid whose + * columns share one width (seeded from the longest label via + * --servcheck-chip-min) so every chip is equal width across all rows. A legend + * is a colour key, so the chips use their own solid, opaque colours with white + * text so they stay legible on every theme rather than inheriting the subtle + * row tints. */ .servcheck_legend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(var(--servcheck-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .servcheck_legend .servcheck_legend_item { - flex: 1 1 0; - min-width: var(--servcheck-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/tests/Unit/ServcheckLegendTest.php b/tests/Unit/ServcheckLegendTest.php index 0104fcf..5239c0b 100644 --- a/tests/Unit/ServcheckLegendTest.php +++ b/tests/Unit/ServcheckLegendTest.php @@ -29,7 +29,12 @@ $states = $GLOBALS['servcheck_states']; - expect($output)->toContain('
'); expect(substr_count($output, 'servcheck_legend_item'))->toBe(count($states)); foreach ($states as $index => $state) { From ce519fc37797c4640a1fd4b2bdeccad2ee0299d4 Mon Sep 17 00:00:00 2001 From: TheWitness Date: Wed, 7 Oct 2026 10:27:36 -0400 Subject: [PATCH 3/4] servcheck: use auto-fit for the legend grid; add the full GPL header to the legend test Review follow-up (#129): auto-fit collapses empty tracks so chips fill the legend width on a single row while staying equal across wrapped rows. The new ServcheckLegendTest.php now carries the repository's standard GPL v2 header (matching CspNonceTest.php). --- css/common.css | 2 +- tests/Unit/ServcheckLegendTest.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/css/common.css b/css/common.css index 1925581..44d0951 100644 --- a/css/common.css +++ b/css/common.css @@ -74,7 +74,7 @@ */ .servcheck_legend { display: grid; - grid-template-columns: repeat(auto-fill, minmax(var(--servcheck-chip-min, 8ch), 1fr)); + grid-template-columns: repeat(auto-fit, minmax(var(--servcheck-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } diff --git a/tests/Unit/ServcheckLegendTest.php b/tests/Unit/ServcheckLegendTest.php index 5239c0b..72297a3 100644 --- a/tests/Unit/ServcheckLegendTest.php +++ b/tests/Unit/ServcheckLegendTest.php @@ -2,6 +2,23 @@ /* +-------------------------------------------------------------------------+ | Copyright (C) 2004-2026 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/ | +-------------------------------------------------------------------------+ */ From e5ab1586bfda5168250264edf86b47c408ba249a Mon Sep 17 00:00:00 2001 From: TheWitness Date: Wed, 7 Oct 2026 12:27:21 -0400 Subject: [PATCH 4/4] servcheck: escape status-legend chip labels at output Defence-in-depth: wrap the legend chip display text in html_escape() so markup or HTML entities in a translated label cannot alter the legend DOM. Applied consistently across the thold/monitor/servcheck/mactrack/syslog fleet legends. The chip-min sizing still measures the unescaped label length, so layout is unchanged. --- includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/functions.php b/includes/functions.php index f75cd71..73870d0 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -352,7 +352,7 @@ function servcheck_legend(): void { print '
'; foreach ($servcheck_states as $index => $state) { - print '
' . $state . '
'; + print '
' . html_escape($state) . '
'; } print '
';