Diff for /loncom/interface/lonnavmaps.pm between versions 1.509.2.8 and 1.534

version 1.509.2.8, 2018/09/14 15:58:37 version 1.534, 2017/09/03 18:52:27
Line 2 Line 2
 # Navigate Maps Handler  # Navigate Maps Handler
 #  #
 # $Id$  # $Id$
   
 #  #
 # Copyright Michigan State University Board of Trustees  # Copyright Michigan State University Board of Trustees
 #  #
Line 52  described at http://www.lon-capa.org. Line 51  described at http://www.lon-capa.org.
 X<lonnavmaps, overview> When a user enters a course, LON-CAPA examines the  X<lonnavmaps, overview> When a user enters a course, LON-CAPA examines the
 course structure and caches it in what is often referred to as the  course structure and caches it in what is often referred to as the
 "big hash" X<big hash>. You can see it if you are logged into  "big hash" X<big hash>. You can see it if you are logged into
 LON-CAPA, in a course, by going to /adm/test. (You may need to  LON-CAPA, in a course, by going to /adm/test. The content of 
 tweak the /home/httpd/lonTabs/htpasswd file to view it.) The  the hash will be under the heading "Big Hash".
 content of the hash will be under the heading "Big Hash".  
   Access to /adm/test is controlled by a domain configuration, 
   which a Domain Coordinator will set for a server's default domain
   via: Main Menu > Set domain configuration > Display (Access to 
   server status pages checked), and entering a username:domain
   or IP address in the "Show user environment" row. Users with
   an unexpired domain coordinator role in the server's domain
   automatically receive access to /adm/test.
   
 Big Hash contains, among other things, how resources are related  Big Hash contains, among other things, how resources are related
 to each other (next/previous), what resources are maps, which   to each other (next/previous), what resources are maps, which 
Line 78  Apache::lonnavmaps also provides fairly Line 84  Apache::lonnavmaps also provides fairly
 rendering navmaps, and last but not least, provides the navmaps  rendering navmaps, and last but not least, provides the navmaps
 view for when the user clicks the NAV button.  view for when the user clicks the NAV button.
   
 B<Note>: Apache::lonnavmaps I<only> works for the "currently  B<Note>: Apache::lonnavmaps by default will show information 
 logged in user"; if you want things like "due dates for another  for the "currently logged in user".  However, if information
 student" lonnavmaps can not directly retrieve information like  about resources is needed for a different user, e.g., a bubblesheet
 that. You need the EXT function. This module can still help,  exam which uses randomorder, or randompick needs to be printed or 
 because many things, such as the course structure, are constant  graded for named user(s) or specific CODEs, then the username,
   domain, or CODE can be passed as arguments when creating a new 
   navmap object.
   
   Note if you want things like "due dates for another student,
   you would use the EXT function instead of lonnavmaps.
   That said, the lonnavmaps module can still help, because many
   things, such as the course structure, are usually constant
 between users, and Apache::lonnavmaps can help by providing  between users, and Apache::lonnavmaps can help by providing
 symbs for the EXT call.  symbs for the EXT call.
   
Line 92  all, then documents the Apache::lonnavma Line 105  all, then documents the Apache::lonnavma
 is the key to accessing the Big Hash information, covers the use  is the key to accessing the Big Hash information, covers the use
 of the Iterator (which provides the logic for traversing the   of the Iterator (which provides the logic for traversing the 
 somewhat-complicated Big Hash data structure), documents the  somewhat-complicated Big Hash data structure), documents the
 Apache::lonnavmaps::Resource objects that are returned by   Apache::lonnavmaps::Resource objects that are returned singularly
   by: getBySymb(), getById(), getByMapPc(), and getResourceByUrl()
   (can also be as an array), or in an array by retrieveResources().
   
 =head1 Subroutine: render  =head1 Subroutine: render
   
Line 643  sub getDescription { Line 658  sub getDescription {
             } elsif ($slot_status == $res->RESERVABLE) {              } elsif ($slot_status == $res->RESERVABLE) {
                 $slotmsg = &mt('Reservable, reservations close [_1]',                  $slotmsg = &mt('Reservable, reservations close [_1]',
                            timeToHumanString($slot_time,'end'));                             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) {              } elsif ($slot_status == $res->RESERVABLE_LATER) {
                 $slotmsg = &mt('Reservable, reservations open [_1]',                  $slotmsg = &mt('Reservable, reservations open [_1]',
                            timeToHumanString($slot_time,'start'));                             timeToHumanString($slot_time,'start'));
Line 941  sub render_resource { Line 953  sub render_resource {
     # links to open and close the folder      # links to open and close the folder
   
     my $whitespace = $location.'/whitespace_21.gif';      my $whitespace = $location.'/whitespace_21.gif';
     my $linkopen = "<img src='$whitespace' alt='' />";      my $linkopen = "<img src='$whitespace' alt='' />"."<a href=\"$link\">";
     my $nomodal;  
     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 .= "<a href=\"#\" onclick=\"javascript:window.open('$esclink','resourcepreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1'); return false;\" />";  
         } else {  
             $linkopen .= "<a href=\"$link\" onclick=\"javascript:openMyModal('$esclink',600,500,'yes','true'); return false;\">";  
         }  
     } else {  
         $linkopen .= "<a href=\"$link\">";  
     }  
     my $linkclose = "</a>";      my $linkclose = "</a>";
   
     # Default icon: unknown page      # Default icon: unknown page
Line 1016  sub render_resource { Line 1007  sub render_resource {
             # Don't allow users to manipulate folder              # Don't allow users to manipulate folder
             $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';
             $icon = "<img class=\"LC_space\" src='$whitespace' alt='' />"."<img class=\"LC_contentImage\" src='$location/$icon' alt=\"".($nowOpen ? &mt('Open Folder') : &mt('Close Folder')).' '.$title."\" />";              $icon = "<img class=\"LC_space\" src='$whitespace' alt='' />"."<img class=\"LC_contentImage\" src='$location/$icon' alt=\"".($nowOpen ? &mt('Open Folder') : &mt('Close Folder')).' '.$title."\" />";
               if ($params->{'caller'} eq 'sequence') {
             $linkopen = "";                  $linkopen = "<a href=\"$link\">";
             $linkclose = "";              } else {
                   $linkopen = "";
                   $linkclose = "";
               }
         }          }
         if (((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) ||          if (((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) ||
              (&Apache::lonnet::allowed('cev',$env{'request.course.id'}))) &&                (&Apache::lonnet::allowed('cev',$env{'request.course.id'}))) &&
             ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) {              ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) {
             if (!$params->{'map_no_edit_link'}) {              if (!$params->{'map_no_edit_link'}) {
                 my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png';                  my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png';
Line 1087  sub render_resource { Line 1081  sub render_resource {
     }      }
   
     if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {      if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {
         $linkclose = '</a>';          $result .= "$curMarkerBegin<a href=\"$link\">$title$partLabel</a>$curMarkerEnd$editmapLink$nonLinkedText</td>";
         if ($params->{'modalLink'}) {      } else {
             my $esclink = &js_escape($link);          $result .= "$curMarkerBegin$linkopen$title$partLabel</a>$curMarkerEnd$editmapLink$nonLinkedText</td>";
             if ($nomodal) {  
                 $linkopen = "<a href=\"#\" onclick=\"javascript:window.open('$esclink','resourcepreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1'); return false;\" />";  
             } else {  
                 $linkopen = "<a href=\"$link\" onclick=\"javascript:openMyModal('$esclink',600,500,'yes','true'); return false;\">";  
             }  
         } else {  
             $linkopen = "<a href=\"$link\">";  
         }  
     }      }
     $result .= "$curMarkerBegin$linkopen$title$partLabel$linkclose$curMarkerEnd$editmapLink$nonLinkedText</td>";  
   
     return $result;      return $result;
 }  }
Line 1390  sub render { Line 1375  sub render {
             my $currenturl = $env{'form.postdata'};              my $currenturl = $env{'form.postdata'};
             #$currenturl=~s/^http\:\/\///;              #$currenturl=~s/^http\:\/\///;
             #$currenturl=~s/^[^\/]+//;              #$currenturl=~s/^[^\/]+//;
                           unless ($args->{'caller'} eq 'sequence') {
             $here = $jump = &Apache::lonnet::symbread($currenturl);                  $here = $jump = &Apache::lonnet::symbread($currenturl);
               }
  }   }
  if ($here eq '') {   if (($here eq '') && ($args->{'caller'} ne 'sequence')) {
     my $last;      my $last;
     if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',      if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                     &GDBM_READER(),0640)) {                      &GDBM_READER(),0640)) {
Line 1626  END Line 1612  END
     # We also do this even if $args->{'suppressEmptySequences'}      # We also do this even if $args->{'suppressEmptySequences'}
     # is not true, so we can hide empty sequences for which the      # is not true, so we can hide empty sequences for which the
     # hiddenresource parameter is set to yes (at map level), or      # 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,      # Use DFS for speed, since structure actually doesn't matter,
     # except what map has what resources.      # except what map has what resources.
   
Line 1634  END Line 1620  END
                                                      $it->{FIRST_RESOURCE},                                                       $it->{FIRST_RESOURCE},
                                                      $it->{FINISH_RESOURCE},                                                       $it->{FINISH_RESOURCE},
                                                      {}, undef, 1);                                                       {}, undef, 1);
   
     my $depth = 0;      my $depth = 0;
     $dfsit->next();      $dfsit->next();
     my $curRes = $dfsit->next();      my $curRes = $dfsit->next();
Line 1642  END Line 1627  END
         if ($curRes == $dfsit->BEGIN_MAP()) { $depth++; }          if ($curRes == $dfsit->BEGIN_MAP()) { $depth++; }
         if ($curRes == $dfsit->END_MAP()) { $depth--; }          if ($curRes == $dfsit->END_MAP()) { $depth--; }
   
         if (ref($curRes)) {          if (ref($curRes)) { 
             # Parallel pre-processing: Do sequences have non-filtered-out children?              # Parallel pre-processing: Do sequences have non-filtered-out children?
             if ($curRes->is_map()) {              if ($curRes->is_map()) {
                 $curRes->{DATA}->{HAS_VISIBLE_CHILDREN} = 0;                  $curRes->{DATA}->{HAS_VISIBLE_CHILDREN} = 0;
Line 1719  END Line 1704  END
  undef($args->{'sort'});   undef($args->{'sort'});
     }      }
   
       # Determine if page will be served with https in case
     my $inhibitmenu;      # it contains a syllabus which uses an external URL
     if ($args->{'modalLink'}) {      # which points at an http site.
         $inhibitmenu = '&amp;inhibitmenu=yes';  
       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'};
     }      }
   
     while (1) {      while (1) {
Line 1765  END Line 1762  END
                 next;                  next;
             } else {              } else {
                 my $mapname = &Apache::lonnet::declutter($curRes->src());                  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 (lc($navmap->get_mapparam(undef,$mapname,"0.hiddenresource")) eq 'yes') {
                     if ($userCanSeeHidden) {                      if ($userCanSeeHidden) {
                         $args->{'mapHidden'} = 1;                          $args->{'mapHidden'} = 1;
Line 1857  END Line 1854  END
  $stack=$it->getStack();   $stack=$it->getStack();
     }      }
     ($src,$symb,$anchor)=getLinkForResource($stack);      ($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://})) {
                       if ($hostname ne '') {
                           $src = 'http://'.$hostname.$src;
                       }
                       $src .= ($srcHasQuestion? '&amp;' : '?') . 'usehttp=1';
                       $srcHasQuestion = 1;
                   } elsif (($is_ssl) && ($src =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) {
                       if ($hostname ne '') {
                           $src = 'http://'.$hostname.$src;
                       }
                   }
               }
     if (defined($anchor)) { $anchor='#'.$anchor; }      if (defined($anchor)) { $anchor='#'.$anchor; }
     my $srcHasQuestion = $src =~ /\?/;      if (($args->{'caller'} eq 'sequence') && ($curRes->is_map())) {
     $args->{"resourceLink"} = $src.          $args->{"resourceLink"} = $src.($srcHasQuestion?'&amp;':'?') .'navmap=1';
  ($srcHasQuestion?'&amp;':'?') .      } else {
  'symb=' . &escape($symb).$inhibitmenu.$anchor;          $args->{"resourceLink"} = $src.
       ($srcHasQuestion?'&amp;':'?') .
       'symb=' . &escape($symb).$anchor;
       }
  }   }
         # Now, we've decided what parts to show. Loop through them and          # Now, we've decided what parts to show. Loop through them and
         # show them.          # show them.
Line 2182  sub change_user { Line 2197  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.      # param.xxxx keys.
   
     $self->{PARM_CACHE} = {};      $self->{PARM_CACHE} = {};
Line 2275  sub generate_email_discuss_status { Line 2290  sub generate_email_discuss_status {
     foreach my $msgid (@keys) {      foreach my $msgid (@keys) {
  if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) {   if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) {
             my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid,              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);               &Apache::lonenc::check_decrypt(\$symb); 
             if (($fromcid ne '') && ($fromcid ne $cid)) {              if (($fromcid ne '') && ($fromcid ne $cid)) {
                 next;                  next;
Line 2647  sub parmval { Line 2662  sub parmval {
             return $self->{PARM_CACHE}->{$hashkey};              return $self->{PARM_CACHE}->{$hashkey};
         }          }
     }      }
   
     my $result = $self->parmval_real($what, $symb, $recurse);      my $result = $self->parmval_real($what, $symb, $recurse);
     $self->{PARM_CACHE}->{$hashkey} = $result;      $self->{PARM_CACHE}->{$hashkey} = $result;
     if (wantarray) {      if (wantarray) {
Line 2680  sub parmval_real { Line 2696  sub parmval_real {
   
     my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb);      my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb);
     $mapname = &Apache::lonnet::deversion($mapname);      $mapname = &Apache::lonnet::deversion($mapname);
       my ($recursed,@recurseup); 
       
 # ----------------------------------------------------- Cascading lookup scheme  # ----------------------------------------------------- Cascading lookup scheme
     my $rwhat=$what;      my $rwhat=$what;
     $what=~s/^parameter\_//;      $what=~s/^parameter\_//;
     $what=~s/\_/\./;      $what=~s/\_/\./;
   
     my $symbparm=$symb.'.'.$what;      my $symbparm=$symb.'.'.$what;
       my $recurseparm=$mapname.'___(rec).'.$what;
     my $mapparm=$mapname.'___(all).'.$what;      my $mapparm=$mapname.'___(all).'.$what;
     my $usercourseprefix=$cid;      my $usercourseprefix=$cid;
       
   
   
     my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what;      my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what;
     my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm;      my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm;
       my $grpleveli=$usercourseprefix.'.['.$cgroup.'].'.$recurseparm;
     my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm;      my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm;
   
   
     my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what;      my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what;
     my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm;      my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm;
       my $secleveli=$usercourseprefix.'.['.$csec.'].'.$recurseparm;
     my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm;      my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm;
   
   
     my $courselevel= $usercourseprefix.'.'.$what;      my $courselevel= $usercourseprefix.'.'.$what;
     my $courselevelr=$usercourseprefix.'.'.$symbparm;      my $courselevelr=$usercourseprefix.'.'.$symbparm;
       my $courseleveli=$usercourseprefix.'.'.$recurseparm;
     my $courselevelm=$usercourseprefix.'.'.$mapparm;      my $courselevelm=$usercourseprefix.'.'.$mapparm;
   
   
Line 2714  sub parmval_real { Line 2736  sub parmval_real {
     if ($uname and defined($useropt)) {      if ($uname and defined($useropt)) {
         if (defined($$useropt{$courselevelr})) { return [$$useropt{$courselevelr},'resource']; }          if (defined($$useropt{$courselevelr})) { return [$$useropt{$courselevelr},'resource']; }
         if (defined($$useropt{$courselevelm})) { return [$$useropt{$courselevelm},'map']; }          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;
               if (defined($$useropt{$norecursechk})) {
                   if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return [$$useropt{$norecursechk},'map'];
                   } else {
                       last;
                   }
               }
               my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what;
               if (defined($$useropt{$recursechk})) { return [$$useropt{$recursechk},'map']; } 
           }
         if (defined($$useropt{$courselevel})) { return [$$useropt{$courselevel},'course']; }          if (defined($$useropt{$courselevel})) { return [$$useropt{$courselevel},'course']; }
     }      }
   
Line 2721  sub parmval_real { Line 2760  sub parmval_real {
     if ($cgroup ne '' and defined($courseopt)) {      if ($cgroup ne '' and defined($courseopt)) {
         if (defined($$courseopt{$grplevelr})) { return [$$courseopt{$grplevelr},'resource']; }          if (defined($$courseopt{$grplevelr})) { return [$$courseopt{$grplevelr},'resource']; }
         if (defined($$courseopt{$grplevelm})) { return [$$courseopt{$grplevelm},'map']; }          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;
               if (defined($$courseopt{$norecursechk})) {
                   if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return [$$courseopt{$norecursechk},'map'];
                   } else {
                      last;
                   }
               }
               my $recursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(rec).'.$what;
               if (defined($$courseopt{$recursechk})) { return [$$courseopt{$recursechk},'map']; }      
           }
         if (defined($$courseopt{$grplevel})) { return [$$courseopt{$grplevel},'course']; }          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{$seclevelr})) { return [$$courseopt{$seclevelr},'resource']; }
         if (defined($$courseopt{$seclevelm})) { return [$$courseopt{$seclevelm},'map']; }          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;
               if (defined($$courseopt{$norecursechk})) {
                   if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return [$$courseopt{$norecursechk},'map'];
                   } else {
                       last;
                   }
               }
               my $recursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(rec).'.$what;
               if (defined($$courseopt{$recursechk})) { return [$$courseopt{$recursechk},'map']; }
           }
         if (defined($$courseopt{$seclevel})) { return [$$courseopt{$seclevel},'course']; }          if (defined($$courseopt{$seclevel})) { return [$$courseopt{$seclevel},'course']; }
     }      }
   
Line 2750  sub parmval_real { Line 2823  sub parmval_real {
 # --------------------------------------------------- fifth, check more course  # --------------------------------------------------- fifth, check more course
     if (defined($courseopt)) {      if (defined($courseopt)) {
         if (defined($$courseopt{$courselevelm})) { return [$$courseopt{$courselevelm},'map']; }          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;
               if (defined($$courseopt{$norecursechk})) {
                   if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return [$$courseopt{$norecursechk},'map'];
                   } else {
                       last;
                   }
               }
               my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what;
               if (defined($$courseopt{$recursechk})) {
                   return [$$courseopt{$recursechk},'map'];
               }
           }
         if (defined($$courseopt{$courselevel})) {          if (defined($$courseopt{$courselevel})) {
            my $ret = [$$courseopt{$courselevel},'course'];             my $ret = [$$courseopt{$courselevel},'course'];
            return $ret;             return $ret;
Line 2789  sub recurseup_maps { Line 2881  sub recurseup_maps {
     return @recurseup;      return @recurseup;
 }  }
   
   sub recursed_crumbs {
       my ($self,$mapurl) = @_;
       my (@revmapinfo,@revmapres);
       my $mapres = $self->getResourceByUrl($mapurl);
       if (ref($mapres)) {
           @revmapres = map { $self->getByMapPc($_); } split(/,/,$mapres->map_breadcrumbs());
           shift(@revmapres);
       }
       foreach my $map (@revmapres) {
           my $pc = $map->map_pc();
           next if ((!$pc) || ($pc == 1));
           push(@revmapinfo,{'href' => $map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,});
       }
       return @revmapinfo;
   }
   
 #  #
 #  Determines the open/close dates for printing a map that  #  Determines the open/close dates for printing a map that
 #  encloses a resource.  #  encloses a resource.
Line 2801  sub map_printdates { Line 2909  sub map_printdates {
   
   
     my $opendate = $self->get_mapparam($res->symb(),'',"$part.printstartdate");      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);      return ($opendate, $closedate);
Line 2831  sub get_mapparam { Line 2939  sub get_mapparam {
     my $result='';      my $result='';
     my ($recursed,@recurseup);      my ($recursed,@recurseup);
   
   
     # Figure out which map we are in.      # Figure out which map we are in.
   
     if ($symb && !$mapname) {      if ($symb && !$mapname) {
Line 2839  sub get_mapparam { Line 2948  sub get_mapparam {
         $mapname = &Apache::lonnet::deversion($mapname);          $mapname = &Apache::lonnet::deversion($mapname);
     }      }
   
   
     my $rwhat=$what;      my $rwhat=$what;
     $what=~s/^parameter\_//;      $what=~s/^parameter\_//;
     $what=~s/\_/\./;      $what=~s/\_/\./;
   
     # Build the hash keys for the lookup:      # Build the hash keys for the lookup:
   
     my $symbparm=$symb.'.'.$what;  
     my $mapparm=$mapname.'___(all).'.$what;      my $mapparm=$mapname.'___(all).'.$what;
       my $recurseparm=$mapname.'___(rec).'.$what; 
     my $usercourseprefix=$cid;      my $usercourseprefix=$cid;
   
   
     my $grplevel    = "$usercourseprefix.[$cgroup].$mapparm";      my $grplevelm    = "$usercourseprefix.[$cgroup].$mapparm";
     my $seclevel    = "$usercourseprefix.[$csec].$mapparm";      my $seclevelm    = "$usercourseprefix.[$csec].$mapparm";
     my $courselevel = "$usercourseprefix.$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:      # Get handy references to the hashes we need in $self:
   
Line 2866  sub get_mapparam { Line 2979  sub get_mapparam {
   
   
     if ($uname and defined($useropt)) {      if ($uname and defined($useropt)) {
  if (defined($$useropt{$courselevel})) {   if (defined($$useropt{$courselevelm})) {
     return $$useropt{$courselevel};      return $$useropt{$courselevelm};
  }   }
         if ($what =~ /\.(encrypturl|hiddenresource)$/) {          if (defined($$useropt{$courseleveli})) {
             unless ($recursed) {              return $$useropt{$courseleveli};
                 @recurseup = $self->recurseup_maps($mapname);          }
                 $recursed = 1;          unless ($recursed) {
             }              @recurseup = $self->recurseup_maps($mapname);
             foreach my $item (@recurseup) {              $recursed = 1;
                 my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what;          }
                 if (defined($$useropt{$norecursechk})) {          foreach my $item (@recurseup) {
                     if ($what =~ /\.(encrypturl|hiddenresource)$/) {              my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what;
                         return $$useropt{$norecursechk};              if (defined($$useropt{$norecursechk})) {
                     }                  if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return $$useropt{$norecursechk};
                   } else {
                       last;
                 }                  }
             }              }
               my $recursechk=$usercourseprefix.'.'.$item.'___(rec).'.$what;
               if (defined($$useropt{$recursechk})) {
                   return $$useropt{$recursechk};
               }
         }          }
     }      }
   
Line 2890  sub get_mapparam { Line 3010  sub get_mapparam {
   
   
     if ($cgroup ne '' and defined ($courseopt)) {      if ($cgroup ne '' and defined ($courseopt)) {
  if (defined($$courseopt{$grplevel})) {   if (defined($$courseopt{$grplevelm})) {
     return $$courseopt{$grplevel};      return $$courseopt{$grplevelm};
  }   }
         if ($what =~ /\.(encrypturl|hiddenresource)$/) {          if (defined($$courseopt{$grpleveli})) {
             unless ($recursed) {              return $$courseopt{$grpleveli};
                 @recurseup = $self->recurseup_maps($mapname);          }
                 $recursed = 1;          unless ($recursed) {
             }              @recurseup = $self->recurseup_maps($mapname);
             foreach my $item (@recurseup) {              $recursed = 1;
                 my $norecursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(all).'.$what;          }
                 if (defined($$courseopt{$norecursechk})) {          foreach my $item (@recurseup) {
                     if ($what =~ /\.(encrypturl|hiddenresource)$/) {              my $norecursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(all).'.$what;
                         return $$courseopt{$norecursechk};              if (defined($$courseopt{$norecursechk})) {
                     }                  if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return $$courseopt{$norecursechk};
                   } else {
                       last;
                 }                  }
             }              }
               my $recursechk=$usercourseprefix.'.['.$cgroup.'].'.$item.'___(rec).'.$what;
               if (defined($$courseopt{$recursechk})) {
                   return $$courseopt{$recursechk};
               }
         }          }
     }      }
   
     # Check course -- section      # Check course -- section
   
   
       if ($csec ne '' and defined($courseopt)) {
    if (defined($$courseopt{$seclevelm})) {
       return $$courseopt{$seclevelm};
     if ($csec and defined($courseopt)) {  
  if (defined($$courseopt{$seclevel})) {  
     return $$courseopt{$seclevel};  
  }   }
         if ($what =~ /\.(encrypturl|hiddenresource)$/) {          if (defined($$courseopt{$secleveli})) {
             unless ($recursed) {              return $$courseopt{$secleveli};
                 @recurseup = $self->recurseup_maps($mapname);          }
                 $recursed = 1;          unless ($recursed) {
             }              @recurseup = $self->recurseup_maps($mapname);
             foreach my $item (@recurseup) {              $recursed = 1;
                 my $norecursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(all).'.$what;          }
                 if (defined($$courseopt{$norecursechk})) {          foreach my $item (@recurseup) {
                     if ($what =~ /\.(encrypturl|hiddenresource)$/) {              my $norecursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(all).'.$what;
                         return $$courseopt{$norecursechk};              if (defined($$courseopt{$norecursechk})) {
                     }                  if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                       return $$courseopt{$norecursechk};
                   } else {
                       last;
                 }                  }
             }              }
               my $recursechk=$usercourseprefix.'.['.$csec.'].'.$item.'___(rec).'.$what;
               if (defined($$courseopt{$recursechk})) {
                   return $$courseopt{$recursechk};
               }
         }          }
     }      }
     # Check the map parameters themselves:      # Check the map parameters themselves:
Line 2940  sub get_mapparam { Line 3071  sub get_mapparam {
         my $symbparm=$symb.'.'.$what;          my $symbparm=$symb.'.'.$what;
         my $thisparm = $$parmhash{$symbparm};          my $thisparm = $$parmhash{$symbparm};
         if (defined($thisparm)) {          if (defined($thisparm)) {
             return $thisparm;      return $thisparm;
         }          }
     }      }
   
Line 2948  sub get_mapparam { Line 3079  sub get_mapparam {
     # Additional course parameters:      # Additional course parameters:
   
     if (defined($courseopt)) {      if (defined($courseopt)) {
  if (defined($$courseopt{$courselevel})) {   if (defined($$courseopt{$courselevelm})) {
     return $$courseopt{$courselevel};      return $$courseopt{$courselevelm};
  }   }
         if ($what =~ /\.(encrypturl|hiddenresource)$/) {          unless ($recursed) {
             unless ($recursed) {              @recurseup = $self->recurseup_maps($mapname);
                 @recurseup = $self->recurseup_maps($mapname);              $recursed = 1;
                 $recursed = 1;          }
             }          if (@recurseup) {
             foreach my $item (@recurseup) {              foreach my $item (@recurseup) {
                 my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what;                  my $norecursechk=$usercourseprefix.'.'.$item.'___(all).'.$what;
                 if (defined($$courseopt{$norecursechk})) {                  if (defined($$courseopt{$norecursechk})) {
                     if ($what =~ /\.(encrypturl|hiddenresource)$/) {                      if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                         return $$courseopt{$norecursechk};                          return $$courseopt{$norecursechk};
                       } else {
                           last;
                     }                      }
                 }                  }
                   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 {  sub course_printdates {
Line 3008  sub getcourseparam { Line 3145  sub getcourseparam {
     $what=~s/^parameter\_//;      $what=~s/^parameter\_//;
     $what=~s/\_/\./;      $what=~s/\_/\./;
   
   
     my $symbparm = $symb . '.' . $what;  
     my $mapparm=$mapname.'___(all).'.$what;  
   
     # Local refs to the hashes we're going to look at:      # Local refs to the hashes we're going to look at:
   
     my $useropt   = $self->{USER_OPT};      my $useropt   = $self->{USER_OPT};
Line 4014  sub new { Line 4147  sub new {
           
     # This is a speed optimization, to avoid calling symb() too often.      # This is a speed optimization, to avoid calling symb() too often.
     $self->{SYMB} = $self->symb();      $self->{SYMB} = $self->symb();
      
     return $self;      return $self;
 }  }
   
Line 4140  sub enclosing_map_src { Line 4273  sub enclosing_map_src {
 }  }
 sub symb {  sub symb {
     my $self=shift;      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 $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/;
     my $symbSrc = &Apache::lonnet::declutter($self->src());      my $symbSrc = &Apache::lonnet::declutter($self->src());
     my $symb = &Apache::lonnet::declutter($self->navHash('map_id_'.$first))       my $symb = &Apache::lonnet::declutter($self->navHash('map_id_'.$first)) 
Line 4411  Returns a string with a comma-separated Line 4544  Returns a string with a comma-separated
 for the hierarchy of maps containing a map, with the top level  for the hierarchy of maps containing a map, with the top level
 map first, then descending to deeper levels, with the enclosing map last.  map first, then descending to deeper levels, with the enclosing map last.
   
   =item * B<map_breadcrumbs>:
   
   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  =back
   
 =cut  =cut
Line 4446  sub map_hierarchy { Line 4585  sub map_hierarchy {
     my $pc = $self->map_pc();      my $pc = $self->map_pc();
     return $self->navHash("map_hierarchy_$pc", 0);      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  # Property queries
Line 4670  sub duedate { Line 4814  sub duedate {
     my $date;      my $date;
     my @interval=$self->parmval("interval", $part);      my @interval=$self->parmval("interval", $part);
     my $due_date=$self->parmval("duedate", $part);      my $due_date=$self->parmval("duedate", $part);
     if ($interval[0] =~ /\d+/) {      if ($interval[0] =~ /^(\d+)/) {
        my $first_access=&Apache::lonnet::get_first_access($interval[1],          my $timelimit = $1;
                                                           $self->{SYMB});          my $first_access=&Apache::lonnet::get_first_access($interval[1],
                                                              $self->{SYMB});
  if (defined($first_access)) {   if (defined($first_access)) {
            my $interval = $first_access+$interval[0];              my $interval = $first_access+$timelimit;
     $date = (!$due_date || $interval < $due_date) ? $interval       $date = (!$due_date || $interval < $due_date) ? $interval 
                                                           : $due_date;                                                            : $due_date;
  } else {   } else {
Line 4774  sub getReturnHash { Line 4919  sub getReturnHash {
     my $self = shift;      my $self = shift;
           
     if (!defined($self->{RETURN_HASH})) {      if (!defined($self->{RETURN_HASH})) {
         my %tmpHash  = &Apache::lonnet::restore($self->{SYMB},undef,$self->{DOMAIN},$self->{USERNAME});          #my %tmpHash  = &Apache::lonnet::restore($self->{SYMB},undef,$self->{DOMAIN},$self->{USERNAME});
         $self->{RETURN_HASH} = \%tmpHash;          #$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}};
     }      }
 }         }       
   
Line 5006  sub extractParts { Line 5157  sub extractParts {
     my %parts;      my %parts;
   
     # Retrieve part count, if this is a problem      # Retrieve part count, if this is a problem
     if ($self->is_problem()) {      if ($self->is_raw_problem()) {
  my $partorder = &Apache::lonnet::metadata($self->src(), 'partorder');   my $partorder = &Apache::lonnet::metadata($self->src(), 'partorder');
         my $metadata = &Apache::lonnet::metadata($self->src(), 'packages');          my $metadata = &Apache::lonnet::metadata($self->src(), 'packages');
   
Line 5580  sub check_for_slot { Line 5731  sub check_for_slot {
                                 ($checkedin,$checkedinslot) = $self->checkedin();                                  ($checkedin,$checkedinslot) = $self->checkedin();
                                 unless ((grep(/^\Q$checkedin\E/,@proctors)) &&                                  unless ((grep(/^\Q$checkedin\E/,@proctors)) &&
                                         ($checkedinslot eq $slot_name)) {                                          ($checkedinslot eq $slot_name)) {
                                     return (NEEDS_CHECKIN,$end,$slot_name);                                       return (NEEDS_CHECKIN,undef,$slot_name); 
                                 }                                  }
                             }                              }
                             return (RESERVED,$end,$slot_name);                              return (RESERVED,$end,$slot_name);
Line 5626  sub check_for_slot { Line 5777  sub check_for_slot {
         my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'},          my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'},
                                                                $env{'user.domain'});                                                                 $env{'user.domain'});
         if (ref($reservable) eq 'HASH') {          if (ref($reservable) eq 'HASH') {
               my ($map) = &Apache::lonnet::decode_symb($symb);
             if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) {              if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) {
                 foreach my $slot (reverse (@{$reservable->{'now_order'}})) {                  foreach my $slot (reverse (@{$reservable->{'now_order'}})) {
                     my $canuse;                      my $canuse;
                     if (($reservable->{'now'}{$slot}{'symb'} eq '') ||                      if ($reservable->{'now'}{$slot}{'symb'} eq '') {
                         ($reservable->{'now'}{$slot}{'symb'} eq $symb)) {  
                         $canuse = 1;                          $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 ($canuse) {
                         if ($checkedin) {                          if ($checkedin) {
Line 5652  sub check_for_slot { Line 5820  sub check_for_slot {
             if ((ref($reservable->{'future_order'}) eq 'ARRAY') && (ref($reservable->{'future'}) eq 'HASH')) {              if ((ref($reservable->{'future_order'}) eq 'ARRAY') && (ref($reservable->{'future'}) eq 'HASH')) {
                 foreach my $slot (@{$reservable->{'future_order'}}) {                  foreach my $slot (@{$reservable->{'future_order'}}) {
                     my $canuse;                      my $canuse;
                     if (($reservable->{'future'}{$slot}{'symb'} eq '') ||                      if ($reservable->{'future'}{$slot}{'symb'} eq '') {
                         ($reservable->{'future'}{$slot}{'symb'} eq $symb)) {                          $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;                          $canuse = 1;
                     }                      }
                     if ($canuse) {                      if ($canuse) {

Removed from v.1.509.2.8  
changed lines
  Added in v.1.534


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>