[system] / trunk / webwork-modperl / lib / WeBWorK / ContentGenerator / Hardcopy.pm Repository:
ViewVC logotype

Diff of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Hardcopy.pm

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

Revision 640 Revision 641
5 5
6package WeBWorK::ContentGenerator::Hardcopy; 6package WeBWorK::ContentGenerator::Hardcopy;
7 7
8=head1 NAME 8=head1 NAME
9 9
10WeBWorK::ContentGenerator::Test - generate a PDF version of one or more 10WeBWorK::ContentGenerator::Hardcopy - generate a PDF version of one or more
11problem sets. 11problem sets.
12 12
13=cut 13=cut
14 14
15use strict; 15use strict;
16use warnings; 16use warnings;
17use base qw(WeBWorK::ContentGenerator); 17use base qw(WeBWorK::ContentGenerator);
18use Apache::Constants qw(:common); 18#use Apache::Constants qw(:common);
19use CGI qw(); 19use CGI qw();
20use File::Path qw(rmtree); 20use File::Path qw(rmtree);
21use File::Temp qw(tempdir); 21use File::Temp qw(tempdir);
22use WeBWorK::DB::Classlist; 22use WeBWorK::DB::Classlist;
23use WeBWorK::DB::WW; 23use WeBWorK::DB::WW;
24use WeBWorK::Form; 24use WeBWorK::Form;
25use WeBWorK::Utils qw(readFile); 25use WeBWorK::Utils qw(readFile);
26 26
27sub texBlockComment { return "\n".("%"x80)."\n%% ".join("", @_)."\n".("%"x80)."\n\n"; } 27sub texBlockComment(@) { return "\n".("%"x80)."\n%% ".join("", @_)."\n".("%"x80)."\n\n"; }
28 28
29sub initialize { 29sub initialize {
30 my $self = shift; 30 my ($self, $singleSet, undef) = @_;
31
32 my $r = $self->{r};
31 my $ce = $self->{courseEnvironment}; 33 my $ce = $self->{courseEnvironment};
34 my @sets = $r->param("set");
35
36 if (length $singleSet > 0) {
37 $singleSet =~ s/^set//;
38 unshift @sets, $singleSet;
39 }
40
32 $self->{cldb} = WeBWorK::DB::Classlist->new($ce); 41 $self->{cldb} = WeBWorK::DB::Classlist->new($ce);
33 $self->{wwdb} = WeBWorK::DB::WW->new($ce); 42 $self->{wwdb} = WeBWorK::DB::WW->new($ce);
43 $self->{sets} = \@sets;
44 $self->{errors} = [];
45 $self->{warnings} = [];
34} 46}
35 47
36sub path { 48sub path {
37 my ($self, undef, $args) = @_; 49 my ($self, undef, $args) = @_;
38 50
49sub title { 61sub title {
50 return "Hardcopy Generator"; 62 return "Hardcopy Generator";
51} 63}
52 64
53sub body { 65sub body {
54 my ($self, $singleSet) = @_; 66 my $self = shift;
55 $singleSet =~ s/^set//; 67
56 my $r = $self->{r};
57 my $ce = $self->{courseEnvironment}; 68 my $courseName = $self->{courseEnvironment}->{courseName};
58 $self->{wwdb} = WeBWorK::DB::WW->new($ce); 69 my $userName = $self->{r}->param("user");
70 my @sets = @{$self->{sets}};
59 71
60 my @sets = $r->param("set");
61 unshift @sets, $singleSet;
62 unless (@sets) { 72 unless (@sets) {
63 print CGI::p("No problem sets were specified."); 73 print CGI::p("No problem sets were specified.");
64 return OK;
65 }
66
67 #print CGI::pre($self->getMultiSetTeX(@sets));
68 #return "";
69
70 print CGI::p("Generating your hardcopy...");
71 my $url = $self->makeHardcopy(@sets);
72 if ($url) {
73 print CGI::p("Ok, your hardcopy is ready. Click the following link to download it.");
74 print CGI::p({-align=>"center"},
75 CGI::big(CGI::a({-href=>$url}, "Download PDF Hardcopy"))
76 );
77 } else {
78 print CGI::p("Hmm, looks like I was unable to generate the hardcopy you requested. I'm really sorry... :(");
79 }
80
81 return ""; 74 return "";
82} 75 }
83 76
84# ----- 77 # determine where hardcopy is going to go
85
86sub makeHardcopy {
87 my ($self, @sets) = @_;
88 my $courseName = $self->{courseEnvironment}->{courseName};
89 my $userName = $self->{r}->param("user");
90 my $tempDir = $self->{courseEnvironment}->{courseDirs}->{html_temp} 78 my $tempDir = $self->{courseEnvironment}->{courseDirs}->{html_temp}
91 . "/hardcopy"; 79 . "/hardcopy";
92 my $tempURL = $self->{courseEnvironment}->{courseURLs}->{html_temp} 80 my $tempURL = $self->{courseEnvironment}->{courseURLs}->{html_temp}
93 . "/hardcopy"; 81 . "/hardcopy";
94 82
102 my $setName = $sets[0]; 90 my $setName = $sets[0];
103 $fileName = "$courseName.$userName.$setName.pdf"; 91 $fileName = "$courseName.$userName.$setName.pdf";
104 } else { 92 } else {
105 $fileName = "$courseName.$userName.pdf"; 93 $fileName = "$courseName.$userName.pdf";
106 } 94 }
95
96 # determine full URL
97 my $fullURL = "$tempURL/$fileName";
98
99 # generate TeX from sets
107 my $tex = $self->getMultiSetTeX(@sets); 100 my $tex = $self->getMultiSetTeX(@sets);
101 #print CGI::pre($tex);
102
103 # check for PG errors (fatal)
104 if (@{$self->{errors}}) {
105 my @errors = @{$self->{errors}};
106 print CGI::h2("Software Errors");
107 print CGI::p(<<EOF);
108WeBWorK has encountered one or more software errors while attempting to process these sets.
109It is likely that there are error(s) in the problem itself.
110If you are a student, contact your professor to have the error(s) corrected.
111If you are a professor, please consut the error output below for more informaiton.
112EOF
113 foreach my $error (@errors) {
114 print CGI::h3("Set: ", $error->{set}, ", Problem: ", $error->{problem});
115 print CGI::h4("Error messages"), CGI::blockquote(CGI::pre($error->{message}));
116 print CGI::h4("Error context"), CGI::blockquote(CGI::pre($error->{context}));
117 }
118
119 return "";
120 }
121
122 # "try" to generate hardcopy
108 $self->latex2pdf($tex, $tempDir, $fileName) or return; 123 eval { $self->latex2pdf($tex, $tempDir, $fileName) };
124 if ($@) {
125 print CGI::p("An error occured while trying to generate your PDF hardcopy:");
126 print CGI::blockquote(CGI::pre($@));
127 return "";
128 } else {
129 print CGI::p({-align=>"center"},
130 CGI::big(CGI::a({-href=>$fullURL}, "Download PDF Hardcopy"))
131 );
132 }
109 133
110 return "$tempURL/$fileName"; 134 # check for PG warnings (non-fatal)
135 if (@{$self->{warnings}}) {
136 my @warnings = @{$self->{warnings}};
137 print CGI::h2("Software Warnings");
138 print CGI::p(<<EOF);
139WeBWorK has encountered warnings while attempting to process these sets.
140It is likely that this indicates an error or ambiguity in the problem(s) themselves.
141If you are a student, contact your professor to have the problem(s) corrected.
142If you are a professor, please consut the error output below for more informaiton.
143EOF
144 foreach my $warning (@warnings) {
145 print CGI::h3("Set: ", $warning->{set}, ", Problem: ", $warning->{problem});
146 print CGI::h4("Warning messages"), CGI::blockquote(CGI::pre($warning->{message}));
147 }
148 }
149
150 return "";
111} 151}
152
153# -----
112 154
113sub latex2pdf { 155sub latex2pdf {
114 # this is a little ad-hoc function which I will replace with a LaTeX 156 # this is a little ad-hoc function which I will replace with a LaTeX
115 # module at some point (or put it in Utils). 157 # module at some point (or put it in Utils).
116 my ($self, $tex, $fileBase, $fileName) = @_; 158 my ($self, $tex, $fileBase, $fileName) = @_;
123 my $pdfFile = "$wd/hardcopy.pdf"; 165 my $pdfFile = "$wd/hardcopy.pdf";
124 my $logFile = "$wd/hardcopy.log"; 166 my $logFile = "$wd/hardcopy.log";
125 167
126 # write the tex file 168 # write the tex file
127 local *TEX; 169 local *TEX;
128 open TEX, ">", $texFile; 170 open TEX, ">", $texFile or die "Failed to open $texFile: $!\n";
129 print TEX $tex; 171 print TEX $tex;
130 close TEX; 172 close TEX;
131 173
132 # call pdflatex - we don't want to chdir in the mod_perl process, as 174 # call pdflatex - we don't want to chdir in the mod_perl process, as
133 # that might step on the feet of other things (esp. in Apache 2.0) 175 # that might step on the feet of other things (esp. in Apache 2.0)
134 my $pdflatex = $ce->{externalPrograms}->{pdflatex}; 176 my $pdflatex = $ce->{externalPrograms}->{pdflatex};
135 system "cd $wd && $pdflatex $texFile"; 177 system "cd $wd && $pdflatex $texFile" and die "Failed to call pdflatex: $!\n";
136 178
137 if (-e $pdfFile) { 179 if (-e $pdfFile) {
138 # move resulting PDF file to appropriate location 180 # move resulting PDF file to appropriate location
139 my $mv = $ce->{externalPrograms}->{mv};
140 system $mv, $pdfFile, $finalFile and die "Failed to mv: $!\n"; 181 system "/bin/mv", $pdfFile, $finalFile and die "Failed to mv: $!\n";
141 } 182 }
142 183
143 # remove temporary directory 184 # remove temporary directory
144 rmtree($wd, 0, 1); 185 rmtree($wd, 0, 1);
145 186
146 return -e $finalFile; 187 -e $finalFile or die "Failed to create $finalFile for no apparent reason.\n";
147} 188}
148 189
149# ----- 190# -----
150 191
151sub getMultiSetTeX { 192sub getMultiSetTeX {
154 my $tex = ""; 195 my $tex = "";
155 196
156 # the document preamble 197 # the document preamble
157 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble}); 198 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble});
158 199
159 while (my $set = shift @sets) { 200 while (defined (my $setName = shift @sets)) {
160 $tex .= $self->getSetTeX($set); 201 $tex .= $self->getSetTeX($setName);
161 if (@sets) { 202 if (@sets) {
162 # divide sets, but not after the last set 203 # divide sets, but not after the last set
163 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider}); 204 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider});
164 } 205 }
165 } 206 }
214 my $r = $self->{r}; 255 my $r = $self->{r};
215 my $ce = $self->{courseEnvironment}; 256 my $ce = $self->{courseEnvironment};
216 257
217 my $wwdb = $self->{wwdb}; 258 my $wwdb = $self->{wwdb};
218 my $cldb = $self->{cldb}; 259 my $cldb = $self->{cldb};
219 my $user = $cldb->getUser($r->param("user")); 260 my $user = $cldb->getUser($r->param("user"));
220 my $set = $wwdb->getSet($user->id, $setName); 261 my $set = $wwdb->getSet($user->id, $setName);
221 my $psvn = $wwdb->getPSVN($user->id, $setName); 262 my $psvn = $wwdb->getPSVN($user->id, $setName);
222 263
223 # decide what to do about problem number 264 # decide what to do about problem number
224 my $problem; 265 my $problem;
225 if ($problemNumber) { 266 if ($problemNumber) {
226 $problem = $wwdb->getProblem($user->id, $setName, $problemNumber); 267 $problem = $wwdb->getProblem($user->id, $setName, $problemNumber);
248 showSolutions => 0, 289 showSolutions => 0,
249 processAnswers => 0, 290 processAnswers => 0,
250 }, 291 },
251 ); 292 );
252 293
253 warn "***GET READY FOR PG WARNINGS!!!!!\n***SET=$setName PROBLEM=$problemNumber\n", 294 if ($pg->{warnings} ne "") {
254 $pg->{warnings}, "***OK NO MORE PG WARNINGS!!!!\n" if $pg->{warnings}; 295 push @{$self->{warnings}}, {
296 set => $setName,
297 problem => $problemNumber,
298 message => $pg->{warnings},
299 };
300 }
301
302 if ($pg->{flags}->{error_flag}) {
303 push @{$self->{errors}}, {
304 set => $setName,
305 problem => $problemNumber,
306 message => $pg->{errors},
307 context => $pg->{body_text},
308 };
309 # if there was an error, body_text contains
310 # the error context, not TeX code
311 $pg->{body_text} = undef;
312 }
255 313
256 return $pg->{body_text}; 314 return $pg->{body_text};
257} 315}
258 316
259sub texInclude { 317sub texInclude {

Legend:
Removed from v.640  
changed lines
  Added in v.641

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9