Personal tools

BuddyPress に enemy 機能を入れる

written by ultraviolet on

物凄く久しぶりに WordPress/BuddyPress をいじってます。

Torgをモチーフにしたパロディサイト MarketPress を前に立てたんですが、これに今いろいろ機能追加してまして。
まずは Facebook Like ボタンをつける plugin を作って (WordPress としての blog post に like つけるのはあったけど BuddyPress の profile につけるのはなかったので、Open Graph の og:* タグまで含めて作ってみた)、それから profile が勝手にリンクに変換されるのが気に食わなかったので Custom Profile Filters を入れてさらにいじって profile の一部を bold に変えられるようにしたり。

さらに、ユーザ同士の Friend 関係に加えて Enemy 関係も登録できるようにしたくて、それを追加しました。
とは言ってもゼロから作るのは手間が大変なので、土台になりそうな plugin は無いかと探しまわった結果、BuddyPress Followers という plugin が結構近そうだなと。これは、Twitter の follow と同じく相手の承認を必要としない一方向の follow 関係を作るための plugin です。これを土台に作ることにしました。

まず、BuddyPress Followers は gettext による localize 対応になってて、po/mo ファイルをいじれば表示を簡単に変えられる仕組みなので、これを使ってまずは単純に Follower/Following 表示を Enemy 表示に直します。これで見かけはほぼ Enemy になった。
次に、Follow は一方向なので、Followers と Following が別々に管理されるわけですが、コードをいじって、どちらかが追加されたら必ずもう一方も同時に追加されるようにして、管理を一元化します。タブも Followers タブと Following タブの二つが別々に表示されるんですが、一方だけ (Enemy タブとして) 表示するように改造。

さらに、BuddyPress Followers では、follow 追加/解除が activity stream に出てこないので、この機能も追加。ただしこれは、フックを使って別の plugin として実装するのが筋だろうと考え、bp_follow_start_followingbp_follow_stop_following の二つのフックに add_action() するコードを書きました。
ところがそしたらいきなりエラーが。なんじゃそりゃと思ってよく見たら、BuddyPress Followers の中に、フックを使うと初めて顕在化するバグが含まれてた。do_action_ref_array() の中で引数を渡すのに array() で括ってなかったと言う… まあ、引数を渡すのに参照渡しせずにわざわざ配列使うという do_action_ref_array() の仕様の方がどうかしてるのだけど、動かないと困るので、これは直しておきました。ここテストせずにリリースしましたね?

/********************************************************************************
 * Business Functions
 */

/**
 * Start following a user's activity
 *
 * @global $bp The global BuddyPress settings variable created in bp_core_setup_globals()
 * @uses wp_parse_args() Parses arguments from an array or request string.
 * @param $args/leader_id - user ID of user to follow
 * @param $args/follower_id - user ID of the user who follows
 * @return bool
 */
function bp_follow_start_following( $args = '' ) {
    global $bp;

    $defaults = array(
        'leader_id'   => bp_displayed_user_id(),
        'follower_id' => bp_loggedin_user_id()
    );

    $r = wp_parse_args( $args, $defaults );
    extract( $r, EXTR_SKIP );

    $follow = new BP_Follow;
    $follow->leader_id = (int)$leader_id;
    $follow->follower_id = (int)$follower_id;

    if ( !$follow->save() )
        return false;

    /* Add a screen count notification */
    bp_core_add_notification( $follower_id, $leader_id, $bp->follow->id, 'new_follow' );

    /* Add a more specific email notification */
    bp_follow_new_follow_email_notification( array( 'leader_id' =>
        $leader_id, 'follower_id' => $follower_id ) );

    do_action_ref_array( 'bp_follow_start_following', array(&$follow) );

    return true;
}

/**
 * Stop following a user's activity
 *
 * @global $bp The global BuddyPress settings variable created in bp_core_setup_globals()
 * @uses wp_parse_args() Parses arguments from an array or request string.
 * @param $args/leader_id - user ID of user to stop following
 * @param $args/follower_id - user ID of the user who wants to stop following
 * @return bool
 */
function bp_follow_stop_following( $args = '' ) {

    $defaults = array(
        'leader_id'   => bp_displayed_user_id(),
        'follower_id' => bp_loggedin_user_id()
    );

    $r = wp_parse_args( $args, $defaults );
    extract( $r, EXTR_SKIP );

    $follow = new BP_Follow( $leader_id, $follower_id );

    if ( !$follow->delete() )
        return false;

    do_action_ref_array( 'bp_follow_stop_following', array(&$follow) );

    return true;
}

BuddyPress の action stream にメッセージ追加する方法は、Friend 追加/削除でメッセージ出してる部分を参考にしました。bp_activity_add() 関数を使うということなのだけど、この関数の取る引数を完全には理解できてないので、一部間違ってるかも。あと BP_Follow クラスのプロパティも把握に苦労しました。この辺、ドキュメントの整備を望む。

できた plugin がこんな感じ。

< ?php
/*
Plugin Name: BuddyPress Followers Action Stream
Plugin URI: 
Description: Require BuddyPress Followers plugin
Version: 1.0
Requires at least: WP 3.0 / BP 1.2.6
Tested up to: WP 3.2.1 / BP 1.5.1
License: GNU/GPL 2
Author: Kanawa Corporation
Author URI: http://www.kanawa.com/
*/

function bp_enemy_action_add(&$follow) {

    $follower_name = bp_core_get_userlink($follow->follower_id);
    $leader_name = bp_core_get_userlink($follow->leader_id);
    bp_activity_add( array(
        'user_id' => $follow->follower_id,
        'item_id' => $follow->id,
        'secondary_item_id' => $follow->leader_id,
        'component' => $follow->id,
        'action' => sprintf(__('%1$s and %2$s are now enemies',
            'bp-enemy-action'), $follower_name, $leader_name),
        'type' => 'enmity_created',
        'recorded_time' => bp_core_current_time(),
        'hide_sitewide' => false)
    );

    bp_activity_add(array(
        'user_id' => $follow->leader_id,
        'item_id' => $follow->id,
        'secondary_item_id' => $follow->follower_id,
        'component' => $follow->id,
        'action' => sprintf(__('%1$s and %2$s are now enemies',
            'bp-enemy-action'), $follower_name, $leader_name),
        'type' => 'enmity_created',
        'recorded_time' => bp_core_current_time(),
        'hide_sitewide' => true)
    );

}

function bp_enemy_action_delete(&$follow) {

    $follower_name = bp_core_get_userlink($follow->follower_id);
    $leader_name = bp_core_get_userlink($follow->leader_id);

    bp_activity_add(
        array(
        'user_id' => $follow->follower_id,
        'item_id' => $follow->id,
        'secondary_item_id' => $follow->leader_id,
        'component' => $follow->id,
        'action' => sprintf(__('%1$s and %2$s are no longer enemies',
            'bp-enemy-action'), $follower_name, $leader_name),
        'type' => 'enmity_deleted',
        'recorded_time' => bp_core_current_time(),
        'hide_sitewide' => false
        )
    );

    bp_activity_add(array(
        'user_id' => $follow->leader_id,
        'item_id' => $follow->id,
        'secondary_item_id' => $follow->follower_id,
        'component' => $follow->id,
        'action' => sprintf(__('%1$s and %2$s are no longer enemies',
            'bp-enemy-action'), $follower_name, $leader_name),
        'type' => 'enmity_deleted',
        'recorded_time' => bp_core_current_time(),
        'hide_sitewide' => true)
    );

}
add_action( 'bp_follow_start_following','bp_enemy_action_add');
add_action( 'bp_follow_stop_following','bp_enemy_action_delete');

?>

実際に動いてる様子が 3327′s enemy とかです。

Postedit on 2011/11/28:

do_action_ref_array()array() が足りない件、BuddyPress Followers plugin の次のバージョン(1.1.1)で直るそうです。来週リリース予定だそうな。素晴らしい。


5 Responses to “BuddyPress に enemy 機能を入れる”

  1. pingback from Rauru Blog » Blog Archive » BuddyPress 関数/プロパティの備忘録

    [...] enemy plugin の記事 [...]

  2. comment from Tracy

    あなたのBloggerが好きで、あなたの更新の文章を期待します

  3. comment from MBT

    更新の文章を期待

  4. comment from mspy coupon code

    Your means of explaining all in this paragraph is actually fastidious,
    every one be able to effortlessly know it, Thanks a
    lot.

    Visit my blog – mspy coupon code

  5. comment from ナイキ スニーカー

    感謝を分かち合う

Leave Your Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

  • Languages

  • Recent Posts

  • Archives

  • Categories

  • Themes

  • Subscriptions

  • Meta

  • Social Services

    Flickr  Picasa  movapic  Photobucket  Zooomr  YouTube  Ustream  Vimeo  scribd  SlideShare  Hatena Bookmarks  Diigo  Commons Marker  Google Reader  StumbleUpon  Digg  Reddit  Hatena Diary  Rauru Blog  WordPress  Blogger  LiveJorunal  Livedoor Blog  posterous  Tumblr  Clipp  Twitter  Plurk  LogPi  identi.ca  Disqus  IntenseDebate  TypePad  Last.fm  GoodReads  LibraryThing  Booklog  amazon wish list  Polyvore  pupe  Upcoming  Wakoopa  yelp  Dopplr  Foursquare  ロケタッチ  GetGlue  Hatena Mono  Kiva  ohloh  MySpace  Windows Live Space  LinkedIn  Facebook  Google+  Plaxo  Netvibes  FriendFeed  backtype  klout  MyBlogLog  socialtunes  kotonoha  2manji  Himitsuku  iddy  mixi  the interviews