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

Annotation of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Hardcopy.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 562 - (view) (download) (as text)

1 : sh002i 478 ################################################################################
2 : sh002i 494 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
3 : sh002i 478 # $Id$
4 :     ################################################################################
5 :    
6 :     package WeBWorK::ContentGenerator::Hardcopy;
7 :    
8 :     =head1 NAME
9 :    
10 :     WeBWorK::ContentGenerator::Test - generate a PDF version of one or more
11 :     problem sets.
12 :    
13 :     =cut
14 :    
15 :     use strict;
16 :     use warnings;
17 :     use base qw(WeBWorK::ContentGenerator);
18 :     use Apache::Constants qw(:common);
19 :     use CGI qw();
20 : sh002i 502 use File::Path qw(rmtree);
21 :     use File::Temp qw(tempdir);
22 :     use WeBWorK::DB::Classlist;
23 :     use WeBWorK::DB::WW;
24 : sh002i 478 use WeBWorK::Form;
25 :     use WeBWorK::Utils qw(readFile);
26 :    
27 : sh002i 492 sub texBlockComment { return "\n".("%"x80)."\n%% ".join("", @_)."\n".("%"x80)."\n\n"; }
28 :    
29 : sh002i 502 sub initialize {
30 :     my $self = shift;
31 :     my $ce = $self->{courseEnvironment};
32 :     $self->{cldb} = WeBWorK::DB::Classlist->new($ce);
33 :     $self->{wwdb} = WeBWorK::DB::WW->new($ce);
34 :     }
35 :    
36 :     sub path {
37 :     my ($self, undef, $args) = @_;
38 :    
39 :     my $ce = $self->{courseEnvironment};
40 :     my $root = $ce->{webworkURLs}->{root};
41 :     my $courseName = $ce->{courseName};
42 :     return $self->pathMacro($args,
43 :     "Home" => "$root",
44 :     $courseName => "$root/$courseName",
45 :     "Hardcopy Generator" => "",
46 :     );
47 :     }
48 :    
49 :     sub title {
50 : sh002i 547 return "Hardcopy Generator";
51 : sh002i 502 }
52 :    
53 :     sub body {
54 : sh002i 478 my ($self, $singleSet) = @_;
55 :     $singleSet =~ s/^set//;
56 :     my $r = $self->{r};
57 :     my $ce = $self->{courseEnvironment};
58 :     $self->{wwdb} = WeBWorK::DB::WW->new($ce);
59 :    
60 :     my @sets = $r->param("set");
61 :     unshift @sets, $singleSet;
62 : sh002i 502 unless (@sets) {
63 :     print CGI::p("No problem sets were specified.");
64 :     return OK;
65 :     }
66 : sh002i 478
67 : sh002i 562 #print CGI::pre($self->getMultiSetTeX(@sets));
68 :     #return "";
69 :    
70 : sh002i 502 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 : sh002i 478
81 : sh002i 502 return "";
82 : sh002i 478 }
83 :    
84 : sh002i 502 # -----
85 :    
86 :     sub makeHardcopy {
87 : sh002i 492 my ($self, @sets) = @_;
88 : sh002i 502 my $courseName = $self->{courseEnvironment}->{courseName};
89 :     my $userName = $self->{r}->param("user");
90 :     my $tempDir = $self->{courseEnvironment}->{courseDirs}->{html_temp}
91 :     . "/hardcopy";
92 :     my $tempURL = $self->{courseEnvironment}->{courseURLs}->{html_temp}
93 :     . "/hardcopy";
94 :    
95 :     # determine name of PDF file
96 :     my $fileName;
97 :     if (@sets > 1) {
98 :     # multiset output
99 :     $fileName = "$courseName.$userName.multiset.pdf"
100 :     } elsif (@sets == 1) {
101 :     # only one set
102 :     my $setName = $sets[0];
103 :     $fileName = "$courseName.$userName.$setName.pdf";
104 :     } else {
105 :     $fileName = "$courseName.$userName.pdf";
106 :     }
107 :     my $tex = $self->getMultiSetTeX(@sets);
108 : sh002i 547 #print CGI::pre($tex);
109 : sh002i 502 $self->latex2pdf($tex, $tempDir, $fileName) or return;
110 :    
111 :     return "$tempURL/$fileName";
112 :     }
113 :    
114 :     sub latex2pdf {
115 :     # this is a little ad-hoc function which I will replace with a LaTeX
116 :     # module at some point (or put it in Utils).
117 :     my ($self, $tex, $fileBase, $fileName) = @_;
118 :     my $finalFile = "$fileBase/$fileName";
119 : sh002i 492 my $ce = $self->{courseEnvironment};
120 : sh002i 502
121 :     # create a temporary directory for tex to shit in
122 :     my $wd = tempdir("webwork-hardcopy-XXXXXXXX", TMPDIR => 1);
123 :     my $texFile = "$wd/hardcopy.tex";
124 :     my $pdfFile = "$wd/hardcopy.pdf";
125 : sh002i 562 my $logFile = "$wd/hardcopy.log";
126 : sh002i 502
127 :     # write the tex file
128 :     local *TEX;
129 :     open TEX, ">", $texFile;
130 :     print TEX $tex;
131 :     close TEX;
132 :    
133 :     # call pdflatex - we don't want to chdir in the mod_perl process, as
134 :     # that might step on the feet of other things (esp. in Apache 2.0)
135 : sh002i 492 my $pdflatex = $ce->{externalPrograms}->{pdflatex};
136 : sh002i 502 system "cd $wd && $pdflatex $texFile";
137 : sh002i 478
138 : sh002i 502 if (-e $pdfFile) {
139 :     # move resulting PDF file to appropriate location
140 :     my $mv = $ce->{externalPrograms}->{mv};
141 :     system $mv, $pdfFile, $finalFile and die "Failed to mv: $!\n";
142 :     }
143 :    
144 :     # remove temporary directory
145 :     rmtree($wd, 0, 1);
146 :    
147 :     return -e $finalFile;
148 : sh002i 478 }
149 :    
150 : sh002i 502 # -----
151 :    
152 :     sub getMultiSetTeX {
153 : sh002i 492 my ($self, @sets) = @_;
154 :     my $ce = $self->{courseEnvironment};
155 : sh002i 502 my $tex = "";
156 : sh002i 492
157 : sh002i 502 # the document preamble
158 :     $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble});
159 : sh002i 492
160 :     while (my $set = shift @sets) {
161 : sh002i 502 $tex .= $self->getSetTeX($set);
162 : sh002i 492 if (@sets) {
163 :     # divide sets, but not after the last set
164 : sh002i 502 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider});
165 : sh002i 492 }
166 :     }
167 :    
168 : sh002i 502 # the document postamble
169 :     $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{postamble});
170 :    
171 :     return $tex;
172 : sh002i 492 }
173 :    
174 : sh002i 478 sub getSetTeX {
175 :     my ($self, $setName) = @_;
176 :     my $ce = $self->{courseEnvironment};
177 :     my $wwdb = $self->{wwdb};
178 :     my $user = $self->{r}->param("user");
179 : sh002i 492 my @problemNumbers = sort { $a <=> $b } $wwdb->getProblems($user, $setName);
180 : sh002i 478
181 : sh002i 492 # get header and footer
182 :     my $setHeader = $wwdb->getSet($user, $setName)->set_header
183 :     || $ce->{webworkFiles}->{hardcopySnippets}->{setHeader};
184 :     # database doesn't support the following yet :(
185 :     #my $setFooter = $wwdb->getSet($user, $setName)->set_footer
186 :     # || $ce->{webworkFiles}->{hardcopySnippets}->{setFooter};
187 : sh002i 502 # so we don't allow per-set customization, which is probably okay :)
188 :     my $setFooter = $ce->{webworkFiles}->{hardcopySnippets}->{setFooter};
189 : sh002i 478
190 : sh002i 502 my $tex = "";
191 :    
192 : sh002i 492 # render header
193 : sh002i 502 $tex .= texBlockComment("BEGIN $setName : $setHeader");
194 : sh002i 547 $tex .= $self->getProblemTeX($setName, 0, $setHeader);
195 : sh002i 478
196 :     # render each problem
197 : sh002i 492 while (my $problemNumber = shift @problemNumbers) {
198 : sh002i 502 $tex .= texBlockComment("BEGIN $setName : $problemNumber");
199 :     $tex .= $self->getProblemTeX($setName, $problemNumber);
200 : sh002i 492 if (@problemNumbers) {
201 :     # divide problems, but not after the last problem
202 : sh002i 502 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{problemDivider});
203 : sh002i 492 }
204 : sh002i 478 }
205 :    
206 : sh002i 492 # render footer
207 : sh002i 502 $tex .= texBlockComment("BEGIN $setName : $setFooter");
208 :     $tex .= $self->getProblemTeX($setName, 0, $setFooter);
209 :    
210 :     return $tex;
211 : sh002i 478 }
212 :    
213 :     sub getProblemTeX {
214 : sh002i 502 my ($self, $setName, $problemNumber, $pgFile) = @_;
215 : sh002i 478 my $r = $self->{r};
216 :     my $ce = $self->{courseEnvironment};
217 :    
218 : sh002i 502 my $wwdb = $self->{wwdb};
219 :     my $cldb = $self->{cldb};
220 :     my $user = $cldb->getUser($r->param("user"));
221 :     my $set = $wwdb->getSet($user->id, $setName);
222 :     my $psvn = $wwdb->getPSVN($user->id, $setName);
223 :    
224 :     # decide what to do about problem number
225 :     my $problem;
226 :     if ($problemNumber) {
227 :     $problem = $wwdb->getProblem($user->id, $setName, $problemNumber);
228 :     } elsif ($pgFile) {
229 :     $problem = WeBWorK::Problem->new(
230 :     id => 0,
231 :     set_id => $set->id,
232 :     login_id => $user->id,
233 :     source_file => $pgFile,
234 :     # the rest of Problem's fields are not needed, i think
235 :     );
236 :     }
237 :    
238 : sh002i 478 my $pg = WeBWorK::PG->new(
239 :     $ce,
240 : sh002i 502 $user,
241 : sh002i 478 $r->param('key'),
242 : sh002i 502 $set,
243 :     $problem,
244 :     $psvn,
245 :     {}, # no form fields!
246 : sh002i 478 { # translation options
247 :     displayMode => "tex",
248 :     showHints => 0,
249 :     showSolutions => 0,
250 :     processAnswers => 0,
251 :     },
252 :     );
253 :    
254 :     return $pg->{body_text};
255 :     }
256 :    
257 : sh002i 492 sub texInclude {
258 :     my ($self, $texFile) = @_;
259 : sh002i 502 my $tex = "";
260 : sh002i 492
261 : sh002i 502 $tex .= texBlockComment("BEGIN: $texFile");
262 : sh002i 492 eval {
263 : sh002i 502 $tex .= readFile($texFile)
264 : sh002i 492 };
265 :     if ($@) {
266 : sh002i 502 $tex .= texBlockComment($@);
267 : sh002i 492 }
268 : sh002i 502
269 :     return $tex;
270 : sh002i 478 }
271 :    
272 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9