Diff for /loncom/interface/lonnavmaps.pm between versions 1.509.2.14.2.12 and 1.509.2.16

version 1.509.2.14.2.12, 2025/05/28 13:42:14 version 1.509.2.16, 2024/07/02 15:53:16
Line 695  sub getDescription { Line 695  sub getDescription {
     }      }
     if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT)      if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT)
  && $res->handgrade($part) ne 'yes') {   && $res->handgrade($part) ne 'yes') {
         my $msg = &mt('Answer available');          return &Apache::lonhtmlcommon::direct_parm_link(&mt("Answer available"),$res->symb(),'answerdate,duedate',$part);
         my $parmlist = 'answerdate,duedate';  
         if (($res->is_tool) && ($res->is_gradable())) {  
             if (($status == $res->PARTIALLY_CORRECT) && ($res->parmval('retrypartial',$part))) {  
                 $msg = &mt('Grade received');  
                 $parmlist = 'retrypartial';  
             } else {  
                 $msg = &mt('Grade available');  
             }  
         }  
         return &Apache::lonhtmlcommon::direct_parm_link($msg,$res->symb(),$parmlist,$part);  
     }      }
     if ($status == $res->EXCUSED) {      if ($status == $res->EXCUSED) {
         return &mt("Excused by instructor");          return &mt("Excused by instructor");
Line 959  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 ($nomodal,$linkopen,$linkclose);      my $linkopen = "<img src='$whitespace' alt='' />";
     unless ($resource->is_map() || $params->{'resource_nolink'}) {      my $nomodal;
         $linkopen = "<img src='$whitespace' alt='' />";      if (($params->{'modalLink'}) && (!$resource->is_sequence())) {
         $linkclose = "</a>";          if ($link =~m{^(?:|/adm/wrapper)/ext/([^#]+)}) {
         if (($params->{'modalLink'}) && (!$resource->is_sequence())) {              my $exturl = $1;
             if ($link =~m{^(?:|/adm/wrapper)/ext/([^#]+)}) {              if (($ENV{'SERVER_PORT'} == 443) && ($exturl !~ /^https:/)) {
                 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;
             }              }
             my $esclink = &js_escape($link);          } elsif (($link eq "/public/$LONCAPA::match_domain/$LONCAPA::match_courseid/syllabus") &&
             if ($nomodal) {                   ($env{'request.course.id'}) && ($ENV{'SERVER_PORT'} == 443) &&
                 $linkopen .= "<a href=\"#\" onclick=\"javascript:window.open('$esclink','resourcepreview','height=400,width=500,scrollbars=1,resizable=1,menubar=0,location=1'); return false;\" />";                   ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
             } else {               $nomodal = 1;
                 $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\">";              $linkopen .= "<a href=\"$link\" onclick=\"javascript:openMyModal('$esclink',600,500,'yes','true'); return false;\">";
         }          }
       } 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 1011  sub render_resource { Line 999  sub render_resource {
         if ($it->{CONDITION}) {          if ($it->{CONDITION}) {
             $nowOpen = !$nowOpen;              $nowOpen = !$nowOpen;
         }          }
  my $folderType;  
  if (&advancedUser() && $resource->is_missing_map()) {   my $folderType = $resource->is_sequence() ? 'folder' : 'page';
     $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 1035  sub render_resource { Line 1019  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 1061  sub render_resource { Line 1044  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 1209  sub render_quick_status { Line 1172  sub render_quick_status {
     my $linkclose = "</a>";      my $linkclose = "</a>";
   
  $result .= '<td class="LC_middle">';   $result .= '<td class="LC_middle">';
     if ($resource->is_gradable() &&      if ($resource->is_problem() &&
         !$firstDisplayed) {          !$firstDisplayed) {
         my $icon = $statusIconMap{$resource->simpleStatus($part)};          my $icon = $statusIconMap{$resource->simpleStatus($part)};
         my $alt = $iconAltTags{$icon};          my $alt = $iconAltTags{$icon};
Line 1234  sub render_long_status { Line 1197  sub render_long_status {
                                   
     my $color;      my $color;
     my $info = '';      my $info = '';
     if ($resource->is_gradable() || $resource->is_practice()) {      if ($resource->is_problem() || $resource->is_practice()) {
         $color = $colormap{$resource->status};          $color = $colormap{$resource->status};
   
         if (dueInLessThan24Hours($resource, $part)) {          if (dueInLessThan24Hours($resource, $part)) {
Line 1249  sub render_long_status { Line 1212  sub render_long_status {
          }           }
     }      }
           
     if (($resource->kind() eq "res") &&      if ($resource->kind() eq "res" &&
         ($resource->is_raw_problem() || $resource->is_gradable()) &&          $resource->is_raw_problem() &&
         !$firstDisplayed) {          !$firstDisplayed) {
         if ($color) {$result .= '<span style="color:'.$color.'"'.$info.'><b>'; }          if ($color) {$result .= '<span style="color:'.$color.'"'.$info.'><b>'; }
         $result .= getDescription($resource, $part);          $result .= getDescription($resource, $part);
Line 1297  my @statuses = ($resObj->CORRECT, $resOb Line 1260  my @statuses = ($resObj->CORRECT, $resOb
   
 sub render_parts_summary_status {  sub render_parts_summary_status {
     my ($resource, $part, $params) = @_;      my ($resource, $part, $params) = @_;
     if (!$resource->is_gradable() && !$resource->contains_problem) { return '<td></td>'; }      if (!$resource->is_problem() && !$resource->contains_problem) { return '<td></td>'; }
     if ($params->{showParts}) {       if ($params->{showParts}) { 
  return '<td></td>';   return '<td></td>';
     }      }
Line 1366  sub cmp_title { Line 1329  sub cmp_title {
 sub render {  sub render {
     my $args = shift;      my $args = shift;
     &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});      &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
       my $result = '';
     # Configure the renderer.      # Configure the renderer.
     my $cols = $args->{'cols'};      my $cols = $args->{'cols'};
     if (!defined($cols)) {      if (!defined($cols)) {
         # no columns, no nav maps.          # no columns, no nav maps.
         return '';          return '';
     }      }
     my $legend = '';  
     my $tools = '';  
     my $result = '';  
     my $tools_printed = 0;  
     my $tablestarted = 0;  
     my $navmap;      my $navmap;
     if (defined($args->{'navmap'})) {      if (defined($args->{'navmap'})) {
         $navmap = $args->{'navmap'};          $navmap = $args->{'navmap'};
Line 1413  sub render { Line 1372  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'}) && !$args->{'nocurrloc'}) {      if (!$env{'form.folderManip'} && !defined($args->{'iterator'})) {
         # 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 1588  sub render { Line 1513  sub render {
         
     # Print key?      # Print key?
     if ($printKey) {      if ($printKey) {
         $legend = '<table border="0" cellpadding="2" cellspacing="0">';          $result .= '<table border="0" cellpadding="2" cellspacing="0">';
         $legend .= '<tr><td align="right" valign="bottom">Key:&nbsp;&nbsp;</td>';          $result.='<tr><td align="right" valign="bottom">Key:&nbsp;&nbsp;</td>';
  my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");   my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
         if ($navmap->{LAST_CHECK}) {          if ($navmap->{LAST_CHECK}) {
             $legend .=               $result .= 
                 '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('New discussion since').' '.                  '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('New discussion since').' '.
                 strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})).                  strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})).
                 '</td><td align="center" valign="bottom">&nbsp;&nbsp;'.                  '</td><td align="center" valign="bottom">&nbsp;&nbsp;'.
                 '<img src="'.$location.'/feedback.gif" alt="" /> '.&mt('New message (click to open)').'<p>'.                  '<img src="'.$location.'/feedback.gif" alt="" /> '.&mt('New message (click to open)').'<p>'.
                 '</td>';                   '</td>'; 
         } else {          } else {
             $legend .= '<td align="center" valign="bottom">&nbsp;&nbsp;'.              $result .= '<td align="center" valign="bottom">&nbsp;&nbsp;'.
                 '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('Discussions').'</td><td align="center" valign="bottom">'.                  '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('Discussions').'</td><td align="center" valign="bottom">'.
                 '&nbsp;&nbsp;<img src="'.$location.'/feedback.gif" alt="" /> '.&mt('New message (click to open)').                  '&nbsp;&nbsp;<img src="'.$location.'/feedback.gif" alt="" /> '.&mt('New message (click to open)').
                 '</td>';                   '</td>'; 
         }          }
   
         $legend .= '</tr></table>';          $result .= '</tr></table>';
     }      }
   
     if ($printCloseAll && !$args->{'resource_no_folder_link'}) {      if ($printCloseAll && !$args->{'resource_no_folder_link'}) {
Line 1625  sub render { Line 1550  sub render {
                               "location.href='$link'",$text);                                "location.href='$link'",$text);
             }              }
  } else {   } else {
     $tools = '<a href="'.$link.'">'.&mt($text).'</a>';      $result.= '<a href="'.$link.'">'.&mt($text).'</a>';
  }   }
         $tools .= "\n";          $result .= "\n";
     }      }
   
     # Check for any unread discussions in all resources.      # Check for any unread discussions in all resources.
Line 1637  sub render { Line 1562  sub render {
       'Mark all posts read');        'Mark all posts read');
  my $time=time;   my $time=time;
         my $querystr = &HTML::Entities::encode($ENV{'QUERY_STRING'},'<>&"');          my $querystr = &HTML::Entities::encode($ENV{'QUERY_STRING'},'<>&"');
  $tools .= (<<END);   $result .= (<<END);
     <form name="clearbubbles" method="post" action="/adm/feedback">      <form name="clearbubbles" method="post" action="/adm/feedback">
  <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" />
Line 1654  END Line 1579  END
     }      }
     if ($totdisc > 0) {      if ($totdisc > 0) {
  $haveDisc =~ s/:$//;   $haveDisc =~ s/:$//;
  $tools .= (<<END);   $result .= (<<END);
  <input type="hidden" name="navmaps" value="$haveDisc" />   <input type="hidden" name="navmaps" value="$haveDisc" />
     </form>      </form>
 END  END
             }              }
  }   }
  $tools .= '</form>';   $result.='</form>';
     }      }
     if (($args->{'caller'} eq 'navmapsdisplay') && ($env{'request.course.id'})) {      if (($args->{'caller'} eq 'navmapsdisplay') &&
           ((&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") {
             if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) ||              &add_linkitem($args->{'linkitems'},'edittoplevel',
                 (&Apache::lonnet::allowed('cev',$env{'request.course.id'}))) {                            "javascript:gocmd('/adm/coursedocs','editdocs');",
                 &add_linkitem($args->{'linkitems'},'edittoplevel',                            'Content Editor');
                               "javascript:gocmd('/adm/coursedocs','editdocs');",  
                               'Content Editor');  
             }  
             if ($counter) {  
                 &add_linkitem($args->{'linkitems'},'printout',  
                               "javascript:gopost('/adm/printout','/adm/navmaps');",  
                               'Prepare a printable document');  
             }  
         }          }
     }      }
   
     if ($args->{'caller'} eq 'navmapsdisplay') {      if ($args->{'caller'} eq 'navmapsdisplay') {
         $tools .= &show_linkitems_toolbar($args,$condition);          $result .= &show_linkitems_toolbar($args,$condition);
     } elsif ($args->{'sort_html'}) {       } elsif ($args->{'sort_html'}) { 
         $tools .= $args->{'sort_html'};           $result.=$args->{'sort_html'}; 
     }      }
   
     #$tools .= "<br />\n";      #$result .= "<br />\n";
       if ($r) {
           $r->print($result);
           $r->rflush();
           $result = "";
       }
     # End parameter setting      # End parameter setting
       
       $result .= "<br />\n";
   
     # Data      # Data
       $result.=&Apache::loncommon::start_data_table("LC_tableOfContent");    
   
     my $res = "Apache::lonnavmaps::resource";      my $res = "Apache::lonnavmaps::resource";
     my %condenseStatuses =      my %condenseStatuses =
Line 1702  END Line 1629  END
     $args->{'counter'} = 0; # counts the rows      $args->{'counter'} = 0; # counts the rows
     $args->{'indentLevel'} = 0;      $args->{'indentLevel'} = 0;
     $args->{'isNewBranch'} = 0;      $args->{'isNewBranch'} = 0;
     $args->{'condensed'} = 0;      $args->{'condensed'} = 0;   
     $args->{'deeplinknolist'} = 0;  
   
     my $location = &Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace_21.gif");      my $location = &Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace_21.gif");
     $args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='$location' alt='' />");      $args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='$location' alt='' />");
Line 1716  END Line 1642  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 1760  END Line 1666  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 (&$dfsFilterFunc($curRes)) {                  if (&$filterFunc($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 1879  END Line 1784  END
   
         # If this has been filtered out, continue on          # If this has been filtered out, continue on
         if (!(&$filterFunc($curRes))) {          if (!(&$filterFunc($curRes))) {
             if (!$userCanSeeHidden && !$curRes->randomout && $curRes->deeplinkout) {  
                 $args->{'deeplinknolist'} ++;  
             }  
             $args->{'isNewBranch'} = 0; # Don't falsely remember this              $args->{'isNewBranch'} = 0; # Don't falsely remember this
             next;              next;
         }           } 
   
         # 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 1902  END Line 1802  END
                     } else {                      } else {
                         next;                          next;
                     }                      }
                 } elsif ($curRes->deeplinkout) {  
                     if ($userCanSeeHidden) {  
                         $args->{'mapHiddenDeepLink'} = 1;  
                     } else {  
                         $args->{'deeplinknolist'} ++;  
                         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 {  
                             $args->{'deeplinknolist'} ++;  
                             next;  
                         }  
                     }  
                 }                  }
             }              }
         }          }
Line 1930  END Line 1812  END
         }          }
   
         $args->{'counter'}++;          $args->{'counter'}++;
         unless ($tablestarted) {  
             $result .= "<br />\n".&Apache::loncommon::start_data_table("LC_tableOfContent");  
             $tablestarted = 1;  
         }  
   
         # Does it have multiple parts?          # Does it have multiple parts?
         $args->{'multipart'} = 0;          $args->{'multipart'} = 0;
Line 1986  END Line 1864  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 2084  END Line 1953  END
         }          }
   
         if ($r && $rownum % 20 == 0) {          if ($r && $rownum % 20 == 0) {
             unless ($tools_printed) {  
                 $r->print($legend.$tools);  
                 $legend = "";  
                 $tools = "";  
                 $tools_printed = 1;  
             }  
             $r->print($result);              $r->print($result);
             $result = "";              $result = "";
             $r->rflush();              $r->rflush();
Line 2105  END Line 1968  END
  }   }
     }      }
   
     if ($tablestarted) {      $result.=&Apache::loncommon::end_data_table();
         $result.=&Apache::loncommon::end_data_table();      
     }  
   
     # Print out the part that jumps to #curloc if it exists      # Print out the part that jumps to #curloc if it exists
     # delay needed because the browser is processing the jump before      # delay needed because the browser is processing the jump before
     # it finishes rendering, so it goes to the wrong place!      # it finishes rendering, so it goes to the wrong place!
Line 2125  if (location.href.indexOf('#curloc')==-1 Line 1986  if (location.href.indexOf('#curloc')==-1
     }      }
   
     if ($r) {      if ($r) {
         unless ($tools_printed) {  
             if (($args->{'counter'}) || ($userCanSeeHidden) ||  
                 (($args->{'caller'} eq 'navmapsdisplay') &&  
                  ($env{'form.showOnlyHomework'} ||  
                   $ENV{QUERY_STRING} =~ /^jumpToFirstHomework/))) {  
                 $r->print($legend.$tools);  
             }  
             $legend = "";  
             $tools = "";  
             $tools_printed = 1;  
         }  
         $r->print($result);          $r->print($result);
         $result = "";          $result = "";
         $r->rflush();          $r->rflush();
     }      }
                   
     return $legend.$tools.$result;      return $result;
 }  }
   
 sub add_linkitem {  sub add_linkitem {
Line 2167  sub show_linkitems_toolbar { Line 2017  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','printout','edittoplevel');                               'changefolder','clearbubbles','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 2299  sub new { Line 2149  sub new {
   
     $self->{USERNAME} = shift || $env{'user.name'};      $self->{USERNAME} = shift || $env{'user.name'};
     $self->{DOMAIN}   = shift || $env{'user.domain'};      $self->{DOMAIN}   = shift || $env{'user.domain'};
     $self->{SECTION}  = shift;  
     $self->{CODE}     = shift;      $self->{CODE}     = shift;
     $self->{NOHIDE}   = shift;      $self->{NOHIDE} = shift;
   
   
     if (($self->{SECTION} eq '') && ($env{'request.course.sec'} ne '')) {  
         if (($self->{USERNAME} eq $env{'user.name'}) &&  
             ($self->{USERNAME} eq $env{'user.domain'})) {  
             $self->{SECTION} = $env{'request.course.sec'};  
         }  
     }  
   
     # Resource cache stores navmap resources as we reference them. We generate      # Resource cache stores navmap resources as we reference them. We generate
     # them on-demand so we don't pay for creating resources unless we use them.      # them on-demand so we don't pay for creating resources unless we use them.
Line 2351  sub new { Line 2194  sub new {
  $self->{PARM_HASH} = \%parmhash;   $self->{PARM_HASH} = \%parmhash;
  $self->{PARM_CACHE} = {};   $self->{PARM_CACHE} = {};
     } else {      } else {
  $self->change_user($self->{USERNAME}, $self->{DOMAIN}, $self->{SECTION}, $self->{CODE}, $self->{NOHIDE});   $self->change_user($self->{USERNAME}, $self->{DOMAIN},  $self->{CODE}, $self->{NOHIDE});
     }      }
   
     return $self;      return $self;
Line 2362  sub new { Line 2205  sub new {
 # username/domain associated with a navmap (e.g. to navigate for someone  # username/domain associated with a navmap (e.g. to navigate for someone
 # else besides the current user...if sufficiently privileged.  # else besides the current user...if sufficiently privileged.
 # Parameters:  # Parameters:
 #    user    - New user.  #    user  - New user.
 #    domain  - Domain to which the user belongs.  #    domain- Domain the user belongs to.
 #    section - Section to which the user belongs.  #    code  - Anonymous CODE in use.
 #    code    - Anonymous CODE in use.  
 # Implicit inputs:  # Implicit inputs:
 #     #   
 sub change_user {  sub change_user {
     my $self = shift;      my $self = shift;
     $self->{USERNAME} = shift;      $self->{USERNAME} = shift;
     $self->{DOMAIN}   = shift;      $self->{DOMAIN}   = shift;
     $self->{SECTION}  = shift;  
     $self->{CODE}     = shift;      $self->{CODE}     = shift;
     $self->{NOHIDE}   = shift;      $self->{NOHIDE}   = shift;
   
Line 2589  sub getIterator { Line 2430  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 2878  sub parmval_real { Line 2719  sub parmval_real {
     $self->generate_course_user_opt();      $self->generate_course_user_opt();
   
     my $cid=$env{'request.course.id'};      my $cid=$env{'request.course.id'};
     my $csec=$self->{SECTION};      my $csec=$env{'request.course.sec'};
     my $cgroup='';      my $cgroup='';
     my @cgrps=split(/:/,$env{'request.course.groups'});      my @cgrps=split(/:/,$env{'request.course.groups'});
     if (@cgrps > 0) {      if (@cgrps > 0) {
Line 2893  sub parmval_real { Line 2734  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 $toolsymb = '';  
     if ($fn =~ /ext\.tool$/) {  
         $toolsymb = $symb;  
     }  
 # ----------------------------------------------------- Cascading lookup scheme  # ----------------------------------------------------- Cascading lookup scheme
     my $rwhat=$what;      my $rwhat=$what;
     $what=~s/^parameter\_//;      $what=~s/^parameter\_//;
Line 2960  sub parmval_real { Line 2797  sub parmval_real {
   
     my $meta_rwhat=$rwhat;      my $meta_rwhat=$rwhat;
     $meta_rwhat=~s/\./_/g;      $meta_rwhat=~s/\./_/g;
     my $default=&Apache::lonnet::metadata($fn,$meta_rwhat,$toolsymb);      my $default=&Apache::lonnet::metadata($fn,$meta_rwhat);
     if (defined($default)) { return [$default,'resource']}      if (defined($default)) { return [$default,'resource']}
     $default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat,$toolsymb);      $default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat);
     if (defined($default)) { return [$default,'resource']}      if (defined($default)) { return [$default,'resource']}
 # --------------------------------------------------- fifth, check more course  # --------------------------------------------------- fifth, check more course
     if (defined($courseopt)) {      if (defined($courseopt)) {
Line 2985  sub parmval_real { Line 2822  sub parmval_real {
        if (defined($partgeneral[0])) { return \@partgeneral; }         if (defined($partgeneral[0])) { return \@partgeneral; }
     }      }
     if ($recurse) { return []; }      if ($recurse) { return []; }
     my $pack_def=&Apache::lonnet::packages_tab_default($fn,'resource.'.$rwhat,$toolsymb);      my $pack_def=&Apache::lonnet::packages_tab_default($fn,'resource.'.$rwhat);
     if (defined($pack_def)) { return [$pack_def,'resource']; }      if (defined($pack_def)) { return [$pack_def,'resource']; }
     return [''];      return [''];
 }  }
   
 sub recurseup_maps {  sub recurseup_maps {
     my ($self,$mapname,$getsymb) = @_;      my ($self,$mapname) = @_;
     my @recurseup;      my @recurseup;
     if ($mapname) {      if ($mapname) {
         my $res = $self->getResourceByUrl($mapname);          my $res = $self->getResourceByUrl($mapname);
Line 2999  sub recurseup_maps { Line 2836  sub recurseup_maps {
             my @pcs = split(/,/,$res->map_hierarchy());              my @pcs = split(/,/,$res->map_hierarchy());
             shift(@pcs);              shift(@pcs);
             if (@pcs) {              if (@pcs) {
                 if ($getsymb) {                  @recurseup = map { &Apache::lonnet::declutter($self->getByMapPc($_)->src()); } reverse(@pcs);
                     @recurseup = map { &Apache::lonnet::declutter($self->getByMapPc($_)->symb()); } reverse(@pcs);  
                 } else {  
                     @recurseup = map { &Apache::lonnet::declutter($self->getByMapPc($_)->src()); } reverse(@pcs);  
                 }  
             }              }
         }          }
     }      }
Line 3035  sub recursed_crumbs { Line 2868  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);
         my $text = $map->title();          push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,});
         if ($text eq '') {          $totallength += length($map->title());
             $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 3052  sub recursed_crumbs { Line 2881  sub recursed_crumbs {
             }              }
             @revmapinfo = ();              @revmapinfo = ();
             foreach my $map (@links) {              foreach my $map (@links) {
                 my $title = $map->title();                  my $showntitle = &truncate_crumb_text($map->title(),$avg);
                 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 3131  sub get_mapparam { Line 2956  sub get_mapparam {
     # Get the course id and section if there is one.      # Get the course id and section if there is one.
   
     my $cid=$env{'request.course.id'};      my $cid=$env{'request.course.id'};
     my $csec=$self->{SECTION};      my $csec=$env{'request.course.sec'};
     my $cgroup='';      my $cgroup='';
     my @cgrps=split(/:/,$env{'request.course.groups'});      my @cgrps=split(/:/,$env{'request.course.groups'});
     if (@cgrps > 0) {      if (@cgrps > 0) {
Line 3300  sub getcourseparam { Line 3125  sub getcourseparam {
   
     my $uname = $self->{USERNAME};      my $uname = $self->{USERNAME};
     my $udom  = $self->{DOMAIN};      my $udom  = $self->{DOMAIN};
     my $csec  = $self->{SECTION};  
           
     # Course and group ids come from the env:      # Course, section, group ids come from the env:
   
     my $cid   = $env{'request.course.id'};      my $cid   = $env{'request.course.id'};
       my $csec  = $env{'request.course.sec'};
     my $cgroup = ''; # Assume no group      my $cgroup = ''; # Assume no group
   
     my @cgroups = split(/:/, $env{'request.course.groups'});      my @cgroups = split(/:/, $env{'request.course.groups'});
Line 3541  sub usedVersion { Line 3366  sub usedVersion {
     return $self->navhash("version_$linkurl");      return $self->navhash("version_$linkurl");
 }  }
   
 sub isFirstResource {  
     my $self = shift;  
     my $map = shift;  
     my $symb = shift;  
     return unless (ref($map));  
     my $isfirst;  
     my $firstResource = $map->map_start();  
     if (ref($firstResource)) {  
         if ((!$firstResource->is_map()) && ($firstResource->src() ne ''))  {  
             if ($firstResource->symb() eq $symb) {  
                 $isfirst = 1;  
             } else {  
                 $isfirst = 0;  
             }  
         } else {  
             my $it = $self->getIterator($firstResource,undef,undef,1);  
             while ( my $res=$it->next()) {  
                 if ((ref($res)) && ($res->src() ne '') && (!$res->is_map())) {  
                     if ($res->symb() eq $symb) {  
                         $isfirst = 1;  
                     } else {  
                         $isfirst = 0;  
                     }  
                     last;  
                 }  
             }  
         }  
     }  
     return $isfirst;  
 }  
   
 sub isLastResource {  
     my $self = shift;  
     my $map = shift;  
     my $symb = shift;  
     return unless (ref($map));  
     my $islast;  
     my $lastResource = $map->map_finish();  
     if (ref($lastResource)) {  
         if ((!$lastResource->is_map()) && ($lastResource->src() ne ''))  {  
             if ($lastResource->symb() eq $symb) {  
                 $islast = 1;  
             } else {  
                 $islast = 0;  
             }  
         } else {  
             my $currRes = $self->getBySymb($symb);  
             if (ref($currRes)) {  
                 my $it = $self->getIterator($currRes,undef,undef,1);  
                 while ( my $res=$it->next()) {  
                     if ((ref($res)) && ($res->src() ne '') && (!$res->is_map())) {  
                         if ($res->symb() eq $symb) {  
                             $islast = 1;  
                         } else {  
                             $islast = 0;  
                         }  
                         last;  
                     }  
                 }  
             }  
         }  
     }  
     return $islast;  
 }  
   
 1;  1;
   
 package Apache::lonnavmaps::iterator;  package Apache::lonnavmaps::iterator;
Line 3636  getIterator behaves as follows: Line 3396  getIterator behaves as follows:
   
 =over 4  =over 4
   
 =item * B<getIterator>(firstResource, finishResource, filterHash, condition, forceTop, returnTopMap, $deeplinklisted):  =item * B<getIterator>(firstResource, finishResource, filterHash, condition, forceTop, returnTopMap):
   
 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 3653  that is not just a single, 'redirecting' Line 3413  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. deeplinklisted if true (default false), will  before anything else.
 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 3793  sub new { Line 3550  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 3888  sub new { Line 3641  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 4059  sub next { Line 3811  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,$self->{DEEPLINKLISTED});      my $browsePriv = $self->{HERE}->browsePriv($noblockcheck);
     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 4494  sub from { my $self=shift; return $self- Line 4245  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 4663  sub is_problem { Line 4413  sub is_problem {
     }      }
     return 0;      return 0;
 }  }
 sub is_tool {  
     my $self=shift;  
     my $src = $self->src();  
     return ($src =~ /ext\.tool$/);  
 }  
 sub is_gradable {  
     my $self=shift;  
     my $src = $self->src();  
     if (($src =~ /$LONCAPA::assess_re/) ||  
         (($self->is_tool()) && ($self->parmval('gradable',0) =~ /^yes$/i))) {  
         return !($self->is_practice());  
     }  
 }  
 #  #
 #  The has below is the set of status that are considered 'incomplete'  #  The has below is the set of status that are considered 'incomplete'
 #  #
Line 4734  sub is_sequence { Line 4471  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 4768  sub is_task { Line 4500  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 5088  sub duedate { Line 4821  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 $timelimit = $1;         my $first_access=&Apache::lonnet::get_first_access($interval[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+$timelimit;             my $interval = $first_access+$interval[0];
     $date = (!$due_date || $interval < $due_date) ? $interval       $date = (!$due_date || $interval < $due_date) ? $interval 
                                                           : $due_date;                                                            : $due_date;
  } else {   } else {
Line 5166  sub weight { Line 4898  sub weight {
     my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',      my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',
                                 $self->{SYMB}, $self->{DOMAIN},                                  $self->{SYMB}, $self->{DOMAIN},
                                 $self->{USERNAME},                                  $self->{USERNAME},
                                 $self->{SECTION});                                  $env{'request.course.sec'});
     return $weight;      return $weight;
 }  }
 sub part_display {  sub part_display {
Line 5187  sub slot_control { Line 4919  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 5375  sub parts { Line 5067  sub parts {
     my $self = shift;      my $self = shift;
   
     if ($self->ext) { return []; }      if ($self->ext) { return []; }
     if (($self->is_tool()) &&  
         ($self->is_gradable())) { return ['0']; }  
   
     $self->extractParts();      $self->extractParts();
     return $self->{PARTS};      return $self->{PARTS};
Line 5467  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_raw_problem()) {      if ($self->is_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 5774  Attempted, and not yet graded. Line 5464  Attempted, and not yet graded.
   
 Attempted, and credit received for attempt (survey and anonymous survey only).  Attempted, and credit received for attempt (survey and anonymous survey only).
   
 =item * B<INCORRECT_BY_PASSBACK>:  
   
 Attempted, but wrong for LTI Tool Provider by passback of grade  
   
 =item * B<CORRECT_BY_PASSBACK>:  
   
 Correct for LTI Tool Provider by passback of grade  
   
 =back  =back
   
 =cut  =cut
Line 5794  sub CORRECT_BY_OVERRIDE   { return 14; } Line 5476  sub CORRECT_BY_OVERRIDE   { return 14; }
 sub EXCUSED               { return 15; }  sub EXCUSED               { return 15; }
 sub ATTEMPTED             { return 16; }  sub ATTEMPTED             { return 16; }
 sub CREDIT_ATTEMPTED      { return 17; }  sub CREDIT_ATTEMPTED      { return 17; }
 sub INCORRECT_BY_PASSBACK { return 18; }  
 sub CORRECT_BY_PASSBACK   { return 19; }  
   
 sub getCompletionStatus {  sub getCompletionStatus {
     my $self = shift;      my $self = shift;
Line 5810  sub getCompletionStatus { Line 5490  sub getCompletionStatus {
     if ($status eq 'correct_by_override') {      if ($status eq 'correct_by_override') {
  return $self->CORRECT_BY_OVERRIDE;   return $self->CORRECT_BY_OVERRIDE;
     }      }
     if ($status eq 'correct_by_passback') {  
         return $self->CORRECT_BY_PASSBACK;  
     }  
     if ($status eq 'incorrect_attempted') {return $self->INCORRECT; }      if ($status eq 'incorrect_attempted') {return $self->INCORRECT; }
     if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; }      if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; }
     if ($status eq 'incorrect_by_passback') {return $self->INCORRECT_BY_PASSBACK; }  
     if ($status eq 'excused') {return $self->EXCUSED; }      if ($status eq 'excused') {return $self->EXCUSED; }
     if ($status eq 'ungraded_attempted') {return $self->ATTEMPTED; }      if ($status eq 'ungraded_attempted') {return $self->ATTEMPTED; }
     if ($status eq 'credit_attempted') {      if ($status eq 'credit_attempted') {
Line 5989  sub status { Line 5665  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 ) {
         $completionStatus == CORRECT_BY_PASSBACK ) {  
  if ( $suppressFeedback ) {   if ( $suppressFeedback ) {
             if ($dateStatus == PAST_DUE_ANSWER_LATER ||              if ($dateStatus == PAST_DUE_ANSWER_LATER ||
                 $dateStatus == PAST_DUE_NO_ANSWER ) {                  $dateStatus == PAST_DUE_NO_ANSWER ) {
Line 6014  sub status { Line 5689  sub status {
   
     # If it's WRONG... and not open      # If it's WRONG... and not open
     if ( ($completionStatus == INCORRECT ||       if ( ($completionStatus == INCORRECT || 
   $completionStatus == INCORRECT_BY_OVERRIDE ||    $completionStatus == INCORRECT_BY_OVERRIDE)
           $completionStatus == INCORRECT_BY_PASSBACK)  
  && (!$self->opendate($part) ||  $self->opendate($part) > time()) ) {   && (!$self->opendate($part) ||  $self->opendate($part) > time()) ) {
  return INCORRECT;   return INCORRECT;
     }      }
Line 6073  sub status { Line 5747  sub status {
     }      }
   
     # If it's WRONG...      # If it's WRONG...
     if ($completionStatus == INCORRECT || $completionStatus == INCORRECT_BY_OVERRIDE ||      if ($completionStatus == INCORRECT || $completionStatus == INCORRECT_BY_OVERRIDE) {
         $completionStatus == INCORRECT_BY_PASSBACK) {  
         # and there are TRIES LEFT:          # and there are TRIES LEFT:
         if ($self->tries($part) < $self->maxtries($part) || !$self->maxtries($part)) {          if ($self->tries($part) < $self->maxtries($part) || !$self->maxtries($part)) {
             return $suppressFeedback ? ANSWER_SUBMITTED : TRIES_LEFT;              return $suppressFeedback ? ANSWER_SUBMITTED : TRIES_LEFT;
Line 6451  sub getPrevious { Line 6124  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.2.12  
changed lines
  Added in v.1.509.2.16


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