12A: Answer the conflict questions before anything acts on them - #19
Open
nikolaystrikhar wants to merge 3 commits into
Open
12A: Answer the conflict questions before anything acts on them#19nikolaystrikhar wants to merge 3 commits into
nikolaystrikhar wants to merge 3 commits into
Conversation
Adds three classes that only report: Conflict\Detector (is a registered sub-plugin's standalone active), Conflict\Gatekeeper (may this request, and this user, have a conflict resolved) and Conflict\Redirector (which admin screen a resolved request should land on). None of them deactivates, queues or redirects; each is bound in the container and nothing calls them yet. Kept off Resolver_Interface deliberately: detection is a query, and a host rebinding the resolver should not be able to drop it by omission.
Closed
sanitize_key() narrowed "any action arg at all" to "any action that survives
sanitize_key": admin.php dispatches admin_action_{$action} on the raw value, so
an action named outside a-z0-9_- emptied to '' and the gate admitted the one
request it is most confident it refuses.
admin_url_for() branched on is_network_admin() alone while its own comment
promised all three admins, so a conflict resolved under /wp-admin/user/ threw
the user out onto a site's own screens.
The Gatekeeper docblock still measured the SSO race against plugins_loaded
priority 1, which its own test had already moved to 5.
Every new PHP file declares strict_types, so the rule arrives with the file rather than as a sweep over it afterwards. PR 21 covers everything that already existed on main.
d4mation
approved these changes
Aug 13, 2026
Comment on lines
+174
to
+176
| if ( is_user_admin() ) { | ||
| return user_admin_url( $screen ); | ||
| } |
There was a problem hiding this comment.
I don't know if this would ever actually be used in practice, but it is harmless and could account for a weird edge case we aren't considering I suppose.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What: adds
Conflict\Detector,Conflict\GatekeeperandConflict\Redirectorand binds all three in the container. No hook is wired here and nothing calls them yet; the step that does arrives in the PR above this one.Usage:
Why this way:
Detection is a query, so it stays off the resolver's contract — a host binding its own could otherwise answer "no conflict" and quietly disable the pass.
Two gate methods, because
user_may_resolve()pins the current user: asked unconditionally, an SSO plugin's visitors read as signed out on every admin request, so the cheap request gate turns away cron, WP-CLI and every POST first.On multisite the capability is
manage_network_plugins, by name —deactivate_plugins()acts network-wide, and core only widensactivate_pluginsinto it while the Plugins menu is off for sites.A
GETcarrying an action is refused along with every POST, sinceplugins.php?action=activateis the requestplugin_sandbox_scrape()replays. Any action arg at all, never a known-safe list.The redirector answers with the screen requested, not the referrer — only a validated basename and a re-encoded query leave it, with
admin_url(),network_admin_url()oruser_admin_url()in front.