Parent Directory
|
Revision Log
Filter problem contents before saving to disk to handle line ending problems. All occurences of \r\n and \r are replaced by \n. Began improving the error messages if files cannot not be read.
1 package WeBWorK::ContentGenerator::Instructor::PGProblemEditor; 2 use base qw(WeBWorK::ContentGenerator::Instructor); 3 4 5 =head1 NAME 6 7 WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list 8 9 =cut 10 11 use strict; 12 use warnings; 13 use CGI qw(); 14 use WeBWorK::Utils qw(readFile); 15 use Apache::Constants qw(:common REDIRECT); 16 17 18 our $libraryName; 19 our $rowheight; 20 21 sub title { 22 my $self = shift; 23 #FIXME don't need the entire path ?? 24 return "Instructor Tools - PG Problem Editor for ". $self->{problemPath}; 25 } 26 sub go { 27 my $self = shift; 28 my ($setName, $problemNumber) = @_; 29 my $r = $self->{r}; 30 my $ce = $self->{ce}; 31 my $submit_button = $r->param('submit'); # obtain submit command from form 32 33 # various actions depending on state. 34 if ( defined($submit_button) and ($submit_button eq 'Save' or $submit_button eq 'Refresh') ) { 35 36 $self->initialize($setName,$problemNumber); # write the necessary files 37 # return file path for viewing problem 38 # in $self->{currentSourceFilePath} 39 #redirect to view the problem 40 41 my $hostname = $r->hostname(); 42 my $port = $r->get_server_port(); 43 my $uri = $r->uri; 44 my $courseName = $self->{ce}->{courseName}; 45 my $editFileSuffix = $self->{ce}->{editFileSuffix}; 46 my $problemSeed = ($r->param('problemSeed')) ? $r->param('problemSeed') : ''; 47 my $displayMode = ($r->param('displayMode')) ? $r->param('displayMode') : ''; 48 49 my $viewURL = "http://$hostname:$port"; 50 $viewURL .= $ce->{webworkURLs}->{root}."/$courseName/$setName/$problemNumber/?"; 51 $viewURL .= $self->url_authen_args; 52 $viewURL .= "&displayMode=$displayMode&problemSeed=$problemSeed"; # optional displayMode and problemSeed overrides 53 $viewURL .= "&editMode=temporaryFile"; 54 $viewURL .= '&sourceFilePath='. $self->{currentSourceFilePath}; # path to pg text for viewing 55 $viewURL .= "&submit_button=$submit_button"; # allows Problem.pg to recognize state 56 $viewURL .= '&editErrors='.$self->{editErrors}; # of problem being viewed. 57 $r->header_out(Location => $viewURL ); 58 return REDIRECT; 59 } else { 60 # initialize and 61 # display the editing window 62 63 $self->SUPER::go(@_); 64 } 65 66 } 67 68 sub initialize { 69 70 my ($self, $setName, $problemNumber) = @_; 71 my $ce = $self->{ce}; 72 my $r = $self->{r}; 73 my $path_info = $r->path_info || ""; 74 my $db = $self->{db}; 75 my $user = $r->param('user'); 76 my $effectiveUserName = $r->param('effectiveUser'); 77 my $courseName = $ce->{courseName}; 78 79 # FIXME -- sometimes this doesn't find a set 80 # my $set = $db->getGlobalUserSet($effectiveUserName, $setName); 81 # my $setID = $set->set_id; 82 83 # Find URL for viewing problem 84 85 # find path to pg file for the problem 86 # FIXME there is a discrepancy in the way that the problems are found. 87 # FIXME more error checking is needed in case the problem doesn't exist. 88 # my $problem_record = $db->getUserProblem($user,$setID,1); 89 my $problem_record = $db->getGlobalUserProblem($effectiveUserName, $setName, $problemNumber); 90 # If there is no global_user defined problem, (i.e. the sets haven't been assigned yet), then look for a global version of the problem. 91 $problem_record = $db->getGlobalProblem($setName, $problemNumber) unless defined($problem_record); 92 die "Cannot find a problem record for set $setName / problem $problemNumber" 93 unless defined($problem_record); 94 my $templateDirectory = $ce->{courseDirs}->{templates}; 95 my $problemPath = $templateDirectory."/".$problem_record->source_file; 96 my $editFileSuffix = 'tmp'; 97 my $submit_button = $r->param('submit'); 98 99 my $displayMode = ( defined($r->param('displayMode')) ) ? $r->param('displayMode') : $ce->{pg}->{options}->{displayMode}; 100 # try to get problem seed from the input parameter, or from the problem record 101 my $problemSeed; 102 if ( defined($r->param('problemSeed')) ) { 103 $problemSeed = $r->param('problemSeed'); 104 } elsif ($problem_record->can('problem_seed')) { 105 $problemSeed = $problem_record->problem_seed; 106 } 107 # make absolutely sure that the problem seed is defined, if it hasn't been. 108 $problemSeed = '123456' unless defined($problemSeed) and $problemSeed =~/\S/; 109 110 my $problemContents = ''; 111 my $currentSourceFilePath = ''; 112 my $editErrors = ''; 113 # update the .pg and .pg.tmp files in the directory 114 if (not defined($submit_button) ) { 115 # this is a fresh editing job 116 # copy the pg file to a new file with the same name with .tmp added 117 # store this name in the $self->currentSourceFilePath for use in body 118 119 eval { $problemContents = WeBWorK::Utils::readFile($problemPath) 120 }; # try to read file 121 $problemContents = $@ if $@; 122 $editErrors .= $problemContents; 123 $currentSourceFilePath = "$problemPath.$editFileSuffix"; 124 $self->{currentSourceFilePath} = $currentSourceFilePath; 125 } elsif ($submit_button eq 'Refresh' ) { 126 # grab the problemContents from the form in order to save it to the tmp file 127 # store tmp file name in the $self->currentSourceFilePath for use in body 128 129 $problemContents = $r->param('problemContents'); 130 $currentSourceFilePath = "$problemPath.$editFileSuffix"; 131 $self->{currentSourceFilePath} = $currentSourceFilePath; 132 } elsif ($submit_button eq 'Save') { 133 # grab the problemContents from the form in order to save it to the permanent file 134 # later we will unlink (delete) the temporary file 135 # store permanent file name in the $self->currentSourceFilePath for use in body 136 137 $problemContents = $r->param('problemContents'); 138 $currentSourceFilePath = "$problemPath"; 139 $self->{currentSourceFilePath} = $currentSourceFilePath; 140 } else { 141 # give a warning 142 die "Unrecognized submit command $submit_button"; 143 } 144 145 # Handle the problem of line endings. Make sure that all of the line endings. Convert \r\n to \n 146 $problemContents =~ s/\r\n/\n/g; 147 $problemContents =~ s/\r/\n/g; 148 149 # print changed pg files 150 # FIXME make sure that the permissions are set correctly!!! 151 # Make sure that the warning is being transmitted properly. 152 153 eval { 154 local *OUTPUTFILE; 155 open OUTPUTFILE, ">", $currentSourceFilePath 156 or die "Failed to write to $currentSourceFilePath: $!"; 157 print OUTPUTFILE $problemContents; 158 close OUTPUTFILE; 159 }; 160 # record an error string for later use if there was a difficulty in writing to the file 161 # FIXME is this string every inspected? 162 $editErrors .= $@ if $@; 163 if ( $editErrors) { 164 165 $self->{editErrors} = "Unable to write to $currentSourceFilePath: $editErrors"; 166 #diagnose errors: 167 warn "Editing errors: $editErrors\n"; 168 warn "The file $currentSourceFilePath exists. \n " if -e $currentSourceFilePath; 169 warn "The file $currentSourceFilePath cannot be found. \n " unless -e $currentSourceFilePath; 170 warn "The file $currentSourceFilePath does not have write permissions. \n" 171 if -e $currentSourceFilePath and not -w $currentSourceFilePath; 172 173 174 175 } else { 176 # unlink the temporary file if there are no errors and the save button has been pushed 177 178 $self->{editErrors} = ''; 179 unlink("$problemPath.$editFileSuffix") if defined($submit_button) and $submit_button eq 'Save'; 180 }; 181 182 183 # return values for use in the body subroutine 184 $self->{problemPath} = $problemPath; 185 $self->{displayMode} = $displayMode; 186 $self->{problemSeed} = $problemSeed; 187 188 # FIXME there is no way to edit in a temporary file -- all editing takes place on disk!!! 189 190 191 192 } 193 194 sub body { 195 my $self = shift; 196 197 # test area 198 my $r = $self->{r}; 199 my $db = $self->{db}; 200 my $ce = $self->{ce}; 201 my $user = $r->param('user'); 202 my $key = $db->getKey($user)->key(); 203 204 205 ################ 206 # Gathering info 207 # What is needed 208 # $problemPath -- 209 # $formURL -- given by $r->uri 210 # $tmpProblemPath 211 my $problemPath = $self->{problemPath}; 212 213 214 215 216 217 218 219 my $header = "Problem Editor: $problemPath"; 220 221 ######################################################################### 222 # Find the text for the problem, either in the tmp file, if it exists 223 # or in the original file in the template directory 224 ######################################################################### 225 my $problemContents = ''; 226 227 eval { $problemContents = WeBWorK::Utils::readFile($problemPath) }; # try to read file 228 $problemContents = $@ if $@; 229 230 231 232 ######################################################################### 233 # Format the page 234 ######################################################################### 235 # Define parameters for textarea 236 # FIXME 237 # Should the seed be set from some particular user instance?? 238 # The mode list should be obtained from global.conf ultimately 239 my $rows = 20; 240 my $columns = 80; 241 my $mode_list = ['plainText','formattedText','images']; 242 my $displayMode = $self->{displayMode}; 243 my $problemSeed = $self->{problemSeed}; 244 my $uri = $r->uri; 245 ######################################################################## 246 # Define a link to view the problem 247 #FIXME 248 249 ######################################################################### 250 251 252 253 254 255 return CGI::p($header), 256 #CGI::start_form("POST",$r->uri,-target=>'_problem'), doesn't pass on the target parameter??? 257 qq!<form method="POST" action="$uri" enctype="application/x-www-form-urlencoded", target="_problem">!, 258 $self->hidden_authen_fields, 259 CGI::div( 260 CGI::textfield(-name=>'problemSeed',-value=>$problemSeed), 261 'Mode: ', 262 CGI::popup_menu(-name=>'displayMode', -'values'=>$mode_list, 263 -default=>$displayMode), 264 CGI::a( 265 {-href=>'http://webwork.math.rochester.edu/docs/docs/pglanguage/manpages/',-target=>"manpage_window"}, 266 'Manpages', 267 ) 268 ), 269 CGI::p( 270 CGI::textarea(-name => 'problemContents', -default => $problemContents, 271 -rows => $rows, -columns => $columns, -override => 1, 272 ), 273 ), 274 CGI::p( 275 CGI::submit(-value=>'Refresh',-name=>'submit'), 276 CGI::submit(-value=>'Save',-name=>'submit'), 277 # $actionString 278 ), 279 280 #CGI::a({-href=>$ce->{viewProblemURL},-target=>'_viewProblem'},'view problem'), 281 CGI::end_form(), 282 # "<p> the parameters passed are " #FIXME -- debugging code 283 # . join("<BR>", %{$r->param()}) . 284 # "</p> and the gatheredInfo is ", 285 # "problemPath=$problemPath<br> formURL=".$r->uri . "<br>" , 286 # "viewProblemURL ".$ce->{viewProblemURL}."<br>", 287 # "problem_obj =". $ce->{problem_obj}."<br>", 288 # "path_components ". $ce->{path_components}.'<br>', 289 # "hostname =$hostname<br>", 290 # "port =$port <br>", 291 # "uri = $uri <br>", 292 # "viewURL =".$ce->{viewURL}."<br>", 293 294 ; 295 296 297 } 298 299 300 301 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |