--- loncom/interface/lonnavmaps.pm 2019/02/03 22:25:47 1.509.2.9
+++ loncom/interface/lonnavmaps.pm 2021/03/08 03:48:34 1.509.2.13.2.1
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Navigate Maps Handler
#
-# $Id: lonnavmaps.pm,v 1.509.2.9 2019/02/03 22:25:47 raeburn Exp $
+# $Id: lonnavmaps.pm,v 1.509.2.13.2.1 2021/03/08 03:48:34 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
@@ -486,7 +486,7 @@ use Apache::lonlocal;
use Apache::lonnet;
use Apache::lonmap;
-use POSIX qw (floor strftime);
+use POSIX qw (ceil floor strftime);
use Time::HiRes qw( gettimeofday tv_interval );
use LONCAPA;
use DateTime();
@@ -577,7 +577,11 @@ sub getLinkForResource {
my $anchor;
if ($res->is_page()) {
foreach my $item (@$stack) { if (defined($item)) { $anchor = $item; } }
- $anchor=&escape($anchor->shown_symb());
+ if ($anchor->encrypted() && !&advancedUser()) {
+ $anchor='LC_'.$anchor->id();
+ } else {
+ $anchor=&escape($anchor->shown_symb());
+ }
return ($res->link(),$res->shown_symb(),$anchor);
}
# in case folder was skipped over as "only sequence"
@@ -1016,9 +1020,12 @@ sub render_resource {
# Don't allow users to manipulate folder
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';
$icon = ""."";
-
- $linkopen = "";
- $linkclose = "";
+ if ($params->{'caller'} eq 'sequence') {
+ $linkopen = "";
+ } else {
+ $linkopen = "";
+ $linkclose = "";
+ }
}
if (((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) ||
(&Apache::lonnet::allowed('cev',$env{'request.course.id'}))) &&
@@ -1390,10 +1397,11 @@ sub render {
my $currenturl = $env{'form.postdata'};
#$currenturl=~s/^http\:\/\///;
#$currenturl=~s/^[^\/]+//;
-
- $here = $jump = &Apache::lonnet::symbread($currenturl);
+ unless ($args->{'caller'} eq 'sequence') {
+ $here = $jump = &Apache::lonnet::symbread($currenturl);
+ }
}
- if ($here eq '') {
+ if (($here eq '') && ($args->{'caller'} ne 'sequence')) {
my $last;
if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
&GDBM_READER(),0640)) {
@@ -1722,6 +1730,23 @@ END
undef($args->{'sort'});
}
+ # Determine if page will be served with https in case
+ # it contains a syllabus which uses an external URL
+ # which points at an http site.
+
+ my ($is_ssl,$cdom,$cnum,$hostname);
+ if ($ENV{'SERVER_PORT'} == 443) {
+ $is_ssl = 1;
+ if ($r) {
+ $hostname = $r->hostname();
+ } else {
+ $hostname = $ENV{'SERVER_NAME'};
+ }
+ }
+ if ($env{'request.course.id'}) {
+ $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ }
my $inhibitmenu;
if ($args->{'modalLink'}) {
@@ -1860,11 +1885,35 @@ END
$stack=$it->getStack();
}
($src,$symb,$anchor)=getLinkForResource($stack);
+ my $srcHasQuestion = $src =~ /\?/;
+ if ($env{'request.course.id'}) {
+ if (($is_ssl) && ($src =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) &&
+ ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
+ unless (&Apache::lonnet::uses_sts()) {
+ if ($hostname ne '') {
+ $src = 'http://'.$hostname.$src;
+ }
+ $src .= ($srcHasQuestion? '&' : '?') . 'usehttp=1';
+ $srcHasQuestion = 1;
+ }
+ } elsif (($is_ssl) && ($src =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) {
+ unless (&Apache::lonnet::uses_sts()) {
+ if ($hostname ne '') {
+ $src = 'http://'.$hostname.$src;
+ }
+ $src .= ($srcHasQuestion? '&' : '?') . 'usehttp=1';
+ $srcHasQuestion = 1;
+ }
+ }
+ }
if (defined($anchor)) { $anchor='#'.$anchor; }
- my $srcHasQuestion = $src =~ /\?/;
- $args->{"resourceLink"} = $src.
- ($srcHasQuestion?'&':'?') .
- 'symb=' . &escape($symb).$inhibitmenu.$anchor;
+ if (($args->{'caller'} eq 'sequence') && ($curRes->is_map())) {
+ $args->{"resourceLink"} = $src.($srcHasQuestion?'&':'?') .'navmap=1';
+ } else {
+ $args->{"resourceLink"} = $src.
+ ($srcHasQuestion?'&':'?') .
+ 'symb=' . &escape($symb).$inhibitmenu.$anchor;
+ }
}
# Now, we've decided what parts to show. Loop through them and
# show them.
@@ -1892,7 +1941,7 @@ END
$currentJumpDelta) {
# Jam the anchor after the
tag;
# necessary for valid HTML (which Mozilla requires)
- $colHTML =~ s/\>/\>\/;
+ $colHTML =~ s/\>/\>\\<\/a\>/;
$displayedJumpMarker = 1;
}
$result .= $colHTML . "\n";
@@ -2792,6 +2841,91 @@ sub recurseup_maps {
return @recurseup;
}
+sub recursed_crumbs {
+ my ($self,$mapurl,$restitle) = @_;
+ my (@revmapinfo,@revmapres);
+ my $mapres = $self->getResourceByUrl($mapurl);
+ if (ref($mapres)) {
+ @revmapres = map { $self->getByMapPc($_); } split(/,/,$mapres->map_breadcrumbs());
+ shift(@revmapres);
+ }
+ my $allowedlength = 60;
+ my $minlength = 5;
+ my $allowedtitle = 30;
+ if (($env{'environment.icons'} eq 'iconsonly') && (!$env{'browser.mobile'})) {
+ $allowedlength = 100;
+ $allowedtitle = 70;
+ }
+ if (length($restitle) > $allowedtitle) {
+ $restitle = &truncate_crumb_text($restitle,$allowedtitle);
+ }
+ my $totallength = length($restitle);
+ my @links;
+
+ foreach my $map (@revmapres) {
+ my $pc = $map->map_pc();
+ next if ((!$pc) || ($pc == 1));
+ push(@links,$map);
+ push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,});
+ $totallength += length($map->title());
+ }
+ my $numlinks = scalar(@links);
+ if ($numlinks) {
+ if ($totallength - $allowedlength > 0) {
+ my $available = $allowedlength - length($restitle);
+ my $avg = POSIX::ceil($available/$numlinks);
+ if ($avg < $minlength) {
+ $avg = $minlength;
+ }
+ @revmapinfo = ();
+ foreach my $map (@links) {
+ my $showntitle = &truncate_crumb_text($map->title(),$avg);
+ if ($showntitle ne '') {
+ push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $showntitle,'no_mt' => 1,});
+ }
+ }
+ }
+ }
+ if ($restitle ne '') {
+ push(@revmapinfo,{'text' => $restitle, 'no_mt' => 1});
+ }
+ return @revmapinfo;
+}
+
+sub truncate_crumb_text {
+ my ($title,$limit) = @_;
+ my $showntitle = '';
+ if (length($title) > $limit) {
+ my @words = split(/\b\s*/,$title);
+ if (@words == 1) {
+ $showntitle = substr($title,0,$limit).' ...';
+ } else {
+ my $linklength = 0;
+ my $num = 0;
+ foreach my $word (@words) {
+ $linklength += 1+length($word);
+ if ($word eq '-') {
+ $showntitle =~ s/ $//;
+ $showntitle .= $word;
+ } elsif ($linklength > $limit) {
+ if ($num < @words) {
+ $showntitle .= $word.' ...';
+ last;
+ } else {
+ $showntitle .= $word;
+ }
+ } else {
+ $showntitle .= $word.' ';
+ }
+ }
+ $showntitle =~ s/ $//;
+ }
+ return $showntitle;
+ } else {
+ return $title;
+ }
+}
+
#
# Determines the open/close dates for printing a map that
# encloses a resource.
@@ -3665,7 +3799,8 @@ sub next {
# That ends the main iterator logic. Now, do we want to recurse
# down this map (if this resource is a map)?
if ( ($self->{HERE}->is_sequence() || (!$closeAllPages && $self->{HERE}->is_page())) &&
- (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) {
+ (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION}) &&
+ ($env{'request.role.adv'} || !$self->{HERE}->randomout())) {
$self->{RECURSIVE_ITERATOR_FLAG} = 1;
my $firstResource = $self->{HERE}->map_start();
my $finishResource = $self->{HERE}->map_finish();
@@ -4414,6 +4549,12 @@ Returns a string with a comma-separated
for the hierarchy of maps containing a map, with the top level
map first, then descending to deeper levels, with the enclosing map last.
+=item * B:
+
+Same as map_hierarchy, except maps containing only a single itemm if
+it's a map, or containing no items are omitted, unless it's the top
+level map (map_pc = 1), which is always included.
+
=back
=cut
@@ -4449,6 +4590,11 @@ sub map_hierarchy {
my $pc = $self->map_pc();
return $self->navHash("map_hierarchy_$pc", 0);
}
+sub map_breadcrumbs {
+ my $self = shift;
+ my $pc = $self->map_pc();
+ return $self->navHash("map_breadcrumbs_$pc", 0);
+}
#####
# Property queries
@@ -4673,11 +4819,12 @@ sub duedate {
my $date;
my @interval=$self->parmval("interval", $part);
my $due_date=$self->parmval("duedate", $part);
- if ($interval[0] =~ /\d+/) {
- my $first_access=&Apache::lonnet::get_first_access($interval[1],
- $self->{SYMB});
+ if ($interval[0] =~ /^(\d+)/) {
+ my $timelimit = $1;
+ my $first_access=&Apache::lonnet::get_first_access($interval[1],
+ $self->{SYMB});
if (defined($first_access)) {
- my $interval = $first_access+$interval[0];
+ my $interval = $first_access+$timelimit;
$date = (!$due_date || $interval < $due_date) ? $interval
: $due_date;
} else {
|