diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 07a9305..20edbcb 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -26,26 +26,26 @@ When generating code for this repository: ## Project Structure ``` -gpsmap/ # Repository root (install to plugins/gpsmap/ in Cacti) -├── class/ # Supporting PHP classes +gpsmap/ # Repository root (install to plugins/gpsmap/ in Cacti) +├── class/ # Supporting PHP classes ├── includes/ │ ├── setup/ -│ │ ├── tabs.php # top_header_tabs / top_graph_header_tabs callback -│ │ ├── settings.php # config_arrays/config_settings/draw_navigation_text/api_device_save -│ │ └── database.php # gpsmap_setup_database() / gpsmap_upgrade_database() -│ └── polling.php # poller_bottom callback, writes map XML/KML/HTML -├── images/ # Marker icons (Green/Orange/Red) -├── js/ # GPSMaps.js, infobubble.js -├── locales/ # Internationalization files -├── tests/ # Test suite -├── XML/ # Poller-generated map artifacts (all.xml, all.kml, all-top.html) -├── gpsmap.php # Main map view page +│ │ ├── tabs.php # top_header_tabs / top_graph_header_tabs callback +│ │ ├── settings.php # config_arrays/config_settings/draw_navigation_text/api_device_save +│ │ └── database.php # gpsmap_setup_database() / gpsmap_upgrade_database() +│ └── polling.php # poller_bottom callback, writes map XML/KML/HTML +├── images/ # Marker icons (Green/Orange/Red) +├── js/ # GPSMaps.js, infobubble.js +├── locales/ # Internationalization files +├── tests/ # Test suite +├── XML/ # Poller-generated map artifacts (all.xml, all.kml, all-top.html) +├── gpsmap.php # Main map view page ├── gpsmap_security.php # Access/permission helpers -├── gpstemplates.php # Map template administration -├── print.php # Print-friendly map view -├── INFO # Plugin metadata (name, version, compat) +├── gpstemplates.php # Map template administration +├── print.php # Print-friendly map view +├── INFO # Plugin metadata (name, version, compat) ├── README.md -└── setup.php # Plugin install/uninstall/upgrade hooks +└── setup.php # Plugin install/uninstall/upgrade hooks ``` ## Naming Conventions @@ -134,7 +134,7 @@ function gpsmap_check_upgrade() { $old = read_config_option('plugin_gpsmap_version', TRUE); if ($current != $old) { - include_once($config['base_path'] . '/plugins/gpsmap/includes/setup/database.php'); + require_once($config['base_path'] . '/plugins/gpsmap/includes/setup/database.php'); gpsmap_upgrade_database(); } } @@ -244,6 +244,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. This plugin already keeps + its library/helper code under `includes/` (schema in `includes/setup/database.php`); reference + plugin files from there. - **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 @@ -252,3 +256,7 @@ existing code or adding new code, not just in dedicated cleanup passes: line, `@param` lines, a blank comment line, then `@return`. Infer parameter/return types from actual usage; don't change the function's real type-hints in the same pass (let static analysis flag mismatches separately). Skip vendored third-party library files. + +## File manifest & upgrade pruning + +The plugin ships a root `manifest.json` with three arrays: `tombstones` (files/directories older versions shipped that have since moved or been removed), `expected` (the top-level files and directories that ship today, directories written with a trailing `/`), and `whitelist` (paths holding user data that must never be touched). Keep `expected` current: CI runs `tests/bin/validate-manifest.php`, which fails on any drift between `expected` and the real top-level tree (it ignores `tests/`, `phpunit.xml`, `.git*`, `.md*`, and whitelisted paths). Custom customer CSS/theme files belong in `expected`, and stylesheets live in `css/` (not `themes/`). On upgrade, `gpsmap_prune_files()` deletes the tombstoned paths, the dev-only `tests/` tree, and the `phpunit.xml` test config, leaves `whitelist`, `.git*`, and `.md*` alone, and logs (without removing) any top-level entry the manifest does not account for. As a safety measure it refuses any tombstone that resolves outside the plugin directory (a tampered manifest.json) and logs a warning for any file or directory it cannot remove. When you move or delete a shipped file, add its old path to `tombstones` and update `expected` in the same change. diff --git a/.github/workflows/plugin-ci-workflow.yml b/.github/workflows/plugin-ci-workflow.yml index 7696e88..ccb467b 100644 --- a/.github/workflows/plugin-ci-workflow.yml +++ b/.github/workflows/plugin-ci-workflow.yml @@ -83,6 +83,9 @@ jobs: - name: Check PHP version run: php -v + - name: Validate plugin manifest (expected-file drift) + run: php cacti/plugins/gpsmap/tests/bin/validate-manifest.php + - name: Run apt-get update run: sudo apt-get update diff --git a/.mdlrc b/.mdlrc deleted file mode 100644 index 2f92946..0000000 --- a/.mdlrc +++ /dev/null @@ -1,3 +0,0 @@ -# mdl cli configuration -style ".mdl_style.rb" -verbose false diff --git a/CHANGELOG.md b/CHANGELOG.md index 9070f82..79dabfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Changelog --- develop --- +* refactor: Switch every file inclusion from include/include_once to require/require_once for fail-fast consistency (schema already lives in includes/setup/database.php via the plugin table API, so no schema changes were needed) * 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 * security: Add a version-safe CSP nonce (`plugin_gpsmap_csp_nonce()`) to every inline `