[system] / trunk / webwork2 / lib / WeBWorK / ContentGenerator / Instructor / PGProblemEditor.pm Repository:
ViewVC logotype

Annotation of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2032 - (view) (download) (as text)

1 : sh002i 1663 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4 : jj 2029 # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v 1.29 2004/05/06 21:53:41 jj 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 1980 use HTML::Entities;
33 : jj 2016 use WeBWorK::Utils::Tasks qw(fake_set fake_problem);
34 : gage 889
35 : sh002i 1924 ###########################################################
36 :     # This editor will edit problem files or set header files or files, such as course_info
37 :     # whose name is defined in the global.conf database
38 :     #
39 :     # Only files under the template directory ( or linked to this location) can be edited.
40 :     #
41 :     # The course information and problems are located in the course templates directory.
42 :     # Course information has the name defined by courseFiles->{course_info}
43 :     #
44 :     # Only files under the template directory ( or linked to this location) can be edited.
45 :     #
46 :     # editMode = temporaryFile (view the temp file defined by course_info.txt.user_name.tmp
47 :     # instead of the file course_info.txt)
48 :     # The editFileSuffix is "user_name.tmp" by default. It's definition should be moved to Instructor.pm #FIXME
49 :     ###########################################################
50 : gage 925
51 : sh002i 1924 #our $libraryName;
52 :     #our $rowheight;
53 : gage 889
54 : gage 1747 sub pre_header_initialize {
55 : sh002i 1924 my ($self) = @_;
56 :     my $r = $self->r;
57 :     my $ce = $r->ce;
58 :     my $urlpath = $r->urlpath;
59 : gage 925
60 : sh002i 1924 my $submit_button = $r->param('submit'); # obtain submit command from form
61 :    
62 :     # Save problem to permanent or temporary file, then redirect for viewing
63 :     if (defined($submit_button) and ($submit_button eq 'Save' or $submit_button eq 'Refresh')) {
64 :     my $setName = $r->urlpath->arg("setID");
65 :     my $problemNumber = $r->urlpath->arg("problemID");
66 : gage 925
67 : sh002i 1924 # write the necessary files
68 :     # return file path for viewing problem in $self->{currentSourceFilePath}
69 :     # obtain the appropriate seed
70 :     $self->saveFileChanges($setName, $problemNumber);
71 :    
72 :     ##### calculate redirect URL based on file type #####
73 :    
74 :     # get some information
75 :     #my $hostname = $r->hostname();
76 :     #my $port = $r->get_server_port();
77 :     #my $uri = $r->uri;
78 : gage 1980 my $courseName = $urlpath->arg("courseID");
79 : sh002i 1924 my $problemSeed = ($r->param('problemSeed')) ? $r->param('problemSeed') : '';
80 :     my $displayMode = ($r->param('displayMode')) ? $r->param('displayMode') : '';
81 :    
82 :     my $viewURL = '';
83 :    
84 :     # problems redirect to Problem.pm
85 :     $self->{file_type} eq 'problem' and do {
86 :     my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
87 : jj 2016 courseID => $courseName, setID => $setName, problemID => $problemNumber);
88 :     $viewURL = $self->systemLink($problemPage,
89 : sh002i 1924 params => {
90 : gage 1980 displayMode => $displayMode,
91 :     problemSeed => $problemSeed,
92 :     editMode => ($submit_button eq "Save" ? "savedFile" : "temporaryFile"),
93 :     sourceFilePath => $self->{currentSourceFilePath},
94 :     submiterror => $self->{submiterror},
95 : sh002i 1924 }
96 : jj 2016 );
97 : sh002i 1924 };
98 : jj 2016
99 : sh002i 1924 # set headers redirect to ProblemSet.pm
100 :     $self->{file_type} eq 'set_header' and do {
101 :     my $problemSetPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
102 :     courseID => $courseName, setID => $setName);
103 :     $viewURL = $self->systemLink($problemSetPage,
104 :     params => {
105 :     displayMode => $displayMode,
106 :     problemSeed => $problemSeed,
107 : jj 2016 editMode => ($submit_button eq "Save" ? "savedFile" : "temporaryFile"),
108 : sh002i 1924 }
109 :     );
110 :     };
111 :    
112 :     # course info redirects to ProblemSets.pm
113 :     $self->{file_type} eq 'course_info' and do {
114 :     my $problemSetsPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets",
115 :     courseID => $courseName);
116 :     $viewURL = $self->systemLink($problemSetsPage,
117 :     params => {
118 :     editMode => ($submit_button eq "Save" ? "savedFile" : "temporaryFile"),
119 :     }
120 :     );
121 :     };
122 :    
123 :     if ($viewURL) {
124 :     $self->reply_with_redirect($viewURL);
125 : gage 1747 } else {
126 : sh002i 1924 die "Invalid file_type ", $self->{file_type}, " specified by saveFileChanges";
127 : sh002i 1198 }
128 : gage 925 }
129 :     }
130 :    
131 : gage 1747 sub initialize {
132 : sh002i 1924 my ($self) = @_;
133 :     my $r = $self->r;
134 :    
135 : sh002i 1841 my $setName = $r->urlpath->arg("setID");
136 :     my $problemNumber = $r->urlpath->arg("problemID");
137 : sh002i 1924
138 :     # if we got to initialize(), then saveFileChanges was not called in pre_header_initialize().
139 :     # therefore we call it here:
140 :     $self->saveFileChanges($setName, $problemNumber);
141 :     }
142 : gage 1747
143 : jj 2029 sub title {
144 :     my $self = shift;
145 :     my $r = $self->r;
146 :     my $problemNumber = $r->urlpath->arg("problemID");
147 :     my $file_type = $self->{'file_type'} || '';
148 :     return "Set Header" if($file_type eq 'set_header');
149 :     return "Course Information" if($file_type eq 'course_info');
150 :     return 'Problem ' . $r->{urlpath}->name;
151 :     }
152 :    
153 : sh002i 1924 sub body {
154 :     my ($self) = @_;
155 :     my $r = $self->r;
156 :     my $db = $r->db;
157 :     my $ce = $r->ce;
158 :    
159 :     # Gathering info
160 :     my $editFilePath = $self->{problemPath}; # path to the permanent file to be edited
161 :     my $inputFilePath = $self->{inputFilePath}; # path to the file currently being worked with (might be a .tmp file)
162 :    
163 :     my $header = CGI::i("Editing problem: $inputFilePath");
164 :    
165 :     #########################################################################
166 :     # Find the text for the problem, either in the tmp file, if it exists
167 :     # or in the original file in the template directory
168 :     #########################################################################
169 :    
170 :     my $problemContents = ${$self->{r_problemContents}};
171 :    
172 :     #########################################################################
173 :     # Format the page
174 :     #########################################################################
175 :    
176 :     # Define parameters for textarea
177 :     # FIXME
178 :     # Should the seed be set from some particular user instance??
179 :     # The mode list should be obtained from global.conf ultimately
180 :     my $rows = 20;
181 :     my $columns = 80;
182 :     my $mode_list = ['plainText','formattedText','images'];
183 :     my $displayMode = $self->{displayMode};
184 :     my $problemSeed = $self->{problemSeed};
185 :     my $uri = $r->uri;
186 : jj 2016
187 :     my $force_field = defined($r->param('sourceFilePath')) ?
188 :     CGI::hidden(-name=>'sourceFilePath',
189 :     -default=>$r->param('sourceFilePath')) : '';
190 : sh002i 1924 return CGI::p($header),
191 :     #CGI::start_form("POST",$r->uri,-target=>'_problem'), doesn't pass on the target parameter???
192 :     # THIS IS BECAUSE TARGET IS NOT A PARAMETER OF <FORM>!!!!!!!!
193 :     qq!<form method="POST" action="$uri" enctype="application/x-www-form-urlencoded", target="_problem">!,
194 :     $self->hidden_authen_fields,
195 : jj 2016 $force_field,
196 : sh002i 1924 CGI::hidden(-name=>'file_type',-default=>$self->{file_type}),
197 :     CGI::div(
198 :     'Seed: ',
199 :     CGI::textfield(-name=>'problemSeed',-value=>$problemSeed),
200 :     'Mode: ',
201 :     CGI::popup_menu(-name=>'displayMode', -values=>$mode_list, -default=>$displayMode),
202 :     CGI::a({-href=>'http://webwork.math.rochester.edu/docs/docs/pglanguage/manpages/',-target=>"manpage_window"},
203 :     'Manpages',
204 :     )
205 :     ),
206 :     CGI::p(
207 :     CGI::textarea(
208 :     -name => 'problemContents', -default => $problemContents,
209 :     -rows => $rows, -columns => $columns, -override => 1,
210 :     ),
211 :     ),
212 :     CGI::p(
213 :     CGI::submit(-value=>'Refresh',-name=>'submit'),
214 :     CGI::submit(-value=>'Save', -name=>'submit'),
215 :     CGI::submit(-value=>'Revert', -name=>'submit'),
216 :     CGI::submit(-value=>'Save as',-name=>'submit'),
217 :     CGI::textfield(-name=>'save_to_new_file', -value=>""),
218 :     ),
219 :     CGI::end_form(),
220 :     }
221 : gage 1747
222 : sh002i 1924 ################################################################################
223 :     # Utilities
224 :     ################################################################################
225 : gage 1747
226 : sh002i 1924 # saveFileChanges does most of the work. it is a separate method so that it can
227 :     # be called from either pre_header_initialize() or initilize(), depending on
228 :     # whether a redirect is needed or not.
229 :     #
230 :     # it actually does a lot more than save changes to the file being edited, and
231 :     # sometimes less.
232 : gage 1747
233 :     sub saveFileChanges {
234 : malsyned 980 my ($self, $setName, $problemNumber) = @_;
235 : sh002i 1924 my $r = $self->r;
236 :     my $ce = $r->ce;
237 :     my $db = $r->db;
238 :     my $urlpath = $r->urlpath;
239 :    
240 :     my $courseName = $urlpath->arg("courseID");
241 :     my $user = $r->param('user');
242 :     my $effectiveUserName = $r->param('effectiveUser');
243 : gage 925
244 : sh002i 1924 $setName = '' unless defined $setName;
245 :     $problemNumber = '' unless defined $problemNumber;
246 : malsyned 980
247 : sh002i 1924 ##### Determine path to the file to be edited. #####
248 : malsyned 980
249 : sh002i 1924 my $editFilePath = $ce->{courseDirs}->{templates};
250 :     my $problem_record = undef;
251 : gage 1348
252 : sh002i 1924 my $file_type = $r->param("file_type") || '';
253 : gage 1747
254 : sh002i 1924 if ($file_type eq 'course_info') {
255 :     # we are editing the course_info file
256 :     $self->{file_type} = 'course_info';
257 :    
258 :     # value of courseFiles::course_info is relative to templates directory
259 :     $editFilePath .= '/' . $ce->{courseFiles}->{course_info};
260 :     } else {
261 :     # we are editing a problem file or a set header file
262 :    
263 :     # FIXME there is a discrepancy in the way that the problems are found.
264 :     # FIXME more error checking is needed in case the problem doesn't exist.
265 :     # (i wonder what the above comments mean... -sam)
266 :    
267 :     if (defined $problemNumber) {
268 :     if ($problemNumber == 0) {
269 :     # we are editing a header file
270 :     $self->{file_type} = 'set_header';
271 :    
272 :     # first try getting the merged set for the effective user
273 :     my $set_record = $db->getMergedSet($effectiveUserName, $setName); # checked
274 :    
275 :     # if that doesn't work (the set is not yet assigned), get the global record
276 :     $set_record = $db->getGlobalSet($setName); # checked
277 :    
278 :     # bail if no set is found
279 :     die "Cannot find a set record for set $setName" unless defined($set_record);
280 :    
281 :     $editFilePath .= '/' . $set_record->set_header;
282 :     } else {
283 :     # we are editing a "real" problem
284 :     $self->{file_type} = 'problem';
285 :    
286 :     # first try getting the merged problem for the effective user
287 :     $problem_record = $db->getMergedProblem($effectiveUserName, $setName, $problemNumber); # checked
288 :    
289 :     # if that doesn't work (the problem is not yet assigned), get the global record
290 :     $problem_record = $db->getGlobalProblem($setName, $problemNumber) unless defined($problem_record); # checked
291 :    
292 : jj 2016
293 :     if(not defined($problem_record)) {
294 :     my $forcedSourceFile = $r->param('sourceFilePath');
295 :     # bail if no problem is found and we aren't faking it
296 :     die "Cannot find a problem record for set $setName / problem $problemNumber" unless defined($forcedSourceFile);
297 :     $problem_record = fake_problem($db);
298 :     $problem_record->problem_id($problemNumber);
299 :     $problem_record->source_file($forcedSourceFile);
300 :     }
301 :    
302 : sh002i 1924
303 :     $editFilePath .= '/' . $problem_record->source_file;
304 :     }
305 : gage 1747 }
306 : gage 1348 }
307 :    
308 : sh002i 1924 my $editFileSuffix = $user.'.tmp';
309 :     my $submit_button = $r->param('submit');
310 : gage 1747
311 :     ##############################################################################
312 :     # Determine the display mode
313 :     # try to get problem seed from the input parameter, or from the problem record
314 :     # This will be needed for viewing the problem via redirect.
315 :     # They are also two of the parameters which can be set by the editor
316 :     ##############################################################################
317 : sh002i 1924
318 :     my $displayMode;
319 :     if (defined $r->param('displayMode')) {
320 :     $displayMode = $r->param('displayMode');
321 :     } else {
322 :     $displayMode = $ce->{pg}->{options}->{displayMode};
323 :     }
324 :    
325 : gage 991 my $problemSeed;
326 : sh002i 1924 if (defined $r->param('problemSeed')) {
327 :     $problemSeed = $r->param('problemSeed');
328 : gage 1348 } elsif (defined($problem_record) and $problem_record->can('problem_seed')) {
329 : sh002i 1924 $problemSeed = $problem_record->problem_seed;
330 : gage 991 }
331 : sh002i 1924
332 : gage 991 # make absolutely sure that the problem seed is defined, if it hasn't been.
333 : sh002i 1924 $problemSeed = '123456' unless defined $problemSeed and $problemSeed =~/\S/;
334 : malsyned 980
335 : gage 1747 ##############################################################################
336 :     # read and update the targetFile and targetFile.tmp files in the directory
337 :     # if a .tmp file already exists use that, unless the revert button has been pressed.
338 :     # These .tmp files are
339 :     # removed when the file is finally saved.
340 :     ##############################################################################
341 :    
342 : sh002i 1924 my $problemContents = '';
343 :     my $currentSourceFilePath = '';
344 : gage 1591 my $editErrors = '';
345 :    
346 : sh002i 1924 my $inputFilePath;
347 :     if (-r "$editFilePath.$editFileSuffix") {
348 :     $inputFilePath = "$editFilePath.$editFileSuffix";
349 :     } else {
350 :     $inputFilePath = $editFilePath;
351 :     }
352 :    
353 :     $inputFilePath = $editFilePath if defined($submit_button) and $submit_button eq 'Revert';
354 :    
355 :     ##### handle button clicks #####
356 :    
357 :     if (not defined $submit_button or $submit_button eq 'Revert' ) {
358 : malsyned 980 # this is a fresh editing job
359 :     # copy the pg file to a new file with the same name with .tmp added
360 : gage 981 # store this name in the $self->currentSourceFilePath for use in body
361 : sh002i 1924
362 : gage 1591 # try to read file
363 : jj 2032 if(-e $inputFilePath) {
364 :     eval { $problemContents = WeBWorK::Utils::readFile($inputFilePath) };
365 :     $problemContents = $@ if $@;
366 :     } else { # file not existing is not an error
367 :     $problemContents = '';
368 :     }
369 : sh002i 1924
370 :     $currentSourceFilePath = "$editFilePath.$editFileSuffix";
371 :     $self->{currentSourceFilePath} = $currentSourceFilePath;
372 :     $self->{problemPath} = $editFilePath;
373 :     } elsif ($submit_button eq 'Refresh') {
374 : gage 981 # grab the problemContents from the form in order to save it to the tmp file
375 :     # store tmp file name in the $self->currentSourceFilePath for use in body
376 : sh002i 1924 $problemContents = $r->param('problemContents');
377 : malsyned 980
378 : sh002i 1924 $currentSourceFilePath = "$editFilePath.$editFileSuffix";
379 :     $self->{currentSourceFilePath} = $currentSourceFilePath;
380 :     $self->{problemPath} = $editFilePath;
381 : malsyned 980 } elsif ($submit_button eq 'Save') {
382 : gage 981 # grab the problemContents from the form in order to save it to the permanent file
383 :     # later we will unlink (delete) the temporary file
384 :     # store permanent file name in the $self->currentSourceFilePath for use in body
385 : sh002i 1924 $problemContents = $r->param('problemContents');
386 : malsyned 980
387 : sh002i 1924 $currentSourceFilePath = "$editFilePath";
388 :     $self->{currentSourceFilePath} = $currentSourceFilePath;
389 :     $self->{problemPath} = $editFilePath;
390 : gage 1750 } elsif ($submit_button eq 'Save as') {
391 :     # grab the problemContents from the form in order to save it to a new permanent file
392 :     # later we will unlink (delete) the current temporary file
393 :     # store new permanent file name in the $self->currentSourceFilePath for use in body
394 : sh002i 1924 $problemContents = $r->param('problemContents');
395 :     $currentSourceFilePath = $ce->{courseDirs}->{templates} . '/' .$r->param('save_to_new_file');
396 :     $self->{currentSourceFilePath} = $currentSourceFilePath;
397 :     $self->{problemPath} = $currentSourceFilePath;
398 : malsyned 980 } else {
399 : sh002i 1924 die "Unrecognized submit command: $submit_button";
400 : malsyned 980 }
401 : gage 1105
402 :     # Handle the problem of line endings. Make sure that all of the line endings. Convert \r\n to \n
403 : sh002i 1924 $problemContents =~ s/\r\n/\n/g;
404 :     $problemContents =~ s/\r/\n/g;
405 : gage 1105
406 : gage 1750 # FIXME convert all double returns to paragraphs for .txt files
407 : sh002i 1924 # instead of doing this here, it should be done n the PLACE WHERE THE FILE IS DISPLAYED!!!
408 :     #if ($self->{file_type} eq 'course_info' ) {
409 :     # $problemContents =~ s/\n\n/\n<p>\n/g;
410 :     #}
411 :    
412 : gage 1747 ##############################################################################
413 :     # write changes to the approriate files
414 : malsyned 980 # FIXME make sure that the permissions are set correctly!!!
415 :     # Make sure that the warning is being transmitted properly.
416 : gage 1747 ##############################################################################
417 : sh002i 1924
418 : gage 1750 # FIXME set a local state rather continue to call on the submit button.
419 : sh002i 1924 if (defined $submit_button and $submit_button eq 'Save as' and defined $currentSourceFilePath and -e $currentSourceFilePath) {
420 : gage 1750 warn "File $currentSourceFilePath exists. File not saved.";
421 :     } else {
422 :     eval {
423 :     local *OUTPUTFILE;
424 :     open OUTPUTFILE, ">", $currentSourceFilePath
425 : gage 1980 or die "Failed to open $currentSourceFilePath";
426 : gage 1750 print OUTPUTFILE $problemContents;
427 :     close OUTPUTFILE;
428 : gage 1980 }; # any errors are caught in the next block
429 :    
430 : gage 1750 }
431 : sh002i 1924
432 : gage 1980 ###########################################################
433 :     # Catch errors in saving files, clean up temp files
434 :     ###########################################################
435 :    
436 : gage 1183 my $openTempFileErrors = $@ if $@;
437 :    
438 : sh002i 1924 if ($openTempFileErrors) {
439 : gage 1980 $self->{submiterror} = "Unable to write to $currentSourceFilePath: It is likely that the permissions in the template directory have not been set correctly. See log for details.";
440 : gage 1105 #diagnose errors:
441 : gage 1980 warn "Unable to write to $currentSourceFilePath: $openTempFileErrors";
442 : gage 1183 warn "The file $currentSourceFilePath exists. \n " if -e $currentSourceFilePath; #FIXME
443 : gage 1105 warn "The file $currentSourceFilePath cannot be found. \n " unless -e $currentSourceFilePath;
444 :     warn "The file $currentSourceFilePath does not have write permissions. \n"
445 :     if -e $currentSourceFilePath and not -w $currentSourceFilePath;
446 : gage 981 } else {
447 :     # unlink the temporary file if there are no errors and the save button has been pushed
448 : sh002i 1924 unlink("$editFilePath.$editFileSuffix")
449 :     if defined $submit_button and ($submit_button eq 'Save' or $submit_button eq 'Save as');
450 :     }
451 : malsyned 980
452 : gage 981 # return values for use in the body subroutine
453 : gage 1591 $self->{inputFilePath} = $inputFilePath;
454 :     $self->{displayMode} = $displayMode;
455 :     $self->{problemSeed} = $problemSeed;
456 :     $self->{r_problemContents} = \$problemContents;
457 : gage 1747 $self->{editFileSuffix} = $editFileSuffix;
458 : malsyned 980 }
459 :    
460 : gage 889 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9