[system] / branches / rel-2-4-patches / webwork2 / lib / WeBWorK / PG.pm Repository:
ViewVC logotype

Diff of /branches/rel-2-4-patches/webwork2/lib/WeBWorK/PG.pm

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

Revision 620 Revision 4397
1################################################################################ 1################################################################################
2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 2# WeBWorK Online Homework Delivery System
3# $Id$ 3# Copyright © 2000-2006 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: webwork2/lib/WeBWorK/PG.pm,v 1.67 2006/08/17 23:54:09 dpvc Exp $
5#
6# This program is free software; you can redistribute it and/or modify it under
7# the terms of either: (a) the GNU General Public License as published by the
8# Free Software Foundation; either version 2, or (at your option) any later
9# version, or (b) the "Artistic License" which comes with this package.
10#
11# This program is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14# Artistic License for more details.
4################################################################################ 15################################################################################
5 16
6package WeBWorK::PG; 17package WeBWorK::PG;
7 18
8=head1 NAME 19=head1 NAME
9 20
10WeBWorK::PG - Wrap the action of the PG Translator in an easy-to-use API. 21WeBWorK::PG - Invoke one of several PG rendering methods using an easy-to-use
22API.
11 23
12=cut 24=cut
13 25
14use strict; 26use strict;
15use warnings; 27use warnings;
16use File::Path qw(rmtree);
17use File::Temp qw(tempdir);
18use WeBWorK::DB::Classlist;
19use WeBWorK::DB::WW;
20use WeBWorK::PG::Translator; 28use WeBWorK::PG::ImageGenerator;
21use WeBWorK::Problem; 29use WeBWorK::Utils qw(runtime_use formatDateTime makeTempDirectory);
22use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry); 30use WeBWorK::Utils::RestrictedClosureClass;
23 31
24sub new($$$$$$$$) { 32use constant DISPLAY_MODES => {
25 my $invocant = shift; 33 # display name # mode name
26 my $class = ref($invocant) || $invocant; 34 tex => "TeX",
35 plainText => "HTML",
36 formattedText => "HTML_tth",
37 images => "HTML_dpng",
38 jsMath => "HTML_jsMath",
39 asciimath => "HTML_asciimath",
40 LaTeXMathML => "HTML_LaTeXMathML",
41};
42
43sub new {
44 shift; # throw away invocant -- we don't need it
45 my ($ce, $user, $key, $set, $problem, $psvn, $formFields,
46 $translationOptions) = @_;
47
48 my $renderer = $ce->{pg}->{renderer};
49
50 runtime_use $renderer;
51
52 return $renderer->new(@_);
53}
54
55sub defineProblemEnvir {
27 my ( 56 my (
28 $courseEnv,
29 $user,
30 $key,
31 $set, 57 $self,
32 $problem,
33 $psvn,
34 $formFields, # in CGI::Vars format
35 $translationOptions, # hashref containing options for the
36 # translator, such as whether to show
37 # hints and the display mode to use
38 ) = @_;
39
40 # write timing log entry
41 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
42 "user=".$user->id.",problem=".$courseEnv->{courseName}."/".$set->id."/".$problem->id.",mode=".$translationOptions->{displayMode},
43 "begin");
44
45 # install a local warn handler to collect warnings
46 my $warnings = "";
47 if ($courseEnv->{pg}->{options}->{catchWarnings}) {
48 local $SIG{__WARN__} = sub { $warnings .= shift };
49 }
50
51 # create a Translator
52 #warn "PG: creating a Translator\n";
53 my $translator = WeBWorK::PG::Translator->new;
54
55 # set the directory hash
56 #warn "PG: setting the directory hash\n";
57 $translator->rh_directories({
58 courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros},
59 macroDirectory => $courseEnv->{courseDirs}->{macros},
60 templateDirectory => $courseEnv->{courseDirs}->{templates},
61 tempDirectory => $courseEnv->{courseDirs}->{html_temp},
62 });
63
64 # evaluate modules and "extra packages"
65 #warn "PG: evaluating modules and \"extra packages\"\n";
66 my @modules = @{ $courseEnv->{pg}->{modules} };
67 foreach my $module_packages_ref (@modules) {
68 my ($module, @extra_packages) = @$module_packages_ref;
69 # the first item is the main package
70 $translator->evaluate_modules($module);
71 # the remaining items are "extra" packages
72 $translator->load_extra_packages(@extra_packages);
73 }
74
75 # set the environment (from defineProblemEnvir)
76 #warn "PG: setting the environment (from defineProblemEnvir)\n";
77 my $envir = defineProblemEnvir(
78 $courseEnv,
79 $user,
80 $key, 58 $ce,
81 $set,
82 $problem,
83 $psvn,
84 $formFields,
85 $translationOptions,
86 );
87 $translator->environment($envir);
88
89 # initialize the Translator
90 #warn "PG: initializing the Translator\n";
91 $translator->initialize();
92
93 # load IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load
94 # i'd like to change this at some point to have the same sort of interface to global.conf
95 # that the module loading does -- have a list of macros to load unrestrictedly.
96 #warn "PG: loading IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load\n";
97 foreach (qw(IO.pl PG.pl dangerousMacros.pl)) {
98 my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_";
99 my $err = $translator->unrestricted_load($macroPath);
100 warn "Error while loading $macroPath: $err" if $err;
101 }
102 #my $pg_pl = $courseEnv->{webworkDirs}->{macros} . "/PG.pl";
103 #my $dangerousMacros_pl = $courseEnv->{webworkDirs}->{macros} . "/dangerousMacros.pl";
104 #my $io_pl = $courseEnv->{webworkDirs}->{macros} . "/IO.pl";
105 #my $err = $translator->unrestricted_load($pg_pl);
106 #warn "Error while loading $pg_pl: $err" if $err;
107 #$err = $translator->unrestricted_load($dangerousMacros_pl);
108 #warn "Error while loading $dangerousMacros_pl: $err" if $err;
109 #$err = $translator->unrestricted_load($io_pl);
110 #warn "Error while loading $io_pl: $err" if $err;
111
112 # set the opcode mask (using default values)
113 #warn "PG: setting the opcode mask (using default values)\n";
114 $translator->set_mask();
115
116 # store the problem source
117 #warn "PG: storing the problem source\n";
118 my $sourceFile = $problem->source_file;
119 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
120 unless ($sourceFile =~ /^\//);
121 eval { $translator->source_string(readFile($sourceFile)) };
122 if ($@) {
123 # well, we couldn't get the problem source, for some reason.
124 return bless {
125 translator => $translator,
126 head_text => "",
127 body_text => <<EOF,
128WeBWorK::Utils::readFile($sourceFile) says:
129$@
130EOF
131 answers => {},
132 result => {},
133 state => {},
134 errors => "Failed to read the problem source file.",
135 warnings => $warnings,
136 flags => {error_flag => 1},
137 }, $class;
138 }
139
140 # install a safety filter (&safetyFilter)
141 #warn "PG: installing a safety filter\n";
142 $translator->rf_safety_filter(\&safetyFilter);
143
144 # translate the PG source into text
145 #warn "PG: translating the PG source into text\n";
146 $translator->translate();
147
148 # after we're done translating, we may have to clean up after the translator.
149 # for example, 'images' mode uses a tempdir for dvipng's temp files. We have
150 # to remove it.
151 if ($translationOptions->{displayMode} eq 'images' && $envir->{dvipngTempDir}) {
152 rmtree($envir->{dvipngTempDir}, 0, 0);
153 }
154
155 my ($result, $state); # we'll need these on the other side of the if block!
156 if ($translationOptions->{processAnswers}) {
157
158 # process student answers
159 #warn "PG: processing student answers\n";
160 $translator->process_answers($formFields);
161
162 # retrieve the problem state and give it to the translator
163 #warn "PG: retrieving the problem state and giving it to the translator\n";
164 $translator->rh_problem_state({
165 recorded_score => $problem->status,
166 num_of_correct_ans => $problem->num_correct,
167 num_of_incorrect_ans => $problem->num_incorrect,
168 });
169
170 # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by
171 # the PG macro package (PG.pl)
172 #warn "PG: determining an entry order\n";
173 my @answerOrder =
174 $translator->rh_flags->{ANSWER_ENTRY_ORDER}
175 ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} }
176 : keys %{ $translator->rh_evaluated_answers };
177
178 # install a grader -- use the one specified in the problem,
179 # or fall back on the default from the course environment.
180 # (two magic strings are accepted, to avoid having to
181 # reference code when it would be difficult.)
182 #warn "PG: installing a grader\n";
183 my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE}
184 || $courseEnv->{pg}->{options}->{grader};
185 $grader = $translator->rf_std_problem_grader
186 if $grader eq "std_problem_grader";
187 $grader = $translator->rf_avg_problem_grader
188 if $grader eq "avg_problem_grader";
189 die "Problem grader $grader is not a CODE reference."
190 unless ref $grader eq "CODE";
191 $translator->rf_problem_grader($grader);
192
193 # grade the problem
194 #warn "PG: grading the problem\n";
195 ($result, $state) = $translator->grade_problem(
196 answers_submitted => $translationOptions->{processAnswers},
197 ANSWER_ENTRY_ORDER => \@answerOrder,
198 );
199
200 }
201
202 # write timing log entry
203 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", "", "end");
204
205 # return an object which contains the translator and the results of
206 # the translation process. this is DIFFERENT from the "format expected
207 # by Webwork.pm (and I believe processProblem8, but check.)"
208 return bless {
209 translator => $translator,
210 head_text => ${ $translator->r_header },
211 body_text => ${ $translator->r_text },
212 answers => $translator->rh_evaluated_answers,
213 result => $result,
214 state => $state,
215 errors => $translator->errors,
216 warnings => $warnings,
217 flags => $translator->rh_flags,
218 }, $class;
219}
220
221# -----
222
223sub defineProblemEnvir($$$$$$$) {
224 my (
225 $courseEnv,
226 $user, 59 $user,
227 $key, 60 $key,
228 $set, 61 $set,
229 $problem, 62 $problem,
230 $psvn, 63 $psvn,
231 $formFields, 64 $formFields,
232 $options, 65 $options,
66 $extras,
233 ) = @_; 67 ) = @_;
234 68
235 my %envir; 69 my %envir;
70
71 # ----------------------------------------------------------------------
236 72
237 # PG environment variables 73 # PG environment variables
238 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002 74 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
239 # any changes are noted by "ADDED:" or "REMOVED:" 75 # any changes are noted by "ADDED:" or "REMOVED:"
240 76
241 # Vital state information 77 # Vital state information
242 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img, 78 # ADDED: displayModeFailover, displayHintsQ, displaySolutionsQ,
243 # texDisposition 79 # refreshMath2img, texDisposition
244 80
245 $envir{psvn} = $psvn; 81 $envir{psvn} = $set->psvn;
246 $envir{psvnNumber} = $envir{psvn}; 82 $envir{psvnNumber} = $envir{psvn};
247 $envir{probNum} = $problem->id; 83 $envir{probNum} = $problem->problem_id;
248 $envir{questionNumber} = $envir{probNum}; 84 $envir{questionNumber} = $envir{probNum};
249 $envir{fileName} = $problem->source_file; 85 $envir{fileName} = $problem->source_file;
250 $envir{probFileName} = $envir{fileName}; 86 $envir{probFileName} = $envir{fileName};
251 $envir{problemSeed} = $problem->problem_seed; 87 $envir{problemSeed} = $problem->problem_seed;
252 $envir{displayMode} = translateDisplayModeNames($options->{displayMode}); 88 $envir{displayMode} = translateDisplayModeNames($options->{displayMode});
253 $envir{languageMode} = $envir{displayMode}; 89 $envir{languageMode} = $envir{displayMode};
254 $envir{outputMode} = $envir{displayMode}; 90 $envir{outputMode} = $envir{displayMode};
255 $envir{displayHintsQ} = $options->{hints}; 91 $envir{displayHintsQ} = $options->{showHints};
256 $envir{displaySolutionsQ} = $options->{solutions}; 92 $envir{displaySolutionsQ} = $options->{showSolutions};
257 $envir{refreshMath2img} = $options->{refreshMath2img};
258 $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex 93 $envir{texDisposition} = "pdf"; # in webwork2, we use pdflatex
259 94
260 # Problem Information 95 # Problem Information
261 # ADDED: courseName 96 # ADDED: courseName, formatedDueDate
262 97
263 $envir{openDate} = $set->open_date; 98 $envir{openDate} = $set->open_date;
264 $envir{formattedOpenDate} = formatDateTime($envir{openDate}); 99 $envir{formattedOpenDate} = formatDateTime($envir{openDate}, $ce->{siteDefaults}{timezone});
265 $envir{dueDate} = $set->due_date; 100 $envir{dueDate} = $set->due_date;
266 $envir{formattedDueDate} = formatDateTime($envir{dueDate}); 101 $envir{formattedDueDate} = formatDateTime($envir{dueDate}, $ce->{siteDefaults}{timezone});
102 $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files
267 $envir{answerDate} = $set->answer_date; 103 $envir{answerDate} = $set->answer_date;
268 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}); 104 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}, $ce->{siteDefaults}{timezone});
269 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0); 105 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
270 $envir{problemValue} = $problem->value; 106 $envir{problemValue} = $problem->value;
271 $envir{sessionKey} = $key; 107 $envir{sessionKey} = $key;
272 $envir{courseName} = $courseEnv->{courseName}; 108 $envir{courseName} = $ce->{courseName};
273 109
274 # Student Information 110 # Student Information
275 # ADDED: studentID 111 # ADDED: studentID
276 112
277 $envir{sectionName} = $user->section; 113 $envir{sectionName} = $user->section;
278 $envir{sectionNumber} = $envir{sectionName}; 114 $envir{sectionNumber} = $envir{sectionName};
279 $envir{recitationName} = $user->recitation; 115 $envir{recitationName} = $user->recitation;
280 $envir{recitationNumber} = $envir{recitationName}; 116 $envir{recitationNumber} = $envir{recitationName};
281 $envir{setNumber} = $set->id; 117 $envir{setNumber} = $set->set_id;
282 $envir{studentLogin} = $user->id; 118 $envir{studentLogin} = $user->user_id;
283 $envir{studentName} = $user->first_name . " " . $user->last_name; 119 $envir{studentName} = $user->first_name . " " . $user->last_name;
284 $envir{studentID} = $user->student_id; 120 $envir{studentID} = $user->student_id;
285 121
286 # Answer Information 122 # Answer Information
287 # REMOVED: refSubmittedAnswers 123 # REMOVED: refSubmittedAnswers
290 126
291 # External Programs 127 # External Programs
292 # ADDED: externalLaTeXPath, externalDvipngPath, 128 # ADDED: externalLaTeXPath, externalDvipngPath,
293 # externalGif2EpsPath, externalPng2EpsPath 129 # externalGif2EpsPath, externalPng2EpsPath
294 130
295 $envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth}; 131 $envir{externalTTHPath} = $ce->{externalPrograms}->{tth};
296 $envir{externalLaTeXPath} = $courseEnv->{externalPrograms}->{latex}; 132 $envir{externalLaTeXPath} = $ce->{externalPrograms}->{latex};
297 $envir{externalDvipngPath} = $courseEnv->{externalPrograms}->{dvipng}; 133 $envir{externalDvipngPath} = $ce->{externalPrograms}->{dvipng};
298 $envir{externalGif2EpsPath} = $courseEnv->{externalPrograms}->{gif2eps}; 134 $envir{externalGif2EpsPath} = $ce->{externalPrograms}->{gif2eps};
299 $envir{externalPng2EpsPath} = $courseEnv->{externalPrograms}->{png2eps}; 135 $envir{externalPng2EpsPath} = $ce->{externalPrograms}->{png2eps};
300 $envir{externalGif2PngPath} = $courseEnv->{externalPrograms}->{gif2png}; 136 $envir{externalGif2PngPath} = $ce->{externalPrograms}->{gif2png};
301 137 $envir{externalCheckUrl} = $ce->{externalPrograms}->{checkurl};
302 # Directories and URLs 138 # Directories and URLs
303 # REMOVED: courseName 139 # REMOVED: courseName
304 # ADDED: dvipngTempDir 140 # ADDED: dvipngTempDir
141 # ADDED: jsMathURL
142 # ADDED: asciimathURL
143 # ADDED: macrosPath
144 # REMOVED: macrosDirectory, courseScriptsDirectory
145 # ADDED: LaTeXMathML
305 146
306 $envir{cgiDirectory} = undef; 147 $envir{cgiDirectory} = undef;
307 $envir{cgiURL} = undef; 148 $envir{cgiURL} = undef;
308 $envir{classDirectory} = undef; 149 $envir{classDirectory} = undef;
309 $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/"; 150 $envir{macrosPath} = $ce->{pg}->{directories}{macrosPath};
151 $envir{appletPath} = $ce->{pg}->{directories}{appletPath};
152 $envir{pgDirectories} = $ce->{pg}->{directories};
310 $envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/"; 153 $envir{htmlDirectory} = $ce->{courseDirs}->{html}."/";
311 $envir{htmlURL} = $courseEnv->{courseURLs}->{html}."/"; 154 $envir{htmlURL} = $ce->{courseURLs}->{html}."/";
312 $envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/";
313 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/"; 155 $envir{templateDirectory} = $ce->{courseDirs}->{templates}."/";
314 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/"; 156 $envir{tempDirectory} = $ce->{courseDirs}->{html_temp}."/";
315 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/"; 157 $envir{tempURL} = $ce->{courseURLs}->{html_temp}."/";
316 $envir{scriptDirectory} = undef; 158 $envir{scriptDirectory} = undef;
317 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/"; 159 $envir{webworkDocsURL} = $ce->{webworkURLs}->{docs}."/";
318 $envir{dvipngTempDir} = $options->{displayMode} eq 'images' 160 $envir{localHelpURL} = $ce->{webworkURLs}->{local_help}."/";
319 ? tempdir("webwork-dvipng-XXXXXXXX", DIR => $envir{tempDirectory}) 161 $envir{jsMathURL} = $ce->{webworkURLs}->{jsMath};
320 : undef; 162 $envir{asciimathURL} = $ce->{webworkURLs}->{asciimath};
163 $envir{LaTeXMathMLURL} = $ce->{webworkURLs}->{LaTeXMathML};
164 $envir{server_root_url} = $ce->{apache_root_url};
165
166 # Information for sending mail
167
168 $envir{mailSmtpServer} = $ce->{mail}->{smtpServer};
169 $envir{mailSmtpSender} = $ce->{mail}->{smtpSender};
170 $envir{ALLOW_MAIL_TO} = $ce->{mail}->{allowedRecipients};
321 171
322 # Default values for evaluating answers 172 # Default values for evaluating answers
323 173
324 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults}; 174 my $ansEvalDefaults = $ce->{pg}->{ansEvalDefaults};
325 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults); 175 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
326 176
177 # ----------------------------------------------------------------------
178
179 # ADDED: ImageGenerator for images mode
180 if (defined $extras->{image_generator}) {
181 $envir{imagegen} = $extras->{image_generator};
182 # only allow access to the add() method
183 $envir{imagegen} = new WeBWorK::Utils::RestrictedClosureClass($extras->{image_generator}, "add");
184 }
185
186 # ADDED: jsMath options
187 $envir{jsMath} = {%{$ce->{pg}{displayModeOptions}{jsMath}}};
188
327 # Other things... 189 # Other things...
328 190 $envir{QUIZ_PREFIX} = $options->{QUIZ_PREFIX}; # used by quizzes
329 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader}; 191 $envir{PROBLEM_GRADER_TO_USE} = $ce->{pg}->{options}->{grader};
192 $envir{PRINT_FILE_NAMES_FOR} = $ce->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
193
194 # ADDED: __files__
195 # an array for mapping (eval nnn) to filenames in error messages
196 $envir{__files__} = {
197 root => $ce->{webworkDirs}{root}, # used to shorten filenames
198 pg => $ce->{pg}{directories}{root}, # ditto
199 tmpl => $ce->{courseDirs}{templates}, # ditto
200 };
201
202 # variables for interpreting capa problems and other things to be
203 # seen in a pg file
204 my $specialPGEnvironmentVarHash = $ce->{pg}->{specialPGEnvironmentVars};
205 for my $SPGEV (keys %{$specialPGEnvironmentVarHash}) {
206 $envir{$SPGEV} = $specialPGEnvironmentVarHash->{$SPGEV};
207 }
330 208
331 return \%envir; 209 return \%envir;
332} 210}
333 211
334sub translateDisplayModeNames($) { 212sub translateDisplayModeNames($) {
335 my $name = shift; 213 my $name = shift;
336 return { 214 return DISPLAY_MODES()->{$name};
337 tex => "TeX",
338 plainText => "HTML",
339 formattedText => "HTML_tth",
340 images => "HTML_img"
341 }->{$name};
342} 215}
343 216
344sub safetyFilter { 217sub oldSafetyFilter {
345 my $answer = shift; # accepts one answer and checks it 218 my $answer = shift; # accepts one answer and checks it
346 my $submittedAnswer = $answer; 219 my $submittedAnswer = $answer;
347 $answer = '' unless defined $answer; 220 $answer = '' unless defined $answer;
348 my ($errorno); 221 my ($errorno);
349 $answer =~ tr/\000-\037/ /; 222 $answer =~ tr/\000-\037/ /;
353 $errorno = 0; ## don't report blank answer as error 226 $errorno = 0; ## don't report blank answer as error
354 return ($answer,$errorno); 227 return ($answer,$errorno);
355 } 228 }
356 # replace ^ with ** (for exponentiation) 229 # replace ^ with ** (for exponentiation)
357 # $answer =~ s/\^/**/g; 230 # $answer =~ s/\^/**/g;
358 # Return if forbidden characters are found 231 # Return if forbidden characters are found
359 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) { 232 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ ) {
360 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c; 233 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
361 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>"; 234 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
362 return ($answer,$errorno); 235 return ($answer,$errorno);
363 } 236 }
364 $errorno = 0; 237 $errorno = 0;
365 return($answer, $errorno); 238 return($answer, $errorno);
366} 239}
367 240
241sub nullSafetyFilter {
242 return shift, 0; # no errors
243}
244
3681; 2451;
369 246
370__END__ 247__END__
371 248
372=head1 SYNOPSIS 249=head1 SYNOPSIS
373 250
374 $pg = WeBWorK::PG->new( 251 $pg = WeBWorK::PG->new(
375 $courseEnv, # a WeBWorK::CourseEnvironment object 252 $ce, # a WeBWorK::CourseEnvironment object
376 $user, # a WeBWorK::User object 253 $user, # a WeBWorK::DB::Record::User object
377 $sessionKey, 254 $sessionKey,
378 $set, # a WeBWorK::Set object 255 $set, # a WeBWorK::DB::Record::UserSet object
379 $problem, # a WeBWorK::Problem object 256 $problem, # a WeBWorK::DB::Record::UserProblem object
380 $psvn, 257 $psvn,
381 $formFields # in &WeBWorK::Form::Vars format 258 $formFields # in &WeBWorK::Form::Vars format
382 { # translation options 259 { # translation options
383 displayMode => "images", # (plainText|formattedText|images) 260 displayMode => "images", # (plainText|formattedText|images)
384 showHints => 1, # (0|1) 261 showHints => 1, # (0|1)
398 $warnings = $pg->{warnings}; # text string 275 $warnings = $pg->{warnings}; # text string
399 $flags = $pg->{flags}; # hash reference 276 $flags = $pg->{flags}; # hash reference
400 277
401=head1 DESCRIPTION 278=head1 DESCRIPTION
402 279
403WeBWorK::PG encapsulates the PG translation process, making multiple calls to 280WeBWorK::PG is a factory for modules which use the WeBWorK::PG API. Notable
404WeBWorK::PG::Translator. Much of the flexibility of the Translator is hidden, 281modules which use this API (and exist) are WeBWorK::PG::Local and
405instead making choices that are appropriate for the webwork-modperl system. 282WeBWorK::PG::Remote. The course environment key $pg{renderer} is consulted to
283determine which render to use.
406 284
407=head1 CONSTRUCTION 285=head1 THE WEBWORK::PG API
286
287Modules which support this API must implement the following method:
408 288
409=over 289=over
410 290
411=item new (ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS) 291=item new ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS
412 292
413The C<new> method creates a translator, initializes it using the parameters 293The C<new> method creates a translator, initializes it using the parameters
414specified, translates a PG file, and processes answers. It returns a reference 294specified, translates a PG file, and processes answers. It returns a reference
415to a blessed hash containing the results of the translation process. 295to a blessed hash containing the results of the translation process.
416 296
436 316
437a WeBWorK::Set object 317a WeBWorK::Set object
438 318
439=item PROBLEM 319=item PROBLEM
440 320
441a WeBWorK::Problem object. The contents of the source_file field can specify a 321a WeBWorK::DB::Record::UserProblem object. The contents of the source_file
442PG file either by absolute path or path relative to the "templates" directory. 322field can specify a PG file either by absolute path or path relative to the
443I<The caller should remove taint from this value before passing!> 323"templates" directory. I<The caller should remove taint from this value before
324passing!>
444 325
445=item PSVN 326=item PSVN
446 327
447the problem set version number 328the problem set version number
448 329
471boolean, render solutions 352boolean, render solutions
472 353
473=item refreshMath2img 354=item refreshMath2img
474 355
475boolean, force images created by math2img (in "images" mode) to be recreated, 356boolean, force images created by math2img (in "images" mode) to be recreated,
476even if the PG source has not been updated. 357even if the PG source has not been updated. FIXME: remove this option.
477 358
478=item processAnswers 359=item processAnswers
479 360
480boolean, call answer evaluators and graders 361boolean, call answer evaluators and graders
481 362
529 410
530A hash containing PG_flags (see the Translator docs). 411A hash containing PG_flags (see the Translator docs).
531 412
532=back 413=back
533 414
534=head1 OPERATION 415=head1 METHODS PROVIDED BY THE BASE CLASS
535 416
536WeBWorK::PG goes through the following operations when constructed: 417The following methods are provided for use by subclasses of WeBWorK::PG.
537 418
538=over 419=over
539 420
540=item Get database information 421=item defineProblemEnvir ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS
541 422
542Retrieve information about the current user, set, and problem from the 423Generate a problem environment hash to pass to the renderer.
543database.
544 424
545=item Create a translator 425=item translateDisplayModeNames NAME
546 426
547Instantiate a WeBWorK::PG::Translator object. 427NAME contains
548
549=item Set the directory hash
550
551Set the translator's directory hash (courseScripts, macros, templates, and temp
552directories) from the course environment.
553
554=item Evaluate PG modules
555
556Using the module list from the course environment (pg->modules), perform a
557"use"-like operation to evaluate modules at runtime.
558
559=item Set the problem environment
560
561Use data from the user, set, and problem, as well as the course environemnt and
562translation options, to set the problem environment.
563
564=item Initialize the translator
565
566Call &WeBWorK::PG::Translator::initialize. What more do you want?
567
568=item Load PG.pl and dangerousMacros.pl
569
570These macros must be loaded without opcode masking, so they are loaded here.
571
572=item Set the opcode mask
573
574Set the opcode mask to the default specified by WeBWorK::PG::Translator.
575
576=item Load the problem source
577
578Give the problem source to the translator.
579
580=item Install a safety filter
581
582The safety filter is used to preprocess student input before evaluation. The
583default safety filter, &WeBWorK::PG::safetyFilter, is used.
584
585=item Translate the problem source
586
587Call &WeBWorK::PG::Translator::translate to render the problem source into the
588format given by the display mode.
589
590=item Process student answers
591
592Use form field inputs to evaluate student answers.
593
594=item Load the problem state
595
596Use values from the database to initialize the problem state, so that the
597grader will have a point of reference.
598
599=item Determine an entry order
600
601Use the ANSWER_ENTRY_ORDER flag to determine the order of answers in the
602problem. This is important for problems with dependancies among parts.
603
604=item Install a grader
605
606Use the PROBLEM_GRADER_TO_USE flag, or a default from the course environment,
607to install a grader.
608
609=item Grade the problem
610
611Use the selected grader to grade the problem.
612 428
613=back 429=back
614 430
615=head1 AUTHOR 431=head1 AUTHOR
616 432

Legend:
Removed from v.620  
changed lines
  Added in v.4397

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9