Skip to content

Comments: Generalize ping handling with an is_ping comment type flag (Trac #35214) - #54

Open
adamsilverstein wants to merge 9 commits into
feature/comment-type-render-callbackfrom
feature/comment-type-ping-grouping
Open

Comments: Generalize ping handling with an is_ping comment type flag (Trac #35214)#54
adamsilverstein wants to merge 9 commits into
feature/comment-type-render-callbackfrom
feature/comment-type-ping-grouping

Conversation

@adamsilverstein

@adamsilverstein adamsilverstein commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Summary

This is item 4 of the Trac #35214 "below the hood" follow-up work: generalizing the hard-coded pingback/trackback handling so registered comment types can opt into ping behaviour.

Previously, pingbacks and trackbacks were singled out by hard-coded comment_type string comparisons:

  • separate_comments() bucketed 'pingback'/'trackback' into the 'pings' group via if ( 'trackback' === $type || 'pingback' === $type ).
  • Walker_Comment::start_el() rendered the compact ping markup via if ( ( 'pingback' === ... || 'trackback' === ... ) && $args['short_ping'] ).
  • WP_Comment_Query expanded a 'pings' type token to ['pingback','trackback'].

None of these could be expressed by a registered comment type, so a plugin registering (say) a webmention type could not be grouped, queried, or rendered as a ping.

What changed

  • WP_Comment_Type::$is_ping (default false) - a new flag marking a type as a ping (a notification from another site) rather than a human-authored comment.
  • The built-in pingback and trackback types are registered with 'is_ping' => true.
  • separate_comments() now groups any registered ping type into the pings bucket.
  • Walker_Comment::start_el() now renders any registered ping type with the compact ping markup (reusing the comment type object it already looks up for render_callback).
  • WP_Comment_Query now expands a 'pings' type to every registered ping type.

Built-in behaviour is unchanged: pingback/trackback still group, query, and render exactly as before, and the default comment/note types are not pings.

Review updates

Following a review pass over the stack:

  • The query side landed here rather than as a follow-up. An earlier draft left WP_Comment_Query( 'type' => 'pings' ) on the built-in pair, which meant a theme reading $wp_query->comments_by_type['pings'] and a plugin calling get_comments( array( 'type' => 'pings' ) ) would disagree about which comments are pings. Rather than ship that window in a stable release, 'pings' now expands from the registry on both sides.

    The resolved set goes into the comment query cache key: which types are pings depends on what is registered, that changes when a plugin is activated, and the comment last_changed salt only moves when a comment does. Without it a 'pings' query would keep serving results cached from before the type existed. There is a test for exactly that.

  • A registered ping type is now labeled with its own name. Walker_Comment::ping() prints a literal "Pingback:", which has been imprecise since 3.6 when trackbacks started sharing the markup. Once any type can opt in, "Pingback: example.com" for a webmention is plainly wrong for the audience this flag is for. Registered non-built-in types use their singular_name, matching what comment_type() already does; the built-ins keep the literal string so their markup is byte-identical.

    The existing test asserted 'Pingback:' for a webmention, which pinned the wrong label, so it was replaced by one test for the compact shape (label, author link, no comment body) and one for the label itself.

  • The is_ping docs now say where the flag stops. It drives grouping, querying, and display. It does not reach validation, default comment status, or notification emails - those still key on the pingback and trackback type names, so a custom ping type gains none of their handling and, just as importantly, none of their bypasses.

  • New test: the end-to-end case the suite was missing, wp_list_comments() with type => 'pings' listing a registered ping type, which is where a theme actually meets the grouping change.

The pings type name is reserved against registration in #12311, so a type literally named pings can no longer collide with the meta bucket.

Still out of scope

  • check_comment() author/email validation skip for pings, get_default_comment_status() ping status mapping, wp_notify_postauthor() / wp_notify_moderator() wording, and the dashboard recent-comments labels all still key on the two built-in names. These are moderation and notification semantics rather than grouping, and each carries its own behaviour-regression risk.
  • A generic ping class in get_comment_class(), so themes have one stable selector for custom ping types (today a webmention only gets .webmention, missing the .pingback / .trackback styling classic themes ship).

These are tracked as the ping generalization backlog on #35214.

Testing

$ phpunit --group comment
OK (717 tests, 1742 assertions)

$ phpunit --group feed
OK (44 tests, 318 assertions)

New coverage in tests/phpunit/tests/comment/separateComments.php, walker.php, query.php, and wpCommentType.php. PHPCS reports no new warnings on the changed files and PHPStan is clean.

Stacking

Based on feature/comment-type-render-callback (fork PR #53) because it touches the same Walker_Comment::start_el() method. Retarget to trunk once the registration API (#12311) and the display-callback PR land.

See #35214.

AI Use

Code and description both written with 🤖 Claude Code. I will review and test.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3f6b76c7-4fb0-4ab7-bce0-5bc8cd8104ee

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/comment-type-ping-grouping

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Pingbacks and trackbacks were singled out by hard-coded `comment_type`
string comparisons in `separate_comments()` and `Walker_Comment`, so the
"this is a ping, not a human comment" distinction could not be expressed
by a registered comment type.

Add an `is_ping` property to `WP_Comment_Type` (default false) and mark
the built-in `pingback` and `trackback` types with it. `separate_comments()`
now groups any registered ping type into the `pings` bucket, and
`Walker_Comment::start_el()` renders any ping type with the compact ping
markup. Built-in behaviour is unchanged.

See #35214.
Cover the new flag end to end: the `WP_Comment_Type` default and storage,
the built-in pingback/trackback types being marked as pings (and
comment/note not), `separate_comments()` grouping a registered ping type
into the `pings` bucket while leaving non-ping types out, and
`Walker_Comment` rendering a registered ping type with the compact ping
markup.

See #35214.
Add the complementary cases for the is_ping && short_ping guard: the
built-in pingback still renders as a compact ping (regression guard for
the move from hard-coded type strings to the is_ping flag), a ping type
renders its full markup when short_ping is off, and a non-ping type is
never rendered as a ping even with short_ping enabled.

See #35214.
@adamsilverstein
adamsilverstein force-pushed the feature/comment-type-ping-grouping branch from 6c4b5b3 to 3a5a401 Compare June 25, 2026 06:33
…ent-type-ping-grouping

# Conflicts:
#	src/wp-includes/comment.php
- The is_ping docs now state the 'short_ping' condition, that a
  registered 'render_callback' takes precedence over the compact ping
  markup, and the classic-theme-only scope.
- Add the missing @SInCE 7.1.0 changelog entries to
  separate_comments() and extend Walker_Comment::start_el()'s.
- Update the wp_list_comments() 'type' argument doc: 'pings' now means
  every registered comment type with 'is_ping'.
- Tests: pin the render_callback-beats-short_ping precedence, the
  unregistered-type bucket (no 'pings' membership, matching the old
  hard-coded behavior), and the legacy empty-string 'comment' bucket.
  Drop cleanup-only unregister calls now handled by the test framework.
…ent-type-ping-grouping

# Conflicts:
#	src/wp-includes/comment.php
…ct markup.

`Walker_Comment::ping()` prints a literal "Pingback:". That has been imprecise
since 3.6, when trackbacks started using the same markup, but it was at least
never wrong by more than one word. Now that any type can opt into ping grouping,
a webmention rendering as "Pingback: example.com" is plainly wrong output for
exactly the audience the flag is for.

Use the type's `singular_name` for registered, non-built-in types, matching what
`comment_type()` already does on this branch, and leave the string alone for the
built-ins so their markup is byte-identical.

The test that asserted the literal "Pingback:" for a webmention was pinning the
bug, so replace it: one test for the compact shape (label, author link, no
comment body), one for the label itself. Also add the end-to-end case the suite
was missing - `wp_list_comments()` with `type => 'pings'` listing a registered
ping type - which is where a theme actually meets the grouping change.
`separate_comments()` and `wp_list_comments()` group pings by the `is_ping` flag,
while `WP_Comment_Query` kept expanding the 'pings' token to 'pingback' and
'trackback'. A theme reading `$wp_query->comments_by_type['pings']` and a plugin
calling `get_comments( array( 'type' => 'pings' ) )` would disagree about which
comments are pings, so land the query side in the same release rather than ship
that window.

The resolved set goes into the comment query cache key. Which types are pings
depends on what is registered, which changes when a plugin is activated, and the
comment `last_changed` salt only moves when a comment does - so without this a
'pings' query would keep serving results cached before the type existed.

Registration happens on 'init', so the built-in pair remains the fallback for
callers that query before then.
The flag's docs covered grouping and rendering but not the two things a plugin
author most needs to know before using it: that the compact ping markup now
labels the comment with the type's `singular_name`, so a ping type ought to
register one, and that the flag stops at display and grouping. Validation,
default comment status, and notification emails still key on the 'pingback' and
'trackback' type names, so a custom ping type gains none of their handling - and,
just as importantly, none of their bypasses.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant