--- loncom/interface/selfenroll.pm 2008/07/30 16:25:35 1.14
+++ loncom/interface/selfenroll.pm 2009/02/05 12:27:21 1.15
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Allow users to self-enroll in a course
#
-# $Id: selfenroll.pm,v 1.14 2008/07/30 16:25:35 raeburn Exp $
+# $Id: selfenroll.pm,v 1.15 2009/02/05 12:27:21 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -78,20 +78,45 @@ sub handler {
}
my ($canenroll,$selfenroll_types,$selfenroll_registered,@cancreate,
$knownuser,$selfenroll_access_start,$selfenroll_access_end,
- $selfenroll_section,$selfenroll_future,%curr_role,$cdomdesc);
+ $selfenroll_section,$selfenroll_future,%curr_role,$cdomdesc,
+ $selfenroll_approval,$selfenroll_limit,$selfenroll_cap,
+ $selfenroll_notifylist,$owner);
$selfenroll_types = $coursehash{'internal.selfenroll_types'};
$selfenroll_registered = $coursehash{'internal.selfenroll_registered'};
$selfenroll_section = $coursehash{'internal.selfenroll_section'};
$selfenroll_access_start = $coursehash{'internal.selfenroll_start_access'};
$selfenroll_access_end = $coursehash{'internal.selfenroll_end_access'};
+ $selfenroll_limit = $coursehash{'internal.selfenroll_limit'};
+ $selfenroll_cap = $coursehash{'internal.selfenroll_cap'};
+ $selfenroll_approval = $coursehash{'internal.selfenroll_approval'};
+ $selfenroll_notifylist = $coursehash{'internal.selfenroll_notifylist'};
+ $owner = $coursehash{'internal.courseowner'};
+ my $nospace;
if ($selfenroll_types ne '') {
my $start = $coursehash{'internal.selfenroll_start_date'};
my $end = $coursehash{'internal.selfenroll_end_date'};
if (($start > 0 && $start < $now) && (($end == 0) || ($end > 0 && $end > $now))) {
- $canenroll = 1;
+ if (($selfenroll_limit eq 'allstudents') ||
+ ($selfenroll_limit eq 'selfenroll')) {
+ $nospace =
+ &enrollment_limit_check($selfenroll_limit,$selfenroll_cap,
+ $cdom,$cnum);
+ if (!$nospace) {
+ $canenroll = 1;
+ }
+ } else {
+ $canenroll = 1;
+ }
} elsif (($end == 0) || ($end > 0 && $end > $now)) {
if ($start > $now) {
- $selfenroll_future = &Apache::lonlocal::locallocaltime($start);
+ if (($selfenroll_limit eq 'allstudents') ||
+ ($selfenroll_limit eq 'selfenroll')) {
+ $nospace =
+ &enrollment_limit_check($selfenroll_limit,$cdom,$cnum);
+ }
+ if (!$nospace) {
+ $selfenroll_future = &Apache::lonlocal::locallocaltime($start);
+ }
}
}
}
@@ -100,6 +125,14 @@ sub handler {
$r->print('
'.&mt('Self-enrollment unavailable').'
'.
&mt('Self-enrollment is not currently available for this course.').
'
');
+ if ($nospace) {
+ if ($selfenroll_limit eq 'allstudents') {
+ $r->print(&mt('The enrollment limit of [quant,_1,student] has been reached.',$selfenroll_cap));
+ } else {
+ $r->print(&mt('The enrollment limit of [quant,_1,self-enrolled student] has been reached.',$selfenroll_cap));
+
+ }
+ }
if ($selfenroll_types ne '') {
if ($selfenroll_future ne '') {
if ($selfenroll_types eq '*') {
@@ -190,7 +223,8 @@ sub handler {
}
&process_self_enroll($r,$cdom,$cnum,$selfenroll_types,$selfenroll_registered,
$selfenroll_access_start,$selfenroll_access_end,
- $selfenroll_section,$now);
+ $selfenroll_section,$now,$selfenroll_approval,
+ $selfenroll_notifylist,$owner);
} elsif ($env{'form.phase'} eq 'login') {
my $submit_text = &mt('Log in');
$r->print(''.&mt('Log-in to LON-CAPA').'
');
@@ -282,6 +316,28 @@ END
return OK;
}
+sub enrollment_limit_check {
+ my ($selfenroll_limit,$selfenroll_cap,$cdom,$cnum) = @_;
+ my $nospace = 0;
+ my (%idx,%stucount);
+ my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cnum);
+ $idx{'type'} = &Apache::loncoursedata::CL_TYPE();
+ $idx{'status'} = &Apache::loncoursedata::CL_STATUS();
+ while (my ($student,$data) = each(%$classlist)) {
+ if (($data->[$idx{'status'}] eq 'Active') ||
+ ($data->[$idx{'status'}] eq 'Future')) {
+ if ($data->[$idx{'type'}] eq 'selfenroll') {
+ $stucount{'selfenroll'} ++;
+ }
+ $stucount{'allstudents'} ++;
+ }
+ }
+ if ($stucount{$selfenroll_limit} >= $selfenroll_cap) {
+ $nospace = 1;
+ }
+ return $nospace;
+}
+
sub page_header {
my ($r,$courseid,$js,$desc) = @_;
my $start_page =
@@ -357,7 +413,8 @@ sub has_role {
sub process_self_enroll {
my ($r,$cdom,$cnum,$selfenroll_types,$selfenroll_registered,
- $selfenroll_access_start,$selfenroll_access_end,$selfenroll_section,$now) = @_;
+ $selfenroll_access_start,$selfenroll_access_end,$selfenroll_section,
+ $now,$selfenroll_approval,$selfenroll_notifylist,$owner) = @_;
my $udom = $env{'user.domain'};
my $uname = $env{'user.name'};
my $selfenroll = 0;
@@ -397,48 +454,55 @@ sub process_self_enroll {
return;
}
}
- my $enrollresult =
- &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,
- undef,undef,$usec,$selfenroll_access_end,$selfenroll_access_start,
- 'manual',undef,$cdom.'_'.$cnum,$selfenroll);
- if ($enrollresult eq 'ok') {
- my (%userroles,%newrole,%newgroups);
- my $role = 'st';
- my $area = '/'.$cdom.'/'.$cnum;
- my $spec = $role.'.'.$area;
- if ($usec ne '') {
- $spec .= '/'.$usec;
- $area .= '/'.$usec;
- }
- &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,
- $area);
- &Apache::lonnet::set_userprivs(\%userroles,\%newrole,%newgroups);
- $userroles{'user.role.'.$spec} = $selfenroll_access_start.'.'.$selfenroll_access_end;
- &Apache::lonnet::appenv(\%userroles,[$role,'cm']);
- $r->print(''.&mt('Enrollment process complete').'
');
- if ($selfenroll_access_end && $selfenroll_access_end <= $now) {
- $r->print(&mt('The end date for access to this course for users who self-enroll has passed.').'
'.&mt('Consequently, although a new role was created for you in the course, it is an inactive role which does not provide access to the course.'));
- } else {
- $r->print(&mt('Self-enrollment in this course was successful.').'
');
- my $showstart = &Apache::lonlocal::locallocaltime($selfenroll_access_start);
- my $showend = &Apache::lonlocal::locallocaltime($selfenroll_access_end);
- if ($selfenroll_access_start && $selfenroll_access_start >$now) {
- $r->print(&mt('The start date for access to this course for users who self-enroll has yet to be reached.').'
'.&mt('Consequently, although a new role was created for you in the course, you will not be able to select this role until [_1].',$showstart));
+ if ($selfenroll_approval) {
+ my $outcome =
+ &store_selfenroll_request($udom,$uname,$usec,$cdom,$cnum,
+ $selfenroll_notifylist,$owner);
+ $r->print($outcome);
+ } else {
+ my $enrollresult =
+ &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,
+ undef,undef,$usec,$selfenroll_access_end,$selfenroll_access_start,
+ 'selfenroll',undef,$cdom.'_'.$cnum,$selfenroll);
+ if ($enrollresult eq 'ok') {
+ my (%userroles,%newrole,%newgroups);
+ my $role = 'st';
+ my $area = '/'.$cdom.'/'.$cnum;
+ my $spec = $role.'.'.$area;
+ if ($usec ne '') {
+ $spec .= '/'.$usec;
+ $area .= '/'.$usec;
+ }
+ &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum,
+ $area);
+ &Apache::lonnet::set_userprivs(\%userroles,\%newrole,%newgroups);
+ $userroles{'user.role.'.$spec} = $selfenroll_access_start.'.'.$selfenroll_access_end;
+ &Apache::lonnet::appenv(\%userroles,[$role,'cm']);
+ $r->print(''.&mt('Enrollment process complete').'
');
+ if ($selfenroll_access_end && $selfenroll_access_end <= $now) {
+ $r->print(&mt('The end date for access to this course for users who self-enroll has passed.').'
'.&mt('Consequently, although a new role was created for you in the course, it is an inactive role which does not provide access to the course.'));
} else {
- my $newrole = 'st./'.$cdom.'/'.$cnum;
- if ($usec ne '') {
- $newrole .= '/'.$usec;
+ $r->print(&mt('Self-enrollment in this course was successful.').'
');
+ my $showstart = &Apache::lonlocal::locallocaltime($selfenroll_access_start);
+ my $showend = &Apache::lonlocal::locallocaltime($selfenroll_access_end);
+ if ($selfenroll_access_start && $selfenroll_access_start >$now) {
+ $r->print(&mt('The start date for access to this course for users who self-enroll has yet to be reached.').'
'.&mt('Consequently, although a new role was created for you in the course, you will not be able to select this role until [_1].',$showstart));
+ } else {
+ my $newrole = 'st./'.$cdom.'/'.$cnum;
+ if ($usec ne '') {
+ $newrole .= '/'.$usec;
+ }
+ my $rolelink = &jump_to_role($newrole);
+ $r->print(&mt('Your new role is available immediately, and will provide access to the course until [_1].',$showend).'
'."\n".
+ $rolelink);
}
- my $rolelink = &jump_to_role($newrole);
- $r->print(&mt('Your new role is available immediately, and will provide access to the course until [_1].',$showend).'
'."\n".
- $rolelink);
}
- }
- } else {
- $r->print(''.&mt('Enrollment incomplete').'
'.
- &mt('Self-enrollment in this course failed.'));
- if ($enrollresult ne '') {
- $r->print(''.$enrollresult.'');
+ } else {
+ $r->print(''.&mt('Enrollment incomplete').'
'.
+ &mt('Self-enrollment in this course failed.'));
+ if ($enrollresult ne '') {
+ $r->print(''.$enrollresult.'');
+ }
}
}
} else {
@@ -470,6 +534,143 @@ sub user_can_selfenroll {
return $selfenroll;
}
+sub store_selfenroll_request {
+ my ($udom,$uname,$usec,$cdom,$cnum,$selfenroll_notifylist,$owner) = @_;
+ my $namespace = 'selfenrollrequests';
+ my $output;
+ my $now = time;
+ my %existing =
+ &Apache::lonnet::get($namespace,[$uname.':'.$udom],$cdom,$cnum);
+ if ($existing{$uname.':'.$udom}) {
+ my ($timestamp,$sec) = split(/:/,$existing{$uname.':'.$udom});
+ $output = &mt('A self-enrollment request already exists for you for this course.').'
'.&mt('Your earlier request was submitted: [_1] and remains in a queue awaiting action by a Course Coordinator.',&Apache::lonlocal::locallocaltime($timestamp));
+ } else {
+ my %selfenroll = (
+ $uname.':'.$udom => $now.':'.$usec,
+ );
+ my $putresult = &Apache::lonnet::put($namespace,\%selfenroll,$cdom,$cnum);
+ if ($putresult eq 'ok') {
+ $output = &mt('Your request for self-enrollment has been recorded.').'
'.
+ &mt('A message will be sent to your LON-CAPA account when the course coordinator takes action on your request').'
';
+ my %emails = &Apache::loncommon::getemails($uname,$udom);
+ if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) {
+ my $address = $emails{'permanentemail'};
+ if ($address eq '') {
+ $address = $emails{'notification'};
+ }
+ $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address);
+ }
+ if ($selfenroll_notifylist) {
+ my $fullname = &Apache::loncommon::plainname($uname,$udom);
+ my %courseinfo = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
+ my $coursedesc = $courseinfo{'description'};
+ &send_notification($selfenroll_notifylist,$fullname,$cdom.
+ '_'.$cnum,$coursedesc,$now,'request',$owner);
+ }
+ } else {
+ $output = ''.&mt('An error occurred when recording your request.').'';
+
+ }
+ }
+ return $output;
+}
+
+sub send_notification {
+ my ($notifylist,$textstr,$cid,$coursedesc,$timestamp,$context,$sender,
+ $approvedlist,$rejectedlist) = @_;
+# FIXME locallocaltime needs to be able to take $sender_lh as an argument
+# so this can be localized to the recipients date display format/time zone
+ $timestamp =&Apache::lonlocal::locallocaltime($timestamp);
+ my $msgcc;
+ my ($rawsubj,@rawmsg,$subject,$message,$namelink);
+ $namelink = &Apache::loncommon::aboutmewrapper(
+ &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}));
+ if ($context eq 'managers') {
+ $rawsubj = 'Self-enrollment requests processed';
+ push(@rawmsg,{
+ mt => 'Enrollment requests in the following course: [_1] have been processed.',
+ args => [$coursedesc],
+ });
+ } elsif ($context eq 'enroller') {
+ $rawsubj = 'Enrollment request';
+ push(@rawmsg,{
+ mt => 'Your request for enrollment in the following course: [_1], requested on [_2], has been reviewed by a Course Coordinator.',
+ args => [$coursedesc,$timestamp],
+ });
+ if (ref($textstr) eq 'ARRAY') {
+ push(@rawmsg,@{$textstr});
+ }
+ } else {
+ $rawsubj = 'Self-enrollment request';
+ push(@rawmsg,{
+ mt => 'Enrollment in the following course: [_1] was requested by [_2] on [_3].',
+ args => [$coursedesc,$textstr,$timestamp],
+ },
+ {
+ mt =>'As Course Coordinator, use Main Menu -> Manage Couse Users -> "Enrollment Requests" to display a list of pending enrollment requests which you can either approve or reject.'
+ });
+ }
+ my @to_notify = split(/,/,$notifylist);
+ my $numsent = 0;
+ my @recusers;
+ my @recudoms;
+ foreach my $cc (@to_notify) {
+ my ($ccname,$ccdom) = split(/:/,$cc);
+ if (!exists($msgcc->{$ccname.':'.$ccdom})) {
+ push(@recusers,$ccname);
+ push(@recudoms,$ccdom);
+ $msgcc->{$ccname.':'.$ccdom}='';
+ $numsent ++;
+ }
+ }
+ my %reciphash = (
+ cc => $msgcc,
+ );
+ my ($uname,$udom);
+ if ($sender =~ /:/) {
+ ($uname,$udom) = split(/:/,$sender);
+ } else {
+ $uname = $sender;
+ my %courseinfo = &Apache::lonnet::coursedescription($cid);
+ $udom = $courseinfo{'num'};
+ }
+ my %sentmessage;
+ my $stamp = time;
+ my $msgcount = &Apache::lonmsg::get_uniq();
+ my $sender_lh = &Apache::loncommon::user_lang($uname,$udom,$cid);
+ $subject = &Apache::lonlocal::mt_user($sender_lh,$rawsubj);
+ $message = '';
+ foreach my $item (@rawmsg) {
+ if (ref($item) eq 'HASH') {
+ $message .= &Apache::lonlocal::mt_user($sender_lh,$item->{mt},@{$item->{args}})."\n";
+ }
+ }
+ &Apache::lonmsg::process_sent_mail($subject,'',$numsent,$stamp,$uname,$udom,$msgcount,$cid,$$,$message,\@recusers,\@recudoms);
+ my ($recipid,$recipstatus) =
+ &Apache::lonmsg::store_recipients($subject,$uname,$udom,\%reciphash);
+ foreach my $recip (sort(keys(%{$msgcc}))) {
+ my ($ccname,$ccdom) = split(/:/,$recip);
+ my $recip_lh = &Apache::loncommon::user_lang($ccname,$ccdom,$cid);
+ my $subject = &Apache::lonlocal::mt_user($sender_lh,$rawsubj);
+ my $message = '';
+ foreach my $item (@rawmsg) {
+ if (ref($item) eq 'HASH') {
+ $message .= &Apache::lonlocal::mt_user($sender_lh,$item->{mt},
+ @{$item->{args}})."\n";
+ }
+ }
+ if ($context eq 'managers') {
+ if ($approvedlist) {
+ $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Approved enrollments:')."\n".$approvedlist;
+ }
+ if ($rejectedlist) {
+ $message .= "\n\n".&Apache::lonlocal::mt_user($sender_lh,'Rejected enrollments:')."\n".$rejectedlist;
+ }
+ }
+ my $status = &Apache::lonmsg::user_normal_msg($ccname,$ccdom,$subject,$message,undef,undef,undef,1,\%sentmessage,undef,undef,undef,1,$recipid);
+ }
+}
+
sub jump_to_role {
my ($role) = @_;
my $output = <<"END";