[LON-CAPA-cvs] cvs: loncom /interface longroup.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Thu, 18 May 2006 12:33:15 -0000


This is a MIME encoded message

--raeburn1147955595
Content-Type: text/plain

raeburn		Thu May 18 08:33:15 2006 EDT

  Added files:                 
    /loncom/interface	longroup.pm 
  Log:
  Apparently longroup.pm was omitted from prior commit.   &coursegroups() and &get_group_settings() moved to longroup.pm, which contains general utility functions for asking about groups.  Also contains &group_changes() which is used to add/drop group memberships as a result of role changes, as determined by group settings for auto-add and auto-drop.
  
  
--raeburn1147955595
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20060518083315.txt"


Index: loncom/interface/longroup.pm
+++ loncom/interface/longroup.pm
# The LearningOnline Network with CAPA
# accessor routines used to provide information about course groups 
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
                                                                                
package Apache::longroup;
                                                                                
use strict;
use Apache::lonnet;

###############################################
=pod

=item coursegroups

Retrieve information about groups in a course,

Input:
1. Optional course domain
2. Optional course number
3. Optional group name

Course domain and number will be taken from user's
environment if not supplied. Optional group name will 
be passed to lonnet::get_coursegroups() as a regexp to
use in the call to the dump function.
                                                                                
Output
Returns hash of groups in the course (subject to the
optional group name filter). In the hash, the keys are
group names, and their corresponding values
are scalars containing group information in XML. This
can be sent to &get_group_settings() to be parsed.

Side effects:
None.
=cut

###############################################

sub coursegroups {
    my ($cdom,$cnum,$group) = @_;
    if (!defined($cdom) || !defined($cnum)) {
        my $cid =  $env{'request.course.id'};

        return if (!defined($cid));

        $cdom = $env{'course.'.$cid.'.domain'};
        $cnum = $env{'course.'.$cid.'.num'};
    }
    my %curr_groups = &Apache::lonnet::get_coursegroups($cdom,$cnum,$group);
    my ($tmp) = keys(%curr_groups);
    if ($tmp=~/^(con_lost|no_such_host|error: [^2] )/) {
        undef(%curr_groups);
        &logthis('Error retrieving groups: '.$tmp.' in '.$cnum.':'.$cdom);
    } elsif ($tmp=~/^error: 2 /) {
        undef(%curr_groups);
    }
    return %curr_groups;
}

###############################################

=item get_group_settings
                                                                                
Uses TokeParser to extract group information from the
XML used to describe course groups.
                                                                                
Input:
Scalar containing XML  - as retrieved from &coursegroups().
                                                                                
Output:
Hash containing group information as key=values for (a), and
hash of hashes for (b)
                                                                                
Keys (in two categories):
(a) groupname, creator, creation, modified, startdate,enddate.
Corresponding values are name of the group, creator of the group
(username:domain), UNIX time for date group was created, and
settings were last modified, and default start and end access
times for group members.
                                                                                
(b) functions returned in hash of hashes.
Outer hash key is functions.
Inner hash keys are chat,discussion,email,files,homepage,roster.
Corresponding values are either on or off, depending on
whether this type of functionality is available for the group.
                                                                                
=cut

###############################################

sub get_group_settings {
    my ($groupinfo)=@_;
    my $parser=HTML::TokeParser->new(\$groupinfo);
    my $token;
    my $tool = '';
    my $role = '';
    my %content=();
    while ($token=$parser->get_token) {
        if ($token->[0] eq 'S')  {
            my $entry=$token->[1];
            if ($entry eq 'functions' || $entry eq 'autosec') {
                %{$content{$entry}} = ();
                $tool = $entry;
            } elsif ($entry eq 'role') {
                if ($tool eq 'autosec') {
                    $role = $token->[2]{id};
                    @{$content{$tool}{$role}} = ();
                }
            } else {
                my $value=$parser->get_text('/'.$entry);
                if ($entry eq 'name') {
                    if ($tool eq 'functions') {
                        my $function = $token->[2]{id};
                        $content{$tool}{$function} = $value;
                    }
                } elsif ($entry eq 'groupname') {
                    $content{$entry}=&unescape($value);
                } elsif (($entry eq 'roles') || ($entry eq 'types') ||
                         ($entry eq 'sectionpick') || ($entry eq 'defpriv')) {
                    push(@{$content{$entry}},$value);
                } elsif ($entry eq 'section') {
                    if ($tool eq 'autosec'  && $role ne '') {
                        push(@{$content{$tool}{$role}},$value);
                    }
                } else {
                    $content{$entry}=$value;
                }
            }
        } elsif ($token->[0] eq 'E') {
            if ($token->[1] eq 'functions' || $token->[1] eq 'autosec') {
                $tool = '';
            } elsif ($token->[1] eq 'role') {
                $role = '';
            }
                                                                                
        }
    }
    return %content;
}

###############################################

sub check_group_access {
    my ($group) = @_;
    my $access = 1;
    my $now = time;
    my ($start,$end) = split(/\./,$env{'user.role.gr/'.$env{'request.course,id'}.'/'.$group});
    if (($end!=0) && ($end<$now)) { $access = 0; }
    if (($start!=0) && ($start>$now)) { $access=0; }
    return $access;
}

###############################################

=pod
                                                                                
=item group_changes

Add or drop group memberships in a course as a result of
changes in a user's roles/sections. Called by
&Apache::lonnet:assignrole()     
                                                                                
Input:
1. User's domain
2. User's username
3. Url of role
4. Role
5. End date of role
6. Start date of role

Checks to see if role for which assignment is being made is in a course.
If so, gathers information about auto-group population settings for
groups in the course.

If role is being expired, will also expire any group memberships that
are specified for auto-group population for the specific role and
section (including section 'none' and 'all' sections), unless a
different role/section also included in auto-group population
for the course is included amongst the user's unexpired roles
and would trigger membership in teh same group(s) 

If role is being added, will add any group memberships specified
for auto-group population, unless use is already a group member.
Uses default group privileges and default start and end group access
times. 

Output
None

Side effects:
May result in calls to Apache::lonnet::modify_group_roles()
and Apache::lonnet::modify_coursegroup_membership() to add
or expire group membership(s) for a user. 

=cut

sub group_changes {
    my ($udom,$uname,$url,$role,$origend,$origstart) = @_;
    my $now = time;
    my $chgtype;
    if ($origend > 0 && $origend <= $now) {
        $chgtype = 'drop';
    } else {
        $chgtype = 'add';
    }
    my ($cid,$cdom,$cnum,$sec);
    if ($url =~ m-^(/[^/]+/[^/]+)/([^/]+)$-) {
        $cid = $1;
        $sec = $2;
    } else {
        $cid = $url;
    }
    my $courseid = $cid;
    $courseid =~ s|^/||;
    $courseid =~ s|/|_|;
    my %crshash=&Apache::lonnet::coursedescription($cid);
    $cdom = $crshash{'domain'};
    $cnum = $crshash{'num'};
    if (defined($cdom) && defined($cnum)) {
        my %settings;
        my @changegroups = ();
        my %dropgroup = ();
        my %dropstart = ();
        my %addgroup = ();
        my %curr_groups = &coursegroups($cdom,$cnum);
        if (%curr_groups) {
            foreach my $group (keys(%curr_groups)) {
                %{$settings{$group}}=&get_group_settings($curr_groups{$group});
                if ($chgtype eq 'add') {
                    if (!($settings{$group}{autoadd} eq 'on')) {
                        next;
                    }
                } else {
                    if (!($settings{$group}{autodrop} eq 'on')) {
                        next;
                    }
                }
                my @autosec = ();
                if (ref($settings{$group}{'autosec'}{$role}) eq 'ARRAY') {
                    @autosec = @{$settings{$group}{'autosec'}{$role}};
                }
                if ($sec eq '') {
                    $sec = 'none';
                }
                if ((grep(/^$sec$/,@autosec)) || (grep(/^all$/,@autosec))) {
                    push(@changegroups,$group);
                }
            }
        }
       if (@changegroups > 0) {
            my %currpriv;
            my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,$cid);
            my ($tmp) = keys(%roleshash);
            if ($tmp=~/^error:/) {
                &Apache::lonnet::logthis('Error retrieving roles: '.$tmp.
                                         ' for '.$uname.':'.$udom);
            } else {
                my $group_privs = '';
                foreach my $group (@changegroups) {
                    if ($chgtype eq 'add') {
                        if (ref($settings{$group}{'defpriv'}) eq 'ARRAY') {
                            $group_privs =
                                  join(':',@{$settings{$group}{'defpriv'}});
                        }
                    }
                    my $key = $cid.'/'.$group.'_gr';
                    if (defined($roleshash{$key})) {
                        if ($roleshash{$key}=~ /^gr\/([^_]*)_(\d+)_([\-\d]+)$/) {
                            my $grpstart = $3;
                            my $grpend = $2;
                            $currpriv{$group} = $1;
                            if ($chgtype eq 'drop') {
                                if ($grpstart == -1) { next; } # deleted
                                if ($grpend == 0 || $grpend > $now) {
                                    unless (defined($dropgroup{$group})) {
                                        $dropstart{$group} = $grpstart;
                                        if ($grpstart > $now) {
                                            $dropstart{$group} = $now;
                                        }
                                        $dropgroup{$group} = $now.':'.
                                                            $dropstart{$group}.
                                                         ':'.$currpriv{$group};
                                    }
                                }
                            } elsif ($chgtype eq 'add') {
                                if (($grpstart == -1) || ($grpend > 0 &&
                                     ($grpend < $settings{$group}{'enddate'} ||
                                      $settings{$group}{'enddate'} == 0)) ||
                                     ($grpstart > $settings{$group}{'startdate'})) {
                                    unless(defined($addgroup{$group})) {
                                        $addgroup{$group} =
                                            $settings{$group}{'enddate'}.':'.
                                            $settings{$group}{'startdate'}.':'.
                                            $group_privs;
                                    }
                                }
                            }
                        }
                    } elsif ($chgtype eq 'add') {
                        $addgroup{$group} = $settings{$group}{'enddate'}.':'.
                                            $settings{$group}{'startdate'}.':'.
                                            $group_privs;
                    }
                }
                if ($chgtype eq 'add') {
                    foreach my $add (keys(%addgroup)) {
                        if (&Apache::lonnet::modify_group_roles($cdom,$cnum,
                                                  $add,$uname.':'.$udom,
                                                  $settings{$add}{'enddate'},
                                                  $settings{$add}{'startdate'},
                                                  $group_privs) eq 'ok') {
                            my %usersettings;
                            $usersettings{$add.':'.$uname.':'.$udom} =
                                                               $addgroup{$add};
                            my $roster_result =
                               &Apache::lonnet::modify_coursegroup_membership(
                                                   $cdom,$cnum,\%usersettings);
                        }
                    }
                } elsif ($chgtype eq 'drop') {
                    foreach my $drop (keys(%dropgroup)) {
                        my $nodrop = 0;
                        if ($settings{$drop}{'autoadd'} eq 'on') {
                            foreach my $urole (keys(%{$settings{$drop}{'autosec'}})) {
                                if ($nodrop) {
                                    last;
                                } else {
                                    my @autosec = ();
                                    if (ref($settings{$drop}{'autosec'}{$urole}) eq 'ARRAY') {
                                        @autosec = @{$settings{$drop}{'autosec'}{$urole}};
                                    }
                                    foreach my $usec (@autosec) {
                                        if ($usec eq 'all') {
                                            foreach my $ukey (keys(%roleshash)) {
                                                if ($ukey =~ /^\Q$cid\E(\/?\w*)_($urole)$/) {
                                                    unless ($sec eq $1) {
                                                        if ($roleshash{$ukey} =~ /_?(\d*)_?([\-\d]*)$/) {
                                                            my $roleend = $1;
                                                            if ((!$roleend) ||
                                                                ($roleend > $now)) {
                                                                $nodrop = 1;
                                                                last;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        } else {
                                            my $ukey = $cid.'/'.$usec.'_'.$urole;
                                            if ($usec eq 'none') {
                                                if ($sec eq '') {
                                                    next;
                                                }
                                            } else {
                                                if ($usec eq $sec) {
                                                    next;
                                                }
                                            }
                                            if (exists($roleshash{$ukey})) {
                                                if ($roleshash{$ukey} =~
                                                       /_?(\d*)_?([\-\d]*)$/) {
                                                    my $roleend = $1;
                                                    if ((!$roleend) ||
                                                        ($roleend > $now)) {
                                                        $nodrop = 1;
                                                        last;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (!$nodrop) {
                            if (&Apache::lonnet::modify_group_roles($cdom,
                                                         $cnum,$drop,
                                                         $uname.':'.$udom,$now,
                                                         $dropstart{$drop},
                                                         $currpriv{$drop}) 
                                                                     eq 'ok') {
                                my %usersettings;
                                $usersettings{$drop.':'.$uname.':'.$udom} =
                                                             $dropgroup{$drop};
                                my $roster_result =
                                &Apache::lonnet::modify_coursegroup_membership(
                                                   $cdom,$cnum,\%usersettings);
                            }
                        }
                    }
                }
            }
        }
    }
    return;
}

###############################################

1;


--raeburn1147955595--