Skip to:
Content
Pages
Categories
Search
Top
Bottom

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

  • @indigetal

    Participant

    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 hooks** — bp_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.

Viewing 4 replies - 1 through 4 (of 4 total)
  • @emaralive

    Moderator

    You should submit a ticket with the type set to “enhancement”, with the details you have expressed here, such that your proposal can be considered and dispatched accordingly.

    Afterwards, if you decide to submit a PR, the ticket can be referenced which will attach the PR to the ticket.

    @indigetal

    Participant

    Great, thanks!

    @emaralive

    Moderator

    For reference, see Trac ticket #9328.

    @indigetal

    Participant

    I have now created 2 more tickets in addition to this one: #9239, “Add filter hook to bp_email_get_type_schema()” and #9237, “Add privacy column to bp_activity for per-item visibility control.”

    I am a BuddyBoss user who has developed several BuddyBoss-related plugins. However, I have decided to migrate to BuddyPress and bring over several features that come packaged with the BuddyBoss Platform plugin to BuddyPress in order to do so. As I work through the migration, I am identifying very small, but useful, contributions that BuddyBoss has made to the BuddyPress version that they merged into their plugin.

    I will continue adding more enhancement ticket requests as I work through the migration/extraction.

Viewing 4 replies - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.
Skip to toolbar