Rev 1295 | Blame | Compare with Previous | Last modification | View Log | RSS feed
################################################################################ Codestriker: Copyright (c) 2001, 2002 David Sitsky. All rights reserved.# sits@users.sourceforge.net## This program is free software; you can redistribute it and modify it under# the terms of the GPL.# Action object for handling the submission of a new comment.package Codestriker::Action::SubmitNewComment;use strict;use HTML::Entities ();use Codestriker::Model::Comment;use Codestriker::Model::File;use Codestriker::Model::Topic;use Codestriker::Http::Render;# If the input is valid, create the appropriate topic into the database.sub process($$$) {my ($type, $http_input, $http_response) = @_;# Obtain a new URL builder object.my $query = $http_response->get_query();my $url_builder = Codestriker::Http::UrlBuilder->new($query);# Check that the appropriate fields have been filled in.my $topicid = $http_input->get('topic');my $line = $http_input->get('line');my $fn = $http_input->get('fn');my $new = $http_input->get('new');my $comments = $http_input->get('comments');my $email = $http_input->get('email');my $cc = $http_input->get('comment_cc');my $mode = $http_input->get('mode');my $anchor = $http_input->get('a');my $format = $http_input->get('format');# Check that the fields have been filled appropriately.if ($comments eq "" || !defined $comments) {$http_response->error("No comments were entered");}if ($email eq "" || !defined $email) {$http_response->error("No email address was entered");}# Retrieve the comment metric values.my @metrics = ();foreach my $comment_state_metric (@{$Codestriker::comment_state_metrics}) {my $name = "comment_state_metric_" . $comment_state_metric->{name};my $metric = {};$metric->{name} = $comment_state_metric->{name};$metric->{value} = $http_input->get($name);if ($metric->{value} eq "Select Value") {$http_response->error("Metric value for $metric->{name} unspecified");}push @metrics, $metric;}# Retrieve the appropriate topic details.my $topic = Codestriker::Model::Topic->new($topicid);# Don't accept any new comments if the topic state is read only.if (Codestriker::topic_readonly($topic->{topic_state})) {$http_response->error("Topic state is read only");}# Fire the topic listener to indicate that the user has viewed the topic.Codestriker::TopicListeners::Manager::topic_viewed($email, $topic);# Create the comment in the database.my $comment = Codestriker::Model::Comment->new();$comment->create($topicid, $line, $fn, $new,$email, $comments, \@metrics);$comment->{cc} = $cc;# Tell the listener classes that a comment has just been created.my $listener_response =Codestriker::TopicListeners::Manager::comment_create($topic, $comment);if (defined $format && $format eq "xml") {my $response = $listener_response ne '' ? $listener_response : 'OK';print $query->header(-content_type=>'text/xml');print "<?xml version=\"1.0\" encoding=\"UTF-8\" " ."standalone=\"yes\"?>\n";print "<response><method>submitnewcomment</method>" ."<result>" . HTML::Entities::encode($response) ."</result></response>\n";} else {$http_response->error($listener_response) if $listener_response ne '';# Display a simple screen indicating that the comment has been# registered. Clicking the Close button simply dismisses the# edit popup. Leaving it # up will ensure the next editing# topic will be handled quickly, as the # overhead of bringing# up a new window is removed.my $reload = $query->param('submit') eq 'Submit+Refresh' ? 1 : 0;$http_response->generate_header(topic=>$topic,topic_title=>"Comment Submitted: " ."$topic->{title}",email=>$email,repository=>$Codestriker::repository_name_map->{$topic->{repository}},load_anchor=>$anchor,reload=>$reload, cache=>0);my $view_topic_url = $url_builder->view_url($topicid, $line, $mode);my $view_comments_url = $url_builder->view_comments_url($topicid);my $vars = {};$vars->{'view_topic_url'} = $view_topic_url;$vars->{'view_comments_url'} = $view_comments_url;$vars->{'comment'} = $comment->{data};my $template = Codestriker::Http::Template->new("submitnewcomment");$template->process($vars);$http_response->generate_footer();}}# Given a topic and topic line number, try to determine the line# number of the new file it corresponds to. For topic lines which# were made against '+' lines or unchanged lines, this will give an# accurate result. For other situations, the number returned will be# approximate. The results are returned in $filename_ref,# $linenumber_ref and $accurate_ref references. This is a deprecated method# which is only used for data migration purposes (within checksetup.pl and# import.pl).sub _get_file_linenumber ($$$$$$$$){my ($type, $topic, $topic_linenumber, $filenumber_ref,$filename_ref, $linenumber_ref, $accurate_ref, $new_ref) = @_;# Find the appropriate file that $topic_linenumber refers to.my (@filename, @revision, @offset, @binary);Codestriker::Model::File->get_filetable($topic, \@filename, \@revision,\@offset, \@binary);# No filetable.return 0 if ($#filename == -1);my $diff_limit = -1;my $index;for ($index = 0; $index <= $#filename; $index++) {last if ($offset[$index] > $topic_linenumber);}# Check if the comment was made against a diff header.if ($index <= $#offset) {my $diff_header_size;if ($revision[$index] eq $Codestriker::ADDED_REVISION ||$revision[$index] eq $Codestriker::REMOVED_REVISION) {# Added or removed file.$diff_header_size = 6;}elsif ($revision[$index] eq $Codestriker::PATCH_REVISION) {# Patch file$diff_header_size = 3;}else {# Normal CVS diff header.$diff_header_size = 7;}if ( ($topic_linenumber >=$offset[$index] - $diff_header_size) &&($topic_linenumber <= $offset[$index]) ) {$$filenumber_ref = $index;$$filename_ref = $filename[$index];$$linenumber_ref = 1;$$accurate_ref = 0;$$new_ref = 0;return 1;}}$index--;# Couldn't find a matching linenumber.if ($index < 0 || $index > $#filename) {$$filenumber_ref = -1;$$filename_ref = "";return 1;}# Retrieve the diff text corresponding to this file.my ($tmp_offset, $tmp_revision, $diff_text);Codestriker::Model::File->get($topic, $index, \$tmp_offset,\$tmp_revision, \$diff_text);# Go through the patch file until we reach the topic linenumber of# interest.my $new = 0;my $accurate_line = 0;my $oldfile_linenumber = 0;my $newfile_linenumber = 0;my $current_topic_linenumber;my @lines = split /\n/, $diff_text;for (my $i = 0, $current_topic_linenumber = $offset[$index];$i <= $#lines && $current_topic_linenumber <= $topic_linenumber;$i++, $current_topic_linenumber++) {$_ = $lines[$i];if (/^\@\@ \-(\d+),\d+ \+(\d+),\d+ \@\@.*$/o) {# Matching diff header, record what the current linenumber is now# in the new file.$oldfile_linenumber = $1 - 1;$newfile_linenumber = $2 - 1;$accurate_line = 0;$new = 0;}elsif (/^\s.*$/o) {# A line with no change.$oldfile_linenumber++;$newfile_linenumber++;$accurate_line = 1;$new = 1;}elsif (/^\+.*$/o) {# A line corresponding to the new file.$newfile_linenumber++;$accurate_line = 1;$new = 1;}elsif (/^\-.*$/o) {# A line corresponding to the old file.$oldfile_linenumber++;$accurate_line = 0;$new = 0;}}if ($current_topic_linenumber >= $topic_linenumber) {# The topic linenumber was found.$$filenumber_ref = $index;$$filename_ref = $filename[$index];$$linenumber_ref = $new ? $newfile_linenumber : $oldfile_linenumber;$$accurate_ref = $accurate_line;$$new_ref = $new;}else {# The topic linenumber was not found.$$filenumber_ref = -1;$$filename_ref = "";}return 1;}1;