Repository navigation
fix: repoint include/ -> includes/ plugin_hooks on every upgrade check so broken installs self-heal - #55
Merged
Conversation
The hook file repoint lived inside the version-change gate in plugin_evidence_upgrade_database(), so installs whose plugin_config.version was already bumped to the current version (but whose plugin_hooks rows were never repointed from the old include/ path) never got healed. With the old include/ directory still present this risks "Cannot redeclare ..." fatals from loading both include/<lib> and includes/<lib>; after deleting include/ it produces repeated "SECURITY ERROR: Attempted inclusion of invalid plugin file include/<lib>" because the stale hook rows point at a now-missing file. Run the idempotent repoint UPDATE unconditionally (before the version comparison) so broken installs self-heal on the next upgrade check. The WHERE ... file LIKE 'include/%' filter makes it a no-op on healthy installs. Mirrors the intropage fix (Cacti/plugin_intropage#410).
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The existing matching-version lifecycle test will fail until updated for the new unconditional database call.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Moves stale plugin hook repair outside the version gate so broken installations self-heal.
Changes:
- Repoints legacy
include/hook paths on every upgrade check. - Normalizes pruning-call indentation.
| File | Description |
|---|---|
includes/database.php |
Makes hook-path repair unconditional. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…e installs The repoint moved out of the version-change gate, so plugin_evidence_check_config() now issues the idempotent plugin_hooks UPDATE even when the stored version already matches. Update the lifecycle test to pin that contract (exactly one db call: the repoint) instead of asserting no work is done.
browniebraun
approved these changes
Oct 1, 2026
xmacan
approved these changes
Oct 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Carries the same fix as Cacti/plugin_intropage#410 over to
plugin_evidence, which has the identical pattern.When the plugin's library directory was renamed
include/->includes/,plugin_evidence_upgrade_database()gained a migration that repoints staleplugin_hooksrows from the old path to the new one:…but it sits inside the
if (!cacti_version_compare($oldv, $current, '='))version gate. On an install whoseplugin_config.versionwas already bumped to the current version without its hooks having been repointed, the gate is permanently closed and the repoint never runs again. That leaves the hook rows pointing atinclude/<file>:include/still on disk, loading bothinclude/<lib>andincludes/<lib>risksCannot redeclare ...fatals;include/is deleted, Cacti's plugin file-inclusion security check rejects every stale row withSECURITY ERROR: Attempted inclusion of invalid plugin file include/<lib> ....Fix
Run the idempotent repoint unconditionally, before the version comparison, so a broken install self-heals on the next upgrade check (reached via
plugin_evidence_check_config(), invoked by Cacti core directly rather than through the broken hook rows). TheWHERE ... file LIKE 'include/%'filter makes it a no-op on healthy installs. While here, the over-indentedevidence_prune_files();call inside the gate is normalized to the surrounding indentation.Scope / fleet review
I audited the other Cacti plugins that performed the same
include/->includes/move (aninclude/tombstone inmanifest.json):setup.php(never aninclude/<file>library path), so there are no stale hook rows to repoint and no failure. No change needed.plugin_tagslistsinclude/underexpected(it still ships that directory) rather thantombstones, so it never did this migration and is unaffected.Validation
includes/database.phpchanges; the repoint moves out of the version gate, no other logic is touched.file LIKE 'include/%', so the extraUPDATEis a no-op.include/...): the repoint now runs, clearing both the redeclaration fatal and theSECURITY ERRORfloods on the next page load.Note: I was unable to run
php -lin this environment; the change is a straight hoist of an existing statement plus an indentation normalization, reviewed by inspection.