Last updated July 11, 2026, Version 0.34
GatherPress stores RSVPs as WordPress comments with a custom comment_type of
gatherpress_rsvp. The comment row is the canonical record — status changes
(attending, not_attending, waiting_list), guest counts, and anonymous /
authenticated state all live on the comment and its meta. Reusing the comments
table means RSVPs inherit WordPress’s moderation, capability, and i18n
infrastructure for free.
Comment-query coexistence
Because RSVPs live in wp_comments, generic comment queries (sidebar widgets,
admin moderation lists, REST endpoints, federation plugins) would surface them
alongside real comments unless filtered out. GatherPress hooks
pre_get_comments and removes the gatherpress_rsvp type from each query’s
type / type__in vars in Rsvp\Query::exclude_rsvp_from_comment_query()
(includes/core/classes/rsvp/class-query.php).
The exclusion mutates query vars rather than appending a WHERE comment_type !=
… clause because the comment_type column is not indexed in WordPress core
(see Trac #59488). Pre-populating
the type list lets MySQL use the existing index and avoids a full-table scan on
sites with large comment volumes.
When the default exclusion gets in the way
Mutating shared query vars is the right trade-off for performance but can
conflict with other plugins that read or write the same vars on
pre_get_comments. The canonical example is the ActivityPub
plugin — federation
interactions (likes, boosts, quotes) flow through wp_comments with their own
types, and ActivityPub’s own pre_get_comments callback assumes the caller’s
type__in reflects the original query.
To opt out of GatherPress’s default exclusion for a specific query, return
false from the gatherpress_rsvp_comment_query_exclusion filter. The filter
receives the live WP_Comment_Query, so the opt-out can be scoped to the
queries an integration actually owns:
add_filter(
'gatherpress_rsvp_comment_query_exclusion',
function ( bool $exclude, WP_Comment_Query $query ): bool {
// Only short-circuit when the caller is asking for federation
// interaction types — leave every other comment query alone so
// GatherPress's default RSVP exclusion continues to apply.
$types = (array) ( $query->query_vars['type__in'] ?? array() );
if ( array_intersect( $types, array( 'like', 'announce' ) ) ) {
return false;
}
return $exclude;
},
10,
2
);
A scoped opt-out is preferred over a global remove_action() against
Rsvp\Query::exclude_rsvp_from_comment_query: it leaves the exclusion in
effect for unrelated comment lists on the same site, and it has no coupling to
GatherPress’s class names or singleton accessors, so it survives internal
refactors without code changes on the integration side.
Sitewide gating (RSVP Mode and Open RSVP)
Since 0.34.0 the rsvp_mode setting is the master switch for the whole RSVP
subsystem. When it is set to disabled, GatherPress removes the
gatherpress-rsvp post type support from every post type that declares it
(Rsvp\Setup::maybe_disable_rsvp()), so every post_type_supports() guard in
the plugin — and in companion plugins following the same pattern — returns
false without needing its own setting check. The gatherpress/rsvp* blocks are
also filtered out of the block inserter, and the RSVPs admin page is not
registered.
Open RSVP has two gates: the sitewide enable_open_rsvp setting and a
per-event gatherpress_enable_open_rsvp post meta (unset means enabled).
Rsvp::allows_open_rsvp() resolves both; when it returns false the RSVP Form
block renders nothing and form or REST submissions are rejected with a 403.
Further reading
- Per-hook reference:
docs/developer/hooks/(auto-regenerated by
CI from the docblock above eachapply_filters()/do_action()call). - Hook naming conventions:
docs/developer/hooks-naming-convention.md.