--- loncom/interface/loncoursegroups.pm 2006/11/20 23:49:49 1.64
+++ loncom/interface/loncoursegroups.pm 2007/01/03 21:55:37 1.69
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: loncoursegroups.pm,v 1.64 2006/11/20 23:49:49 raeburn Exp $
+# $Id: loncoursegroups.pm,v 1.69 2007/01/03 21:55:37 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -92,13 +92,13 @@ sub handler {
my $action = $env{'form.action'};
my $state = $env{'form.state'};
- if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify') || ($action eq 'delete')) {
+ if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify') || ($action eq 'delete') || ($action eq 'reenable')) {
if (!defined($state)) {
$state = 'view';
}
}
if ($action eq 'create' || $action eq 'modify' || $action eq 'view' ||
- $action eq 'delete') {
+ $action eq 'delete' || $action eq 'reenable') {
if ($view_permission || $manage_permission) {
if ($state eq 'view') {
&print_main_menu($r,$cdom,$cnum,\%functions,\%idx,
@@ -167,11 +167,14 @@ sub display_groups {
view => ' 'print(&mt('Group deletion failed'));
+ $r->print(&mt('Group deletion failed.'));
}
}
return;
}
+sub reenable_folder {
+ my ($cdom,$cnum,$groupname,$description) = @_;
+ my $outcome;
+ my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
+ my $allgrpsmap = $crspath.'group_allfolders.sequence';
+ my $foldertitle = &mt('Course Folder -').$description;
+ my $mapurl = $crspath.'group_folder_'.
+ $groupname.'.sequence';
+ my ($errtext,$fatal)=&LONCAPA::map::mapread($allgrpsmap);
+ if ($fatal) {
+ $outcome=&mt('Error reading contents of parent folder to group').
+ " ($allgrpsmap): $errtext".'
';
+ } else {
+ my $idx=&LONCAPA::map::getresidx($mapurl);
+ $LONCAPA::map::resources[$idx] = $foldertitle.':'.$mapurl.
+ ':false:normal:res';
+ $LONCAPA::map::order[1+$#LONCAPA::map::order]=$idx;
+ my ($outtext,$errtext) = &LONCAPA::map::storemap($allgrpsmap,1);
+ if ($errtext) {
+ $outcome = &mt('Error storing updated parent folder to group').
+ "- $allgrpsmap - $errtext".'
';
+ } else {
+ my ($furl,$ferr) =
+ &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
+ }
+ }
+ return $outcome;
+}
+
sub modify_folders {
my ($cdom,$cnum,$groupname) = @_;
my $outcome;
@@ -1173,8 +1233,12 @@ sub modify_folders {
my $groupmap = '/uploaded/'.$cdom.'/'.$cnum.'/'.'group_folder_'.
$groupname.'.sequence';
my $groupmapres = $navmap->getResourceByUrl($groupmap);
+ my ($map,$id,$src);
if ($groupmapres) {
- my ($map,$id,$src)=&Apache::lonnet::decode_symb($groupmapres->symb());
+ ($map,$id,$src)=&Apache::lonnet::decode_symb($groupmapres->symb());
+ }
+ undef($navmap);
+ if ($map) {
$map = '/'.$map;
my ($errtext,$fatal) = &LONCAPA::map::mapread($map);
if ($fatal) {
@@ -1201,17 +1265,116 @@ sub modify_folders {
}
$#LONCAPA::map::order--;
my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1);
- if ($outtext) {
- $outcome = &mt('Error storing updated parent folder to group'). " ($map): $errtext".'
';
- return;
- }
+ if ($errtext) {
+ $outcome = &mt('Error storing updated parent folder to group'). "- $map - $errtext".'
';
+ } else {
+ my ($furl,$ferr) =
+ &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
+ }
}
}
}
- undef($navmap);
return $outcome;
}
+sub verify_reenable {
+ my ($r,$groupname,$formname,$action,$page,$states,$stored) = @_;
+ $r->print(&Apache::lonhtmlcommon::echo_form_input([]));
+ $r->print(&mt("You have requested enabling the following previously deleted group: ").''.
+ $stored->{'description'}.''.
+ '
'.&mt('When a deleted group is re-enabled the following occurs:').''.
+ '- '.&mt('Group settings and membership at the time the group was deleted are reinstated.').'
'.
+ '- '.&mt('A group folder is added to the "Course Groups" folder which contains folders for all groups in the course.').'
');
+ my $prevtext = &mt('Go back');
+ my $nexttext = &mt('Reenable group');
+ my $prev;
+ if ($env{'form.refpage'} eq 'enrl') {
+ $prev = 'view';
+ }
+ &display_navbuttons($r,$formname,$prev,$prevtext,
+ $$states{$action}[$page+1],$nexttext);
+ return;
+}
+
+sub reenable_group {
+ my ($r,$cdom,$cnum,$groupname) = @_;
+ my %groups =
+ &Apache::longroup::coursegroups($cdom,$cnum,$groupname,
+ 'deleted_groups');
+ if (keys(%groups) == 0) {
+ $r->print(&mt('The group ([_1]) was not re-enabled, because it is not a deleted group.
Perhaps it has already been re-enabled?',$groupname));
+ return;
+ }
+ my %groupinfo =
+ &Apache::longroup::get_group_settings($groups{$groupname});
+ my $defstart = $groupinfo{'startdate'};
+ my $defend = $groupinfo{'enddate'};
+ my $showstart = &Apache::lonlocal::locallocaltime($defstart);
+ my $showend;
+ if ($defend == 0) {
+ $showend = &mt('No end date set');
+ } else {
+ $showend = &Apache::lonlocal::locallocaltime($defend);
+ }
+ my $description = &unescape($groupinfo{'description'});
+ my $num_users = 0;
+ my $num_ok = 0;
+ my $num_fail = 0;
+ my (%usersettings,@enabled,@unenabled);
+ my ($result,$message) =
+ &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum,$groupname,
+ 'reenable');
+ if ($result eq 'ok') {
+ my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
+ $groupname);
+ foreach my $key (sort(keys(%membership))) {
+ if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
+ my $user = $1;
+ my($end,$start,$userprivs) = split(/:/,$membership{$key},3);
+ if (($start == -1) && ($end == $groupinfo{'modified'})) {
+ $num_users ++;
+ $usersettings{$groupname.':'.$user} = $defend.':'.
+ $defstart.':'.
+ $userprivs;
+ if (&Apache::lonnet::modify_group_roles($cdom,$cnum,
+ $groupname,$user,
+ $defend,$defstart,
+ $userprivs) eq 'ok') {
+ $num_ok ++;
+ push(@enabled,$user);
+ } else {
+ push(@unenabled,$user);
+ $num_fail ++;
+ }
+ }
+ }
+ }
+ if ($num_users > 0) {
+ if ($num_ok > 0) {
+ my $roster_result =
+ &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum,
+ \%usersettings);
+ if ($roster_result eq 'ok') {
+ $r->print(&mt('Membership reinstated for [_1] users, each with start and end dates for group access set to defaults: [_2] and [_3]',$num_ok,$showstart,$showend).'
');
+ }
+ } else {
+ $r->print(&mt('A problem occurred when trying to reinstate [_1] of the [_2] members of the pre-existing group.',$num_fail,$num_users).'
');
+ }
+ } else {
+ $r->print(&mt('There were no group members to reinstate, as none were removed when the group was deleted.').'
');
+ }
+ my $outcome = &reenable_folder($cdom,$cnum,$groupname,$description);
+ if ($outcome eq '') {
+ $r->print(&mt('Group successfully re-enabled.'));
+ } else {
+ $r->print(&mt("Although the group was re-enabled, an error ([_1]) occurred when adding the group's folder to the 'Course Groups' folder.",$outcome));
+ }
+ } else {
+ $r->print(&mt('Re-enabling group failed'));
+ }
+ return;
+}
+
sub header {
my ($bodytitle,$jscript,$action,$state,$page,$loaditems) = @_;
my $start_page=
@@ -2976,7 +3139,7 @@ sub write_group_data {
$description,$tools,\%groupinfo,
$gpterm,$ucgpterm,$crstype);
if ($result ne 'ok') {
- $r->print(&mt('A problem occurred when creating folders for the new [_1]. [_2].
',$gpterm,$result));
+ $r->print(&mt('A problem occurred when creating folders for the new [_1].
[_2]
',$gpterm,$result));
}
$r->print(&mt('[_1] [_2] was created.
',$ucgpterm,$groupname));
} elsif ($action eq 'modify') {
@@ -3510,28 +3673,38 @@ sub add_group_folder {
if ($cdom eq '' || $cnum eq '') {
return &mt('Error: invalid course domain or number - group folder creation failed');
}
- my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage);
- my $navmap = Apache::lonnavmaps::navmap->new();
+ my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage,$warning);
my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
$allgrpsmap = $crspath.'group_allfolders.sequence';
- my $topmap = $navmap->getResourceByUrl($allgrpsmap);
- undef($navmap);
if ($action eq 'create') {
- # check if group_allfolders.sequence exists.
- if (!$topmap) {
- my $grpstitle = &mt('[_1] [_2]s',$crstype,$ucgpterm);
- my $topmap_url = '/'.$env{'course.'.$env{'request.course.id'}.'.url'};
- $topmap_url =~ s|/+|/|g;
- if ($topmap_url =~ m|^/uploaded|) {
- $outcome = &map_updater($cdom,$cnum,'group_allfolders.sequence',
- 'toplevelgroup',$grpstitle,$topmap_url);
+ if (&get_folder_lock($cdom,$cnum,'group_allfolders',$now) eq 'ok') {
+ # check if group_allfolders.sequence exists.
+ my $mapcontents = &Apache::lonnet::getfile($allgrpsmap);
+ if ($mapcontents eq '-1') { #file does not exist;
+ my $grpstitle = &mt('[_1] [_2]s',$crstype,$ucgpterm);
+ my $topmap_url = '/'.$env{'course.'.$env{'request.course.id'}.'.url'};
+ $topmap_url =~ s|/+|/|g;
+ if ($topmap_url =~ m|^/uploaded|) {
+ $outcome = &map_updater($cdom,$cnum,'group_allfolders.sequence',
+ 'toplevelgroup',$grpstitle,$topmap_url);
+ } else {
+ $outcome = &mt('Non-standard course - folder for all groups not added.');
+ }
if ($outcome ne 'ok') {
+ my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders');
+ if ($delresult ne 'ok') {
+ $warning = $delresult;
+ }
return $outcome;
}
- } else {
- $outcome = &mt('Non-standard course - folder for all groups not added.');
- return $outcome;
}
+ my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders');
+ if ($delresult ne 'ok') {
+ $warning = $delresult ;
+ }
+ } else {
+ $outcome = &mt('Could not obtain exclusive lock to check status of the folder for all groups. No group folder added.');
+ return $outcome;
}
my $grpfolder = &mt('[_1] Folder -',$ucgpterm,).$description;
$grppage='/adm/'.$cdom.'/'.$cnum.'/'.$groupname.'/smppg';
@@ -3541,7 +3714,7 @@ sub add_group_folder {
'grpseq',$grpfolder,$allgrpsmap,$grppage,
$grptitle);
if ($outcome ne 'ok') {
- return $outcome;
+ return $outcome.$warning;
}
my $pageout = &create_homepage($cdom,$cnum,$groupname,$groupinfo,
$tools,$gpterm,$ucgpterm,$now);
@@ -3552,7 +3725,7 @@ sub add_group_folder {
my $outcome = &map_updater($cdom,$cnum,'group_boards_'.$groupname.
'.sequence','bbseq',$disctitle,$grpmap);
if ($outcome ne 'ok') {
- return $outcome;
+ return $outcome.$warning;
}
$boardsmap = $crspath.'group_boards_'.$groupname.'.sequence';
}
@@ -3560,7 +3733,7 @@ sub add_group_folder {
#modify group folder if status of discussions tools is changed
}
my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
- $navmap = Apache::lonnavmaps::navmap->new();
+ my $navmap = Apache::lonnavmaps::navmap->new();
# modify parameters
my $parm_result;
if ($action eq 'create') {
@@ -3574,8 +3747,39 @@ sub add_group_folder {
$parm_result .= &parm_setter($navmap,$cdom,$boardsmap,$groupname);
}
}
+ undef($navmap);
if ($parm_result) {
- return $parm_result;
+ return $warning.$parm_result;
+ } else {
+ return 'ok';
+ }
+}
+
+sub get_folder_lock {
+ my ($cdom,$cnum,$folder_name,$now) = @_;
+ # get lock for folder being edited.
+ my $lockhash = {
+ $folder_name."\0".'locked_folder' => $now.':'.$env{'user.name'}.
+ ':'.$env{'user.domain'},
+ };
+ my $tries = 0;
+ my $gotlock = &Apache::lonnet::newput('coursegroups',$lockhash,$cdom,$cnum);
+
+ while (($gotlock ne 'ok') && $tries <3) {
+ $tries ++;
+ sleep(1);
+ $gotlock = &Apache::lonnet::newput('coursegroups',$lockhash,$cdom,$cnum);
+ }
+ return $gotlock;
+}
+
+sub release_folder_lock {
+ my ($cdom,$cnum,$folder_name) = @_;
+ # remove lock
+ my @del_lock = ($folder_name."\0".'locked_folder');
+ my $dellockoutcome=&Apache::lonnet::del('coursegroups',\@del_lock,$cdom,$cnum);
+ if ($dellockoutcome ne 'ok') {
+ return ('
'.&mt('Warning: failed to release lock for folder: [_1].',$folder_name).'
');
} else {
return 'ok';
}
@@ -3592,7 +3796,7 @@ sub map_updater {
if ($newmapurl !~ m|^/uploaded|) {
$outcome = &mt('Error uploading new folder.')." ($newfile): $newmapurl".'
';
return $outcome;
- }
+ }
my ($errtext,$fatal)=&LONCAPA::map::mapread($parentmap);
if ($fatal) {
$outcome = &mt('Error reading contents of parent folder')." ($parentmap): $errtext".'
';
@@ -3603,7 +3807,7 @@ sub map_updater {
':false:normal:res';
$LONCAPA::map::order[1+$#LONCAPA::map::order]=$newidx;
my ($outtext,$errtext) = &LONCAPA::map::storemap($parentmap,1);
- if ($outtext) {
+ if ($errtext) {
$outcome = &mt('Error storing updated parent folder')." ($parentmap): $errtext".'
';
return $outcome;
}
@@ -3638,18 +3842,23 @@ sub parm_setter {
},
);
my $res = $navmap->getResourceByUrl($url);
- my $symb = $res->symb();
- foreach my $level (keys(%hide_settings)) {
- my $parmresult = &Apache::lonparmset::storeparm_by_symb($symb,
+ if ($res) {
+ my $symb = $res->symb();
+ foreach my $level (keys(%hide_settings)) {
+ my $parmresult =
+ &Apache::lonparmset::storeparm_by_symb($symb,
'0_hiddenresource',
$hide_settings{$level}{'num'},
$hide_settings{$level}{'set'},
'string_yesno',undef,$cdom,
undef,undef,
$hide_settings{$level}{'extra'});
- if ($parmresult) {
- $allresults .= $level.': '.$parmresult;
+ if ($parmresult) {
+ $allresults .= $level.': '.$parmresult;
+ }
}
+ } else {
+ $allresults = &mt('Parameters not set for [_1] because the resource was not recognized as part of the course',$url).'
';
}
return $allresults;
}
@@ -3713,7 +3922,8 @@ sub validate_groupname {
my ($groupname,$action,$cdom,$cnum,$gpterm,$ucgpterm,$crstype) = @_;
my %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
- my %deleted_groups = &Apache::lonnet::get_deleted_groups($cdom,$cnum);
+ my %deleted_groups = &Apache::longroup::coursegroups($cdom,$cnum,undef,
+ 'deleted_groups');
if (my $tmp = &Apache::lonnet::error(%deleted_groups)) {
undef(%deleted_groups);
&Apache::lonnet::logthis('Error retrieving groups: '.$tmp.' in '.$cnum.':'.$cdom);