Repository navigation
Conversation
Site\handle() read the option with get_option( $key, true, '' ). get_option() takes two arguments, so the third was ignored and the default was true. With nothing stored, the code then compared true with 'active' and set the flag inactive, which overrode the default of any site flag registered as active. Site\save() passed a PHP bool to update_option(). WordPress stores true as '1', which handle() never matches against 'active', and stores false as '' (or skips the write when no row exists), which handle() treats as unset. The sanitize callback registered in site-metabox.php hid this on admin-ajax.php only, because it runs once admin_init has fired. Code that sets the flag on the front end or in WP-CLI wrote the bare bool and lost the state. Read with '' as the default and write 'active' or 'inactive', as User\save() does, so the round trip no longer depends on the sanitize filter. Co-Authored-By: Claude <noreply@anthropic.com>
render() read the option with the same get_option( $key, true, '' ) call as Site\handle(), so a site flag that is active by default and has nothing stored showed as unchecked. Saving the General settings page for any reason then stored 'inactive' and switched the flag off. Site\handle() has already applied any stored value to the flag on init, so render the flag's own active state. Co-Authored-By: Claude <noreply@anthropic.com>
svandragt
marked this pull request as draft
October 16, 2026 13:01
svandragt
marked this pull request as ready for review
October 16, 2026 14:46
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.
Site-scoped flags lose their state in three ways. A flag registered as active by default starts inactive. A flag turned on by code outside wp-admin reads back as off on the next request. Saving Settings → General can switch off a flag that is active by default.
What changed
true, which never matched'active', so the flag was switched off.1'active'or'inactive', the same as user flags. Before, it stored a bool, which reads back as off. The admin bar toggle worked only because the settings sanitise callback converted the value onadmin-ajax.php. Code that set the flag on the front end or in WP-CLI lost the state.2'inactive'.3Test plan
'active' => true, and every check starts with nothing stored.5master'inactive'stored'1'stored'active'stored'inactive'stored'active'storedThe admin bar toggle already worked on
master, because the settings sanitise callback converts the value onadmin-ajax.php.Smoke output
Before:
active'1''active'/'inactive'After: every case reads back what was saved, and the default holds when nothing is stored.
This is independent of #26 (Lint PHP and report Composer package changes in CI) and #31 (Fix the WPCS code execution advisory and require PHP 8.2). If #31 merges first, this needs a rebase for return type spacing. The changed lines don't touch return types, so I expect no conflict.
Footnotes
get_option( $key, true, '' )→get_option( $key, '' )inSite\handle(),inc/site.php.get_option()takes two arguments, so the third was ignored. ↩update_option( $key, $value )→update_option( $key, $value ? 'active' : 'inactive' )inSite\save(). The sanitise callback isSiteMetabox\sanitize_value(), registered onadmin_init. ↩SiteMetabox\render()ininc/site-metabox.phpnow uses$flag->active, whichSite\handle()sets oninit. ↩The script stubs
get_option,update_optionand thesanitize_option_{$option}filter, then loadsinc/class-flag.php,inc/class-flags.phpandinc/site.php. It ran on PHP 8.2. ↩A must-use plugin registers the flag on
init. Each check runswp option delete _wp_flag_demofirst and readsactivein a newwp evalprocess. The admin bar check logs in, takes the toggle URL from the admin bar HTML and requests it. The Settings check submits the General form unchanged tooptions.php. ↩