[system] / branches / rel-2-1-patches / webwork-modperl / lib / WeBWorK / ContentGenerator / Instructor / PGProblemEditor.pm Repository:
ViewVC logotype

Annotation of /branches/rel-2-1-patches/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1747 - (view) (download) (as text)
Original Path: trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm

1 : sh002i 1663 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4 : gage 1747 # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v 1.22 2003/12/12 02:24:30 gage Exp $
5 : sh002i 1663 #
6 :     # This program is free software; you can redistribute it and/or modify it under
7 :     # the terms of either: (a) the GNU General Public License as published by the
8 :     # Free Software Foundation; either version 2, or (at your option) any later
9 :     # version, or (b) the "Artistic License" which comes with this package.
10 :     #
11 :     # This program is distributed in the hope that it will be useful, but WITHOUT
12 :     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 :     # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14 :     # Artistic License for more details.
15 :     ################################################################################
16 :    
17 : gage 889 package WeBWorK::ContentGenerator::Instructor::PGProblemEditor;
18 :     use base qw(WeBWorK::ContentGenerator::Instructor);
19 :    
20 :    
21 :     =head1 NAME
22 :    
23 :     WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list
24 :    
25 :     =cut
26 :    
27 :     use strict;
28 :     use warnings;
29 :     use CGI qw();
30 :     use WeBWorK::Utils qw(readFile);
31 : gage 925 use Apache::Constants qw(:common REDIRECT);
32 : gage 889
33 : gage 925
34 : gage 889 our $libraryName;
35 :     our $rowheight;
36 :    
37 :     sub title {
38 :     my $self = shift;
39 : gage 892 #FIXME don't need the entire path ??
40 : gage 1591 return "Instructor Tools - PG Problem Editor ";
41 : gage 889 }
42 : gage 1747
43 :     sub header { #FIXME this should be moved up to ContentGenerator
44 :     my $self = shift;
45 :     return REDIRECT if $self->{noContent};
46 :     my $r = $self->{r};
47 :     $r->content_type('text/html');
48 :     $r->send_http_header();
49 :     return OK;
50 :     }
51 :    
52 :     ###########################################################
53 :     # This editor will edit problem files or set header files or files, such as course_info
54 :     # whose name is defined in the global.conf database
55 :     #
56 :     # Only files under the template directory ( or linked to this location) can be edited.
57 :     #
58 :     # The course information and problems are located in the course templates directory.
59 :     # Course information has the name defined by courseFiles->{course_info}
60 :     #
61 :     # Only files under the template directory ( or linked to this location) can be edited.
62 :     #
63 :     # editMode = temporaryFile (view the temp file defined by course_info.txt.user_name.tmp
64 :     # instead of the file course_info.txt)
65 :     # The editFileSuffix is "user_name.tmp" by default. It's definition should be moved to Instructor.pm #FIXME
66 :     ###########################################################
67 :    
68 :     sub pre_header_initialize {
69 : gage 925 my $self = shift;
70 :     my ($setName, $problemNumber) = @_;
71 :     my $r = $self->{r};
72 :     my $ce = $self->{ce};
73 :     my $submit_button = $r->param('submit'); # obtain submit command from form
74 : gage 889
75 : gage 1747 #####################################################
76 :     # Save problem to permanent or temporary file
77 :     # Then redirect for viewing
78 :     #####################################################
79 : gage 925 if ( defined($submit_button) and ($submit_button eq 'Save' or $submit_button eq 'Refresh') ) {
80 :    
81 : gage 1747 $self->saveFileChanges($setName,$problemNumber); # write the necessary files
82 : gage 925 # return file path for viewing problem
83 : gage 981 # in $self->{currentSourceFilePath}
84 : gage 1747 # obtain the appropriate seed.
85 : gage 925 #redirect to view the problem
86 :    
87 : gage 1747 my $hostname = $r->hostname();
88 :     my $port = $r->get_server_port();
89 :     my $uri = $r->uri;
90 :     my $courseName = $self->{ce}->{courseName};
91 :     my $problemSeed = ($r->param('problemSeed')) ? $r->param('problemSeed') : '';
92 :     my $displayMode = ($r->param('displayMode')) ? $r->param('displayMode') : '';
93 :     my $viewURL = '';
94 : gage 1352 if ($self->{file_type} eq 'problem') {
95 :     # redirect to have problem read by Problem.pm
96 : gage 1747 $viewURL = "http://$hostname:$port";
97 : gage 1352 $viewURL .= $ce->{webworkURLs}->{root}."/$courseName/$setName/$problemNumber/?";
98 :     $viewURL .= $self->url_authen_args;
99 :     $viewURL .= "&displayMode=$displayMode&problemSeed=$problemSeed"; # optional displayMode and problemSeed overrides
100 :     if ($submit_button eq 'Save') {
101 : gage 1747 $viewURL .= "&editMode=savedFile";
102 : gage 1352 } else {
103 : gage 1747 $viewURL .= "&editMode=temporaryFile";
104 : gage 1352 }
105 :     $viewURL .= '&sourceFilePath='. $self->{currentSourceFilePath}; # path to pg text for viewing
106 : gage 1591 # allows Problem.pg to recognize state
107 :     # of problem being viewed.
108 : gage 1352 } elsif ($self->{file_type} eq 'set_header') {
109 :     # redirect set headers to ProblemList page
110 :     $viewURL = "http://$hostname:$port";
111 :     $viewURL .= $ce->{webworkURLs}->{root}."/$courseName/$setName/?";
112 :     $viewURL .= $self->url_authen_args;
113 :     $viewURL .= "&displayMode=$displayMode&problemSeed=$problemSeed"; # optional displayMode and problemSeed overrides
114 :     if ($submit_button eq 'Save') {
115 : gage 1747 $viewURL .= "&editMode=savedFile";
116 :     } else {
117 :     $viewURL .= "&editMode=temporaryFile";
118 : gage 1352 }
119 : gage 1747 } elsif ($self->{file_type} eq 'course_info' ) {
120 :     $viewURL = "http://$hostname:$port";
121 :     $viewURL .= $ce->{webworkURLs}->{root}."/$courseName/?";
122 :     $viewURL .= $self->url_authen_args;
123 :     if ($submit_button eq 'Save') {
124 :     $viewURL .= "&editMode=savedFile";
125 :     } else {
126 :     $viewURL .= "&editMode=temporaryFile";
127 :     }
128 :     } else {
129 :     warn "PGProblemEditor does not have facilities for editing files with file_type ".$self->{file_type};
130 : sh002i 1198 }
131 : gage 1747
132 : gage 925 $r->header_out(Location => $viewURL );
133 : gage 1747 $self->{noContent} = 1; # forces redirect
134 :     return;
135 : gage 925 }
136 :    
137 :     }
138 :    
139 : gage 1747 sub initialize {
140 :     my $self = shift;
141 :     my ($setName, $problemNumber) = @_;
142 :     $self -> saveFileChanges(@_);
143 :    
144 :    
145 :    
146 :     }
147 :    
148 :     sub saveFileChanges {
149 : malsyned 980
150 :     my ($self, $setName, $problemNumber) = @_;
151 :     my $ce = $self->{ce};
152 :     my $r = $self->{r};
153 :     my $path_info = $r->path_info || "";
154 :     my $db = $self->{db};
155 :     my $user = $r->param('user');
156 :     my $effectiveUserName = $r->param('effectiveUser');
157 :     my $courseName = $ce->{courseName};
158 : gage 925
159 : gage 1747 $setName = '' unless defined $setName;
160 :     $problemNumber = '' unless defined $problemNumber;
161 : malsyned 980
162 : gage 1747 ##################################################
163 :     # Determine path to the file to be edited.
164 :     ##################################################
165 :     my $templateDirectory = $ce->{courseDirs}->{templates};
166 :     my $editFilePath = $templateDirectory;
167 :     my $problem_record = undef;
168 : malsyned 980
169 : gage 1747 my $file_type = $r->param("file_type") || '';
170 : gage 1348
171 : gage 1747 if ($file_type eq 'course_info' ) {
172 :     $editFilePath .= '/'. $ce->{courseFiles}->{course_info};
173 :     $self->{file_type} = 'course_info';
174 :     # no problem_record is defined in this case
175 :    
176 :     } else { # we areediting a problem file or a set header file
177 :    
178 :     # FIXME there is a discrepancy in the way that the problems are found.
179 :     # FIXME more error checking is needed in case the problem doesn't exist.
180 :     if (defined($problemNumber) and $problemNumber) {
181 :     $problem_record = $db->getMergedProblem($effectiveUserName, $setName, $problemNumber); # checked
182 :     # If there is no global_user defined problem, (i.e. the sets haven't been assigned yet),
183 :     # look for a global version of the problem.
184 :     $problem_record = $db->getGlobalProblem($setName, $problemNumber) unless defined($problem_record); # checked
185 :     # bail if no problem is found
186 :     die "Cannot find a problem record for set $setName / problem $problemNumber"
187 :     unless defined($problem_record);
188 :     $editFilePath .= '/'.$problem_record->source_file;
189 :     $self->{file_type} = 'problem';
190 :     } elsif (defined($problemNumber) and $problemNumber==0) { # we are editing a header file
191 :     my $set_record = $db->getMergedSet($effectiveUserName, $setName); # checked
192 :     die "Cannot find a set record for set $setName" unless defined($set_record);
193 :     $editFilePath .= '/'.$set_record->set_header;
194 :     $self->{file_type} = 'set_header';
195 :     }
196 : gage 1348 }
197 :    
198 : gage 1747
199 :    
200 :    
201 : gage 1591 my $editFileSuffix = $user.'.tmp';
202 : malsyned 980 my $submit_button = $r->param('submit');
203 :    
204 : gage 1747
205 :     ##############################################################################
206 :     # Determine the display mode
207 :     # try to get problem seed from the input parameter, or from the problem record
208 :     # This will be needed for viewing the problem via redirect.
209 :     # They are also two of the parameters which can be set by the editor
210 :     ##############################################################################
211 : malsyned 980 my $displayMode = ( defined($r->param('displayMode')) ) ? $r->param('displayMode') : $ce->{pg}->{options}->{displayMode};
212 : gage 1747
213 : gage 991 my $problemSeed;
214 :     if ( defined($r->param('problemSeed')) ) {
215 :     $problemSeed = $r->param('problemSeed');
216 : gage 1348 } elsif (defined($problem_record) and $problem_record->can('problem_seed')) {
217 : gage 991 $problemSeed = $problem_record->problem_seed;
218 :     }
219 :     # make absolutely sure that the problem seed is defined, if it hasn't been.
220 :     $problemSeed = '123456' unless defined($problemSeed) and $problemSeed =~/\S/;
221 : malsyned 980
222 : gage 1747 ##############################################################################
223 :     # read and update the targetFile and targetFile.tmp files in the directory
224 :     # if a .tmp file already exists use that, unless the revert button has been pressed.
225 :     # These .tmp files are
226 :     # removed when the file is finally saved.
227 :     ##############################################################################
228 :    
229 : malsyned 980 my $problemContents = '';
230 :     my $currentSourceFilePath = '';
231 : gage 1591 my $editErrors = '';
232 : gage 1747
233 :     my $inputFilePath = (-r "$editFilePath.$editFileSuffix")?"$editFilePath.$editFileSuffix" : $editFilePath;
234 :     $inputFilePath = $editFilePath if defined($submit_button) and $submit_button eq 'Revert';
235 : gage 1591
236 :     if (not defined($submit_button) or $submit_button eq 'Revert' ) {
237 : malsyned 980 # this is a fresh editing job
238 :     # copy the pg file to a new file with the same name with .tmp added
239 : gage 981 # store this name in the $self->currentSourceFilePath for use in body
240 : gage 1591 eval { $problemContents = WeBWorK::Utils::readFile($inputFilePath) };
241 :     # try to read file
242 : malsyned 980 $problemContents = $@ if $@;
243 : gage 1105 $editErrors .= $problemContents;
244 : gage 1747 $currentSourceFilePath = "$editFilePath.$editFileSuffix";
245 : gage 981 $self->{currentSourceFilePath} = $currentSourceFilePath;
246 : malsyned 980 } elsif ($submit_button eq 'Refresh' ) {
247 : gage 981 # grab the problemContents from the form in order to save it to the tmp file
248 :     # store tmp file name in the $self->currentSourceFilePath for use in body
249 : malsyned 980
250 :     $problemContents = $r->param('problemContents');
251 : gage 1747 $currentSourceFilePath = "$editFilePath.$editFileSuffix";
252 : gage 981 $self->{currentSourceFilePath} = $currentSourceFilePath;
253 : malsyned 980 } elsif ($submit_button eq 'Save') {
254 : gage 981 # grab the problemContents from the form in order to save it to the permanent file
255 :     # later we will unlink (delete) the temporary file
256 :     # store permanent file name in the $self->currentSourceFilePath for use in body
257 : malsyned 980
258 :     $problemContents = $r->param('problemContents');
259 : gage 1747 $currentSourceFilePath = "$editFilePath";
260 : gage 1591 $self->{currentSourceFilePath} = $currentSourceFilePath;
261 : malsyned 980 } else {
262 :     # give a warning
263 :     die "Unrecognized submit command $submit_button";
264 :     }
265 : gage 1105
266 :     # Handle the problem of line endings. Make sure that all of the line endings. Convert \r\n to \n
267 :     $problemContents =~ s/\r\n/\n/g;
268 :     $problemContents =~ s/\r/\n/g;
269 :    
270 : gage 1747 # FIXME convert all double returns to paragraphs
271 :     $problemContents =~ s/\n\n/\n<p>\n/g;
272 :     ##############################################################################
273 :     #
274 :     # write changes to the approriate files
275 : malsyned 980 # FIXME make sure that the permissions are set correctly!!!
276 :     # Make sure that the warning is being transmitted properly.
277 : gage 1747 ##############################################################################
278 : malsyned 980 eval {
279 :     local *OUTPUTFILE;
280 :     open OUTPUTFILE, ">", $currentSourceFilePath
281 : gage 1348 or die "Failed to write to $currentSourceFilePath.
282 :     It is likely that the permissions in the template directory have not been set correctly.".
283 :     "The web server must be able to create and write to files in the directory containing the problem.
284 :     $!";
285 : malsyned 980 print OUTPUTFILE $problemContents;
286 :     close OUTPUTFILE;
287 :     };
288 : gage 981 # record an error string for later use if there was a difficulty in writing to the file
289 : gage 1747 # FIXME is this string ever inspected?
290 : gage 1183
291 :     my $openTempFileErrors = $@ if $@;
292 :    
293 :     if ( $openTempFileErrors) {
294 : gage 1105
295 : gage 1183 $self->{openTempFileErrors} = "Unable to write to $currentSourceFilePath: $openTempFileErrors";
296 : gage 1105 #diagnose errors:
297 : gage 1183 warn "Editing errors: $openTempFileErrors\n";
298 :     warn "The file $currentSourceFilePath exists. \n " if -e $currentSourceFilePath; #FIXME
299 : gage 1105 warn "The file $currentSourceFilePath cannot be found. \n " unless -e $currentSourceFilePath;
300 :     warn "The file $currentSourceFilePath does not have write permissions. \n"
301 :     if -e $currentSourceFilePath and not -w $currentSourceFilePath;
302 : malsyned 980
303 :    
304 : gage 1105
305 : gage 981 } else {
306 :     # unlink the temporary file if there are no errors and the save button has been pushed
307 :    
308 : gage 1183 $self->{openTempFileErrors} = '';
309 : gage 1747 unlink("$editFilePath.$editFileSuffix") if defined($submit_button) and $submit_button eq 'Save';
310 : malsyned 980 };
311 :    
312 :    
313 : gage 981 # return values for use in the body subroutine
314 : gage 1747 $self->{problemPath} = $editFilePath;
315 : gage 1591 $self->{inputFilePath} = $inputFilePath;
316 :     $self->{displayMode} = $displayMode;
317 :     $self->{problemSeed} = $problemSeed;
318 :     $self->{r_problemContents} = \$problemContents;
319 : gage 1747 $self->{editFileSuffix} = $editFileSuffix;
320 : malsyned 980
321 : gage 1747
322 : malsyned 980
323 :    
324 :     }
325 : gage 1747 sub saveFile {
326 :     my $self = shift;
327 :    
328 : malsyned 980
329 : gage 1747
330 :    
331 :    
332 :    
333 :     }
334 : gage 1295 sub path {
335 :     my $self = shift;
336 : gage 1747 my $r = $self->{r};
337 :     my $set_id = '';
338 :     my $problem_id = '';
339 :     unless (defined( $r->param("file_type") and $r->param("file_type") eq 'course_info' ) ){
340 :     $set_id = shift;
341 :     $problem_id = shift;
342 :     }
343 :     #FIXME this is a bad way to pass the args, since it's position changes if the set/problem info
344 :     # isn't there
345 : gage 1295 my $args = $_[-1];
346 : gage 1747
347 : gage 1295 my $ce = $self->{ce};
348 :     my $root = $ce->{webworkURLs}->{root};
349 :     my $courseName = $ce->{courseName};
350 :     return $self->pathMacro($args,
351 :     "Home" => "$root",
352 :     $courseName => "$root/$courseName",
353 :     'instructor' => "$root/$courseName/instructor",
354 :     'sets' => "$root/$courseName/instructor/sets/",
355 : gage 1591 "$set_id" => "$root/$courseName/instructor/sets/$set_id/",
356 : gage 1295 "problems" => "$root/$courseName/instructor/sets/$set_id/problems",
357 : gage 1348 "$problem_id" => ''
358 : gage 1295 );
359 :     }
360 : gage 889 sub body {
361 :     my $self = shift;
362 :    
363 :     # test area
364 : gage 981 my $r = $self->{r};
365 :     my $db = $self->{db};
366 :     my $ce = $self->{ce};
367 :     my $user = $r->param('user');
368 : gage 889
369 :    
370 : gage 1667
371 : gage 889 ################
372 :     # Gathering info
373 :     # What is needed
374 : gage 1747 # $editFilePath --
375 : gage 892 # $formURL -- given by $r->uri
376 : gage 889 # $tmpProblemPath
377 : gage 1747 my $editFilePath = $self->{problemPath}; # path to the permanent file to be edited
378 :     my $inputFilePath = $self->{inputFilePath}; # path to the file currently being worked with (might be a .tmp file)
379 : gage 889
380 : gage 892
381 : gage 889
382 :    
383 :    
384 : gage 1591 my $header = CGI::i("Editing problem: $inputFilePath");
385 : gage 889
386 :     #########################################################################
387 : gage 892 # Find the text for the problem, either in the tmp file, if it exists
388 :     # or in the original file in the template directory
389 :     #########################################################################
390 : gage 1591 my $problemContents = ${$self->{r_problemContents}};
391 : gage 1105
392 : gage 1747 # eval { $problemContents = WeBWorK::Utils::readFile($editFilePath) }; # try to read file
393 : gage 1591 # $problemContents = $@ if $@;
394 : gage 889
395 : gage 925
396 :    
397 :     #########################################################################
398 :     # Format the page
399 :     #########################################################################
400 : gage 892 # Define parameters for textarea
401 : gage 928 # FIXME
402 :     # Should the seed be set from some particular user instance??
403 :     # The mode list should be obtained from global.conf ultimately
404 : gage 902 my $rows = 20;
405 :     my $columns = 80;
406 : gage 928 my $mode_list = ['plainText','formattedText','images'];
407 :     my $displayMode = $self->{displayMode};
408 :     my $problemSeed = $self->{problemSeed};
409 : gage 925 my $uri = $r->uri;
410 : gage 902 ########################################################################
411 :     # Define a link to view the problem
412 :     #FIXME
413 : gage 892
414 : gage 889 #########################################################################
415 :    
416 :    
417 : gage 1186 warn "Errors in the problem ".CGI::br().$self->{editErrors} if $self->{editErrors};
418 : gage 889
419 : gage 1747
420 : gage 889 return CGI::p($header),
421 : gage 925 #CGI::start_form("POST",$r->uri,-target=>'_problem'), doesn't pass on the target parameter???
422 : gage 1747 qq!<form method="POST" action="$uri" enctype="application/x-www-form-urlencoded", target="_problem">!,
423 : gage 892 $self->hidden_authen_fields,
424 : gage 1352 CGI::hidden(-name=>'file_type',-default=>$self->{file_type}),
425 : gage 902 CGI::div(
426 : gage 1363 'Seed: ',
427 : gage 928 CGI::textfield(-name=>'problemSeed',-value=>$problemSeed),
428 : gage 902 'Mode: ',
429 : gage 928 CGI::popup_menu(-name=>'displayMode', -'values'=>$mode_list,
430 :     -default=>$displayMode),
431 : gage 902 CGI::a(
432 :     {-href=>'http://webwork.math.rochester.edu/docs/docs/pglanguage/manpages/',-target=>"manpage_window"},
433 :     'Manpages',
434 :     )
435 : gage 892 ),
436 : gage 902 CGI::p(
437 :     CGI::textarea(-name => 'problemContents', -default => $problemContents,
438 :     -rows => $rows, -columns => $columns, -override => 1,
439 :     ),
440 :     ),
441 :     CGI::p(
442 : gage 1747 CGI::submit(-value=>'Refresh',-name=>'submit'),
443 : gage 902 CGI::submit(-value=>'Save',-name=>'submit'),
444 : gage 1591 CGI::submit(-value=>'Revert',-name=>'submit'),
445 :     ),
446 : gage 902 CGI::end_form(),
447 : gage 889
448 : gage 925
449 : gage 889 }
450 :    
451 : gage 928
452 : gage 889
453 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9