Repository navigation
Comments: Add a capabilities object to comment types - #52
adamsilverstein wants to merge 17 commits into
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:
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
|
Follow-up: capability enforcement via This PR intentionally keeps the cap object advisory. Proposing the lowest-risk path to actual enforcement, mirroring
One question to settle before coding: do custom comment types keep deriving edit permission from the parent post, or get a permission boundary independent of it? That is the substantive design fork (the comment:19 concern). Happy to write this up on Trac #35214 if the direction looks right. |
Give `WP_Comment_Type` a `cap` object built from new `capability_type` and `capabilities` registration arguments, modeled on `WP_Post_Type` and `get_post_type_capabilities()`. A new `get_comment_type_capabilities()` helper builds the capability strings from the `capability_type` base (default 'comment'), so a registered type can describe its own read, edit, delete, and moderate capabilities. This is advisory metadata only: `map_meta_cap()` is intentionally not changed, so there is no behavior change. The built-in `comment` type resolves to the existing `edit_comment` and `moderate_comments` capabilities, preserving current behavior. Enforcing per-type capabilities through `map_meta_cap()` is left to a follow-up so the capability model can be agreed on first. See #35214.
Cover the new `capability_type`/`capabilities` arguments and the `get_comment_type_capabilities()` helper: default and custom capability types, array capability types with explicit plurals, the `capabilities` override, that the input `capabilities` array is not retained as a property, and that the built-in `comment` type stays backward compatible with the existing core capabilities. See #35214.
The existing tests spot-checked individual generated capabilities; read_comment, moderate_comment, and delete_comments were never asserted. Add a test pinning the complete meta and primitive capability set built by get_comment_type_capabilities() from a string base, plus a direct test of the array capability_type form (explicit plural). See #35214.
d2ee949 to
c4978f3
Compare
…e-caps # Conflicts: # src/wp-includes/class-wp-comment-type.php # src/wp-includes/comment.php # tests/phpunit/tests/comment/types.php
- Document that with the default 'comment' capability_type, most generated primitive capabilities exist in no default role and are not consulted by the default mapping: consumers should check meta capabilities with a comment ID, not the primitives. - Add the per-capability @return reference to get_comment_type_capabilities() (mirroring the post type version) and note that it normalizes the passed object's capability_type as a side effect. - Type WP_Comment_Type::$capability_type as string: set_props() collapses the array registration form to the singular base.
…e-caps # Conflicts: # src/wp-includes/class-wp-comment-type.php # src/wp-includes/comment.php # tests/phpunit/tests/comment/types.php
`get_comment_type_capabilities()` generated a `read_comment` meta capability alongside `edit_comment`, `delete_comment`, and `moderate_comment`, but `map_meta_cap()` has no case for it and none is planned with the enforcement follow-up. A consumer taking the documented advice - check the meta capabilities with a comment ID and let `map_meta_cap()` resolve them - would get a literal capability that no default role grants, so the check denies everyone including administrators, with no release in which that changes. Post types ship `read_post` from day one together with its mapping, so the parity argument does not carry to shipping one unmapped. Drop it from the generated set rather than document a capability that cannot work, and add a test pinning the omission so it is only reintroduced with its mapping. No behavior change for the built-in types: nothing in core reads `read_comment`.
…t lands. The "advisory metadata only, `map_meta_cap()` is not affected" warning lived on `WP_Comment_Type::$cap` and in `get_comment_type_capabilities()`, but not in the `register_comment_type()` argument docs, which is the surface a plugin author reads before passing `capability_type`. Someone registering a 'review' type and granting `edit_reviews` to a role could reasonably conclude that core's moderation and edit paths now require it for their type. They do not: anyone with `moderate_comments` can still edit, spam, approve, or delete those comments through every existing path. The risk is not the checks a plugin makes - those are fail-closed - it is the checks it skips believing core makes them, so the only fix available here is to say so where it will be read. Also qualify the "check the meta capabilities" advice, which only resolves for `edit_comment` on the default base today, and warn against reusing a post type's `capability_type`: a base of 'post' would send a comment ID through `map_meta_cap()`'s post branch.
…y overrides. The backward-compatibility claim for `pingback`, `trackback`, and `note` rested on all three registering without a `capability_type`, which nothing asserted: only the `comment` type's cap object was checked. Compare each built-in against it directly, so a future registration that quietly gives one of them its own base is caught. Also cover a `capabilities` override of a meta capability. Only primitive overrides were tested, and a type pointing `edit_comment` at a name `map_meta_cap()` already resolves is the one route to working per-type checks before enforcement lands.
…e-caps # Conflicts: # src/wp-includes/comment.php
The branch was written while trunk was 7.1-alpha; trunk is now 7.2-alpha, so the new capability_type and cap properties and get_comment_type_capabilities() carried @SInCE tags for a release that will never contain them, contradicting the 7.2.0 stamps on the rest of the class. Also close three documentation gaps the stamps review surfaced: the read_comment omission rationale claimed map_meta_cap() coverage as the bar while delete_comment and moderate_comment are advertised without cases, so it now rests on read having no per-comment semantics yet; the edit-only "others" axis is called out as deliberate so the missing delete_others_comments key reads as a decision rather than an oversight; and the three cap tests without @Covers annotations gain them. See #35214.
The docblocks for get_comment_type_capabilities(), the register_comment_type() arguments, and the WP_Comment_Type capability properties repeated the "advisory" caveat several times and carried design rationale (the edit-only "others" axis, which primitives default roles grant) that belongs in the ticket rather than the file. Keep what a caller needs: how the base builds the names, that they are not enforced yet, the post base collision, and the argument mutation. The "used outside of map_meta_cap()" inline comment is dropped, as nothing consults those primitives yet.
…tests. get_comment_type_capabilities() is new in 7.2.0, so it can declare its object argument and stdClass return natively without a back-compat cost; its only caller, WP_Comment_Type::set_props(), already passes an object. The new tests get `: void` and a typed data provider parameter to match the rest of the file.
…e-caps # Conflicts: # src/wp-includes/class-wp-comment-type.php
Trunk is in the 7.2 beta, so these additions can no longer ship in 7.2.0.
Stack: Custom Comment Types (#35214)
register_comment_type()registration API/wp/v2/comment-typesendpointmap_meta_cap()render_callbackdisplay callbackis_pingping groupingdefault_excluded_comment_typesfilterwp_update_comment_counts()recount helperWordPress#12311 and WordPress#12310 are on WordPress/wordpress-develop; the rest are fork PRs targeting their parent branch and will retarget to trunk as their base lands.
Description refreshed by Claude after another review:
Trac ticket: https://core.trac.wordpress.org/ticket/35214
AI Use
Claude Code did the typing here, I did the asking. I will review and test.