[system] / trunk / webwork2 / lib / WeBWorK / PG.pm Repository:
ViewVC logotype

Diff of /trunk/webwork2/lib/WeBWorK/PG.pm

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

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

Legend:
Removed from v.699  
changed lines
  Added in v.4091

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9