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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 3667 Revision 3718
1################################################################################ 1################################################################################
2# WeBWorK Online Homework Delivery System 2# WeBWorK Online Homework Delivery System
3# Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ 3# Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v 1.56 2005/07/30 17:26:45 gage Exp $ 4# $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm,v 1.57 2005/09/29 01:57:56 gage Exp $
5# 5#
6# This program is free software; you can redistribute it and/or modify it under 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 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 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. 9# version, or (b) the "Artistic License" which comes with this package.
14# Artistic License for more details. 14# Artistic License for more details.
15################################################################################ 15################################################################################
16 16
17package WeBWorK::ContentGenerator::Instructor::PGProblemEditor; 17package WeBWorK::ContentGenerator::Instructor::PGProblemEditor;
18use base qw(WeBWorK::ContentGenerator::Instructor); 18use base qw(WeBWorK::ContentGenerator::Instructor);
19
19 20
20 21
21=head1 NAME 22=head1 NAME
22 23
23WeBWorK::ContentGenerator::Instructor::PGProblemEditor - Edit a pg file 24WeBWorK::ContentGenerator::Instructor::PGProblemEditor - Edit a pg file
60# file_type eq 'problem' 61# file_type eq 'problem'
61# this is the most common type -- this editor can be called by an instructor when viewing any problem. 62# this is the most common type -- this editor can be called by an instructor when viewing any problem.
62# the information for retrieving the source file is found using the problemID in order to look 63# the information for retrieving the source file is found using the problemID in order to look
63# look up the source file path. 64# look up the source file path.
64# 65#
65# file_type eq 'problem_with_source' 66# file_type eq 'source_path_for_problem_file'
66# This is the same as the 'problem' file type except that the source for the problem is found in 67# This is the same as the 'problem' file type except that the source for the problem is found in
67# the parameter $r->param('sourceFilePath'). 68# the parameter $r->param('sourceFilePath'). This path is relative to the templates directory
68# 69#
69# file_type eq 'set_header' 70# file_type eq 'set_header'
70# This is a special case of editing the problem. The set header is often listed as problem 0 in the set's list of problems. 71# This is a special case of editing the problem. The set header is often listed as problem 0 in the set's list of problems.
71# 72#
72# file_type eq 'hardcopy_header' 73# file_type eq 'hardcopy_header'
80# 81#
81# file_type eq 'blank_problem' 82# file_type eq 'blank_problem'
82# This is a special call which allows one to create and edit a new PG problem. The "stationery" source for this problem is 83# This is a special call which allows one to create and edit a new PG problem. The "stationery" source for this problem is
83# stored in the conf/snippets directory and defined in global.conf by $webworkFiles{screenSnippets}{blankProblem} 84# stored in the conf/snippets directory and defined in global.conf by $webworkFiles{screenSnippets}{blankProblem}
84############################################################# 85#############################################################
85# submit button actions -- these and the file_type determine the state of the module 86# Requested actions -- these and the file_type determine the state of the module
86# Save ---- action = save 87# Save ---- action = save
87# Save as ---- action = save_as 88# Save as ---- action = save_as
88# View Problem ---- action = refresh 89# View Problem ---- action = view
89# Add this problem to: ---- action = add_problem_to_set 90# Add this problem to: ---- action = add_problem
90# Make this set header for: ---- action = add_set_header_to_set 91# Make this set header for: ---- action = add_problem
91# Revert ---- action = revert 92# Revert ---- action = revert
92# no submit button defined ---- action = fresh_edit 93# no submit button defined ---- action = fresh_edit
93################################################### 94###################################################
94# 95#
95# Determining which is the correct path to the file is a mess!!! FIXME 96# Determining which is the correct path to the file is a mess!!! FIXME
96# The path to the file to be edited is eventually put in tempFilePath 97# The path to the file to be edited is eventually put in tempFilePath
97# 98#
98# $problemPath is also used as is editFilePath. let's try to regularize these. 99# (tempFilePath)(editFilePath)(forcedSourceFile)
99#(sourceFile) (problemPath)(tempFilePath)(editFilePath)(forcedSourceFile)(problemPath)
100#input parameter can be: sourceFilePath 100#input parameter is: sourceFilePath
101################################################################# 101#################################################################
102# params read 102# params read
103# user 103# user
104# effectiveUser 104# effectiveUser
105# submit 105# submit
111# sourceFilePath 111# sourceFilePath
112# problemContents 112# problemContents
113# save_to_new_file 113# save_to_new_file
114# 114#
115 115
116#our $libraryName; 116use constant ACTION_FORMS => [qw(view add_problem make_local_copy save save_as revert)]; #[qw(view save save_as revert add_problem add_header make_local_copy)];
117#our $rowheight; 117
118our $TEMPFILESUFFIX; 118# permissions needed to perform a given action
119use constant FORM_PERMS => {
120 view => "modify_student_data",
121 add_problem => "modify_student_data",
122 make_local_copy => "modify_student_data",
123 save => "modify_student_data",
124 save_as => "modify_student_data",
125 revert => "modify_student_data",
126};
127
119 128
120sub pre_header_initialize { 129sub pre_header_initialize {
121 my ($self) = @_; 130 my ($self) = @_;
122 my $r = $self->r; 131 my $r = $self->r;
123 my $ce = $r->ce; 132 my $ce = $r->ce;
124 my $urlpath = $r->urlpath; 133 my $urlpath = $r->urlpath;
125 my $authz = $r->authz; 134 my $authz = $r->authz;
126 my $user = $r->param('user'); 135 my $user = $r->param('user');
127 $TEMPFILESUFFIX = $user.'.tmp'; 136 $self->{courseID} = $urlpath->arg("courseID");
137 $self->{setID} = $r->urlpath->arg("setID") ; # using $r->urlpath->arg("setID") ||'' causes trouble with set 0!!!
138 $self->{problemID} = $r->urlpath->arg("problemID");
128 139
129 my $submit_button = $r->param('submit'); # obtain submit command from form 140 my $submit_button = $r->param('submit'); # obtain submit command from form
141 my $actionID = $r->param('action');
130 my $file_type = $r->param("file_type") || ''; 142 my $file_type = $r->param("file_type") || '';
131 my $setName = $r->urlpath->arg("setID") ; # using $r->urlpath->arg("setID") ||'' causes trouble with set 0!!! 143 my $setName = $self->{setID};
132 my $problemNumber = $r->urlpath->arg("problemID"); 144 my $problemNumber = $self->{problemID};
133 145
134 # Check permissions 146 # Check permissions
135 return unless ($authz->hasPermissions($user, "access_instructor_tools")); 147 return unless ($authz->hasPermissions($user, "access_instructor_tools"));
136 return unless ($authz->hasPermissions($user, "modify_problem_sets")); 148 return unless ($authz->hasPermissions($user, "modify_problem_sets"));
137 149
150 ##############################################################################
151 # displayMode and problemSeed
152 #
153 # Determine the display mode
154 # If $self->{problemSeed} was obtained within saveFileChanges from the problem_record
155 # then it can be overridden by the value obtained from the form.
156 # Insure that $self->{problemSeed} has some non-empty value
157 # displayMode and problemSeed
158 # will be needed for viewing the problem via redirect.
159 # They are also two of the parameters which can be set by the editor
160 ##############################################################################
161
162 if (defined $r->param('displayMode')) {
163 $self->{displayMode} = $r->param('displayMode');
164 } else {
165 $self->{displayMode} = $ce->{pg}->{options}->{displayMode};
166 }
167
168 # form version of problemSeed overrides version obtained from the the problem_record
169 # inside saveFileChanges
170 $self->{problemSeed} = $r->param('problemSeed') if (defined $r->param('problemSeed'));
171 # Make sure that the problem seed has some value
172 $self->{problemSeed} = '123456' unless defined $self->{problemSeed} and $self->{problemSeed} =~/\S/;
173
174 ##############################################################################
138 ############################################################################# 175 #############################################################################
139 # Save file to permanent or temporary file, then redirect for viewing 176 # Save file to permanent or temporary file, then redirect for viewing
140 ############################################################################# 177 #############################################################################
141 # 178 #
142 # Any file "saved as" should be assigned to "Undefined_Set" and redirectoed to be viewed again in the editor 179 # Any file "saved as" should be assigned to "Undefined_Set" and redirectoed to be viewed again in the editor
157 # If this has not been defined we are dealing with a set header 194 # If this has not been defined we are dealing with a set header
158 # or regular problem 195 # or regular problem
159 if (defined($file_type) and ($file_type =~/\S/)) { #file_type is defined and is not blank 196 if (defined($file_type) and ($file_type =~/\S/)) { #file_type is defined and is not blank
160 # file type is already defined -- do nothing 197 # file type is already defined -- do nothing
161 } else { 198 } else {
162 # if "sourcFilePath" is defined in the form, then we are getting the path directly. 199 # if "sourceFilePath" is defined in the form, then we are getting the path directly.
163 # if the problem number is defined and is 0 200 # if the problem number is defined and is 0
164 # then we are dealing with some kind of 201 # then we are dealing with some kind of
165 # header file. The default is 'set_header' which prints properly 202 # header file. The default is 'set_header' which prints properly
166 # to the screen. 203 # to the screen.
167 # If the problem number is not zero, we are dealing with a real problem 204 # If the problem number is not zero, we are dealing with a real problem
177 } 214 }
178 215
179 } 216 }
180 } 217 }
181 die "The file_type variable has not been defined or is blank." unless defined($file_type) and $file_type =~/\S/; 218 die "The file_type variable has not been defined or is blank." unless defined($file_type) and $file_type =~/\S/;
219 # clean up sourceFilePath, just in case
220 # double check that sourceFilePath is relative to the templates file
221 if ($file_type eq 'source_path_for_problem_file' ) {
222 my $templatesDirectory = $ce->{courseDirs}->{templates};
223 my $sourceFilePath = $r->param('sourceFilePath');
224 $sourceFilePath =~ s/$templatesDirectory//;
225 $sourceFilePath =~ s|^/||; # remove intial /
226 $self->{sourceFilePath} = $sourceFilePath;
227 }
182 $self->{file_type} = $file_type; 228 $self->{file_type} = $file_type;
183 229
184 ########################################## 230 ##########################################
185 # File type is one of: blank_problem course_info problem set_header hardcopy_header problem_with_source 231 # File type is one of: blank_problem course_info problem set_header hardcopy_header source_path_for_problem_file
186 ########################################## 232 ##########################################
187 # 233 #
188 # Determine the path to the file 234 # Determine the path to the file
189 # 235 #
190 ########################################### 236 ###########################################
191 $self->getFilePaths($setName, $problemNumber, $file_type,$TEMPFILESUFFIX); 237 $self->getFilePaths($setName, $problemNumber, $file_type);
192 # result stored in $self->{editFilePath}, and $self->{tempFilePath} 238 #defines $self->{editFilePath} # path to the permanent file to be edited
239 # $self->{tempFilePath} # path to the permanent file to be edited has .tmp suffix
240 # $self->{inputFilePath} # path to the file for input, (might be a .tmp file)
241
242
243
244 ##########################################
245 # Default problem contents
246 ##########################################
247 $self->{r_problemContents}= undef;
248
193 ########################################## 249 ##########################################
194 # 250 #
195 # Determine action 251 # Determine action
196 # 252 #
197 ########################################### 253 ###########################################
198 # Submit button is one of: "add this problem to" , "add this set header to ", "Refresh" "Revert" "Save" "Save As" 254
199 $submit_button = $r->param('submit'); 255 if ($actionID) {
200 SUBMIT_CASE: { 256 unless (grep { $_ eq $actionID } @{ ACTION_FORMS() } ) {
201 (! defined($submit_button) ) and do { # fresh problem to edit 257 die "Action $actionID not found";
258 }
259 # Check permissions
260 if (not FORM_PERMS()->{$actionID} or $authz->hasPermissions($user, FORM_PERMS()->{$actionID})) {
261 my $actionHandler = "${actionID}_handler";
262 my %genericParams =();
263# foreach my $param (qw(selected_users)) {
264# $genericParams{$param} = [ $r->param($param) ];
265# }
266 my %actionParams = $self->getActionParams($actionID);
267 my %tableParams = (); # $self->getTableParams();
268 $self->{action}= $actionID;
269 $self->$actionHandler(\%genericParams, \%actionParams, \%tableParams);
270 } else {
271 $self->addbadmessage( "You are not authorized to perform this action.");
272 }
273 } else {
202 $self->{action} = 'fresh_edit'; 274 $self->{action}='fresh_edit';
203 last SUBMIT_CASE; 275 my $actionHandler = "fresh_edit_handler";
204 }; 276 my %genericParams;
205 277 my %actionParams = (); #$self->getActionParams($actionID);
206 ($submit_button eq 'Add this problem to: ') and do { 278 my %tableParams = (); # $self->getTableParams();
207 $self->{action} = 'add_problem_to_set'; 279 my $problemContents = '';
208 last SUBMIT_CASE; 280 $self->{r_problemContents}=\$problemContents;
209 }; 281 $self->$actionHandler(\%genericParams, \%actionParams, \%tableParams);
210 282 }
211 ($submit_button eq 'Make this the set header for: ') and do { 283
212 $self->{action} = 'add_set_header_to_set';
213 last SUBMIT_CASE;
214 };
215
216 ($submit_button eq 'View problem') and do {
217 $self->{action} ='refresh';
218 last SUBMIT_CASE;
219 };
220
221 ($submit_button eq 'Revert') and do {
222 $self->{action} = 'revert';
223 last SUBMIT_CASE;
224 };
225
226 ($submit_button eq 'Save') and do {
227 $self->{action} = 'save';
228 last SUBMIT_CASE;
229 };
230
231 ($submit_button eq 'Save as') and do {
232 $self->{action} = 'save_as';
233 last SUBMIT_CASE;
234 };
235
236 ($submit_button eq 'Add problem to: ') and do {
237 $self->{action} = 'add_problem_to_set';
238 last SUBMIT_CASE;
239 };
240 ($submit_button eq 'Make local copy at: ') and do {
241 $self->{action} = 'make_local_copy';
242 last SUBMIT_CASE;
243 };
244 # else
245 die "Unrecognized submit command: |$submit_button|";
246
247 } # END SUBMIT_CASE
248
249
250 ###########################################
251 # Save file
252 ######################################
253
254 # The subroutine below writes the necessary files and obtains the appropriate seed.
255 # and returns
256 # $self->{problemPath} --- file path for viewing problem in $self->{problemPath}
257 # $self->{failure}
258
259
260 $self->saveFileChanges($setName, $problemNumber, $file_type,$TEMPFILESUFFIX);
261 284
262 ############################################################################## 285 ##############################################################################
263 # displayMode and problemSeed 286 # displayMode and problemSeed
264 # 287 #
265 # Determine the display mode 288 # Determine the display mode
300 # FIXME: even with an error we still open a new page because of the target specified in the form 323 # FIXME: even with an error we still open a new page because of the target specified in the form
301 324
302 325
303 # Some cases do not need a redirect: save, refresh, save_as, add_problem_to_set, add_header_to_set,make_local_copy 326 # Some cases do not need a redirect: save, refresh, save_as, add_problem_to_set, add_header_to_set,make_local_copy
304 my $action = $self->{action}; 327 my $action = $self->{action};
328 return ;
305 329
306 return unless $action eq 'save'
307 or $action eq 'refresh'
308 or $action eq 'save_as'
309 or $action eq 'add_problem_to_set'
310 or $action eq 'make_local_copy'
311 or $action eq 'add_set_header_to_set';
312
313
314 ######################################
315 # calculate redirect URL based on file type
316 ######################################
317 my $courseName = $urlpath->arg("courseID");
318 my $problemSeed = ($r->param('problemSeed')) ? $r->param('problemSeed') : '';
319 my $displayMode = ($r->param('displayMode')) ? $r->param('displayMode') : '';
320
321 my $viewURL = '';
322
323 ######################################
324 # problem file_type
325 # redirect to Problem.pm with setID = "Undefined_Set if "Save As" option is chosen
326 # redirect to Problem.pm with setID = current $setID if "Save" or "Revert" or "Refresh is chosen"
327 ######################################
328 REDIRECT_CASES: {
329 ($file_type eq 'problem' or $file_type eq 'source_path_for_problem_file' or $file_type eq 'blank_problem') and do {
330 my $sourceFilePath = $self->{problemPath};
331 # strip off template directory prefix
332 $sourceFilePath =~ s|^$ce->{courseDirs}->{templates}/||;
333 if ($action eq 'save_as') { # redirect to myself
334 my $edit_level = $r->param("edit_level") || 0;
335 $edit_level++;
336
337 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
338 courseID => $courseName, setID => 'Undefined_Set', problemID => 'Undefined_Problem'
339 );
340 $viewURL = $self->systemLink($problemPage,
341 params=>{
342 sourceFilePath => $sourceFilePath,
343 edit_level => $edit_level,
344 file_type => 'source_path_for_problem_file',
345 status_message => uri_escape($self->{status_message})
346
347 }
348 );
349
350
351 } elsif ( $action eq 'add_problem_to_set') {
352
353 my $targetSetName = $r->param('target_set');
354 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
355 courseID => $courseName, setID => $targetSetName,
356 problemID => WeBWorK::Utils::max( $r->db->listGlobalProblems($targetSetName))
357 );
358 $viewURL = $self->systemLink($problemPage,
359 params => {
360 displayMode => $displayMode,
361 problemSeed => $problemSeed,
362 editMode => "savedFile",
363 sourceFilePath => $sourceFilePath,
364 status_message => uri_escape($self->{status_message})
365
366 }
367 );
368 } elsif ($action eq 'make_local_copy') { # redirect to myself
369 my $edit_level = $r->param("edit_level") || 0;
370 $edit_level++;
371
372 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
373 courseID => $courseName, setID => $setName, problemID => $problemNumber
374 );
375 $viewURL = $self->systemLink($problemPage,
376 params=>{
377 sourceFilePath => $sourceFilePath,
378 edit_level => $edit_level,
379 file_type => 'source_path_for_problem_file',
380 status_message => uri_escape($self->{status_message})
381
382 }
383 );
384
385
386 } elsif ( $action eq 'add_set_header_to_set') {
387 my $targetSetName = $r->param('target_set');
388 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
389 courseID => $courseName, setID => $targetSetName
390 );
391 $viewURL = $self->systemLink($problemPage,
392 params => {
393 displayMode => $displayMode,
394 editMode => "savedFile",
395 status_message => uri_escape($self->{status_message})
396 }
397 );
398 } else { # saved problems and refreshed problems redirect to Problem.pm
399 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
400 courseID => $courseName, setID => $setName, problemID => $problemNumber
401 );
402 $viewURL = $self->systemLink($problemPage,
403 params => {
404 displayMode => $displayMode,
405 problemSeed => $problemSeed,
406 editMode => ($action eq "save" ? "savedFile" : "temporaryFile"),
407 sourceFilePath => $sourceFilePath,
408 status_message => uri_escape($self->{status_message})
409
410 }
411 );
412 }
413 last REDIRECT_CASES;
414 };
415 ######################################
416 # blank_problem file_type
417 # redirect to Problem.pm
418 ######################################
419
420 $file_type eq 'blank_problem' and do {
421 return; # no redirect is needed
422 };
423
424 ######################################
425 # set headers file_type
426 # redirect to ProblemSet.pm
427 ######################################
428
429 ($file_type eq 'set_header' or $file_type eq 'hardcopy_header' ) and do {
430 if ($action eq 'save_as') { # redirect to myself
431 my $sourceFilePath = $self->{problemPath};
432 # strip off template directory prefix
433 $sourceFilePath =~ s|^$ce->{courseDirs}->{templates}/||;
434
435 my $edit_level = $r->param("edit_level") || 0;
436 $edit_level++;
437
438 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
439 courseID => $courseName, setID => 'Undefined_Set', problemID => 'Undefined_Problem'
440 );
441 $viewURL = $self->systemLink($problemPage,
442 params=>{
443 sourceFilePath => $sourceFilePath,
444 edit_level => $edit_level,
445 file_type => 'source_path_for_problem_file',
446 status_message => uri_escape($self->{status_message})
447 }
448 );
449 } elsif ( $action eq 'add_set_header_to_set') {
450 my $targetSetName = $r->param('target_set');
451 my $problemPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
452 courseID => $courseName, setID => $targetSetName
453 );
454 $viewURL = $self->systemLink($problemPage,
455 params => {
456 displayMode => $displayMode,
457 editMode => "savedFile",
458 status_message => uri_escape($self->{status_message})
459 }
460 );
461 } else {
462 my $problemSetPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
463 courseID => $courseName, setID => $setName);
464 $viewURL = $self->systemLink($problemSetPage,
465 params => {
466 displayMode => $displayMode,
467 problemSeed => $problemSeed,
468 editMode => ($action eq "save" ? "savedFile" : "temporaryFile"),
469 status_message => uri_escape($self->{status_message})
470 }
471 );
472 }
473 last REDIRECT_CASES;
474 };
475 ######################################
476 # course_info file type
477 # redirect to ProblemSets.pm
478 ######################################
479 $file_type eq 'course_info' and do {
480 my $problemSetsPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets",
481 courseID => $courseName);
482 $viewURL = $self->systemLink($problemSetsPage,
483 params => {
484 editMode => ($action eq "save" ? "savedFile" : "temporaryFile"),
485 status_message => uri_escape($self->{status_message})
486 }
487 );
488 last REDIRECT_CASES;
489 };
490 # else if no redirect needed -- there must be an error.
491 die "The file_type $file_type does not have a defined redirect procedure.";
492 } # End REDIRECT_CASES
493
494 if ($viewURL) {
495 $self->reply_with_redirect($viewURL);
496 } else {
497 die "Invalid file_type $file_type specified by saveFileChanges";
498 }
499} 330}
500 331
501 332
502sub initialize { 333sub initialize {
503 my ($self) = @_; 334 my ($self) = @_;
509 return unless ($authz->hasPermissions($user, "access_instructor_tools")); 340 return unless ($authz->hasPermissions($user, "access_instructor_tools"));
510 return unless ($authz->hasPermissions($user, "modify_problem_sets")); 341 return unless ($authz->hasPermissions($user, "modify_problem_sets"));
511 342
512 my $tempFilePath = $self->{tempFilePath}; # path to the file currently being worked with (might be a .tmp file) 343 my $tempFilePath = $self->{tempFilePath}; # path to the file currently being worked with (might be a .tmp file)
513 my $inputFilePath = $self->{inputFilePath}; # path to the file for input, (might be a .tmp file) 344 my $inputFilePath = $self->{inputFilePath}; # path to the file for input, (might be a .tmp file)
514 my $protected_file = (not -w $inputFilePath ) and -e $inputFilePath; #FIXME -- let's try to insure that the input file always exists, even for revert.
515 345
516 $self->addmessage($r->param('status_message') ||''); # record status messages carried over if this is a redirect 346 $self->addmessage($r->param('status_message') ||''); # record status messages carried over if this is a redirect
517 $self->addbadmessage("Changes in this file have not yet been permanently saved.") if -r $tempFilePath; 347 $self->addbadmessage("Changes in this file have not yet been permanently saved.") if -r $tempFilePath;
518 348 if ( not( -e $inputFilePath) ) {
349 $self->addbadmessage("This file: $inputFilePath, cannot be found.");
350 } elsif (not -w $inputFilePath ) {
519 $self->addbadmessage("This file '$inputFilePath' is protected! ".CGI::br()."To edit this text you must either 'Make a local copy' of this problem, or 351 $self->addbadmessage("This file '$inputFilePath' is protected! ".CGI::br()."To edit this text you must either 'Make a local copy' of this problem, or
520 use 'Save As' to save it to another file.") if $protected_file; 352 use 'Save As' to save it to another file.");
353 }
354
521 355
522} 356}
523 357
524sub path { 358sub path {
525 my ($self, $args) = @_; 359 my ($self, $args) = @_;
574 408
575 # Gathering info 409 # Gathering info
576 my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited 410 my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited
577 my $tempFilePath = $self->{tempFilePath}; # path to the file currently being worked with (might be a .tmp file) 411 my $tempFilePath = $self->{tempFilePath}; # path to the file currently being worked with (might be a .tmp file)
578 my $inputFilePath = $self->{inputFilePath}; # path to the file for input, (might be a .tmp file) 412 my $inputFilePath = $self->{inputFilePath}; # path to the file for input, (might be a .tmp file)
579 my $setName = $r->urlpath->arg("setID") ; 413 my $setName = $self->{setID} ;
580 my $problemNumber = $r->urlpath->arg("problemID") ; 414 my $problemNumber = $self->{problemID} ;
581 $setName = defined($setName) ? $setName : ''; # we need this instead of using the || construction 415 $setName = defined($setName) ? $setName : ''; # we need this instead of using the || construction
582 # to keep set 0 from being set to the 416 # to keep set 0 from being set to the
583 # empty string. 417 # empty string.
584 $problemNumber = defined($problemNumber) ? $problemNumber : ''; 418 $problemNumber = defined($problemNumber) ? $problemNumber : '';
585 419
586
587 ######################################################################### 420 #########################################################################
588 # Find the text for the problem, either in the tmp file, if it exists 421 # Find the text for the problem, either in the tmp file, if it exists
589 # or in the original file in the template directory 422 # or in the original file in the template directory
590 # or in the problem contents gathered in the initialization phase. 423 # or in the problem contents gathered in the initialization phase.
591 ######################################################################### 424 #########################################################################
592 425
593 my $problemContents = ${$self->{r_problemContents}}; 426 my $problemContents = ${$self->{r_problemContents}};
594 427
595 unless ( $problemContents =~/\S/) { # non-empty contents 428 unless ( $problemContents =~/\S/) { # non-empty contents
596 if (-r $tempFilePath and not -d $tempFilePath) { 429 if (-r $tempFilePath and not -d $tempFilePath) {
597 eval { $problemContents = WeBWorK::Utils::readFile($tempFilePath) }; 430 eval { $problemContents = WeBWorK::Utils::readFile($tempFilePath) };
598 $problemContents = $@ if $@; 431 $problemContents = $@ if $@;
599 $inputFilePath = $tempFilePath; 432 $inputFilePath = $tempFilePath;
609 #warn "obtaining input from r_problemContents"; 442 #warn "obtaining input from r_problemContents";
610 } 443 }
611 444
612 my $protected_file = not -w $inputFilePath; 445 my $protected_file = not -w $inputFilePath;
613 my $header = CGI::i("Editing problem".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath"); 446 my $header = CGI::i("Editing problem".CGI::b("set $setName/ problem $problemNumber</emphasis>").CGI::br()." in file $inputFilePath");
614 $header = ($inputFilePath =~ /$TEMPFILESUFFIX/) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file 447 $header = ($self->isTempFilePath($inputFilePath) ) ? CGI::div({class=>'temporaryFile'},$header) : $header; # use colors if temporary file
615 448
616 ######################################################################### 449 #########################################################################
617 # Format the page 450 # Format the page
618 ######################################################################### 451 #########################################################################
619 452
627 my $problemSeed = $self->{problemSeed}; 460 my $problemSeed = $self->{problemSeed};
628 my $uri = $r->uri; 461 my $uri = $r->uri;
629 my $edit_level = $r->param('edit_level') || 0; 462 my $edit_level = $r->param('edit_level') || 0;
630 my $file_type = $self->{file_type}; 463 my $file_type = $self->{file_type};
631 464
632 my $force_field = defined($r->param('sourceFilePath')) ? 465 my $force_field = (defined($self->{sourceFilePath}) and $self->{sourceFilePath} ne "") ?
633 CGI::hidden(-name=>'sourceFilePath', 466 CGI::hidden(-name=>'sourceFilePath',
634 -default=>$r->param('sourceFilePath')) : ''; 467 -default=>$self->{sourceFilePath}) : '';
635 468
636 my @allSetNames = sort $db->listGlobalSets; 469 my @allSetNames = sort $db->listGlobalSets;
637 for (my $j=0; $j<scalar(@allSetNames); $j++) { 470 for (my $j=0; $j<scalar(@allSetNames); $j++) {
638 $allSetNames[$j] =~ s|^set||; 471 $allSetNames[$j] =~ s|^set||;
639 $allSetNames[$j] =~ s|\.def||; 472 $allSetNames[$j] =~ s|\.def||;
640 } 473 }
641 my $target = "problem$edit_level"; 474 my $target = "problem$edit_level"; # increasing edit_level gives you a new window with each edit.
642 # Prepare Preview button 475
643 my $view_problem_form = CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}).
644 $self->hidden_authen_fields.
645 $force_field.
646 CGI::hidden(-name=>'file_type',-default=>$self->{file_type}).
647 CGI::hidden(-name=>'problemSeed',-default=>$problemSeed).
648 CGI::hidden(-name=>'displayMode',-default=>$displayMode).
649 CGI::hidden(-name=>'problemContents',-default=>$problemContents).
650 CGI::submit(-value=>'View problem',-name=>'submit').
651 CGI::end_form();
652 # Prepare add to set buttons
653 my $add_files_to_set_buttons = '';
654 if ($file_type eq 'problem' or $file_type eq 'source_path_for_problem_file' or $file_type eq 'blank_problem' ) {
655 $add_files_to_set_buttons .= CGI::submit(-value=>'Add problem to: ',-name=>'submit' ) ;
656 }
657 if ($file_type eq 'set_header' # set header or the problem number is not a regular positive number
658 or ( $file_type =~ /problem/ and ($problemNumber =~ /\D|^0$|^$/ )) ){
659 $add_files_to_set_buttons .=CGI::submit(-value=>'Make this the set header for: ',-name=>'submit' );
660 }
661 # Add pop-up menu for the target set if either of these buttons has been revealed.
662 $add_files_to_set_buttons .= CGI::popup_menu(-name=>'target_set',-values=>\@allSetNames, -default=>$setName) if $add_files_to_set_buttons;
663
664 476
665 return CGI::p($header), 477 print CGI::p($header),
666 CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}), 478 CGI::start_form({method=>"POST", name=>"editor", action=>"$uri", target=>$target, enctype=>"application/x-www-form-urlencoded"}),
667 $self->hidden_authen_fields, 479 $self->hidden_authen_fields,
668 $force_field, 480 $force_field,
669 CGI::hidden(-name=>'file_type',-default=>$self->{file_type}), 481 CGI::hidden(-name=>'file_type',-default=>$self->{file_type}),
670 CGI::div( 482 CGI::div(
671 'Seed: ',
672 CGI::textfield(-name=>'problemSeed',-value=>$problemSeed),
673 'Mode: ',
674 CGI::popup_menu(-name=>'displayMode', -values=>$mode_list, -default=>$displayMode),
675 CGI::a({-href=>'http://webwork.math.rochester.edu/docs/docs/pglanguage/manpages/',-target=>"manpage_window"}, 483 CGI::a({-href=>'http://webwork.math.rochester.edu/docs/docs/pglanguage/manpages/',-target=>"manpage_window"},
676 '&nbsp;Manpages&nbsp;', 484 '&nbsp;Manpages&nbsp;',
677 ), 485 ),
678 CGI::a({-href=>'http://devel.webwork.rochester.edu/twiki/bin/view/Webwork/PGmacrosByFile',-target=>"manpage_window"}, 486 CGI::a({-href=>'http://devel.webwork.rochester.edu/twiki/bin/view/Webwork/PGmacrosByFile',-target=>"manpage_window"},
679 '&nbsp;macro list&nbsp;', 487 '&nbsp;macro list&nbsp;',
685 CGI::p( 493 CGI::p(
686 CGI::textarea( 494 CGI::textarea(
687 -name => 'problemContents', -default => $problemContents, 495 -name => 'problemContents', -default => $problemContents,
688 -rows => $rows, -columns => $columns, -override => 1, 496 -rows => $rows, -columns => $columns, -override => 1,
689 ), 497 ),
690 ), 498 );
691 CGI::p( 499
692 $add_files_to_set_buttons, 500
693 CGI::br(), 501
694 CGI::submit(-value=>'View problem',-name=>'submit'), 502######### print action forms
695 $protected_file ? CGI::submit(-value=>'Save',-name=>'submit', -disabled=>1) : CGI::submit(-value=>'Save',-name=>'submit'), 503
696 CGI::submit(-value=>'Revert', -name=>'submit'), 504 print CGI::start_table({});
697 CGI::submit(-value=>'Save as',-name=>'submit'), 505 #print CGI::Tr({}, CGI::td({-colspan=>2}, "Select an action to perform:"));
698 CGI::textfield(-name=>'save_to_new_file', -size=>40, -value=>""),
699 506
700 ), 507 my @formsToShow = @{ ACTION_FORMS() };
701 # allow one to make a local copy if the viewed file can't be edited. #FIXME the method for determining the localfilePath needs work 508 my $default_choice = $formsToShow[0];
702 (-w $editFilePath) ? "" : CGI::p(CGI::hr(), 509 my $i = 0;
703 CGI::submit(-value=>'Make local copy at: ',-name=>'submit'), "[TMPL]/".determineLocalFilePath($editFilePath), 510 foreach my $actionID (@formsToShow) {
704 CGI::hidden(-name=>'local_copy_file_path', -value=>determineLocalFilePath($editFilePath) ) 511 # Check permissions
705 ), 512 #next if FORM_PERMS()->{$actionID} and not $authz->hasPermissions($user, FORM_PERMS()->{$actionID});
513 my $actionForm = "${actionID}_form";
514 my $onChange = "document.userlist.action[$i].checked=true";
515 my %actionParams = $self->getActionParams($actionID);
516 my $line_contents = $self->$actionForm($onChange, %actionParams);
517 my $radio_params = {-type=>"radio", -name=>"action", -value=>$actionID};
518 $radio_params->{checked}=1 if ($actionID eq $default_choice) ;
519 print CGI::Tr({-valign=>"top"},
520 CGI::td({}, CGI::input($radio_params)),
521 CGI::td({}, $line_contents)
522 ) if $line_contents;
523
524 $i++;
525 }
526 print CGI::Tr({}, CGI::td({-align=>"right"}, "Select above then:"),
527 CGI::td({-align=>"left"}, CGI::submit(-name=>'submit', -value=>"Take Action!")),
528 );
529 print CGI::end_table();
530
531
706 CGI::end_form(); 532 print CGI::end_form();
707 533 return "";
534
708 535
709} 536}
710 537
711################################################################################ 538################################################################################
712# Utilities 539# Utilities
718sub determineLocalFilePath { 545sub determineLocalFilePath {
719 my $path = shift; 546 my $path = shift;
720 if ($path =~ /Library/) { 547 if ($path =~ /Library/) {
721 $path =~ s|^.*?Library/||; # truncate the url up to a segment such as ...rochesterLibrary/....... 548 $path =~ s|^.*?Library/||; # truncate the url up to a segment such as ...rochesterLibrary/.......
722 } else { # if its not in a library we'll just save it locally 549 } else { # if its not in a library we'll just save it locally
723 $path = "new_problem_".rand(40); #l hope there aren't any collisions. 550 $path = "new_problem_".rand(40).".pg"; #l hope there aren't any collisions.
724 } 551 }
725 $path; 552 $path;
726 553
727} 554}
555
556sub determineTempFilePath { # this does not create the path to the file
557 my $self = shift; die "determineTempFilePath is a method" unless ref($self);
558 my $path =shift;
559 my $user = $self->r->param("user");
560 $user = rand(1000) unless defined $user;
561 my $courseDirectory = $self->r->ce->{courseDirs};
562 #FIXME -- we can put all of the temp files in a special directory
563 # so that even library files can viewed.
564 ###############
565 # Calculate the location of the temporary file
566 ###############
567 my $templatesDirectory = $courseDirectory->{templates};
568 if ($path =~ /^$templatesDirectory/ ) {
569 $path =~ s|^$templatesDirectory||;
570 $path =~ s|^/||; # remove the initial slash if any
571 } else {
572 die "determineTempFilePath should only be used on paths within the templates directory, not on $path";
573 }
574 my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit";
575 $path = "$tmpEditFileDirectory/$path.$user.tmp";
576 #$path .= ".$user.tmp";
577 #WeBWorK::Utils::surePathToFile($templatesDirectory, $path);
578 $path;
579}
580sub isTempFilePath {
581 my $self = shift;
582 my $path = shift;
583 my $courseDirectory = $self->r->ce->{courseDirs};
584 my $templatesDirectory = $courseDirectory->{templates};
585 my $tmpEditFileDirectory = (defined ($courseDirectory->{tmpEditFileDir}) ) ? $courseDirectory->{tmpEditFileDir} : "$templatesDirectory/tmpEdit";
586 ($path =~/^$tmpEditFileDirectory/) ? 1: 0;
587}
728sub getFilePaths { 588sub getFilePaths {
729 my ($self, $setName, $problemNumber, $file_type, $TEMPFILESUFFIX) = @_; 589 my ($self, $setName, $problemNumber, $file_type) = @_;
730 my $r = $self->r; 590 my $r = $self->r;
731 my $ce = $r->ce; 591 my $ce = $r->ce;
732 my $db = $r->db; 592 my $db = $r->db;
733 my $urlpath = $r->urlpath; 593 my $urlpath = $r->urlpath;
734 my $courseName = $urlpath->arg("courseID"); 594 my $courseName = $urlpath->arg("courseID");
739 $problemNumber = '' unless defined $problemNumber; 599 $problemNumber = '' unless defined $problemNumber;
740 die 'Internal error to PGProblemEditor -- file type is not defined' unless defined $file_type; 600 die 'Internal error to PGProblemEditor -- file type is not defined' unless defined $file_type;
741 601
742 ########################################################## 602 ##########################################################
743 # Determine path to the input file to be edited. 603 # Determine path to the input file to be edited.
744 # set EditFilePath to this value
745 #
746 # There are potentially four files in play
747 # The permanent path of the input file == $editFilePath == $self->{problemPath} 604 # The permanent path of the input file == $editFilePath
748 # A temporary path to the input file == $tempFilePath== "$editFilePath.$TEMPFILESUFFIX"== $self->{problemPath} 605 # A temporary path to the input file == $tempFilePath
749 ########################################################## 606 ##########################################################
750 # Relevant parameters 607 # Relevant parameters
751 # $r->param("displayMode") 608 # $r->param("displayMode")
752 # $r->param('problemSeed') 609 # $r->param('problemSeed')
753 # $r->param('submit') 610 # $r->param('submit')
755 # $r->param('sourceFilePath') 612 # $r->param('sourceFilePath')
756 # $r->param('problemContents') 613 # $r->param('problemContents')
757 # $r->param('save_to_new_file') 614 # $r->param('save_to_new_file')
758 ########################################################################## 615 ##########################################################################
759 # Define the following variables 616 # Define the following variables
760 # path to regular file -- $self->{problemPath} = $editFilePath; 617 # path to regular file -- $editFilePath;
761 # path to file being read (temporary or permanent) 618 # path to file being read (temporary or permanent)
762 # --- $self->{problemPath} = $problemPath;
763 # contents of the file being read --- $problemContents 619 # contents of the file being read --- $problemContents
764 # $self->{r_problemContents} = \$problemContents; 620 # $self->{r_problemContents} = \$problemContents;
765 # $self->{TEMPFILESUFFIX} = $TEMPFILESUFFIX;
766 ########################################################################### 621 ###########################################################################
767 622
768 my $editFilePath = $ce->{courseDirs}->{templates}; 623 my $editFilePath = $ce->{courseDirs}->{templates};
769 624
770 ########################################################################## 625 ##########################################################################
780 last CASE; 635 last CASE;
781 }; 636 };
782 637
783 ($file_type eq 'blank_problem') and do { 638 ($file_type eq 'blank_problem') and do {
784 $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{blankProblem}; 639 $editFilePath = $ce->{webworkFiles}->{screenSnippets}->{blankProblem};
785 $self->addbadmessage("$editFilePath is blank problem template file and should not be edited directly. " 640 $self->addbadmessage("$editFilePath is blank problem template file and can not be edited directly. "
786 ."First use 'Save as' to make a local copy, then add the file to the current problem set, then edit the file." 641 ."First use 'Save as' to make a local copy, then add the file to the current problem set, then edit the file."
787 ); 642 );
788 last CASE; 643 last CASE;
789 }; 644 };
790 645
831 $self->{problemSeed}= $problem_record->problem_seed if defined($problem_record) and $problem_record->can('problem_seed') ; 686 $self->{problemSeed}= $problem_record->problem_seed if defined($problem_record) and $problem_record->can('problem_seed') ;
832 last CASE; 687 last CASE;
833 }; # end 'problem' case 688 }; # end 'problem' case
834 689
835 ($file_type eq 'source_path_for_problem_file') and do { 690 ($file_type eq 'source_path_for_problem_file') and do {
836 my $forcedSourceFile = $r->param('sourceFilePath'); 691 my $forcedSourceFile = $self->{sourceFilePath};
837 # bail if no source path for the problem is found ; 692 # bail if no source path for the problem is found ;
838 die "Cannot find a file path to save to" unless( defined($forcedSourceFile) and ($forcedSourceFile =~ /\S/) ); 693 die "Cannot find a file path to save to" unless( defined($forcedSourceFile) and ($forcedSourceFile =~ /\S/) );
839 $self->{problemSeed} = 1234; 694 $self->{problemSeed} = 1234;
840 $editFilePath .= '/' . $forcedSourceFile; 695 $editFilePath .= '/' . $forcedSourceFile;
841 last CASE; 696 last CASE;
861 ################################################# 716 #################################################
862 # The path to the permanent file is now verified and stored in $editFilePath 717 # The path to the permanent file is now verified and stored in $editFilePath
863 # Whew!!! 718 # Whew!!!
864 ################################################# 719 #################################################
865 720
866 my $tempFilePath = "$editFilePath.$TEMPFILESUFFIX"; 721 my $tempFilePath = $self->determineTempFilePath($editFilePath); #"$editFilePath.$TEMPFILESUFFIX";
867 $self->{editFilePath} = $editFilePath; 722 $self->{editFilePath} = $editFilePath;
868 $self->{tempFilePath} = $tempFilePath; 723 $self->{tempFilePath} = $tempFilePath;
869 $self->{inputFilePath} = (-r "$editFilePath.$TEMPFILESUFFIX") ? $tempFilePath : $editFilePath; 724 $self->{inputFilePath} = (-r $tempFilePath) ? $tempFilePath : $editFilePath;
870 725 #warn "editfile path is $editFilePath and tempFile is $tempFilePath and inputFilePath is ". $self->{inputFilePath};
871} 726}
727sub new_saveFileChanges {
872 728
873################################################################################ 729################################################################################
874# saveFileChanges does most of the work. it is a separate method so that it can 730# new_saveFileChanges does most of the work. it is a separate method so that it can
875# be called from either pre_header_initialize() or initilize(), depending on 731# be called from either pre_header_initialize() or initilize(), depending on
876# whether a redirect is needed or not. 732# whether a redirect is needed or not.
877# 733#
878# it actually does a lot more than save changes to the file being edited, and 734# it actually does a lot more than save changes to the file being edited, and
879# sometimes less. 735# sometimes less.
880################################################################################ 736################################################################################
881sub saveFileChanges {
882 my ($self, $setName, $problemNumber, $file_type, $TEMPFILESUFFIX) = @_;
883 my $r = $self->r;
884 my $ce = $r->ce;
885 my $db = $r->db;
886 my $urlpath = $r->urlpath;
887
888 my $courseName = $urlpath->arg("courseID");
889 my $user = $r->param('user');
890 my $effectiveUserName = $r->param('effectiveUser');
891 737
892 $setName = '' unless defined $setName; 738 my ($self, $outputFilePath, $problemContents ) = @_;
893 $problemNumber = '' unless defined $problemNumber; 739 my $r = $self->r;
894 $file_type = '' unless defined $file_type; 740 my $ce = $r->ce;
895 741
896 my $action = $self->{action}; 742 my $action = $self->{action}||'no action';
897 my $editFilePath = $self->{editFilePath}; 743 my $editFilePath = $self->{editFilePath};
898 my $tempFilePath = $self->{tempFilePath}; 744 my $tempFilePath = $self->{tempFilePath};
745
746 if (defined($problemContents) and ref($problemContents) ) {
747 $problemContents = ${$problemContents};
748 } elsif( not defined($problemContents) or $problemContents =~/\S/ ) {
749 $problemContents = ${$self->{r_problemContents}};
750 }
899 ############################################################################## 751 ##############################################################################
900 # read and update the targetFile and targetFile.tmp files in the directory 752 # read and update the targetFile and targetFile.tmp files in the directory
901 # if a .tmp file already exists use that, unless the revert button has been pressed. 753 # if a .tmp file already exists use that, unless the revert button has been pressed.
902 # These .tmp files are 754 # The .tmp files are removed when the file is or when the revert occurs.
903 # removed when the file is finally saved.
904 # Place the path of the file to be read in $problemPath.
905 ############################################################################## 755 ##############################################################################
906 756
907 757
908 my $problemContents = ''; 758 unless (defined($outputFilePath) and $outputFilePath =~/\S/ ) {
909 my $outputFilePath = undef; # this is actually the output file for this subroutine 759 $self->addbadmessage("You must specify an file name in order to save a new file.");
910 # it is then read in as source in the body of this module 760 return "";
761 }
911 my $do_not_save = 0; # flag to prevent saving of file 762 my $do_not_save = 0 ; # flag to prevent saving of file
912 my $editErrors = ''; 763 my $editErrors = '';
913
914 ##########################################################################
915 # For each of the actions define the following variables:
916 #
917 # path to permanent file -- $self->{problemPath} = $editFilePath;
918 # path to file being read (temporary or permanent)
919 # --- $self->{problemPath} = $problemPath;
920 # contents of the file being read --- $problemContents
921 # $self->{r_problemContents} = \$problemContents;
922 #
923 #################################
924 # handle button clicks #####
925 # Read contents of file
926 #################################
927 ACTION_CASES: {
928 ($action eq 'fresh_edit') and do {
929 # this is a fresh editing job
930 # the original file will be read in the body
931 last ACTION_CASES;
932 };
933
934 ($action eq 'revert') and do {
935 # this is also fresh editing job
936 $outputFilePath = undef;
937 $self->addgoodmessage("Reverting to original file $editFilePath");
938 $self->{problemPath} = $editFilePath;
939 $self->{inputFilePath}=$editFilePath;
940 last ACTION_CASES;
941 };
942
943 ($action eq 'refresh') and do {
944 # grab the problemContents from the form in order to save it to the tmp file
945 # store tmp file name in the $self->problemPath for use in body
946
947 $problemContents = $r->param('problemContents');
948 $outputFilePath = "$editFilePath.$TEMPFILESUFFIX";
949 $self->{problemPath} = $outputFilePath;
950 last ACTION_CASES;
951 };
952
953 ($action eq 'save') and do {
954 # grab the problemContents from the form in order to save it to the permanent file
955 # later we will unlink (delete) the temporary file
956 # store permanent file name in the $self->problemPath for use in body
957 $problemContents = $r->param('problemContents');
958 $outputFilePath = "$editFilePath";
959 $self->{problemPath} = $outputFilePath;
960 #$self->addgoodmessage("Saving to file $outputFilePath");
961 last ACTION_CASES;
962 };
963
964 ($action eq 'save_as') and do {
965 my $new_file_name =$r->param('save_to_new_file') || '';
966 #################################################
967 #bail unless this new file name has been defined
968 #################################################
969 if ( $new_file_name !~ /\S/) { # need a non-blank file name
970 # setting $self->{failure} stops saving and any redirects
971 $do_not_save = 1;
972 warn "new file name is $new_file_name";
973 $self->addbadmessage(CGI::p("Please specify a file to save to."));
974 last ACTION_CASES; #stop processing
975 }
976 #################################################
977 # grab the problemContents from the form in order to save it to a new permanent file
978 # later we will unlink (delete) the current temporary file
979 # store new permanent file name in the $self->problemPath for use in body
980 #################################################
981 $problemContents = $r->param('problemContents');
982
983 #################################################
984 # Rescue the user in case they forgot to end the file name with .pg
985 #################################################
986 if($self->{file_type} eq 'problem'
987 or $self->{file_type} eq 'blank_problem'
988 or $self->{file_type} eq 'set_header') {
989 $new_file_name =~ s/\.pg$//; # remove it if it is there
990 $new_file_name .= '.pg'; # put it there
991
992 }
993
994 #################################################
995 # check to prevent overwrites:
996 #################################################
997 $outputFilePath = $ce->{courseDirs}->{templates} . '/' .
998 $new_file_name;
999
1000 if (defined $outputFilePath and -e $outputFilePath) {
1001 # setting $do_not_save stops saving and any redirects
1002 $do_not_save = 1;
1003 $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved."));
1004 } else {
1005 #$self->addgoodmessage("Saving to file $outputFilePath.");
1006 }
1007 $self->{problemPath} = $outputFilePath;
1008 last ACTION_CASES;
1009 };
1010 ($action eq 'make_local_copy') and do {
1011 my $new_file_name =$r->param('local_copy_file_path') || '';
1012 #################################################
1013 #bail unless this new file name has been defined
1014 #################################################
1015 if ( $new_file_name !~ /\S/) { # need a non-blank file name
1016 # setting $self->{failure} stops saving and any redirects
1017 $do_not_save = 1;
1018 warn "new file name is $new_file_name";
1019 $self->addbadmessage(CGI::p("Please specify a file to save to."));
1020 last ACTION_CASES; #stop processing
1021 }
1022 #################################################
1023 # grab the problemContents from the form in order to save it to a new permanent file
1024 # later we will unlink (delete) the current temporary file
1025 # store new permanent file name in the $self->problemPath for use in body
1026 #################################################
1027 $problemContents = $r->param('problemContents');
1028
1029 #################################################
1030 # Rescue the user in case they forgot to end the file name with .pg
1031 #################################################
1032 if($self->{file_type} eq 'problem'
1033 or $self->{file_type} eq 'blank_problem'
1034 or $self->{file_type} eq 'set_header') {
1035 $new_file_name =~ s/\.pg$//; # remove it if it is there
1036 $new_file_name .= '.pg'; # put it there
1037
1038 }
1039
1040 #################################################
1041 # check to prevent overwrites:
1042 #################################################
1043 $outputFilePath = $ce->{courseDirs}->{templates} . '/' .
1044 $new_file_name;
1045
1046 if (defined $outputFilePath and -e $outputFilePath) {
1047 # setting $do_not_save stops saving and any redirects
1048 $do_not_save = 1;
1049 $self->addbadmessage(CGI::p("There is already a file at [TMPL]/$new_file_name. File not saved."));
1050 } else {
1051 $self->addgoodmessage("A local copy of $editFilePath is being made...") ;
1052 }
1053 $self->{problemPath} = $outputFilePath;
1054 #################################################
1055 # if new file has been successfully saved change the file path name for the problem
1056 #################################################
1057 unless ($do_not_save) {
1058 my $problemRecord = $db->getGlobalProblem($setName,$problemNumber);
1059 $problemRecord->source_file($new_file_name);
1060 if ( $db->putGlobalProblem($problemRecord) ) {
1061 $self->addgoodmessage("A local, editable, copy of $new_file_name has been made for problem $problemNumber.") ;
1062 $self->{problemPath} = $outputFilePath; # define the file path for redirect
1063 } else {
1064 $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error.");
1065 }
1066 }
1067
1068
1069
1070 last ACTION_CASES;
1071 };
1072 ($action eq 'add_problem_to_set') and do {
1073 my $sourceFile = $editFilePath;
1074 my $targetSetName = $r->param('target_set');
1075 my $freeProblemID = WeBWorK::Utils::max($db->listGlobalProblems($targetSetName)) + 1;
1076 $sourceFile =~ s|^$ce->{courseDirs}->{templates}/||;
1077 my $problemRecord = $self->addProblemToSet(
1078 setName => $targetSetName,
1079 sourceFile => $sourceFile,
1080 problemID => $freeProblemID
1081 );
1082 $self->assignProblemToAllSetUsers($problemRecord);
1083 $self->addgoodmessage("Added $sourceFile to ". $targetSetName. " as problem $freeProblemID") ;
1084 $outputFilePath = undef; # don't save any files
1085 $self->{problemPath} = $editFilePath;
1086
1087 };
1088 ($action eq 'add_set_header_to_set') and do {
1089 my $sourceFile = $editFilePath;
1090 my $targetSetName = $r->param('target_set');
1091 $sourceFile =~ s|^$ce->{courseDirs}->{templates}/||;
1092 my $setRecord = $db->getGlobalSet($targetSetName);
1093 $setRecord->set_header($sourceFile);
1094 if( $db->putGlobalSet($setRecord) ) {
1095 $self->addgoodmessage("Added $sourceFile to ". $targetSetName. " as new set header ") ;
1096 } else {
1097 $do_not_save = 1 ;
1098 $self->addbadmessage("Unable to make $sourceFile the set header for $targetSetName");
1099 }
1100 # change file type to set_header if it not already so
1101 $self->{file_type} = 'set_header';
1102 $outputFilePath = undef; # don't save any files
1103 $self->{problemPath} = $editFilePath;
1104
1105 };
1106 last ACTION_CASES;
1107
1108 die "Unrecognized action command: $action";
1109 }; # end ACTION_CASES
1110
1111
1112 764
1113 ############################################################################## 765 ##############################################################################
1114 # write changes to the approriate files 766 # write changes to the approriate files
1115 # FIXME make sure that the permissions are set correctly!!! 767 # FIXME make sure that the permissions are set correctly!!!
1116 # Make sure that the warning is being transmitted properly. 768 # Make sure that the warning is being transmitted properly.
1117 ############################################################################## 769 ##############################################################################
1118 770
1119 my $writeFileErrors; 771 my $writeFileErrors;
1120 if ( defined($outputFilePath) and $outputFilePath =~/\S/ and ! $do_not_save ) { # save file 772 if ( defined($outputFilePath) and $outputFilePath =~/\S/ ) { # save file
1121 # Handle the problem of line endings. 773 # Handle the problem of line endings.
1122 # Make sure that all of the line endings are of unix type. 774 # Make sure that all of the line endings are of unix type.
1123 # Convert \r\n to \n 775 # Convert \r\n to \n
1124 $problemContents =~ s/\r\n/\n/g; 776 #$problemContents =~ s/\r\n/\n/g;
1125 $problemContents =~ s/\r/\n/g; 777 #$problemContents =~ s/\r/\n/g;
1126 778
1127 # make sure any missing directories are created 779 # make sure any missing directories are created
1128 $outputFilePath = WeBWorK::Utils::surePathToFile($ce->{courseDirs}->{templates}, 780 WeBWorK::Utils::surePathToFile($ce->{courseDirs}->{templates},
1129 $outputFilePath); 781 $outputFilePath);
1130 782
1131 eval { 783 eval {
1132 local *OUTPUTFILE; 784 local *OUTPUTFILE;
1133 open OUTPUTFILE, ">", $outputFilePath 785 open OUTPUTFILE, ">$outputFilePath"
1134 or die "Failed to open $outputFilePath"; 786 or die "Failed to open $outputFilePath";
1135 print OUTPUTFILE $problemContents; 787 print OUTPUTFILE $problemContents;
1136 close OUTPUTFILE; 788 close OUTPUTFILE;
1137 }; # any errors are caught in the next block 789 # any errors are caught in the next block
1138 790 };
791
1139 $writeFileErrors = $@ if $@; 792 $writeFileErrors = $@ if $@;
1140 } 793 }
1141 794
1142 ########################################################### 795 ###########################################################
1143 # Catch errors in saving files, clean up temp files 796 # Catch errors in saving files, clean up temp files
1144 ########################################################### 797 ###########################################################
1145 798
1146 $self->{failure} = $do_not_save; # don't do redirects if the file was not saved. 799 $self->{saveError} = $do_not_save; # don't do redirects if the file was not saved.
1147 # don't unlink files or send success messages 800 # don't unlink files or send success messages
1148 801
1149 if ($writeFileErrors) { 802 if ($writeFileErrors) {
1150 # get the current directory from the outputFilePath 803 # get the current directory from the outputFilePath
1151 $outputFilePath =~ m|^(/.*?/)[^/]+$|; 804 $outputFilePath =~ m|^(/.*?/)[^/]+$|;
1165 818
1166 $self->{failure} = 1; 819 $self->{failure} = 1;
1167 $self->addbadmessage(CGI::p($errorMessage)); 820 $self->addbadmessage(CGI::p($errorMessage));
1168 821
1169 } 822 }
823 ###########################################################
824 # clean up temp files on revert, save and save_as
825 ###########################################################
1170 unless( $writeFileErrors or $do_not_save) { # everything worked! unlink and announce success! 826 unless( $writeFileErrors or $do_not_save) { # everything worked! unlink and announce success!
1171 # unlink the temporary file if there are no errors and the save button has been pushed 827 # unlink the temporary file if there are no errors and the save button has been pushed
1172 if ($action eq 'save' or $action eq 'save_as' or $action eq 'revert') { 828 if ($action eq 'save' or $action eq 'save_as' or $action eq 'revert') {
1173 unlink($self->{tempFilePath}) ; 829 unlink($self->{tempFilePath}) ;
1174 } 830 }
1175 if ( defined($outputFilePath) and ! $self->{failure} ) { 831 if ( defined($outputFilePath) and ! $self->{failure} ) {
1176 my $msg = "Saved to file: $outputFilePath"; 832 my $msg = "Saved to file: |$outputFilePath|";
1177 $self->addgoodmessage($msg); 833 $self->addgoodmessage($msg);
1178 } 834 }
1179 835
1180 } 836 }
837
838
839} # end new_saveFileChanges
840
841
842
843
844
845sub getActionParams {
846 my ($self, $actionID) = @_;
847 my $r = $self->{r};
848
849 my %actionParams=();
850 foreach my $param ($r->param) {
851 next unless $param =~ m/^action\.$actionID\./;
852 $actionParams{$param} = [ $r->param($param) ];
853 }
854 return %actionParams;
855}
856
857sub fixProblemContents {
858 #NOT a method
859 my $problemContents = shift;
860 # Handle the problem of line endings.
861 # Make sure that all of the line endings are of unix type.
862 # Convert \r\n to \n
863 $problemContents =~ s/\r\n/\n/g;
864 $problemContents =~ s/\r/\n/g;
865 $problemContents;
866}
867
868sub fresh_edit_handler {
869 my ($self, $genericParams, $actionParams, $tableParams) = @_;
870 $self->addgoodmessage("fresh_edit_handler called");
871}
872sub view_form {
873 my ($self, $onChange, %actionParams) = @_;
874 my $output_string = "View";
875 unless ($self->{file_type} eq 'course_info') {
876 $output_string .= join(" ",
877 " problem using seed ",
878 CGI::textfield(-name=>'action.view.seed',-value=>$self->{problemSeed}),
879 "and display mode ",
880 CGI::popup_menu(-name=>'action.view.displayMode', -values=>$self->r->ce->{pg}->{displayModes},
881 -default=>$self->{displayMode}
882 ), ".",
883 );
884 }
885
886 return $output_string; #FIXME add -lables to the pop up menu
887}
888
889sub view_handler {
890 my ($self, $genericParams, $actionParams, $tableParams) = @_;
891 my $courseName = $self->{courseID};
892 my $setName = $self->{setID};
893 my $problemNumber = $self->{problemID};
894 my $problemSeed = ($actionParams->{'action.view.seed'}) ?
895 $actionParams->{'action.view.seed'}->[0]
896 : 1234;
897 my $displayMode = ($actionParams->{'action.view.displayMode'}) ?
898 $actionParams->{'action.view.displayMode'}->[0]
899 : $self->r->ce->{pg}->{options}->{displayMode};
900
901 my $editFilePath = $self->{editFilePath};
902 my $tempFilePath = $self->{tempFilePath};
903 ########################################################
904 # grab the problemContents from the form in order to save it to the tmp file
905 ########################################################
906 my $problemContents = fixProblemContents($self->r->param('problemContents'));
907 $self->{r_problemContents} = \$problemContents;
908
909
910 my $do_not_save = 0;
911 my $file_type = $self->{file_type};
912 $self->new_saveFileChanges($tempFilePath,);
913
914 ########################################################
915 # construct redirect URL and redirect
916 ########################################################
917 my $edit_level = $self->r->param("edit_level") || 0;
918 $edit_level++;
919 my $viewURL;
920
921 if ($file_type eq 'problem' ) { # redirect to Problem.pm
922 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
923 courseID => $courseName, setID => $setName, problemID => $problemNumber
924 );
1181 925
1182 # return values for use in the body subroutine 926 $viewURL = $self->systemLink($problemPage,
1183 # The path to the current permanent file being edited: 927 params => {
1184 # $self->{problemPath} = $editFilePath; 928 displayMode => $displayMode,
1185 # The path to the current temporary file (if any). If no temporary file this the same 929 problemSeed => $problemSeed,
1186 # as the permanent file path: 930 editMode => "temporaryFile",
1187 # $self->{outputFilePath} = $outputFilePath; 931 edit_level => $edit_level,
1188 # 932 sourceFilePath => $tempFilePath,
933 status_message => uri_escape($self->{status_message})
1189 934
935 }
936 );
937 } elsif ($file_type eq 'set_header' or $file_type eq 'hardcopy_header') { # redirect to ProblemSet
938 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
939 courseID => $courseName, setID => $setName,
940 );
941
942 $viewURL = $self->systemLink($problemPage,
943 params => {
944 displayMode => $displayMode,
945 problemSeed => $problemSeed,
946 editMode => "temporaryFile",
947 edit_level => $edit_level,
948 status_message => uri_escape($self->{status_message})
949
950 }
951 );
952
953
954 } elsif ($file_type eq 'course_info') { # redirecto to ProblemSets.pm
955 my $problemSetsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets",
956 courseID => $courseName);
957 $viewURL = $self->systemLink($problemSetsPage,
958 params => {
959 editMode => ("temporaryFile"),
960 edit_level => $edit_level,
961 status_message => uri_escape($self->{status_message})
962 }
963 );
964 } elsif ($file_type eq 'source_path_for_problem_file') { # redirect to Problem.pm
965 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
966 courseID => $courseName, setID => $setName, problemID => $problemNumber
967 );
968
969 $viewURL = $self->systemLink($problemPage,
970 params => {
971 displayMode => $displayMode,
972 problemSeed => $problemSeed,
973 editMode => "temporaryFile",
974 edit_level => $edit_level,
975 sourceFilePath => $tempFilePath,
976 status_message => uri_escape($self->{status_message})
977
978 }
979 );
980 } else {
981 die "I don't know how to redirect this file type $file_type ";
982 }
983
984 $self->reply_with_redirect($viewURL);
985}
986
987sub add_problem_form {
988 my $self = shift;
989 my ($onChange, %actionParams) = @_;
990 my $r = $self->r;
991 my $setName = $self->{setID} ;
992 my $problemNumber = $self->{problemID} ;
993 $setName = defined($setName) ? $setName : ''; # we need this instead of using the || construction
994 # to keep set 0 from being set to the
995 # empty string.
996 $setName =~ s|^set||;
997 my @allSetNames = sort $r->db->listGlobalSets;
998 for (my $j=0; $j<scalar(@allSetNames); $j++) {
999 $allSetNames[$j] =~ s|^set||;
1000 $allSetNames[$j] =~ s|\.def||;
1001 }
1002 return "" if $self->{file_type} eq 'course_info';
1003 return join(" ",
1004 "Add problem to set " ,
1005 CGI::popup_menu(-name=>'action.add_problem.target_set', -values=>\@allSetNames, -default=>$setName),
1006 " as ",
1007 CGI::popup_menu(-name=>'action.add_problem.file_type', -values=>['problem','set_header'], -default=>'problem'),
1008
1009 ); #FIXME add -lables to the pop up menu
1010 return "";
1011}
1012
1013sub add_problem_handler {
1014 my ($self, $genericParams, $actionParams, $tableParams) = @_;
1015# $self->addgoodmessage("add_problem_handler called");
1016 my $courseName = $self->{courseID};
1017 my $setName = $self->{setID};
1018 my $problemNumber = $self->{problemID};
1019 my $sourceFilePath = $self->{editFilePath};
1020 my $displayMode = $self->{displayMode};
1021 my $problemSeed = $self->{problemSeed};
1022
1023 my $targetSetName = $actionParams->{'action.add_problem.target_set'}->[0];
1024 my $targetFileType = $actionParams->{'action.add_problem.file_type'}->[0];
1025 my $templatesPath = $self->r->ce->{courseDirs}->{templates};
1026 $sourceFilePath =~ s|^$templatesPath/||;
1027
1028 my $edit_level = $self->r->param("edit_level") || 0;
1029 $edit_level++;
1030
1031 my $viewURL ='';
1032 if ($targetFileType eq 'problem') {
1033 my $targetProblemNumber = 1+ WeBWorK::Utils::max( $self->r->db->listGlobalProblems($targetSetName));
1034
1035 #################################################
1036 # Update problem record
1037 #################################################
1038 my $problemRecord = $self->addProblemToSet(
1039 setName => $targetSetName,
1040 sourceFile => $sourceFilePath,
1041 problemID => $targetProblemNumber,
1042 );
1043 $self->assignProblemToAllSetUsers($problemRecord);
1044 $self->addgoodmessage("Added $sourceFilePath to ". $targetSetName. " as problem $targetProblemNumber") ;
1045 $self->{file_type} = 'problem'; # change file type to problem -- if it's not already that
1046
1047 #################################################
1048 # Set up redirect Problem.pm
1049 #################################################
1050 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
1051 courseID => $courseName,
1052 setID => $targetSetName,
1053 problemID => $targetProblemNumber,
1054 );
1055 $viewURL = $self->systemLink($problemPage,
1056 params => {
1057 displayMode => $displayMode,
1058 problemSeed => $problemSeed,
1059 editMode => "savedFile",
1060 edit_level => $edit_level,
1061 sourceFilePath => $sourceFilePath,
1062 status_message => uri_escape($self->{status_message})
1063
1064 }
1065 );
1066 } elsif ($targetFileType eq 'set_header') {
1067 #################################################
1068 # Update set record
1069 #################################################
1070 my $setRecord = $self->db->getGlobalSet($targetSetName);
1071 $setRecord->set_header($sourceFilePath);
1072 if( $self->db->putGlobalSet($setRecord) ) {
1073 $self->addgoodmessage("Added $sourceFilePath to ". $targetSetName. " as new set header ") ;
1074 } else {
1075 $self->addbadmessage("Unable to make $sourceFilePath the set header for $targetSetName");
1076 }
1077 $self->{file_type} = 'set_header'; # change file type to set_header if it not already so
1078 #################################################
1079 # Set up redirect
1080 #################################################
1081 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
1082 courseID => $courseName, setID => $targetSetName
1083 );
1084 $viewURL = $self->systemLink($problemPage,
1085 params => {
1086 displayMode => $displayMode,
1087 editMode => "savedFile",
1088 edit_level => $edit_level,
1089 status_message => uri_escape($self->{status_message})
1090 }
1091 );
1092 } else {
1093 die "Don't know what to do with target file type $targetFileType";
1094 }
1095
1096 $self->reply_with_redirect($viewURL);
1097}
1098
1099
1100sub save_form {
1101 my ($self, $onChange, %actionParams) = @_;
1102 my $r => $self->r;
1103 if (-w $self->{editFilePath}) {
1104 return "Save";
1105 } else {
1106 return ""; #"Can't save -- No write permission";
1107 }
1108
1109}
1110
1111sub save_handler {
1112 my ($self, $genericParams, $actionParams, $tableParams) = @_;
1113 $self->addgoodmessage("save_handler called");
1114 my $courseName = $self->{courseID};
1115 my $setName = $self->{setID};
1116 my $problemNumber = $self->{problemID};
1117 my $displayMode = $self->{displayMode};
1118 my $problemSeed = $self->{problemSeed};
1119
1120 #################################################
1121 # grab the problemContents from the form in order to save it to a new permanent file
1122 # later we will unlink (delete) the current temporary file
1123 #################################################
1124 my $problemContents = fixProblemContents($self->r->param('problemContents'));
1190 $self->{r_problemContents} = \$problemContents; 1125 $self->{r_problemContents} = \$problemContents;
1191} # end saveFileChanges 1126
1127 #################################################
1128 # Construct the output file path
1129 #################################################
1130 my $editFilePath = $self->{editFilePath};
1131 my $outputFilePath = $editFilePath;
1132
1133 my $do_not_save = 0;
1134 my $file_type = $self->{file_type};
1135 $self->new_saveFileChanges($outputFilePath);
1136 #################################################
1137 # Set up redirect to Problem.pm
1138 #################################################
1139 my $viewURL;
1140 ########################################################
1141 # construct redirect URL and redirect
1142 ########################################################
1143 if ($file_type eq 'problem' ) { # redirect to Problem.pm
1144 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
1145 courseID => $courseName, setID => $setName, problemID => $problemNumber
1146 );
1147
1148 $viewURL = $self->systemLink($problemPage,
1149 params => {
1150 displayMode => $displayMode,
1151 problemSeed => $problemSeed,
1152 editMode => "savedFile",
1153 edit_level => 0,
1154 sourceFilePath => $editFilePath,
1155 status_message => uri_escape($self->{status_message})
1156
1157 }
1158 );
1159 } elsif ($file_type eq 'set_header' or $file_type eq 'hardcopy_header') { # redirect to ProblemSet
1160 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
1161 courseID => $courseName, setID => $setName,
1162 );
1163
1164 $viewURL = $self->systemLink($problemPage,
1165 params => {
1166 displayMode => $displayMode,
1167 problemSeed => $problemSeed,
1168 editMode => "savedFile",
1169 edit_level => 0,
1170 status_message => uri_escape($self->{status_message})
1171
1172 }
1173 );
1174
1175
1176 } elsif ($file_type eq 'course_info') { # redirect to ProblemSets.pm
1177 my $problemSetsPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets",
1178 courseID => $courseName);
1179 $viewURL = $self->systemLink($problemSetsPage,
1180 params => {
1181 editMode => ("savedFile"),
1182 edit_level => 0,
1183 status_message => uri_escape($self->{status_message})
1184 }
1185 );
1186
1187 } else {
1188 die "I don't know how to redirect this file type $file_type ";
1189 }
1190
1191 $self->reply_with_redirect($viewURL);
1192}
1193
1194sub save_as_form {
1195 my ($self, $onChange, %actionParams) = @_;
1196 return "Save as [TMPL]/".CGI::textfield(-name=>'action.save_as.target_file', -size=>40, -value=>""),;
1197
1198}
1199
1200sub save_as_handler {
1201 my ($self, $genericParams, $actionParams, $tableParams) = @_;
1202 $self->addgoodmessage("save_as_handler called");
1203 my $courseName = $self->{courseID};
1204 my $setName = $self->{setID};
1205 my $problemNumber = $self->{problemID};
1206 my $displayMode = $self->{displayMode};
1207 my $problemSeed = $self->{problemSeed};
1208
1209 my $do_not_save = 0;
1210 my $new_file_name = $actionParams->{'action.save_as.target_file'}->[0] || '';
1211 $new_file_name =~ s/^\s*//; #remove initial and final white space
1212 $new_file_name =~ s/\s*$//;
1213 if ( $new_file_name !~ /\S/) { # need a non-blank file name
1214 # setting $self->{failure} stops saving and any redirects
1215 $do_not_save = 1;
1216 warn "new file name is $new_file_name";
1217 $self->addbadmessage(CGI::p("Please specify a file to save to."));
1218 last ACTION_CASES; #stop processing
1219 }
1220
1221 #################################################
1222 # grab the problemContents from the form in order to save it to a new permanent file
1223 # later we will unlink (delete) the current temporary file
1224 #################################################
1225 my $problemContents = fixProblemContents($self->r->param('problemContents'));
1226 $self->{r_problemContents} = \$problemContents;
1227
1228 #################################################
1229 # Rescue the user in case they forgot to end the file name with .pg
1230 #################################################
1231 my $file_type = $self->{file_type};
1232 if($self->{file_type} eq 'problem'
1233 or $self->{file_type} eq 'blank_problem'
1234 or $self->{file_type} eq 'set_header') {
1235 $new_file_name =~ s/\.pg$//; # remove it if it is there
1236 $new_file_name .= '.pg'; # put it there
1237
1238 }
1239 #################################################
1240 # Construct the output file path
1241 #################################################
1242 my $outputFilePath = $self->r->ce->{courseDirs}->{templates} . '/' .
1243 $new_file_name;
1244 if (defined $outputFilePath and -e $outputFilePath) {
1245 # setting $do_not_save stops saving and any redirects
1246 $do_not_save = 1;
1247 $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved."));
1248 } else {
1249 $self->{editFilePath} = $outputFilePath;
1250 $self->{tempFilePath} = ''; # nothing needs to be unlinked.
1251 $self->{inputFilePath} = '';
1252 }
1253
1254
1255
1256 unless ($do_not_save ) {
1257 $self->new_saveFileChanges($outputFilePath, \$problemContents);
1258 }
1259 my $edit_level = $self->r->param("edit_level") || 0;
1260 $edit_level++;
1261
1262 #################################################
1263 # Set up redirect
1264 # The redirect gives the server time to detect that the new file exists.
1265 #################################################
1266 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
1267 courseID => $courseName, setID => 'Undefined_Set', problemID => 'Undefined_Set'
1268 );
1269 my $viewURL = $self->systemLink($problemPage,
1270 params=>{
1271 sourceFilePath => $outputFilePath, #The path relative to the templates directory is required.
1272 edit_level => $edit_level,
1273 file_type => 'source_path_for_problem_file',
1274 status_message => uri_escape($self->{status_message})
1275
1276 }
1277 );
1278
1279 $self->reply_with_redirect($viewURL);
1280return ""; # no redirect needed
1281}
1282sub revert_form {
1283 my ($self, $onChange, %actionParams) = @_;
1284 return "Revert" ;
1285
1286}
1287sub revert_handler {
1288 my ($self, $genericParams, $actionParams, $tableParams) = @_;
1289 $self->addgoodmessage("revert_handler called");
1290
1291 my $courseName = $self->{courseID};
1292 my $setName = $self->{setID};
1293 my $problemNumber = $self->{problemID};
1294 my $displayMode = $self->{displayMode};
1295 my $problemSeed = $self->{problemSeed};
1296 #################################################
1297 # Reset the problem paths
1298 #################################################
1299
1300 my $editFilePath = $self->{editFilePath};
1301 $self->{inputFilePath} = $editFilePath;
1302 $self->{tempFilePath} = '';
1303 # unlink the temp files;
1304 unlink($self->{tempFilePath});
1305 my $problemContents ='';
1306 $self->{r_problemContents} = \$problemContents;
1307 $self->addgoodmessage("Reverting to original file $editFilePath");
1308 # no redirect is needed
1309}
1310sub make_local_copy_form {
1311 my ($self, $genericParams, $actionParams, $tableParams) = @_;
1312 my $editFilePath = $self->{editFilePath}; # path to the permanent file to be edited
1313 return "" unless -e $editFilePath;
1314 return "" if -w $editFilePath;
1315 return "" unless $self->{file_type} eq 'problem' or $self->{file_type} eq 'set_header' ;
1316 return join ("",
1317 "Make local copy at: [TMPL]/".determineLocalFilePath($editFilePath),
1318 CGI::hidden(-name=>'action.make_local_copy.target_file', -value=>determineLocalFilePath($editFilePath) ),
1319 CGI::hidden(-name=>'action.make_local_copy.source_file', -value=>$editFilePath ),
1320 );
1321
1322}
1323
1324sub make_local_copy_handler {
1325 my ($self, $genericParams, $actionParams, $tableParams) = @_;
1326 $self->addgoodmessage("make_local_copy_handler called");
1327
1328 my $courseName = $self->{courseID};
1329 my $setName = $self->{setID};
1330 my $problemNumber = $self->{problemID};
1331
1332 my $displayMode = $self->{displayMode};
1333 my $problemSeed = $self->{problemSeed};
1334
1335 my $do_not_save = 0; #error flag
1336 #################################################
1337 # Save the file locally
1338 #################################################
1339 my $new_file_name = $actionParams->{'action.make_local_copy.target_file'}->[0] || '';
1340 my $sourceFilePath = $actionParams->{'action.make_local_copy.source_file'}->[0] || '';
1341 my $templatesPath = $self->r->ce->{courseDirs}->{templates};
1342 $sourceFilePath =~ s|^$templatesPath/||; # make sure path relative to templates directory
1343
1344 if ( $new_file_name !~ /\S/) { # need a non-blank file name
1345 # setting $self->{failure} stops saving and any redirects
1346 $do_not_save = 1;
1347 warn "new file name is $new_file_name";
1348 $self->addbadmessage(CGI::p("Please specify a file to save to."));
1349 }
1350
1351 #################################################
1352 # grab the problemContents from the form in order to save it to a new permanent file
1353 # later we will unlink (delete) the current temporary file
1354 #################################################
1355
1356 my $problemContents = fixProblemContents($self->r->param('problemContents'));
1357 $self->{r_problemContents} = \$problemContents;
1358 warn "problem contents is empty" unless $problemContents;
1359 #################################################
1360 # Construct the output file path
1361 #################################################
1362 my $outputFilePath = $self->r->ce->{courseDirs}->{templates} . '/' .
1363 $new_file_name;
1364 if (defined $outputFilePath and -e $outputFilePath) {
1365 # setting $do_not_save stops saving and any redirects
1366 $do_not_save = 1;
1367 $self->addbadmessage(CGI::p("File $outputFilePath exists. File not saved."));
1368 } else {
1369 #$self->addgoodmessage("Saving to file $outputFilePath.");
1370 }
1371 my $file_type = $self->{file_type};
1372 unless ($do_not_save ) {
1373 $self->new_saveFileChanges($outputFilePath);
1374 }
1375 #################################################
1376 # Modify source file in problem
1377 #################################################
1378 if (-r $outputFilePath and !$do_not_save) {
1379 my $problemRecord = $self->r->db->getGlobalProblem($setName,$problemNumber);
1380 $problemRecord->source_file($new_file_name);
1381 if ( $self->r->db->putGlobalProblem($problemRecord) ) {
1382 $self->addgoodmessage("A local, editable, copy of [TMPL]/$sourceFilePath has been made for problem $problemNumber.") ;
1383 } else {
1384 $self->addbadmessage("Unable to change the source file path for set $setName, problem $problemNumber. Unknown error.");
1385 }
1386 }
1387 my $edit_level = $self->r->param("edit_level") || 0;
1388 $edit_level++;
1389 #################################################
1390 # Set up redirect
1391 #################################################
1392
1393 my $problemPage = $self->r->urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
1394 courseID => $courseName, setID => $setName, problemID => $problemNumber
1395 );
1396 my $viewURL = $self->systemLink($problemPage,
1397 params=>{
1398 sourceFilePath => $sourceFilePath,
1399 edit_level => $edit_level,
1400 file_type => 'problem',
1401 status_message => uri_escape($self->{status_message})
1402
1403 }
1404 );
1405 $self->reply_with_redirect($viewURL);
1406}
1407
1408
1409
1192 1410
11931; 14111;

Legend:
Removed from v.3667  
changed lines
  Added in v.3718

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9