| … | |
… | |
| 10 | |
10 | |
| 11 | use strict; |
11 | use strict; |
| 12 | use warnings; |
12 | use warnings; |
| 13 | use CGI qw(); |
13 | use CGI qw(); |
| 14 | use WeBWorK::Utils qw(readFile); |
14 | use WeBWorK::Utils qw(readFile); |
|
|
15 | use Apache::Constants qw(:common REDIRECT); |
|
|
16 | |
| 15 | |
17 | |
| 16 | our $libraryName; |
18 | our $libraryName; |
| 17 | our $rowheight; |
19 | our $rowheight; |
| 18 | |
20 | |
| 19 | sub title { |
21 | sub title { |
| 20 | my $self = shift; |
22 | my $self = shift; |
| 21 | #FIXME don't need the entire path ?? |
23 | #FIXME don't need the entire path ?? |
| 22 | return "Instructor Tools - PG Problem Editor for ". $self->{ce}->{problemPath}; |
24 | return "Instructor Tools - PG Problem Editor for ". $self->{ce}->{problemPath}; |
| 23 | } |
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->{ce}->{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 $seed = ($r->param('seed')) ? $r->param('seed') : ''; |
|
|
47 | my $displayMode = ($r->param('displayMode')) ? $r->param('displayMode') : ''; |
|
|
48 | |
|
|
49 | my $viewURL = "http://$hostname:$port"; |
|
|
50 | $viewURL .= "/webwork/$courseName/$setName/$problemNumber/?"; |
|
|
51 | $viewURL .= $self->url_authen_args; |
|
|
52 | $viewURL .= "&displayMode=$displayMode&seed=$seed"; # optional displayMode and seed overrides |
|
|
53 | $viewURL .= "&editMode=temporaryFile"; |
|
|
54 | $viewURL .= '&sourceFilePath='.$self->{ce}->{currentSourceFilePath}; # path to pg text for viewing |
|
|
55 | $viewURL .= "&submit_button=$submit_button"; # allows Problem.pg to recognize state |
|
|
56 | $viewURL .= '&editErrors='.$self->{ce}->{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 | |
| 24 | |
68 | |
| 25 | sub body { |
69 | sub body { |
| 26 | my $self = shift; |
70 | my $self = shift; |
| 27 | |
71 | |
| 28 | # test area |
72 | # test area |
| … | |
… | |
| 40 | # $formURL -- given by $r->uri |
84 | # $formURL -- given by $r->uri |
| 41 | # $tmpProblemPath |
85 | # $tmpProblemPath |
| 42 | #my ($problemPath,$formURL,$tmpProblemPath) = $self->initialize(); |
86 | #my ($problemPath,$formURL,$tmpProblemPath) = $self->initialize(); |
| 43 | my $problemPath = $ce->{problemPath}; |
87 | my $problemPath = $ce->{problemPath}; |
| 44 | |
88 | |
| 45 | my $tmpProblemPath = $ce->{tmpProblemPath}; |
89 | #my $tmpProblemPath = $ce->{tmpProblemPath}; |
| 46 | |
90 | |
| 47 | |
91 | |
| 48 | |
92 | |
| 49 | |
93 | |
| 50 | |
94 | |
| 51 | |
95 | |
| 52 | my $header = 'Problem Editor'; |
96 | my $header = "Problem Editor: $problemPath"; |
| 53 | |
97 | |
| 54 | ######################################################################### |
98 | ######################################################################### |
| 55 | # Find the text for the problem, either in the tmp file, if it exists |
99 | # Find the text for the problem, either in the tmp file, if it exists |
| 56 | # or in the original file in the template directory |
100 | # or in the original file in the template directory |
| 57 | ######################################################################### |
101 | ######################################################################### |
| 58 | my $problemContents = ''; |
102 | my $problemContents = ''; |
| 59 | my $editMode = (defined($r->param('problemContents')))? |
103 | # my $editMode = (defined($r->param('problemContents')))? |
| 60 | 'tmpMode':'startMode'; |
104 | # 'tmpMode':'startMode'; |
| 61 | |
105 | # |
| 62 | if ( $editMode eq 'tmpMode') { |
106 | # if ( $editMode eq 'tmpMode') { |
| 63 | $problemContents = $r->param('problemContents'); |
107 | # $problemContents = $r->param('problemContents'); |
| 64 | |
108 | # |
| 65 | } else{ |
109 | # } else{ |
| 66 | eval { $problemContents = WeBWorK::Utils::readFile($problemPath) }; # try to read file |
110 | eval { $problemContents = WeBWorK::Utils::readFile($problemPath) }; # try to read file |
| 67 | $problemContents = $@ if $@; |
111 | $problemContents = $@ if $@; |
| 68 | } |
112 | # } |
| 69 | |
113 | |
| 70 | # save Action FIXME -- is this the write place for this? |
114 | # save Action FIXME -- is this the write place for this? |
| 71 | my $actionString = ''; |
115 | # my $actionString = ''; |
| 72 | if ($r->param('submit') eq 'Save') { |
116 | # if ($r->param('submit') eq 'Save') { |
| 73 | $actionString = "File saved to $problemPath"; |
117 | # $actionString = "File saved to $problemPath"; |
| 74 | #FIXME it would be MUCH better to work with temporary files |
118 | # #FIXME it would be MUCH better to work with temporary files |
| 75 | open(FILE,">$problemPath") or die "Can't open $problemPath"; |
119 | # open(FILE,">$problemPath") or die "Can't open $problemPath"; |
| 76 | print FILE $problemContents; |
120 | # print FILE $problemContents; |
| 77 | close(FILE); |
121 | # close(FILE); |
| 78 | |
122 | # |
| 79 | } |
123 | # } |
|
|
124 | |
| 80 | |
125 | |
| 81 | # create tmp file version for later use |
|
|
| 82 | # So that you don't need duplicate information in forms |
|
|
| 83 | # FIXME |
|
|
| 84 | # open(FILE,">$tmpProblemPath") || die "Failed to open $tmpProblemPath"; |
|
|
| 85 | # print FILE "tmpfileVersion\n\n" . $problemContents; |
|
|
| 86 | # close(FILE); |
|
|
| 87 | |
126 | |
|
|
127 | |
|
|
128 | ######################################################################### |
|
|
129 | # Format the page |
|
|
130 | ######################################################################### |
| 88 | # Define parameters for textarea |
131 | # Define parameters for textarea |
| 89 | # FIXME these parameters should be capable of being updated dynamically. |
132 | # FIXME these parameters should be capable of being updated dynamically. |
| 90 | my $rows = 20; |
133 | my $rows = 20; |
| 91 | my $columns = 80; |
134 | my $columns = 80; |
| 92 | my $mode_list = ['HTML', 'HTML_tth','HTML_dpng', 'Latex2HTML']; |
135 | my $mode_list = ['HTML', 'HTML_tth','HTML_dpng', 'Latex2HTML']; |
| 93 | my $mode = ( defined($r->param('mode')) ) ? $r->param('mode') : 'HTML_tth'; |
136 | my $mode = ( defined($r->param('mode')) ) ? $r->param('mode') : 'HTML_tth'; |
| 94 | my $seed = ( defined($r->param('seed')) ) ? $r->param('seed') : '1234'; |
137 | my $seed = ( defined($r->param('seed')) ) ? $r->param('seed') : '1234'; |
|
|
138 | my $uri = $r->uri; |
| 95 | ######################################################################## |
139 | ######################################################################## |
| 96 | # Define a link to view the problem |
140 | # Define a link to view the problem |
| 97 | #FIXME |
141 | #FIXME |
| 98 | |
142 | |
| 99 | ######################################################################### |
143 | ######################################################################### |
| 100 | |
144 | |
| 101 | |
145 | |
| 102 | |
146 | |
| 103 | ######################################################################### |
147 | |
| 104 | # Format the page |
148 | |
| 105 | ######################################################################### |
|
|
| 106 | |
|
|
| 107 | return CGI::p($header), |
149 | return CGI::p($header), |
| 108 | CGI::startform("POST",$r->uri), |
150 | #CGI::start_form("POST",$r->uri,-target=>'_problem'), doesn't pass on the target parameter??? |
|
|
151 | qq!<form method="POST" action="$uri" enctype="application/x-www-form-urlencoded", target="_problem">!, |
| 109 | $self->hidden_authen_fields, |
152 | $self->hidden_authen_fields, |
| 110 | CGI::div( |
153 | CGI::div( |
| 111 | CGI::textfield(-name=>'seed',-value=>$seed), |
154 | CGI::textfield(-name=>'seed',-value=>$seed), |
| 112 | 'Mode: ', |
155 | 'Mode: ', |
| 113 | CGI::popup_menu(-name=>'mode', -'values'=>$mode_list, |
156 | CGI::popup_menu(-name=>'mode', -'values'=>$mode_list, |
| … | |
… | |
| 121 | CGI::textarea(-name => 'problemContents', -default => $problemContents, |
164 | CGI::textarea(-name => 'problemContents', -default => $problemContents, |
| 122 | -rows => $rows, -columns => $columns, -override => 1, |
165 | -rows => $rows, -columns => $columns, -override => 1, |
| 123 | ), |
166 | ), |
| 124 | ), |
167 | ), |
| 125 | CGI::p( |
168 | CGI::p( |
|
|
169 | CGI::submit(-value=>'Refresh',-name=>'submit'), |
| 126 | CGI::submit(-value=>'Save',-name=>'submit'), |
170 | CGI::submit(-value=>'Save',-name=>'submit'), |
| 127 | $actionString |
171 | # $actionString |
| 128 | ), |
172 | ), |
|
|
173 | |
| 129 | CGI::a({-href=>$ce->{viewProblemURL},-target=>'_viewProblem'},'view problem'), |
174 | #CGI::a({-href=>$ce->{viewProblemURL},-target=>'_viewProblem'},'view problem'), |
| 130 | CGI::end_form(), |
175 | CGI::end_form(), |
| 131 | "<p> the parameters passed are " #FIXME -- debugging code |
176 | "<p> the parameters passed are " #FIXME -- debugging code |
| 132 | . join("<BR>", %{$r->param()}) . |
177 | . join("<BR>", %{$r->param()}) . |
| 133 | "</p> and the gatheredInfo is ", |
178 | "</p> and the gatheredInfo is ", |
| 134 | "problemPath=$problemPath<br> formURL=".$r->uri . "<br> tmpProblemPath=$tmpProblemPath<br>" , |
179 | "problemPath=$problemPath<br> formURL=".$r->uri . "<br>" , |
| 135 | "viewProblemURL ".$ce->{viewProblemURL}."<br>", |
180 | # "viewProblemURL ".$ce->{viewProblemURL}."<br>", |
| 136 | "problem_obj =". $ce->{problem_obj}."<br>", |
181 | # "problem_obj =". $ce->{problem_obj}."<br>", |
| 137 | "path_components ". $ce->{path_components}; |
182 | "path_components ". $ce->{path_components}.'<br>', |
|
|
183 | # "hostname =$hostname<br>", |
|
|
184 | # "port =$port <br>", |
|
|
185 | "uri = $uri <br>", |
|
|
186 | # "viewURL =".$ce->{viewURL}."<br>", |
| 138 | |
187 | |
| 139 | ; |
188 | ; |
| 140 | |
189 | |
|
|
190 | |
| 141 | } |
191 | } |
| 142 | |
192 | |
| 143 | sub initialize { |
193 | sub initialize { |
| 144 | #fix me. This is very much hacked together. In particular can we pass the key inside the post? |
194 | |
| 145 | my ($self, $setName, $problemNumber) = @_; |
195 | my ($self, $setName, $problemNumber) = @_; |
| 146 | my $ce = $self->{ce}; |
196 | my $ce = $self->{ce}; |
| 147 | my $r = $self->{r}; |
197 | my $r = $self->{r}; |
| 148 | my $path_info = $r->path_info || ""; |
198 | my $path_info = $r->path_info || ""; |
| 149 | my $db = $self->{db}; |
199 | my $db = $self->{db}; |
| … | |
… | |
| 151 | my $effectiveUserName = $r->param('effectiveUser'); |
201 | my $effectiveUserName = $r->param('effectiveUser'); |
| 152 | my $courseName = $ce->{courseName}; |
202 | my $courseName = $ce->{courseName}; |
| 153 | |
203 | |
| 154 | my $set = $db->getGlobalUserSet($effectiveUserName, $setName); |
204 | my $set = $db->getGlobalUserSet($effectiveUserName, $setName); |
| 155 | my $setID = $set->set_id; |
205 | my $setID = $set->set_id; |
|
|
206 | |
| 156 | # Find URL for viewing problem |
207 | # Find URL for viewing problem |
| 157 | my $viewProblemURL = "/webwork/$courseName/".join("/",$setID,$problemNumber)."?" .$self->url_authen_args(); |
208 | # my $viewProblemURL = "/webwork/$courseName/".join("/",$setID,$problemNumber)."?" .$self->url_authen_args(); |
| 158 | |
209 | |
|
|
210 | # find path to pg file for the problem |
|
|
211 | # FIXME there is a descrepency in the way that the problems are found. |
| 159 | my $problem_record = $db->getUserProblem($user,$setID,1); |
212 | # my $problem_record = $db->getUserProblem($user,$setID,1); |
|
|
213 | my $problem_record = $db->getGlobalUserProblem($effectiveUserName, $setName, $problemNumber); |
| 160 | my $templateDirectory = $ce->{courseDirs}->{templates}; |
214 | my $templateDirectory = $ce->{courseDirs}->{templates}; |
| 161 | my $problemPath = $templateDirectory."/".$problem_record->source_file; |
215 | my $problemPath = $templateDirectory."/".$problem_record->source_file; |
|
|
216 | my $editFileSuffix = 'tmp'; |
|
|
217 | my $submit_button = $r->param('submit'); |
|
|
218 | |
|
|
219 | my $problemContents = ''; |
|
|
220 | my $currentSourceFilePath = ''; |
|
|
221 | # update the .pg and .pg.tmp files in the directory |
|
|
222 | if (not defined($submit_button) ) { |
|
|
223 | # this is a fresh editing job |
|
|
224 | # copy the pg file to a new file with the same name with .tmp added |
|
|
225 | # store this name in the $ce->currentSourceFilePath for use in body |
|
|
226 | |
|
|
227 | eval { $problemContents = WeBWorK::Utils::readFile($problemPath) |
|
|
228 | }; # try to read file |
|
|
229 | $problemContents = $@ if $@; |
|
|
230 | $currentSourceFilePath = "$problemPath.$editFileSuffix"; |
|
|
231 | $ce->{currentSourceFilePath} = $currentSourceFilePath; |
|
|
232 | } elsif ($submit_button eq 'Refresh' ) { |
|
|
233 | # grab the problemContents from the form and save it to the tmp file |
|
|
234 | # store tmp file name in the $ce->currentSourceFilePath for use in body |
|
|
235 | |
|
|
236 | $problemContents = $r->param('problemContents'); |
|
|
237 | $currentSourceFilePath = "$problemPath.$editFileSuffix"; |
|
|
238 | $ce->{currentSourceFilePath} = $currentSourceFilePath; |
|
|
239 | } elsif ($submit_button eq 'Save') { |
|
|
240 | # grab the problemContents from the form and save it to the permanent file |
|
|
241 | # unlink (delete) the temporary file |
|
|
242 | # store the permanent file name in the $ce->problemContents for use in body |
|
|
243 | |
|
|
244 | $problemContents = $r->param('problemContents'); |
|
|
245 | $currentSourceFilePath = "$problemPath"; |
|
|
246 | $ce->{currentSourceFilePath} = $currentSourceFilePath; |
|
|
247 | } else { |
|
|
248 | # give a warning |
|
|
249 | die "Unrecognized submit command $submit_button"; |
|
|
250 | } |
|
|
251 | # print changed pg files |
|
|
252 | # FIXME make sure that the permissions are set correctly!!! |
|
|
253 | # Make sure that the warning is being transmitted properly. |
|
|
254 | eval { |
|
|
255 | local *OUTPUTFILE; |
|
|
256 | open OUTPUTFILE, ">", $currentSourceFilePath |
|
|
257 | or die "Failed to write to $currentSourceFilePath: $!"; |
|
|
258 | print OUTPUTFILE $problemContents; |
|
|
259 | close OUTPUTFILE; |
|
|
260 | }; |
|
|
261 | my $errors = $@ if $@; |
|
|
262 | if ( $errors) { |
|
|
263 | |
|
|
264 | $ce->{editErrors} = "Unable to write to $currentSourceFilePath: $errors"; |
|
|
265 | |
|
|
266 | } else { # unlink the temporary file if there are no errors. |
|
|
267 | $ce->{editErrors} = ''; |
|
|
268 | unlink("$problemPath.$editFileSuffix") if defined($submit_button) and $submit_button eq 'Save'; |
|
|
269 | |
|
|
270 | }; |
|
|
271 | |
|
|
272 | |
| 162 | # return values. FIXME -- is this the right way to pass the values to body?? |
273 | # return values. FIXME -- is this the right way to pass the values to body?? |
| 163 | $ce->{viewProblemURL} = $viewProblemURL; |
274 | # $ce->{viewProblemURL} = $viewProblemURL; |
| 164 | $ce->{problemPath} = $problemPath; |
275 | $ce->{problemPath} = $problemPath; |
| 165 | $ce->{path_components} = join("/",$setID,$problemNumber); |
276 | $ce->{path_components} = join("/",$setID,$problemNumber); |
| 166 | |
277 | |
| 167 | # FIXME there is no way to edit in a temporary file -- all editing takes place on disk!!! |
278 | # FIXME there is no way to edit in a temporary file -- all editing takes place on disk!!! |
| 168 | |
279 | |