From b8359e236e831d8bc10bb128872c22c8ac81e7df Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 29 Sep 2026 21:14:15 -0400 Subject: [PATCH 01/12] Move functions.php into includes/ and use require/require_once Relocates the functions.php helper library into includes/ (updating cycle.php's reference and the moved file's own setup.php include to ../setup.php) and switches every file inclusion from include/include_once to require/require_once for fail-fast consistency. This plugin has no database schema, so there is no includes/database.php. --- .github/copilot-instructions.md | 21 +++++++++++++-------- cycle.php | 16 ++++++++-------- functions.php => includes/functions.php | 2 +- 3 files changed, 22 insertions(+), 17 deletions(-) rename functions.php => includes/functions.php (99%) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2c273fa..a444561 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -25,14 +25,15 @@ When generating code for this repository: ``` cycle/ # Repository root (install to plugins/cycle/ in Cacti) -├── images/ # UI icons -├── locales/ # Internationalization files -├── cycle.js # Client-side graph rotation logic -├── cycle.php # Main cycle viewer/administration UI -├── functions.php # Shared helper functions -├── INFO # Plugin metadata (name, version, compat) +├── includes/ # Library/helper files, require_once'd from the entry points +│ └── functions.php # Shared helper functions +├── images/ # UI icons +├── locales/ # Internationalization files +├── cycle.js # Client-side graph rotation logic +├── cycle.php # Main cycle viewer/administration UI +├── INFO # Plugin metadata (name, version, compat) ├── README.md -└── setup.php # Plugin install/uninstall/upgrade hooks +└── setup.php # Plugin install/uninstall/upgrade hooks ``` ## Naming Conventions @@ -143,7 +144,7 @@ Document all changes in `CHANGELOG.md`; use descriptive commit messages referenc - 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 @@ -168,6 +169,10 @@ 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`) under `includes/` and reference them from that path; entry points + (`cycle.php`, `setup.php`) stay in the plugin root. - **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/cycle.php b/cycle.php index 37b94c1..ba2942e 100644 --- a/cycle.php +++ b/cycle.php @@ -26,14 +26,14 @@ chdir('../../'); -include_once('./include/auth.php'); -include_once('./lib/time.php'); -include_once('./lib/html_tree.php'); -include_once('./lib/api_graph.php'); -include_once('./lib/api_tree.php'); -include_once('./lib/utility.php'); -include_once('./lib/api_data_source.php'); -include_once('./plugins/cycle/functions.php'); +require_once('./include/auth.php'); +require_once('./lib/time.php'); +require_once('./lib/html_tree.php'); +require_once('./lib/api_graph.php'); +require_once('./lib/api_tree.php'); +require_once('./lib/utility.php'); +require_once('./lib/api_data_source.php'); +require_once('./plugins/cycle/includes/functions.php'); set_default_action(); diff --git a/functions.php b/includes/functions.php similarity index 99% rename from functions.php rename to includes/functions.php index b7fd8b2..4b7b700 100644 --- a/functions.php +++ b/includes/functions.php @@ -22,7 +22,7 @@ +-------------------------------------------------------------------------+ */ -include_once(__DIR__ . '/setup.php'); +require_once(__DIR__ . '/../setup.php'); $graphs_ppage = [ 1 => __('%d Graph', 1, 'cycle'), From cdf029e28a46e746169a52d89f8c1010fe79d1c6 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 29 Sep 2026 22:27:31 -0400 Subject: [PATCH 02/12] CI: allowlist unmeasured cycle.php web entry point in patch-coverage --- tests/bin/patch-coverage.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/bin/patch-coverage.php b/tests/bin/patch-coverage.php index e65b53d..5b176c4 100644 --- a/tests/bin/patch-coverage.php +++ b/tests/bin/patch-coverage.php @@ -160,6 +160,7 @@ function changed_lines($base_ref) { * Empty by default; add entries per repository as the need arises. */ $unmeasured_allowlist = [ + 'cycle.php', // web UI entry point (chdir(../..) + require auth.php); not loadable in the isolated unit process ]; $unmeasured = array_values(array_diff(array_keys($changed), array_keys($measured))); $unexpected_unmeasured = array_values(array_diff($unmeasured, $unmeasured_allowlist)); From 00cc3b1d6dbe415144cf42045c3a4a9f696af6ec Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 29 Sep 2026 22:28:32 -0400 Subject: [PATCH 03/12] i18n: regenerate cacti.pot for functions.php -> includes/functions.php move --- locales/po/cacti.pot | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locales/po/cacti.pot b/locales/po/cacti.pot index 996019c..0d45bd1 100644 --- a/locales/po/cacti.pot +++ b/locales/po/cacti.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Cacti \n" "Report-Msgid-Bugs-To: developers@cacti.net\n" -"POT-Creation-Date: 2026-09-28 16:05-0400\n" +"POT-Creation-Date: 2026-09-29 22:28-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Cacti Developers >\n" "Language-Team: Cacti Developers \n" @@ -141,22 +141,22 @@ msgstr "" msgid "Cycle Graphs" msgstr "" -#: functions.php setup.php +#: includes/functions.php setup.php #, php-format msgid "%d Graph" msgstr "" -#: functions.php setup.php +#: includes/functions.php setup.php #, php-format msgid "%d Graphs" msgstr "" -#: functions.php setup.php +#: includes/functions.php setup.php #, php-format msgid "%d Column" msgstr "" -#: functions.php setup.php +#: includes/functions.php setup.php #, php-format msgid "%d Columns" msgstr "" From fb9305fd00ae97e97d53862e8d52c92ccb4575d6 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 29 Sep 2026 22:48:59 -0400 Subject: [PATCH 04/12] INFO: set compat to 1.2.32 --- INFO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INFO b/INFO index cd8fde6..3203864 100644 --- a/INFO +++ b/INFO @@ -26,5 +26,5 @@ longname = Cycle Graphs author = The Cacti Group email = homepage = http://www.cacti.net -compat = 1.1.22 +compat = 1.2.32 capabilities = online_view:1, online_mgmt:1, offline_view:0, offline_mgmt:0, remote_collect:0 From 50a398c75a3c9d9c27e92ca60da60c93b3a98328 Mon Sep 17 00:00:00 2001 From: TheWitness Date: Tue, 29 Sep 2026 23:28:54 -0400 Subject: [PATCH 05/12] docs: changelog entry for includes/functions.php relocation and require sweep --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 577ba13..c1ca5a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # ChangeLog --- develop --- +* dev: Relocate `functions.php` to `includes/functions.php` and convert every `include`/`include_once` to `require`/`require_once` for fail-fast loading * dev: Enforce patch coverage of changed lines in CI and remove the inert COMPOSER_ROOT_VERSION env from the Pest step * security: Add a version-safe CSP nonce (`plugin_cycle_csp_nonce()`) to every inline `