Diff for /loncom/interface/lonnavmaps.pm between versions 1.542 and 1.563

version 1.542, 2018/04/14 17:52:43 version 1.563, 2023/04/04 23:15:48
Line 357  user into thinking that if the sequence Line 357  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 549  my %colormap = Line 549  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 592  sub getLinkForResource { Line 596  sub getLinkForResource {
     my $anchor;      my $anchor;
     if ($res->is_page()) {      if ($res->is_page()) {
  foreach my $item (@$stack) { if (defined($item)) { $anchor = $item; }  }   foreach my $item (@$stack) { if (defined($item)) { $anchor = $item; }  }
  $anchor=&escape($anchor->shown_symb());   if ($anchor->encrypted() && !&advancedUser()) {
       $anchor='LC_'.$anchor->id();
    } else {
       $anchor=&escape($anchor->shown_symb());
    }
  return ($res->link(),$res->shown_symb(),$anchor);   return ($res->link(),$res->shown_symb(),$anchor);
     }      }
             # in case folder was skipped over as "only sequence"              # in case folder was skipped over as "only sequence"
Line 690  sub getDescription { Line 698  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 963  sub render_resource { Line 971  sub render_resource {
         $newBranchText = "<img src='$location/branch.gif' alt=".mt('Branch')." />";          $newBranchText = "<img src='$location/branch.gif' alt=".mt('Branch')." />";
     }      }
   
     # 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 1016  sub render_resource { Line 1024  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 1036  sub render_resource { Line 1048  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 1074  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 1388  sub render { Line 1421  sub render {
         # Without renaming the filterfunc, the server seems to go into          # Without renaming the filterfunc, the server seems to go into
         # 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 1436  sub render { Line 1503  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 1482  sub render { Line 1553  sub render {
         if ($args->{'iterator_map'}) {          if ($args->{'iterator_map'}) {
             my $map = $args->{'iterator_map'};              my $map = $args->{'iterator_map'};
             $map = $navmap->getResourceByUrl($map);              $map = $navmap->getResourceByUrl($map);
             my $firstResource = $map->map_start();              if (ref($map)) {
             my $finishResource = $map->map_finish();                  my $firstResource = $map->map_start();
                   my $finishResource = $map->map_finish();
             $args->{'iterator'} = $it = $navmap->getIterator($firstResource, $finishResource, $filterHash, $condition);                  $args->{'iterator'} = $it = $navmap->getIterator($firstResource, $finishResource, $filterHash, $condition);
               } else {
                   return;
               }
         } else {          } else {
             $args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition,undef,$args->{'include_top_level_map'});              $args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition,undef,$args->{'include_top_level_map'});
         }          }
Line 1554  sub render { Line 1628  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 1580  sub render { Line 1651  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 1603  END Line 1671  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 1658  END Line 1732  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 1681  END Line 1775  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 1805  END Line 1900  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 1817  END Line 1914  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 1879  END Line 1992  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) {
             $args->{'multipart'} = 0;              $args->{'multipart'} = 0;
Line 1906  END Line 2028  END
             if ($env{'request.course.id'}) {              if ($env{'request.course.id'}) {
                 if (($is_ssl) && ($src =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) &&                  if (($is_ssl) && ($src =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) &&
                     ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {                      ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
                     if ($hostname ne '') {                      unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                         $src = 'http://'.$hostname.$src;                          if ($hostname ne '') {
                               $src = 'http://'.$hostname.$src;
                           }
                           $src .= ($srcHasQuestion? '&amp;' : '?') . 'usehttp=1';
                           $srcHasQuestion = 1;
                     }                      }
                     $src .= ($srcHasQuestion? '&amp;' : '?') . 'usehttp=1';  
                     $srcHasQuestion = 1;  
                 } elsif (($is_ssl) && ($src =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) {                  } elsif (($is_ssl) && ($src =~ m{^\Q/adm/wrapper/ext/\E(?!https:)})) {
                     if ($hostname ne '') {                      unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl($hostname))) {
                         $src = 'http://'.$hostname.$src;                          if ($hostname ne '') {
                               $src = 'http://'.$hostname.$src;
                           }
                           $src .= ($srcHasQuestion? '&amp;' : '?') . 'usehttp=1';
                           $srcHasQuestion = 1;
                     }                      }
                 }                  }
             }              }
Line 1952  END Line 2080  END
                     $currentJumpDelta) {                      $currentJumpDelta) {
                     # Jam the anchor after the <td> tag;                      # Jam the anchor after the <td> tag;
                     # necessary for valid HTML (which Mozilla requires)                      # necessary for valid HTML (which Mozilla requires)
                     $colHTML =~ s/\>/\>\<a name="curloc" \/\>/;                      $colHTML =~ s/\>/\>\<a name="curloc" \>\<\/a\>/;
                     $displayedJumpMarker = 1;                      $displayedJumpMarker = 1;
                 }                  }
                 $result .= $colHTML . "\n";                  $result .= $colHTML . "\n";
Line 2026  sub show_linkitems_toolbar { Line 2154  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 2439  sub getIterator { Line 2567  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 2958  sub recursed_crumbs { Line 3086  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' => $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 2971  sub recursed_crumbs { Line 3103  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' => $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 3203  sub get_mapparam { Line 3339  sub get_mapparam {
  if (defined($$courseopt{$courselevelm})) {   if (defined($$courseopt{$courselevelm})) {
     return $$courseopt{$courselevelm};      return $$courseopt{$courselevelm};
  }   }
           if (defined($$courseopt{$courseleveli})) {
               return $$courseopt{$courseleveli};
           }
         unless ($recursed) {          unless ($recursed) {
             @recurseup = $self->recurseup_maps($mapname);              @recurseup = $self->recurseup_maps($mapname);
             $recursed = 1;              $recursed = 1;
Line 3576  getIterator behaves as follows: Line 3715  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 3593  that is not just a single, 'redirecting' Line 3732  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 3730  sub new { Line 3872  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 3821  sub new { Line 3967  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 3981  sub next { Line 4128  sub next {
     # That ends the main iterator logic. Now, do we want to recurse      # That ends the main iterator logic. Now, do we want to recurse
     # down this map (if this resource is a map)?      # down this map (if this resource is a map)?
     if ( ($self->{HERE}->is_sequence() || (!$closeAllPages && $self->{HERE}->is_page())) &&      if ( ($self->{HERE}->is_sequence() || (!$closeAllPages && $self->{HERE}->is_page())) &&
         (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) {          (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION}) &&
           ($env{'request.role.adv'} || !$self->{HERE}->randomout())) {
         $self->{RECURSIVE_ITERATOR_FLAG} = 1;          $self->{RECURSIVE_ITERATOR_FLAG} = 1;
         my $firstResource = $self->{HERE}->map_start();          my $firstResource = $self->{HERE}->map_start();
         my $finishResource = $self->{HERE}->map_finish();          my $finishResource = $self->{HERE}->map_finish();
Line 3990  sub next { Line 4138  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 4424  sub from { my $self=shift; return $self- Line 4573  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_sequence { Line 4813  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 4692  sub is_task { Line 4847  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 5112  sub slot_control { Line 5266  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 5525  The problem will be opened later. Line 5719  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 5538  The due date has passed and there is no Line 5731  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 5553  sub PAST_DUE_NO_ANSWER     { return 2; } Line 5766  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 5756  set. Line 5973  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 5839  sub status { Line 6076  sub status {
     if ($completionStatus == CORRECT ||      if ($completionStatus == CORRECT ||
         $completionStatus == CORRECT_BY_OVERRIDE ||          $completionStatus == CORRECT_BY_OVERRIDE ||
         $completionStatus == CORRECT_BY_PASSBACK ) {          $completionStatus == CORRECT_BY_PASSBACK ) {
  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 5879  sub status { Line 6127  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 6125  my %compositeToSimple = Line 6389  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 6303  sub getPrevious { Line 6571  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.542  
changed lines
  Added in v.1.563


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