OSDN Git Service

Model::Comments: add create method
authorhylom <hylom@users.sourceforge.jp>
Wed, 19 Oct 2016 10:49:30 +0000 (19:49 +0900)
committerhylom <hylom@users.sourceforge.jp>
Wed, 19 Oct 2016 10:49:30 +0000 (19:49 +0900)
src/newslash_web/lib/Newslash/Model/Comments.pm

index 0e195c4..ccb9c1d 100644 (file)
@@ -4,6 +4,9 @@ use Newslash::Model::Base -base;
 use Data::Dumper;
 use Mojo::Log;
 
+use bytes qw();
+use Digest::MD5 qw(md5_hex);
+
 #========================================================================
 
 =head2 select($query_type, $value)
@@ -104,4 +107,433 @@ sub build_comment_tree {
     return $root;
 }
 
+sub generate_signature {
+    my ($self, $comment) = @_;
+    return md5_hex(encode_utf8($comment);
+}
+
+#========================================================================
+
+=head2 create(\%params, \%options)
+
+create comment
+
+=over 4
+
+=item Parameters
+
+=over 4
+
+=item \%options
+
+comment parameters
+
+ * sid
+ * pid
+ * title
+ * comment
+ * tags
+
+=item \%options
+
+options for submission
+
+=back
+
+=item Return value
+
+ARRAY of story contents
+
+=back
+
+=cut
+
+sub create {
+    my ($self, $params, $user, $extra_params, $opts) = @_;
+    if (!$params || !$user) {
+        return undef;
+    }
+    $opts ||= {};
+    $extra_params ||= {};
+
+    my $subject_orig = 'yes';
+
+    # if pid given, validate them
+    if ($params->{pid}) {
+        my $parent = $self->select(cid => $params->{pid});
+        if (!$parent) {
+            # ERROR: pid not exists
+        }
+        if ($parent->{sid} != $params->{sid}) {
+            # ERROR: pid is other story's comment
+        }
+        # TODO: check visibility
+        # check title is reply?
+        if ($params->{title} =~ /$parent->{subject}/) {
+            $subject_orig = 'no';
+        }
+    }
+    my $subject_max_length = 50;
+    my $subject = substr $params->{subject}, 0, $subject_max_length;
+    my $signature = $self->generate_signature($params->{comment});
+
+    my $sql = <<"EOSQL";
+INSERT INTO comments
+    (sid, pid, date, ipid, subnetid, subject, subject_orig, uid, points, pointsorig, pointsmax,
+     signature, len, karma_bonus, karma, karma_abs)
+  VALUE
+    (?,   ?,   NOW(),?,    ?,        ?,       ?,            ?,   ?,      ?,          ?,
+     ?,         ?,   ?,           ?,     ?)
+EOSQL
+
+    my $dbh = $self->connect_db({AutoCommit => 0,});
+    $rs = $dbh->do($sql, undef,
+                   $param->{sid},
+                   $param->{pid},
+                   $user->{ipid},
+                   $user->{subnetid},
+                   $subject, #subject
+                   $subject_orig, #subject_orig
+                   $user->{uid},
+                   $param->{points} || 0,
+                   $param->{points} || 0, #pointsorig
+                   $param->{points} || 0, #pointsmax
+                   $signature, #signature,
+                   bytes::length $param->{comment}, #len
+                   $param->{karma_bonus} || 'no',
+                   $param->{karma} || 0,
+                   $param->{karma_abs} || 0
+                  );
+    if (!$rs) {
+        # error occured
+        $self->set_errorno($dbh->{mysql_errno});
+        $self->set_error("mysql_error");
+        $dbh->rollback;
+        $dbh->disconnect;
+        return undef;
+    }
+    my $cid = $dbh->last_insert_id(undef, undef, undef, undef);
+    $sql = "INSERT INTO comment_text (cid, comment) VALUE (?, ?)";
+    $rs = $dbh->do($sql, undef, $cid, $params->{comment});
+    if (!$rs) {
+        # error occured
+        $self->set_errorno($dbh->{mysql_errno});
+        $self->set_error("mysql_error");
+        $dbh->rollback;
+        $dbh->disconnect;
+        return undef;
+    }
+
+    # update discussion
+    $sql = "UPDATE discussions SET commentcount = commentcount + 1 WHERE id = ?";
+    $rs = $dbh->do($sql, undef, $sid);
+    if (!$rs) {
+        # error occured
+        $self->set_errorno($dbh->{mysql_errno});
+        $self->set_error("mysql_error");
+        $dbh->rollback;
+        $dbh->disconnect;
+        return undef;
+    }
+
+    # create firehose item
+    $self->firehose_createItemFromComment($cid);
+
+    $dbh->commit;
+    $dbh->disconnect;
+    return $cid;
+}
+
+
+sub firehose_createItemFromComment {
+    my($self, $cid) = @_;
+    my $comment = $self->getComment($cid);
+    my $text = $self->getCommentText($cid);
+    my $globjid = $self->getGlobjidCreate("comments", $cid);
+
+    # Set initial popularity scores -- we'll be forcing a quick
+    # recalculation of them so these scores don't much matter.
+    my($popularity, $editorpop, $neediness);
+    $popularity = $self->getEntryPopularityForColorLevel(7);
+    $editorpop = $self->getEntryPopularityForColorLevel(7);
+    $neediness = $self->getEntryPopularityForColorLevel(6);
+
+    # recalculation of them so these scores don't much matter.
+    my($popularity, $editorpop, $neediness);
+    $popularity = $self->getEntryPopularityForColorLevel(7);
+    $editorpop = $self->getEntryPopularityForColorLevel(7);
+    $neediness = $self->getEntryPopularityForColorLevel(6);
+
+    my $data = {
+                uid             => $comment->{uid},
+                public          => "yes",
+                title           => $comment->{subject},
+                introtext       => $text,
+                ipid            => $comment->{ipid},
+                subnetid        => $comment->{subnetid},
+                type            => "comment",
+                srcid           => $comment->{cid},
+                popularity      => $popularity,
+                editorpop       => $editorpop,
+                globjid         => $globjid,
+                discussion      => $comment->{sid},
+                createtime      => $comment->{date},
+               };
+    my $fhid = $self->createFireHose($data);
+
+    if (!isAnon($comment->{uid})) {
+        my $constants = getCurrentStatic();
+        my $tags = getObject('Slash::Tags');
+        $tags->createTag({
+                          uid                     => $comment->{uid},
+                          name                    => $constants->{tags_upvote_tagname},
+                          globjid                 => $globjid,
+                          private                 => 1,
+                         });
+    }
+
+    my $tagboxdb = getObject('Slash::Tagbox');
+    if ($tagboxdb) {
+        for my $tbname (qw( FireHoseScores FHEditorPop CommentScoreReason )) {
+            my $tagbox = $tagboxdb->getTagboxes($tbname);
+            next unless $tagbox;
+            $tagbox->{object}->forceFeederRecalc($globjid);
+        }
+    }
+
+    return $fhid;
+}
+
+
+
+sub saveComment {
+       #my($comm, $comment, $user, $discussion, $error_message, $submit_type) = @_; # probably $comm = $form
+       #my $slashdb = getCurrentDB();
+       #my $constants = getCurrentStatic();
+       #my $reader = getObject('Slash::DB', { db_type => 'reader' });
+
+       #$submit_type ||= "none";
+
+       $comm->{nobonus}  = $user->{nobonus}    unless $comm->{nobonus_present};
+       $comm->{postanon} = $user->{postanon}   unless $comm->{postanon_present};
+       $comm->{nosubscriberbonus} = $user->{nosubscriberbonus}
+                                               unless $comm->{nosubscriberbonus_present};
+
+#print STDERR scalar(localtime) . " $$ E header_emitted=$header_emitted do_emit_html=$do_emit_html redirect_to=" . (defined($redirect_to) ? $redirect_to : "undef") . "\n";
+
+       # Set starting points to the AC's starting points, by default.
+       # If the user is posting under their own name, we'll reset this
+       # value (and add other modifiers) in a moment.
+       my $pts = getCurrentAnonymousCoward('defaultpoints');
+       my $karma_bonus = 0;
+       my $subscriber_bonus = 0;
+       my $tweak = 0;
+
+       if (!$comm->{anon}) {
+               $pts = $user->{defaultpoints};
+
+               if ($constants->{karma_posting_penalty_style} == 0) {
+                       $pts-- if $user->{karma} < 0;
+                       $pts-- if $user->{karma} < $constants->{badkarma};
+                } else {
+                       $tweak-- if $user->{karma} < 0;
+                       $tweak-- if $user->{karma} < $constants->{badkarma};
+               }
+               # Enforce proper ranges on comment points.
+               my($minScore, $maxScore) =
+                       ($constants->{comment_minscore}, $constants->{comment_maxscore});
+               $pts = $minScore if $pts < $minScore;
+               $pts = $maxScore if $pts > $maxScore;
+               $karma_bonus = 1 if $pts >= 1 && $user->{karma} > $constants->{goodkarma}
+                       && !$comm->{nobonus};
+               $subscriber_bonus = 1 if $constants->{plugin}{Subscribe}
+                       && $user->{is_subscriber}
+                       && (!$comm->{nosubscriberbonus} || $comm->{nosubscriberbonus} ne 'on');
+       }
+
+#print STDERR scalar(localtime) . " $$ F header_emitted=$header_emitted do_emit_html=$do_emit_html\n";
+
+       my $clean_comment = {
+               subject         => $comment->{subject},
+               comment         => $comment->{comment},
+               sid             => $comment->{sid},
+               pid             => $comment->{pid},
+               ipid            => $user->{ipid},
+               subnetid        => $user->{subnetid},
+               uid             => $comment->{uid},
+               points          => $pts,
+               tweak           => $tweak,
+               tweak_orig      => $tweak,
+               karma_bonus     => $karma_bonus ? 'yes' : 'no',
+       };
+
+       if ($constants->{plugin}{Subscribe}) {
+               $clean_comment->{subscriber_bonus} = $subscriber_bonus ? 'yes' : 'no';
+       }
+
+       my $maxCid = $slashdb->createComment($clean_comment);
+       $slashdb->saveCommentInfo($maxCid, $submit_type);
+       if ($constants->{comment_karma_disable_and_log}) {
+               my $post_str = "";
+               $post_str .= "NO_ANON " if $user->{state}{commentkarma_no_anon};
+               $post_str .= "NO_POST " if $user->{state}{commentkarma_no_post};
+               if (isAnon($comment->{uid}) && $user->{state}{commentkarma_no_anon}) {
+                       $slashdb->createCommentLog({
+                               cid     => $maxCid,
+                               logtext => "COMMENTKARMA ANON: $post_str"
+                       });
+               } elsif (!isAnon($comment->{uid}) && $user->{state}{commentkarma_no_post}) {
+                       $slashdb->createCommentLog({
+                               cid     => $maxCid,
+                               logtext => "COMMENTKARMA USER: $post_str"
+                       });
+               }
+       }
+       if ($constants->{comment_is_troll_disable_and_log}) {
+               $slashdb->createCommentLog({
+                       cid     => $maxCid,
+                       logtext => "ISTROLL"
+               });
+       }
+
+#print STDERR scalar(localtime) . " $$ G maxCid=$maxCid\n";
+
+       # make the formkeys happy
+       $comm->{maxCid} = $maxCid;
+
+       $slashdb->setUser($user->{uid}, {
+               '-expiry_comm'  => 'expiry_comm-1',
+       }) if allowExpiry();
+
+       if ($maxCid == -1) {
+               $$error_message = getError('submission error');
+               return -1;
+
+       } elsif (!$maxCid) {
+               # This site has more than 2**32 comments?  Wow.
+               $$error_message = getError('maxcid exceeded');
+               return -1;
+       }
+
+
+       my $saved_comment = $slashdb->getComment($maxCid);
+       slashHook('comment_save_success', { comment => $saved_comment });
+
+       my $moddb = getObject("Slash::$constants->{m1_pluginname}");
+       if ($moddb) {
+               my $text = $moddb->checkDiscussionForUndoModeration($comm->{sid});
+               print $text if $text && !discussion2($user);
+       }
+
+       my $tc = $slashdb->getVar('totalComments', 'value', 1);
+       $slashdb->setVar('totalComments', ++$tc);
+
+
+       if ($discussion->{sid}) {
+               $slashdb->setStory($discussion->{sid}, { writestatus => 'dirty' });
+       }
+
+       $slashdb->setUser($clean_comment->{uid}, {
+               -totalcomments => 'totalcomments+1',
+       }) if !isAnon($clean_comment->{uid});
+
+       my($messages, $reply, %users);
+       my $kinds = $reader->getDescriptions('discussion_kinds');
+       if ($comm->{pid}
+               || $kinds->{ $discussion->{dkid} } =~ /^journal/
+               || $constants->{commentnew_msg}) {
+               $messages = getObject('Slash::Messages');
+               $reply = $slashdb->getCommentReply($comm->{sid}, $maxCid);
+       }
+
+       $clean_comment->{pointsorig} = $clean_comment->{points};
+
+       # reply to comment
+       if ($messages && $comm->{pid}) {
+               my $parent = $slashdb->getCommentReply($comm->{sid}, $comm->{pid});
+               my $users  = $messages->checkMessageCodes(MSG_CODE_COMMENT_REPLY, [$parent->{uid}]);
+               if (_send_comment_msg($users->[0], \%users, $pts, $clean_comment)) {
+                       my $data  = {
+                               template_name   => 'reply_msg',
+                               template_page   => 'comments',
+                               subject         => {
+                                       template_name => 'reply_msg_subj',
+                                       template_page => 'comments',
+                               },
+                               reply           => $reply,
+                               parent          => $parent,
+                               discussion      => $discussion,
+                       };
+                       $messages->create($users->[0], MSG_CODE_COMMENT_REPLY, $data);
+                       $users{$users->[0]}++;
+               }
+       }
+
+       # reply to journal
+       if ($messages && ($kinds->{ $discussion->{dkid} } eq "journal" || $kinds->{ $discussion->{dkid} } =~ /^journal/ && $constants->{messages_send_journal_story_comments})) {
+               my $users  = $messages->checkMessageCodes(MSG_CODE_JOURNAL_REPLY, [$discussion->{uid}]);
+               if (_send_comment_msg($users->[0], \%users, $pts, $clean_comment)) {
+                       my $data  = {
+                               template_name   => 'journrep',
+                               template_page   => 'comments',
+                               subject         => {
+                                       template_name => 'journrep_subj',
+                                       template_page => 'comments',
+                               },
+                               reply           => $reply,
+                               discussion      => $discussion,
+                       };
+
+                       $messages->create($users->[0], MSG_CODE_JOURNAL_REPLY, $data);
+                       $users{$users->[0]}++;
+               }
+       }
+
+       # comment posted
+       if ($messages && $constants->{commentnew_msg}) {
+               my $users = $messages->getMessageUsers(MSG_CODE_NEW_COMMENT);
+
+               my $data  = {
+                       template_name   => 'commnew',
+                       template_page   => 'comments',
+                       subject         => {
+                               template_name => 'commnew_subj',
+                               template_page => 'comments',
+                       },
+                       reply           => $reply,
+                       discussion      => $discussion,
+               };
+
+               my @users_send;
+               for my $usera (@$users) {
+                       next if $users{$usera};
+                       push @users_send, $usera;
+                       $users{$usera}++;
+               }
+               $messages->create(\@users_send, MSG_CODE_NEW_COMMENT, $data) if @users_send;
+       }
+
+       my $achievements = getObject('Slash::Achievements');
+       if ($achievements) {
+               $achievements->setUserAchievement('comment_posted', $user->{uid});
+       }
+
+       my $dynamic_blocks = getObject('Slash::DynamicBlocks');
+       if ($dynamic_blocks) {
+               $dynamic_blocks->setUserBlock('comments', $user->{uid});
+       }
+
+       if ($constants->{validate_html}) {
+               my $validator = getObject('Slash::Validator');
+               my $test = parseDomainTags($comment->{comment});
+               $validator->isValid($test, {
+                       data_type       => 'comment',
+                       data_id         => $maxCid,
+                       message         => 1
+               }) if $validator;
+       }
+
+       return $saved_comment;
+}
+
 1;