Skip to content

chore: PHPStan level 8 typing pass + bugfixes - #66

Merged
bmfmancini merged 1 commit into
developfrom
chore/phpstan-level-8-typing
Sep 25, 2026
Merged

bmfmancini merged 1 commit into
developfrom
chore/phpstan-level-8-typing

Conversation

@TheWitness

Copy link
Copy Markdown
Member

Summary

PHPStan level 8 pass for plugin_maint, following the same process as the prior repos in this rollout. This repo was already extensively natively-typed (PHP 8 return types throughout every function) before this pass, so the work was almost entirely type-narrowing rather than adding new typing.

(a) Error count

PHPStan level 8: 28 -> 0 errors (after adding a handful of missing Cacti-core function/constant stubs to the scratch bootstrap: load_current_session_value, date_time_format, form_hidden_box, get_colored_device_status, MESSAGE_LEVEL_INFO).

(b) Genuine bugs fixed

No hard runtime bugs found this time (a small, already-clean repo) - fixes were all type-narrowing gaps that could theoretically surface as PHP warnings/notices on malformed data:

  • functions.php / setup.php: several if (!empty($x)) checks on db_fetch_row_prepared() results only narrow out the false half of the real array|bool return type - changed to is_array($x) && !empty($x) everywhere this pattern appeared (3 sites).
  • maint.php: two db_fetch_row_prepared() results were read via array offset ($list['name'], $maint_item_data['name']) without narrowing out the bool half first - added is_array($x) ? $x : [] narrowing plus a ?? '' fallback at each read site.
  • setup.php: plugin_maint_version()'s parse_ini_file() result is now guarded against a missing/malformed [info] section before the final return $info['info'];.

(c) Stubs added/verified

5 new scratch PHPStan bootstrap stubs sourced from Cacti/cacti's develop branch (load_current_session_value, date_time_format, form_hidden_box, get_colored_device_status, MESSAGE_LEVEL_INFO constant), plus the established reusable base set. Also widened html_header_checkbox's over-narrow array<string,mixed> stub param type to plain array (Cacti core's own docblock permits a flat list of column-name strings too, confirmed against lib/html.php's real implementation).

(d) Test result

Full Pest suite: 50 passed (161 assertions), run against the real 1.2.x host via bind-mount, unchanged before and after this pass. One test (SetupStructureTest) asserts the exact literal source text return $info['info'] is present in setup.php - restructured the parse_ini_file() hardening as an early-return guard (if (!isset($info['info']) || !is_array($info['info'])) { return []; }) rather than a ternary, so the guard and the test's literal-text assertion both hold. php-cs-fixer (Cacti develop config) and php -l both clean (no style changes needed at all - this repo's formatting was already fully compliant).

(e) Unresolved / flagged for maintainer judgement

None.

Files changed

functions.php, maint.php, setup.php, CHANGELOG.md, locales/po/cacti.pot (translation template refresh only; per-language .po files reverted to avoid Weblate churn).

Brings plugin_maint to PHPStan level 8 with 0 errors (28 -> 0, after
adding a handful of missing Cacti-core function/constant stubs). This
repo was already extensively natively-typed (PHP 8 return types
throughout) before this pass, so the work was almost entirely
type-narrowing fixes rather than adding new typing.

Fixes:
- functions.php / setup.php: several `if (!empty($x))` checks on
  `db_fetch_row_prepared()` results only narrow out the `false` half of
  the real `array|bool` return type, leaving bare `true` in the union
  (db_fetch_row_prepared can theoretically return literal `true`, though
  in practice it never does) - changed to `is_array($x) && !empty($x)`
  everywhere this pattern appeared.
- maint.php: two `db_fetch_row_prepared()` results were read via array
  offset (`$list['name']`, `$maint_item_data['name']`) without narrowing
  out the `bool` half first - added `is_array($x) ? $x : []` narrowing
  plus a `?? ''` fallback at each read site.
- setup.php: `plugin_maint_version()`'s `parse_ini_file()` result is now
  guarded against a missing/malformed `[info]` section before the final
  `return $info['info'];` (kept the exact original return statement text
  intact, since this repo's own SetupStructureTest asserts that literal
  source string is present - restructured as an early-return guard rather
  than a ternary, to satisfy both the type-safety fix and the existing
  test).

Also ran php-cs-fixer (already clean, no changes) and regenerated
locales/po/cacti.pot (reverted per-language .po churn, per this
rollout's established Weblate-ownership convention).

Full Pest suite: 50 passed (161 assertions), unchanged before/after.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

No unresolved issues were identified, and all approval assessments are positive.

Review effort: Lite
Findings: None

What changed in this PR

This PR completes a PHPStan level 8 typing pass, adding defensive handling for database and INI parsing results while refreshing documentation and translation metadata.

Changes:

  • Added safe array narrowing for database results.
  • Guarded missing or malformed plugin metadata.
  • Refreshed the changelog and gettext template.
File Description
setup.php Validates plugin metadata and database results.
maint.php Safely handles missing schedule rows and names.
locales/​po/​cacti.pot Updates generated source references.
functions.php Narrows schedule query results before use.
CHANGELOG.md Documents the PHPStan pass.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@bmfmancini
bmfmancini merged commit baa4efc into develop Sep 25, 2026
4 checks passed
@TheWitness
TheWitness deleted the chore/phpstan-level-8-typing branch October 20, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants