Skip to content

ci: pin the plugin floor to Cacti 1.2's, which is exactly PHP 8.0 - #373

Open
somethingwithproof wants to merge 2 commits into
Cacti:developfrom
somethingwithproof:chore/php-floor-guard
Open

ci: pin the plugin floor to Cacti 1.2's, which is exactly PHP 8.0#373
somethingwithproof wants to merge 2 commits into
Cacti:developfrom
somethingwithproof:chore/php-floor-guard

Conversation

@somethingwithproof

@somethingwithproof somethingwithproof commented Aug 20, 2026

Copy link
Copy Markdown
Member

INFO declares compat = 1.2.17, and nothing enforced what that implies.

The Cacti 1.2 floor is exactly PHP 8.0.0. Cacti 1.2 commits and ships include/vendor/composer/platform_check.php; autoload_real.php:25 requires it, and global.php:556 loads that autoloader at boot. It throws a RuntimeException when PHP_VERSION_ID < 80000. So a 1.2 install cannot boot below 8.0.

CACTI_PHP_VERSION_MINIMUM still says 5.4.0, but it is dead metadata. It appears exactly once in the whole 1.2 tree, at its own definition, and no code reads it. composer.json on 1.2.x agrees with the platform check at >=8.0.

So PHP 8.0 syntax and functions are correct here, and 8.1 and later are not. This PR makes the plugin match that exactly.

php80-floor CI job. Runs php -l under 8.0 over every runtime file, which rejects enums, readonly, never, first-class callables and pure intersection types exactly, with no pattern to maintain and no false positives. The existing matrix starts at 8.1, where all of those lint clean, so nothing could catch them before.

Php81FunctionGuardTest. php -l cannot see a call to a function that does not exist yet, so post-8.0 function names are checked separately: array_is_list, enum_exists, fsync, json_validate, mb_str_pad and the 8.4 array helpers. It walks tokens rather than raw text, so comments and string literals cannot trigger it; it skips function declarations so a polyfill does not flag itself; and it catches fully-qualified calls like \array_is_list().

This replaces Php74CompatibilityTest, which checked four hardcoded paths with regexes over raw file text. It was one major version too strict, banning str_contains() and match that 1.2 supports, while missing every runtime file outside its four, and it would have flagged the word match( inside a comment. Coverage goes from 4 files to all 28.

Two strpos() calls become str_contains() in include/functions.php, now that the floor is established. Both are exact substitutions.

Verification:

floor chain      global.php:556 -> vendor/autoload.php -> autoload_real.php:25
                 -> platform_check.php: throw if PHP_VERSION_ID < 80000
guard            28 runtime files, no post-8.0 calls
token walker     catches plain and \qualified calls; ignores comments,
                 string literals and polyfill declarations
php80-floor loop exits 1 and names the file on a syntax error
equivalence      strpos(...)!==false and str_contains agree on all cases tested
php -l           clean, whole tree
workflow         parses, two jobs

Raised separately, because neither belongs here: no CI job runs the Pest suite at all, and composer.json has no scripts block although the workflow calls composer run-script lint.

Copilot AI lite review requested due to automatic review settings August 20, 2026 02:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR strengthens the plugin’s declared Cacti 1.2 compatibility by enforcing an effective PHP 7.4 syntax floor in CI (via PHP 7.4 linting), and replaces a brittle regex-based PHP compatibility test with a token-based guard that scans all runtime PHP files for PHP 8-only function calls.

Changes:

  • Add a dedicated php74-floor CI job that runs php -l under PHP 7.4 across all non-test, non-vendor PHP files.
  • Replace the removed Php74CompatibilityTest with a new token-walking Php80FunctionGuardTest that scans the runtime tree for PHP 8-only function calls.
  • Update several security tests’ string-prefix/contains checks to use str_starts_with / str_contains.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.github/workflows/plugin-ci-workflow.yml Adds the php74-floor job to enforce PHP 7.4 syntax compatibility via linting.
tests/Security/AuthGuardTest.php Refactors prefix/substring checks to PHP 8 string helpers.
tests/Security/OutputEscapingTest.php Refactors comment detection / substring checks to PHP 8 string helpers.
tests/Security/PreparedStatementConsistencyTest.php Refactors comment-line detection to str_starts_with.
tests/Security/Php74CompatibilityTest.php Removes the prior regex-based PHP compatibility test.
tests/Security/Php80FunctionGuardTest.php Adds token-based scanning of runtime PHP files for PHP 8-only function calls.
Suppressed comments (1)

tests/Security/Php80FunctionGuardTest.php:67

  • The token walker will currently flag method/static calls like Foo::str_contains() as “PHP 8 function calls”, and it can also misclassify function &str_contains(...) as a call because & sits between T_FUNCTION and the name. Skipping ::/->/new contexts and ignoring & while searching backwards avoids these false positives.
			for ($back = $index - 1; $back >= 0; $back--) {
				$prior = $tokens[$back];

				if (is_array($prior) && in_array($prior[0], [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT], true)) {
					continue;

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

Comment thread tests/Security/Php81FunctionGuardTest.php
1.2 ships include/vendor/composer/platform_check.php and reaches it from
global.php at boot, so it throws below PHP_VERSION_ID 80000; the 5.4.0 in
CACTI_PHP_VERSION_MINIMUM is read by nothing.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
@somethingwithproof somethingwithproof changed the title ci: gate the PHP 7.4 floor that INFO's 1.2 compat implies ci: pin the plugin floor to Cacti 1.2's, which is exactly PHP 8.0 Aug 20, 2026
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
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.

2 participants