--- rat/lonuserstate.pm 2017/09/03 18:19:09 1.152 +++ rat/lonuserstate.pm 2021/04/19 21:12:53 1.162 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Construct and maintain state and binary representation of course for user # -# $Id: lonuserstate.pm,v 1.152 2017/09/03 18:19:09 raeburn Exp $ +# $Id: lonuserstate.pm,v 1.162 2021/04/19 21:12:53 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -62,6 +62,9 @@ my %randomorder; # maps to order content my %randomizationcode; # code used to grade folder for bubblesheet exam my %encurl; # URLs in this folder are supposed to be encrypted my %hiddenurl; # this URL (or complete folder) is supposed to be hidden +my %deeplinkonly; # this URL (or complete folder) is deep-link only +my %rescount; # count of unhidden items in each map +my %mapcount; # count of unhidden maps in each map # ----------------------------------- Remove version from URL and store in hash @@ -240,6 +243,8 @@ sub loadmap { my @map_ids; my $codechecked; + $rescount{$lpc} = 0; + $mapcount{$lpc} = 0; while (my $token = $parser->get_token) { next if ($token->[0] ne 'S'); @@ -249,6 +254,13 @@ sub loadmap { my $resource_id = &parse_resource($token,$lpc,$ispage,$uri,$courseid); if (defined $resource_id) { push(@map_ids, $resource_id); + if ($hash{'src_'.$lpc.'.'.$resource_id}) { + $rescount{$lpc} ++; + if (($hash{'src_'.$lpc.'.'.$resource_id}=~/\.sequence$/) || + ($hash{'src_'.$lpc.'.'.$resource_id}=~/\.page$/)) { + $mapcount{$lpc} ++; + } + } unless ($codechecked) { my $startsymb = &Apache::lonnet::encode_symb($hash{'map_id_'.$lpc},$resource_id, @@ -281,15 +293,7 @@ sub loadmap { # Handle randomization and random selection if ($randomize) { - my $advanced; - if ($env{'request.course.id'}) { - $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); - } else { - $env{'request.course.id'} = $courseid; - $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); - $env{'request.course.id'} = ''; - } - unless ($advanced) { + unless (&is_advanced($courseid)) { # Order of resources is not randomized if user has and advanced role in the course. my $seed; @@ -372,6 +376,18 @@ sub loadmap { } } +sub is_advanced { + my ($courseid) = @_; + my $advanced; + if ($env{'request.course.id'}) { + $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); + } else { + $env{'request.course.id'} = $courseid; + $advanced = (&Apache::lonnet::allowed('adv') eq 'F'); + $env{'request.course.id'} = ''; + } + return $advanced; +} # -------------------------------------------------------------------- Resource # @@ -458,7 +474,11 @@ sub parse_resource { # is not a page. If the resource is a page then it must be # assembled (at fetch time?). - unless ($ispage) { + if ($ispage) { + if ($token->[2]->{'external'} eq 'true') { # external + $turi=~s{^http\://}{/ext/}; + } + } else { $turi=~/\.(\w+)$/; my $embstyle=&Apache::loncommon::fileembstyle($1); if ($token->[2]->{'external'} eq 'true') { # external @@ -550,7 +570,9 @@ sub parse_resource { if (($turi=~/\.sequence$/) || ($turi=~/\.page$/)) { $hash{'is_map_'.$rid}=1; - &loadmap($turi,$rid,$courseid); + if ((!$hiddenurl{$rid}) || (&is_advanced($courseid))) { + &loadmap($turi,$rid,$courseid); + } } return $token->[2]->{'id'}; } @@ -906,6 +928,14 @@ sub traceroute { && ($hash{'src_'.$rid}!~/\.sequence$/)) { $retfrid=$rid; } + my @deeplink=&Apache::lonnet::EXT('resource.0.deeplink',$symb); + unless ((@deeplink == 0) || ($deeplink[0] eq 'full')) { + $deeplinkonly{$rid}=join(':',@deeplink); + if ($deeplink[1] eq 'map') { + my $parent = (split(/\,/,$hash{'map_hierarchy_'.$mapid}))[-1]; + $deeplinkonly{"$parent.$mapid"}=$deeplinkonly{$rid}; + } + } if (defined($hash{'conditions_'.$rid})) { $hash{'conditions_'.$rid}=simplify( @@ -1114,6 +1144,14 @@ sub hiddenurls { if ($currentrids[$k]) { $hash{'randomout_'.$currentrids[$k]}=1; my ($mapid,$resid)=split(/\./,$currentrids[$k]); + if ($rescount{$mapid}) { + $rescount{$mapid} --; + } + if ($hash{'is_map_'.$currentrids[$k]}) { + if ($mapcount{$mapid}) { + $mapcount{$mapid} --; + } + } $randomoutentry.='&'. &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid}, $resid, @@ -1126,6 +1164,14 @@ sub hiddenurls { foreach my $rid (keys(%hiddenurl)) { $hash{'randomout_'.$rid}=1; my ($mapid,$resid)=split(/\./,$rid); + if ($rescount{$mapid}) { + $rescount{$mapid} --; + } + if ($hash{'is_map_'.$rid}) { + if ($mapcount{$mapid}) { + $mapcount{$mapid} --; + } + } $randomoutentry.='&'. &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid, $hash{'src_'.$rid}).'&'; @@ -1136,10 +1182,36 @@ sub hiddenurls { } } +# -------------------------------------- populate big hash with map breadcrumbs + +# Create map_breadcrumbs_$pc from map_hierarchy_$pc by omitting intermediate +# maps not shown in Course Contents table. + +sub mapcrumbs { + foreach my $key (keys(%rescount)) { + if ($hash{'map_hierarchy_'.$key}) { + my $skipnext = 0; + foreach my $id (split(/,/,$hash{'map_hierarchy_'.$key}),$key) { + unless ($skipnext) { + $hash{'map_breadcrumbs_'.$key} .= "$id,"; + } + unless (($id == 0) || ($id == 1)) { + if ((!$rescount{$id}) || ($rescount{$id} == 1 && $mapcount{$id} == 1)) { + $skipnext = 1; + } else { + $skipnext = 0; + } + } + } + $hash{'map_breadcrumbs_'.$key} =~ s/,$//; + } + } +} + # ---------------------------------------------------- Read map and all submaps sub readmap { - my $short=shift; + my ($short,$critmsg_check) = @_; $short=~s/^\///; # TODO: Hidden dependency on current user: @@ -1156,7 +1228,7 @@ sub readmap { } @cond=('true:normal'); - unless (open(LOCKFILE,">$fn.db.lock")) { + unless (open(LOCKFILE,">","$fn.db.lock")) { # # Most likely a permissions problem on the lockfile or its directory. # @@ -1174,8 +1246,14 @@ sub readmap { &unlink_tmpfiles($fn); } undef %randompick; + undef %randompickseed; + undef %randomorder; + undef %randomizationcode; undef %hiddenurl; undef %encurl; + undef %deeplinkonly; + undef %rescount; + undef %mapcount; $retfrid=''; $errtext=''; my ($untiedhash,$untiedparmhash,$tiedhash,$tiedparmhash); # More state flags. @@ -1317,8 +1395,14 @@ sub readmap { $lock=1; } undef %randompick; + undef %randompickseed; + undef %randomorder; + undef %randomizationcode; undef %hiddenurl; undef %encurl; + undef %deeplinkonly; + undef %rescount; + undef %mapcount; $errtext=''; $retfrid=''; # @@ -1366,12 +1450,16 @@ sub readmap { # Depends on user must parameterize this as well..or separate as this is: # more part of determining what someone sees on entering a course? +# When lonuserstate::readmap() is called from lonroles.pm, i.e., +# after selecting a role in a course, critical_redirect will be called, +# unless the course has a blocking event in effect, when suppresses +# critical message checking (users without evb priv). +# - my @what=&Apache::lonnet::dump('critical',$env{'user.domain'}, - $env{'user.name'}); - if ($what[0]) { - if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) { - $retfurl='/adm/email?critical=display'; + if ($critmsg_check) { + my ($redirect,$url) = &Apache::loncommon::critical_redirect(); + if ($redirect) { + $retfurl = $url; } } return ($retfurl,$errtext); @@ -1437,6 +1525,7 @@ sub build_tmp_hashes { &traceroute('0',$hash{'map_start_'.$uri},'&'); &accinit($uri,$short,$fn); &hiddenurls(); + &mapcrumbs(); } $errtext .= &get_mapalias_errors(); # ------------------------------------------------------- Put versions into src @@ -1454,6 +1543,10 @@ sub build_tmp_hashes { # $hash{'src_'.$id}=&Apache::lonenc::encrypted($hash{'src_'.$id}); $hash{'encrypted_'.$id}=1; } +# ------------------------------------------------------------ Deep-linked URLs + foreach my $id (keys(%deeplinkonly)) { + $hash{'deeplinkonly_'.$id}=$deeplinkonly{$id}; + } # ----------------------------------------------- Close hashes to finally store # --------------------------------- Routine must pass this point, no early outs $hash{'first_rid'}=$retfrid; @@ -1468,7 +1561,7 @@ sub build_tmp_hashes { # ---------------------------------------------------- Store away initial state { my $cfh; - if (open($cfh,">$fn.state")) { + if (open($cfh,">","$fn.state")) { print $cfh join("\n",@cond); $gotstate = 1; } else { @@ -1505,7 +1598,7 @@ sub evalstate { if (-e $fn) { my @conditions=(); { - open(my $fh,"<$fn"); + open(my $fh,"<",$fn); @conditions=<$fh>; close($fh); } 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.