Diff for /loncom/interface/lonnavmaps.pm between versions 1.509.2.14 and 1.509.2.14.2.8

version 1.509.2.14, 2021/12/31 23:14:04 version 1.509.2.14.2.8, 2023/05/27 12:40:25
Line 342  user into thinking that if the sequence Line 342  user into thinking that if the sequence
 under it; for example, see the "Show Uncompleted Homework" view on the  under it; for example, see the "Show Uncompleted Homework" view on the
 B<NAV> screen.  B<NAV> screen.
   
 =item * B<suppressNavmaps>: default: false  =item * B<suppressNavmap>: default: false
   
 If true, will not display Navigate Content resources.   If true, will not display Navigate Content resources. 
   
Line 534  my %colormap = Line 534  my %colormap =
       $resObj->EXCUSED                => '#3333FF',        $resObj->EXCUSED                => '#3333FF',
       $resObj->PAST_DUE_ANSWER_LATER  => '',        $resObj->PAST_DUE_ANSWER_LATER  => '',
       $resObj->PAST_DUE_NO_ANSWER     => '',        $resObj->PAST_DUE_NO_ANSWER     => '',
         $resObj->PAST_DUE_ATMPT_ANS     => '',
         $resObj->PAST_DUE_ATMPT_NOANS   => '',
         $resObj->PAST_DUE_NO_ATMT_ANS   => '',
         $resObj->PAST_DUE_NO_ATMT_NOANS => '',
       $resObj->ANSWER_OPEN            => '#006600',        $resObj->ANSWER_OPEN            => '#006600',
       $resObj->OPEN_LATER             => '',        $resObj->OPEN_LATER             => '',
       $resObj->TRIES_LEFT             => '',        $resObj->TRIES_LEFT             => '',
Line 679  sub getDescription { Line 683  sub getDescription {
             return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part).$slotinfo;              return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part).$slotinfo;
         }          }
     }      }
     if ($status == $res->PAST_DUE_ANSWER_LATER) {      if (($status == $res->PAST_DUE_ANSWER_LATER) || ($status == $res->PAST_DUE_ATMPT_ANS) || ($status == $res->PAST_DUE_NO_ATMT_ANS)) {
         return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part));          return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part));
     }      }
     if ($status == $res->PAST_DUE_NO_ANSWER) {      if (($status == $res->PAST_DUE_NO_ANSWER) || ($status == $res->PAST_DUE_ATMPT_NOANS) || ($status == $res->PAST_DUE_NO_ATMT_NOANS)) {
  if ($res->is_practice()) {   if ($res->is_practice()) {
     return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part));      return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part));
  } else {   } else {
Line 945  sub render_resource { Line 949  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 ($nomodal,$linkopen,$linkclose);
     my $nomodal;      unless ($resource->is_map() || $params->{'resource_nolink'}) {
     if (($params->{'modalLink'}) && (!$resource->is_sequence())) {          $linkopen = "<img src='$whitespace' alt='' />";
         if ($link =~m{^(?:|/adm/wrapper)/ext/([^#]+)}) {          $linkclose = "</a>";
             my $exturl = $1;          if (($params->{'modalLink'}) && (!$resource->is_sequence())) {
             if (($ENV{'SERVER_PORT'} == 443) && ($exturl !~ /^https:/)) {              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;                  $nomodal = 1;
             }              }
         } elsif (($link eq "/public/$LONCAPA::match_domain/$LONCAPA::match_courseid/syllabus") &&              my $esclink = &js_escape($link);
                  ($env{'request.course.id'}) && ($ENV{'SERVER_PORT'} == 443) &&              if ($nomodal) {
                  ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {                  $linkopen .= "<a href=\"#\" onclick=\"javascript:window.open('$esclink','resourcepreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1'); return false;\" />";
              $nomodal = 1;              } else {
         }                  $linkopen .= "<a href=\"$link\" onclick=\"javascript:openMyModal('$esclink',600,500,'yes','true'); return false;\">";
         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 {          } else {
             $linkopen .= "<a href=\"$link\" onclick=\"javascript:openMyModal('$esclink',600,500,'yes','true'); return false;\">";              $linkopen .= "<a href=\"$link\">";
         }          }
     } else {  
         $linkopen .= "<a href=\"$link\">";  
     }      }
     my $linkclose = "</a>";  
   
     # Default icon: unknown page      # Default icon: unknown page
     my $icon = "<img class=\"LC_contentImage\" src='$location/unknown.gif' alt='' />";      my $icon = "<img class=\"LC_contentImage\" src='$location/unknown.gif' alt='' />";
Line 995  sub render_resource { Line 1001  sub render_resource {
         if ($it->{CONDITION}) {          if ($it->{CONDITION}) {
             $nowOpen = !$nowOpen;              $nowOpen = !$nowOpen;
         }          }
    my $folderType;
  my $folderType = $resource->is_sequence() ? 'folder' : 'page';   if (&advancedUser() && $resource->is_missing_map()) {
       $folderType = 'none';
    } else {
       $folderType = $resource->is_sequence() ? 'folder' : 'page';
    }
         my $title=$resource->title;          my $title=$resource->title;
  $title=~s/\"/\&qout;/g;   $title=~s/\"/\&qout;/g;
         if (!$params->{'resource_no_folder_link'}) {          if (!$params->{'resource_no_folder_link'}) {
Line 1015  sub render_resource { Line 1025  sub render_resource {
                 '&amp;jump=' .                  '&amp;jump=' .
                 &escape($resource->symb()) .                   &escape($resource->symb()) . 
                 "&amp;folderManip=1\">";                  "&amp;folderManip=1\">";
               $linkclose = '</a>';
         } else {          } else {
             # 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') {              if ($params->{'caller'} eq 'sequence') {
                 $linkopen = "<a href=\"$link\">";                  $linkopen = "<a href=\"$link\">";
                   $linkclose = '</a>';
             } else {              } else {
                 $linkopen = "";                  $linkopen = "";
                 $linkclose = "";                  $linkclose = "";
Line 1040  sub render_resource { Line 1051  sub render_resource {
         }          }
         if ($params->{'mapHidden'} || $resource->randomout()) {          if ($params->{'mapHidden'} || $resource->randomout()) {
             $nonLinkedText .= ' <span class="LC_warning">('.&mt('hidden').')</span> ';              $nonLinkedText .= ' <span class="LC_warning">('.&mt('hidden').')</span> ';
           } elsif ($params->{'mapUnlisted'}) {
               $nonLinkedText .= ' <span class="LC_warning">('.&mt('unlisted').')</span> ';
           } elsif ($params->{'mapHiddenDeepLink'} || $resource->deeplinkout()) {
               $nonLinkedText .= ' <span class="LC_warning">('.&mt('not shown').')</span> ';
         }          }
     } else {      } else {
         if ($resource->randomout()) {          if ($resource->randomout()) {
             $nonLinkedText .= ' <span class="LC_warning">('.&mt('hidden').')</span> ';              $nonLinkedText .= ' <span class="LC_warning">('.&mt('hidden').')</span> ';
           } elsif ($resource->deeplinkout()) {
               $nonLinkedText .= ' <span class="LC_warning">('.&mt('not shown').')</span> ';
           } else {
               my $deeplink = $resource->deeplink($params->{caller});
               if ((($deeplink eq 'absent') || ($deeplink eq 'grades')) &&
                     &advancedUser()) {
                   $nonLinkedText .= ' <span class="LC_warning">('.&mt('unlisted').')</span> ';
               } elsif (($deeplink) && ($deeplink) ne 'full') {
                   if (&advancedUser()) {
                       $nonLinkedText .= ' <span class="LC_warning">('.&mt('deep-link access').
                                         ')</span> ';
                   } else {
                       $nonLinkedText .= ' <span class="LC_warning">('.&mt('access via external site').
                                         ')</span> ';
                   }
               }
         }          }
     }      }
     if (!$resource->condval()) {      if (!$resource->condval()) {
Line 1368  sub render { Line 1399  sub render {
         # an infinite loop          # an infinite loop
         my $oldFilterFunc = $filterFunc;          my $oldFilterFunc = $filterFunc;
         $filterFunc = sub { my $res = shift; return !$res->randomout() &&           $filterFunc = sub { my $res = shift; return !$res->randomout() && 
                                   ($res->deeplink($args->{'caller'}) ne 'absent') &&
                                   ($res->deeplink($args->{'caller'}) ne 'grades') &&
                                   !$res->deeplinkout() &&
                                 &$oldFilterFunc($res);};                                  &$oldFilterFunc($res);};
     }      }
   
     my $condition = 0;      my $condition = 0;
     if ($env{'form.condition'}) {      if ($env{'form.condition'}) {
         $condition = 1;          $condition = 1;
       } elsif (($env{'request.deeplink.login'}) && ($env{'request.course.id'}) && (!$userCanSeeHidden)) {
           if (!defined($navmap)) {
               $navmap = Apache::lonnavmaps::navmap->new();
           }
           if (defined($navmap)) {
               my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
               my $symb = &Apache::loncommon::symb_from_tinyurl($env{'request.deeplink.login'},$cnum,$cdom);
               if ($symb) {
                   my $deeplink;
                   my $res = $navmap->getBySymb($symb);
                   if ($res->is_map()) {
                       my $mapname = &Apache::lonnet::declutter($res->src());
                       $mapname = &Apache::lonnet::deversion($mapname);
                       $deeplink = $navmap->get_mapparam(undef,$mapname,"0.deeplink");
                   } else {
                       $deeplink = $res->deeplink();
                   }
                   if ($deeplink ne '') {
                       if ((split(/,/,$deeplink))[1] eq 'hide') {
                           if ($res->is_map()) {
                               map { $filterHash->{$_} = 1 if $_ } split(/,/,$res->map_hierarchy());
                           } else {
                               my $mapurl = (&Apache::lonnet::decode_symb($symb))[0];
                               my $map = $navmap->getResourceByUrl($mapurl);
                               map { $filterHash->{$_} = 1 if $_ } split(/,/,$map->map_hierarchy());
                           }
                       }
                   }
               }
           }
     }      }
   
     if (!$env{'form.folderManip'} && !defined($args->{'iterator'})) {      if (!$env{'form.folderManip'} && !defined($args->{'iterator'}) && !$args->{'nocurrloc'}) {
         # Step 1: Check to see if we have a navmap          # Step 1: Check to see if we have a navmap
         if (!defined($navmap)) {          if (!defined($navmap)) {
             $navmap = Apache::lonnavmaps::navmap->new();              $navmap = Apache::lonnavmaps::navmap->new();
Line 1415  sub render { Line 1480  sub render {
         my $mapIterator = $navmap->getIterator(undef, undef, undef, 1);          my $mapIterator = $navmap->getIterator(undef, undef, undef, 1);
         my $curRes;          my $curRes;
         my $found = 0;          my $found = 0;
           my $here_is_navmaps = 0;
           if ($here =~ m{___\d+___adm/navmaps$}) {
               $here_is_navmaps = 1;
           }
                   
         # We only need to do this if we need to open the maps to show the          # We only need to do this if we need to open the maps to show the
         # current position. This will change the counter so we can't count          # current position. This will change the counter so we can't count
         # for the jump marker with this loop.          # for the jump marker with this loop.
         while ($here && ($curRes = $mapIterator->next()) && !$found) {          while ($here && ($curRes = $mapIterator->next()) && !$found && !$here_is_navmaps) {
             if (ref($curRes) && $curRes->symb() eq $here) {              if (ref($curRes) && $curRes->symb() eq $here) {
                 my $mapStack = $mapIterator->getStack();                  my $mapStack = $mapIterator->getStack();
                                   
Line 1536  sub render { Line 1605  sub render {
  '&amp;here='.&escape($here);   '&amp;here='.&escape($here);
     $text='Open all folders';      $text='Open all folders';
         }          }
         if ($env{'form.register'}) {  
             $link .= '&amp;register='.$env{'form.register'};  
         }  
  if ($args->{'caller'} eq 'navmapsdisplay') {   if ($args->{'caller'} eq 'navmapsdisplay') {
             unless ($args->{'notools'}) {              unless ($args->{'notools'}) {
                 &add_linkitem($args->{'linkitems'},'changefolder',                  &add_linkitem($args->{'linkitems'},'changefolder',
Line 1562  sub render { Line 1628  sub render {
  <input type="hidden" name="navurl" value="$querystr" />   <input type="hidden" name="navurl" value="$querystr" />
  <input type="hidden" name="navtime" value="$time" />   <input type="hidden" name="navtime" value="$time" />
 END  END
         if ($env{'form.register'}) {  
             $result .= '<input type="hidden" name="register" value="'.$env{'form.register'}.'" />';  
         }  
         if ($args->{'sort'} eq 'discussion') {           if ($args->{'sort'} eq 'discussion') { 
     my $totdisc = 0;      my $totdisc = 0;
     my $haveDisc = '';      my $haveDisc = '';
Line 1585  END Line 1648  END
  }   }
  $result.='</form>';   $result.='</form>';
     }      }
     if (($args->{'caller'} eq 'navmapsdisplay') &&      if (($args->{'caller'} eq 'navmapsdisplay') && ($env{'request.course.id'})) {
         ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) ||  
          (&Apache::lonnet::allowed('cev',$env{'request.course.id'})))) {  
         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
         if ($env{'course.'.$env{'request.course.id'}.'.url'} eq           if ($env{'course.'.$env{'request.course.id'}.'.url'} eq
             "uploaded/$cdom/$cnum/default.sequence") {              "uploaded/$cdom/$cnum/default.sequence") {
             &add_linkitem($args->{'linkitems'},'edittoplevel',              if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) ||
                           "javascript:gocmd('/adm/coursedocs','editdocs');",                  (&Apache::lonnet::allowed('cev',$env{'request.course.id'}))) {
                           'Content Editor');                  &add_linkitem($args->{'linkitems'},'edittoplevel',
                                 "javascript:gocmd('/adm/coursedocs','editdocs');",
                                 'Content Editor');
               }
               if ($counter) {
                   &add_linkitem($args->{'linkitems'},'printout',
                                 "javascript:gopost('/adm/printout','/adm/navmaps');",
                                 'Prepare a printable document');
               }
         }          }
     }      }
   
Line 1640  END Line 1709  END
     # 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.
       #
       # To ensure the "Selected Resources from selected folder in course"
       # printout generation option will work in sessions launched via a
       # deep link, the value of $args->{'filterFunc'} included in the
       # call to lonnavmaps::render() is omitted from the filter function
       # used with the DFS Iterator when $args->{'caller'} is 'printout'.
       #
       # As a result $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} can be
       # set to 1 for folder(s) which include resources only accessible
       # for sessions launched via a deep link, when the current session
       # is of that type.
   
     my $dfsit = Apache::lonnavmaps::DFSiterator->new($navmap,      my $dfsit = Apache::lonnavmaps::DFSiterator->new($navmap,
                                                      $it->{FIRST_RESOURCE},                                                       $it->{FIRST_RESOURCE},
                                                      $it->{FINISH_RESOURCE},                                                       $it->{FINISH_RESOURCE},
                                                      {}, undef, 1);                                                       {}, undef, 1);
   
       my $dfsFilterFunc;
       if ($args->{'caller'} eq 'printout') {
           $dfsFilterFunc = sub { my $res = shift; return !$res->randomout() &&
                                 ($res->deeplink($args->{'caller'}) ne 'absent') &&
                                 ($res->deeplink($args->{'caller'}) ne 'grades') &&
                                 !$res->deeplinkout();};
       } else {
           $dfsFilterFunc = $filterFunc;
       }
     my $depth = 0;      my $depth = 0;
     $dfsit->next();      $dfsit->next();
     my $curRes = $dfsit->next();      my $curRes = $dfsit->next();
Line 1664  END Line 1753  END
             } elsif ($curRes->src()) {              } elsif ($curRes->src()) {
                 # Not a sequence: if it's filtered, ignore it, otherwise                  # Not a sequence: if it's filtered, ignore it, otherwise
                 # rise up the stack and mark the sequences as having children                  # rise up the stack and mark the sequences as having children
                 if (&$filterFunc($curRes)) {                  if (&$dfsFilterFunc($curRes)) {
                     for my $sequence (@{$dfsit->getStack()}) {                      for my $sequence (@{$dfsit->getStack()}) {
                           next unless ($sequence->is_map());
                         $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} = 1;                          $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} = 1;
                     }                      }
                 }                  }
Line 1788  END Line 1878  END
   
         # If this is an empty sequence and we're filtering them, continue on          # If this is an empty sequence and we're filtering them, continue on
         $args->{'mapHidden'} = 0;          $args->{'mapHidden'} = 0;
           $args->{'mapUnlisted'} = 0;
           $args->{'mapHiddenDeepLink'} = 0;
         if (($curRes->is_map()) && (!$curRes->{DATA}->{HAS_VISIBLE_CHILDREN})) {          if (($curRes->is_map()) && (!$curRes->{DATA}->{HAS_VISIBLE_CHILDREN})) {
             if ($args->{'suppressEmptySequences'}) {              if ($args->{'suppressEmptySequences'}) {
                 next;                  next;
Line 1800  END Line 1892  END
                     } else {                      } else {
                         next;                          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;
                           }
                       }
                 }                  }
             }              }
         }          }
Line 1862  END Line 1970  END
     $args->{'condensed'} = 1;      $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 the multipart problem was condensed, "forget" it was multipart
         if (scalar(@parts) == 1) {          if (scalar(@parts) == 1) {
Line 2015  sub show_linkitems_toolbar { Line 2132  sub show_linkitems_toolbar {
             $result .= '<td align="left">'."\n".              $result .= '<td align="left">'."\n".
                        '<ul id="LC_toolbar">';                         '<ul id="LC_toolbar">';
             my @linkorder = ('firsthomework','everything','uncompleted',              my @linkorder = ('firsthomework','everything','uncompleted',
                              'changefolder','clearbubbles','edittoplevel');                               'changefolder','clearbubbles','printout','edittoplevel');
             foreach my $link (@linkorder) {              foreach my $link (@linkorder) {
                 if (ref($args->{'linkitems'}{$link}) eq 'HASH') {                  if (ref($args->{'linkitems'}{$link}) eq 'HASH') {
                     if ($args->{'linkitems'}{$link}{'text'} ne '') {                      if ($args->{'linkitems'}{$link}{'text'} ne '') {
Line 2428  sub getIterator { Line 2545  sub getIterator {
     my $self = shift;      my $self = shift;
     my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift,      my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift,
                                                      shift, undef, shift,                                                       shift, undef, shift,
      shift, shift);       shift, shift, shift);
     return $iterator;      return $iterator;
 }  }
   
Line 2866  sub recursed_crumbs { Line 2983  sub recursed_crumbs {
         my $pc = $map->map_pc();          my $pc = $map->map_pc();
         next if ((!$pc) || ($pc == 1));          next if ((!$pc) || ($pc == 1));
         push(@links,$map);          push(@links,$map);
         push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,});          my $text = $map->title();
         $totallength += length($map->title());          if ($text eq '') {
               $text = '...';
           }
           push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $text,'no_mt' => 1,});
           $totallength += length($text);
     }      }
     my $numlinks = scalar(@links);      my $numlinks = scalar(@links);
     if ($numlinks) {      if ($numlinks) {
Line 2879  sub recursed_crumbs { Line 3000  sub recursed_crumbs {
             }              }
             @revmapinfo = ();              @revmapinfo = ();
             foreach my $map (@links) {              foreach my $map (@links) {
                 my $showntitle = &truncate_crumb_text($map->title(),$avg);                  my $title = $map->title();
                   if ($title eq '') {
                       $title = '...';
                   }
                   my $showntitle = &truncate_crumb_text($title,$avg);
                 if ($showntitle ne '') {                  if ($showntitle ne '') {
                     push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $showntitle,'no_mt' => 1,});                      push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $showntitle,'no_mt' => 1,});
                 }                  }
Line 3394  getIterator behaves as follows: Line 3519  getIterator behaves as follows:
   
 =over 4  =over 4
   
 =item * B<getIterator>(firstResource, finishResource, filterHash, condition, forceTop, returnTopMap):  =item * B<getIterator>(firstResource, finishResource, filterHash, condition, forceTop, returnTopMap, $deeplinklisted):
   
 All parameters are optional. firstResource is a resource reference  All parameters are optional. firstResource is a resource reference
 corresponding to where the iterator should start. It defaults to  corresponding to where the iterator should start. It defaults to
Line 3411  that is not just a single, 'redirecting' Line 3536  that is not just a single, 'redirecting'
 will return all information, starting with the top-level map,  will return all information, starting with the top-level map,
 regardless of content. returnTopMap, if true (default false), will  regardless of content. returnTopMap, if true (default false), will
 cause the iterator to return the top-level map object (resource 0.0)  cause the iterator to return the top-level map object (resource 0.0)
 before anything else.  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().
   
 Thus, by default, only top-level resources will be shown. Change the  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  condition to a 1 without changing the hash, and all resources will be
Line 3548  sub new { Line 3676  sub new {
     # have we done that yet?      # have we done that yet?
     $self->{HAVE_RETURNED_0} = 0;      $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      # 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.      # over the parts of the map we're going to look at.
   
Line 3639  sub new { Line 3771  sub new {
  $finishResource, $self->{FILTER},   $finishResource, $self->{FILTER},
  $self->{ALREADY_SEEN},    $self->{ALREADY_SEEN}, 
  $self->{CONDITION},   $self->{CONDITION},
  $self->{FORCE_TOP});   $self->{FORCE_TOP},
                                                    undef,$self->{DEEPLINKLISTED});
     }      }
   
     # Set up some bookkeeping information.      # Set up some bookkeeping information.
Line 3809  sub next { Line 3942  sub next {
                                               $finishResource, $self->{FILTER},                                                $finishResource, $self->{FILTER},
                                               $self->{ALREADY_SEEN},                                                $self->{ALREADY_SEEN},
       $self->{CONDITION},        $self->{CONDITION},
       $self->{FORCE_TOP});        $self->{FORCE_TOP},
                                                 undef,$self->{DEEPLINKLISTED});
     }      }
   
     # If this is a blank resource, don't actually return it.      # 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      # 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.      #  that you can use; other things depend on this behavior.
     my $browsePriv = $self->{HERE}->browsePriv($noblockcheck);      my $browsePriv = $self->{HERE}->browsePriv($noblockcheck,$self->{DEEPLINKLISTED});
     if (!$self->{HERE}->src() ||       if (!$self->{HERE}->src() || 
         (!($browsePriv eq 'F') && !($browsePriv eq '2')) ) {          (!($browsePriv eq 'F') && !($browsePriv eq '2')) ) {
         return $self->next($closeAllPages);          return $self->next($closeAllPages);
Line 4243  sub from { my $self=shift; return $self- Line 4377  sub from { my $self=shift; return $self-
 sub goesto { my $self=shift; return $self->navHash("goesto_", 1); }  sub goesto { my $self=shift; return $self->navHash("goesto_", 1); }
 sub kind { my $self=shift; return $self->navHash("kind_", 1); }  sub kind { my $self=shift; return $self->navHash("kind_", 1); }
 sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }  sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }
   sub deeplinkout { my $self=shift; return $self->navHash("deeplinkout_", 1); }
 sub randompick {   sub randompick { 
     my $self = shift;      my $self = shift;
     my $randompick = $self->parmval('randompick');      my $randompick = $self->parmval('randompick');
Line 4469  sub is_sequence { Line 4604  sub is_sequence {
     return $self->navHash("is_map_", 1) &&       return $self->navHash("is_map_", 1) && 
     $self->navHash("map_type_" . $self->map_pc()) eq 'sequence';      $self->navHash("map_type_" . $self->map_pc()) eq 'sequence';
 }  }
   sub is_missing_map {
       my $self=shift;
       return $self->navHash("is_map_", 1) &&
       $self->navHash("map_type_" . $self->map_pc()) eq 'none';
   }
 sub is_survey {  sub is_survey {
     my $self = shift();      my $self = shift();
     my $part = shift();      my $part = shift();
Line 4498  sub is_task { Line 4638  sub is_task {
   
 sub is_empty_sequence {  sub is_empty_sequence {
     my $self=shift;      my $self=shift;
     my $src = $self->src();  
     return !$self->is_page() && $self->navHash("is_map_", 1) && !$self->navHash("map_type_" . $self->map_pc());      return !$self->is_page() && $self->navHash("is_map_", 1) && !$self->navHash("map_type_" . $self->map_pc());
 }  }
   
Line 4819  sub duedate { Line 4958  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;
           my $first_access=&Apache::lonnet::get_first_access($interval[1],
                                                           $self->{SYMB});                                                            $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 4917  sub slot_control { Line 5057  sub slot_control {
     my $available = $self->parmval("available", $part);       my $available = $self->parmval("available", $part); 
     return ($useslots,$availablestudent,$available);      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  # Multiple things need this
 sub getReturnHash {  sub getReturnHash {
Line 5322  The problem will be opened later. Line 5502  The problem will be opened later.
   
 Open and not yet due.  Open and not yet due.
   
   
 =item * B<PAST_DUE_ANSWER_LATER>:  =item * B<PAST_DUE_ANSWER_LATER>:
   
 The due date has passed, but the answer date has not yet arrived.  The due date has passed, but the answer date has not yet arrived.
Line 5335  The due date has passed and there is no Line 5514  The due date has passed and there is no
   
 The answer date is here.  The answer date is here.
   
   =item * B<NOTHING_SET>:
   
   No dates have been set for this problem at all.
   
   =item * B<PAST_DUE_ATMPT_ANS>:
   
   The due date has passed, feedback is suppressed, the problem was attempted, and the answer date has not yet arrived.
   
   =item * B<PAST_DUE_ATMPT_NOANS>:
   
   The due date has passed, feedback is suppressed, the problem was attempted, and there is no answer opening date set.
   
   =item * B<PAST_DUE_NO_ATMT_ANS>:
   
   The due date has passed, feedback is suppressed, the problem was not attempted, and the answer date has not yet arrived.
   
   =item * B<PAST_DUE_NO_ATMT_NOANS>:
   
   The due date has passed, feedback is suppressed, the problem was not attempted, and there is no answer opening date set.
   
 =item * B<NETWORK_FAILURE>:  =item * B<NETWORK_FAILURE>:
   
 The information is unknown due to network failure.  The information is unknown due to network failure.
Line 5350  sub PAST_DUE_NO_ANSWER     { return 2; } Line 5549  sub PAST_DUE_NO_ANSWER     { return 2; }
 sub PAST_DUE_ANSWER_LATER  { return 3; }  sub PAST_DUE_ANSWER_LATER  { return 3; }
 sub ANSWER_OPEN            { return 4; }  sub ANSWER_OPEN            { return 4; }
 sub NOTHING_SET            { return 5; }  sub NOTHING_SET            { return 5; }
   sub PAST_DUE_ATMPT_ANS     { return 6; }
   sub PAST_DUE_ATMPT_NOANS   { return 7; }
   sub PAST_DUE_NO_ATMT_ANS   { return 8; }
   sub PAST_DUE_NO_ATMT_NOANS { return 9; }
 sub NETWORK_FAILURE        { return 100; }  sub NETWORK_FAILURE        { return 100; }
   
 # getDateStatus gets the date status for a given problem part.   # getDateStatus gets the date status for a given problem part. 
Line 5539  set. Line 5742  set.
 The problem is past due, not considered correct, and an answer date in  The problem is past due, not considered correct, and an answer date in
 the future is set.  the future is set.
   
   =item * B<PAST_DUE_ATMPT_ANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   attempted and an answer date in the future is set.
   
   =item * B<PAST_DUE_ATMPT_NOANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   attempted and no answer date is set.
   
   =item * B<PAST_DUE_NO_ATMT_ANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   not attempted and an answer date in the future is set.
   
   =item * B<PAST_DUE_NO_ATMT_NOANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   not attempted and no answer date is set.
   
 =item * B<ANSWER_OPEN>:  =item * B<ANSWER_OPEN>:
   
 The problem is past due, not correct, and the answer is now available.  The problem is past due, not correct, and the answer is now available.
Line 5621  sub status { Line 5844  sub status {
     # There are a few whole rows we can dispose of:      # There are a few whole rows we can dispose of:
     if ($completionStatus == CORRECT ||      if ($completionStatus == CORRECT ||
         $completionStatus == CORRECT_BY_OVERRIDE ) {          $completionStatus == CORRECT_BY_OVERRIDE ) {
  if ( $suppressFeedback ) { return ANSWER_SUBMITTED }   if ( $suppressFeedback ) {
               if ($dateStatus == PAST_DUE_ANSWER_LATER ||
                   $dateStatus == PAST_DUE_NO_ANSWER ) {
                   if ($dateStatus == PAST_DUE_ANSWER_LATER) {
                       return PAST_DUE_ATMPT_ANS;
                   } else {
                       return PAST_DUE_ATMPT_NOANS;
                   }
               } else {
                   return ANSWER_SUBMITTED;
               }
           }
  my $awarded=$self->awarded($part);   my $awarded=$self->awarded($part);
  if ($awarded < 1 && $awarded > 0) {   if ($awarded < 1 && $awarded > 0) {
             return PARTIALLY_CORRECT;              return PARTIALLY_CORRECT;
Line 5660  sub status { Line 5894  sub status {
   
     if ($dateStatus == PAST_DUE_ANSWER_LATER ||      if ($dateStatus == PAST_DUE_ANSWER_LATER ||
         $dateStatus == PAST_DUE_NO_ANSWER ) {          $dateStatus == PAST_DUE_NO_ANSWER ) {
         return $suppressFeedback ? ANSWER_SUBMITTED : $dateStatus;           if ($suppressFeedback) {
               if ($completionStatus == NOT_ATTEMPTED) {
                   if ($dateStatus == PAST_DUE_ANSWER_LATER) {
                       return PAST_DUE_NO_ATMT_ANS;
                   } else {
                       return PAST_DUE_NO_ATMT_NOANS;
                   }
               } else {
                   if ($dateStatus == PAST_DUE_ANSWER_LATER) {
                       return PAST_DUE_ATMPT_ANS;
                   } else {
                       return PAST_DUE_ATMPT_NOANS;
                   }
               }
           } else {
               return $dateStatus;
           }
     }      }
   
     if ($dateStatus == ANSWER_OPEN) {      if ($dateStatus == ANSWER_OPEN) {
Line 5870  my %compositeToSimple = Line 6120  my %compositeToSimple =
       EXCUSED()               => CORRECT,        EXCUSED()               => CORRECT,
       PAST_DUE_NO_ANSWER()    => INCORRECT,        PAST_DUE_NO_ANSWER()    => INCORRECT,
       PAST_DUE_ANSWER_LATER() => INCORRECT,        PAST_DUE_ANSWER_LATER() => INCORRECT,
         PAST_DUE_ATMPT_ANS()    => ATTEMPTED,
         PAST_DUE_ATMPT_NOANS()  => ATTEMPTED,
         PAST_DUE_NO_ATMT_ANS()  => CLOSED,
         PAST_DUE_NO_ATMT_NOANS() => CLOSED,
       ANSWER_OPEN()           => INCORRECT,        ANSWER_OPEN()           => INCORRECT,
       OPEN_LATER()            => CLOSED,        OPEN_LATER()            => CLOSED,
       TRIES_LEFT()            => OPEN,        TRIES_LEFT()            => OPEN,
Line 6048  sub getPrevious { Line 6302  sub getPrevious {
 sub browsePriv {  sub browsePriv {
     my $self = shift;      my $self = shift;
     my $noblockcheck = shift;      my $noblockcheck = shift;
       my $deeplinklisted = shift;
     if (defined($self->{BROWSE_PRIV})) {      if (defined($self->{BROWSE_PRIV})) {
         return $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->{BROWSE_PRIV} = &Apache::lonnet::allowed('bre',$self->src(),
     $self->{SYMB},undef,      $self->{SYMB},undef,
                                                     undef,$noblockcheck);                                                      undef,$noblockcheck,
                                                       undef,$nodeeplinkcheck,
                                                       $nodeeplinkout);
 }  }
   
 =pod  =pod

Removed from v.1.509.2.14  
changed lines
  Added in v.1.509.2.14.2.8


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