Buddypress – Add activity scope [closed]

What you want is something like the below class, provided in a gist by @boone-gorges. The code is for extending the groups stream with some tabs matching groupmeta.

Code:

/**
* This is a quick and dirty class to work around the fact that bp_has_groups() does not have a
* meta_query parameter (or even an 'in' parameter). Usage:
*
* 1) Just before you fire up your bp_has_groups() loop, instantiate the NG_BP_Groups_Meta_Filter
*    class, with parameters $key and $value
* 2) Do your groups loop as normal
* 3) When you've closed the bp_has_groups() loop (endif;), call the method remove_filters() just
*    to be safe.
*
* EXAMPLE
* Here's how you would run a bp_has_groups() loop that would only show groups that had the meta
* key/value: 'favorite_gum' => 'Juicy Fruit'
*
*   $meta_filter = new NG_BP_Groups_Meta_Filter( 'favorite_gum', 'Juicy Fruit' );
*
*   // Note that you can pass whatever arguments you want to bp_has_groups(), as usual
*   if ( bp_has_groups() ) :
*       while ( bp_groups() ) :
*           bp_the_group();
*           // Do your template stuff here
*       endwhile;
*   endif;
*
*   // Make sure that other loops on the page are clean
*   $meta_filter->remove_filters();
*/
class BP_Groups_Meta_Filter {
    protected $key;
    protected $value;
    protected $group_ids = array();

    function __construct( $key, $value ) {
        $this->key = $key;
        $this->value = $value;
        $this->setup_group_ids();
        add_filter( 'bp_groups_get_paged_groups_sql', array( &$this, 'filter_sql' ) );
        add_filter( 'bp_groups_get_total_groups_sql', array( &$this, 'filter_sql' ) );
    }

    function setup_group_ids() {
        global $wpdb, $bp;
        $sql = $wpdb->prepare( "SELECT group_id FROM {$bp->groups->table_name_groupmeta} WHERE meta_key = %s AND meta_value = %s", $this->key, $this->value );
        $this->group_ids = wp_parse_id_list( $wpdb->get_col( $sql ) );
    }

    function get_group_ids() {
        return $this->group_ids; 
    }

    function filter_sql( $sql ) {
        $group_ids = $this->get_group_ids();
        if ( empty( $group_ids ) ) {
            return $sql;
        }
        $sql_a = explode( 'WHERE', $sql );
        $new_sql = $sql_a[0] . 'WHERE g.id IN (' . implode( ',', $group_ids ) . ') AND ' . $sql_a[1];
        return $new_sql;
    }

    function remove_filters() {
        remove_filter( 'bp_groups_get_paged_groups_sql', array( &$this, 'filter_sql' ) );
        remove_filter( 'bp_groups_get_total_groups_sql', array( &$this, 'filter_sql' ) );
    }
}

Source: Limit a bp_has_groups() loop to groups matching a groupmeta key/value pair

This works very well, I have used it on several occasions now. To make it work you have to take care of creating the additional tabs and make sure you have a routine to take care of the filtering. A bit more insight can be found at the linked gist source for the class, take a closer look at the comments.

Additionally I provide you an example on how I used it in the past. Below code is an example on how to make use of that in combination with the group meta data provided by the plugin BuddyPress Group Tags. Used for the filter are the categories not the tags and of course this works only if the plugin is in use.

Code:

// create the tabs
add_action( 'bp_groups_directory_group_types', 'bp_ng_cat_grp_tabs_out' );
function bp_ng_cat_grp_tabs_out() {
    $gtags_categories = get_option( 'gtags_category' );
    $gtags_cat_keys = array_keys( $gtags_categories );

    foreach ( $gtags_cat_keys as $g_cat_k ) {
        ?>
            <li class="selected" id="groups-<?php echo $g_cat_k; ?>">
                <a href="https://wordpress.stackexchange.com/questions/132109/<?php bp_root_domain() ?>">
                    <?php $grp_count = count(gtags_get_group_ids( $g_cat_k )); printf( __( '%s <span>%s</span>', 'buddypress' ), $g_cat_k, $grp_count ) ?>
                </a>
            </li>
        <?php
    }
}

// take care of filtering
add_action( 'bp_before_groups_loop', 'bp_ng_cat_grp_tabs_filter' );
function bp_ng_cat_grp_tabs_filter() {
    $grp_querys = bp_ajax_querystring( 'groups' );
    $grp_querys_split = explode( '&' , $grp_querys);
    $grp_scope = preg_grep( '#scope=#' , $grp_querys_split);

    if ( $grp_scope != '' ) {
        $grp_scope = explode( '=' , implode( $grp_scope) );
        $grp_scope = $grp_scope[1];
    }

    $gtags_categories = get_option( 'gtags_category' );
    $gtags_cat_keys = array_keys( $gtags_categories );

    if ( ! empty( $grp_scope ) && in_array( $grp_scope, $gtags_cat_keys ) ) :
        $meta_filter = new BP_Groups_Meta_Filter( 'gtags_group_cat', $grp_scope );
    endif;
}

Ok, this should give you sufficient enough information on how this works. Of course this doesn’t regard the activity stream, but like I said you need something like this and I’m certain it’s possible. I just never had to do it, so I can’t provide you with a complete example.

As you can see, key is to adapt the SQL to your needs, this can be done via the available filters. You can find those and pretty much all the other information you need to build your class for extending the activity stream in bp-activity-classes.php file. You definitely want to take a look at the
bp_activity_get_user_join_filter
and
bp_activity_get_where_conditions
filter, but there are others to consider, depending on what your actual setup will be. Below code gives you an basic example on how to use the filters to alter the activity stream/loop. As it is it replaces the activity view and shows activities with the meta key favorite_count and sorts the results according to the meta value. Keep in mind, this isn’t a solution, I just wrote this on the fly to give you more insight and a better starting point. So take it as it is intended, purely for testing, learning and understanding purposes.

Code:

    add_filter( 'bp_activity_get_where_conditions', 'wpse132109_alter_bp_activity_where_conditions', 12, 5 );
    function wpse132109_alter_bp_activity_where_conditions( $where_conditions, $r, $select_sql, $from_sql, $join_sql ) {
        global $bp;

        $meta_array = array(
            'relation' => 'AND',
            array(
                'key' => 'favorite_count',
                'compare' => 'EXISTS'
            )
        );
        $bp_activity_get_meta_query_sql = BP_Activity_Activity::get_meta_query_sql( $meta_array );
        if ( ! empty( $bp_activity_get_meta_query_sql['where'] ) ) {
            $where_conditions[] = $bp_activity_get_meta_query_sql['where'];
        }

        return $where_conditions;
    }

    add_filter( 'bp_activity_get_user_join_filter', 'wpse132109_alter_bp_activity_activties_sql', 12, 6 );
    function wpse132109_alter_bp_activity_activties_sql( $sql , $select_sql , $from_sql , $where_sql , $sort , $pag_sql="" ) {
        global $bp;

        $meta_array = array(
            'relation' => 'AND',
            array(
                'key' => 'favorite_count',
                'compare' => 'EXISTS'
            )
        );
        $bp_activity_get_meta_query_sql = BP_Activity_Activity::get_meta_query_sql( $meta_array );
        if ( ! empty( $bp_activity_get_meta_query_sql['join'] ) ) {
            $join_sql .= $bp_activity_get_meta_query_sql['join'];
        }

        $sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} ORDER BY sti_bp_activity_meta.meta_value {$sort}";
        return $sql;
    }

Note: neither for productive use nor in anyway optimized

Ok, that’s a lot now, but this definitely should get you started. Just a short summary:

  1. Create a class for your activity filter
    • it will be somewhat similar to the above shown;
    • use the filters available to alter the SQL to your needs;
  2. Take care of
    • the output of your new tab(s);
    • the filtering options, so they are recognized and used;