--- loncom/interface/lonnavmaps.pm 2022/01/01 04:14:05 1.509.2.14.2.1 +++ loncom/interface/lonnavmaps.pm 2016/09/15 16:30:10 1.524 @@ -1,8 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.509.2.14.2.1 2022/01/01 04:14:05 raeburn Exp $ - +# $Id: lonnavmaps.pm,v 1.524 2016/09/15 16:30:10 damieng Exp $ # # Copyright Michigan State University Board of Trustees # @@ -486,7 +485,7 @@ use Apache::lonlocal; use Apache::lonnet; use Apache::lonmap; -use POSIX qw (ceil floor strftime); +use POSIX qw (floor strftime); use Time::HiRes qw( gettimeofday tv_interval ); use LONCAPA; use DateTime(); @@ -577,11 +576,7 @@ sub getLinkForResource { my $anchor; if ($res->is_page()) { foreach my $item (@$stack) { if (defined($item)) { $anchor = $item; } } - if ($anchor->encrypted() && !&advancedUser()) { - $anchor='LC_'.$anchor->id(); - } else { - $anchor=&escape($anchor->shown_symb()); - } + $anchor=&escape($anchor->shown_symb()); return ($res->link(),$res->shown_symb(),$anchor); } # in case folder was skipped over as "only sequence" @@ -647,9 +642,6 @@ sub getDescription { } elsif ($slot_status == $res->RESERVABLE) { $slotmsg = &mt('Reservable, reservations close [_1]', timeToHumanString($slot_time,'end')); - } elsif ($slot_status == $res->NEEDS_CHECKIN) { - $slotmsg = &mt('Reserved, check-in needed - ends [_1]', - timeToHumanString($slot_time,'end')); } elsif ($slot_status == $res->RESERVABLE_LATER) { $slotmsg = &mt('Reservable, reservations open [_1]', timeToHumanString($slot_time,'start')); @@ -945,31 +937,8 @@ sub render_resource { # links to open and close the folder my $whitespace = $location.'/whitespace_21.gif'; - my ($nomodal,$linkopen,$linkclose); - unless ($resource->is_map() || $params->{'resource_nolink'}) { - $linkopen = ""; - $linkclose = ""; - if (($params->{'modalLink'}) && (!$resource->is_sequence())) { - if ($link =~m{^(?:|/adm/wrapper)/ext/([^#]+)}) { - my $exturl = $1; - if (($ENV{'SERVER_PORT'} == 443) && ($exturl !~ /^https:/)) { - $nomodal = 1; - } - } elsif (($link eq "/public/$LONCAPA::match_domain/$LONCAPA::match_courseid/syllabus") && - ($env{'request.course.id'}) && ($ENV{'SERVER_PORT'} == 443) && - ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) { - $nomodal = 1; - } - my $esclink = &js_escape($link); - if ($nomodal) { - $linkopen .= ""; - } else { - $linkopen .= ""; - } - } else { - $linkopen .= ""; - } - } + my $linkopen = "".""; + my $linkclose = ""; # Default icon: unknown page my $icon = ""; @@ -1017,21 +986,16 @@ sub render_resource { '&jump=' . &escape($resource->symb()) . "&folderManip=1\">"; - $linkclose = ''; + } else { # Don't allow users to manipulate folder $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif'; $icon = ""."\"".($nowOpen"; - if ($params->{'caller'} eq 'sequence') { - $linkopen = ""; - $linkclose = ''; - } else { - $linkopen = ""; - $linkclose = ""; - } + + $linkopen = ""; + $linkclose = ""; } - if (((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) || - (&Apache::lonnet::allowed('cev',$env{'request.course.id'}))) && + if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) && ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) { if (!$params->{'map_no_edit_link'}) { my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png'; @@ -1043,30 +1007,10 @@ sub render_resource { } if ($params->{'mapHidden'} || $resource->randomout()) { $nonLinkedText .= ' ('.&mt('hidden').') '; - } elsif ($params->{'mapUnlisted'}) { - $nonLinkedText .= ' ('.&mt('unlisted').') '; - } elsif ($params->{'mapHiddenDeepLink'} || $resource->deeplinkout()) { - $nonLinkedText .= ' ('.&mt('not shown').') '; } } else { if ($resource->randomout()) { $nonLinkedText .= ' ('.&mt('hidden').') '; - } elsif ($resource->deeplinkout()) { - $nonLinkedText .= ' ('.&mt('not shown').') '; - } else { - my $deeplink = $resource->deeplink($params->{caller}); - if ((($deeplink eq 'absent') || ($deeplink eq 'grades')) && - &advancedUser()) { - $nonLinkedText .= ' ('.&mt('unlisted').') '; - } elsif (($deeplink) && ($deeplink) ne 'full') { - if (&advancedUser()) { - $nonLinkedText .= ' ('.&mt('deep-link access'). - ') '; - } else { - $nonLinkedText .= ' ('.&mt('access via external site'). - ') '; - } - } } } if (!$resource->condval()) { @@ -1117,19 +1061,10 @@ sub render_resource { } if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { - $linkclose = ''; - if ($params->{'modalLink'}) { - my $esclink = &js_escape($link); - if ($nomodal) { - $linkopen = ""; - } else { - $linkopen = ""; - } - } else { - $linkopen = ""; - } + $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$editmapLink$nonLinkedText"; + } else { + $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$editmapLink$nonLinkedText"; } - $result .= "$curMarkerBegin$linkopen$title$partLabel$linkclose$curMarkerEnd$editmapLink$nonLinkedText"; return $result; } @@ -1391,9 +1326,6 @@ sub render { # an infinite loop my $oldFilterFunc = $filterFunc; $filterFunc = sub { my $res = shift; return !$res->randomout() && - ($res->deeplink($args->{'caller'}) ne 'absent') && - ($res->deeplink($args->{'caller'}) ne 'grades') && - !$res->deeplinkout() && &$oldFilterFunc($res);}; } @@ -1423,11 +1355,10 @@ sub render { my $currenturl = $env{'form.postdata'}; #$currenturl=~s/^http\:\/\///; #$currenturl=~s/^[^\/]+//; - unless ($args->{'caller'} eq 'sequence') { - $here = $jump = &Apache::lonnet::symbread($currenturl); - } + + $here = $jump = &Apache::lonnet::symbread($currenturl); } - if (($here eq '') && ($args->{'caller'} ne 'sequence')) { + if ($here eq '') { my $last; if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', &GDBM_READER(),0640)) { @@ -1487,13 +1418,10 @@ sub render { if ($args->{'iterator_map'}) { my $map = $args->{'iterator_map'}; $map = $navmap->getResourceByUrl($map); - if (ref($map)) { - my $firstResource = $map->map_start(); - my $finishResource = $map->map_finish(); - $args->{'iterator'} = $it = $navmap->getIterator($firstResource, $finishResource, $filterHash, $condition); - } else { - return; - } + my $firstResource = $map->map_start(); + my $finishResource = $map->map_finish(); + + $args->{'iterator'} = $it = $navmap->getIterator($firstResource, $finishResource, $filterHash, $condition); } else { $args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition,undef,$args->{'include_top_level_map'}); } @@ -1612,8 +1540,7 @@ END $result.=''; } if (($args->{'caller'} eq 'navmapsdisplay') && - ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) || - (&Apache::lonnet::allowed('cev',$env{'request.course.id'})))) { + (&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) { my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; if ($env{'course.'.$env{'request.course.id'}.'.url'} eq @@ -1663,7 +1590,7 @@ END # We also do this even if $args->{'suppressEmptySequences'} # is not true, so we can hide empty sequences for which the # hiddenresource parameter is set to yes (at map level), or - # mark as hidden for users who have $userCanSeeHidden. + # mark as hidden for users who have $userCanSeeHidden. # Use DFS for speed, since structure actually doesn't matter, # except what map has what resources. @@ -1671,7 +1598,6 @@ END $it->{FIRST_RESOURCE}, $it->{FINISH_RESOURCE}, {}, undef, 1); - my $depth = 0; $dfsit->next(); my $curRes = $dfsit->next(); @@ -1679,7 +1605,7 @@ END if ($curRes == $dfsit->BEGIN_MAP()) { $depth++; } if ($curRes == $dfsit->END_MAP()) { $depth--; } - if (ref($curRes)) { + if (ref($curRes)) { # Parallel pre-processing: Do sequences have non-filtered-out children? if ($curRes->is_map()) { $curRes->{DATA}->{HAS_VISIBLE_CHILDREN} = 0; @@ -1756,28 +1682,6 @@ 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'}) { - $inhibitmenu = '&inhibitmenu=yes'; - } while (1) { if ($args->{'sort'}) { @@ -1814,36 +1718,18 @@ END # If this is an empty sequence and we're filtering them, continue on $args->{'mapHidden'} = 0; - $args->{'mapUnlisted'} = 0; - $args->{'mapHiddenDeepLink'} = 0; if (($curRes->is_map()) && (!$curRes->{DATA}->{HAS_VISIBLE_CHILDREN})) { if ($args->{'suppressEmptySequences'}) { next; } else { my $mapname = &Apache::lonnet::declutter($curRes->src()); - $mapname = &Apache::lonnet::deversion($mapname); + $mapname = &Apache::lonnet::deversion($mapname); if (lc($navmap->get_mapparam(undef,$mapname,"0.hiddenresource")) eq 'yes') { if ($userCanSeeHidden) { $args->{'mapHidden'} = 1; } else { next; } - } elsif ($curRes->deeplinkout) { - if ($userCanSeeHidden) { - $args->{'mapHiddenDeepLink'} = 1; - } else { - next; - } - } else { - my $deeplink = $navmap->get_mapparam(undef,$mapname,"0.deeplink"); - my ($state,$others,$listed) = split(/,/,$deeplink); - if (($listed eq 'absent') || ($listed eq 'grades')) { - if ($userCanSeeHidden) { - $args->{'mapUnlisted'} = 1; - } else { - next; - } - } } } } @@ -1906,16 +1792,7 @@ END $args->{'condensed'} = 1; } } - } - # If deep-link parameter is set (and is not set to full) suppress link - # unless privileged user, tinyurl used for login resolved to a map, and - # the resource is within the map. - if ((!$curRes->deeplink($args->{'caller'})) || - ($curRes->deeplink($args->{'caller'}) eq 'full') || &advancedUser()) { - $args->{'resource_nolink'} = 0; - } else { - $args->{'resource_nolink'} = 1; - } + } # If the multipart problem was condensed, "forget" it was multipart if (scalar(@parts) == 1) { @@ -1938,35 +1815,11 @@ 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()) || (&Apache::lonnet::waf_allssl($hostname))) { - 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()) || (&Apache::lonnet::waf_allssl($hostname))) { - if ($hostname ne '') { - $src = 'http://'.$hostname.$src; - } - $src .= ($srcHasQuestion? '&' : '?') . 'usehttp=1'; - $srcHasQuestion = 1; - } - } - } if (defined($anchor)) { $anchor='#'.$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; - } + my $srcHasQuestion = $src =~ /\?/; + $args->{"resourceLink"} = $src. + ($srcHasQuestion?'&':'?') . + 'symb=' . &escape($symb).$anchor; } # Now, we've decided what parts to show. Loop through them and # show them. @@ -1994,7 +1847,7 @@ END $currentJumpDelta) { # Jam the anchor after the tag; # necessary for valid HTML (which Mozilla requires) - $colHTML =~ s/\>/\>\\<\/a\>/; + $colHTML =~ s/\>/\>\/; $displayedJumpMarker = 1; } $result .= $colHTML . "\n"; @@ -2287,7 +2140,7 @@ sub change_user { - # Now clear the parm cache and reconstruct the parm hash fromt he big_hash + # Now clear the parm cache and reconstruct the parm hash from the big_hash # param.xxxx keys. $self->{PARM_CACHE} = {}; @@ -2380,7 +2233,7 @@ sub generate_email_discuss_status { foreach my $msgid (@keys) { if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid, - $symb,$error) = &Apache::lonmsg::unpackmsgid(&LONCAPA::escape($msgid)); + $symb,$error) = &Apache::lonmsg::unpackmsgid($msgid); &Apache::lonenc::check_decrypt(\$symb); if (($fromcid ne '') && ($fromcid ne $cid)) { next; @@ -2481,7 +2334,7 @@ sub getIterator { my $self = shift; my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift, shift, undef, shift, - shift, shift, shift); + shift, shift); return $iterator; } @@ -2752,6 +2605,7 @@ sub parmval { return $self->{PARM_CACHE}->{$hashkey}; } } + my $result = $self->parmval_real($what, $symb, $recurse); $self->{PARM_CACHE}->{$hashkey} = $result; if (wantarray) { @@ -2785,29 +2639,35 @@ sub parmval_real { my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb); $mapname = &Apache::lonnet::deversion($mapname); + my ($recursed,@recurseup); + # ----------------------------------------------------- Cascading lookup scheme my $rwhat=$what; $what=~s/^parameter\_//; $what=~s/\_/\./; my $symbparm=$symb.'.'.$what; + my $recurseparm=$mapname.'___(rec).'.$what; my $mapparm=$mapname.'___(all).'.$what; my $usercourseprefix=$cid; - + my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what; my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm; + my $grpleveli=$usercourseprefix.'.['.$cgroup.'].'.$recurseparm; my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm; my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; + my $secleveli=$usercourseprefix.'.['.$csec.'].'.$recurseparm; my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm; my $courselevel= $usercourseprefix.'.'.$what; my $courselevelr=$usercourseprefix.'.'.$symbparm; + my $courseleveli=$usercourseprefix.'.'.$recurseparm; my $courselevelm=$usercourseprefix.'.'.$mapparm; @@ -2819,6 +2679,17 @@ sub parmval_real { if ($uname and defined($useropt)) { if (defined($$useropt{$courselevelr})) { return [$$useropt{$courselevelr},'resource']; } if (defined($$useropt{$courselevelm})) { return [$$useropt{$courselevelm},'map']; } + if (defined($$useropt{$courseleveli})) { return [$$useropt{$courseleveli},'map']; } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; + last if (defined($$useropt{$norecursechk})); + my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what; + if (defined($$useropt{$recursechk})) { return [$$useropt{$recursechk},'map']; } + } if (defined($$useropt{$courselevel})) { return [$$useropt{$courselevel},'course']; } } @@ -2826,12 +2697,34 @@ sub parmval_real { if ($cgroup ne '' and defined($courseopt)) { if (defined($$courseopt{$grplevelr})) { return [$$courseopt{$grplevelr},'resource']; } if (defined($$courseopt{$grplevelm})) { return [$$courseopt{$grplevelm},'map']; } + if (defined($$courseopt{$grpleveli})) { return [$$courseopt{$grpleveli},'map']; } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(all).'.$what; + last if (defined($$courseopt{$norecursechk})); + my $recursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(rec).'.$what; + if (defined($$courseopt{$recursechk})) { return [$$courseopt{$recursechk},'map']; } + } if (defined($$courseopt{$grplevel})) { return [$$courseopt{$grplevel},'course']; } } - if ($csec and defined($courseopt)) { + if ($csec ne '' and defined($courseopt)) { if (defined($$courseopt{$seclevelr})) { return [$$courseopt{$seclevelr},'resource']; } if (defined($$courseopt{$seclevelm})) { return [$$courseopt{$seclevelm},'map']; } + if (defined($$courseopt{$secleveli})) { return [$$courseopt{$secleveli},'map']; } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(all).'.$what; + last if (defined($$courseopt{$norecursechk})); + my $recursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(rec).'.$what; + if (defined($$courseopt{$recursechk})) { return [$$courseopt{$recursechk},'map']; } + } if (defined($$courseopt{$seclevel})) { return [$$courseopt{$seclevel},'course']; } } @@ -2855,6 +2748,19 @@ sub parmval_real { # --------------------------------------------------- fifth, check more course if (defined($courseopt)) { if (defined($$courseopt{$courselevelm})) { return [$$courseopt{$courselevelm},'map']; } + if (defined($$courseopt{$courseleveli})) { return [$$courseopt{$courseleveli},'map']; } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; + last if (defined($$courseopt{$norecursechk})); + my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what; + if (defined($$courseopt{$recursechk})) { + return [$$courseopt{$recursechk},'map']; + } + } if (defined($$courseopt{$courselevel})) { my $ret = [$$courseopt{$courselevel},'course']; return $ret; @@ -2894,91 +2800,6 @@ 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. @@ -2991,7 +2812,7 @@ sub map_printdates { my $opendate = $self->get_mapparam($res->symb(),'',"$part.printstartdate"); - my $closedate= $self->get_mapparam($res->symb(),'', "$part.printenddate"); + my $closedate= $self->get_mapparam($res->symb(),'',"$part.printenddate"); return ($opendate, $closedate); @@ -3021,6 +2842,7 @@ sub get_mapparam { my $result=''; my ($recursed,@recurseup); + # Figure out which map we are in. if ($symb && !$mapname) { @@ -3029,21 +2851,25 @@ sub get_mapparam { $mapname = &Apache::lonnet::deversion($mapname); } + my $rwhat=$what; $what=~s/^parameter\_//; $what=~s/\_/\./; # Build the hash keys for the lookup: - my $symbparm=$symb.'.'.$what; my $mapparm=$mapname.'___(all).'.$what; + my $recurseparm=$mapname.'___(rec).'.$what; my $usercourseprefix=$cid; - my $grplevel = "$usercourseprefix.[$cgroup].$mapparm"; - my $seclevel = "$usercourseprefix.[$csec].$mapparm"; - my $courselevel = "$usercourseprefix.$mapparm"; - + my $grplevelm = "$usercourseprefix.[$cgroup].$mapparm"; + my $seclevelm = "$usercourseprefix.[$csec].$mapparm"; + my $courselevelm = "$usercourseprefix.$mapparm"; + + my $grpleveli = "$usercourseprefix.[$cgroup].$recurseparm"; + my $secleveli = "$usercourseprefix.[$csec].$recurseparm"; + my $courseleveli = "$usercourseprefix.$recurseparm"; # Get handy references to the hashes we need in $self: @@ -3056,21 +2882,22 @@ sub get_mapparam { if ($uname and defined($useropt)) { - if (defined($$useropt{$courselevel})) { - return $$useropt{$courselevel}; + if (defined($$useropt{$courselevelm})) { + return $$useropt{$courselevelm}; } - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - unless ($recursed) { - @recurseup = $self->recurseup_maps($mapname); - $recursed = 1; - } - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; - if (defined($$useropt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$useropt{$norecursechk}; - } - } + if (defined($$useropt{$courseleveli})) { + return $$useropt{$courseleveli}; + } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; + last if (defined($$useropt{$norecursechk})); + my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what; + if (defined($$useropt{$recursechk})) { + return $$useropt{$recursechk}; } } } @@ -3080,21 +2907,22 @@ sub get_mapparam { if ($cgroup ne '' and defined ($courseopt)) { - if (defined($$courseopt{$grplevel})) { - return $$courseopt{$grplevel}; + if (defined($$courseopt{$grplevelm})) { + return $$courseopt{$grplevelm}; } - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - unless ($recursed) { - @recurseup = $self->recurseup_maps($mapname); - $recursed = 1; - } - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(all).'.$what; - if (defined($$courseopt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$courseopt{$norecursechk}; - } - } + if (defined($$courseopt{$grpleveli})) { + return $$courseopt{$grpleveli}; + } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(all).'.$what; + last if (defined($$courseopt{$norecursechk})); + my $recursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(rec).'.$what; + if (defined($$courseopt{$recursechk})) { + return $$courseopt{$recursechk}; } } } @@ -3102,25 +2930,23 @@ sub get_mapparam { # Check course -- section - - - - if ($csec and defined($courseopt)) { - if (defined($$courseopt{$seclevel})) { - return $$courseopt{$seclevel}; + if ($csec ne '' and defined($courseopt)) { + if (defined($$courseopt{$seclevelm})) { + return $$courseopt{$seclevelm}; } - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - unless ($recursed) { - @recurseup = $self->recurseup_maps($mapname); - $recursed = 1; - } - foreach my $item (@recurseup) { - my $norecursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(all).'.$what; - if (defined($$courseopt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$courseopt{$norecursechk}; - } - } + if (defined($$courseopt{$secleveli})) { + return $$courseopt{$secleveli}; + } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + foreach my $item (@recurseup) { + my $norecursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(all).'.$what; + last if (defined($$courseopt{$norecursechk})); + my $recursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(rec).'.$what; + if (defined($$courseopt{$recursechk})) { + return $$courseopt{$recursechk}; } } } @@ -3130,7 +2956,7 @@ sub get_mapparam { my $symbparm=$symb.'.'.$what; my $thisparm = $$parmhash{$symbparm}; if (defined($thisparm)) { - return $thisparm; + return $thisparm; } } @@ -3138,25 +2964,25 @@ sub get_mapparam { # Additional course parameters: if (defined($courseopt)) { - if (defined($$courseopt{$courselevel})) { - return $$courseopt{$courselevel}; + if (defined($$courseopt{$courselevelm})) { + return $$courseopt{$courselevelm}; } - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - unless ($recursed) { - @recurseup = $self->recurseup_maps($mapname); - $recursed = 1; - } + unless ($recursed) { + @recurseup = $self->recurseup_maps($mapname); + $recursed = 1; + } + if (@recurseup) { foreach my $item (@recurseup) { my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what; - if (defined($$courseopt{$norecursechk})) { - if ($what =~ /\.(encrypturl|hiddenresource)$/) { - return $$courseopt{$norecursechk}; - } + last if (defined($$courseopt{$norecursechk})); + my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what; + if (defined($$courseopt{$recursechk})) { + return $$courseopt{$recursechk}; } } } } - return undef; # Unefined if we got here. + return undef; # Undefined if we got here. } sub course_printdates { @@ -3198,10 +3024,6 @@ sub getcourseparam { $what=~s/^parameter\_//; $what=~s/\_/\./; - - my $symbparm = $symb . '.' . $what; - my $mapparm=$mapname.'___(all).'.$what; - # Local refs to the hashes we're going to look at: my $useropt = $self->{USER_OPT}; @@ -3447,7 +3269,7 @@ getIterator behaves as follows: =over 4 -=item * B(firstResource, finishResource, filterHash, condition, forceTop, returnTopMap, $deeplinklisted): +=item * B(firstResource, finishResource, filterHash, condition, forceTop, returnTopMap): All parameters are optional. firstResource is a resource reference corresponding to where the iterator should start. It defaults to @@ -3464,10 +3286,7 @@ that is not just a single, 'redirecting' will return all information, starting with the top-level map, regardless of content. returnTopMap, if true (default false), will cause the iterator to return the top-level map object (resource 0.0) -before anything else. deeplinklisted if true (default false), will -check "listed" status of a resource with a deeplink, and unless "absent" -will exclude deeplink checking when retrieving the browsePriv from -lonnet::allowed(). +before anything else. Thus, by default, only top-level resources will be shown. Change the condition to a 1 without changing the hash, and all resources will be @@ -3604,10 +3423,6 @@ sub new { # have we done that yet? $self->{HAVE_RETURNED_0} = 0; - # Do we want to check the "listed" status for a resource for which - # deeplinking applies. - $self->{DEEPLINKLISTED} = shift; - # Now, we need to pre-process the map, by walking forward and backward # over the parts of the map we're going to look at. @@ -3699,8 +3514,7 @@ sub new { $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}, $self->{CONDITION}, - $self->{FORCE_TOP}, - undef,$self->{DEEPLINKLISTED}); + $self->{FORCE_TOP}); } # Set up some bookkeeping information. @@ -3860,8 +3674,7 @@ 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}) && - ($env{'request.role.adv'} || !$self->{HERE}->randomout())) { + (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) { $self->{RECURSIVE_ITERATOR_FLAG} = 1; my $firstResource = $self->{HERE}->map_start(); my $finishResource = $self->{HERE}->map_finish(); @@ -3870,14 +3683,13 @@ sub next { $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}, $self->{CONDITION}, - $self->{FORCE_TOP}, - undef,$self->{DEEPLINKLISTED}); + $self->{FORCE_TOP}); } # If this is a blank resource, don't actually return it. # Should you ever find you need it, make sure to add an option to the code # that you can use; other things depend on this behavior. - my $browsePriv = $self->{HERE}->browsePriv($noblockcheck,$self->{DEEPLINKLISTED}); + my $browsePriv = $self->{HERE}->browsePriv($noblockcheck); if (!$self->{HERE}->src() || (!($browsePriv eq 'F') && !($browsePriv eq '2')) ) { return $self->next($closeAllPages); @@ -4214,7 +4026,7 @@ sub new { # This is a speed optimization, to avoid calling symb() too often. $self->{SYMB} = $self->symb(); - + return $self; } @@ -4305,7 +4117,6 @@ sub from { my $self=shift; return $self- sub goesto { my $self=shift; return $self->navHash("goesto_", 1); } sub kind { my $self=shift; return $self->navHash("kind_", 1); } sub randomout { my $self=shift; return $self->navHash("randomout_", 1); } -sub deeplinkout { my $self=shift; return $self->navHash("deeplinkout_", 1); } sub randompick { my $self = shift; my $randompick = $self->parmval('randompick'); @@ -4341,7 +4152,7 @@ sub enclosing_map_src { } sub symb { my $self=shift; - if (defined($self->{SYMB})) { return $self->{SYMB}; } + if (defined $self->{SYMB}) { return $self->{SYMB}; } (my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/; my $symbSrc = &Apache::lonnet::declutter($self->src()); my $symb = &Apache::lonnet::declutter($self->navHash('map_id_'.$first)) @@ -4561,6 +4372,7 @@ sub is_task { sub is_empty_sequence { my $self=shift; + my $src = $self->src(); return !$self->is_page() && $self->navHash("is_map_", 1) && !$self->navHash("map_type_" . $self->map_pc()); } @@ -4611,12 +4423,6 @@ 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 @@ -4652,11 +4458,6 @@ 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 @@ -4881,12 +4682,12 @@ sub duedate { my $date; my @interval=$self->parmval("interval", $part); my $due_date=$self->parmval("duedate", $part); - if ($interval[0] =~ /(\d+)/) { + if ($interval[0] =~ /^(\d+)/) { my $timelimit = $1; my $first_access=&Apache::lonnet::get_first_access($interval[1], - $self->{SYMB}); + $self->{SYMB}); if (defined($first_access)) { - my $interval = $first_access+$timelimit + my $interval = $first_access+$timelimit; $date = (!$due_date || $interval < $due_date) ? $interval : $due_date; } else { @@ -4980,54 +4781,20 @@ sub slot_control { my $available = $self->parmval("available", $part); return ($useslots,$availablestudent,$available); } -sub deeplink { - my ($self,$caller,$action) = @_; - my $deeplink = $self->parmval("deeplink"); - if ($deeplink) { - my ($state,$others,$listed,$scope) = split(/,/,$deeplink); - if ($action eq 'getlisted') { - return $listed; - } - if ($env{'request.deeplink.login'}) { - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom); - if ($deeplink_symb) { - my ($loginmap,$mapname); - if ($deeplink_symb =~ /\.(page|sequence)$/) { - $mapname = $self->enclosing_map_src(); - $loginmap = &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($deeplink_symb))[2]); - return if ($mapname eq $loginmap); - } else { - return if ($deeplink_symb eq $self->symb()); - if (($scope eq 'map') || ($scope eq 'rec')) { - $mapname = $self->enclosing_map_src(); - $loginmap = &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($deeplink_symb))[0]); - return if ($mapname eq $loginmap); - } - } - if ($scope eq 'rec') { - my $map_pc = $self->navHash('map_pc_'.$mapname); - my @recurseup = split(/,/,$self->navHash('map_hierarchy_'.$map_pc)); - my $login_pc = $self->navHash('map_pc_'.$loginmap); - return if (grep(/^\Q$login_pc\E$/,@recurseup)); - } - } - } - unless (($caller eq 'sequence') || ($state eq 'both')) { - return $listed; - } - } - return; -} # Multiple things need this sub getReturnHash { my $self = shift; if (!defined($self->{RETURN_HASH})) { - my %tmpHash = &Apache::lonnet::restore($self->{SYMB},undef,$self->{DOMAIN},$self->{USERNAME}); - $self->{RETURN_HASH} = \%tmpHash; + #my %tmpHash = &Apache::lonnet::restore($self->{SYMB},undef,$self->{DOMAIN},$self->{USERNAME}); + #$self->{RETURN_HASH} = \%tmpHash; + # When info is retrieved for several resources (as when rendering a directory), + # it is much faster to use the user profile dump and avoid repeated lonnet requests + # (especially since lonnet::currentdump is using Lond directly whenever possible, + # and lonnet::restore is not at this point). + $self->{NAV_MAP}->get_user_data(); + $self->{RETURN_HASH} = $self->{NAV_MAP}->{STUDENT_DATA}->{$self->{SYMB}}; } } @@ -5832,7 +5599,7 @@ sub check_for_slot { ($checkedin,$checkedinslot) = $self->checkedin(); unless ((grep(/^\Q$checkedin\E/,@proctors)) && ($checkedinslot eq $slot_name)) { - return (NEEDS_CHECKIN,$end,$slot_name); + return (NEEDS_CHECKIN,undef,$slot_name); } } return (RESERVED,$end,$slot_name); @@ -5878,12 +5645,29 @@ sub check_for_slot { my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'}, $env{'user.domain'}); if (ref($reservable) eq 'HASH') { + my ($map) = &Apache::lonnet::decode_symb($symb); if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) { foreach my $slot (reverse (@{$reservable->{'now_order'}})) { my $canuse; - if (($reservable->{'now'}{$slot}{'symb'} eq '') || - ($reservable->{'now'}{$slot}{'symb'} eq $symb)) { + if ($reservable->{'now'}{$slot}{'symb'} eq '') { $canuse = 1; + } else { + my %oksymbs; + my @slotsymbs = split(/\s*,\s*/,$reservable->{'now'}{$slot}{'symb'}); + map { $oksymbs{$_} = 1; } @slotsymbs; + if ($oksymbs{$symb}) { + $canuse = 1; + } else { + foreach my $item (@slotsymbs) { + if ($item =~ /\.(page|sequence)$/) { + (undef,undef, my $sloturl) = &Apache::lonnet::decode_symb($item); + if (($map ne '') && ($map eq $sloturl)) { + $canuse = 1; + last; + } + } + } + } } if ($canuse) { if ($checkedin) { @@ -5904,8 +5688,26 @@ sub check_for_slot { if ((ref($reservable->{'future_order'}) eq 'ARRAY') && (ref($reservable->{'future'}) eq 'HASH')) { foreach my $slot (@{$reservable->{'future_order'}}) { my $canuse; - if (($reservable->{'future'}{$slot}{'symb'} eq '') || - ($reservable->{'future'}{$slot}{'symb'} eq $symb)) { + if ($reservable->{'future'}{$slot}{'symb'} eq '') { + $canuse = 1; + } elsif ($reservable->{'future'}{$slot}{'symb'} =~ /,/) { + my %oksymbs; + my @slotsymbs = split(/\s*,\s*/,$reservable->{'future'}{$slot}{'symb'}); + map { $oksymbs{$_} = 1; } @slotsymbs; + if ($oksymbs{$symb}) { + $canuse = 1; + } else { + foreach my $item (@slotsymbs) { + if ($item =~ /\.(page|sequence)$/) { + (undef,undef, my $sloturl) = &Apache::lonnet::decode_symb($item); + if (($map ne '') && ($map eq $sloturl)) { + $canuse = 1; + last; + } + } + } + } + } elsif ($reservable->{'future'}{$slot}{'symb'} eq $symb) { $canuse = 1; } if ($canuse) { @@ -6151,23 +5953,13 @@ sub getPrevious { sub browsePriv { my $self = shift; my $noblockcheck = shift; - my $deeplinklisted = shift; if (defined($self->{BROWSE_PRIV})) { return $self->{BROWSE_PRIV}; } - my ($nodeeplinkcheck,$nodeeplinkout); - if ($deeplinklisted) { - my $deeplink = $self->deeplink(undef,'getlisted'); - if (($deeplink) && ($deeplink ne 'absent')) { - $nodeeplinkcheck = 1; - } - $nodeeplinkout = 1; - } + $self->{BROWSE_PRIV} = &Apache::lonnet::allowed('bre',$self->src(), $self->{SYMB},undef, - undef,$noblockcheck, - undef,$nodeeplinkcheck, - $nodeeplinkout); + undef,$noblockcheck); } =pod