--- loncom/interface/selfenroll.pm 2009/02/05 12:27:21 1.15 +++ loncom/interface/selfenroll.pm 2021/12/14 12:53:12 1.27.2.8 @@ -1,7 +1,7 @@ # The LearningOnline Network # Allow users to self-enroll in a course # -# $Id: selfenroll.pm,v 1.15 2009/02/05 12:27:21 raeburn Exp $ +# $Id: selfenroll.pm,v 1.27.2.8 2021/12/14 12:53:12 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -34,6 +34,8 @@ use Apache::lonnet; use Apache::loncommon; use Apache::lonlocal; use Apache::createaccount; +use Apache::loncoursequeueadmin; +use Apache::lonuserutils; use LONCAPA qw(:DEFAULT :match); sub handler { @@ -53,9 +55,11 @@ sub handler { &Apache::lonlocal::get_language_handle($r); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['courseid']); my $js = &Apache::createaccount::catreturn_js(); - my ($coursechk,$courseid) = &validate_course_id($env{'form.courseid'}); - if ($coursechk ne 'ok') { - &page_header($r,$courseid,$js); + + my $courseid = Apache::lonnet::is_course($env{'form.courseid'}); + + unless ($courseid) { + &page_header($r,$env{'form.courseid'},$js); $r->print('

'.&mt('Self-enrollment error').'

'. ''. &mt('Invalid domain or course number').''); @@ -80,7 +84,7 @@ sub handler { $knownuser,$selfenroll_access_start,$selfenroll_access_end, $selfenroll_section,$selfenroll_future,%curr_role,$cdomdesc, $selfenroll_approval,$selfenroll_limit,$selfenroll_cap, - $selfenroll_notifylist,$owner); + $selfenroll_notifylist,$owner,$crstype); $selfenroll_types = $coursehash{'internal.selfenroll_types'}; $selfenroll_registered = $coursehash{'internal.selfenroll_registered'}; $selfenroll_section = $coursehash{'internal.selfenroll_section'}; @@ -91,6 +95,10 @@ sub handler { $selfenroll_approval = $coursehash{'internal.selfenroll_approval'}; $selfenroll_notifylist = $coursehash{'internal.selfenroll_notifylist'}; $owner = $coursehash{'internal.courseowner'}; + $crstype = $coursehash{'internal.type'}; + if ($crstype eq '') { + $crstype = 'Course'; + } my $nospace; if ($selfenroll_types ne '') { my $start = $coursehash{'internal.selfenroll_start_date'}; @@ -213,7 +221,8 @@ sub handler { if ($sso_url eq '') { $sso_url = $login_path; } - $missing_formitem = &mt('The link to the requested page could not be followed.')."\\n".&mt('The placeholder for the courseID is absent.'); + $missing_formitem = &mt('The link to the requested page could not be followed.')."\n".&mt('The placeholder for the courseID is absent.'); + &js_escape(\$missing_formitem); if ($knownuser) { if (keys(%curr_role)) { $r->print('

'.&mt('Self-enrollment unavailable').'

'. @@ -224,7 +233,7 @@ sub handler { &process_self_enroll($r,$cdom,$cnum,$selfenroll_types,$selfenroll_registered, $selfenroll_access_start,$selfenroll_access_end, $selfenroll_section,$now,$selfenroll_approval, - $selfenroll_notifylist,$owner); + $selfenroll_notifylist,$owner,$crstype,$lonhost,$handle); } elsif ($env{'form.phase'} eq 'login') { my $submit_text = &mt('Log in'); $r->print('

'.&mt('Log-in to LON-CAPA').'

'); @@ -358,17 +367,6 @@ sub page_footer { return; } -sub validate_course_id { - my ($courseid) = @_; - my ($cdom,$cnum) = ($env{'form.courseid'} =~ /^($match_domain)_($match_courseid)$/); - if ($cdom ne '' && $cnum ne '') { - if (&Apache::lonnet::is_course($cdom,$cnum)) { - return ('ok',$courseid); - } - } - return; -} - sub user_is_known { my $known = 0; if ($env{'user.name'} ne '' && $env{'user.name'} ne 'public' @@ -404,7 +402,7 @@ sub has_role { my $output; if ($curr_role{'status'} eq 'active') { my $rolelink = &jump_to_role($curr_role{'role'}); - $output = &mt('You already have an active student role (section: "[_1]") in this course.',$curr_role{'section'}).'
'.$rolelink; + $output = &mt('You already have an active student role (section: "[_1]") in this course.',$curr_role{'section'}).'
'.$rolelink; } elsif ($curr_role{'status'} eq 'future') { $output = &mt('You have a student role (section: "[_1]") in this course which will become active [_2].',$curr_role{'section'},$curr_role{'start'}); } @@ -414,7 +412,7 @@ 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_approval,$selfenroll_notifylist,$owner) = @_; + $now,$selfenroll_approval,$selfenroll_notifylist,$owner,$crstype,$lonhost,$handle) = @_; my $udom = $env{'user.domain'}; my $uname = $env{'user.name'}; my $selfenroll = 0; @@ -441,11 +439,13 @@ sub process_self_enroll { if ($selfenroll_section eq 'none') { $usec = ''; } + my $instcid; if ($selfenroll_registered) { - my ($registered,$instsec,$message) = &check_registered($cdom,$cnum); + my ($registered,$instsec,$instcid,$message) = &check_registered($cdom,$cnum); $usec = $instsec; if (!$registered) { - $r->print('

'.&mt('Self-enrollment unavailable').'

'.&mt('Self-enrollment is restricted to students officially registered for this course.').'
'); + $r->print('

'.&mt('Self-enrollment unavailable').'

'. + &mt('Self-enrollment is restricted to students officially registered for this course.').'
'); if ($message) { $r->print($message); } else { @@ -456,14 +456,15 @@ sub process_self_enroll { } if ($selfenroll_approval) { my $outcome = - &store_selfenroll_request($udom,$uname,$usec,$cdom,$cnum, - $selfenroll_notifylist,$owner); + &store_selfenroll_request($r,$udom,$uname,$usec,$cdom,$cnum, + $selfenroll_notifylist,$owner, + $selfenroll_approval,$crstype,$lonhost,$handle); $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); + 'selfenroll',undef,$cdom.'_'.$cnum,$selfenroll,'selfenroll','',$instcid); if ($enrollresult eq 'ok') { my (%userroles,%newrole,%newgroups); my $role = 'st'; @@ -475,7 +476,7 @@ sub process_self_enroll { } &Apache::lonnet::standard_roleprivs(\%newrole,$role,$cdom,$spec,$cnum, $area); - &Apache::lonnet::set_userprivs(\%userroles,\%newrole,%newgroups); + &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').'

'); @@ -535,37 +536,91 @@ sub user_can_selfenroll { } sub store_selfenroll_request { - my ($udom,$uname,$usec,$cdom,$cnum,$selfenroll_notifylist,$owner) = @_; + my ($r,$udom,$uname,$usec,$cdom,$cnum,$selfenroll_notifylist,$owner, + $selfenroll_approval,$crstype,$lonhost,$handle) = @_; 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)); + my $status; + $output = &mt('A self-enrollment request already exists for you for this course.').'
'; + my %info = &Apache::lonnet::get($namespace,[$cdom.'_'.$cnum],$udom,$uname); + if (ref($info{$cdom.'_'.$cnum}) eq 'HASH') { + $status = $info{$cdom.'_'.$cnum}{'status'}; + } + if ($status eq 'pending') { + my $token = $info{$cdom.'_'.$cnum}{'token'}; + my ($statusupdate,$pendingform) = &pending_selfenrollment_form($r,$cdom,$cnum,$crstype,$token,$lonhost); + if ($statusupdate eq 'pending') { + $output .= $pendingform; + } + } else { + $output .= &mt('Your earlier request is in a queue awaiting action by a Course Coordinator.'). + '

'.&Apache::loncoursequeueadmin::queued_selfenrollment(); + } } else { my %selfenroll = ( $uname.':'.$udom => $now.':'.$usec, ); my $putresult = &Apache::lonnet::put($namespace,\%selfenroll,$cdom,$cnum); + my $status = 'request'; + if ($selfenroll_approval eq '2') { + $status = 'pending'; + } 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); + my %userenroll = ( + $cdom.'_'.$cnum => { + timestamp => $now, + section => $usec, + status => $status, + }); + my $token; + if ($status eq 'pending') { + $token = &Apache::lonnet::tmpput(\%selfenroll,$lonhost); + $userenroll{$cdom.'_'.$cnum}{'token'} = $token; + $userenroll{$cdom.'_'.$cnum}{'lonhost'} = $lonhost; + $userenroll{$cdom.'_'.$cnum}{'handle'} = $handle; + } + my $warning; + my $userresult = &Apache::lonnet::put($namespace,\%userenroll,$udom,$uname); + if ($userresult ne 'ok') { + $warning = &mt('An error occurred saving a personal record of your request.'); + } + $output = &mt('Your request for self-enrollment has been recorded.').'
'; + if ($status eq 'pending') { + my ($statusupdate,$pendingform) = &pending_selfenrollment_form($r,$cdom,$cnum,$crstype,$token,$lonhost); + if ($statusupdate eq 'request') { + $status = $statusupdate; + } else { + $output .= $pendingform; + } + } + if ($status eq 'request') { + $output .= &mt('A message will be sent to your LON-CAPA account when the course coordinator takes action on your request.').'
'. + &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').'
'; + 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 ($warning) { + $output .= ''.$warning.'
'; + } + $output .= &Apache::loncoursequeueadmin::queued_selfenrollment(); + + if ($selfenroll_notifylist) { + my $fullname = &Apache::loncommon::plainname($uname,$udom); + my %courseinfo = &Apache::lonnet::coursedescription($cdom.'_'.$cnum); + my $coursedesc = $courseinfo{'description'}; + &Apache::loncoursequeueadmin::send_selfserve_notification( + $selfenroll_notifylist,$fullname,$cdom.'_'.$cnum, + $coursedesc,$now,'selfenrollreq',$owner); + } } } else { $output = ''.&mt('An error occurred when recording your request.').''; @@ -575,100 +630,60 @@ sub store_selfenroll_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; +sub pending_selfenrollment_form { + my ($r,$cdom,$cnum,$crstype,$token,$lonhost) = @_; + my ($status,$output); + my $coursetype = &Apache::lonuserutils::get_extended_type($cdom,$cnum,$crstype); + my %postvalues = ( + 'username' => $env{'user.name'}, + 'domain' => $env{'user.domain'}, + 'course' => $cdom.'_'.$cnum, + 'coursetype' => $coursetype, + ); + my %domconfig = &Apache::lonnet::get_dom('configuration',['selfenrollment'],$cdom); + + if (ref($domconfig{'selfenrollment'}) eq 'HASH') { + my ($url,$buttontext,$code,@fields); + if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') { + my %courseinfo = &Apache::lonnet::coursedescription($cdom.'_'.$cnum,{ 'one_time' => 1}); + $postvalues{'uniquecode'} = $courseinfo{'internal.uniquecode'}; + $postvalues{'description'} = $courseinfo{'description'}; + $url = $domconfig{'selfenrollment'}{'validation'}{'url'}; + if (ref($domconfig{'selfenrollment'}{'validation'}{'fields'}) eq 'ARRAY') { + @fields = @{$domconfig{'selfenrollment'}{'validation'}{'fields'}}; + } + $buttontext = $domconfig{'selfenrollment'}{'validation'}{'button'}; + + $output .= $domconfig{'selfenrollment'}{'validation'}{'markup'}; + if (($url =~ m{^(https?\://|/)}) && (@fields > 0)) { + $output .= '
'."\n"; + foreach my $field (@fields) { + if ($postvalues{$field}) { + $output .= ''."\n"; + } + } + if ($buttontext eq '') { + $buttontext = &mt('Complete my enrollment'); + } + my $hostname = &Apache::lonnet::hostname($lonhost); + my $protocol = $Apache::lonnet::protocol{$lonhost}; + $protocol = 'http' if ($protocol ne 'https'); + my $alias = &Apache::lonnet::use_proxy_alias($r,$lonhost); + $hostname = $alias if ($alias ne ''); + my $enroller = $protocol.'://'.$hostname.'/cgi-bin/enrollqueued.pl'; + $output .= ''."\n". + ''."\n". + ''."\n". + '
'."\n"; + $status = 'pending'; + } else { + $status = 'request'; } } - my $status = &Apache::lonmsg::user_normal_msg($ccname,$ccdom,$subject,$message,undef,undef,undef,1,\%sentmessage,undef,undef,undef,1,$recipid); + } else { + $status = 'request'; } + return ($status,$output); } sub jump_to_role { @@ -775,12 +790,12 @@ sub print_selfenroll_types { sub check_registered { my ($cdom,$cnum) = @_; - my ($registered,$instsec,$message); + my ($registered,$instsec,$instcid,$message); my %settings = &Apache::lonnet::get('environment',['internal.coursecode', 'internal.sectionnums', 'internal.crosslistings'],$cdom,$cnum); my (@allcourses,%LC_code,%affiliates,%reply); - &Apache::loncommon::get_institutional_codes(\%settings,\@allcourses,\%LC_code); + &Apache::loncommon::get_institutional_codes($cdom,$cnum,\%settings,\@allcourses,\%LC_code); if (@allcourses > 0) { @{$affiliates{$cnum}} = @allcourses; my $outcome = &Apache::lonnet::fetch_enrollment_query('updatenow',\%affiliates,\%reply,$cdom,$cnum); @@ -795,6 +810,7 @@ sub check_registered { if (defined($enrolled{$env{'user.name'}})) { $registered = 1; $instsec = $LC_code{$class}; + $instcid = $class; last; } } @@ -807,7 +823,7 @@ sub check_registered { } else { $message = &mt('As no institutional course sections are currently associated with this course, your registration status is undetermined.'); } - return ($registered,$instsec,$message); + return ($registered,$instsec,$instcid,$message); } 1;