Comments: Allow comment types to register a display callback - #53
Comments: Allow comment types to register a display callback#53adamsilverstein wants to merge 9 commits into
Conversation
Add a `render_callback` argument to `register_comment_type()`, stored on `WP_Comment_Type`. When a comment's registered type defines one, `Walker_Comment` uses it to render that comment, receiving the same arguments as the `callback` argument of wp_list_comments() (the comment, the arguments, and the depth). This gives custom comment types control over their own display, as raised in the tracking ticket, without each type having to filter the walker. An explicit `callback` passed to wp_list_comments() still takes precedence, and built-in types set no callback, so there is no change to existing output. See #35214.
Cover the `render_callback` argument: that a registered type's callback renders its comments through `Walker_Comment`, that an explicit wp_list_comments() `callback` takes precedence, that a type without a callback renders normally, and that the property defaults to null and stores a provided callable. See #35214.
|
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 ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 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 |
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the 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. |
…ard. Add a test asserting the render_callback receives the comment, the arguments array, and the depth (the documented wp_list_comments() callback contract, previously only the comment was exercised), and a test that a non-callable render_callback is ignored via is_callable() and the comment renders normally. See #35214.
Walker_Comment prints the render_callback output verbatim, matching the existing wp_list_comments() `callback` contract. Note in both the WP_Comment_Type::$render_callback property and the register_comment_type() parameter docs that the callback is responsible for escaping its output.
…e-render-callback # Conflicts: # src/wp-includes/class-wp-comment-type.php # src/wp-includes/comment.php
…th tests. - State the full precedence chain (explicit wp_list_comments() 'callback', then 'render_callback', then default markup), the open-tag contract (output only the element opening; end_el() or 'end-callback' closes it after children), and the classic-theme-only scope (block themes never invoke Walker_Comment) in both the property and args docblocks. - Add the missing @SInCE 7.1.0 changelog entry to Walker_Comment::start_el(). - Fix the test callbacks, which echoed closed <li> elements: end_el() appends its own close, so the previous assertions passed while the markup contained stray closing tags. Assert the full element shape, pin end_el()'s close, and cover a threaded child rendering inside its parent's callback-opened element plus legacy empty-string types. - Document the render_comments() helper's $args parameter and drop cleanup-only unregister calls now handled by the test framework.
…e-render-callback # Conflicts: # src/wp-includes/comment.php
…tract. Three parts of the contract were left for a developer to infer: The callback opens the element that `Walker_Comment::end_el()` closes, and `end_el()` emits `</div>` or `</li>` depending on the `style` argument. The docs said "an unclosed `<li>` by default", which is true but reads as the whole story - a callback that always opens an `<li>` produces mismatched markup under `style => 'div'`. Say that the callback has to branch on `$args['style']`, the way the built-in `comment()` does. The name deliberately echoes `register_block_type()`, whose `render_callback` returns a string. This one is captured with an output buffer, so a return value is silently discarded. Say "must echo" rather than "output". Built-in types cannot be re-registered, but `set_props()` applies the registration args filters to them too, so `register_comment_type_args` can set a callback on 'comment', 'pingback', or 'trackback'. That is worth keeping - it grants no more than the `callback` argument of wp_list_comments() always has - so document it as the intended override path, along with the one consequence that is easy to miss: a callback on the 'comment' type replaces the walker's link stripping for pending comments.
…aths. The suite covered the default `<li>` style only, so nothing would catch a change that broke the pairing between a callback's opening tag and `end_el()`'s closing one under `style => 'div'`. Also pin the filter-based override of a built-in type. That path falls out of where `set_props()` applies the registration args filters, and is now documented as intended, so it needs a test to keep it from being tightened away as an oversight.
Description
Adds a
render_callbackargument toregister_comment_type()so a custom comment type can control how its comments are displayed in comment lists, addressing dshanske's request on the tracking ticket (#35214 comment:18) for "a way to register a callback to handle display that can still be overridden by the usual methods."What it adds
render_callbackregistration argument, stored onWP_Comment_Type(defaultnull).Walker_Comment::start_el()dispatches to a comment type'srender_callbackwhen one is set, passing the same arguments as the wp_list_comments()callback: the comment, the arguments array, and the depth.Precedence / non-breaking
callbackpassed towp_list_comments()still takes precedence (handled before the type callback).comment,pingback,trackback) set no callback, so their output is unchanged.Scope / boundary
Stacked on WordPress#12311 (the
register_comment_type()API) and targets that branch; it will be retargeted totrunkonce WordPress#12311 lands. This is item 3 of the remaining below-the-hood work on #35214.Item 4 (generalizing the remaining hard-coded
pingback/trackbackchecks inWalker_Commentandseparate_comments()) is intentionally not included: those checks encode a ping-vs-comment distinction the registry does not yet model, so generalizing them safely needs a dedicated "ping grouping" concept on the registration object and carries output-regression risk. It is better handled as its own focused PR.Testing
New coverage in
tests/phpunit/tests/comment/walker.phpandwpCommentType.php. PHPCS reports no new warnings on the changed files and PHPStan is clean.Review updates
wp_list_comments()'callback'wins, then the type'srender_callback, then the default markup.Walker_Comment::end_el()closes it after any children are rendered, the same contract aswp_list_comments()callbacks - and the classic-theme-only scope: block themes render comments through thecore/comment-templateblock and never invokeWalker_Comment.<li>elements, which produced stray closing tags the substring assertions missed. The tests now emit unclosed<li>elements and assert the full element shape includingend_el()'s close, plus a threaded-child test pinning the contract end to end.Following a second review pass over the stack, three more parts of the contract that were left to inference:
$args['style'].end_el()emits</div>understyle => 'div'and</li>otherwise. "An unclosed<li>by default" was accurate but read as the whole story, and a callback that always opens an<li>produces mismatched markup. Documented, and pinned with a test under thedivstyle - the suite previously only covered the default.register_block_type(), whoserender_callbackreturns a string. This one is captured with an output buffer, so a returned string is silently discarded. Now says so, with the contrast called out.set_props()appliesregister_comment_type_argsto_builtinregistrations too, so a plugin can set a callback oncomment,pingback, ortrackbackeven though re-registration is blocked. Worth keeping - it grants no more than thewp_list_comments()callbackargument always has - so it is now documented as the sanctioned override path and covered by a test, rather than left as an accident of where the filter sits. One consequence is called out in the docs: a callback on thecommenttype also replaces the walker's link stripping for pending comments.See #35214.
AI Use
Code and description both written with 🤖 Claude Code. I will review and test.