[LON-CAPA-cvs] cvs: loncom(version_2_11_X) /interface slotrequest.pm
raeburn
raeburn at source.lon-capa.org
Sun Jul 7 18:06:50 EDT 2019
raeburn Sun Jul 7 22:06:50 2019 EDT
Modified files: (Branch: version_2_11_X)
/loncom/interface slotrequest.pm
Log:
- For 2.11
Backport 1.141, 1.142
-------------- next part --------------
Index: loncom/interface/slotrequest.pm
diff -u loncom/interface/slotrequest.pm:1.125.2.7 loncom/interface/slotrequest.pm:1.125.2.8
--- loncom/interface/slotrequest.pm:1.125.2.7 Sat Jun 22 19:18:28 2019
+++ loncom/interface/slotrequest.pm Sun Jul 7 22:06:50 2019
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler for requesting to have slots added to a students record
#
-# $Id: slotrequest.pm,v 1.125.2.7 2019/06/22 19:18:28 raeburn Exp $
+# $Id: slotrequest.pm,v 1.125.2.8 2019/07/07 22:06:50 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -456,11 +456,11 @@
return 'error: Unable to determine current status';
}
- my $parm_symb = $symb;
+ my $symb_for_db = $symb;
my $parm_level = 1;
if ($use_slots eq 'map' || $use_slots eq 'map_map') {
my ($map) = &Apache::lonnet::decode_symb($symb);
- $parm_symb = &Apache::lonnet::symbread($map);
+ $symb_for_db = &Apache::lonnet::symbread($map);
$parm_level = 2;
}
@@ -503,7 +503,7 @@
my %reservation=('name' => $env{'user.name'}.':'.$env{'user.domain'},
'timestamp' => time,
- 'symb' => $parm_symb);
+ 'symb' => $symb_for_db);
my $success=&Apache::lonnet::newput('slot_reservations',
{"$slot_name\0$wanted" =>
@@ -515,7 +515,9 @@
if ($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;
}
@@ -524,29 +526,27 @@
}
sub store_slot_parm {
- my ($symb,$slot_name,$parm_level,$new_value,$cnum,$cdom) = @_;
- my $result=&Apache::lonparmset::storeparm_by_symb($symb,
- '0_availablestudent',
- $parm_level, $new_value,
- 'string',
- $env{'user.name'},
- $env{'user.domain'});
+ my ($symb_for_parm,$symb_for_db,$slot_name,$parm_level,$new_value,
+ $cnum,$cdom,$uname,$udom,$action,$context,$delflag) = @_;
+
+ # store new parameter string
+ my $result=&Apache::lonparmset::storeparm_by_symb($symb_for_parm,
+ '0_availablestudent',
+ $parm_level,$new_value,
+ 'string',$uname,$udom);
&Apache::lonxml::debug("hrrm $result");
my %storehash = (
- symb => $symb,
+ symb => $symb_for_db,
slot => $slot_name,
- action => 'reserve',
- context => $env{'form.context'},
+ action => $action,
+ context => $context,
);
&Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
- '',$env{'user.name'},$env{'user.domain'},
- $cnum,$cdom);
+ $delflag,$uname,$udom,$cnum,$cdom);
&Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
- 1,$env{'user.name'},$env{'user.domain'},
- $env{'user.name'},$env{'user.domain'});
-
- return;
+ $delflag,$uname,$udom,$uname,$udom);
+ return $result;
}
sub remove_registration {
@@ -642,7 +642,7 @@
&release_reservation($slot_name,$uname,$udom,
$consumed{$entry}{'symb'},$mgr);
if (!$result) {
- $r->print('<p><span class="LC_error">'.&mt($msg).'</span></p>');
+ $r->print('<p class="LC_error">'.&mt($msg).'</p>');
} else {
$r->print("<p>$msg</p>");
}
@@ -672,7 +672,7 @@
my ($result,$msg) =
&release_reservation($slot_name,$uname,$udom,$symb,$mgr);
if (!$result) {
- $r->print('<p><span class="LC_error">'.&mt($msg).'</span></p>');
+ $r->print('<p class="LC_error">'.&mt($msg).'</p>');
} else {
$r->print("<p>$msg</p>");
}
@@ -690,26 +690,184 @@
my ($slot_name,$uname,$udom,$symb,$mgr) = @_;
my %slot=&Apache::lonnet::get_slot($slot_name);
my $description=&get_description($slot_name,\%slot);
+ my $msg;
if ($mgr ne 'F') {
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
- # to check slot parameters on
+ # get navmap object
my $navmap=Apache::lonnavmaps::navmap->new;
if (!defined($navmap)) {
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> '.
+ &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);
+
+ # 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 ($passed_resource->is_map()) {
my ($a_resource) =
$navmap->retrieveResources($passed_resource,
sub {$_[0]->is_problem()},0,1);
- $symb = $a_resource->symb();
+ $parm_symb = $a_resource->symb();
}
} else {
unless ($mgr eq 'F') {
@@ -717,17 +875,99 @@
}
}
- # get parameter string, check for existence, rebuild string with the slot
- my $student = &Apache::lonnet::EXT("resource.0.availablestudent",
- $symb,$udom,$uname);
- my @slots = split(/:/,$student);
+ # 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.,
+ # non-recursive enclosing map/folder level for specific user)
+ # and the symb for this reservation in slot_reservations.db
+ # will be the symb of the map itself.
- my @new_slots;
- foreach my $exist_slot (@slots) {
- if ($exist_slot eq $slot_name) { next; }
- push(@new_slots,$exist_slot);
+ my $use_slots = &Apache::lonnet::EXT('resource.0.useslots',
+ $parm_symb,$udom,$uname);
+ if (&Apache::lonnet::error($use_slots)) {
+ 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);
+ }
+ }
+
+ #
+ # 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);
}
- my $new_param = join(':', at new_slots);
+}
+
+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]->is_tool() },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.
# If value is map or map_map, then the parm level is 2 (i.e.,
@@ -735,64 +975,32 @@
# and the symb for this reservation in slot_reservations.db
# will be the symb of the map itself.
- my $use_slots = &Apache::lonnet::EXT("resource.0.useslots",
- $symb,$udom,$uname);
+ my $use_slots = &Apache::lonnet::EXT('resource.0.useslots',
+ $symb_for_parm,$udom,$uname);
&Apache::lonxml::debug("use_slots is $use_slots<br />");
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_symb = $passed_resource->symb();
if ($use_slots eq 'map' || $use_slots eq 'map_map') {
$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
- # correct symb, and if so, remove the reservation
- my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
- "^$slot_name\0");
- 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_slots;
+ foreach my $exist_slot (@slots) {
+ next if ($exist_slot eq $slot_name);
+ push(@new_slots,$exist_slot);
}
+ my $new_value = join(':', at new_slots);
- # store new parameter string
- my $result=&Apache::lonparmset::storeparm_by_symb($symb,
- '0_availablestudent',
- $parm_level, $new_param,
- '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);
+ my $result = &store_slot_parm($symb_for_parm,$symb,$slot_name,$parm_level,
+ $new_value,$cnum,$cdom,$uname,$udom,'release',
+ $context,1);
+ return $result;
}
sub delete_slot {
@@ -814,7 +1022,7 @@
if ($ret eq 'ok') {
$r->print('<p>'.&mt('Slot [_1] marked as deleted.','<tt>'.$slot_name.'</tt>').'</p>');
} 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 {
if (%consumed) {
@@ -846,9 +1054,9 @@
my $slot_name=&check_for_conflict($symb,$env{'form.slotname'},\%slot);
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)
- .'</span></p>');
+ .'</p>');
&return_link($r);
return 0;
}
@@ -901,9 +1109,9 @@
if (defined($reserved)) {
my $retvalue = 0;
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)
- .'</span></p>');
+ .'</p>');
} elsif ($reserved > -1) {
$r->print('<p style="font-weight: bold;">'.&mt('Successfully signed up: [_1]',$description).'</p>');
$retvalue = 1;
More information about the LON-CAPA-cvs
mailing list