From a3f89882829aff524e7f6ffb091fb5f82b3c8d8f Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 29 Sep 2026 21:22:28 -0400 Subject: [PATCH 01/18] Relocate schema + functions to includes/, add db_update_table upgrade Moves the plugin_maint_schedules/plugin_maint_hosts schema into a new includes/database.php (thold model) and functions.php into includes/functions.php. setup.php delegates via require_once; the is_device_in_maintenance hook now registers includes/functions.php. Implements plugin_maint_check_upgrade() to version-gate, refresh the schema via db_update_table() (string/backtick composite primaries normalized to arrays so db_update_table is safe), and update the full plugin_config row. Converts include/include_once to require/require_once. Tests updated for the moved paths. --- .github/copilot-instructions.md | 28 +++-- CHANGELOG.md | 1 + includes/database.php | 106 ++++++++++++++++ functions.php => includes/functions.php | 0 maint.php | 4 +- setup.php | 113 +++++++++++------- tests/Security/AuthGuardTest.php | 2 +- tests/Security/OutputEscapingTest.php | 6 +- .../PreparedStatementConsistencyTest.php | 4 +- tests/Security/RedirectSafetyTest.php | 2 +- tests/Unit/CheckHostTest.php | 2 +- tests/Unit/CheckScheduleTest.php | 2 +- .../MaintDeviceActionsAndDatabaseTest.php | 1 + tests/bootstrap-unit.php | 13 ++ 14 files changed, 222 insertions(+), 62 deletions(-) create mode 100644 includes/database.php rename functions.php => includes/functions.php (100%) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e408b48..aeb19c3 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -25,12 +25,14 @@ When generating code for this repository: ``` maint/ # Repository root (install to plugins/maint/ in Cacti) -├── locales/ # Internationalization files -├── functions.php # Runtime maintenance checks (plugin_maint_check_* -> plugin_maint_check_schedule) -├── maint.php # Main UI/controller: CRUD schedules, tabbed views, host associations -├── INFO # Plugin metadata (name, version, compat) +├── includes/ # Library/helper files, require_once'd from the entry points +│ ├── database.php # Schema management: table defs + create/upgrade helpers +│ └── functions.php # Runtime maintenance checks (plugin_maint_check_* -> plugin_maint_check_schedule) +├── locales/ # Internationalization files +├── maint.php # Main UI/controller: CRUD schedules, tabbed views, host associations +├── INFO # Plugin metadata (name, version, compat) ├── README.md -└── setup.php # Plugin entry points and hooks (menu, realms, device actions, maintenance hook) +└── setup.php # Plugin entry points and hooks (menu, realms, device actions, maintenance hook) ``` ## Naming Conventions @@ -77,7 +79,14 @@ arithmetic, strict `===` comparisons). ## Database Operations -Tables are created in `maint_setup_database()` via `api_plugin_db_table_create()`; `plugin_maint_check_schedule()` updates `stime`/`etime` for recurring schedules when windows pass, and schedule listing in `maint.php` uses it to compute "Active" state. +All schema management lives in `includes/database.php` (the thold model), not in `setup.php`. `setup.php`'s +install/upgrade paths `require_once($config['base_path'] . '/plugins/maint/includes/database.php')` and +delegate. Each table is defined once (`maint_schedules_table_data()`, `maint_hosts_table_data()`) and created +via `api_plugin_db_table_create('maint', ...)`; `plugin_maint_check_upgrade()` version-gates against +`plugin_config`, refreshes the schema through `maint_upgrade_tables()` (`db_update_table()` when the table +exists, create fallback when missing), and updates the full `plugin_config` row on a version change. +`plugin_maint_check_schedule()` (in `includes/functions.php`) updates `stime`/`etime` for recurring schedules +when windows pass, and schedule listing in `maint.php` uses it to compute "Active" state. ## Internationalization @@ -126,7 +135,7 @@ Document all changes via commit history; use descriptive commit messages referen - Translatable strings are managed with GNU gettext via `locales/build_gettext.sh`. `locales/po/cacti.pot` is the source template; Weblate owns syncing the per-language `.po`/`.mo` files from it. - **Never commit the per-language `.po` or compiled `.mo` files** (`locales/po/*.po`, `locales/LC_MESSAGES/*.mo`) in a plugin PR. Weblate is the sole owner of those catalogs, and regenerating them here produces spurious diffs and merge conflicts. `locales/po/cacti.pot` is the ONLY translation artifact a PR may add or modify. -- When a pull request adds or changes a string wrapped in `__()`/`__n()`/`__esc()`/`__x()`/`__xn()`/`__gettext()`, run `locales/build_gettext.sh` before pushing and stage `locales/po/cacti.pot` only. `build_gettext.sh` also rewrites the `.po`/`.mo` files as a side effect; revert those before committing (`git checkout -- locales/po/*.po locales/LC_MESSAGES`), or run only the `xgettext` step that targets `cacti.pot`. +- When a pull request adds or changes a string wrapped in `__()`/`__n()`/`__esc()`/`__x()`/`__xn()`/`__gettext()`, run `locales/build_gettext.sh` before pushing and stage `locales/po/cacti.pot` only. `build_gettext.sh` also rewrites the `.po`/`.mo` files as a side effect; revert those before committing (`git checkout -- locales/po/*.po locales/LC_MESSAGES`), or run only the `xgettext` step that targets `cacti.pot`. ## References @@ -150,6 +159,11 @@ existing code or adding new code, not just in dedicated cleanup passes: - **i18n text domain.** Every `__()`/`__esc()` call must include this plugin's text domain as the final argument, except when deliberately comparing against a literal, untranslated Cacti-core label. +- **File inclusion uses `require`/`require_once`.** Always use `require`/`require_once` (never + `include`/`include_once`) so a missing dependency fails fast and loudly. Keep library/helper files + (e.g. `functions.php`, `includes/database.php`) under `includes/` and reference them from that path; + entry points (`maint.php`, `setup.php`) stay in the plugin root. A hook registered for a function that + lives in `includes/functions.php` must pass `'includes/functions.php'` as its file argument. - **Plugin table-creation API.** Use `api_plugin_db_table_create()`/`api_plugin_db_add_column()` (from Cacti core's `lib/plugins.php`) instead of raw `CREATE TABLE`/`ALTER TABLE ... ADD COLUMN`. Both are idempotent (safe no-ops when already applied), so the same call can run unconditionally diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d1c76..f337f0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ --- develop --- +* refactor: Move schema management into includes/database.php (the thold model) and relocate functions.php into includes/; setup.php delegates via require_once, and plugin_maint_check_upgrade() now refreshes the schema via db_update_table() and updates the full plugin_config row on a version change. Switches every file inclusion from include/include_once to require/require_once * dev: Enforce patch coverage of changed lines in CI and remove the inert COMPOSER_ROOT_VERSION env from the Pest step * feature: Add a standard Cacti search filter to the Maintenance Schedules list that also matches the hostname/description/location/site name of associated Thold devices and the hostname/description of associated Servcheck tests * security: Add a version-safe CSP nonce (`plugin_maint_csp_nonce()`) to every inline `