Parent Directory
|
Revision Log
- created macros/IO.pl, which is loaded with no opmask by PG.pm. It is a copy of WeBWorK::PG::IO.pm, with some changes to make it work as a macro package. The translator no longer shares IO.pm's functions with the safe compartment. This is a BAD THING, and should be reconsidered when the Translator is revised. - Changed many (but not all) checks for HTML or HTML_tth modes to match /^HTML/ in the macros. - changed &header to &head in Problem.pm - Added problem environment variables for gif2eps and png2eps and modified &dangerousMacros::alias to use them - fixed MOST of the harmless warnings in the system. there's still the "Use of uninitialized value in null operation" warning in template(), tho. Still to come: - make images in PDFs work - fix TTH mode character encodings on mac (maybe) - have logout button invalidate key - Pretty die messages (from outside of the translator) - Feedback - need nice modular way of sending email - Options - email address and password
1 ################################################################################ 2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 3 # $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 use File::Path qw(rmtree); 21 use File::Temp qw(tempdir); 22 use WeBWorK::DB::Classlist; 23 use WeBWorK::DB::WW; 24 use WeBWorK::Form; 25 use WeBWorK::Utils qw(readFile); 26 27 sub texBlockComment { return "\n".("%"x80)."\n%% ".join("", @_)."\n".("%"x80)."\n\n"; } 28 29 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 return "Hardcopy Generator"; 51 } 52 53 sub body { 54 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 unless (@sets) { 63 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 ""; 82 } 83 84 # ----- 85 86 sub 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} 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 #print CGI::pre($tex); 109 $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 my $ce = $self->{courseEnvironment}; 120 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 my $logFile = "$wd/hardcopy.log"; 126 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 my $pdflatex = $ce->{externalPrograms}->{pdflatex}; 136 system "cd $wd && $pdflatex $texFile"; 137 138 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 } 149 150 # ----- 151 152 sub getMultiSetTeX { 153 my ($self, @sets) = @_; 154 my $ce = $self->{courseEnvironment}; 155 my $tex = ""; 156 157 # the document preamble 158 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble}); 159 160 while (my $set = shift @sets) { 161 $tex .= $self->getSetTeX($set); 162 if (@sets) { 163 # divide sets, but not after the last set 164 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider}); 165 } 166 } 167 168 # the document postamble 169 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{postamble}); 170 171 return $tex; 172 } 173 174 sub getSetTeX { 175 my ($self, $setName) = @_; 176 my $ce = $self->{courseEnvironment}; 177 my $wwdb = $self->{wwdb}; 178 my $user = $self->{r}->param("user"); 179 my @problemNumbers = sort { $a <=> $b } $wwdb->getProblems($user, $setName); 180 181 # 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 # so we don't allow per-set customization, which is probably okay :) 188 my $setFooter = $ce->{webworkFiles}->{hardcopySnippets}->{setFooter}; 189 190 my $tex = ""; 191 192 # render header 193 $tex .= texBlockComment("BEGIN $setName : $setHeader"); 194 $tex .= $self->getProblemTeX($setName, 0, $setHeader); 195 196 # render each problem 197 while (my $problemNumber = shift @problemNumbers) { 198 $tex .= texBlockComment("BEGIN $setName : $problemNumber"); 199 $tex .= $self->getProblemTeX($setName, $problemNumber); 200 if (@problemNumbers) { 201 # divide problems, but not after the last problem 202 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{problemDivider}); 203 } 204 } 205 206 # render footer 207 $tex .= texBlockComment("BEGIN $setName : $setFooter"); 208 $tex .= $self->getProblemTeX($setName, 0, $setFooter); 209 210 return $tex; 211 } 212 213 sub getProblemTeX { 214 my ($self, $setName, $problemNumber, $pgFile) = @_; 215 my $r = $self->{r}; 216 my $ce = $self->{courseEnvironment}; 217 218 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 my $pg = WeBWorK::PG->new( 239 $ce, 240 $user, 241 $r->param('key'), 242 $set, 243 $problem, 244 $psvn, 245 {}, # no form fields! 246 { # 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 sub texInclude { 258 my ($self, $texFile) = @_; 259 my $tex = ""; 260 261 $tex .= texBlockComment("BEGIN: $texFile"); 262 eval { 263 $tex .= readFile($texFile) 264 }; 265 if ($@) { 266 $tex .= texBlockComment($@); 267 } 268 269 return $tex; 270 } 271 272 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |