Foorum::Controller::Comment - Foorum::Controller::Comment documentation
Index
Code Index:
AUTHOR

Fayland Lam <fayland at gmail.com>
package Foorum::Controller::Comment;
use strict;
use warnings;
our $VERSION = '1.001000';
use parent 'Catalyst::Controller';
use Foorum::Utils qw/encodeHTML/;
sub auto : Private {
my ( $self, $c ) = @_;
unless ( $c->user_exists ) {
$c->res->redirect('/login');
return 0;
}
if ( $c->user->{status} eq 'banned' or $c->user->{status} eq 'blocked' ) {
$c->forward( '/print_error', ['ERROR_PERMISSION_DENIED'] );
return 0;
}
return 1;
}
sub post : Local {
my ( $self, $c ) = @_;
# get object_type and object_id from c.req.referer
my $path = $c->req->referer || '/';
my ( $object_id, $object_type, $forum_id )
= $c->model('Object')->get_object_from_url( $c, $path );
return $c->res->redirect($path) unless ( $object_id and $object_type );
my $forum;
if ($forum_id) { # maybe that's a ForumCode
$forum = $c->controller('Get')->forum( $c, $forum_id );
$forum_id = $forum->{forum_id};
if ( $forum->{settings}->{can_post_replies}
and $forum->{settings}->{can_post_replies} eq 'N' ) {
$c->detach( '/print_error', ['ERROR_PERMISSION_DENIED'] );
}
}
my $reply_to = 0;
if ( 'topic' eq $object_type ) {
my $topic = $c->controller('Get')
->topic( $c, $object_id, { forum_id => $forum_id } );
# topic is closed or not
$c->detach( '/print_error', ['ERROR_CLOSED'] )
if ( $topic->{closed} );
# for topic. only the first comment (topic) is reply_to == 0.
# get the first comment for reply_to
my $rs = $c->model('DBIC::Comment')->find(
{ object_type => 'topic',
object_id => $object_id,
},
{ order_by => 'post_on',
rows => 1,
page => 1,
columns => ['comment_id'],
}
)
; # I'm confused that why search->first is not working at all. YYY?
# and why find is working at all
$c->detach( '/print_error', ['ERROR_CLOSED'] ) unless ($rs);
$reply_to = $rs->comment_id;
}
# execute validation.
$self->validate_params($c);
my $upload = $c->req->upload('upload');
my $upload_id = 0;
if ($upload) {
$upload_id
= $c->model('DBIC::Upload')
->add_file( $upload,
{ forum_id => $forum_id, user_id => $c->user->user_id } );
unless ( $upload_id =~ /^\d+$/ ) {
$c->detach( '/print_error', [$upload_id] );
}
}
my $title = $c->req->param('title');
my $formatter = $c->req->param('formatter');
my $text = $c->req->param('text');
# create record
my $new_comment = $c->model('DBIC::Comment')->create_comment(
{ object_type => $object_type,
object_id => $object_id,
forum_id => $forum_id,
upload_id => $upload_id,
reply_to => $reply_to,
title => $title,
text => $text,
formatter => $formatter,
user_id => $c->user->user_id,
post_ip => $c->req->address,
lang => $c->stash->{lang},
}
);
# update object after create
if ( 'topic' eq $object_type ) {
# update forum and topic
$c->model('DBIC::Forum')->update_forum(
$forum_id,
{ total_replies => \'total_replies + 1', #'
last_post_id => $object_id,
}
);
$c->model('DBIC::Topic')->update_topic(
$object_id,
{ total_replies => \'total_replies + 1',
last_update_date => time(),
last_updator_id => $c->user->user_id,
}
);
}
# go this comment
my $comment_id = $new_comment->comment_id;
$path = $c->model('Object')->get_url_from_object(
$c,
{ object_id => $object_id,
object_type => $object_type,
forum_id => $forum_id
}
);
$path .= "/comment_id=$comment_id/#c$comment_id";
$c->res->redirect($path);
}
sub reply : LocalRegex('^(\d+)/reply$') {
my ( $self, $c ) = @_;
$c->stash(
{ template => 'comment/new.html',
mode => 'reply',
}
);
my $comment_id = $c->req->snippets->[0];
my $comment = $c->controller('Get')
->comment( $c, $comment_id, { with_author => 1, with_text => 1 } );
my ( $object_id, $object_type, $forum_id ) = (
$comment->{object_id}, $comment->{object_type},
$comment->{forum_id}
);
my $forum;
$forum = $c->controller('Get')->forum( $c, $forum_id ) if ($forum_id);
if ($forum) {
if ( $forum->{settings}->{can_post_replies}
and $forum->{settings}->{can_post_replies} eq 'N' ) {
$c->detach( '/print_error', ['ERROR_PERMISSION_DENIED'] );
}
}
if ( 'topic' eq $object_type ) {
my $topic = $c->controller('Get')
->topic( $c, $object_id, { forum_id => $forum_id } );
# topic is closed or not
$c->detach( '/print_error', ['ERROR_CLOSED'] )
if ( $topic->{closed} );
}
return unless ( $c->req->method eq 'POST' );
# execute validation.
$self->validate_params($c);
my $upload = $c->req->upload('upload');
my $upload_id = 0;
if ($upload) {
$upload_id = $c->model('DBIC::Upload')->add_file(
$upload,
{ forum_id => $comment->{forum_id},
user_id => $c->user->user_id
}
);
unless ( $upload_id =~ /^\d+$/ ) {
return $c->set_invalid_form( upload => $upload_id );
}
}
my $title = $c->req->param('title');
my $formatter = $c->req->param('formatter');
my $text = $c->req->param('text');
# only admin has HTML rights
if ( 'html' eq $formatter ) {
my $is_admin = $c->model('Policy')->is_admin( $c, 'site' );
$formatter = 'plain' unless ($is_admin);
}
my $info = {
object_type => $object_type,
object_id => $object_id,
forum_id => $forum_id,
upload_id => $upload_id,
reply_to => $comment_id,
title => $title,
text => $text,
formatter => $formatter,
user_id => $c->user->user_id,
post_ip => $c->req->address,
lang => $c->stash->{lang},
};
# create record
my $new_comment = $c->model('DBIC::Comment')->create_comment($info);
# update object after create
if ( 'topic' eq $object_type ) {
# update forum and topic
$c->model('DBIC::Forum')->update_forum(
$forum_id,
{ total_replies => \'total_replies + 1', #'
last_post_id => $object_id,
}
);
$c->model('DBIC::Topic')->update_topic(
$object_id,
{ total_replies => \'total_replies + 1',
last_update_date => time(),
last_updator_id => $c->user->user_id,
}
);
}
my $path = $c->model('Object')->get_url_from_object( $c, $info );
# go this comment
$comment_id = $new_comment->comment_id;
$path .= "/comment_id=$comment_id/?st=1#c$comment_id";
$c->res->redirect($path);
}
sub edit : LocalRegex('^(\d+)/edit$') {
my ( $self, $c ) = @_;
my $comment_id = $c->req->snippets->[0];
my $comment = $c->controller('Get')->comment( $c, $comment_id );
# permission
if ( $c->user->user_id != $comment->{author_id} ) {
$c->detach( '/print_error', ['ERROR_PERMISSION_DENIED'] );
}
$c->stash(
{ template => 'comment/new.html',
mode => 'edit',
}
);
# edit upload
my $old_upload;
if ( $comment->{upload_id} ) {
$old_upload = $c->model('DBIC::Upload')
->find( { upload_id => $comment->{upload_id} } );
}
$c->stash->{upload} = $old_upload;
return unless ( $c->req->method eq 'POST' );
# execute validation.
$self->validate_params($c);
my $new_upload = $c->req->upload('upload');
my $upload_id = $comment->{upload_id};
if ( ( $c->req->param('attachment_action') eq 'delete' ) or $new_upload )
{
# delete old upload
if ($old_upload) {
$c->model('DBIC::Upload')->remove_by_upload($old_upload);
$upload_id = 0;
}
# add new upload
if ($new_upload) {
$upload_id = $c->model('DBIC::Upload')->add_file(
$new_upload,
{ forum_id => $comment->{forum_id},
user_id => $c->user->user_id
}
);
unless ( $upload_id =~ /^\d+$/ ) {
return $c->set_invalid_form( upload => $upload_id );
}
}
}
my $title = $c->req->param('title');
my $text = $c->req->param('text');
my $formatter = $c->req->param('formatter');
$title = encodeHTML($title);
$c->model('DBIC')->resultset('Comment')
->search( { comment_id => $comment_id, } )->update(
{ title => $title,
text => $text,
formatter => $formatter,
update_on => time(),
post_ip => $c->req->address,
upload_id => $upload_id,
}
);
my ( $object_id, $object_type, $forum_id ) = (
$comment->{object_id}, $comment->{object_type},
$comment->{forum_id}
);
my $info = {
object_type => $object_type,
object_id => $object_id,
forum_id => $forum_id,
};
my $path = $c->model('Object')->get_url_from_object( $c, $info );
# for topic
if ( 'topic' eq $object_type and $comment->{reply_to} == 0 ) {
$c->model('DBIC')->resultset('Topic')
->search( { topic_id => $object_id } )
->update( { title => $title } );
}
my $cache_key = "comment|object_type=$object_type|object_id=$object_id";
$c->cache->remove($cache_key);
# go this comment
$path .= "/comment_id=$comment_id/?st=1#c$comment_id";
$c->res->redirect($path);
}
sub delete : LocalRegex('^(\d+)/delete$') {
my ( $self, $c ) = @_;
my $comment_id = $c->req->snippets->[0];
my $comment = $c->controller('Get')->comment( $c, $comment_id );
my ( $object_id, $object_type, $forum_id ) = (
$comment->{object_id}, $comment->{object_type},
$comment->{forum_id}
);
my $forum;
$forum = $c->controller('Get')->forum( $c, $forum_id ) if ($forum_id);
my $is_admin = 0;
if ($forum_id) {
$is_admin = $c->model('Policy')->is_moderator( $c, $forum_id );
} else {
$is_admin = $c->model('Policy')->is_moderator( $c, 'site' );
}
# permission
if ( $c->user->user_id != $comment->{author_id}
and not $is_admin ) {
$c->detach( '/print_error', ['ERROR_PERMISSION_DENIED'] );
}
my $info = {
object_type => $comment->{object_type},
object_id => $comment->{object_id},
forum_id => $comment->{forum_id},
};
my $path = $c->model('Object')->get_url_from_object( $c, $info );
# esp treat
if ( 'topic' eq $object_type ) {
my $topic = $c->controller('Get')
->topic( $c, $object_id, { forum_id => $forum_id } );
if ( $comment->{reply_to} == 0 ) {
# u can only delete 5 topics one day
my $most_deletion_per_day
= $c->config->{per_day}->{most_deletion_topic}
|| 5;
my $one_day_ago = time() - 86400;
my $deleted_count
= $c->model('DBIC')->resultset('LogAction')->count(
{ forum_id => $forum_id,
action => 'delete',
time => { '>', $one_day_ago }
}
);
if ( $deleted_count >= $most_deletion_per_day ) {
$c->detach(
'/print_error',
[ "For security reason, you can't delete more than $most_deletion_per_day topics in one day"
]
);
}
$c->model('DBIC::Topic')->remove(
$object_id,
{ log_text => $comment->{title},
operator_id => $c->user->user_id
}
);
$path = $forum->{forum_url};
}
}
# delete comment
my $delete_counts = 0;
unless ( 'topic' eq $object_type and $comment->{reply_to} == 0 ) {
$delete_counts
= $c->model('DBIC::Comment')->remove_children($comment);
}
if ( 'topic' eq $object_type and $comment->{reply_to} != 0 ) {
# update topic
my $lastest = $c->model('DBIC')->resultset('Comment')->find(
{ object_type => 'topic',
object_id => $object_id,
},
{ order_by => \'post_on DESC', }
);
my @extra_cols;
if ($lastest) {
@extra_cols = (
last_updator_id => $lastest->author_id,
last_update_date => $lastest->update_on || $lastest->post_on,
);
} else {
@extra_cols = (
last_updator_id => 0,
last_update_date => 0,
);
}
$c->model('DBIC::Topic')->update_topic(
$object_id,
{ total_replies => \"total_replies - $delete_counts",
@extra_cols,
}
);
# update forum
$c->model('DBIC::Forum')
->update_forum( $forum_id,
{ total_replies => \"total_replies - $delete_counts" } );
}
$c->res->redirect("$path?st=1");
}
sub validate_params : Private {
my ( $self, $c ) = @_;
my $st = $c->model('DBIC::Comment')->validate_params( $c->req->params );
if ($st) {
if ( $st =~ /^BAD_(\w+)_(.*?)$/ ) {
my $place = ucfirst( lc($1) );
my $word = $2;
$c->detach( '/print_error',
[qq~Sorry, your $place has a bad word "$word".~] );
} else {
$c->detach( '/print_error', [$st] );
}
}
}
1;
__END__