Parent Directory
|
Revision Log
small changes to support hardcopy work. -sam
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 $self->latex2pdf($tex, $tempDir, $fileName) or return; 109 110 return "$tempURL/$fileName"; 111 } 112 113 sub latex2pdf { 114 # this is a little ad-hoc function which I will replace with a LaTeX 115 # module at some point (or put it in Utils). 116 my ($self, $tex, $fileBase, $fileName) = @_; 117 my $finalFile = "$fileBase/$fileName"; 118 my $ce = $self->{courseEnvironment}; 119 120 # create a temporary directory for tex to shit in 121 my $wd = tempdir("webwork-hardcopy-XXXXXXXX", TMPDIR => 1); 122 my $texFile = "$wd/hardcopy.tex"; 123 my $pdfFile = "$wd/hardcopy.pdf"; 124 my $logFile = "$wd/hardcopy.log"; 125 126 # write the tex file 127 local *TEX; 128 open TEX, ">", $texFile; 129 print TEX $tex; 130 close TEX; 131 132 # 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) 134 my $pdflatex = $ce->{externalPrograms}->{pdflatex}; 135 system "cd $wd && $pdflatex $texFile"; 136 137 if (-e $pdfFile) { 138 # move resulting PDF file to appropriate location 139 my $mv = $ce->{externalPrograms}->{mv}; 140 system $mv, $pdfFile, $finalFile and die "Failed to mv: $!\n"; 141 } 142 143 # remove temporary directory 144 #rmtree($wd, 0, 1); 145 146 return -e $finalFile; 147 } 148 149 # ----- 150 151 sub getMultiSetTeX { 152 my ($self, @sets) = @_; 153 my $ce = $self->{courseEnvironment}; 154 my $tex = ""; 155 156 # the document preamble 157 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{preamble}); 158 159 while (my $set = shift @sets) { 160 $tex .= $self->getSetTeX($set); 161 if (@sets) { 162 # divide sets, but not after the last set 163 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{setDivider}); 164 } 165 } 166 167 # the document postamble 168 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{postamble}); 169 170 return $tex; 171 } 172 173 sub getSetTeX { 174 my ($self, $setName) = @_; 175 my $ce = $self->{courseEnvironment}; 176 my $wwdb = $self->{wwdb}; 177 my $user = $self->{r}->param("user"); 178 my @problemNumbers = sort { $a <=> $b } $wwdb->getProblems($user, $setName); 179 180 # get header and footer 181 my $setHeader = $wwdb->getSet($user, $setName)->set_header 182 || $ce->{webworkFiles}->{hardcopySnippets}->{setHeader}; 183 # database doesn't support the following yet :( 184 #my $setFooter = $wwdb->getSet($user, $setName)->set_footer 185 # || $ce->{webworkFiles}->{hardcopySnippets}->{setFooter}; 186 # so we don't allow per-set customization, which is probably okay :) 187 my $setFooter = $ce->{webworkFiles}->{hardcopySnippets}->{setFooter}; 188 189 my $tex = ""; 190 191 # render header 192 $tex .= texBlockComment("BEGIN $setName : $setHeader"); 193 $tex .= $self->getProblemTeX($setName, 0, $setHeader); 194 195 # render each problem 196 while (my $problemNumber = shift @problemNumbers) { 197 $tex .= texBlockComment("BEGIN $setName : $problemNumber"); 198 $tex .= $self->getProblemTeX($setName, $problemNumber); 199 if (@problemNumbers) { 200 # divide problems, but not after the last problem 201 $tex .= $self->texInclude($ce->{webworkFiles}->{hardcopySnippets}->{problemDivider}); 202 } 203 } 204 205 # render footer 206 $tex .= texBlockComment("BEGIN $setName : $setFooter"); 207 $tex .= $self->getProblemTeX($setName, 0, $setFooter); 208 209 return $tex; 210 } 211 212 sub getProblemTeX { 213 my ($self, $setName, $problemNumber, $pgFile) = @_; 214 my $r = $self->{r}; 215 my $ce = $self->{courseEnvironment}; 216 217 my $wwdb = $self->{wwdb}; 218 my $cldb = $self->{cldb}; 219 my $user = $cldb->getUser($r->param("user")); 220 my $set = $wwdb->getSet($user->id, $setName); 221 my $psvn = $wwdb->getPSVN($user->id, $setName); 222 223 # decide what to do about problem number 224 my $problem; 225 if ($problemNumber) { 226 $problem = $wwdb->getProblem($user->id, $setName, $problemNumber); 227 } elsif ($pgFile) { 228 $problem = WeBWorK::Problem->new( 229 id => 0, 230 set_id => $set->id, 231 login_id => $user->id, 232 source_file => $pgFile, 233 # the rest of Problem's fields are not needed, i think 234 ); 235 } 236 237 my $pg = WeBWorK::PG->new( 238 $ce, 239 $user, 240 $r->param('key'), 241 $set, 242 $problem, 243 $psvn, 244 {}, # no form fields! 245 { # translation options 246 displayMode => "tex", 247 showHints => 0, 248 showSolutions => 0, 249 processAnswers => 0, 250 }, 251 ); 252 253 warn "***GET READY FOR PG WARNINGS!!!!!\n***SET=$setName PROBLEM=$problemNumber\n", 254 $pg->{warnings}, "***OK NO MORE PG WARNINGS!!!!\n" if $pg->{warnings}; 255 256 return $pg->{body_text}; 257 } 258 259 sub texInclude { 260 my ($self, $texFile) = @_; 261 my $tex = ""; 262 263 $tex .= texBlockComment("BEGIN: $texFile"); 264 eval { 265 $tex .= readFile($texFile) 266 }; 267 if ($@) { 268 $tex .= texBlockComment($@); 269 } 270 271 return $tex; 272 } 273 274 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |