* INFO: set compat to 1.2.32
* docs: update Copilot instructions Cacti baseline to 1.2.32 (matches INFO compat)
* INFO: back off compat to 1.2.29
* Add manifest.json + upgrade-time file pruning
* Prune phpunit.xml on upgrade and ignore markdown-lint configs
phpunit.xml ships in the repo for CI but is a dev-only test artifact, so it
is removed from manifest.json 'expected', pruned from installs on upgrade
(like tests/), and excluded from the manifest drift check.
The retired markdown-lint configs (.mdlrc, .md_style.rb) are deleted, and
.md* is now ignored like .git*: protected from pruning and excluded from
drift if it reappears.
* Move thold_functions.php and thold_webapi.php into includes/; flatten css
The main threshold library becomes includes/functions.php and the web API
helper becomes includes/webapi.php; every caller (setup.php, includes/*, the
CLI/poller/notify entry points and the test suite) loads them from includes/.
Each per-theme stylesheet css/<theme>/main.css becomes css/<theme>.css so users
can drop their own css/<theme>.css into the css base, and the page_head hook
looks there. Old paths are tombstoned so existing installs drop the stale
copies on upgrade.
* Regenerate cacti.pot for the includes/ file relocations
Moving the plugin's library files into includes/ changed the source-reference
lines in the translation template; regenerate it so the 'Verify translation
template' CI check passes.
* Harden the hook-include test and make RPN integer ops explicit
The HookFunctionsIncludeTest invokes real hooks with placeholder input purely
to execute their relocated include_once lines; it now swallows engine
notices/warnings/deprecations during those calls (and restores the error
handler and config afterward) so it cannot trip the suite's failOnDeprecation
or leak state into other tests. The RPN % and ^ operators now cast their
operands to int explicitly, matching their long-standing integer-truncation
behaviour while silencing the implicit float-to-int conversion deprecation.
* Harden prune against tampered-manifest path traversal
The upgrade-time prune now rejects any tombstone containing '.'/'..' segments
(which could escape the plugin directory or resolve to its root) and treats
ancestors of whitelist entries as protected, so a tombstone on a parent
directory can no longer delete a whitelisted file beneath it.
* docs: update and align the Project Structure block
Point the structure tree at the relocated files (libraries now under
includes/, data files under docs/, stylesheets under css/) and align the
trailing '# ...' comments to a single column so they no longer drift right.
* docs/tests: standardize test header and correct manifest-contract notes
- Use the full license header (from the plugin's own setup.php) in
tests/Unit/PruneFilesTest.php instead of the abbreviated copyright banner.
- Document that the manifest drift check and the upgrade-time prune also
handle phpunit.xml and .md* files, matching the implemented behavior.
* refactor: rename prune helpers to the plugin-slug function prefix
The repository naming contract reserves the plugin_<name>_ prefix for plugin
lifecycle / hook-registration functions; all other functions use the plain
<name>_ prefix. Rename the internal upgrade helpers accordingly:
plugin_<name>_prune_files() -> <name>_prune_files()
plugin_<name>_rmtree() -> <name>_rmtree()
The call site, unit tests, and the copilot-instructions.md references are
updated to match. No behavioral change.
* chore: set the Cacti compatibility floor to 1.2.29
Align the compat metadata (and the contributor-guide references) with the
team decision to standardize the minimum supported Cacti version at 1.2.29;
the previously proposed 1.2.32 floor was not adopted.
---------
Co-authored-by: Copilot <copilot@users.noreply.github.com>
* refactor(thold): extract the notification delivery from the threshold check
Every send site resolved the notification list's format file, then mailed the
list unless it was empty or the threshold had been acknowledged. That pair is
now thold_mail_notification(), and the five sites whose shape matched exactly
call it.
The body is still built inside the guard rather than by the caller, because
composing it resolves the device's site and an empty recipient list should not
pay for a message nobody receives. The function returns the message so the
sites that mail a second list can reuse it as before.
One observable difference: where the primary list is empty, $message is now ''
rather than unset. The second mail already read that unset variable, so this
removes an undefined-variable read without changing what the mail contains.
thold_check_threshold() goes from 1378 lines to 1343.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: pin the alert-to-warning downgrade
A threshold already in alert whose reading falls back into the warning band
notifies a downgrade rather than a restoral. Reaching it needs both fail
counts at or above their triggers on the same poll, which none of the earlier
scenarios set up.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: remove orphaned evaluation context block
* ci: retry transient dependency downloads
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>