Skip to:
Content
Pages
Categories
Search
Top
Bottom

BP 1.2: How to add a custom tab on the Home activity section


  • Mike Pratt
    Participant

    @mikepratt

    Props to @jjj and @Mrmaz for their help in this. This technique turned out to be much less trivial than we thought (at least in the hunt for a solution) but it adds a dynamic to your site that might prove very useful.

    The Need: I will use my site as an example and for context. We run an alumni site and have Class groups created back to 1939. We also have groups that are not class specific (e.g. Reading Room, Politics, etc) The new activity stream in 1.2 will, no doubt, be a huge hit and boost engagement. The ‘My Groups’ tab is awesome to see stuff in all the groups you care about i.e. are a member of. In our case, members really care about all the activity in their Class.

    Requirement: Add a tab that filters activity for a user’s Class – or said differently – for a specified Group.

    The Solution:

    Step 1: create a function that adds a filter to modify the query used in creating the activity stream. In the activity stream, a $scope needs to be specified. In this example ‘myclass’ is the scope. This function also checks to ensure a user is logged in. Finally,

    function_to_get_group_id_for_logged_in_user()

    is simply a placeholder for one of 2 things: you either hard code a Group ID of your choosing, or (as in my case) you add a function to dynamically insert a Group ID – we do a look up of a user’s Class field value). These functions go, of course, in your theme functions.php file (or even in bp-custom.php in the plugin folder)

    function bp_my_ajax_querystring_activity_filter( $query_string, $scope ) {
    global $bp;

    if ( $scope != 'myclass' || !is_user_logged_in() )
    return $query_string;

    $args = array();
    parse_str( $query_string, $args );
    $args['object'] = $bp->groups->id;
    $args['primary_id'] = function_to_get_group_id_for_logged_in_user();

    return http_build_query( $args );
    }
    add_filter( 'bp_dtheme_ajax_querystring_activity_filter',
    'bp_my_ajax_querystring_activity_filter', 1, 2 );

    Step 2: Create the tab list item

    In this case, I am in a child theme off the parent bp-default. You need to create the folder /activity in your theme and copy /activity/index.php into that new folder. Then add the following line in the list class “item-list-tabs activity-type-tabs”

    <li id="activity-myclass"><a href="<?php echo site_url( BP_ACTIVITY_SLUG . '/#myclass/' ) ?>" title="<?php _e( 'Activity for my Class Year.', 'buddypress' ) ?>"><?php printf( __( 'My Class', 'buddypress' ) ) ?></a></li>

    Important!: notice the list-id has ‘myclass’ in the name. You must include your scope name here for the scope to be passed properly. The #myclass slug can actually be whatever you want as long as it’s unique (my suggestion is keep it the same or close for consistency) The rest of the customization is up to you (title, etc)

    That’s it. Now, when user’s click that tab, they get all the functionality of the other tabs but for one particular group. I can see this having many uses, depending on the focus of your BP site.

    @Andy – feel free to copy this as a How To in Docs if you deem it worthy (or not riddled with errors!)

Viewing 12 replies - 1 through 12 (of 12 total)

  • Andy Peatling
    Keymaster

    @apeatling

    Looks good, but you don’t need to copy the template. Just add this function in your child theme’s functions.php file (or wherever you put the other code):

    function my_theme_add_activity_tab() {
    if ( !is_user_logged_in() )
    return false;
    ?>
    <li id="activity-myclass">
    <a href="<?php echo site_url( BP_ACTIVITY_SLUG . '/#myclass/' ) ?>" title="<?php _e( 'Activity for my Class Year.', 'buddypress' ) ?>">
    <?php printf( __( 'My Class', 'buddypress' ) ) ?>
    </a>
    </li>
    <?php
    }
    add_action( 'bp_activity_type_tabs', 'my_theme_add_activity_tab' );


    Andy Peatling
    Keymaster

    @apeatling

    The next step in future versions would obviously be to create a nice API that abstracts away most of this.


    Mike Pratt
    Participant

    @mikepratt

    @andy is correct. You do not have to copy the template. I did because I wanted the list item to be placed specifically. If you choose not to, it will go at the end of the list. The pro there is that you don’t have to worry about template changes down the road.


    MrMaz
    Participant

    @mrmaz

    I opened a ticket a few days back with a patch to add an action BEFORE the mentions tab to avoid having to copy the template. This also puts it inside the login check if statement, so you don’t have to check if the user is logged in.

    https://trac.buddypress.org/ticket/1715


    Mike Pratt
    Participant

    @mikepratt

    Update: Here is how we use a custom field to look up a group and return it’s ID to create a custom query stream:

    // passes MyClass scope into ajax query for custom Class Year activity filter
    function bp_my_ajax_querystring_activity_filter( $query_string, $scope ) {
    global $bp, $wpdb;

    if ( $scope != 'myclass' || !is_user_logged_in() )
    return $query_string;

    $args = array();
    parse_str( $query_string, $args );
    $args['object'] = $bp->groups->id;

    // get user's class year and generate slug (BN naming
    convention is usma-yyyy for class groups)
    $slug = "usma-". bp_get_profile_field_data( array('field'=>
    'Class Year', 'user_id' => $bp->loggedin_user->id));;
    $groupid = BP_Groups_Group::get_id_from_slug($slug);
    $args['primary_id'] = $groupid;

    return http_build_query( $args );
    }
    add_filter( 'bp_dtheme_ajax_querystring_activity_filter',
    'bp_my_ajax_querystring_activity_filter', 1, 2 );

    Every new user selects a graduating Class Year e.g. 1987 upon registration. They are auto-joined to a Class group with the naming convention ‘USMA YYYY’ (the slug is then ‘usma-yyyy’

    So the $slug var is generated off a lookup of the logged in user’s Class year field and then the slug permits lookup of the Group ID. Of course, sticking to a naming convention is how this works but the concept is pretty simple.

    You could easily have a custom field (required or voluntary) that provides a starting point via it’s values for custom Activity filtering. TIP: Stick to drop-downs and check boxes in order to control the values fed to the $slug function.


    Bowe
    Participant

    @bowromir

    This is absolutely awesome! I’m so going to use this to display information from a certain country only! Thanks a lot for explaining this Mike (and all who helped him)


    MrMaz
    Participant

    @mrmaz

    UPDATE:

    The filtering has been consolidated and drastically improved as of revision 2580. Here is an updated example:

    function my_activity_filter( $query_string, $object, $filter, $scope, $page, $search_terms, $extras ) {
    global $bp;

    if ( $object != 'activity' || $scope != 'myclass' || !is_user_logged_in() )
    return $query_string;

    $args = array();
    parse_str( $query_string, $args );
    $args['object'] = $bp->groups->id;
    $args['primary_id'] = function_to_get_group_id_for_logged_in_user();

    return http_build_query( $args );
    }
    add_filter( 'bp_dtheme_ajax_querystring', 'my_activity_filter', 1, 7 );

    As you can see a TON more information about the request is being passed to the filtering, so you can more easily determine what you need to do to handle it properly.


    Mike Pratt
    Participant

    @mikepratt

    so here’s a tweaked version and the latest in my custom tab efforts, fyi:

    // passes MyClass scope into ajax query for custom Class Year activity filter
    function bn_ajax_querystring_activity_filter( $query_string, $object, $filter, $scope, $page, $search_terms, $extras ) {

    global $bp;

    if ( !is_user_logged_in() || $object != 'activity' )
    return $query_string;

    $args = array();
    parse_str( $query_string, $args );
    $args['object'] = $bp->groups->id;

    switch ($scope){

    case 'myclass':

    $slug = "usma-". bp_get_profile_field_data( array('field'=> 'Class Year', 'user_id' => $bp->loggedin_user->id));
    $groupid = BP_Groups_Group::get_id_from_slug($slug);
    $args['primary_id'] = $groupid;
    break;

    case 'mycadetco':

    $slug = bp_get_profile_field_data( array('field'=> 'Cadet Company', 'user_id' => $bp->loggedin_user->id));
    $groupid = BP_Groups_Group::get_id_from_slug($slug);
    $args['primary_id'] = $groupid;
    break;

    case 'mybranch':

    $slug = sanitize_title(bp_get_profile_field_data( array('field'=> 'Branch', 'user_id' => $bp->loggedin_user->id)));
    $groupid = BP_Groups_Group::get_id_from_slug($slug);
    $args['primary_id'] = $groupid;
    break;

    default:

    return $query_string;
    }

    return http_build_query( $args );
    }
    add_filter( 'bp_dtheme_ajax_querystring', 'bn_ajax_querystring_activity_filter', 1, 7 );

    and the action:

    function bn_add_activity_tab() {

    if ( !is_user_logged_in() )
    return false;
    ?>
    <!-- default item-list-tabs activity-type-tabs

    <ul> -->

    </div><!-- default item-list-tabs activity-type-tabs -->

    <div class="item-list-tabs activity-type-tabs" id="bn-tabs">

    </ul>
    <ul>
    <li id="activity-myclass">
    <a>" title="<?php _e( 'Activity for my Class Year', 'buddypress' ) ?>">
    <?php printf( __( 'My Class', 'buddypress' ) ) ?>
    </a>

    <li id="activity-mycadetco">
    <a>" title="<?php _e( 'Activity for my Cadet Company', 'buddypress' ) ?>">
    <?php printf( __( 'My Cadet Company', 'buddypress' ) ) ?>
    </a>

    <li id="activity-mybranch">
    <a>" title="<?php _e( 'Activity for my Army Branch', 'buddypress' ) ?>">
    <?php printf( __( 'My Branch', 'buddypress' ) ) ?>
    </a>

    <?php
    }
    add_action( 'bp_activity_type_tabs', 'bn_add_activity_tab', 1, 2 );

    A few things to note:

    1. use the WP function sanitize_title() if you have a field that might return more than one word e.g. the group ‘Military Police’ returns ‘military police’ but transforms into ‘military-police’ (a pretty slug0 which gives you a correct slug now.

    2. I added addl markup to force my new tabs into their own element.

    3. Don’t be shy to make suggestions and keep improving this technique. I think many will use it to customize their installs.


    designodyssey
    Participant

    @designodyssey

    @mike

    This should definitely be added to the FAQ:How to sticky post.


    MrMaz
    Participant

    @mrmaz

    There are a lot of new actions in RC so you can put your custom tabs anywhere you want.


    Mike Pratt
    Participant

    @mikepratt

    Thanks to @MrMaz, this will be a huge hit on my site, I think


    revolutionfrance
    Participant

    @revolutionfrance

    Hey Mike! Is there any way to customize this so that you add a tab to filter activity based on one of the profile fields? Thx for your help!

Viewing 12 replies - 1 through 12 (of 12 total)
  • The topic ‘BP 1.2: How to add a custom tab on the Home activity section’ is closed to new replies.
Skip to toolbar