Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1293 dpurdie 1
###############################################################################
2
# Codestriker: Copyright (c) 2001, 2002 David Sitsky.  All rights reserved.
3
# sits@users.sourceforge.net
4
#
5
# This program is free software; you can redistribute it and modify it under
6
# the terms of the GPL.
7
 
8
# Action object for handling the submission of a new comment.
9
 
10
package Codestriker::Action::SubmitNewComment;
11
 
12
use strict;
13
 
14
use HTML::Entities ();
15
use Codestriker::Model::Comment;
16
use Codestriker::Model::File;
17
use Codestriker::Model::Topic;
18
use Codestriker::Http::Render;
19
 
20
# If the input is valid, create the appropriate topic into the database.
21
sub process($$$) {
22
    my ($type, $http_input, $http_response) = @_;
23
 
24
    # Obtain a new URL builder object.
25
    my $query = $http_response->get_query();
26
    my $url_builder = Codestriker::Http::UrlBuilder->new($query);
27
 
28
    # Check that the appropriate fields have been filled in.
29
    my $topicid = $http_input->get('topic');
30
    my $line = $http_input->get('line');
31
    my $fn = $http_input->get('fn');
32
    my $new = $http_input->get('new');
33
    my $comments = $http_input->get('comments');
34
    my $email = $http_input->get('email');
35
    my $cc = $http_input->get('comment_cc');
36
    my $mode = $http_input->get('mode');
37
    my $anchor = $http_input->get('a');
38
    my $format = $http_input->get('format');
39
 
40
    # Check that the fields have been filled appropriately.
41
    if ($comments eq "" || !defined $comments) {
42
	$http_response->error("No comments were entered");
43
    }
44
    if ($email eq "" || !defined $email) {
45
	$http_response->error("No email address was entered");
46
    }
47
 
48
    # Retrieve the comment metric values.
49
    my @metrics = ();
50
    foreach my $comment_state_metric (@{$Codestriker::comment_state_metrics}) {
51
	my $name = "comment_state_metric_" . $comment_state_metric->{name};
52
	my $metric = {};
53
	$metric->{name} = $comment_state_metric->{name};
54
	$metric->{value} = $http_input->get($name);
55
	if ($metric->{value} eq "Select Value") {
56
	    $http_response->error("Metric value for $metric->{name} unspecified");
57
	}
58
	push @metrics, $metric;
59
    }
60
 
61
    # Retrieve the appropriate topic details.
62
    my $topic = Codestriker::Model::Topic->new($topicid); 
63
 
64
    # Don't accept any new comments if the topic state is read only.
65
    if (Codestriker::topic_readonly($topic->{topic_state})) {
66
	$http_response->error("Topic state is read only");
67
    }
68
 
69
    # Fire the topic listener to indicate that the user has viewed the topic.
70
    Codestriker::TopicListeners::Manager::topic_viewed($email, $topic);
71
 
72
    # Create the comment in the database.
73
    my $comment = Codestriker::Model::Comment->new();
74
    $comment->create($topicid, $line, $fn, $new,
75
		     $email, $comments, \@metrics);
76
    $comment->{cc} = $cc;
77
 
78
    # Tell the listener classes that a comment has just been created.
79
    my $listener_response = 
80
    	Codestriker::TopicListeners::Manager::comment_create($topic, $comment);
81
 
82
    if (defined $format && $format eq "xml") {
83
	my $response = $listener_response ne '' ? $listener_response : 'OK';
84
 
85
	print $query->header(-content_type=>'text/xml');
86
	print "<?xml version=\"1.0\" encoding=\"UTF-8\" " .
87
	            "standalone=\"yes\"?>\n";
88
	print "<response><method>submitnewcomment</method>" .
89
	    "<result>" . HTML::Entities::encode($response) .
90
	    "</result></response>\n";
91
    } else {
92
	$http_response->error($listener_response) if $listener_response ne '';
93
	# Display a simple screen indicating that the comment has been
94
	# registered.  Clicking the Close button simply dismisses the
95
	# edit popup.  Leaving it # up will ensure the next editing
96
	# topic will be handled quickly, as the # overhead of bringing
97
	# up a new window is removed.
98
	my $reload = $query->param('submit') eq 'Submit+Refresh' ? 1 : 0;
99
	$http_response->generate_header(topic=>$topic,
100
					topic_title=>"Comment Submitted: " .
101
					             "$topic->{title}",
102
					email=>$email, 
103
					repository=>$Codestriker::repository_name_map->{$topic->{repository}},
104
					load_anchor=>$anchor,
105
					reload=>$reload, cache=>0);
106
 
107
	my $view_topic_url = $url_builder->view_url($topicid, $line, $mode);
108
	my $view_comments_url = $url_builder->view_comments_url($topicid);
109
 
110
	my $vars = {};
111
	$vars->{'view_topic_url'} = $view_topic_url;
112
	$vars->{'view_comments_url'} = $view_comments_url;
113
	$vars->{'comment'} = $comment->{data};
114
 
115
	my $template = Codestriker::Http::Template->new("submitnewcomment");
116
	$template->process($vars);
117
 
118
	$http_response->generate_footer();
119
    }
120
}
121
 
122
# Given a topic and topic line number, try to determine the line
123
# number of the new file it corresponds to.  For topic lines which
124
# were made against '+' lines or unchanged lines, this will give an
125
# accurate result.  For other situations, the number returned will be
126
# approximate.  The results are returned in $filename_ref,
127
# $linenumber_ref and $accurate_ref references.  This is a deprecated method
128
# which is only used for data migration purposes (within checksetup.pl and
129
# import.pl).
130
sub _get_file_linenumber ($$$$$$$$)
131
{
132
    my ($type, $topic, $topic_linenumber, $filenumber_ref,
133
	$filename_ref, $linenumber_ref, $accurate_ref, $new_ref) = @_;
134
 
135
    # Find the appropriate file that $topic_linenumber refers to.
136
    my (@filename, @revision, @offset, @binary);
137
    Codestriker::Model::File->get_filetable($topic, \@filename, \@revision,
138
					    \@offset, \@binary);
139
    # No filetable.
140
    return 0 if ($#filename == -1);
141
 
142
    my $diff_limit = -1;
143
    my $index;
144
    for ($index = 0; $index <= $#filename; $index++) {
145
	last if ($offset[$index] > $topic_linenumber);
146
    }
147
 
148
    # Check if the comment was made against a diff header.
149
    if ($index <= $#offset) {
150
	my $diff_header_size;
151
	if ($revision[$index] eq $Codestriker::ADDED_REVISION ||
152
	    $revision[$index] eq $Codestriker::REMOVED_REVISION) {
153
	    # Added or removed file.
154
	    $diff_header_size = 6;
155
	}
156
	elsif ($revision[$index] eq $Codestriker::PATCH_REVISION) {
157
	    # Patch file
158
	    $diff_header_size = 3;
159
	}
160
	else {
161
	    # Normal CVS diff header.
162
	    $diff_header_size = 7;
163
	}
164
 
165
	if ( ($topic_linenumber >=
166
	      $offset[$index] - $diff_header_size) &&
167
	     ($topic_linenumber <= $offset[$index]) ) {
168
	    $$filenumber_ref = $index;
169
	    $$filename_ref = $filename[$index];
170
	    $$linenumber_ref = 1;
171
	    $$accurate_ref = 0;
172
	    $$new_ref = 0;
173
	    return 1;
174
	}
175
    }
176
    $index--;
177
 
178
    # Couldn't find a matching linenumber.
179
    if ($index < 0 || $index > $#filename) {
180
	$$filenumber_ref = -1;
181
	$$filename_ref = "";
182
	return 1;
183
    }
184
 
185
    # Retrieve the diff text corresponding to this file.
186
    my ($tmp_offset, $tmp_revision, $diff_text);
187
    Codestriker::Model::File->get($topic, $index, \$tmp_offset,
188
				  \$tmp_revision, \$diff_text);
189
 
190
    # Go through the patch file until we reach the topic linenumber of
191
    # interest.
192
    my $new = 0;
193
    my $accurate_line = 0;
194
    my $oldfile_linenumber = 0;
195
    my $newfile_linenumber = 0;
196
    my $current_topic_linenumber;
197
    my @lines = split /\n/, $diff_text;
198
    for (my $i = 0, $current_topic_linenumber = $offset[$index];
199
	 $i <= $#lines && $current_topic_linenumber <= $topic_linenumber;
200
	 $i++, $current_topic_linenumber++) {
201
	$_ = $lines[$i];
202
	if (/^\@\@ \-(\d+),\d+ \+(\d+),\d+ \@\@.*$/o) {
203
	    # Matching diff header, record what the current linenumber is now
204
	    # in the new file.
205
	    $oldfile_linenumber = $1 - 1;
206
	    $newfile_linenumber = $2 - 1;
207
	    $accurate_line = 0;
208
	    $new = 0;
209
	}
210
	elsif (/^\s.*$/o) {
211
	    # A line with no change.
212
	    $oldfile_linenumber++;
213
	    $newfile_linenumber++;
214
	    $accurate_line = 1;
215
	    $new = 1;
216
	}
217
	elsif (/^\+.*$/o) {
218
	    # A line corresponding to the new file.
219
	    $newfile_linenumber++;
220
	    $accurate_line = 1;
221
	    $new = 1;
222
	}
223
	elsif (/^\-.*$/o) {
224
	    # A line corresponding to the old file.
225
	    $oldfile_linenumber++;
226
	    $accurate_line = 0;
227
	    $new = 0;
228
	}
229
    }
230
 
231
    if ($current_topic_linenumber >= $topic_linenumber) {
232
	# The topic linenumber was found.
233
	$$filenumber_ref = $index;
234
	$$filename_ref = $filename[$index];
235
	$$linenumber_ref = $new ? $newfile_linenumber : $oldfile_linenumber;
236
	$$accurate_ref = $accurate_line;
237
	$$new_ref = $new;
238
    }
239
    else {
240
	# The topic linenumber was not found.
241
	$$filenumber_ref = -1;
242
	$$filename_ref = "";
243
    }
244
    return 1;
245
}
246
 
247
1;