Diff for /loncom/interface/lonnavmaps.pm between versions 1.461 and 1.482

version 1.461, 2011/05/25 09:03:07 version 1.482, 2012/04/04 15:00:17
Line 225  automatically. Line 225  automatically.
   
 =over 4  =over 4
   
 =item * B<iterator>: default: constructs one from %env  =item * B<iterator: default: constructs one from %env>
   
 A reference to a fresh ::iterator to use from the navmaps. The  A reference to a fresh ::iterator to use from the navmaps. The
 rendering will reflect the options passed to the iterator, so you can  rendering will reflect the options passed to the iterator, so you can
Line 464  returns 4 Line 464  returns 4
   
 =item add_linkitem()  =item add_linkitem()
   
 =item show_linkitems()  =item show_linkitems_toolbar()
   
 =back  =back
   
Line 478  use Apache::loncommon(); Line 478  use Apache::loncommon();
 use Apache::lonenc();  use Apache::lonenc();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnet;  use Apache::lonnet;
   use Apache::lonmap;
   
 use POSIX qw (floor strftime);  use POSIX qw (floor strftime);
 use Time::HiRes qw( gettimeofday tv_interval );  use Time::HiRes qw( gettimeofday tv_interval );
 use LONCAPA;  use LONCAPA;
 use DateTime();  use DateTime();
 use Data::Dumper;  
   # For debugging
   
   # use Data::Dumper;
   
   
 # symbolic constants  # symbolic constants
 sub SYMB { return 1; }  sub SYMB { return 1; }
 sub URL { return 2; }  sub URL { return 2; }
Line 509  my %statusIconMap = Line 515  my %statusIconMap =
 my %iconAltTags =   #texthash does not work here  my %iconAltTags =   #texthash does not work here
     ( 'navmap.correct.gif'  => 'Correct',      ( 'navmap.correct.gif'  => 'Correct',
       'navmap.wrong.gif'    => 'Incorrect',        'navmap.wrong.gif'    => 'Incorrect',
       'navmap.open.gif'     => 'Open',        'navmap.open.gif'     => 'Is Open',
       'navmap.partial.gif'  => 'Partially Correct',        'navmap.partial.gif'  => 'Partially Correct',
       'navmap.ellipsis.gif' => 'Attempted',        'navmap.ellipsis.gif' => 'Attempted',
      );       );
Line 536  my %colormap = Line 542  my %colormap =
 # is not yet done and due in less than 24 hours  # is not yet done and due in less than 24 hours
 my $hurryUpColor = "#FF0000";  my $hurryUpColor = "#FF0000";
   
 my $future_slots_checked = 0;  
 my $future_slots = 0;  
   
 sub addToFilter {  sub addToFilter {
     my $hashIn = shift;      my $hashIn = shift;
     my $addition = shift;      my $addition = shift;
Line 612  sub getDescription { Line 615  sub getDescription {
         return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part);          return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part);
     }      }
     if ($status == $res->OPEN_LATER) {      if ($status == $res->OPEN_LATER) {
         return &mt("Open ") .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start'),$res->symb(),'opendate',$part);          return &mt("Open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start'),$res->symb(),'opendate',$part));
     }      }
     if ($res->simpleStatus($part) == $res->OPEN) {      if ($res->simpleStatus($part) == $res->OPEN) {
         unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) {          unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) {
Line 629  sub getDescription { Line 632  sub getDescription {
                 return &mt('Reserved - next open [_1]',                  return &mt('Reserved - next open [_1]',
                            timeToHumanString($slot_time,'start'));                             timeToHumanString($slot_time,'start'));
             } elsif ($slot_status == $res->RESERVABLE) {              } elsif ($slot_status == $res->RESERVABLE) {
                 return &mt('Reservable ending [_1]',                  return &mt('Reservable, reservations close [_1]',
                            timeToHumanString($slot_time,'end'));                             timeToHumanString($slot_time,'end'));
             } elsif ($slot_status == $res->RESERVABLE_LATER) {              } elsif ($slot_status == $res->RESERVABLE_LATER) {
                 return &mt('Reservable starting [_1]',                  return &mt('Reservable, reservations open [_1]',
                            timeToHumanString($slot_time,'start'));                             timeToHumanString($slot_time,'start'));
             } elsif ($slot_status == $res->NOT_IN_A_SLOT) {              } elsif ($slot_status == $res->NOT_IN_A_SLOT) {
                 return &mt('Reserve a time/place to work');                  return &mt('Reserve a time/place to work');
Line 646  sub getDescription { Line 649  sub getDescription {
     if ($status == $res->OPEN) {      if ($status == $res->OPEN) {
         if ($due) {          if ($due) {
     if ($res->is_practice()) {      if ($res->is_practice()) {
  return &mt("Closes ")."  " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part);   return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part));
     } else {      } else {
  return &mt("Due")."  " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part);   return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part));
     }      }
         } else {          } else {
             return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part);              return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part);
         }          }
     }      }
     if ($status == $res->PAST_DUE_ANSWER_LATER) {      if ($status == $res->PAST_DUE_ANSWER_LATER) {
         return &mt("Answer open")." " .&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) {
  if ($res->is_practice()) {   if ($res->is_practice()) {
     return &mt("Closed")." " . &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 {
     return &mt("Was due")." " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'answerdate,duedate',$part);      return &mt("Was due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'answerdate,duedate',$part));
  }   }
     }      }
     if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT)      if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT)
Line 694  sub getDescription { Line 697  sub getDescription {
             }              }
         }          }
         if ($due) {          if ($due) {
             return &mt("Due")." " . &Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part) .              return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)) .
                 " $triesString";                  " $triesString";
         } else {          } else {
             return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString";              return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString";
Line 779  sub timeToHumanString { Line 782  sub timeToHumanString {
   
         # Less than an hour          # Less than an hour
         if ( $delta < $hour ) {          if ( $delta < $hour ) {
             # If so, use minutes              # If so, use minutes; or minutes, seconds (if format requires)
             my $minutes = floor($delta / 60);              my $minutes = floor($delta / 60);
               if (($format ne '') && ($format =~ /\%(T|S)/)) {
                   my $display;
                   if ($minutes == 1) {
                       $display = "${prefix}1 minute";
                   } else {
                       $display = "$prefix$minutes minutes";
                   }
                   my $seconds = $delta % $minute;
                   if ($seconds == 0) {
                       $display .= $tense;
                   } elsif ($seconds == 1) {
                       $display .= ", 1 second$tense";
                   } else {
                       $display .= ", $seconds seconds$tense";
                   }
                   return $display;
               }
             if ($minutes == 1) { return "${prefix}1 minute$tense"; }              if ($minutes == 1) { return "${prefix}1 minute$tense"; }
             return "$prefix$minutes minutes$tense";              return "$prefix$minutes minutes$tense";
         }          }
                   
         # Is it less than 24 hours away? If so,          # Is it less than 24 hours away? If so,
         # display hours + minutes          # display hours + minutes, (and + seconds, if format specified it)  
         if ( $delta < $hour * 24) {          if ( $delta < $hour * 24) {
             my $hours = floor($delta / $hour);              my $hours = floor($delta / $hour);
             my $minutes = floor(($delta % $hour) / $minute);              my $minutes = floor(($delta % $hour) / $minute);
Line 801  sub timeToHumanString { Line 821  sub timeToHumanString {
             if ($minutes == 0) {              if ($minutes == 0) {
                 $minuteString = "";                  $minuteString = "";
             }              }
               if (($format ne '') && ($format =~ /\%(T|S)/)) {
                   my $display = "$prefix$hourString$minuteString";
                   my $seconds = $delta-(($hours * $hour)+($minutes * $minute));
                   if ($seconds == 0) {
                       $display .= $tense;
                   } elsif ($seconds == 1) {
                       $display .= ", 1 second$tense";
                   } else {
                       $display .= ", $seconds seconds$tense";
                   }
                   return $display;
               }
             return "$prefix$hourString$minuteString$tense";              return "$prefix$hourString$minuteString$tense";
         }          }
   
           # Date/time is more than 24 hours away
   
  my $dt = DateTime->from_epoch(epoch => $time)   my $dt = DateTime->from_epoch(epoch => $time)
                  ->set_time_zone(&Apache::lonlocal::gettimezone());                   ->set_time_zone(&Apache::lonlocal::gettimezone());
   
  # If there's a caller supplied format, use it.   # If there's a caller supplied format, use it, unless it only displays
           # H:M:S or H:M.
   
  if ($format ne '') {   if (($format ne '') && ($format ne '%T') && ($format ne '%R')) {
     my $timeStr = $dt->strftime($format);      my $timeStr = $dt->strftime($format);
     return $timeStr.' ('.$dt->time_zone_short_name().')';      return $timeStr.' ('.$dt->time_zone_short_name().')';
  }   }
Line 861  sub part_status_summary { return 4; } Line 896  sub part_status_summary { return 4; }
 sub render_resource {  sub render_resource {
     my ($resource, $part, $params) = @_;      my ($resource, $part, $params) = @_;
   
       my $editmapLink;
     my $nonLinkedText = ''; # stuff after resource title not in link      my $nonLinkedText = ''; # stuff after resource title not in link
   
     my $link = $params->{"resourceLink"};      my $link = $params->{"resourceLink"};
Line 942  sub render_resource { Line 978  sub render_resource {
             $linkopen = "";              $linkopen = "";
             $linkclose = "";              $linkclose = "";
         }          }
           if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) &&
               ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) {
               my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png';
               $editmapLink='&nbsp;'.
                            '<a href="/adm/coursedocs?command=direct&symb='.&escape($resource->symb()).'">'.
                            '<img src="'.$icon.'" alt="'.&mt('Edit Content').'" title="'.&mt('Edit Content').'" />'.
                            '</a>';
           }
     }      }
   
     if ($resource->randomout()) {      if ($resource->randomout()) {
Line 975  sub render_resource { Line 1019  sub render_resource {
     # Is this the current resource?      # Is this the current resource?
     if (!$params->{'displayedHereMarker'} &&       if (!$params->{'displayedHereMarker'} && 
         $resource->symb() eq $params->{'here'} ) {          $resource->symb() eq $params->{'here'} ) {
         $curMarkerBegin = '<em>';          unless ($resource->is_map()) {
         $curMarkerEnd = '</em>';              $curMarkerBegin = '<span class="LC_current_nav_location">';
               $curMarkerEnd = '</span>';
           }
  $params->{'displayedHereMarker'} = 1;   $params->{'displayedHereMarker'} = 1;
     }      }
   
Line 995  sub render_resource { Line 1041  sub render_resource {
     if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {      if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {
         $result .= "$curMarkerBegin<a href=\"$link\">$title$partLabel</a>$curMarkerEnd$nonLinkedText</td>";          $result .= "$curMarkerBegin<a href=\"$link\">$title$partLabel</a>$curMarkerEnd$nonLinkedText</td>";
     } else {      } else {
         $result .= "$curMarkerBegin$linkopen$title$partLabel</a>$curMarkerEnd$nonLinkedText</td>";          $result .= "$curMarkerBegin$linkopen$title$partLabel</a>$curMarkerEnd$editmapLink$nonLinkedText</td>";
     }      }
   
     return $result;      return $result;
Line 1009  sub render_communication_status { Line 1055  sub render_communication_status {
     my $linkopen = "<a href=\"$link\">";      my $linkopen = "<a href=\"$link\">";
     my $linkclose = "</a>";      my $linkclose = "</a>";
     my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");      my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
   
     if ($resource->hasDiscussion()) {      if ($resource->hasDiscussion()) {
         $discussionHTML = $linkopen .          $discussionHTML = $linkopen .
             '<img alt="'.&mt('New Discussion').'" src="'.$location.'/chat.gif" title="'.&mt('New Discussion').'"/>' .              '<img alt="'.&mt('New Discussion').'" src="'.$location.'/chat.gif" title="'.&mt('New Discussion').'"/>' .
Line 1090  sub render_long_status { Line 1137  sub render_long_status {
         }          }
     }      }
           
     if (($resource->kind() eq "res" &&      if ($resource->kind() eq "res" &&
         ($resource->is_problem() || $resource->is_practice()) &&          $resource->is_raw_problem() &&
         !$firstDisplayed) &&          !$firstDisplayed) {
         $resource->is_raw_problem()) {  
         if ($color) {$result .= "<font color=\"$color\"><b>"; }          if ($color) {$result .= "<font color=\"$color\"><b>"; }
         $result .= getDescription($resource, $part);          $result .= getDescription($resource, $part);
         if ($color) {$result .= "</b></font>"; }          if ($color) {$result .= "</b></font>"; }
Line 1352  sub render { Line 1398  sub render {
         }          }
     }      }
   
   
     # (re-)Locate the jump point, if any      # (re-)Locate the jump point, if any
     # Note this does not take filtering or hidden into account... need      # Note this does not take filtering or hidden into account... need
     # to be fixed?      # to be fixed?
Line 1419  sub render { Line 1466  sub render {
             $link .= '&amp;register='.$env{'form.register'};              $link .= '&amp;register='.$env{'form.register'};
         }          }
  if ($args->{'caller'} eq 'navmapsdisplay') {   if ($args->{'caller'} eq 'navmapsdisplay') {
     &add_linkitem($args->{'linkitems'},'changefolder',              unless ($args->{'notools'}) {
   "location.href='$link'",$text);                  &add_linkitem($args->{'linkitems'},'changefolder',
                                 "location.href='$link'",$text);
               }
  } else {   } else {
     $result.= '<a href="'.$link.'">'.&mt($text).'</a>';      $result.= '<a href="'.$link.'">'.&mt($text).'</a>';
  }   }
Line 1428  sub render { Line 1477  sub render {
     }      }
   
     # Check for any unread discussions in all resources.      # Check for any unread discussions in all resources.
     if ($args->{'caller'} eq 'navmapsdisplay') {      if (($args->{'caller'} eq 'navmapsdisplay') && (!$args->{'notools'})) {
  &add_linkitem($args->{'linkitems'},'clearbubbles',   &add_linkitem($args->{'linkitems'},'clearbubbles',
       'document.clearbubbles.submit()',        'document.clearbubbles.submit()',
       'Mark all posts read');        'Mark all posts read');
Line 1461  END Line 1510  END
  }   }
  $result.='</form>';   $result.='</form>';
     }      }
       if (($args->{'caller'} eq 'navmapsdisplay') &&
           (&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) {
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           if ($env{'course.'.$env{'request.course.id'}.'.url'} eq 
               "uploaded/$cdom/$cnum/default.sequence") {
               &add_linkitem($args->{'linkitems'},'edittoplevel',
                             "javascript:gocmd('/adm/coursedocs','editdocs');",
                             'Content Editor');
           }
       }
   
     if ($args->{'caller'} eq 'navmapsdisplay') {      if ($args->{'caller'} eq 'navmapsdisplay') {
         $result .= '<table><tr><td>'.          $result .= &show_linkitems_toolbar($args,$condition);
                    &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').'</td>';  
     $result .= '<td>&nbsp;</td>';   
  $result.='<td class="LC_middle">'.&mt('Tools:').'</td>';  
  $result.=&show_linkitems_toolbar($args->{'linkitems'});  
         if ($args->{'sort_html'}) {  
             $result.='<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>'.  
                 '<td align="right">'.$args->{'sort_html'}.'</td></tr>';  
         }  
         $result .= '</table>';  
     } elsif ($args->{'sort_html'}) {       } elsif ($args->{'sort_html'}) { 
         $result.=$args->{'sort_html'};           $result.=$args->{'sort_html'}; 
     }      }
Line 1604  END Line 1655  END
     $curRes = shift(@resources);      $curRes = shift(@resources);
  } else {   } else {
     $curRes = $it->next($closeAllPages);      $curRes = $it->next($closeAllPages);
   
  }   }
  if (!$curRes) { last; }   if (!$curRes) { last; }
   
Line 1809  sub add_linkitem { Line 1861  sub add_linkitem {
 }  }
   
 sub show_linkitems_toolbar {  sub show_linkitems_toolbar {
     my ($linkitems,$condition)=@_;      my ($args,$condition) = @_;
     my @linkorder = ('firsthomework','everything','uncompleted',      my $result;
                      'changefolder','clearbubbles');      if (ref($args) eq 'HASH') {
     my $result .='<td align="left">'."\n".           if (ref($args->{'linkitems'}) eq 'HASH') {
                  '<span class="LC_nobreak">'."\n".              my $numlinks = scalar(keys(%{$args->{'linkitems'}}));
                  '<ul id="LC_toolbar">';              if ($numlinks > 1) {
     foreach my $link (@linkorder) {                  $result = '<td>'.
         my $link_id = 'LC_content_toolbar_'.$link;                            &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',
         if (defined($linkitems->{$link})) {                                                               undef,'RAT').
             if ($linkitems->{$link}{'text'} ne '') {                            '</td>'.
                 $linkitems->{$link}{'cmd'}=~s/"/'/g;                            '<td>&nbsp;</td>'.
                 if ($linkitems->{$link}{'cmd'}) {                            '<td class="LC_middle">'.&mt('Tools:').'</td>';
                     if ($link eq 'changefolder') {              }
                         if ($condition) {              $result .= '<td align="left">'."\n".
                             $link_id='LC_content_toolbar_changefolder_toggled';                         '<span class="LC_nobreak">'."\n".
                         } else {                         '<ul id="LC_toolbar">';
                             $link_id='LC_content_toolbar_changefolder';              my @linkorder = ('firsthomework','everything','uncompleted',
                                'changefolder','clearbubbles','edittoplevel');
               foreach my $link (@linkorder) {
                   if (ref($args->{'linkitems'}{$link}) eq 'HASH') {
                       if ($args->{'linkitems'}{$link}{'text'} ne '') {
                           $args->{'linkitems'}{$link}{'cmd'}=~s/"/'/g;
                           if ($args->{'linkitems'}{$link}{'cmd'}) {
                               my $link_id = 'LC_content_toolbar_'.$link;
                               if ($link eq 'changefolder') {
                                   if ($condition) {
                                       $link_id='LC_content_toolbar_changefolder_toggled';
                                   } else {
                                       $link_id='LC_content_toolbar_changefolder';
                                   }
                               }
                               $result .= '<li><a href="#" '.
                                          'onclick="'.$args->{'linkitems'}{$link}{'cmd'}.'" '.
                                          'id="'.$link_id.'" '.
                                          'class="LC_toolbarItem" '.
                                          'title="'.$args->{'linkitems'}{$link}{'text'}.'">'.
                                          '</a></li>'."\n";
                         }                          }
                     }                      }
                     $result .= '<li><a href="#" '.  
                                'onclick="'.$linkitems->{$link}{'cmd'}.'" '.  
                                'id="'.$link_id.'" '.  
                                'class="LC_toolbarItem" '.  
                                'title="'.$linkitems->{$link}{'text'}.'">'.  
                                '</a></li>'."\n";  
                 }                  }
             }              }
               $result .= '</ul>'.
                          '</span></td>';
               if (($numlinks==1) && (exists($args->{'linkitems'}{'edittoplevel'}))) {
                   $result .= '<td><a href="'.$args->{'linkitems'}{'edittoplevel'}{'cmd'}.'">'.
                              &mt('Content Editor').'</a></td>';
               }
         }          }
           if ($args->{'sort_html'}) {
               $result .= '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>'.
                          '<td align="right">'.$args->{'sort_html'}.'</td>';
           }
       }
       if ($result) {
           $result = "<table><tr>$result</tr></table>";
     }      }
     $result .= '</ul>'.  
                '</span></td>'."\n";  
     return $result;      return $result;
 }  }
   
   
 1;  1;
   
   
Line 1930  sub new { Line 2006  sub new {
     my $proto = shift;      my $proto = shift;
     my $class = ref($proto) || $proto;      my $class = ref($proto) || $proto;
     my $self = {};      my $self = {};
       bless($self); # So we can call change_user if neceesary
   
     $self->{USERNAME} = shift || $env{'user.name'};      $self->{USERNAME} = shift || $env{'user.name'};
     $self->{DOMAIN}   = shift || $env{'user.domain'};      $self->{DOMAIN}   = shift || $env{'user.domain'};
   
   
   
     # 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.
     $self->{RESOURCE_CACHE} = {};      $self->{RESOURCE_CACHE} = {};
Line 1942  sub new { Line 2021  sub new {
     # failed      # failed
     $self->{NETWORK_FAILURE} = 0;      $self->{NETWORK_FAILURE} = 0;
   
     # tie the nav hash      # We can only tie the nav hash as done below if the username/domain
       # match the env one. Otherwise change_user does everything we need...since we can't
       # assume there are course hashes for the specific requested user@domamin:
       #
   
     my %navmaphash;      if ( ($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'})) {
     my %parmhash;  
     my $courseFn = $env{"request.course.fn"};   # tie the nav hash
     if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db",  
               &GDBM_READER(), 0640))) {   my %navmaphash;
         return undef;   my %parmhash;
     }   my $courseFn = $env{"request.course.fn"};
        if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db",
     if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db",    &GDBM_READER(), 0640))) {
               &GDBM_READER(), 0640)))      return undef;
     {   }
         untie %{$self->{PARM_HASH}};  
         return undef;   if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db",
     &GDBM_READER(), 0640)))
    {
       untie %{$self->{PARM_HASH}};
       return undef;
    }
   
    $self->{NAV_HASH} = \%navmaphash;
    $self->{PARM_HASH} = \%parmhash;
    $self->{PARM_CACHE} = {};
       } else {
    $self->change_user($self->{USERNAME}, $self->{DOMAIN});
     }      }
   
     $self->{NAV_HASH} = \%navmaphash;      my $d = Data::Dumper->new([$self]);
     $self->{PARM_HASH} = \%parmhash;  
     $self->{PARM_CACHE} = {};  
   
     bless($self);  
           
     return $self;      return $self;
 }  }
   
   #
   #  In some instances it is useful to be able to dynamically change the
   # username/domain associated with a navmap (e.g. to navigate for someone
   # else besides the current user...if sufficiently privileged.
   # Parameters:
   #    user  - New user.
   #    domain- Domain the user belongs to.
   # Implicit inputs:
   #   
   sub change_user {
       my $self = shift;
       $self->{USERNAME} = shift;
       $self->{DOMAIN}   = shift;
   
       # If the hashes are already tied make sure to break that bond:
   
       untie %{$self->{NAV_HASH}}; 
       untie %{$self->{PARM_HASH}};
   
       # The assumption is that we have to
       # use lonmap here to re-read the hash and from it reconstruct
       # new big and parameter hashes.  An implicit assumption at this time
       # is that the course file is probably not created locally yet
       # an that we will therefore just read without tying.
   
       my ($cdom, $cnum) = split(/\_/, $env{'request.course.id'});
   
       my %big_hash;
       &Apache::lonmap::loadmap($cnum, $cdom, $self->{USERNAME}, $self->{DOMAIN}, \%big_hash);
       $self->{NAV_HASH} = \%big_hash;
   
   
   
       # Now clear the parm cache and reconstruct the parm hash fromt he big_hash
       # param.xxxx keys.
   
       $self->{PARM_CACHE} = {};
       
       my %parm_hash = {};
       foreach my $key (keys %big_hash) {
    if ($key =~ /^param\./) {
       my $param_key = $key;
       $param_key =~ s/^param\.//;
       $parm_hash{$param_key} = $big_hash{$key};
    }
       }
   
       $self->{PARM_HASH} = \%parm_hash;
      
   
   
       
   } 
   
 sub generate_course_user_opt {  sub generate_course_user_opt {
     my $self = shift;      my $self = shift;
     if ($self->{COURSE_USER_OPT_GENERATED}) { return; }      if ($self->{COURSE_USER_OPT_GENERATED}) { return; }
Line 2955  sub new { Line 3098  sub new {
     if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) {       if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { 
         my $firstResource = $resource->map_start();          my $firstResource = $resource->map_start();
         my $finishResource = $resource->map_finish();          my $finishResource = $resource->map_finish();
         return    my $result;
             Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,   my $rdump  = Data::Dumper->new([$result]);
                                               $finishResource, $self->{FILTER},   $result =  Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
                                               $self->{ALREADY_SEEN},        $finishResource, $self->{FILTER},
                                               $self->{CONDITION},       $self->{ALREADY_SEEN}, 
       $self->{FORCE_TOP});       $self->{CONDITION},
        $self->{FORCE_TOP});
    return $result;
              
                   
     }      }
   
Line 2980  sub new { Line 3126  sub new {
     $self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1;      $self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1;
   
     bless ($self);      bless ($self);
       my $selfDump = Data::Dumper->new([$self]);
   
     return $self;      return $self;
 }  }
Line 2995  sub next { Line 3142  sub next {
     # do so.      # do so.
     if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) {      if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) {
         $self->{HAVE_RETURNED_0} = 1;          $self->{HAVE_RETURNED_0} = 1;
    my $nextTopLevel = $self->{NAV_MAP}->getById('0.0');
   
         return $self->{NAV_MAP}->getById('0.0');          return $self->{NAV_MAP}->getById('0.0');
     }      }
     if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) {      if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) {
Line 3014  sub next { Line 3163  sub next {
         if ($self->{RECURSIVE_DEPTH} == 0) {          if ($self->{RECURSIVE_DEPTH} == 0) {
             $self->{RECURSIVE_ITERATOR_FLAG} = 0;              $self->{RECURSIVE_ITERATOR_FLAG} = 0;
         }          }
   
         return $next;          return $next;
     }      }
   
     if (defined($self->{FORCE_NEXT})) {      if (defined($self->{FORCE_NEXT})) {
         my $tmp = $self->{FORCE_NEXT};          my $tmp = $self->{FORCE_NEXT};
         $self->{FORCE_NEXT} = undef;          $self->{FORCE_NEXT} = undef;
   
         return $tmp;          return $tmp;
     }      }
   
Line 3090  sub next { Line 3239  sub next {
     # So we need to look at all the resources we can get to from here,      # So we need to look at all the resources we can get to from here,
     # categorize them if we haven't seen them, remember if we have a new      # categorize them if we haven't seen them, remember if we have a new
     my $nextUnfiltered = $here->getNext();      my $nextUnfiltered = $here->getNext();
   
   
     my $maxDepthAdded = -1;      my $maxDepthAdded = -1;
           
     for (@$nextUnfiltered) {      for (@$nextUnfiltered) {
Line 3123  sub next { Line 3274  sub next {
         $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();
   
         $self->{RECURSIVE_ITERATOR} =           $self->{RECURSIVE_ITERATOR} = 
             Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,              Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
                                               $finishResource, $self->{FILTER},                                                $finishResource, $self->{FILTER},
Line 3141  sub next { Line 3291  sub next {
         return $self->next($closeAllPages);          return $self->next($closeAllPages);
     }      }
   
       my $hereResource = $self->{HERE};
   
     return $self->{HERE};      return $self->{HERE};
   
 }  }
Line 3307  sub next { Line 3459  sub next {
     my $nextUnfiltered;      my $nextUnfiltered;
     if ($self->{DIRECTION} == FORWARD()) {      if ($self->{DIRECTION} == FORWARD()) {
         $nextUnfiltered = $self->{HERE}->getNext();          $nextUnfiltered = $self->{HERE}->getNext();
   
     } else {      } else {
         $nextUnfiltered = $self->{HERE}->getPrevious();          $nextUnfiltered = $self->{HERE}->getPrevious();
     }      }
Line 3461  sub new { Line 3614  sub new {
     $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self;      $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self;
     $self->{RESOURCE_ERROR} = 0;      $self->{RESOURCE_ERROR} = 0;
   
       $self->{DUEDATE_CACHE} = undef;
   
     # A hash that can be used by two-pass algorithms to store data      # A hash that can be used by two-pass algorithms to store data
     # about this resource in. Not used by the resource object      # about this resource in. Not used by the resource object
     # directly.      # directly.
Line 3720  sub is_practice { Line 3875  sub is_practice {
 sub is_problem {  sub is_problem {
     my $self=shift;      my $self=shift;
     my $src = $self->src();      my $src = $self->src();
     if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {      if ($src =~ /$LONCAPA::assess_re/) {
  return !($self->is_practice());   return !($self->is_practice());
     }      }
     return 0;      return 0;
Line 3755  sub is_incomplete { Line 3910  sub is_incomplete {
 sub is_raw_problem {  sub is_raw_problem {
     my $self=shift;      my $self=shift;
     my $src = $self->src();      my $src = $self->src();
     if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {      if ($src =~ /$LONCAPA::assess_re/) {
         return 1;          return 1;
     }      }
     return 0;      return 0;
Line 3997  sub printable { Line 4152  sub printable {
   
     # Get the print open/close dates for the resource.      # Get the print open/close dates for the resource.
   
     my $start = $self->parmval("prinstartdate", $part);      my $start = $self->parmval("printstartdate", $part);
     my $end   = $self->parmval("printenddate", $part);      my $end   = $self->parmval("printenddate", $part);
   
     #  The following cases apply:      #  The following cases apply:
Line 4099  sub checkedin { Line 4254  sub checkedin {
   
 sub duedate {  sub duedate {
     (my $self, my $part) = @_;      (my $self, my $part) = @_;
       if (defined ($self->{DUEDATE_CACHE}->{$part})) {
           return $self->{DUEDATE_CACHE}->{$part};
       }
     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);
Line 4115  sub duedate { Line 4273  sub duedate {
     } else {      } else {
  $date = $due_date;   $date = $due_date;
     }      }
       $self->{DUEDATE_CACHE}->{$part} = $date;
     return $date;      return $date;
 }  }
 sub handgrade {  sub handgrade {
Line 4966  sub status { Line 5125  sub status {
     }      }
   
     # Otherwise, it's untried and open      # Otherwise, it's untried and open
     return OPEN;       return OPEN;
 }  }
   
 sub check_for_slot {  sub check_for_slot {
     my $self = shift;      my $self = shift;
     my $part = shift;      my $part = shift;
       my $symb = $self->symb();
     my ($use_slots,$available,$availablestudent) = $self->slot_control($part);      my ($use_slots,$available,$availablestudent) = $self->slot_control($part);
     if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) {      if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) {
         my @slots = (split(/:/,$availablestudent),split(/:/,$available));          my @slots = (split(/:/,$availablestudent),split(/:/,$available));
Line 4979  sub check_for_slot { Line 5139  sub check_for_slot {
         my $cdom=$env{'course.'.$cid.'.domain'};          my $cdom=$env{'course.'.$cid.'.domain'};
         my $cnum=$env{'course.'.$cid.'.num'};          my $cnum=$env{'course.'.$cid.'.num'};
         my $now = time;          my $now = time;
           my $num_usable_slots = 0;
         if (@slots > 0) {          if (@slots > 0) {
             my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum);              my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum);
             if (&Apache::lonnet::error(%slots)) {              if (&Apache::lonnet::error(%slots)) {
                 return (UNKNOWN);                  return (UNKNOWN);
             }              }
             my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots);              my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots,'starttime');
             my ($checkedin,$checkedinslot);              my ($checkedin,$checkedinslot);
             foreach my $slot_name (@sorted_slots) {              foreach my $slot_name (@sorted_slots) {
                 next if (!defined($slots{$slot_name}) ||                  next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name}));
                          !ref($slots{$slot_name}));  
                 my $end = $slots{$slot_name}->{'endtime'};                  my $end = $slots{$slot_name}->{'endtime'};
                 my $start = $slots{$slot_name}->{'starttime'};                  my $start = $slots{$slot_name}->{'starttime'};
                 my $ip = $slots{$slot_name}->{'ip'};                  my $ip = $slots{$slot_name}->{'ip'};
                 if ($self->simpleStatus() == OPEN) {                  if ($self->simpleStatus() == OPEN) {
                     my $startreserve = $slots{$slot_name}->{'startreserve'};  
                     my @proctors;  
                     if ($slots{$slot_name}->{'proctor'} ne '') {  
                         @proctors = split(',',$slots{$slot_name}->{'proctor'});  
                     }  
                     if ($end > $now) {                      if ($end > $now) {
                         ($checkedin,$checkedinslot) = $self->checkedin();                          if ($start > $now) {
                         if ($startreserve < $now) {                              return (RESERVED_LATER,$start,$slot_name);
                             if ($start > $now) {                          } else {
                                 return (RESERVED_LATER,$start,$slot_name);                              if ($ip ne '') {
                             } else {                                  if (!&Apache::loncommon::check_ip_acc($ip)) {
                                 if ($ip ne '') {                                      return (RESERVED_LOCATION,$ip,$slot_name);
                                     if (!&Apache::loncommon::check_ip_acc($ip)) {  
                                         return (RESERVED_LOCATION,$ip,$slot_name);  
                                     }  
                                 }   
                                 if (@proctors > 0) {  
                                     unless ((grep(/^\Q$checkedin\E/,@proctors)) &&  
                                         ($checkedinslot eq $slot_name)) {  
                                         return (NEEDS_CHECKIN,undef,$slot_name);   
                                     }  
                                 }                                  }
                                 return (RESERVED,$end,$slot_name);  
                             }                              }
                         } else {                              my @proctors;
                             if ($start > $now) {                              if ($slots{$slot_name}->{'proctor'} ne '') {
                                 return (RESERVABLE,$startreserve,$slot_name);                                  @proctors = split(',',$slots{$slot_name}->{'proctor'});
                               }
                               if (@proctors > 0) {
                                   ($checkedin,$checkedinslot) = $self->checkedin();
                                   unless ((grep(/^\Q$checkedin\E/,@proctors)) &&
                                           ($checkedinslot eq $slot_name)) {
                                       return (NEEDS_CHECKIN,undef,$slot_name); 
                                   }
                             }                              }
                               return (RESERVED,$end,$slot_name);
                         }                          }
                     }                      }
                   } elsif ($end > $now) {
                       $num_usable_slots ++;
                 }                  }
             }              }
             my ($is_correct,$got_grade);              my ($is_correct,$got_grade);
Line 5043  sub check_for_slot { Line 5198  sub check_for_slot {
                     return (CORRECT);                       return (CORRECT); 
                 }                  }
             }              }
             return(NOT_IN_A_SLOT);              if ($num_usable_slots) {
         } else {  
             if (!$future_slots_checked) {  
                 $future_slots = &get_future_slots($cdom,$cnum,$now);  
                 $future_slots_checked = 1;  
             }  
             if ($future_slots) {  
                 return(NOT_IN_A_SLOT);                  return(NOT_IN_A_SLOT);
             }              }
             return(NOTRESERVABLE);  
         }          }
     }          my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'},
     return;                                                                 $env{'user.domain'});
 }          if (ref($reservable) eq 'HASH') {
               if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) {
 sub get_future_slots {                  foreach my $slot (reverse (@{$reservable->{'now_order'}})) {
     my ($cdom,$cnum,$now) = @_;                      if (($reservable->{'now'}{$slot}{'symb'} eq '') ||
     my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);                          ($reservable->{'now'}{$slot}{'symb'} eq $symb)) {
     my $future_slots = 0;                          return(RESERVABLE,$reservable->{'now'}{$slot}{'endreserve'});
     foreach my $slot (keys(%slots)) {                      }
         if (($slots{$slot}->{'starttime'} > $now) &&                  }
             ($slots{$slot}->{'endtime'} > $now)) {              }
             $future_slots ++;              if ((ref($reservable->{'future_order'}) eq 'ARRAY') && (ref($reservable->{'future'}) eq 'HASH')) {
                   foreach my $slot (@{$reservable->{'future_order'}}) {
                       if (($reservable->{'future'}{$slot}{'symb'} eq '') ||
                           ($reservable->{'future'}{$slot}{'symb'} eq $symb)) {
                           return(RESERVABLE_LATER,$reservable->{'future'}{$slot}{'startreserve'});
                       }
                   }
               }
         }          }
           return(NOTRESERVABLE);
     }      }
     return $future_slots;      return;
 }  }
   
 sub CLOSED { return 23; }  sub CLOSED { return 23; }

Removed from v.1.461  
changed lines
  Added in v.1.482


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