Skip to:
Content

BuddyPress.org

Opened 5 weeks ago

Last modified 3 weeks ago

#9328 assigned enhancement

Enhancement Request: Add query filter hooks to `BP_Messages_Thread::get_current_threads_for_user()`

Reported by: indigetal's profile indigetal Owned by: johnjamesjacoby's profile johnjamesjacoby
Milestone: 15.0.0 Priority: normal
Severity: normal Version:
Component: Messages Keywords: has-patch
Cc:

Description (last modified by emaralive)

The Gap

BuddyPress's activity component has excellent query-level extensibility:

From BP_Activity_Activity::get() — lines 666, 682

$where_conditions = apply_filters( 'bp_activity_get_where_conditions', $where_conditions, $r, $select_sql, $from_sql, $join_sql );
$join_sql = apply_filters( 'bp_activity_get_join_sql', $join_sql, $r, $select_sql, $from_sql, $where_sql );

These filters allow any addon to inject WHERE clauses and JOINs into the main activity query without modifying core. BuddyBoss's moderation system, for example, hooks into bp_activity_get_where_conditions to hide suspended content — all from addon-level code.

The messages component has no equivalent. BP_Messages_Thread::get_current_threads_for_user() builds its SQL in a $sql array (lines 790–794) and executes it directly:

$sql['select'] = 'SELECT m.thread_id, MAX(m.date_sent) AS date_sent';
$sql['from']   = "FROM {$bp->messages->table_name_recipients} r INNER JOIN {$bp->messages->table_name_messages} m ON m.thread_id = r.thread_id {$meta_query_sql['join']}";
$sql['where']  = "WHERE {$deleted_sql} {$user_id_sql} {$sender_sql} {$type_sql} {$search_sql} {$meta_query_sql['where']}";
$sql['misc']   = "GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}";

$thread_ids = $wpdb->get_results( implode( ' ', $sql ) );

The only filter (bp_messages_thread_current_threads) fires AFTER the query on the fully-constructed result set (line 841) — meaning addons must filter in PHP, not SQL. This is:

  1. A performance problem — filtering in PHP means fetching rows from the database that will be discarded, and constructing full BP_Messages_Thread objects for threads that are then thrown away. This gets worse as thread count grows.
  2. An extensibility gap — addons that need custom thread filtering (archiving, priority inbox, moderation, read/unread management) have no clean way to modify the query
  3. Inconsistent with the activity API — activity has comprehensive pre-query filters; messages doesn't


Proposed Change

Add filter hooks to get_current_threads_for_user() before query execution, following the pattern established by BP_Activity_Activity::get():

After building $sql array (around line 794):

/**
 * Filters the WHERE SQL for the current threads query.
 *
 * @since {next_version}
 *
 * @param string $where_sql  Current WHERE clause.
 * @param array  $r          Parsed query arguments.
 * @param string $select_sql Current SELECT clause.
 * @param string $from_sql   Current FROM clause (includes JOINs).
 */
$sql['where'] = apply_filters( 'bp_messages_thread_get_where_conditions', $sql['where'], $r, $sql['select'], $sql['from'] );

/**
 * Filters the FROM/JOIN SQL for the current threads query.
 *
 * @since {next_version}
 *
 * @param string $from_sql   Current FROM clause (includes JOINs).
 * @param array  $r          Parsed query arguments.
 * @param string $select_sql Current SELECT clause.
 * @param string $where_sql  Current WHERE clause.
 */
$sql['from'] = apply_filters( 'bp_messages_thread_get_join_sql', $sql['from'], $r, $sql['select'], $sql['where'] );

Note on parameter style: In BP_Activity_Activity::get(), the WHERE conditions are passed as an array (joined to a string after the filter), whereas in the messages method they are already a string. This proposal preserves the existing messages code structure and filters the string directly, which is the minimal-change approach. If BP maintainers prefer, the messages SQL could also be refactored to use an array of conditions for parity with activity — but filtering the string is sufficient for all the use cases described below.

Scope

  • ~12 lines added to one file (class-bp-messages-thread.php)
  • Zero behavioral change — the filters pass through existing values by default
  • Follows the pattern established by the activity component's existing filters
  • The existing bp_messages_thread_current_threads post-query filter continues to work as-is


What This Enables for Addons

With these hooks, addon plugins can implement:

  • Message archiving — Add is_hidden column to bp_messages_recipients, filter WHERE to exclude r.is_hidden = 1
  • Message soft-delete — Add is_deleted column to bp_messages_messages, filter FROM/JOIN to exclude deleted messages from thread listing
  • Content moderation — Inject suspend/block conditions into thread queries
  • Priority inbox — Filter by custom meta or thread properties
  • Group messaging — Filter threads by group membership context

None of these features require core changes — they just need the ability to modify the query, which activity already provides but messages doesn't.

Prior Art

BuddyBoss Platform needed exactly these extension points. Because the hooks don't exist in BuddyPress core, BuddyBoss had to:

  1. Restructure get_current_threads_for_user() entirely — they replaced it with a delegating call to a new get_threads_for_user() method containing ~400 lines of rewritten SQL logic
  2. Add is_hidden and is_deleted columns directly into the restructured query conditions
  3. Add their own filter hooksbp_messages_recipient_get_where_conditions and bp_messages_recipient_get_join_sql — with signatures functionally identical to what this proposal suggests

The fact that BuddyBoss independently arrived at the same solution (pre-query filter hooks on the messages SQL) validates the need. If these hooks had existed in BuddyPress core, BuddyBoss could have achieved the same result from addon-level code without forking the class.

I'm happy to submit a PR for this change.

Attachments (1)

9328.patch (1.6 KB) - added by indigetal 3 weeks ago.

Download all attachments as: .zip

Change History (5)

#1 @emaralive
5 weeks ago

  • Component changed from Core to Messages
  • Description modified (diff)
  • Summary changed from Feature Request: Add query filter hooks to `BP_Messages_Thread::get_current_threads_for_user()` to Enhancement Request: Add query filter hooks to `BP_Messages_Thread::get_current_threads_for_user()`
  • Version 14.4.0 deleted

#2 @emaralive
5 weeks ago

  • Description modified (diff)

Edited the description for readability. Slightly modified the Summary.

For reference, this started as a support forum topic, see Add query filter hooks to `BP_Messages_Thread::get_current_threads_for_user()`

@indigetal
3 weeks ago

#3 @indigetal
3 weeks ago

  • Keywords has-patch added

#4 @johnjamesjacoby
3 weeks ago

  • Milestone changed from Awaiting Review to 15.0.0
  • Owner set to johnjamesjacoby
  • Status changed from new to assigned
Note: See TracTickets for help on using tickets.