--- loncom/interface/lonprintout.pm 2011/06/06 10:53:09 1.590 +++ loncom/interface/lonprintout.pm 2015/06/04 13:03:36 1.627.2.15 @@ -1,8 +1,7 @@ - # The LearningOnline Network # Printout # -# $Id: lonprintout.pm,v 1.590 2011/06/06 10:53:09 foxr Exp $ +# $Id: lonprintout.pm,v 1.627.2.15 2015/06/04 13:03:36 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -41,12 +40,12 @@ use Apache::admannotations; use Apache::lonenc; use Apache::entities; use Apache::londefdef; +# use Apache::structurelags; # for language management. use File::Basename; use HTTP::Response; use LONCAPA::map(); -use POSIX qw(strftime); use Apache::lonlocal; use Carp; use LONCAPA; @@ -76,6 +75,58 @@ my $font_size = 'normalsize'; # Default #---------------------------- Helper helpers. ------------------------- +## +# Filter function to determine if a resource is a printable sequence. +# +# @param $res -Resource to check. +# +# @return 1 - printable and a resource +# 0 - either notm a sequence or not printable. +# +sub printable_sequence { + my $res = shift; + + # Non-sequences are not listed: + + if (!$res->is_sequence()) { + return 0; + } + + # Person with pav or pfo can always print: + + if ($perm{'pav'} || $perm{'pfo'}) { + return 1; + } + + if ($res->is_sequence()) { + my $symb = $res->symb(); + my $navmap = $res->{NAV_MAP}; + + # Find the first resource in the map: + + my $iterator = $navmap->getIterator($res, undef, undef, 1, 1); + my $first = $iterator->next(); + + while (1) { + if ($first == $iterator->END_ITERATOR) { last; } + if (ref($first) && ! $first->is_sequence()) {last; } + $first = $iterator->next(); + } + + + # Might be an empty map: + + if (!ref($first)) { + return 0; + } + my $partsref = $first->parts(); + my @parts = @$partsref; + my ($open, $close) = $navmap->map_printdates($first, $parts[0]); + return &printable($open, $close); + } + return 0; +} + # BZ5209: # Create the states needed to run the helper for incomplete problems from # the current folder for selected students. @@ -96,8 +147,7 @@ my $font_size = 'normalsize'; # Default # Return: # XML that can be parsed by the helper to drive the state machine. # -sub create_incomplete_folder_selstud_helper($helper) -{ +sub create_incomplete_folder_selstud_helper { my ($helper, $map) = @_; @@ -123,7 +173,7 @@ sub create_incomplete_folder_selstud_hel my $format_chooser = &generate_format_selector($helper, 'Format of the print job', - '','CHOOSE_STUDENTS_INCOMPLETE_FORMAT'); # end state. + 'CHOOSE_STUDENTS_INCOMPLETE_FORMAT'); # end state. return $resource_chooser . $student_chooser . $format_chooser; } @@ -172,7 +222,6 @@ sub create_incomplete_course_helper { my $format = &generate_format_selector($helper, 'Format of the print job', - '', 'INCOMPLETE_PROBLEMS_COURSE_FORMAT'); # end state. return $resource_chooser . $people_chooser . $format; @@ -303,7 +352,6 @@ CHOOSE_RESOURCES CHOOSE_RESOURCES - return $result; } # @@ -356,7 +404,7 @@ sub generate_code_selector { - Bubble sheet type: + Bubblesheet type: $bubble_types @@ -395,21 +443,25 @@ CHOOSE_ANON1 return $result; } +# Returns the XML for choosing how assignments are to be formatted +# that text must still be parsed by the helper xml parser. +# Parameters: 3 (required) + +# helper - The helper; $helper->{'VARS'}->{'PRINT_TYPE'} used +# to check if splitting PDFs by section can be offered. +# title - Title for the current state. +# this_state - State name of the chooser. + sub generate_format_selector { - my ($helper,$title,$nextstate, $thisstate) = @_; + my ($helper,$title,$this_state) = @_; my $secpdfoption; - my $state = 'PRINT_FORMATTING'; - if ($thisstate) { - $state = $thisstate; - } unless (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon') || ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon_page') || ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon') ) { $secpdfoption = 'Each PDF contains exactly one section'; } return < - $nextstate +
How should the results be printed?
Start each student\'s assignment on a new page/column (add a pagefeed after each assignment) @@ -432,6 +484,307 @@ RESOURCE_SELECTOR #----------------------------------------------------------------------- +# Computes an open and close date from a list of open/close dates for a resource's +# parts. +# +# @param \@opens - reference to an array of open dates. +# @param \@closes - reference to an array of close dates. +# +# @return ($open, $close) +# +# @note If open/close dates are not defined they will be returned as undef +# @note It is possible for there to be no overlap in which case -1,-1 +# will be returned. +# @note The algorithm used is to take the latest open date and the earliest end date. +# +sub compute_open_window { + my ($opensref, $closesref) = @_; + + my @opens = @$opensref; + my @closes = @$closesref; + + # latest open date: + my $latest_open; + + foreach my $open (@opens) { + if (!defined($latest_open) || ($open > $latest_open)) { + $latest_open = $open; + } + } + # Earliest close: + + my $earliest_close; + foreach my $close (@closes) { + if (!defined($earliest_close) || ($close < $earliest_close)) { + $earliest_close = $close; + } + } + + # If no overlap...both are -1 as promised. + + if (($earliest_close ne '') && ($latest_open ne '') + && ($earliest_close < $latest_open)) { + $latest_open = -1; + $earliest_close = -1; + } + + return ($latest_open, $earliest_close); + +} + +## +# Determines if 'now' is within the set of printable dates. +# +# @param $open_date - Starting date/timestamp. +# @param $close_date - Ending date/timestamp. +# +# @return 0 - Not open. +# @return 1 - open. +# +sub printable { + my ($open_date, $close_date) = @_; + + + my $now = time(); + + # Have to do a bit of fancy footwork around undefined open/close dates: + + if ($open_date && ($open_date > $now)) { + return 0; + } + + if ($close_date && ($close_date < $now)) { + return 0; + } + + return 1; + +} + +## +# Returns the innermost print start/print end dates for a resource. +# This is done by looking at the start/end dates for its parts and choosing +# the intersection of those dates. +# +# @param res - lonnvamaps::resource object that represents the resource. +# +# @return (opendate, closedate) +# +# @note If open/close dates are not defined they will be returned as undef +# @note It is possible for there to be no overlap in which case -1,-1 +# will be returned. +# @note The algorithm used is to take the latest open date and the earliest end date. +# For consistency with &printable() in lonnavmaps.pm determination of start +# date for printing checks printstartdate param first, then, if not set, +# opendate param, then, if not set, contentopen param. + + +sub get_print_dates { + my $res = shift; + my $partsref = $res->parts(); + my @parts; + if (ref($partsref) eq 'ARRAY') { + @parts = @{$partsref}; + } + my $open_date; + my $close_date; + my @open_dates; + my @close_dates; + + + if (@parts) { + foreach my $part (@parts) { + my $partopen = $res->parmval('printstartdate', $part); + my $partclose = $res->parmval('printenddate', $part); + if (!$partopen) { + $partopen = $res->parmval('opendate',$part); + } + if (!$partopen) { + $partopen = $res->parmval('contentopen',$part); + } + if ($partopen) { + push(@open_dates, $partopen); + } + if ($partclose) { + push(@close_dates, $partclose); + } + push(@open_dates, $partopen); + push(@close_dates, $partclose); + } + } + + ($open_date, $close_date) = &compute_open_window(\@open_dates, \@close_dates); + + return ($open_date, $close_date); +} + +## +# Get the dates for which a course says a resource can be printed. This is like +# get_print_dates but namvaps::course_print_dates are gotten...and not converted +# to times either. +# +# @param $res - Reference to a resource has from lonnvampas::resource. +# +# @return (opendate, closedate) +# +sub course_print_dates { + my $res = shift; + my $partsref = $res->parts(); + my @parts = @$partsref; + my $open_date; + my $close_date; + my @open_dates; + my @close_dates; + my $navmap = $res->{NAV_MAP}; # Slightly OO dirty. + + # Don't bother looping over undefined or empty parts arraY; + + if (@parts) { + foreach my $part (@parts) { + my ($partopen, $partclose) = $navmap->course_printdates($res, $part); + push(@open_dates, $partopen); + push(@close_dates, $partclose); + } + ($open_date, $close_date) = &compute_open_window(\@open_dates, \@close_dates); + } + return ($open_date, $close_date); +} +## +# Same as above but for the enclosing map: +# +sub map_print_dates { + my $res = shift; + my $partsref = $res->parts(); + my @parts = @$partsref; + my $open_date; + my $close_date; + my @open_dates; + my @close_dates; + my $navmap = $res->{NAV_MAP}; # slightly OO dirty. + + + # Don't bother looping over undefined or empty parts arraY; + + if (@parts) { + foreach my $part (@parts) { + my ($partopen, $partclose) = $navmap->map_printdates($res, $part); + push(@open_dates, $partopen); + push(@close_dates, $partclose); + } + ($open_date, $close_date) = &compute_open_window(\@open_dates, \@close_dates); + } + return ($open_date, $close_date); +} + +# Determine if a resource is incomplete given the map: +# Parameters: +# $username - Name of user for whom we are checking. +# $domain - Domain of user we are checking. +# $map - map name. +# Returns: +# 0 - map is not incomplete. +# 1 - map is incomplete. +# +sub incomplete { + my ($username, $domain, $map) = @_; + + + my $navmap = Apache::lonnavmaps::navmap->new($username, $domain); + + + if (defined($navmap)) { + my $res = $navmap->getResourceByUrl($map); + my $result = $res->is_incomplete(); + return $result; + } else { + return 1; + } +} +# +# When printing for students, the resources and order of the +# resources may need to be altered if there are folders with +# random selectiopn or random ordering (or both) enabled. +# This sub computes the set of resources to print for a student +# modified both by random ordering and selection and filtered +# to only those that are in the original set selected to be printed. +# +# Parameters: +# $map - The URL of the folder being printed. +# Used to determine which startResource and finishResource +# to use when using the navmap's getIterator method. +# $seq - The original set of resources to print. +# (really an array of resource names (array of symb's). +# $who - Student/domain for whome the sequence will be generated. +# $code - CODE being printed when printing Problems/Resources +# from folder for CODEd assignments +# $nohidemap - If true, parameter in map for hiddenresource will be +# ignored. The user calling the routine should have +# both the pav and vgr privileges if this is set to true). +# +# Implicit inputs: +# $ +# Returns: +# reference to an array of resources that can be passed to +# print_resources. +# +sub master_seq_to_person_seq { + my ($map, $seq, $who, $code, $nohidemap) = @_; + + + my ($username, $userdomain, $usersection) = split(/:/, $who); + + # Toss the sequence up into a hash so that we have O(1) lookup time. + # on the items that come out of the user's list of resources. + # + + my %seq_hash = map {$_ => 1} @$seq; + my @output_seq; + + my $unhidden; + if ($nohidemap) { + $unhidden = &Apache::lonnet::clutter($map); + } + + my $navmap = Apache::lonnavmaps::navmap->new($username, $userdomain, + $code,$unhidden); + my ($start,$finish); + + if ($map) { + my $mapres = $navmap->getResourceByUrl($map); + if ($mapres->is_map()) { + $start = $mapres->map_start(); + $finish = $mapres->map_finish(); + } + } + unless ($start && $finish) { + $start = $navmap->firstResource(); + $finish = $navmap->finishResource(); + } + + my $iterator = $navmap->getIterator($start,$finish,{},1); + + # Iterate on the resource..select the items that are randomly selected + # and that are in the seq_has. Presumably the iterator will take care + # of the random ordering part of the deal. + my $curres; + while ($curres = $iterator->next()) { + # + # Only process resources..that are not removed by randomout... + # and are selected for printint as well. + # + + if (ref($curres) && ! $curres->randomout()) { + my $currsymb = $curres->symb(); + if (exists($seq_hash{$currsymb})) { + push(@output_seq, $currsymb); + } + } + } + + return \@output_seq; # for now. + +} + # Fetch the contents of a resource, uninterpreted. # This is used here to fetch a latex file to be included @@ -534,9 +887,10 @@ sub include_pdf { # (unlikely). If it did exist, add the pdf to the set of files/images that # need tob e converted for this print job: - $file =~ s|(.*)/res/|/home/httpd/html/res/|; + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; + $file =~ s{(.*)/res/}{$londocroot/res/}; - open(FILE,">>/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat"); + open(FILE,">>$Apache::lonnet::perlvar{'lonPrtDir'}/$env{'user.name'}_$env{'user.domain'}_printout.dat"); print FILE ("$file\n"); close (FILE); @@ -559,7 +913,29 @@ sub include_pdf { } - +## +# Collect the various \select_language{language_name} +# latex tags to build a \usepackage[lang-list]{babel} which will +# appear just prior to the \begin{document} at the front of the concatenated +# set of resources: +# @param doc - The string of latex to search/replace. +# @return string +# @retval - the modified document stringt. +# +sub collect_languages { + my $doc = shift; + my %languages; + while ($doc =~ /\\selectlanguage{(\w+)}/mg) { + $languages{$1} = 1; # allows us to request each language exactly once. + } + my @lang_list = (keys(%languages)); # List of unique languages + if (scalar @lang_list) { + my $babel_header = '\usepackage[' . join(',', @lang_list) .']{babel}'. "\n"; + $doc =~ s/\\begin{document}/$babel_header\\begin{document}/; + } + return $doc; +} +#------------------------------------------------------------------- # # ssi_with_retries- Does the server side include of a resource. @@ -606,7 +982,6 @@ sub ssi_with_retries { $ssi_last_error_resource = $resource; $ssi_last_error = $response->code . " " . $response->message; $content='\section*{!!! An error occurred !!!}'; - &Apache::lonnet::logthis("Error in SSI resource: $resource Error: $ssi_last_error"); } return $content; @@ -622,7 +997,6 @@ sub get_student_view_with_retries { $ssi_last_error_resource = $curresline.' for user '.$username.':'.$userdomain; $ssi_last_error = $response->code . " " . $response->message; $content='\section*{!!! An error occurred !!!}'; - &Apache::lonnet::logthis("Error in SSI (student view) resource: $curresline Error: $ssi_last_error User: $username:$userdomain"); } return $content; @@ -685,12 +1059,12 @@ sub printf_style_subst { # %s - The section if it is supplied. # sub format_page_header { - my ($width, $format, $assignment, $course, $student, $section) = @_; + my ($width, $format, $assignment, $course, $student) = @_; $width = &recalcto_mm($width); # Get width in mm. - my $chars_per_line = int($width/1.6); # Character/textline. + my $chars_per_line = int($width/2); # Character/textline. # Default format? @@ -706,40 +1080,44 @@ sub format_page_header { # - Allow the assignment to be 2 lines (wrapped). # - + my $firstline = "$student $course"; + if (length($firstline) > $chars_per_line) { + my $lastchar = $chars_per_line - length($student) - 1; + if ($lastchar > 0) { + $course = substr($course, 0, $lastchar); + } else { # Nothing left of course: + $course = ''; + } + } + if (length($assignment) > $chars_per_line) { + $assignment = substr($assignment, 0, $chars_per_line); + } - my $name_length = int($chars_per_line *3 /4); - my $sec_length = int($chars_per_line / 5); + $format = "\\textbf{$student} $course \\hfill \\thepage \\\\ \\textit{$assignment}"; - $format = "%$name_length".'n'; + } else { + # An open question is how to handle long user formatted page headers... + # A possible future is to support e.g. %na so that the user can control + # the truncation of the elements that can appear in the header. + # + $format = &printf_style_subst("a", $format, $assignment); + $format = &printf_style_subst("c", $format, $course); + $format = &printf_style_subst("n", $format, $student); + + # If the user put %'s in the format string, they must be escaped + # to \% else LaTeX will think they are comments and terminate + # the line.. which is bad!!! - if ($section) { - $format .= ' - Sec: '."%$sec_length".'s'; - } + } - $format .= '\\\\%c \\\\ %a'; - + return $format; - } - # An open question is how to handle long user formatted page headers... - # A possible future is to support e.g. %na so that the user can control - # the truncation of the elements that can appear in the header. - # - $format = &printf_style_subst("a", $format, $assignment); - $format = &printf_style_subst("c", $format, $course); - $format = &printf_style_subst("n", $format, $student); - $format = &printf_style_subst("s", $format, $section); - - - # If the user put %'s in the format string, they must be escaped - # to \% else LaTeX will think they are comments and terminate - # the line.. which is bad!!! # If the user has role author, $course and $assignment are empty so # there is '\\ \\ ' in the page header. That's cause a error in LaTeX if($format =~ /\\\\\s\\\\\s/) { #TODO find sensible caption for page header - my $testPrintout = '\\\\'.&mt('Construction Space').' \\\\'.&mt('Test-Printout '); + my $testPrintout = '\\\\'.&mt('Authoring Space').' \\\\'.&mt('Test-Printout '); $format =~ s/\\\\\s\\\\\s/$testPrintout/; } # @@ -861,6 +1239,7 @@ sub is_code_valid { my ($code_type, $code_length) = ('letter', 6); # defaults. my @lines = &Apache::grades::get_scantronformat_file(); foreach my $line (@lines) { + next if (($line =~ /^\#/) || ($line eq '')); my ($name, $type, $length) = (split(/:/, $line))[0,2,4]; if($name eq $code_option) { $code_length = $length; @@ -877,6 +1256,22 @@ sub is_code_valid { } } +# +# Compare two students by section (Used to sort by section). +# +# Implicit inputs, +# $a - The first one +# $b - The second one. +# +# Returns: +# a-section cmp b-section +# +sub compare_sections { + my ($u1, $d1, $s1, $n1, $stat1) = split(/:/, $a); + my ($u2, $d2, $s2, $n2, $stat2) = split(/:/, $b); + + return $s1 cmp $s2; +} # Compare two students by name. The students are in the form # returned by the helper: @@ -1453,8 +1848,6 @@ sub get_course { my $courseidinfo; if (defined($env{'request.course.id'})) { $courseidinfo = &Apache::lonxml::latex_special_symbols(&unescape($env{'course.'.$env{'request.course.id'}.'.description'}),'header'); - my $sec = $env{'request.course.sec'}; - } return $courseidinfo; } @@ -1477,6 +1870,7 @@ sub page_format_transformation { my $name = &get_name(); my $courseidinfo = &get_course(); + if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } my $header_text = $parmhash{'print_header_format'}; $header_text = &format_page_header($textwidth, $header_text, $assignment, $courseidinfo, $name); @@ -1685,6 +2079,7 @@ sub unsupported { my $result.= &print_latex_header($mode); if ($currentURL=~m|^(/adm/wrapper/)?ext/|) { $currentURL=~s|^(/adm/wrapper/)?ext/|http://|; + $currentURL=~s|^http://https://|https://|; my $title=&Apache::lonnet::gettitle($symb); $title = &Apache::lonxml::latex_special_symbols($title); $result.=' \strut \\\\ '.$title.' \strut \\\\ '.$currentURL.' '; @@ -1710,6 +2105,7 @@ sub map_laystyle { sub print_page_in_course { my ($helper, $rparmhash, $currentURL, $resources) = @_; + my %parmhash = %$rparmhash; my @page_resources = @$resources; my $mode = $helper->{'VARS'}->{'LATEX_TYPE'}; @@ -1763,11 +2159,15 @@ sub print_page_in_course { my @page_resources = $navmap->retrieveResources($resource_src); $result .= &print_page_in_course($helper, $rparmhash, $resource_src, \@page_resources); + } elsif ($resource->ext()) { + $result .= &unsupported($currentURL,$mode,$symb); } # these resources go through the XML transformer: - elsif ($resource_src =~ /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) { + elsif ($resource_src =~ /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) { + my $urlp = &Apache::lonnet::clutter($resource_src); + my %form; my %moreenv; @@ -1777,7 +2177,7 @@ sub print_page_in_course { $form{'grade_target'} = 'tex'; $form{'textwidth'} = &get_textwidth($helper, $LaTeXwidth); - $form{'pdfFormFields'} = $pdfFormFields; # + $form{'pdfFormFields'} = 'no'; # $form{'showallfoils'} = $helper->{'VARS'}->{'showallfoils'}; $form{'problem_split'}=$parmhash{'problem_stream_switch'}; @@ -1829,10 +2229,9 @@ sub print_page_in_course { $texversion.='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm '; $texversion.=&path_to_problem($urlp,$LaTeXwidth); } else { - $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm '; - my $URLpath=$urlp; - $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/; - $texversion.=&path_to_problem($URLpath,$LaTeXwidth); + $texversion.='\vskip 0 mm \noindent\textbf{'. + &mt("Printing from Authoring Space: No Title").'}\vskip 0 mm '; + $texversion.=&path_to_problem($urlp,$LaTeXwidth); } $texversion.='\vskip 1 mm '.$answer.'\end{document}'; } @@ -2100,18 +2499,19 @@ sub set_form_extraspace { sub print_construction_sequence { my ($currentURL, $helper, %form, $LaTeXwidth) = @_; - my $result; my $rndseed=time; if ($helper->{'VARS'}->{'curseed'}) { $rndseed=$helper->{'VARS'}->{'curseed'}; } - my $errtext=&LONCAPA::map::mapread($currentURL); + my $errtext=&LONCAPA::map::mapread(&Apache::lonnet::filelocation('',$currentURL)); + # # These make this all support recursing for subsequences. # my @order = @LONCAPA::map::order; my @resources = @LONCAPA::map::resources; + for (my $member=0;$member<=$#order;$member++) { $resources[$order[$member]]=~/^([^:]*):([^:]*):/; my $urlp=$2; @@ -2127,7 +2527,7 @@ sub print_construction_sequence { } if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) && - ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) { + ($urlp=~/$LONCAPA::assess_page_re/)) { # Don't permanently modify %$form... my %answerform = %form; $answerform{'grade_target'}='answer'; @@ -2171,14 +2571,7 @@ sub print_construction_sequence { # IF sequence, recurse: if ($urlp =~ /\.sequence$/) { - my $sequence_url = $urlp; - my $domain = $env{'user.domain'}; # Constr. space only on local - my $user = $env{'user.name'}; - - $sequence_url =~ s/^\/res\/$domain/\/home/; - $sequence_url =~ s/^(\/home\/$user)/$1\/public_html/; -# $sequence_url =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|; - $result .= &print_construction_sequence($sequence_url, + $result .= &print_construction_sequence($urlp, $helper, %form, $LaTeXwidth); } @@ -2222,19 +2615,19 @@ sub print_construction_sequence { #BZ 5209 # 2 map_incomplete_problems_seq Print incomplete problems from the current # folder in student context. -# 101 map_incomplete_problems_people_seq Print incomplete problems from the +# 5 map_incomplete_problems_people_seq Print incomplete problems from the # current folder in privileged context. -# 102 incomplete_problems_selpeople_course Print incomplete problems for +# 5 incomplete_problems_selpeople_course Print incomplete problems for # selected people from the entire course. # # Item 101 has much the same processing as 8, -# Item 102 has much the same processing as 8. # # Differences: Item 101, 102 require per-student filtering of the resource # set so that only the incomplete resources are printed. # For item 100, filtering was done at the helper level. sub output_data { + my ($r,$helper,$rparmhash) = @_; my %parmhash = %$rparmhash; $ssi_error = 0; # This will be set nonzero by failing ssi's. @@ -2320,7 +2713,7 @@ ENDPART my %form; $form{'grade_target'} = 'tex'; $form{'textwidth'} = &get_textwidth($helper, $LaTeXwidth); - $form{'pdfFormFields'} = $pdfFormFields; + $form{'pdfFormFields'} = 'no'; # If form.showallfoils is set, then request all foils be shown: # privilege will be enforced both by not allowing the @@ -2351,11 +2744,11 @@ ENDPART } else { #prints resource from the construction space - $currentURL='/'.$helper->{'VARS'}->{'filename'}; - if ($currentURL=~/([^?]+)/) {$currentURL=$1;} + $currentURL=$helper->{'VARS'}->{'filename'}; $cleanURL=$currentURL; } $selectionmade = 1; + if ($cleanURL!~m|^/adm/| && $cleanURL=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) { my $rndseed=time; @@ -2395,6 +2788,7 @@ ENDPART if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) { + $form{'problem_split'}=$parmhash{'problem_stream_switch'}; $form{'grade_target'}='answer'; $form{'answer_output_mode'}='tex'; @@ -2416,10 +2810,10 @@ ENDPART $texversion.='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm '; $texversion.=&path_to_problem($cleanURL,$LaTeXwidth); } else { - $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm '; - my $URLpath=$cleanURL; - $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/; - $texversion.=&path_to_problem($URLpath,$LaTeXwidth); + $texversion.='\vskip 0 mm \noindent\textbf{'. + &mt("Printing from Authoring Space: No Title").'}\vskip 0 mm '; + + $texversion.=&path_to_problem($cleanURL,$LaTeXwidth); } $texversion.='\vskip 1 mm '.$answer.'\end{document}'; } @@ -2451,10 +2845,6 @@ ENDPART } } elsif ($cleanURL!~m|^/adm/| && $currentURL=~/\.(sequence|page)$/ && $helper->{'VARS'}->{'construction'} eq '1') { - #printing content of sequence from the construction space - - - $currentURL=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|; $result .= &print_construction_sequence($currentURL, $helper, %form, $LaTeXwidth); $result .= '\end{document}'; @@ -2511,7 +2901,6 @@ ENDPART ($print_type eq 'select_sequences') or ($print_type eq 'map_incomplete_problems_seq') ) { - #-- produce an output string if (($print_type eq 'map_problems') or @@ -2547,7 +2936,6 @@ ENDPART &Apache::lonxml::clear_problem_counter(); - my $pbreakresources = keys %page_breaks; for (my $i=0;$i<=$#master_seq;$i++) { &Apache::lonenc::reset_enc(); @@ -2616,7 +3004,7 @@ ENDPART $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; } } else { - if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/) { + if ($urlp=~/$LONCAPA::assess_page_re/) { $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); # $texversion =~ s/\\begin{document}//; # FIXME my $title = &Apache::lonnet::gettitle($master_seq[$i]); @@ -2648,13 +3036,13 @@ ENDPART if (($selectionmade == 4) and ($assignment ne $prevassignment)) { my $name = &get_name(); my $courseidinfo = &get_course(); + if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } $prevassignment=$assignment; my $header_text = $parmhash{'print_header_format'}; $header_text = &format_page_header($textwidth, $header_text, $assignment, $courseidinfo, $name); - if ($numberofcolumns eq '1') { $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{'.$header_text.'}} \vskip 5 mm '; } else { @@ -2724,14 +3112,18 @@ ENDPART } elsif (($print_type eq 'problems_for_students') || ($print_type eq 'problems_for_students_from_page') || ($print_type eq 'all_problems_students') || - ($print_type eq 'resources_for_students')){ + ($print_type eq 'resources_for_students') || + ($print_type eq 'incomplete_problems_selpeople_course') || + ($print_type eq 'map_incomplete_problems_people_seq')){ #-- prints assignments for whole class or for selected students my $type; if (($print_type eq 'problems_for_students') || ($print_type eq 'problems_for_students_from_page') || - ($print_type eq 'all_problems_students') ) { + ($print_type eq 'all_problems_students') || + ($print_type eq 'incomplete_problems_selpeople_course') || + ($print_type eq 'map_incomplete_problems_people_seq')) { $selectionmade=5; $type='problems'; } elsif ($print_type eq 'resources_for_students') { @@ -2751,6 +3143,8 @@ ENDPART if (($helper->{'VARS'}->{'student_sort'} eq 1) && ($helper->{'VARS'}->{'SPLIT_PDFS'} ne "sections")) { @students = sort compare_names @students; + } else { + @students = sort compare_sections @students; } &adjust_number_to_print($helper); @@ -2769,6 +3163,12 @@ ENDPART } my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'}; + my $map; + if ($helper->{VARS}->{'symb'}) { + ($map, my $id, my $resource) = + &Apache::lonnet::decode_symb($helper->{VARS}->{'symb'}); + } + #loop over students my $flag_latex_header_remove = 'NO'; @@ -2783,12 +3183,15 @@ ENDPART ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes')) { $moreenv{'problem_split'}='yes'; } - my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$#students+1,'inline','75'); + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$#students+1); my $student_counter=-1; my $i = 0; my $last_section = (split(/:/,$students[0]))[2]; + my $nohidemap; + if ($perm{'pav'} && $perm{'vgr'}) { + $nohidemap = 1; + } foreach my $person (@students) { - my $duefile="/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due"; if (-e $duefile) { my $temp_file = Apache::File->new('>>'.$duefile); @@ -2804,9 +3207,11 @@ ENDPART } else { $i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'}); } + my $actual_seq = master_seq_to_person_seq($map, \@master_seq, + $person, undef, $nohidemap); my ($output,$fullname, $printed)=&print_resources($r,$helper, $person,$type, - \%moreenv,\@master_seq, + \%moreenv, $actual_seq, $flag_latex_header_remove, $LaTeXwidth); $resources_printed .= ":"; @@ -2829,20 +3234,39 @@ ENDPART my $old_name=$helper->{'VARS'}->{'REUSE_OLD_CODES'}; my $single_code = $helper->{'VARS'}->{'SINGLE_CODE'}; my $selected_code = $helper->{'VARS'}->{'CODE_SELECTED_FROM_LIST'}; - my $code_option=$helper->{'VARS'}->{'CODE_OPTION'}; my @lines = &Apache::grades::get_scantronformat_file(); - my ($code_type,$code_length)=('letter',6); + my ($code_type,$code_length,$bubbles_per_row)=('letter',6,10); foreach my $line (@lines) { - my ($name,$type,$length) = (split(/:/,$line))[0,2,4]; + chomp($line); + my ($name,$type,$length,$bubbles_per_item) = + (split(/:/,$line))[0,2,4,17]; if ($name eq $code_option) { $code_length=$length; if ($type eq 'number') { $code_type = 'number'; } + chomp($bubbles_per_item); + if (($bubbles_per_item ne '') && ($bubbles_per_item > 0)) { + $bubbles_per_row = $bubbles_per_item; + } } } + my ($randomorder,$randompick,$map); + if ($helper->{VARS}{'symb'}) { + ($map, my $id, my $resource) = + &Apache::lonnet::decode_symb($helper->{VARS}{'symb'}); + my $navmap = Apache::lonnavmaps::navmap->new(); + if (defined($navmap)) { + if ($map) { + my $mapres = $navmap->getResourceByUrl($map); + $randomorder = $mapres->randomorder(); + $randompick = $mapres->randompick(); + } + } + } my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth)); $moreenv{'problem_split'} = $parmhash{'problem_stream_switch'}; $moreenv{'instructor_comments'}='hide'; + $moreenv{'bubbles_per_row'} = $bubbles_per_row; my $seed=time+($$<<16)+($$); my @allcodes; if ($old_name) { @@ -2872,6 +3296,8 @@ ENDPART $moreenv{'CODE'}=&get_CODE(\%allcodes,$i,$seed,$code_length, $code_type); } + $code_name =~ s/^\s+//; + $code_name =~ s/\s+$//; if ($code_name) { &Apache::lonnet::put('CODEs', { @@ -2891,8 +3317,12 @@ ENDPART $number_per_page=$num_todo > 0 ? $num_todo : 1; } my $flag_latex_header_remove = 'NO'; - my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$num_todo,'inline','75'); + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$num_todo); my $count=0; + my $nohidemap; + if ($perm{'pav'} && $perm{'vgr'}) { + $nohidemap = 1; + } foreach my $code (sort(@allcodes)) { my $file_num=int($count/$number_per_page); if ($code_type eq 'number') { @@ -2900,9 +3330,17 @@ ENDPART } else { $moreenv{'CODE'}=&num_to_letters($code); } + my $actual_seq = \@master_seq; + if ($randomorder || $randompick) { + $env{'form.CODE'} = $moreenv{'CODE'}; + $actual_seq = master_seq_to_person_seq($map, \@master_seq, + undef, + $moreenv{'CODE'}, $nohidemap); + delete($env{'form.CODE'}); + } my ($output,$fullname, $printed)= &print_resources($r,$helper,'anonymous',$type,\%moreenv, - \@master_seq,$flag_latex_header_remove, + $actual_seq,$flag_latex_header_remove, $LaTeXwidth); $resources_printed .= ":"; $print_array[$file_num].=$output; @@ -2933,11 +3371,7 @@ ENDPART if ($urlp=~/\//) { $form{'problem_split'}=$parmhash{'problem_stream_switch'}; $form{'rndseed'}=$rndseed; - if ($urlp =~ m|/home/([^/]+)/public_html|) { - $urlp =~ s|/home/([^/]*)/public_html|/~$1|; - } else { - $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||; - } + $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||; $resources_printed .= $urlp.':'; my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form); if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || @@ -2958,19 +3392,16 @@ ENDPART $texversion.='\vskip 0 mm \noindent '; $texversion.=&path_to_problem ($urlp,$LaTeXwidth); } else { - $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm '; - my $URLpath=$urlp; - $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/; - $texversion.=&path_to_problem ($URLpath,$LaTeXwidth); + $texversion.='\vskip 0 mm \noindent\textbf{'. + &mt("Printing from Authoring Space: No Title").'}\vskip 0 mm '; + $texversion.=&path_to_problem ($urlp,$LaTeXwidth); } $texversion.='\vskip 1 mm '.$answer.'\end{document}'; } } #this chunk is responsible for printing the path to problem - my $newurlp=$urlp; - if ($newurlp=~/~/) {$newurlp=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;} - $newurlp=&path_to_problem($newurlp,$LaTeXwidth); + my $newurlp=&path_to_problem($urlp,$LaTeXwidth); $texversion =~ s/(\\begin{minipage}{\\textwidth})/$1 $newurlp/; if ($flag_latex_header_remove ne 'NO') { $texversion = &latex_header_footer_remove($texversion); @@ -3019,12 +3450,7 @@ ENDPART my $URLback=''; #link to original document if ($helper->{'VARS'}->{'construction'} eq '1') { - #prints resource from the construction space - $URLback='/'.$helper->{'VARS'}->{'filename'}; - if ($URLback=~/([^?]+)/) { - $URLback=$1; - $URLback=~s|^/~|/priv/|; - } + $URLback=$helper->{'VARS'}->{'filename'}; } # # Final adjustment of the font size: @@ -3032,6 +3458,11 @@ ENDPART $result = set_font_size($result); + # Insert any babel headers required. + + $result = &collect_languages($result); + + #-- writing .tex file in prtspool my $temp_file; my $identifier = &Apache::loncommon::get_cgi_id(); @@ -3159,8 +3590,20 @@ sub print_resources { my ($username,$userdomain,$usersection) = split /:/,$person; my $fullname = &get_name($username,$userdomain); my $namepostfix = "\\\\"; # Both anon and not anon should get the same vspace. - if ($person =~ 'anon') { - $namepostfix .="Name: "; + + + # + # Figure out if we need to filter the output by + # the incomplete problems for that person + # + my $print_type = $helper->{'VARS'}->{'PRINT_TYPE'}; + my $print_incomplete = 0; + if (($print_type eq 'map_incomplete_problems_people_seq') || + ($print_type eq 'incomplete_problems_selpeople_course')) { + $print_incomplete = 1; + } + if ($person eq 'anonymous') { + $namepostfix .=&mt('Name:')." "; $fullname = "CODE - ".$moreenv->{'CODE'}; } @@ -3168,6 +3611,7 @@ sub print_resources { # my $i = 0; + my $actually_printed = 0; # Count of resources printed. #goes through all resources, checks if they are available for #current student, and produces output @@ -3184,7 +3628,15 @@ sub print_resources { # so we will just rely on prntout.pl to strip ENDOFSTUDENTSTAMP from the # postscript. Each ENDOFSTUDENTSTAMP will go on a line by itself. # + my $syllabus_first = 0; + my $current_assignment = ""; + my $assignment; + my $courseidinfo = &get_course(); + my $possprint = scalar(@{$master_seq}); + if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } + if ($usersection ne '') {$courseidinfo.=' - Sec. '.$usersection} + foreach my $curresline (@{$master_seq}) { if (defined $page_breaks{$curresline}) { if($i != 0) { @@ -3193,9 +3645,17 @@ sub print_resources { } $current_output .= &get_extra_vspaces($helper, $curresline); $i++; + my ($map,$id,$res_url) = &Apache::lonnet::decode_symb($curresline); + + # See if we need to emit a new header: + if ( !($type eq 'problems' && - ($curresline!~ m/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) ) { - my ($map,$id,$res_url) = &Apache::lonnet::decode_symb($curresline); + ($curresline!~ m/$LONCAPA::assess_page_re/)) ) { + if ($print_incomplete && !&incomplete($username, $userdomain, $res_url)) { + next; + } + $actually_printed++; # we're going to print one. + if (&Apache::lonnet::allowed('bre',$res_url)) { if ($res_url!~m|^ext/| && $res_url=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { @@ -3209,6 +3669,7 @@ sub print_resources { $rendered = &print_latex_header().$rendered; } } +; if ($remove_latex_header eq 'YES') { $rendered = &latex_header_footer_remove($rendered); } else { @@ -3220,6 +3681,8 @@ sub print_resources { # Use a copy of the hash so we don't pervert it on future loop passes. my %answerenv = %{$moreenv}; $answerenv{'answer_output_mode'}='tex'; + + $answerenv{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; &Apache::lonxml::restore_problem_counter(); @@ -3292,30 +3755,73 @@ sub print_resources { } $remove_latex_header = 'YES'; } + $assignment = &Apache::lonxml::latex_special_symbols( + &Apache::lonnet::gettitle($map), 'header'); + if (($assignment ne $current_assignment) && ($assignment ne "")) { + my $header_line = &format_page_header($LaTeXwidth, $parmhash{'print_header_format'}, + $assignment, $courseidinfo, + $fullname); + my $header_start = ($columns_in_format == 1) ? '\lhead' + : '\fancyhead[LO]'; + $header_line = $header_start.'{'.$header_line.'}'; + $current_output = $current_output . $header_line; + $current_assignment = $assignment; + } + if (&Apache::loncommon::connection_aborted($r)) { last; } } + # If we are printing incomplete it's possible we don't have + # anything to print. The print subsystem is not so good at handling + # that so we're going to generate a stub that says there are no + # incomplete resources for the person. + # + + if ($actually_printed == 0) { + my $message = &mt('No resources to print'); + if (!$possprint) { + if ($perm{'pav'} || $perm{'pfo'}) { + $message = &mt('There are no unhidden resources to print.')."\n\n". + &mt('The most likely reason is one of the following: ')."\n". + '\begin{itemize}'."\n". + '\item '.&mt("The 'Resource hidden from students' parameter is set for the folder being printed.")."\n". + '\item '.&mt("'Hidden' is checked in the Course Editor individually for each resource in the folder being printed.")."\n". + '\end{itemize}'."\n\n". + &mt("Note: to print a bubblesheet exam which you want to hide from students, ". + "use the Course Editor to check the 'Hidden' checkbox for the exam folder itself.")."\n"; + } + } elsif ($print_incomplete) { + $message = &mt('No incomplete resources'); + } + if ($message) { + $current_output = &encapsulate_minipage("\\vskip -10mm \n$message\n \\vskip 100 mm { }\n"); + } + if ($remove_latex_header eq "NO") { + $current_output = &print_latex_header() . $current_output; + } else { + $current_output = &latex_header_footer_remove($current_output); + } + } if ($syllabus_first) { $current_output =~ s/\\\\ Last updated:/Last updated:/ } - my $courseidinfo = &get_course(); my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header'); my $header_line = - &format_page_header($LaTeXwidth, $parmhash{'print_header_format'}, - $currentassignment, $courseidinfo, $fullname, $usersection); - my $header_start = ($columns_in_format == 1) ? '\lhead' - : '\fancyhead[LO]'; - $header_line = $header_start.'{'.$header_line.'}'; + &format_page_header($LaTeXwidth, $parmhash{'print_header_format'}, + $currentassignment, $courseidinfo, $fullname); + my $header_start = ($columns_in_format == 1) ? '\lhead' : '\fancyhead[LO]'; + my $newheader = $header_start.'{'.$header_line.'}'; + if ($current_output=~/\\documentclass/) { - $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$header_line$namepostfix}\\vskip 5 mm /; + $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$newheader$namepostfix}\\vskip 5 mm /; } else { my $blankpages = '\clearpage\strut\clearpage'x$helper->{'VARS'}->{'EMPTY_PAGES'}; - + $current_output = '\strut\vspace*{-6 mm}\\newline'. ©right_line().' \newpage '.$blankpages.$end_of_student. '\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent'. - $header_line.$namepostfix.'} \vskip 5 mm '.$current_output; + $newheader.$namepostfix. '} \vskip 5 mm '.$current_output; } # # Close the student bracketing. @@ -3324,14 +3830,46 @@ sub print_resources { } +sub printing_blocked { + my ($r,$blocktext) = @_; + my $title = &mt('Preparing Printout'); + &Apache::lonhtmlcommon::clear_breadcrumbs(); + &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/printout', + text=> $title}); + my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs($title); + &Apache::loncommon::content_type($r,'text/html'); + &Apache::loncommon::no_cache($r); + $r->send_http_header; + $r->print(&Apache::loncommon::start_page('Preparing Printout'). + $breadcrumbs. + $blocktext. + &Apache::loncommon::end_page()); + return; +} + sub handler { my $r = shift; + + if ($env{'request.course.id'}) { + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($blocked,$blocktext) = + &Apache::loncommon::blocking_status('printout',$cnum,$cdom); + if ($blocked) { + my $checkrole = "cm./$cdom/$cnum"; + if ($env{'request.course.sec'} ne '') { + $checkrole .= "/$env{'request.course.sec'}"; + } + unless ((&Apache::lonnet::allowed('evb',undef,undef,$checkrole)) && + ($env{'request.role'} !~ m{^st\./$cdom/$cnum})) { + &printing_blocked($r,$blocktext); + return OK; + } + } + } &init_perm(); - - - my $helper = printHelper($r); if (!ref($helper)) { return $helper; @@ -3355,7 +3893,7 @@ sub handler { &output_data($r,$helper,\%parmhash); return OK; -} +} use Apache::lonhelper; @@ -3400,12 +3938,7 @@ sub get_randomly_ordered_warning { my $func = sub { return ($_[0]->is_map() && $_[0]->randomorder); }; my @matches = $navmap->retrieveResources($res, $func,1,1,1); - if (@matches) { - $message = "Some of the items below are in folders set to be randomly ordered. However, when printing the contents of these folders, they will be printed in the original order for all students, not the randomized order."; - } - } - if ($message) { - return ''.$message.''; + } } else { $message = "Retrieval of information about ordering of resources failed."; @@ -3495,8 +4028,8 @@ sub printHelper { } # Detect whether we're coming from construction space - if ($env{'form.postdata'}=~/^(?:http:\/\/[^\/]+\/|\/|)\~([^\/]+)\/(.*)$/) { - $helper->{VARS}->{'filename'} = "~$1/$2"; + if ($env{'form.postdata'}=~m{^/priv}) { + $helper->{VARS}->{'filename'} = $env{'form.postdata'}; $helper->{VARS}->{'construction'} = 1; } else { if ($env{'form.postdata'}) { @@ -3534,6 +4067,12 @@ sub printHelper { my $is_published=0; # True when printing from resource space. my $res_printable = 1; # By default the current resource is printable. my $userCanPrint = ($perm{'pav'} || $perm{'pfo'}); + my $res_printstartdate; + my $res_printenddate; + my $map_open = 0; + my $map_close = 0xffffffff; + my $course_open = 0; + my $course_close = 0xffffffff; # Get the resource name from construction space if ($helper->{VARS}->{'construction'}) { @@ -3551,6 +4090,10 @@ sub printHelper { my $navmap = Apache::lonnavmaps::navmap->new(); my $res = $navmap->getBySymb($symb); $res_printable = $res->resprintable() || $userCanPrint; #printability in course context + ($res_printstartdate, $res_printenddate) = &get_print_dates($res); + ($course_open, $course_close) = &course_print_dates($res); + ($map_open, $map_close) = &map_print_dates($res); + } else { # Resource space. @@ -3569,6 +4112,7 @@ sub printHelper { if (!$helper->{VARS}->{'curseed'} && $env{'form.curseed'}) { $helper->{VARS}->{'curseed'}=$env{'form.curseed'}; } + if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) { $helper->{VARS}->{'probstatus'}=$env{'form.problemstatus'}; } @@ -3599,8 +4143,7 @@ sub printHelper { if ($resourceTitle && $res_printable) { push @{$printChoices}, ["$resourceTitle (".&mt('the resource you just saw on the screen').")", 'current_document', 'PAGESIZE']; - } - + } # Useful filter strings @@ -3626,13 +4169,13 @@ sub printHelper { my $start_new_option; if ($perm{'pav'}) { $start_new_option = - "
RESOURCE_SELECTOR - my $nextstate = 'NUMBER_PER_PDF'; $resource_selector .= &generate_format_selector($helper, 'Format of the print job', - $nextstate); + 'PRINT_FORMATTING'); &Apache::lonxml::xmlparse($r, 'helper', < @@ -4042,7 +4587,7 @@ CHOOSE_STUDENTS1 - Bubble sheet type: + Bubblesheet type: $codechoice @@ -4126,7 +4671,7 @@ CHOOSE_FROM_SUBDIR Select the sequence to print resources from: CHOOSE_FROM_ANY_SEQUENCE - return \$res->is_sequence; + return &Apache::lonprintout::printable_sequence(\$res); return $urlValue; return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0); @@ -4148,6 +4693,36 @@ CHOOSE_FROM_ANY_SEQUENCE # Generate the first state, to select which resources get printed. Apache::lonhelper::state->new("START", "Select Printing Options:"); + if (!$res_printable) { + my $now = time; + my $shownprintstart = &Apache::lonlocal::locallocaltime($res_printstartdate); + my $shownprintend = &Apache::lonlocal::locallocaltime($res_printenddate); + my $noprintmsg; + if (($res_printenddate) && ($res_printenddate < $now)) { + $noprintmsg = &mt('Printing for current resource no longer available (ended: [_1])', + $shownprintend); + } else { + if (($res_printstartdate) && ($res_printstartdate > $now)) { + if (($res_printenddate) && ($res_printenddate > $now) && ($res_printenddate > $res_printstartdate)) { + $noprintmsg = &mt('Printing for current resource is only possible between [_1] and [_2]', + $shownprintstart,$shownprintend); + } elsif (!$res_printenddate) { + $noprintmsg = &mt('Printing for current resource will only be possible starting [_1]', + $shownprintstart); + } else { + $noprintmsg = &mt('Printing for current resource is unavailable'); + } + } + } + + if ($noprintmsg) { + $paramHash = Apache::lonhelper::getParamHash(); + $paramHash->{MESSAGE_TEXT} = + '

'.$noprintmsg.'

'; + Apache::lonhelper::message->new(); + } + } + $paramHash = Apache::lonhelper::getParamHash(); $paramHash = Apache::lonhelper::getParamHash(); $paramHash->{MESSAGE_TEXT} = ""; Apache::lonhelper::message->new(); @@ -4487,9 +5062,6 @@ sub render { my $PaperType=&mt('Paper type'); my $landscape=&mt('Landscape'); my $portrait=&mt('Portrait'); - my $pdfFormLabel=&mt('PDF-Formfields'); - my $with=&mt('with Formfields'); - my $without=&mt('without Formfields'); $result.='

'.&mt('Layout Options').'

' @@ -4498,7 +5070,6 @@ sub render { .''.$PageLayout.'' .''.$NumberOfColumns.'' .''.$PaperType.'' - .''.$pdfFormLabel.'' .&Apache::loncommon::end_data_table_header_row() .&Apache::loncommon::start_data_table_row() .'' @@ -4539,12 +5110,6 @@ sub render { $result .= < - - - HTML $result.=&Apache::loncommon::end_data_table_row() .&Apache::loncommon::end_data_table(); @@ -4790,7 +5355,5 @@ sub postprocess { } } - - __END__