DNExpert.com - domain name news & opinions!
Have domain industry news? Contact us!

Hello & welcome!

Mark Blog Post As Favorite In BuddyPress

The current version of BuddyPress for WordPress lacks a key feature that I think should be part of the core BP plugin – the ability for members to mark blog posts as favorite. Instead, all members can currently do is mark other members’ Activity Stream posts as favorite.

Although there are a couple of plugins attempting to do what I describe, they are either unsupported and cumbersome (BP Favorites), or do pretty much the same thing as the current BuddyPress “Favorite” feature (BP Like, I am talking about you).

I wanted to put a button on a single blog posts that says “Add to favorites” and allow members to mark my blog posts as their favorites – I also wanted to integrate these favorites into the existing BuddyPress activity stream in order to cater for future updates which may take care of this stuff – rather then create my own tables (like BP Favorites does).

So, I did a bit of research and coded this feature myself.

Here is how I did it.

1. The first thing I did was find out how BuddyPress adds activities in core code when a blog posts is published. I found out that this is done in bp_blogs_record_activity method of bp-blogs.php. Inside this method I found that I can actually retrieve an activity id of a single blog post by calling the method bp_activity_get_activity_id(). If I have the id of an activity, I can easily add it as my favorite from any place on my site.

2. With the above knowledge in hand, I went to my single.php theme template file and added the following inside my the_post loop:

global $bp;
$activity_id = bp_activity_get_activity_id( array(
'user_id' => $post->author_id,
'type' => 'new_blog_post',
'component' => 'blogs',
'item_id' => 1,
'secondary_item_id' => $post->ID
) );

As you can see from the code above, I am attempting to retrieve the activity id of the activity ‘new_blog_post’ that was created by the post author and stored against post ID when the blog post was published.

Since I am using BuddyPress with a single WordPress installation, the item_id = 1 reference above is my blog id. If you are planning to use this with WPMU, you’ll have to find your blog id and use that.

3. If you look inside bp-default/activity/entry.php, you will find that an activity entry is added as favorite as follows:

<?php if ( is_user_logged_in() ) : ?>
<?php if ( !bp_get_activity_is_favorite() ) : ?>
<a href="<?php bp_activity_favorite_link() ?>" class="fav" title="<?php _e( 'Mark as Favorite', 'buddypress' ) ?>"><?php _e( 'Favorite', 'buddypress' ) ?></a>
<?php else : ?>
<a href="<?php bp_activity_unfavorite_link() ?>" class="unfav" title="<?php _e( 'Remove Favorite', 'buddypress' ) ?>"><?php _e( 'Remove Favorite', 'buddypress' ) ?></a>
<?php endif; ?>
<?php endif;?>

From the code above, you can see that BP checks that the user is logged in, and whether they have added this activity as favorite already before allowing them to add the activity as Favorite. If they have already added the activity as favorite, an UnFavorite button is provided.

I could not simply reuse the code since the core calls to bp_activity_favorite_link() etc use internal activity ids. Instead, I added the following functions to my functions.php file:

function my_bp_activity_is_favorite($activity_id) {
global $bp, $activities_template;
return apply_filters( 'bp_get_activity_is_favorite', in_array( $activity_id, (array)$activities_template->my_favs ) );
}

function my_bp_activity_favorite_link($activity_id) {
global $activities_template;
echo apply_filters( 'bp_get_activity_favorite_link', wp_nonce_url( site_url( BP_ACTIVITY_SLUG . '/favorite/' . $activity_id . '/' ), 'mark_favorite' ) );
}

function my_bp_activity_unfavorite_link($activity_id) {
global $activities_template;
echo apply_filters( 'bp_get_activity_unfavorite_link', wp_nonce_url( site_url( BP_ACTIVITY_SLUG . '/unfavorite/' . $activity_id . '/' ), 'unmark_favorite' ) );
}

Once I had the custom functions in place, I added the following code to my single.php theme file to provide me with a cool “Add as Favorite” button for my blog posts:

<?php if ( is_user_logged_in() ) : ?>
<?php bp_has_activities();
if ( !my_bp_activity_is_favorite($activity_id) ) : ?>
<a href=”<?php my_bp_activity_favorite_link($activity_id) ?>” class=”fav” title=”<?php _e( ‘Mark as Favorite’, ‘buddypress’ ) ?>”><?php _e( ‘Favorite’, ‘buddypress’ ) ?></a>
<?php else : ?>
<a href=”<?php my_bp_activity_unfavorite_link($activity_id) ?>” class=”unfav” title=”<?php _e( ‘Remove Favorite’, ‘buddypress’ ) ?>”><?php _e( ‘Remove Favorite’, ‘buddypress’ ) ?></a>
<?php endif; ?>
<?php endif;?>

Works like a charm!

31 comments

  1. What a great article! I used it on my site and it really does work like a charm.

    Just wondering if you’d know how to display how many favorites that post has?

    Thanks,
    Dan

  2. I appreciate you sharing the technique however it would really help if you could share more detailed instructions (i.e. “Find and Replace”). I tried using your instructions and I think that I am confused about how you apply the code to the_post loop

    Thanks!

  3. I spent a lot of time today to find why the ajax doesn’t work with BP 1.5 (and so the link sends us on a 404 page)…
    an I finally got it : in the single.php file, you have to put the favorite links inside a div which has a ‘activity’ classname. Magical.

  4. Oh, yes i found also this solve, if we put the favorite links inside a div which has a ‘activity’ classname, the it looks like works.

    The page doesn’t redirect and my ‘favorite’ button changes to ‘remove favorite’ button. But i noticed that it doesn’t save the result. When you refresh your page you can see it didn’t worked/saved. I found in a function it get null value from $_POST['id'].

    And again i had spent lot of time, and i put finally same html code (div, ul and li) and then put favorite link inside them. Yeh!! It works!!!

    So, my final code are as below

    $post->author_id,
    ‘type’ => ‘new_blog_post’,
    ‘component’ => ‘blogs’,
    ‘item_id’ => 1,
    ‘secondary_item_id’ => $post->ID
    ) );
    ?>

    <li id="activity-”>

    <a href="” class=”button bp-secondary-action fav” title=””>

    <a href="” class=”button bp-secondary-action unfav” title=””>

  5. Zak, you’re right, the div alone made things look fine, but it didn’t record the favorite.
    Your code seems incomplete to me, problem sending it ? Missing the activity-id in the li id, and another div with activity-meta class. I finally got it working by doing :

    $post->author_id,
    ‘type’ => ‘new_blog_post’,
    ‘component’ => ‘blogs’,
    ‘item_id’ => 1,
    ‘secondary_item_id’ => $post->ID
    ) ); ?>
    <li id="activity-”>

    <a href="” class=”button fav bp-secondary-action” title=””>Favorite

    <a href="” class=”unfav button bp-secondary-action” title=””>Remove Favorite

    If someone can explain how this ajax call works, and where we can add or customize another call without putting in all these div and li, I would be very pleased :-)

  6. Ok, some part of the code is missing when commenting.
    So :
    - add $activity_id to the end of the li id to have : li id=”activity-NN” where NN is the activity id
    - after the li, add a div with class=”activity”, and then another div with class=”activity-meta”
    - then, you can have your favorites link,
    - then close the 2 divs and the li (and the ul where you put your li)

  7. @ Oelita, yes that’s right. it’s good that you were able to get work it too. Some part (php begining and ending sign, and div, ul and variable $activity_id inside php tag in li tag) were missing from my comment.

  8. I’ve added the following code to my single.php file and the button seems to be working but not recording. I see that @Oelita said to add $activity_id to the li, but I’m not quite sure how to do this correctly. I’ve tried a could of different ways. Thanks in advance for the help.


    $post->author_id,
    'type' => 'new_blog_post',
    'component' => 'blogs',
    'item_id' => 1,
    'secondary_item_id' => $post->ID
    ) ); ?>

    <a href="" class="fav button bp-secondary-action" title="">

    <a href="" class="unfav button bp-secondary-action" title="">

  9. I did this in the li, which is how it’s done in the activity/entry.php file. But it didn’t seem to resolve the issue of the favorite getting recorded.

    id=”activity-”

  10. First div with class ‘activity’ is important, without it it will redirect to 404 page instead of ajax call.

    And li with id ‘activity-[activity_id]‘ for example ‘activity-12′ is important to record the action.

    The two div in my code inside li isn’t important.

  11. Worked like a charm! Thanks

    Would you know if it’s possible to and a count function to display the number of favorites within the button?

  12. I can’t get it to work, in step 2 where exactly do I place that code in the single.php file? What I do I wrap it in, because right now it breaks the theme.

  13. I am trying this with latest stable WP 3.3 Network/Multisite installation and BP 1.5.2

    I do get the favorite link in individual blog post BUT the ‘item id’ is missing in the favorite link even after manually adding in the code.
    For example : …/WP/activity/favorite//?_wpnonce=618723325d
    // is remaining blank.

    Any idea how to fix this && how to get it automatically in WP Multisite Subdirectory installation?

    Another thing will be really useful if we can show the count using the snippet here http://buddypress.org/community/groups/how-to-and-troubleshooting/forum/topic/show-favourite-count-after-each-activity/?topic_page=2&num=15

    If you can bundle this and can make a zip of functions.php+single.php that works in WP 3.3 + BP 1.5.2 it will really really help us a lot.
    Thanks and Merry Xmas!

  14. Need Help!! Hopefully someone is still checking this blog. I got all of the code added but the Favorite links do not appear on any of the blog pages. So I am thinking that perhaps I added the code to the wrong single.php page. I do not get any errors but nothing shows up as well.

    The single.php I am using is located at: localhost\wp-content\plugins\buddypress\bp-themes\bp-default\single.php

    Any and all help would be greatly greatly appreciated.

    I was also unsure which function.php to edit. I edited the functions.php that resides in the root folder of my theme. Is this the correct file to add the code to? Thanks.

  15. @Stat1123 – you have to edit your active theme’s single.php file – so, it will only be wp-content\plugins\buddypress\bp-themes\bp-default\single.php if you are using that as your default and not using a custom theme in your wp-content/themes folder.

  16. @Shoshanna, thank you so much! Your code works like a charm in my buddy-site (Buddypress 1.5.4 & WordPress 3.3.1).

  17. Great!! I was exactly looking for this solution! Now I need another little TWEAK:
    how can I get the code in the way, that when s.o. marks a post as “FAVORITE” this will be also anounced (at the same time) in the site wide activity stream? I also realized that in my personal “favorites” the order is by date of the post and not by date of “added to favorites” – how is it possible to solve this?

  18. I have put together a function, which can be called in single.php like this:
    echo get_fav_or_unfav_button_for_post( $post );

    In the code below I replaced the opening and closing HTML tags with ‘[' and ']‘ so the site does not strip it.
    I hope it will show up completely.

    function get_fav_or_unfav_button_for_post( $post ) {
    global $bp, $activities_template;
    if ( ! is_user_logged_in() ) {
    return '';
    }
    $activity_id = bp_activity_get_activity_id( array(
    'user_id' => $post->post_author,
    'type' => 'new_blog_post',
    'component' => 'blogs',
    'item_id' => 1,
    'secondary_item_id' => $post->ID
    ) );
    if ( ! $activity_id ) {
    return '';
    }
    bp_has_activities(); // to update $activities_template with user's favourites
    $old_value = false;
    if ( isset( $activities_template->activity->id ) ) {
    $old_value = $activities_template->activity->id;
    $activities_template->activity->id = $activity_id;
    } else {
    $activities_template->activity = (object) array( 'id' => $activity_id );
    }
    $code = '';
    $code .= '[div class="activity buddy-single"]'."\n";
    $code .= ' [ul id="activity-stream" class="activity-list item-list"]'."\n";
    $code .= ' [li id="activity-'.$activity_id.'" class="blogs new_blog_post"]'."\n";
    $code .= ' [div class="activity-content"]'."\n";
    $code .= ' [div class="activity-meta"]'."\n";
    if ( ! bp_get_activity_is_favorite() ) {
    // not yet favourite, show "Favourite" button
    $code .= ' [a href="'.bp_get_activity_favorite_link( ).'" class="button fav bp-secondary-action" title="'.__( 'Mark as Favorite', 'buddypress' ).'"]'.__( 'Favorite', 'buddypress' ).'[/a]'."\n";
    } else {
    // already favourite, show "Unfavourite" button
    $code .= ' [a href="'.bp_get_activity_unfavorite_link( ).'" class="button unfav bp-secondary-action" title="'.__( 'Remove Favorite', 'buddypress' ).'"]'.__( 'Un-favorite', 'buddypress' ).'[/a]'."\n";
    $code .= ' [a href="'.bp_loggedin_user_domain() . 'activity/favorites/" style="font-size: 12px;"]'.__( 'View Your Favorites', 'buddypress' ).'[/a]'."\n";
    }
    $code .= ' [/div]'."\n"; // end of .activity-meta
    $code .= ' [/div]'."\n"; // end of .activity-content
    $code .= ' [/li]'."\n";
    $code .= ' [/ul]'."\n";
    $code .= '[/div]'."\n"; // end of .activity
    if ( false !== $old_value ) {
    $activities_template->activity->id = $old_value;
    } else {
    $activities_template->activity = null;
    }
    return $code;
    }

  19. hi! Does anyone please have a working solution?

    If I take the code on 100% as Shoshanna pasted, I do have buttons, but for random posts it shows “remove favorite” and “favorite” for already favorite + pressing of those buttons do nothing except showing state of whether post is already favorite or not. thanks!

  20. Hi, I tried the code out on the homepage (index.php) within the loop where all the posts show. It shows the favorite link. But when I click on it, it goes to a 404 page. Does this only work on single.php? How do I tweak it to work on the main page?

    I would appreciate some input. Thanks. :)

  21. Hi there really working on hard this for a couple of hours and cant seem to get it to work, Im trying to use it with a custom post type.

    Does anybody know how I could implement it with a custom post?

    Thanks

  22. Hi there,
    I was looking for a way to put favorite button to the first post of a forum topic. because my website has many groups and forums, and users want me this functionality.
    could you please help me to make it possible?

  23. $post->author_id,
    ‘type’ => ‘new_blog_post’,
    ‘component’ => ‘blogs’,
    ‘item_id’ => 1,
    ‘secondary_item_id’ => $post->ID
    ) ); ?>

    this code not generate Any activity id in my case

    in my single.php show only Remove Favorite button

  24. Well this seems silly. Why would the user favorite an activity? Using the code above, it would be the user favoriting an author writing a blog post. That’s dumb. Isn’t the point to mark a post as a favorite – not favoriting the action of an author writing a post? At least, that’s how things are in the latest version of BuddyPress and WordPress. UGH.

Leave a Reply