Diff for /loncom/interface/slotrequest.pm between versions 1.125.2.3.4.1 and 1.125.2.3.4.2

version 1.125.2.3.4.1, 2019/06/24 03:23:36 version 1.125.2.3.4.2, 2020/04/08 20:06:59
Line 456  sub make_reservation { Line 456  sub make_reservation {
  return 'error: Unable to determine current status';   return 'error: Unable to determine current status';
     }      }
   
     my $parm_symb  = $symb;      my $symb_for_db = $symb;
     my $parm_level = 1;      my $parm_level = 1;
     if ($use_slots eq 'map' || $use_slots eq 'map_map') {      if ($use_slots eq 'map' || $use_slots eq 'map_map') {
  my ($map) = &Apache::lonnet::decode_symb($symb);   my ($map) = &Apache::lonnet::decode_symb($symb);
  $parm_symb = &Apache::lonnet::symbread($map);   $symb_for_db = &Apache::lonnet::symbread($map);
  $parm_level = 2;   $parm_level = 2;
     }      }
   
Line 503  sub make_reservation { Line 503  sub make_reservation {
           
     my %reservation=('name'      => $env{'user.name'}.':'.$env{'user.domain'},      my %reservation=('name'      => $env{'user.name'}.':'.$env{'user.domain'},
      'timestamp' => time,       'timestamp' => time,
      'symb'      => $parm_symb);       'symb'      => $symb_for_db);
   
     my $success=&Apache::lonnet::newput('slot_reservations',      my $success=&Apache::lonnet::newput('slot_reservations',
  {"$slot_name\0$wanted" =>   {"$slot_name\0$wanted" =>
Line 515  sub make_reservation { Line 515  sub make_reservation {
  if ($value) {   if ($value) {
     $new_value=$value.':'.$new_value;      $new_value=$value.':'.$new_value;
  }   }
         &store_slot_parm($symb,$slot_name,$parm_level,$new_value,$cnum,$cdom);          my $result = &store_slot_parm($symb,$symb_for_db,$slot_name,$parm_level,
                                         $new_value,$cnum,$cdom,$env{'user.name'},
                                         $env{'user.domain'},'reserve',$env{'form.context'});
  return $wanted;   return $wanted;
     }      }
   
Line 524  sub make_reservation { Line 526  sub make_reservation {
 }  }
   
 sub store_slot_parm {  sub store_slot_parm {
     my ($symb,$slot_name,$parm_level,$new_value,$cnum,$cdom) = @_;      my ($symb_for_parm,$symb_for_db,$slot_name,$parm_level,$new_value,
     my $result=&Apache::lonparmset::storeparm_by_symb($symb,          $cnum,$cdom,$uname,$udom,$action,$context,$delflag) = @_;
                                                   '0_availablestudent',  
                                                    $parm_level, $new_value,      # store new parameter string
                                                    'string',      my $result=&Apache::lonparmset::storeparm_by_symb($symb_for_parm,
                                                    $env{'user.name'},                                                        '0_availablestudent',
                                                    $env{'user.domain'});                                                        $parm_level,$new_value,
                                                         'string',$uname,$udom);
     &Apache::lonxml::debug("hrrm $result");      &Apache::lonxml::debug("hrrm $result");
     my %storehash = (      my %storehash = (
                        symb    => $symb,                         symb    => $symb_for_db,
                        slot    => $slot_name,                         slot    => $slot_name,
                        action  => 'reserve',                         action  => $action,
                        context => $env{'form.context'},                         context => $context,
                     );                      );
   
     &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,      &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
                                '',$env{'user.name'},$env{'user.domain'},                                 $delflag,$uname,$udom,$cnum,$cdom);
                                $cnum,$cdom);  
     &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,      &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
                                1,$env{'user.name'},$env{'user.domain'},                                 $delflag,$uname,$udom,$uname,$udom);
                                $env{'user.name'},$env{'user.domain'});      return $result;
   
     return;  
 }  }
   
 sub remove_registration {  sub remove_registration {
Line 642  sub release_all_slot { Line 642  sub release_all_slot {
     &release_reservation($slot_name,$uname,$udom,      &release_reservation($slot_name,$uname,$udom,
  $consumed{$entry}{'symb'},$mgr);   $consumed{$entry}{'symb'},$mgr);
         if (!$result) {          if (!$result) {
             $r->print('<p><span class="LC_error">'.&mt($msg).'</span></p>');              $r->print('<p class="LC_error">'.&mt($msg).'</p>');
         } else {          } else {
     $r->print("<p>$msg</p>");      $r->print("<p>$msg</p>");
         }          }
Line 672  sub release_slot { Line 672  sub release_slot {
     my ($result,$msg) =      my ($result,$msg) =
  &release_reservation($slot_name,$uname,$udom,$symb,$mgr);   &release_reservation($slot_name,$uname,$udom,$symb,$mgr);
     if (!$result) {      if (!$result) {
         $r->print('<p><span class="LC_error">'.&mt($msg).'</span></p>');          $r->print('<p class="LC_error">'.&mt($msg).'</p>');
     } else {      } else {
         $r->print("<p>$msg</p>");          $r->print("<p>$msg</p>");
     }      }
Line 690  sub release_reservation { Line 690  sub release_reservation {
     my ($slot_name,$uname,$udom,$symb,$mgr) = @_;      my ($slot_name,$uname,$udom,$symb,$mgr) = @_;
     my %slot=&Apache::lonnet::get_slot($slot_name);      my %slot=&Apache::lonnet::get_slot($slot_name);
     my $description=&get_description($slot_name,\%slot);      my $description=&get_description($slot_name,\%slot);
       my $msg;
   
     if ($mgr ne 'F') {      if ($mgr ne 'F') {
  if ($slot{'starttime'} < time) {   if ($slot{'starttime'} < time) {
     return (0,&mt('Not allowed to release Reservation: [_1], as it has already ended.',$description));      return (0,&mt('Not allowed to release Reservation: [_1], as it has already started.',$description));
  }   }
     }      }
       my $context = $env{'form.context'};
   
     # if the reservation symb is for a map get a resource in that map      # get navmap object
     # to check slot parameters on  
     my $navmap=Apache::lonnavmaps::navmap->new;      my $navmap=Apache::lonnavmaps::navmap->new;
     if (!defined($navmap)) {      if (!defined($navmap)) {
         return (0,'error: Unable to determine current status');          return (0,'error: Unable to determine current status');
     }      }
   
       my ($cnum,$cdom)=&get_course();
   
       # get slot reservations, check if user has reservation
       my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                                          "^$slot_name\0");
   
       #
       # If release is because of a reservation *change*, symb(s) associated with reservation
       # being dropped may differ from the current symb.
       #
       # We need to get symb(s) from slot_reservations.db, and for each symb, update
       # the value of the availablestudent parameter, at the appropriate level
       # (as dictated by the value of the useslots parameter for the symb and user).
       #
       # We also delete all entries for the slot being released, for the specific user.
       #
   
       my $conflict;
   
       if (($env{'form.command'} eq 'change') && ($slot_name eq $env{'form.releaseslot'}) &&
           ($env{'form.slotname'} ne $slot_name)) {
           my %changedto = &Apache::lonnet::get_slot($env{'form.slotname'});
   
           # check for conflicts
           my ($to_uniq_start,$to_uniq_end,$from_uniq_start,$from_uniq_end);
           if (ref($changedto{'uniqueperiod'}) eq 'ARRAY') {
               ($to_uniq_start,$to_uniq_end) = @{$changedto{'uniqueperiod'}};
           }
           if (ref($slot{'uniqueperiod'}) eq 'ARRAY') {
               ($from_uniq_start,$from_uniq_end) = @{$slot{'uniqueperiod'}};
           }
           my $to_start = $changedto{'starttime'};
           my $to_end = $changedto{'endtime'};
           my $from_start = $slot{'starttime'};
           my $from_end = $slot{'endtime'};
   
           if (!
                ($from_start < $to_uniq_start && $from_end < $to_uniq_start) ||
                ($from_start > $to_uniq_end   && $from_end > $to_uniq_end  )) {
               $conflict = 1;
           }
           if (!
                ($to_start < $from_uniq_start && $to_end < $from_uniq_start) ||
                ($to_start > $from_uniq_end   && $to_end > $from_uniq_end  )) {
               $conflict = 1;
           }
   
           if ($conflict) {
               my %symbs_for_slot;
               my (%to_delete,%failed,%released);
               foreach my $entry (keys(%consumed)) {
                   if ( $consumed{$entry}->{'name'} eq ($uname.':'.$udom) ) {
                       $symbs_for_slot{$consumed{$entry}->{'symb'}} = 1;
                       $to_delete{$entry} = 1;
                   }
               }
               if (keys(%to_delete)) {
                   my @removals = keys(%to_delete);
                   if (&Apache::lonnet::del('slot_reservations',\@removals,
                                        $cdom,$cnum) eq 'ok') {
                       foreach my $item (keys(%symbs_for_slot)) {
                           my $result = &update_selectable($navmap,$slot_name,$item,$cdom,
                                                           $cnum,$udom,$uname,$context);
                           if ($result =~ /^error/) {
                               $failed{$item} = 1;
                           } else {
                               $released{$item} = 1;
                           }
                       }
                   }
               }
               if (keys(%released)) {
                   $msg = '<span style="font-weight: bold;">'.
                          &mt('Released Reservation: [_1]',$description).'</span>&nbsp;&nbsp;'.
                          &mt('The following items had their reservation status change').':';
                   my (%folders,%pages,%container,%titles);
                   foreach my $item (keys(%released)) {
                       my $res = $navmap->getBySymb($item);
                       if (ref($res)) {
                           $titles{$item} = $res->title();
                           if ($res->is_map()) {
                               $folders{$item}{'title'} = $titles{$item};
                               if ($res->is_page()) {
                                   $pages{$item}{'title'} = $titles{$item};
                               } else {
                                   $folders{$item}{'title'} = $titles{$item};
                               }
                           } else {
                               my $mapsrc = $res->enclosing_map_src();
                               my $map = $navmap->getResourceByUrl($mapsrc);
                               if (ref($map)) {
                                   if ($map->id() eq '0.0') {
                                       $container{$mapsrc}{'title'} &mt('Top level of course');
                                   } else {
                                       $container{$mapsrc}{'title'} = $map->title();
                                       if ($map->is_page()) {
                                           $container{$mapsrc}{'page'} = 1;
                                       }
                                   }
                               }
                               $container{$mapsrc}{'resources'}{$item} = 1;
                           }
                       }
                   }
                   $msg .= '<ul>';
                   if (keys(%folders)) {
                       $msg .= '<li>'.&mt('Folders').': '.
                               join(', ', map { $folders{$_}{'title'} } (sort { $folders{$b}{'title'} cmp $folders{$a}{'title'} } (keys(%folders)))).
                               '</li>';
                   }
                   if (keys(%pages)) {
                       $msg .= '<li>'.&mt('Composite Pages').': '.
                               join(', ', map { $pages{$_}{'title'} } (sort { $pages{$b}{'title'} cmp $pages{$a}{'title'} } (keys(%pages)))).
                               '</li>';
                   }
                   if (keys(%container)) {
                       $msg .= '<li>'.&mt('Resources').':<ul>';
                       foreach my $key (sort { $container{$b}{'title'} cmp $container{$a}{'title'} } (keys(%container))) {
                           if (ref($container{$key}{'resources'}) eq 'HASH') {
                               $msg .= '<li>'.
                                       join(', ', map { $titles{$_} } (sort(keys(%{$container{$key}{'resources'}}))));
                               if ($container{$key}{'page'}) {
                                   $msg .= ' '.&mt('(in composite page [_1])',$container{$key}{'title'}).'</li>';
                               } else {
                                   $msg .= ' '.&mt('(in folder [_1])',$container{$key}{'title'}).'</li>';
                               }
                           }
                       }
                       $msg .= '</ul></li>';
                   }
                   $msg .= '</ul>';
                   my $person = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'});
                   my $subject = &mt('Reservation change: [_1]',$description);
                   my $msgbody = &mt('Reservation released by [_1] for [_2].',$person,$description);
                   $msg .= &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'release');
                   return (1,$msg);
               } else {
                   if (keys(%to_delete)) {
                       $msg = &mt('Reservation release partially complete for [_1]',$description);
                   } else {
                       $msg = &mt('No entries found for this user to release for [_1].',$description);
                   }
                   return (0,$msg);
               }
           } else {
               $msg = &mt('No conflict found; not releasing: [_1].',$description);
               return (0,$msg);
           }
       }
   
       my $map_symb;
       my $parm_symb = $symb;
     my $passed_resource = $navmap->getBySymb($symb);      my $passed_resource = $navmap->getBySymb($symb);
   
       # if the reservation symb is for a map get a resource in that map
       # to check slot parameters on
       my $parm_level = 1;
     if (ref($passed_resource)) {      if (ref($passed_resource)) {
         if ($passed_resource->is_map()) {          if ($passed_resource->is_map()) {
     my ($a_resource) =       my ($a_resource) = 
                 $navmap->retrieveResources($passed_resource,                   $navmap->retrieveResources($passed_resource, 
                                            sub {$_[0]->is_problem()},0,1);                                             sub {$_[0]->is_problem()},0,1);
             $symb = $a_resource->symb();              $parm_symb = $a_resource->symb();
         }          }
     } else {      } else {
         unless ($mgr eq 'F') {          unless ($mgr eq 'F') {
Line 717  sub release_reservation { Line 875  sub release_reservation {
         }          }
     }      }
   
     # get parameter string, check for existence, rebuild string with the slot      # Get value of useslots parameter in effect for this user.
     my $student = &Apache::lonnet::EXT("resource.0.availablestudent",      # If value is map or map_map, then the parm level is 2 (i.e.,
                                        $symb,$udom,$uname);      # non-recursive enclosing map/folder level for specific user)
     my @slots = split(/:/,$student);      # and the symb for this reservation in slot_reservations.db
       # will be the symb of the map itself.
   
     my @new_slots;      my $use_slots = &Apache::lonnet::EXT('resource.0.useslots',
     foreach my $exist_slot (@slots) {                                           $parm_symb,$udom,$uname);
  if ($exist_slot eq $slot_name) { next; }      if (&Apache::lonnet::error($use_slots)) {
  push(@new_slots,$exist_slot);          return (0,'error: Unable to determine current status');
       }
       if ($use_slots eq 'map' || $use_slots eq 'map_map') {
           $parm_level = 2;
           if ($passed_resource->is_map()) {
               $map_symb = $passed_resource->symb();
           } else {
               my ($map) = &Apache::lonnet::decode_symb($symb);
               $map_symb = &Apache::lonnet::symbread($map);
           }
     }      }
     my $new_param = join(':',@new_slots);  
       #
       # If release is *not* because of a reservation change, i.e., this is a "drop"
       # by a student, or a removal for a single student by an instructor then
       # only remove one entry from slot_reservations.db, where both the user
       # and the symb match the current context.  If useslots was set to map or
       # map_map, then the symb to match in slot_reservations.db is the symb of
       # the enclosing map/folder, not the symb of the resource.
       #
   
       my ($match,$symb_to_check);
       if ($parm_level == 2) {
           $symb_to_check = $map_symb;
       } else {
           $symb_to_check = $parm_symb;
       }
       foreach my $entry (keys(%consumed)) {
           if ( $consumed{$entry}->{'name'} eq ($uname.':'.$udom) ) {
               if ($consumed{$entry}->{'symb'} eq $symb_to_check) {
                   if (&Apache::lonnet::del('slot_reservations',[$entry],
                                            $cdom,$cnum) eq 'ok') {
                       $match = $symb_to_check;
                   }
                   last;
               }
           }
       }
       if ($match) {
           if (&update_selectable($navmap,$slot_name,$symb,$cdom,
                                  $cnum,$udom,$uname,$context) =~ /^error/) {
               if ($mgr eq 'F') {
                   $msg = &mt('Reservation release partially complete for: [_1]',"$uname:$udom").'<br />'.
                          &mt('Update of availablestudent parameter for [_1] was not completed.',"$uname:$udom");
               } else {
                   $msg = &mt('Release partially complete for: [_1]',$description);
               }
               return (0,$msg);
           } else {
               if ($mgr eq 'F') {
                   $msg = &mt('Released Reservation for user: [_1]',"$uname:$udom");
               } else {
                   $msg = '<span style="font-weight: bold;">'.&mt('Released reservation: [_1]',$description).'</span><br /><br />';
                   my $person = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'});
                   my $subject = &mt('Reservation change: [_1]',$description);
                   my $msgbody = &mt('Reservation released by [_1] for [_2].',$person,$description);
                   $msg .= &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'release');
               }
               return (1,$msg);
           }
       } else {
           $msg = &mt('Release failed for: [_1]',$description);
           return (0,$msg);
       }
   }
   
   sub update_selectable {
       my ($navmap,$slot_name,$symb,$cdom,$cnum,$udom,$uname,$context) = @_;
       return 'error: ' unless (ref($navmap));
       my $symb_for_parm = $symb;
       my $passed_resource = $navmap->getBySymb($symb);
       return 'error: invalid symb' unless (ref($passed_resource));
   
       # if the reservation symb is for a map get a resource in that map
       # to check slot parameters on
       if ($passed_resource->is_map()) {
           my ($a_resource) =
               $navmap->retrieveResources($passed_resource,
                                          sub {$_[0]->is_problem()},0,1);
           $symb_for_parm = $a_resource->symb();
       }
       # get parameter string, check for existence, rebuild string with the slot
       my $student = &Apache::lonnet::EXT('resource.0.availablestudent',
                                          $symb_for_parm,$udom,$uname);
   
     # Get value of useslots parameter in effect for this user.      # Get value of useslots parameter in effect for this user.
     # If value is map or map_map, then the parm level is 2 (i.e.,      # If value is map or map_map, then the parm level is 2 (i.e.,
Line 735  sub release_reservation { Line 975  sub release_reservation {
     # and the symb for this reservation in slot_reservations.db      # and the symb for this reservation in slot_reservations.db
     # will be the symb of the map itself.      # will be the symb of the map itself.
   
     my $use_slots = &Apache::lonnet::EXT("resource.0.useslots",      my $use_slots = &Apache::lonnet::EXT('resource.0.useslots',
                                          $symb,$udom,$uname);                                           $symb_for_parm,$udom,$uname);
     &Apache::lonxml::debug("use_slots is  $use_slots<br />");      &Apache::lonxml::debug("use_slots is  $use_slots<br />");
   
     if (&Apache::lonnet::error($use_slots)) {      if (&Apache::lonnet::error($use_slots)) {
         return (0,'error: Unable to determine current status');          return 'error: Unable to determine current status';
     }      }
   
     my $parm_level = 1;      my $parm_level = 1;
     my $parm_symb = $passed_resource->symb();  
     if ($use_slots eq 'map' || $use_slots eq 'map_map') {      if ($use_slots eq 'map' || $use_slots eq 'map_map') {
         $parm_level = 2;          $parm_level = 2;
         unless ($passed_resource->is_map()) {  
             my ($map) = &Apache::lonnet::decode_symb($parm_symb);  
             $parm_symb = &Apache::lonnet::symbread($map);  
         }  
     }      }
   
     my ($cnum,$cdom)=&get_course();      my @slots = split(/:/,$student);
   
     # get slot reservations, check if user has one for the      my @new_slots;
     # correct symb, and if so, remove the reservation      foreach my $exist_slot (@slots) {
     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,          next if ($exist_slot eq $slot_name);
        "^$slot_name\0");          push(@new_slots,$exist_slot);
     foreach my $entry (keys(%consumed)) {  
         if (($consumed{$entry}->{'name'} eq $uname.':'.$udom) &&  
             ($consumed{$entry}->{'symb'} eq $parm_symb)) {  
     &Apache::lonnet::del('slot_reservations',[$entry],  
  $cdom,$cnum);  
             my %storehash = (  
                                symb    => $symb,  
                                slot    => $slot_name,  
                                action  => 'release',  
                                context => $env{'form.context'},  
                         );  
             &Apache::lonnet::write_log('course','slotreservationslog',  
                                        \%storehash,1,$uname,$udom,$cnum,$cdom);  
             &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',  
                                        \%storehash,1,$uname,$udom,$uname,$udom);  
  }  
     }      }
       my $new_value = join(':',@new_slots);
   
     # store new parameter string      my $result = &store_slot_parm($symb_for_parm,$symb,$slot_name,$parm_level,
     my $result=&Apache::lonparmset::storeparm_by_symb($symb,                                    $new_value,$cnum,$cdom,$uname,$udom,'release',
       '0_availablestudent',                                    $context,1);
       $parm_level, $new_param,      return $result;
       'string', $uname, $udom);  
     my $msg;  
     if ($mgr eq 'F') {  
  $msg = &mt('Released Reservation for user: [_1]',"$uname:$udom");  
     } else {  
  $msg = '<span style="font-weight: bold;">'.&mt('Released reservation: [_1]',$description).'</span><br /><br />';  
         my $person = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'});  
         my $subject = &mt('Reservation change: [_1]',$description);  
         my $msgbody = &mt('Reservation released by [_1] for [_2].',$person,$description);  
         $msg .= &slot_change_messaging($slot{'reservationmsg'},$subject,$msgbody,'release');  
     }  
     return (1,$msg);  
 }  }
   
 sub delete_slot {  sub delete_slot {
Line 814  sub delete_slot { Line 1022  sub delete_slot {
  if ($ret eq 'ok') {   if ($ret eq 'ok') {
     $r->print('<p>'.&mt('Slot [_1] marked as deleted.','<tt>'.$slot_name.'</tt>').'</p>');      $r->print('<p>'.&mt('Slot [_1] marked as deleted.','<tt>'.$slot_name.'</tt>').'</p>');
  } else {   } else {
     $r->print('<p><span class="LC_error">'.&mt('An error occurred when attempting to delete slot: [_1]','<tt>'.$slot_name.'</tt>')." ($ret)</span></p>");      $r->print('<p class="LC_error">'.&mt('An error occurred when attempting to delete slot: [_1]','<tt>'.$slot_name.'</tt>')." ($ret)</p>");
  }   }
     } else {      } else {
  if (%consumed) {   if (%consumed) {
Line 846  sub get_slot { Line 1054  sub get_slot {
     my $slot_name=&check_for_conflict($symb,$env{'form.slotname'},\%slot);      my $slot_name=&check_for_conflict($symb,$env{'form.slotname'},\%slot);
   
     if ($slot_name =~ /^error: (.*)/) {      if ($slot_name =~ /^error: (.*)/) {
  $r->print('<p><span class="LC_error">'   $r->print('<p class="LC_error">'
                  .&mt('An error occurred while attempting to make a reservation. ([_1])',$1)                   .&mt('An error occurred while attempting to make a reservation. ([_1])',$1)
                  .'</span></p>');                   .'</p>');
  &return_link($r);   &return_link($r);
  return 0;   return 0;
     }      }
Line 901  STUFF Line 1109  STUFF
     if (defined($reserved)) {      if (defined($reserved)) {
  my $retvalue = 0;   my $retvalue = 0;
  if ($slot_name =~ /^error: (.*)/) {   if ($slot_name =~ /^error: (.*)/) {
     $r->print('<p><span class="LC_error">'      $r->print('<p class="LC_error">'
                      .&mt('An error occurred while attempting to make a reservation. ([_1])',$1)                       .&mt('An error occurred while attempting to make a reservation. ([_1])',$1)
                      .'</span></p>');                       .'</p>');
  } elsif ($reserved > -1) {   } elsif ($reserved > -1) {
     $r->print('<p style="font-weight: bold;">'.&mt('Successfully signed up:  [_1]',$description).'</p>');      $r->print('<p style="font-weight: bold;">'.&mt('Successfully signed up:  [_1]',$description).'</p>');
     $retvalue = 1;      $retvalue = 1;

Removed from v.1.125.2.3.4.1  
changed lines
  Added in v.1.125.2.3.4.2


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