こんにちは,五十嵐です.ブックマークを実際に登録する '/registbookmark' の処理を追加します.
lib/SecureSBM/Controller/Personal.pm:
sub registbookmark : Path('/registbookmark') {
my ( $self, $c ) = @_;
my %data;
my $uid = $c->stash->{user}->user_id;
my $bookmark_exist = 0;
my $bdb;
# URL から直接ブックマークの場合
if( $c->req->method eq 'GET' ){
$c->stash->{template} = 'personal/getregistbookmark.tt';
}
foreach my $k (qw/
bookmark_title
bookmark_url
bookmark_tags
bookmark_comment
/
){
$data{$k} = Jcode::jcode($c->req->param($k))->utf8;
}
ここはお決まりの部分.form からの入力を受け取ります.GET method を確認しているのは,form を経由せずに URL で直接アクセスした場合の処理を行うためです.
URL の空欄チェックを行います.
# URL の確認
if( $data{bookmark_url} eq '' ){
$c->flash->{resultmessage} = 'URL が入力されていません';
$c->res->redirect('/personal');
return 1;
}
URL が確認できたところで,ブックマークの既登録確認を行います.
my $url = $data{bookmark_url};
# Bookmark の既存確認
if( $bdb = $c->model('SecureSBMDB::Bookmark')->
find( {bookmark_uri => $url} )
){
if( my $ubdb = $c->model('SecureSBMDB::UserBookmark')->
find( {user_id => $uid, bookmark_id => $bdb->bookmark_id} )
){
$c->flash->{resultmessage} = $url . ' は既に登録されています.';
$c->res->redirect('/personal');
return 1;
}
$bookmark_exist = 1;
}
stash の代わりに flash を使用してリダイレクトしています.ブックマークが存在していても他人が登録したものの場合には,関連づけを行うために $bookmark_exist = 1 を設定しておきます.
ロールとの関連付けを行うために準備をしておきます.
my $defaultrole = $c->stash->{user}->user_email;
my $rid;
# ロールの準備
if( my $rdb = $c->model('SecureSBMDB::Role')->
find( {role_name => $defaultrole} )
){
$rid = $rdb->role_id;
}
ブックマークのタイトルは,ハイパーリンクの表示に使用するので,空欄のままにはしておけません.空欄の場合には 'no title' を入力しておきます.
# ブックマークの準備
if( $c->req->method eq 'GET' ){
$data{bookmark_title} = _gettitle( $url );
}
if( $data{bookmark_title} eq '' ){
$data{bookmark_title} = 'no title';
}
Bookmark を登録します.既存の確認から登録までに間があるので,ほぼ同時に登録された場合には二重に登録される可能性があります.しかし,まれなことだと思われるので,考慮していません.ブックマーク自体は既存で,自分にとっては初めての登録の場合には $bookmark_exist が 1 になっています.
if( $bookmark_exist or $bdb = $c->model('SecureSBMDB::Bookmark')->
create(
{
bookmark_uri => $data{bookmark_url},
bookmark_title=> $data{bookmark_title}
}
)
){
登録に成功した後,他の処理に入っていきます.ロールへの関連付けを行います.
my $bid = $bdb->bookmark_id;
# ロールへの関連付け
$c->model('SecureSBMDB::BookmarkRole')->
create( {bookmark_id => $bid, role_id => $rid} );
コメントの登録を行います.初めてのブックマーク登録ですので,コメントの作成を行います.コメントは,ユーザとブックマークを関連づける SecureSBMDB::UserBookmark の中に登録しますので,コメントの登録と同時に関連付けが行われます.
# コメントの準備
my $comment;
if( $data{bookmark_comment} ){
$comment = $data{bookmark_comment};
}
# コメント登録
if( my $ubdb = $c->model('SecureSBMDB::UserBookmark')->
create(
{
user_id => $uid,
bookmark_id => $bid,
user_bookmark_comment => $comment,
user_bookmark_ts => 'now'
}
)
){
ユーザとブックマークの関連付け,コメントの登録が終了したら,タグを登録します.
my $ubid = $ubdb->user_bookmark_id;
# タグの準備
my @tags;
if( $data{bookmark_tags} ){
my $tags = $data{bookmark_tags};
$tags =~ s/,/,/g; # 全角カンマの変換
# カンマの前後のスペースを考慮
@tags = split( /\s*[ ],\s*[ ]*/, $tags );
}
タグはカンマで区切りますが,全角カンマが入ってくる可能性がありますので,いったん,すべて半角のスペースに変換します.その後,カンマとそれに続くスペースを取り除いて配列に変換します.全角のスペースが入る可能性があるので,それも考慮しておきます.この部分はブックマークの編集でも使用しますので,後にサブルーチン化します.
タグを登録する際には,タグが既存の場合を考えて,find_or_create を使用して登録します.
# タグ登録
foreach my $v (@tags) {
if( my $tdb = $c->model('SecureSBMDB::Tag')->
find_or_create(
{
tag_name => $v
}
)
){
タグの登録が終了したら,関連付けを行います.
my $tid = $tdb->tag_id;
$c->model('SecureSBMDB::UserBookmarkTag')->
find_or_create(
{
user_bookmark_id => $ubid,
tag_id => $tid
}
);
}
}
この部分もタグの編集で使用する部分ですので,後にサブルーチン化します.最後に if 文を抜け, '/personal' へリダイレクトして終了です.
}
}
if( $c->req->method eq 'GET' ){
$c->forward('personal');
}else{
$c->res->redirect('/personal');
}
}
これで登録 (registbookmark) が終了しました.
登録したら表示する必要がありますので,personal アクションに表示処理を追加します.
lib/SecureSBM/Controller/Personal.pm (personal アクション):
my $bdb = $udb->bookmarks;
# Bookmark の検索
foreach my $bookmark ($bdb->all){
$tmpbm = _makeOneBookmarkEntry( $c, $bookmark->bookmark_id );
if( $tmpbm ){
unshift( @bookmarks, $tmpbm );
}
}
ブックマークをひとつずつ処理していきます.'@bookmarks' 配列に格納していき,stash を用いて最後にテンプレートに渡します.
$c->stash->{mybookmarks} = \@bookmarks;
_makeOneBookmarkEntry() サブルーチンを作成します.取得した内容を変数に代入し,使用する予定の変数を宣言しておきます.
my $title = $bookmark->bookmark_title;
my $uri = $bookmark->bookmark_uri;
my $comment;
my $timestamp;
my $tmpbm = undef;
my $count = $c->model('SecureSBMDB::UserBookmark')->
count( {bookmark_id => $bookmark->bookmark_id} );
$count は何人のユーザがこのブックマークを使用しているかをカウントします.共有数です.
それぞれのブックマークをひとつひとつ処理していきます.
# それぞれのブックマークに対する処理
my $ubdb = $bookmark->user_bookmarks;
foreach my $userbookmark ($ubdb->all){
$comment = $userbookmark->user_bookmark_comment;
$timestamp = $userbookmark->user_bookmark_ts;
タグの処理を行います.タグは配列に格納していきます.
my $ubtdb = $userbookmark->user_bookmark_tags;
my @tags = _getTags( $c, $ubtdb );
$tmpbm = {
id => $bookmark->bookmark_id,
title => $title,
url => $uri,
count => $count,
comment => $comment,
tags => \@tags,
timestamp => $timestamp
};
}
この辺りの処理は,XML/XSLT を利用してサービスの再利用ができるような実装にしたいところですが,今のところ,stash で渡すという処理にしています.
ここまでのアクションに対応するテンプレートを作成します.'mybookmarks' で渡していますので,これを参照する処理を追加します.
<div id="listbookmark">
<h2 id="listbookmark_head">ブックマーク一覧</h2>
<div id="listbookmark_contents">
[% FOREACH bookmark_v IN mybookmarks -%]
<div id="each_listbookmark_[% bookmark_v.id %]" class="eachbookmark">
<a href="[% bookmark_v.url %]">[% bookmark_v.title | html %]</a>
([% bookmark_v.count %])
<br/>
タグ: [%- FOREACH tag_v IN bookmark_v.tags -%][% tag_v | html %],[% END -%]
<br />
コメント: [% bookmark_v.comment | html %]<br />
タイムスタンプ: [% bookmark_v.timestamp %]
</div> <!-- end of each_listbookmark_[% bookmark_v.id %] -->
[% END -%]
</div> <!-- end of listbookmark_contents -->
</div> <!-- end of listbookmark -->
特に解説は必要ないでしょう.今まで出てきたテンプレートで理解できると思います.
mybookmarks が personal アクションから渡されるデータですので,それをひとつひとつ表示していきます.体裁についてはここでは考えていません.それぞれのブックマークを固有の id で指定していることと,div に eachbookmark というクラスを設定して,それぞれのブロックを修飾できるようにしています.見た目はそれぞれのブックマークがくっついて表示されますので,style.css で調整を行うと良いでしょう.

ところで,ブックマークは,現在見ているページを気軽に登録したいものです.そこで,以下のような javascript を作ってみました.
java script:t=encodeURI(document.title);u=encodeURI(location.href);
location.href='http://localhost:3000/prepareregistbookmark?bookmark_url='
+u+'&bookmark_title='+t+'&bookmark_tags=&bookmark_comment=';void(0);
長いので折り返していますが,実際には1行です.このスクリプトをブラウザのブックマークやお気に入りに登録しておくと,表示中のページを Secure-SBM に登録することができます.ただし,あらかじめログインしておくことが必要です.'localhost' 以外のサーバでサービスする場合には,javascript 内の URL のアドレスを変更することを忘れないようにしてください.詳細は
こちらをご覧ください.
これで,ブックマークの登録処理が終わりました.細かい部分でまだ手を加えなければならないところがありますし,「セキュア」SBM としての「セキュア」の部分のコードが全く手つかずです.つまり,現在の処理では自分が登録した URL は全て見えますが,ここに加えて,ロールのマッチングを行う必要があります.まずは全体を仕上げるために大まかな動作を優先させています.スパイラルで作り上げていきましょう.
2007/03/30 記
注: ブログの内容は,開発途中で記述しているため,現在の実装とは異なる場合があります.
参考:
Keyword: Perl Catalyst Secure-SBM SSBM セキュア・ソーシャル・ブックマーク