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_following と bp_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)で直るそうです。来週リリース予定だそうな。素晴らしい。

December 5th, 2011 at 17:55
[...] enemy plugin の記事 [...]
September 12th, 2012 at 18:28
あなたのBloggerが好きで、あなたの更新の文章を期待します
September 15th, 2012 at 22:09
更新の文章を期待