Repository navigation
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Props Bot commandsYou can trigger Props Bot actions by commenting on this PR:
|
This comment has been minimized.
This comment has been minimized.
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
…ve the baseline. `$parent_file` is hard-coded to the string `'themes.php'` earlier in this file and never reassigned, so `empty( $parent_file )` can never be true. Drop the always-false clause; the condition reduces to the half that was actually reachable, regardless of $self's value. This also removes the file's only reference to $self, retiring its `variable.undefined` baseline entry. $self is not actually dead: it's set in wp-admin/menu-header.php, required transitively via wp-admin/admin-header.php earlier in this same file. PHPStan's single-file analysis can't see across that require chain -- the same reason it can't see $submenu's definition in wp-admin/menu.php. The baseline entry's retirement is incidental to removing the unreachable clause, not a fix to a real bug. See #65817.
eb7356b to
2a0ba8b
Compare
Removing the always-false clause also removed the file's only empty( $parent_file ) call, which had its own, separate baseline entry under the empty.variable identifier. That entry is now stale since the error it describes no longer occurs. See #65817.
…als. Reverts the logic change from 2a0ba8b, which removed the `0 === strcmp( $self, $item[2] ) && empty( $parent_file )` branch on the premise that `$parent_file` is never reassigned after being set to 'themes.php'. That premise is wrong: wp-admin/menu-header.php, loaded via admin-header.php, passes `$parent_file` through the `parent_file` filter (and `$self` is derived there from PHP_SELF), so the branch is reachable at runtime. PHPStan cannot follow globals across the require chain, so it inferred the literal 'themes.php' and reported the condition as always false. An inline `@var` does not help, since `treatPhpDocTypesAsCertain: false` makes those rules use the native type. Instead, a `global $self, $parent_file;` statement with `@global` tags after the admin-header.php require resets their native types, which clears `booleanAnd.alwaysFalse`, `empty.variable`, `booleanAnd.leftAlwaysTrue`, and the `$self` `variable.undefined` error without changing behavior. The now-stale `booleanAnd.leftAlwaysTrue` baseline entry for themes.php is removed. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: f160029d-7c28-4d44-9016-a98aa4606cdc
`$submenu` is built in wp-admin/menu.php, loaded via admin.php, so PHPStan could not see it and treated it as possibly undefined and `mixed`. Adding it to the file-scope `global` statement, with an `@global` tag describing its structure (submenu items keyed by parent slug and position, each a list of menu title, capability, and slug, plus an optional page title and classes), clears the `mixed` errors throughout the Appearance submenu loop. The now-stale `$submenu might not be defined` baseline entry for themes.php is removed. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: f160029d-7c28-4d44-9016-a98aa4606cdc
On the Themes screen, `$self` and `$parent_file` are both 'themes.php', which the loop skips via `$forbidden_paths`, so in stock core no button ever gets the `current` class. The condition is only reachable when a plugin changes `$parent_file` through the `parent_file` filter. Note this in the comment, so the branch is not mistaken for dead code again. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: f160029d-7c28-4d44-9016-a98aa4606cdc
This reverts b010970. The branch now leaves the condition's code unchanged from trunk, so the explanation is not needed. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Code-Session-Id: f160029d-7c28-4d44-9016-a98aa4606cdc
In `themes.php`, PHPStan only knew `$parent_file` as the `'themes.php'` literal assigned earlier in the file, so it reported the `empty( $parent_file )` clause of the Appearance submenu condition as never true. That is a false positive: `wp-admin/menu-header.php`, loaded via `admin-header.php`, passes `$parent_file` through the `parent_file` filter, and it also sets `$self`, while `$submenu` comes from `wp-admin/menu.php`. None of these are visible to PHPStan across the `require` chain. The condition is therefore left unchanged, and the globals are instead declared with a file-scope `global` statement and `@global` tags. An inline `@var` would not suffice, since with `treatPhpDocTypesAsCertain` disabled the always-true and always-false rules use the native type, which only the `global` statement resets. This retires the `booleanAnd.alwaysFalse` baseline along with the remaining baseline entries for `themes.php`, and the `$submenu` array shape also resolves the `mixed` errors in the submenu loop at higher rule levels. Developed in #15478. Follow-up to r63019, r63023. Props bgturner, westonruter. See #65817. git-svn-id: https://develop.svn.wordpress.org/trunk@65282 602fd350-edb4-49c9-b593-d223f7449a82
In `themes.php`, PHPStan only knew `$parent_file` as the `'themes.php'` literal assigned earlier in the file, so it reported the `empty( $parent_file )` clause of the Appearance submenu condition as never true. That is a false positive: `wp-admin/menu-header.php`, loaded via `admin-header.php`, passes `$parent_file` through the `parent_file` filter, and it also sets `$self`, while `$submenu` comes from `wp-admin/menu.php`. None of these are visible to PHPStan across the `require` chain. The condition is therefore left unchanged, and the globals are instead declared with a file-scope `global` statement and `@global` tags. An inline `@var` would not suffice, since with `treatPhpDocTypesAsCertain` disabled the always-true and always-false rules use the native type, which only the `global` statement resets. This retires the `booleanAnd.alwaysFalse` baseline along with the remaining baseline entries for `themes.php`, and the `$submenu` array shape also resolves the `mixed` errors in the submenu loop at higher rule levels. Developed in WordPress/wordpress-develop#15478. Follow-up to r63019, r63023. Props bgturner, westonruter. See #65817. Built from https://develop.svn.wordpress.org/trunk@65282 git-svn-id: http://core.svn.wordpress.org/trunk@64431 1a063a9b-81f0-0310-95a4-ce76da25c4cd
✅ Committed in r65282 (e5cb560).
Fixes the only
booleanAnd.alwaysFalsePHPStan error, insrc/wp-admin/themes.php, by declaring the admin globals that the file reads, rather than by changing the condition. The baseline file for the identifier is removed.PHPStan saw
$parent_fileonly as the literal'themes.php'assigned earlier in the file, so it reportedempty( $parent_file )as never true. That is a false positive:wp-admin/menu-header.php, whichwp-admin/admin-header.phploads, passes$parent_filethrough theparent_filefilter, so a plugin can make it empty and reach the first clause. Likewise$selfis set inmenu-header.php, and$submenuinwp-admin/menu.php, neither of which PHPStan follows across therequirechain.The condition is therefore left exactly as it is in trunk. After the
admin-header.phprequire, the file now declares the globals with a file-scopeglobalstatement:An inline
@varis not enough here: withtreatPhpDocTypesAsCertain: false, the always-true/false rules use the native type, which only theglobalstatement resets. The@globaltags are then applied bytests/phpstan/GlobalDocBlockVisitor.php.Baseline entries removed for
themes.php:booleanAnd.alwaysFalse(the whole baseline file, and itsincludesentry inphpstan.neon.dist)booleanAnd.leftAlwaysTrueempty.variablefor$parent_filevariable.undefinedfor$selfand$submenuWith the
$submenushape, the level 10mixederrors in the Appearance submenu loop are also gone.themes.phpno longer has any baseline entries.Original description
Fixes the only
booleanAnd.alwaysFalseerror and removestests/phpstan/baselines/booleanAnd.alwaysFalse.neon.The error
$parent_fileis assigned once, earlier in this file, to the literal string'themes.php', and never reassigned before this line. Soempty( $parent_file )can never be true, and the first half of the||--0 === strcmp( $self, $item[2] ) && empty( $parent_file )-- can never be true either, regardless of what $self is.The fix
Drop the always-false clause. The condition reduces to the half that was actually reachable:
$parent_file && $item[2] === $parent_file.This removes the file's only reference to
$self, which also retires avariable.undefinedbaseline entry for it. To be precise about why:$selfis not dead or unassigned code -- it's a legitimate WordPress admin global, set inwp-admin/menu-header.php(required transitively viawp-admin/admin-header.php, itself required earlier in this same file). PHPStan's single-file analysis can't see across that require chain, the same way it can't see$submenu's definition inwp-admin/menu.php. Removing the reference is safe not because $self was unused, but because the clause it was part of is unreachable regardless of $self's value (see verification below) -- its removal from thevariable.undefinedbaseline is an incidental consequence, not a fix to a real bug.Verification
Since this is top-level script code (not a function) gated behind capability checks and
wp_die(), it isn't practically unit-testable without fully bootstrapping an admin page render. Instead, since$parent_fileis a fixed constant here, the whole expression reduces to a function of just$selfand$item[2]. I exhaustively compared the old and new expressions across representative values of both, including $self's real runtime value ('themes.php') and the values Intelephense/PHPStan would assume if genuinely unset -- all agree:Also ran the full
admintest group (1910 tests) with no regressions.Trac ticket: https://core.trac.wordpress.org/ticket/65817
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): The original commits (2a0ba8b and 25c18e3) do not record a model; Claude Opus 5.5 (medium and high effort) for the follow-up commits.
Used for: The original commits were authored with Claude Code. The follow-up commits, which restore the original condition and declare the globals, were written with Claude Code, along with a code review of the branch and this description; the changes were reviewed and directed by a human contributor.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.