Add support for the new meta.public flag - #10
Conversation
📝 WalkthroughWalkthroughThe ability command now exposes ChangesAbility metadata visibility and filtering
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
`filter_var()` with `FILTER_NULL_ON_FAILURE` returns null for an unparseable value such as `--show-in-rest=bogus`. The guard then skipped the comparison entirely, so the filter silently became a no-op and the command listed every registered ability. Asking to filter and receiving the full set back is worse than an error. Extract the parsing into `parse_bool_filter()` and fail with a clear message instead. `true`/`false`/`1`/`0`/`yes`/`no`, the bare flag, and `--no-show-in-rest` all keep working as before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162D8GNP2TsQyHUQKNoQv3a
WordPress 7.1 introduces `meta.public` as the high-level client exposure setting, with channel-specific flags taking precedence. Core resolves the cascade at registration, so `show_in_rest` already reports effective REST exposure -- but `meta.public` itself was invisible, and there was no way to tell whether REST exposure came from the high-level flag or the channel flag. Add `public` as an optional field on `list` and a default field on `get`, ordered before `show_in_rest`, plus a `--public=` filter on `list`. Add `meta` as an optional field on `get`, rendering the raw metadata as JSON the way `wp ability category get` already does. It is the only way to inspect channel-specific settings such as `mcp.public`, which no dedicated field covers. Nothing here reimplements the precedence rules, and `list` keeps reporting every registered ability regardless of exposure. WP-CLI runs with full trust; these flags are display and filter concerns, not access control. Fixes #9 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162D8GNP2TsQyHUQKNoQv3a
6c2fe89 to
b6922ba
Compare
There was a problem hiding this comment.
Pull request overview
Adds WP-CLI support for the new WordPress 7.1 meta.public ability flag so operators can see and filter on the high-level client exposure setting (and optionally inspect raw meta for channel-specific settings).
Changes:
- Adds
publicas a listable field (and default get field) plus a--public=<bool>filter onwp ability list. - Adds optional raw
metaoutput onwp ability getand emits a one-time debug note on WP < 7.1 whenpublicis declared but inert. - Extends Behat coverage for
public, filtering, raw meta inspection, and invalid boolean filter rejection.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/Ability_Command.php | Implements the new public field/filter, optional meta output, boolean filter parsing, and the WP<7.1 debug note. |
| features/ability.feature | Adds Behat scenarios covering public output/precedence, filtering, raw meta inspection, and invalid boolean values. |
Suppressed comments (1)
src/Ability_Command.php:713
format_ability_for_get()always calls$ability->get_meta()(and later JSON-encodes it) even thoughmetais documented as an optional field and is not included in$this->get_fields(the default output fields). This adds avoidable work on everywp ability getcall and can be noticeable if abilities carry large meta arrays.
/**
* Formats an ability for get output.
*
* @param WP_Ability $ability The ability object.
* @return array<string,mixed>
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
`FILTER_VALIDATE_BOOLEAN` treats an empty string as a valid `false`, so `--public=` and `--show-in-rest=` slipped past the new validation and quietly applied a false filter -- the same footgun the validation was added to close. Reject the empty value before parsing. The error message also claimed only `true` and `false` were accepted while the parser takes the full `FILTER_VALIDATE_BOOLEAN` set. List what is actually accepted rather than narrowing the parser, since `1`/`0` and `yes`/`no` are conventional in WP-CLI flags. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162D8GNP2TsQyHUQKNoQv3a
The `## AVAILABLE FIELDS` docs on both `list` and `get` already state that `public` has no effect before WordPress 7.1 and that it may therefore disagree with `show_in_rest`. That is where someone puzzled by the output will look; `WP_CLI::debug()` output only appears under `--debug`, which is not a flag you reach for when you do not yet know something is wrong. The helper also had a finite life by construction -- it could only ever fire on 6.9 and 7.0 -- while costing a version check and a pass over the displayed items on every run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162D8GNP2TsQyHUQKNoQv3a
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/Ability_Command.php`:
- Line 700: Update the ability output handling in src/Ability_Command.php at
lines 700-700 and 725-725, covering the paths used by wp ability list and wp
ability get. Add a once-per-command guard that inspects the raw meta.public
value and emits a debug notice before the public field is output; preserve the
existing public value conversion and ensure the notice is emitted only once
across both affected sites.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2d0fc88d-b57d-49ec-b9dd-18faf21b2114
📒 Files selected for processing (2)
features/ability.featuresrc/Ability_Command.php
🚧 Files skipped from review as they are similar to previous changes (1)
- features/ability.feature
Declaring `options: true/false` on `--public` and `--show-in-rest` lets
WP-CLI reject bad values in `Subcommand::validate_args()` before the
command runs, which is how `--format` in this same command already works.
That covers everything `parse_bool_filter()` was doing by hand, including
the empty-value case, so the helper and `filter_var()` both go away.
The accepted set narrows to `true` and `false`. `1`/`0`, `yes`/`no`,
`on`/`off` and the `--no-` prefix are no longer accepted -- `--no-public`
in particular now errors, since WP-CLI's loose `in_array()` check does
not match boolean false against the options list. The bare `--public`
form does still pass validation as boolean true, so the comparison
handles it explicitly rather than silently matching nothing.
Errors now come from WP-CLI in its standard form:
Error: Parameter errors:
Invalid value specified for 'public' (...)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162D8GNP2TsQyHUQKNoQv3a
`[--public]` and `[--show-in-rest]` are boolean flags, which is how WP-CLI models these. `Utils\get_flag_value()` then returns true for `--public`, false for `--no-public`, and null when absent, so the filter is a direct boolean comparison with no parsing, no validation code, and no `options` block in the synopsis. Removes the invalid-value scenario along with the parsing it covered, and switches the existing `--show-in-rest=true|false` scenario to the flag form. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162D8GNP2TsQyHUQKNoQv3a
Fixes #9.
WordPress 7.1 introduces
meta.publicas the high-level client exposure setting, with channel-specific flags taking precedence. Core resolves the cascade at registration, soshow_in_restalready reports effective REST exposure — butmeta.publicitself was invisible, and there was no way to tell whether REST exposure came from the high-level flag or the channel flag.What changed
publicis an optional field onlistand a default field onget, ordered beforeshow_in_rest.--public/--no-publicfilter onlist.metais an optional field onget, rendering raw metadata as JSON.list, andget— these generate the command reference pages, so they land here.Nothing reimplements the precedence rules, and
liststill reports every registered ability regardless of exposure. WP-CLI runs with full trust; these are display and filter concerns, not access control.Design decisions
publicrenders1/0, not tri-stateOpen question 1 asked whether
publicshould render1/0/empty the wayreadonlyand friends do throughformat_annotation(). It can't, and shouldn't pretend to.WP_Ability::prepare_properties()always materializes the flag:Core's own tests pin this down —
test_meta_public_defaults_to_false_when_unsetasserts the key is always present inget_meta(),test_meta_public_null_is_treated_as_unsetcollapses explicitnulltofalse, and anything non-boolean throws. "Never declared" and "declared false" are indistinguishable by the time the command sees the ability, so an empty rendering could only ever mean "old WordPress", which is misleading.The REST controller draws the same line: annotations are typed
array( 'boolean', 'null' ),publicis typed'boolean'.format_annotation()exists because$default_annotationsarenull;publicisn't in that category. It uses the same one-linershow_in_restalready does, which also keeps 6.9/7.0 sane where meta is unvalidated free-form.Documentation only for the 6.9/7.0 gap — no runtime note
Open question 2 asked whether a
WP_CLI::debug()note is worth it on versions where the flag is inert. It isn't. The## AVAILABLE FIELDSdocs on bothlistandgetstate thatpublichas no effect before 7.1 and may therefore disagree withshow_in_rest, and that is where someone puzzled by the output actually looks —--debugis not a flag you reach for before you know something is wrong.An earlier revision of this PR added a once-per-run debug note; it was removed in 49800b1. It could only ever fire on 6.9 and 7.0, so it was dead code by construction, and cost a version check plus a pass over the displayed items on every run to say something the docs already say.
metais optional onget, not defaultOpen question 3 proposed mirroring
wp ability category get, wheremetais a default field. This diverges deliberately: on 7.1 ability meta is{annotations, show_in_rest, public}plus channel keys, so a default column would duplicate five fields already rendered as their own rows, every call, on top of two JSON schema blobs. Category meta is default because a category has three other fields and meta is its only extensibility surface.Optional still keeps the escape hatch —
meta.mcp.publicand friends have no field of their own, and Core treats nested channel meta as first-class (_wp_get_abilities_match_meta()matches nested arrays;array( 'mcp' => array( 'public' => true ) )is the documented example). Worth notingmcpis not a Core-defined channel, which argues for a generic raw dump over any channel-specific field. Rendering matchesAbility_Category_Command::format_category_for_get()exactly. Not added tolist, where a JSON blob per row would wreck table output.The exposure filters are plain flags
[--public]and[--show-in-rest]are declared as boolean flags rather than=<bool>params.Utils\get_flag_value()returnstruefor--public,falsefor--no-public, andnullwhen absent, so each filter is a direct boolean comparison — no parsing, no validation code, nooptionsblock.Earlier revisions of this PR tried a hand-rolled
parse_bool_filter()(621cd5c, dc3d2db) and then declarativeoptions: true/false(2db8a66). Both are gone as of d2a444b; the flag form is how WP-CLI models booleans and needs none of it.Behavior change
--show-in-restpreviously took a value:--show-in-rest=true/=false. It is now a flag, so those forms become--show-in-rest/--no-show-in-rest. Since flag-type params do not validate their values, an old-style--show-in-rest=trueis accepted and then matches nothing rather than erroring — worth knowing if the released form is considered load-bearing.That also fixes a latent bug in the old parsing:
filter_var()withFILTER_NULL_ON_FAILUREreturnednullfor an unparseable value and the guard then skipped the comparison entirely, so--show-in-rest=bogussilently became a no-op and listed every registered ability.Notes
meta.public => truerendersshow_in_rest 1on 7.1 andshow_in_rest 0on 6.9/7.0, so output already tracked reachability. Adding thepublicfield is what creates the divergent-looking output, which the field documentation now covers.wp_get_abilities( $args )is deliberately not used. 7.1 added declarative filtering andarray( 'meta' => array( 'public' => true ) )looks like the obvious implementation. It's a trap: on 6.9/7.0 the function takes no parameters, PHP silently discards extra args to userland functions, and the command would return the entire unfiltered registry while claiming to have filtered. Filtering stays in the command loop.README.mdis untouched —regenerate-readme.ymlhandles it on merge tomain."public":"1"), matching the existingreadonly/show_in_restconvention rather than fixing it here.Testing
Three scenarios added to
features/ability.feature:publicseedingshow_in_rest, explicitshow_in_rest => falsewinning overpublic => true,--public/--no-publicfiltering, and rawmetashowing anmcpchannel key while staying out of default output. The exposure scenarios are tagged@require-wp-7.1; themetaone works on 6.9 and is tagged accordingly. The existingshow_in_restfilter scenario switches to the flag form.No other existing scenario changes behavior — every table and JSON assertion in the file is containment-style, and every exact
STDOUT should be:is a single--field=value.