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 viewing of a topic.
9
 
10
package Codestriker::Action::ViewTopic;
11
 
12
use strict;
13
 
14
use Codestriker::Model::Topic;
15
use Codestriker::Model::Comment;
16
use Codestriker::Http::UrlBuilder;
17
use Codestriker::Http::Render;
18
use Codestriker::Repository::RepositoryFactory;
19
use Codestriker::TopicListeners::Manager;
20
 
21
# If the input is valid, display the topic.
22
sub process($$$) {
23
    my ($type, $http_input, $http_response) = @_;
24
 
25
    my $query = $http_response->get_query();
26
 
27
    my $topicid = $http_input->get('topic');
28
    my $mode = $http_input->get('mode');
29
    my $brmode = $http_input->get('brmode');
30
    my $fview = $http_input->get('fview');
31
    my $tabwidth = $http_input->get('tabwidth');
32
    my $email = $http_input->get('email');
33
    my $feedback = $http_input->get('feedback');
34
 
35
    if (Codestriker::Model::Topic::exists($topicid) == 0) {
36
	# Topic no longer exists, most likely its been deleted.
37
	$http_response->error("Topic no longer exists.");
38
    }
39
 
40
    # Retrieve the appropriate topic details.           
41
    my $topic = Codestriker::Model::Topic->new($topicid);     
42
 
43
    # Retrieve the comment details for this topic, firstly determine how
44
    # many distinct comment lines are there.
45
    my @comments = $topic->read_comments();
46
    my %comment_map = ();
47
    foreach my $comment (@comments) {
48
	my $key = $comment->{filenumber} . "|" . $comment->{fileline} . "|" .
49
	    $comment->{filenew};
50
	if (! exists $comment_map{$key}) {
51
	    $comment_map{$key} = 1;
52
	}
53
    }
54
 
55
    # Retrieve the changed files which are a part of this review.
56
    my (@filenames, @revisions, @offsets, @binary, @numchanges);
57
    $topic->get_filestable(
58
    		\@filenames,
59
                \@revisions,
60
                \@offsets,
61
                \@binary,
62
                \@numchanges);
63
 
64
    # Retrieve line-by-line versions of the data and description.
65
    my @document_description = split /\n/, $topic->{description};
66
 
67
    $http_response->generate_header(topic=>$topic,
68
				    comments=>\@comments,
69
				    topic_title=>"Topic Text: $topic->{title}",
70
				    mode=>$mode, tabwidth=>$tabwidth,
71
				    fview=>$fview,
72
				    reload=>0, cache=>1);
73
 
74
    # Retrieve the repository object, if repository functionality is enabled.
75
    my $repository;
76
    if (scalar(@Codestriker::valid_repositories)) {
77
	$repository =
78
	    Codestriker::Repository::RepositoryFactory->get($topic->{repository});
79
    } else {
80
	# Indicate not to activate any repository-related links.
81
	$topic->{repository} = "";
82
    }
83
 
84
    # Create the hash for the template variables.
85
    my $vars = {};
86
    $vars->{'feedback'} = $feedback;
87
 
88
    # Create the necessary template variables for generating the heading part
89
    # of the view topic display.
90
 
91
    # Obtain a new URL builder object.
92
    my $url_builder = Codestriker::Http::UrlBuilder->new($query);
93
 
94
    ProcessTopicHeader($vars, $topic, $url_builder);
95
 
96
    # Display the "update" message if the topic state has been changed.
97
    $vars->{'updated'} = $http_input->get('updated');
98
    $vars->{'rc_ok'} = $Codestriker::OK;
99
    $vars->{'rc_stale_version'} = $Codestriker::STALE_VERSION;
100
    $vars->{'rc_invalid_topic'} = $Codestriker::INVALID_TOPIC;
101
 
102
    if ($topic->{bug_ids} ne "") {
103
	my @bugs = split ', ', $topic->{bug_ids};
104
	my $bug_string = "";
105
	for (my $i = 0; $i <= $#bugs; $i++) {
106
	    $bug_string .=
107
		$query->a({href=>"$Codestriker::bugtracker$bugs[$i]"},
108
			  $bugs[$i]);
109
	    $bug_string .= ', ' unless ($i == $#bugs);
110
	}
111
	$vars->{'bug_string'} = $bug_string;
112
    } else {
113
	$vars->{'bug_string'} = "";
114
    }
115
 
116
    $vars->{'document_reviewers'} = 
117
    	Codestriker->filter_email($topic->{reviewers});
118
    $vars->{'project_name'} = $topic->{project_name};
119
    $vars->{'number_of_lines'} = $topic->get_topic_size_in_lines();
120
 
121
    $vars->{'suggested_topic_size_lines'} =
122
	$Codestriker::suggested_topic_size_lines eq "" ? 0 :
123
	$Codestriker::suggested_topic_size_lines;    
124
 
125
    # Prepare the data for displaying the state update option.
126
    # Make sure the old mode setting is no longer used.
127
    if ((! defined $mode) || $mode == $Codestriker::NORMAL_MODE) {
128
	$mode = $Codestriker::COLOURED_MODE;
129
    }
130
    if (! defined $brmode) {
131
        $brmode = $Codestriker::default_topic_br_mode;
132
    }
133
    if (! defined $fview) {
134
	    $fview = $Codestriker::default_file_to_view;
135
	    if (! defined $fview) {
136
		$fview = -1;
137
	    }
138
    }
139
    $vars->{'mode'} = $mode;
140
    $vars->{'brmode'} = $brmode;
141
    $vars->{'states'} = \@Codestriker::topic_states;
142
    $vars->{'default_state'} = $topic->{state};
143
 
144
    # Set the description of the topic.
145
    my $data = "";
146
    for (my $i = 0; $i <= $#document_description; $i++) {
147
	$data .= $document_description[$i] . "\n";
148
    }
149
    $vars->{'description'} = $data;
150
 
151
    # Obtain the link to download the actual document text.
152
    $vars->{'download_url'} = $url_builder->download_url($topicid);
153
 
154
    # Fire the template on the topic heading information.
155
    my $template = Codestriker::Http::Template->new("viewtopic");
156
    $template->process($vars);
157
 
158
    # The rest of the output is non-template driven, as it is quite
159
    # complex.
160
 
161
    # Give the user the option of swapping between diff view modes.
162
    # If there are no files associated with the review, remove this
163
    # option.
164
    my $coloured_url =
165
	$url_builder->view_url($topicid, -1, $Codestriker::COLOURED_MODE,
166
			       $brmode, $fview);
167
    my $coloured_mono_url =
168
	$url_builder->view_url($topicid, -1,
169
			       $Codestriker::COLOURED_MONO_MODE, $brmode, $fview);
170
    my $br_normal_url =
171
	$url_builder->view_url($topicid, -1, $mode,
172
			       $Codestriker::LINE_BREAK_NORMAL_MODE, $fview);
173
    my $br_assist_url =
174
	$url_builder->view_url($topicid, -1, $mode,
175
			       $Codestriker::LINE_BREAK_ASSIST_MODE, $fview);
176
 
177
    if ($mode == $Codestriker::COLOURED_MODE) {
178
	print " View in " .
179
	    $query->a({href=>$coloured_mono_url}, "monospace font") .
180
	    " | ";
181
    } elsif ($mode == $Codestriker::COLOURED_MONO_MODE) {
182
	print " View in " .
183
	    $query->a({href=>$coloured_url}, "variable-width font") .
184
	    " | ";
185
    }
186
 
187
    if ($brmode == $Codestriker::LINE_BREAK_NORMAL_MODE) {
188
	print " View with " .
189
	    $query->a({href=>$br_assist_url}, "minimal screen width") . ".";
190
    } elsif ($brmode == $Codestriker::LINE_BREAK_ASSIST_MODE) {
191
	print " View with " .
192
	    $query->a({href=>$br_normal_url}, "minimal line breaks") . ".";
193
    }
194
    print " | ";
195
 
196
    # Display the option to change the tab width.
197
    my $newtabwidth = ($tabwidth == 4) ? 8 : 4;
198
    my $change_tabwidth_url;
199
    $change_tabwidth_url =
200
	$url_builder->view_url_extended($topicid, -1, $mode, $newtabwidth,
201
					"", "", 0, $brmode, $fview);
202
 
203
    print " Tab width set to $tabwidth (";
204
    print $query->a({href=>"$change_tabwidth_url"},"change to $newtabwidth");
205
    print ")\n";
206
 
207
    print $query->p if ($mode == $Codestriker::NORMAL_MODE);
208
 
209
    # Number of characters the line number should take, need the real lines
210
    # not the number of changed lines.
211
    my @document = split /\n/, $topic->{document};
212
    my $max_digit_width = length($#document+1);
213
 
214
    # Build the render which will be used to build this page.
215
    my $render = Codestriker::Http::Render->new($query, $url_builder, 1,
216
						$max_digit_width, $topicid,
217
						$mode, \@comments, $tabwidth,
218
						$repository, \@filenames,
219
						\@revisions, \@binary,
220
						\@numchanges, -1,
221
						$brmode, $fview);
222
 
223
    # Display the data that is being reviewed.
224
    $render->start();
225
 
226
    # Retrieve the delta set comprising this review.
227
 
228
    my $old_filename = "";
229
 
230
    # Determine which deltas are to be retrieved.
231
    my @deltas = ();
232
    if ($fview != -1) {
233
	# Get only the deltas for the selected file.    
234
        @deltas = Codestriker::Model::Delta->get_delta_set($topicid, $fview);
235
    }
236
    else {
237
	# Get the whole delta data.
238
        @deltas = Codestriker::Model::Delta->get_delta_set($topicid, -1);
239
    }
240
 
241
    # Now render the selected deltas.
242
    for (my $i = 0; $i <= $#deltas; $i++) {
243
	my $delta =  $deltas[$i];
244
	$render->delta($delta);
245
    }
246
 
247
    $render->finish();
248
 
249
    # Render the HTML trailer.
250
    my $trailer = Codestriker::Http::Template->new("trailer");
251
    $trailer->process();
252
 
253
    print $query->end_html();
254
 
255
    $http_response->generate_footer();
256
 
257
    # Fire the topic listener to indicate that the user has viewed the topic.
258
    Codestriker::TopicListeners::Manager::topic_viewed($email, $topic);
259
}
260
 
261
# This function is used by all of the view topic tabs to fill out the
262
# common template items that are required by all, in addition to the view
263
# topic file action.
264
sub ProcessTopicHeader
265
{
266
    my ($vars, $topic, $url_builder) = @_;
267
 
268
    # Handle the links in the three topic tabs.
269
    $vars->{'view_topicinfo_url'} =
270
	$url_builder->view_topicinfo_url($topic->{topicid});
271
    $vars->{'view_topic_url'} =
272
	## XX mode, last param
273
	$url_builder->view_url($topic->{topicid}, -1, 0);
274
 
275
    $vars->{'view_comments_url'} =
276
	$url_builder->view_comments_url($topic->{topicid});
277
 
278
    $vars->{'view_topic_properties_url'} =
279
	$url_builder->view_topic_properties_url($topic->{topicid});
280
 
281
    my @project_ids = ($topic->{project_id});
282
    $vars->{'list_open_topics_in_project_url'} =
283
	$url_builder->list_topics_url("", "", "", "", "", "", "", "", "",
284
				      "", [ 0 ], \@project_ids);
285
 
286
    # Retrieve the comment details for this topic.
287
    my @comments = $topic->read_comments();
288
 
289
    # Obtains how many comments there are, and the internal link to them.
290
    $vars->{'number_comments'} = $#comments + 1;
291
 
292
    # Obtain the view topic summary information, the title, bugs it relates
293
    # to, and who the participants are.
294
    $vars->{'title'} = $topic->{title};
295
 
296
    $vars->{'author'} = Codestriker->filter_email($topic->{author});
297
 
298
    $vars->{'document_creation_time'} = 
299
	Codestriker->format_timestamp($topic->{creation_ts});
300
 
301
    $vars->{'topic'} = $topic->{topicid};
302
 
303
    $vars->{'reviewers'} = Codestriker->filter_email($topic->{reviewers});
304
    $vars->{'cc'} =  Codestriker->filter_email($topic->{cc});
305
 
306
    # Get the list of obsoleted topics.
307
    my @obsoleted_topics = ();
308
    foreach my $id (@{ $topic->{obsoleted_topics} }) {
309
	my $obsoleted_topic = Codestriker::Model::Topic->new($id);
310
	my $entry = {};
311
	$entry->{title} = $obsoleted_topic->{title};
312
	$entry->{view_url} = $url_builder->view_url($id, -1);
313
	push @obsoleted_topics, $entry;
314
    }
315
    $vars->{'obsoleted_topics'} = \@obsoleted_topics;
316
 
317
    # Get the list of topics this has been obsoleted by.
318
    my @obsoleted_by = ();
319
    foreach my $id (@{ $topic->{obsoleted_by} }) {
320
	my $superseeded_topic = Codestriker::Model::Topic->new($id);
321
	my $entry = {};
322
	$entry->{title} = $superseeded_topic->{title};
323
	$entry->{view_url} = $url_builder->view_url($id, -1);
324
	push @obsoleted_by, $entry;
325
    }
326
    $vars->{'obsoleted_by'} = \@obsoleted_by;
327
    #
328
    # 29-Aug-07 SJK: Add optional URL 
329
    #
330
    $vars->{'desc_url'} = $topic->{desc_url};
331
}
332
 
333
 
334
1;