--- loncom/interface/lonprintout.pm 2011/11/07 16:00:17 1.606
+++ loncom/interface/lonprintout.pm 2014/04/24 15:31:39 1.642
@@ -1,8 +1,7 @@
-
# The LearningOnline Network
# Printout
#
-# $Id: lonprintout.pm,v 1.606 2011/11/07 16:00:17 www Exp $
+# $Id: lonprintout.pm,v 1.642 2014/04/24 15:31:39 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) = @_;
@@ -302,7 +352,6 @@ CHOOSE_RESOURCES
CHOOSE_RESOURCES
-
return $result;
}
#
@@ -435,6 +484,197 @@ 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.
@@ -468,11 +708,14 @@ sub incomplete {
# to only those that are in the original set selcted to be printed.
#
# Parameters:
-# $helper - The helper we need $helper->{'VARS'}->{'symb'}
-# to construct the navmap and the iteration.
-# $seq - The original set of resources to print
+# $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
#
# Implicit inputs:
# $
@@ -481,33 +724,40 @@ sub incomplete {
# print_resources.
#
sub master_seq_to_person_seq {
- my ($helper, $seq, $who) = @_;
+ 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 ($perm{'pav'} && $perm{'vgr'} && $nohidemap) {
+ $unhidden = &Apache::lonnet::clutter($map);
+ }
- my ($map, $id, $url) = &Apache::lonnet::decode_symb($helper->{VARS}->{'symb'});
- my $navmap = Apache::lonnavmaps::navmap->new($username, $userdomain);
- my $iterator = $navmap->getIterator($navmap->firstResource(),
- $navmap->finishResource(),
- {}, 1);
- my %nonResourceItems = (
- $iterator->BEGIN_MAP => 1,
- $iterator->BEGIN_BRANCH => 1,
- $iterator->END_BRANCH => 1,
- $iterator->END_MAP => 1,
- $iterator->FORWARD => 1,
- $iterator->BACKWARD => 1
+ 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();
+ }
- ); # These items are not resources but appear in the midst of iteration.
+ 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
@@ -519,14 +769,13 @@ sub master_seq_to_person_seq {
# Only process resources..that are not removed by randomout...
# and are selected for printint as well.
#
- if (! exists $nonResourceItems{$curres} && ! $curres->randomout()) {
- my $symb = $curres->symb();
- if (exists $seq_hash{$symb}) {
- push(@output_seq, $symb);
+ if (ref($curres) && ! $curres->randomout()) {
+ my $currsymb = $curres->symb();
+ if (exists($seq_hash{$currsymb})) {
+ push(@output_seq, $currsymb);
}
}
}
-
return \@output_seq; # for now.
@@ -634,9 +883,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);
@@ -659,7 +909,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.
@@ -837,7 +1109,7 @@ sub format_page_header {
# 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/;
}
#
@@ -975,6 +1247,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:
@@ -1783,6 +2071,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.' ';
@@ -1862,6 +2151,8 @@ 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:
@@ -1931,7 +2222,7 @@ sub print_page_in_course {
$texversion.=&path_to_problem($urlp,$LaTeXwidth);
} else {
$texversion.='\vskip 0 mm \noindent\textbf{'.
- &mt("Printing from Construction Space: No Title").'}\vskip 0 mm ';
+ &mt("Printing from Authoring Space: No Title").'}\vskip 0 mm ';
$texversion.=&path_to_problem($urlp,$LaTeXwidth);
}
$texversion.='\vskip 1 mm '.$answer.'\end{document}';
@@ -2051,7 +2342,7 @@ sub recently_generated {
# A reference to a page break hash.
#
#
-use Data::Dumper;
+# use Data::Dumper;
# sub dump_helper_vars {
# my ($helper) = @_;
# my $helpervars = Dumper($helper->{'VARS'});
@@ -2228,7 +2519,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';
@@ -2328,6 +2619,7 @@ sub print_construction_sequence {
# 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.
@@ -2511,7 +2803,7 @@ ENDPART
$texversion.=&path_to_problem($cleanURL,$LaTeXwidth);
} else {
$texversion.='\vskip 0 mm \noindent\textbf{'.
- &mt("Printing from Construction Space: No Title").'}\vskip 0 mm ';
+ &mt("Printing from Authoring Space: No Title").'}\vskip 0 mm ';
$texversion.=&path_to_problem($cleanURL,$LaTeXwidth);
}
@@ -2601,7 +2893,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
@@ -2706,7 +2997,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]);
@@ -2744,7 +3035,6 @@ ENDPART
$assignment,
$courseidinfo,
$name);
-
if ($numberofcolumns eq '1') {
$result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{'.$header_text.'}} \vskip 5 mm ';
} else {
@@ -2845,6 +3135,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);
@@ -2863,6 +3155,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';
@@ -2877,7 +3175,7 @@ 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];
@@ -2897,7 +3195,8 @@ ENDPART
} else {
$i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'});
}
- my $actual_seq = master_seq_to_person_seq($helper, \@master_seq, $person);
+ my $actual_seq = master_seq_to_person_seq($map, \@master_seq,
+ $person, undef, 1);
my ($output,$fullname, $printed)=&print_resources($r,$helper,
$person,$type,
\%moreenv, $actual_seq,
@@ -2923,7 +3222,6 @@ 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,$bubbles_per_row)=('letter',6,10);
@@ -2940,6 +3238,19 @@ ENDPART
}
}
}
+ 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';
@@ -2992,7 +3303,7 @@ 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;
foreach my $code (sort(@allcodes)) {
my $file_num=int($count/$number_per_page);
@@ -3001,9 +3312,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'}, 1);
+ 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;
@@ -3056,7 +3375,7 @@ ENDPART
$texversion.=&path_to_problem ($urlp,$LaTeXwidth);
} else {
$texversion.='\vskip 0 mm \noindent\textbf{'.
- &mt("Printing from Construction Space: No Title").'}\vskip 0 mm ';
+ &mt("Printing from Authoring Space: No Title").'}\vskip 0 mm ';
$texversion.=&path_to_problem ($urlp,$LaTeXwidth);
}
$texversion.='\vskip 1 mm '.$answer.'\end{document}';
@@ -3113,12 +3432,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:
@@ -3126,6 +3440,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();
@@ -3254,6 +3573,7 @@ sub print_resources {
my $fullname = &get_name($username,$userdomain);
my $namepostfix = "\\\\"; # Both anon and not anon should get the same vspace.
+
#
# Figure out if we need to filter the output by
# the incomplete problems for that person
@@ -3265,7 +3585,7 @@ sub print_resources {
$print_incomplete = 1;
}
if ($person eq 'anonymous') {
- $namepostfix .="Name: ";
+ $namepostfix .=&mt('Name:')." ";
$fullname = "CODE - ".$moreenv->{'CODE'};
}
@@ -3292,6 +3612,10 @@ sub print_resources {
#
my $syllabus_first = 0;
+ my $current_assignment = "";
+ my $assignment;
+ my $courseidinfo = &get_course();
+
foreach my $curresline (@{$master_seq}) {
if (defined $page_breaks{$curresline}) {
if($i != 0) {
@@ -3300,13 +3624,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)$/) {
@@ -3406,6 +3734,19 @@ 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, $usersection);
+ 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
@@ -3426,24 +3767,24 @@ sub print_resources {
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, $usersection);
+ 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.
@@ -3452,12 +3793,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;
@@ -3481,7 +3856,7 @@ sub handler {
&output_data($r,$helper,\%parmhash);
return OK;
-}
+}
use Apache::lonhelper;
@@ -3526,12 +3901,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.";
@@ -3660,6 +4030,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'}) {
@@ -3677,6 +4053,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.
@@ -3695,6 +4075,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'};
}
@@ -3725,8 +4106,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
@@ -3752,13 +4132,13 @@ sub printHelper {
my $start_new_option;
if ($perm{'pav'}) {
$start_new_option =
- "before selected').
+ "').
"' variable='FINISHPAGE' />".
- "before selected').
+ "').
"' variable='EXTRASPACE' type='text' />" .
"".
- "check for mm').
+ "').
"' variable='EXTRASPACE_UNITS' type='checkbox' />"
;
@@ -3831,7 +4211,7 @@ sub printHelper {
my $nextState = 'CHOOSE_INCOMPLETE_SEQ';
my $textSuffix = '';
- if ($userCanPrint) {
+ if ($userCanPrint) {
$printSelector = 'map_incomplete_problems_people_seq';
$nextState = 'CHOOSE_INCOMPLETE_PEOPLE_SEQ';
$textSuffix = ' for selected students';
@@ -3839,51 +4219,59 @@ sub printHelper {
&create_incomplete_folder_selstud_helper($helper, $map);
&Apache::lonxml::xmlparse($r, 'helper', $helperStates);
} else {
- my $helperStates = &create_incomplete_folder_helper($helper, $map); # Create needed states for student.
- &Apache::lonxml::xmlparse($r, 'helper', $helperStates);
+ if (&printable($map_open, $map_close)) {
+ my $helperStates = &create_incomplete_folder_helper($helper, $map); # Create needed states for student.
+ &Apache::lonxml::xmlparse($r, 'helper', $helperStates);
+ } else {
+ # TODO: Figure out how to break the news...this folder is not printable.
+ }
}
- push(@{$printChoices},
- [&mt('Selected [_1]Incomplete Problems[_2] from folder [_3]' . $textSuffix,
- '', '',
- ''. $sequenceTitle . ''),
- $printSelector,
- $nextState]);
-
+ if ($userCanPrint || &printable($map_open, $map_close)) {
+ push(@{$printChoices},
+ [&mt('Selected [_1]Incomplete Problems[_2] from folder [_3]' . $textSuffix,
+ '', '',
+ ''. $sequenceTitle . ''),
+ $printSelector,
+ $nextState]);
+ }
# Allow problems from sequence
- push @{$printChoices},
+ if ($userCanPrint || &printable($map_open, $map_close)) {
+ push @{$printChoices},
[&mt('Selected [_1]Problems[_2] from folder [_3]','','',''.$sequenceTitle.''),
'map_problems',
'CHOOSE_PROBLEMS'];
- # Allow all resources from sequence
- push @{$printChoices}, [&mt('Selected [_1]Resources[_2] from folder [_3]','','',''.$sequenceTitle.''),
- 'map_problems_pages',
- 'CHOOSE_PROBLEMS_HTML'];
- my $helperFragment = &generate_resource_chooser('CHOOSE_PROBLEMS',
- 'Select Problem(s) to print',
- 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
- 'RESOURCES',
- 'PAGESIZE',
- $map,
- $isProblem, '',
- $symbFilter,
- $start_new_option);
- $helperFragment .= &generate_resource_chooser('CHOOSE_PROBLEMS_HTML',
- 'Select Resource(s) to print',
- 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
- 'RESOURCES',
- 'PAGESIZE',
- $map,
- $isNotMap, '',
- $symbFilter,
- $start_new_option);
-
- &Apache::lonxml::xmlparse($r, 'helper', $helperFragment);
+ # Allow all resources from sequence
+ push @{$printChoices}, [&mt('Selected [_1]Resources[_2] from folder [_3]','','',''.$sequenceTitle.''),
+ 'map_problems_pages',
+ 'CHOOSE_PROBLEMS_HTML'];
+ my $helperFragment = &generate_resource_chooser('CHOOSE_PROBLEMS',
+ 'Select Problem(s) to print',
+ 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
+ 'RESOURCES',
+ 'PAGESIZE',
+ $map,
+ $isProblem, '',
+ $symbFilter,
+ $start_new_option);
+ $helperFragment .= &generate_resource_chooser('CHOOSE_PROBLEMS_HTML',
+ 'Select Resource(s) to print',
+ 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
+ 'RESOURCES',
+ 'PAGESIZE',
+ $map,
+ $isNotMap, '',
+ $symbFilter,
+ $start_new_option);
+
+ &Apache::lonxml::xmlparse($r, 'helper', $helperFragment);
+ } else {
+ # TODO: Figure out how to tell them the folder is not printable.
+ }
}
-
- # If the user has pfo (print for others) allow them to print all
- # problems and resources in the entire course, optionally for selected students
- my $post_data = $helper->{VARS}->{'postdata'};
+ # If the user has pfo (print for others) allow them to print all
+ # problems and resources in the entire course, optionally for selected students
+ my $post_data = $helper->{VARS}->{'postdata'};
if ($perm{'pfo'} && !$is_published &&
($post_data=~/\/res\// || $post_data =~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) {
@@ -3915,7 +4303,7 @@ my $suffixXml = < 0 &&
@@ -4246,7 +4635,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);
@@ -4268,6 +4657,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();
@@ -4489,7 +4908,7 @@ FONT_SELECTION
return "$helper->{VARS}->{'probstatus'}";
Homework Problem
- Exam Problem
+ Bubblesheet Exam Problem
Survey question
,choice computer="anonsurvey"Anonymous survey question
@@ -4607,9 +5026,9 @@ 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');
+ my $pdfFormLabel=&mt('PDF Form Fields');
+ my $with=&mt('with Form Fields');
+ my $without=&mt('without Form Fields');
$result.=''.&mt('Layout Options').'
'
@@ -4910,7 +5329,5 @@ sub postprocess {
}
}
-
-
__END__