--- loncom/interface/Attic/londropadd.pm 2002/04/16 19:08:49 1.25 +++ loncom/interface/Attic/londropadd.pm 2002/09/18 14:17:47 1.51 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to drop and add students in courses # -# $Id: londropadd.pm,v 1.25 2002/04/16 19:08:49 matthew Exp $ +# $Id: londropadd.pm,v 1.51 2002/09/18 14:17:47 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,168 +31,223 @@ # # (TeX Content Handler # -# YEAR=2000 -# 05/29/00,05/30,10/11 Gerd Kortemeyer) -# -# 10/11,10/12,10/16 Gerd Kortemeyer) -# -# 11/20,11/21,11/22,11/23,11/24,11/25,11/27,11/28, -# 12/08,12/12 Gerd Kortemeyer) -# -# 12/26,12/27,12/28, -# YEAR=2001 -# 01/01/01,01/15,02/10,02/13,02/14,02/22 Gerd Kortemeyer -# 8/6 Scott Harrison -# Guy Albertelli -# 9/25 Gerd Kortemeyer -# 12/19 Guy Albertelli -# YEAR=2002 -# 1/4 Gerd Kortemeyer +############################################################### +############################################################### package Apache::londropadd; use strict; use Apache::lonnet(); use Apache::loncommon(); +use Apache::lonhtmlcommon(); use Apache::Constants qw(:common :http REDIRECT); -# ================================================================ Print header - +############################################################### +############################################################### sub header { - my $r=shift; - $r->print(< -LON-CAPA Student Drop/Add +LON-CAPA Enrollment Manager - - -

Drop/Add Students

-
-

Course: $ENV{'course.'.$ENV{'request.course.id'}.'.description'}

+$bodytag + ENDHEAD } -# =========== Drop student from all sections of a course, except optional $csec - -sub dropstudent { - my ($udom,$unam,$courseid,$csec)=@_; +############################################################### +############################################################### +# Drop student from all sections of a course, except optional $csec +sub modifystudent { + my ($udom,$unam,$courseid,$csec,$desiredhost)=@_; + # if $csec is undefined, drop the student from all the courses matching + # this one. If $csec is defined, drop them from all other sections of + # this course and add them to section $csec $courseid=~s/\_/\//g; $courseid=~s/^(\w)/\/$1/; - foreach (split(/\&/, - &Apache::lonnet::reply('dump:'.$udom.':'.$unam.':roles', - &Apache::lonnet::homeserver($unam,$udom)))) { - my ($key,$value)=split(/\=/,$_); - $key=&Apache::lonnet::unescape($key); - if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) { + my %roles = &Apache::lonnet::dump('roles',$udom,$unam); + my ($tmp) = keys(%roles); + # Bail out if we were unable to get the students roles + return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i); + # Go through the roles looking for enrollment in this course + my $result = ''; + foreach my $course (keys(%roles)) { + if ($course=~/^$courseid(?:\/)*(?:\s+)*(\w+)*\_st$/) { + # We are in this course my $section=$1; - if ($key eq $courseid.'_st') { $section=''; } - if (((!$section) && (!$csec)) || ($section ne $csec)) { - my ($dummy,$end,$start)=split(/\_/, - &Apache::lonnet::unescape - ($value)); + $section='' if ($course eq $courseid.'_st'); + if ( ((!$section) && (!$csec)) || ($section ne $csec) ) { + my (undef,$end,$start)=split(/\_/,$roles{$course}); my $now=time; - my $notactive=0; - if ($start) { - if ($now<$start) { $notactive=1; } - } - if ($end) { - if ($now>$end) { $notactive=1; } - } - unless ($notactive) { + # if this is an active role + if (!($start && ($now<$start)) || !($end && ($now>$end))) { my $reply=&Apache::lonnet::modifystudent - ($udom,$unam,'','','', - '','','','',$section,time); + ($udom,$unam,'','','','','','','', + $section,time,undef,undef,$desiredhost); + $result .= $reply.':'; } } } } + if ($result eq '') { + $result eq 'Unable to find section for this student'; + } else { + $result =~ s/(ok:)+/ok/g; + } + return $result; } -# ============================================================== Menu Phase One +############################################################### +############################################################### +# build a domain and server selection form +sub domain_form { + my ($defdom) = @_; + # Set up domain and server selection forms + # + # Get the domains + my @domains = &Apache::loncommon::get_domains(); + # build up the menu information to be passed to + # &Apache::loncommon::linked_select_forms + my %select_menus; + foreach my $dom (@domains) { + # set up the text for this domain + $select_menus{$dom}->{'text'}= $dom; + # we want a choice of 'default' as the default in the second menu + $select_menus{$dom}->{'default'}= 'default'; + $select_menus{$dom}->{'select2'}->{'default'} = 'default'; + # Now build up the other items in the second menu + my %servers = &Apache::loncommon::get_library_servers($dom); + foreach my $server (keys(%servers)) { + $select_menus{$dom}->{'select2'}->{$server} + = "$server $servers{$server}"; + } + } + my $result = &Apache::loncommon::linked_select_forms + ('studentform',' with home server ',$defdom, + 'lcdomain','lcserver',\%select_menus); + return $result; +} -sub menu_phase_one { +############################################################### +############################################################### +# Menu Phase One +sub print_main_menu { my $r=shift; - my $upfile_select=&Apache::loncommon::upfile_select_html(); - $r->print(< -
-

Upload a courselist

-$upfile_select -

-


-

Enroll a single student

-

-


-

Drop students

-

-ENDUPFORM + $r->print(< + + Upload a course list + +

+ + Enroll a single student + +

+ + Modify student data + +

+ + View Classlist + +

+ + Drop Students + +

+END } - -sub phase_two_header { +############################################################### +############################################################### +sub print_upload_manager_header { my ($r,$datatoken,$distotal,$krbdefdom)=@_; my $javascript; + if (! exists($ENV{'form.upfile_associate'})) { + $ENV{'form.upfile_associate'} = 'forward'; + } + if ($ENV{'form.associate'} eq 'Reverse Association') { + if ( $ENV{'form.upfile_associate'} ne 'reverse' ) { + $ENV{'form.upfile_associate'} = 'reverse'; + } else { + $ENV{'form.upfile_associate'} = 'forward'; + } + } if ($ENV{'form.upfile_associate'} eq 'reverse') { - $javascript=&phase_two_javascript_reverse_associate(); + $javascript=&upload_manager_javascript_reverse_associate(); } else { - $javascript=&phase_two_javascript_forward_associate(); + $javascript=&upload_manager_javascript_forward_associate(); } my $javascript_validations=&javascript_validations($krbdefdom); $r->print(<Uploading Class List

Identify fields

Total number of records found in file: $distotal
Enter as many fields as you can. The system will inform you and bring you back to this page if the data selected is insufficient to run your class.
- - - + + + + + - +
- ENDPICK } +############################################################### +############################################################### sub javascript_validations { my ($krbdefdom)=@_; + my %param = ( formname => 'studentform', + kerb_def_dom => $krbdefdom ); + my $authheader = &Apache::loncommon::authform_header(%param); return (<=3) && @@ -336,6 +368,8 @@ function flip(vf,tf) { } } } + // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6), + // clear out any that are set to 'lastname, firstnames' (2) if ((nw>=3) && (nw<=6)) { for (i=0;i<=vf.nfields.value;i++) { if (eval('vf.f'+i+'.selectedIndex')==2) { @@ -343,10 +377,13 @@ function flip(vf,tf) { } } } + // If we set the password, make the password form below correspond to + // the new value. if (nw==9) { - vf.login[1].checked=true; - vf.intpwd.value=''; - vf.krbdom.value=''; + changed_radio('int',document.studentform); + set_auth_radio_buttons('int',document.studentform); + vf.intarg.value=''; + vf.krbarg.value=''; vf.locarg.value=''; } } @@ -363,7 +400,9 @@ function clearpwd(vf) { ENDPICK } -sub phase_two_javascript_reverse_associate { +############################################################### +############################################################### +sub upload_manager_javascript_reverse_associate { return(< 'document.studentform'); + my $krbform = &Apache::loncommon::authform_kerberos(%param); + my $intform = &Apache::loncommon::authform_internal(%param); + my $locform = &Apache::loncommon::authform_local(%param); + my $domform = &domain_form($defdom); $r->print(< @@ -424,28 +471,22 @@ sub phase_two_end {

Login Type

Note: this will not take effect if the user already exists

- -Kerberos authenticated with domain - +$krbform

- -Internally authenticated (with initial password -) +$intform

- -Local Authentication with argument - +$locform

LON-CAPA Domain for Students

-LON-CAPA domain:

+LON-CAPA domain: $domform

Starting and Ending Dates

- - - - - + + + + + Set Starting Date

@@ -460,21 +501,21 @@ LON-CAPA domain: Disable ID/Student Number Safeguard and Force Change of Conflicting IDs (only do if you know what you are doing)

-
-Note: for large courses, this operation might be time consuming. +
+Note: for large courses, this operation may be time consuming. ENDPICK } # ======================================================= Menu Phase Two Upload - -sub menu_phase_two_upload { +sub print_upload_manager_form { my $r=shift; + my $datatoken; if (!$ENV{'form.datatoken'}) { - $datatoken=&Apache::loncommon::upfile_store($r); + $datatoken=&Apache::loncommon::upfile_store($r); } else { - $datatoken=$ENV{'form.datatoken'}; - &Apache::loncommon::load_tmp_file($r); + $datatoken=$ENV{'form.datatoken'}; + &Apache::loncommon::load_tmp_file($r); } my @records=&Apache::loncommon::upfile_record_sep(); my $total=$#records; @@ -485,14 +526,18 @@ sub menu_phase_two_upload { my $today=time; my $halfyear=$today+15552000; my $defdom=$r->dir_config('lonDefDomain'); - &phase_two_header($r,$datatoken,$distotal,$krbdefdom); + &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom); my $i; my $keyfields; if ($total>=0) { - my @d=(['username','Username'],['names','Last Name, First Names'], - ['fname','First Name'],['mname','Middle Names/Initials'], - ['lname','Last Name'],['gen','Generation'], - ['id','ID/Student Number'],['sec','Group/Section'], + my @d=(['username','Username'], + ['names','Last Name, First Names'], + ['fname','First Name'], + ['mname','Middle Names/Initials'], + ['lname','Last Name'], + ['gen','Generation'], + ['id','ID/Student Number'], + ['sec','Group/Section'], ['ipwd','Initial Password']); if ($ENV{'form.upfile_associate'} eq 'reverse') { &Apache::loncommon::csv_print_samples($r,\@records); @@ -506,60 +551,93 @@ sub menu_phase_two_upload { $keyfields=join(',',sort(keys(%sone))); } } - &phase_two_end($r,$i,$keyfields,$defdom,$today,$halfyear); + &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear); } # ======================================================= Enroll single student - sub enroll_single_student { my $r=shift; $r->print('

Enrolling Student

'); + $r->print('

Enrolling '.$ENV{'form.cuname'}." in domain ". + $ENV{'form.lcdomain'}.'

'); if (($ENV{'form.cuname'})&&($ENV{'form.cuname'}!~/\W/)&& - ($ENV{'form.cdomain'})&&($ENV{'form.cdomain'}!~/\W/)) { + ($ENV{'form.lcdomain'})&&($ENV{'form.lcdomain'}!~/\W/)) { + # Deal with home server selection + my $domain=$ENV{'form.lcdomain'}; + my $desiredhost = $ENV{'form.lcserver'}; + if (lc($desiredhost) eq 'default') { + $desiredhost = undef; + } else { + my %home_servers =&Apache::loncommon::get_library_servers($domain); + if (! exists($home_servers{$desiredhost})) { + $r->print('Error:'. + 'Invalid home server specified'); + return; + } + } + $r->print(" with server $desiredhost :") if (defined($desiredhost)); + # End of home server selection logic my $amode=''; my $genpwd=''; if ($ENV{'form.login'} eq 'krb') { - $amode='krb4'; - $genpwd=$ENV{'form.krbdom'}; + $amode='krb'; + $amode.=$ENV{'form.krbver'}; + $genpwd=$ENV{'form.krbarg'}; } elsif ($ENV{'form.login'} eq 'int') { - $amode='internal'; - $genpwd=$ENV{'form.intpwd'}; + $amode='internal'; + $genpwd=$ENV{'form.intarg'}; } elsif ($ENV{'form.login'} eq 'loc') { $amode='localauth'; $genpwd=$ENV{'form.locarg'}; if (!$genpwd) { $genpwd=" "; } } - if (($amode) && ($genpwd)) { - &dropstudent($ENV{'form.cdomain'},$ENV{'form.cuname'}, - $ENV{'request.course.id'},$ENV{'form.csec'}); - $r->print(&Apache::lonnet::modifystudent - ($ENV{'form.cdomain'},$ENV{'form.cuname'}, - $ENV{'form.cstid'},$amode,$genpwd, - $ENV{'form.cfirst'},$ENV{'form.cmiddle'}, - $ENV{'form.clast'},$ENV{'form.cgen'}, - $ENV{'form.csec'},$ENV{'form.enddate'}, - $ENV{'form.startdate'},$ENV{'form.forceid'})); + my $home = &Apache::lonnet::homeserver($ENV{'form.cuname'}, + $ENV{'form.lcdomain'}); + if ((($amode) && ($genpwd)) || ($home ne 'no_host')) { + &modifystudent($ENV{'form.lcdomain'},$ENV{'form.cuname'}, + $ENV{'request.course.id'},$ENV{'form.csec'}, + $desiredhost); + $r->print(&Apache::lonnet::modifystudent( + $ENV{'form.lcdomain'},$ENV{'form.cuname'}, + $ENV{'form.cstid'},$amode,$genpwd, + $ENV{'form.cfirst'},$ENV{'form.cmiddle'}, + $ENV{'form.clast'},$ENV{'form.cgen'}, + $ENV{'form.csec'},$ENV{'form.enddate'}, + $ENV{'form.startdate'},$ENV{'form.forceid'}, + $desiredhost)); } else { - $r->print('Invalid login mode or password'); + $r->print('

ERROR '. + 'Invalid login mode or password. '. + 'Unable to enroll '.$ENV{'form.cuname'}.'.

'); } } else { $r->print('Invalid username or domain'); - } + } } # ======================================================= Menu Phase Two Enroll - -sub menu_phase_two_enroll { +sub print_enroll_single_student_form { my $r=shift; - $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/; - my $krbdefdom=$1; + $r->print("

Enroll One Student

"); + my ($krbdefdom) = $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/; $krbdefdom=~tr/a-z/A-Z/; - my $today=time; - my $halfyear=$today+15552000; + my $today = time; + my $halfyear = $today+15552000; my $defdom=$r->dir_config('lonDefDomain'); my $javascript_validations=&javascript_validations($krbdefdom); - $r->print(< + # Set up authentication forms + my %param = ( formname => 'document.studentform'); + my $krbform = &Apache::loncommon::authform_kerberos(%param); + my $intform = &Apache::loncommon::authform_internal(%param); + my $locform = &Apache::loncommon::authform_local(%param); + # Set up domain selection form + my $domform = &domain_form($defdom); + # Print it all out + $r->print(< + + +

Personal Data

-First Name:
-Middle Name:
-Last Name:
-Generation:

+ + + + + +
First Name:
Middle Name:
Last Name:
Generation:
-ID/Student Number:

+

Login Data

+

Username:

+

Domain: $domform

+

Note: login settings below will not take effect if the user already exists +

+$krbform +

+$intform +

+$locform +

-Group/Section:

+

Course Data

-

Login Data

-Username:

-Domain:

-Note: login settings below will not take effect if the user already exists

- - -Kerberos authenticated with domain -

- -Internally authenticated (with initial password -) -

- -Local Authentication with argument - -

-

Starting and Ending Dates

- - - - - +

Group/Section: +

+ + + + + + +

Set Starting Date

- +>Set Starting Date +

Set Ending Date

+>Set Ending Date +

ID/Student Number

- +

+ID/Student Number: +

+ Disable ID/Student Number Safeguard and Force Change of Conflicting IDs -(only do if you know what you are doing)

-
- -ENDSENROLL +(only do if you know what you are doing) +

+ +

+END + return; +} + +# =================================================== get the current classlist +sub get_current_classlist { + my $r = shift; + # Call DownloadClasslist + my $cid = $ENV{'request.course.id'}; + my $c = $r->connection; + my $classlisthash = &Apache::loncoursedata::DownloadClasslist + ($cid,'Not downloaded',$c); + # Call ProcessClasslist + my %cache; + my @students = &Apache::loncoursedata::ProcessClasslist(\%cache, + $classlisthash, + $cid,$c); + return (\@students,\%cache); } # ========================================================= Menu Phase Two Drop +sub print_drop_menu { + my $r=shift; + $r->print("

Drop Students

"); + my $cid=$ENV{'request.course.id'}; + my ($student_array,$student_data)=&get_current_classlist($r); + if (! scalar(@$student_array)) { + $r->print("There are no students currently enrolled.\n"); + return; + } + # Print out the available choices + &show_drop_list($student_array,$student_data,$r); + return; +} -sub menu_phase_two_drop { +# ============================================== view classlist +sub print_html_classlist { my $r=shift; + $r->print(< +Current Classlist      +CSV format +

+END my $cid=$ENV{'request.course.id'}; - my $classlst=&Apache::lonnet::reply - ('dump:'.$ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist', - $ENV{'course.'.$cid.'.home'}); - my %currentlist=(); - my $now=time; - unless ($classlst=~/^error\:/) { - foreach (split(/\&/,$classlst)) { - my ($name,$value)=split(/\=/,$_); - my ($end,$start)=split(/\:/, - &Apache::lonnet::unescape($value)); - my $active=1; - if (($end) && ($now>$end)) { $active=0; } - if ($active) { - $currentlist{&Apache::lonnet::unescape($name)}=1; - } + my ($student_array,$student_data)=&get_current_classlist($r); + if (! scalar(@$student_array)) { + $r->print("There are no students currently enrolled.\n"); + } else { + # Print out the available choices + if ($ENV{'form.action'} eq 'modifystudent') { + &show_class_list($r,'view','modify',$student_array,$student_data); + } else { + &show_class_list($r,'view','aboutme',$student_array,$student_data); } -# ----------------------------------------------------------- Print out choices - &show_drop_list($r,%currentlist); + } +} + +# ============================================== view classlist +sub print_csv_classlist { + my $r=shift; + my $cid=$ENV{'request.course.id'}; + my ($student_array,$student_data)=&get_current_classlist($r); + if (! scalar(@$student_array)) { + $r->print("There are no students currently enrolled.\n"); } else { - $r->print('

Could not access classlist: '.$classlst. - '

'); + &show_class_list($r,'csv','nolink',$student_array,$student_data); } } # =================================================== Show student list to drop +sub show_class_list { + my ($r,$mode,$linkto,$students,$student_data)=@_; + my $cid=$ENV{'request.course.id'}; + # Print out header + if ($mode eq 'view') { + if ($linkto eq 'aboutme') { + $r->print('Select a user name to view the users page.'); + } elsif ($linkto eq 'modify') { + $r->print('Select a user name to modify the students information'); + } + $r->print(< + + + +END + } elsif ($mode eq 'csv') { + $r->print('"'.join('","',("username","domain","ID","student name", + "section")).'"'."\n"); + } + foreach my $student (@$students) { + my $username = $student_data->{$student.':username'}; + my $domain = $student_data->{$student.':domain'}; + my $section = $student_data->{$student.':section'}; + my $name = $student_data->{$student.':fullname'}; + my $status = $student_data->{$student.':Status'}; + my $id = $student_data->{$student.':id'}; + next if ($status ne 'Active'); + if ($mode eq 'view') { + $r->print("\n + + + + + +END + } elsif ($mode eq 'csv') { + # no need to bother with $linkto + my @line = (); + foreach ($username,$domain,$id,$name,$section) { + push @line,&Apache::loncommon::csv_translate($_); + } + my $tmp = $"; + $" = '","'; + $r->print("\"@line\"\n"); + $" = $tmp; + } + } + $r->print('
usernamedomainIDstudent namesection
\n "); + if ($linkto eq 'nothing') { + $r->print($username); + } elsif ($linkto eq 'aboutme') { + $r->print(&Apache::loncommon::aboutmewrapper($username, + $username, + $domain)); + } elsif ($linkto eq 'modify') { + $r->print(''.$username."\n"); + } + $r->print(<<"END"); + $domain$id$name$section

') if ($mode eq 'view'); +} + +# +# print out form for modification of a single students data +# +sub print_modify_student_form { + my $r = shift(); + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['sdom','sname']); + + my $sname = $ENV{'form.sname'}; + my $sdom = $ENV{'form.sdom'}; + # determine the students name information + my %info=&Apache::lonnet::get('environment', + ['firstname','middlename', + 'lastname','generation'], + $sdom, $sname); + my ($tmp) = keys(%info); + if ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $r->print('Error'. + '

'. + 'Unable to retrieve environment data for '.$sname. + 'in domain '.$sdom.'

'. + 'Please contact your LON-CAPA administrator '. + 'regarding this situation.

'); + return; + } + # determine the students starting and ending times and section + my ($starttime,$endtime,$section) = &get_enrollment_data($sname,$sdom); + # Deal with date forms + my $startdateform = &Apache::lonhtmlcommon::date_setter('studentform', + 'startdate', + $starttime); + my $enddateform = &Apache::lonhtmlcommon::date_setter('studentform', + 'enddate', + $endtime); + # Make sure student is enrolled in course + $r->print(< + + + +

Modify Enrollment for $info{'firstname'} $info{'middlename'} +$info{'lastname'} $info{'generation'}, $sname\@$sdom

+

+Student Name + + + +
FirstMiddleLastGeneration
+ + + +
+

+Section: +

+ + + +
Starting Date:$startdateform
Ending Date:$enddateform
+

+ + +END + return; +} + +# +# modify a single students section +# +sub modify_single_student { + my $r = shift; + # make sure user can modify student data? + my $firstname = $ENV{'form.firstname'}; + my $middlename = $ENV{'form.middlename'}; + my $lastname = $ENV{'form.lastname'}; + my $generation = $ENV{'form.generation'}; + my $section = $ENV{'form.section'}; + my $courseid = $ENV{'request.course.id'}; + my $sname = $ENV{'form.slogin'}; + my $sdom = $ENV{'form.sdomain'}; + my $starttime = &Apache::lonhtmlcommon::get_date_from_form('startdate', + time); + my $endtime = &Apache::lonhtmlcommon::get_date_from_form('enddate', + time); + my $displayable_starttime = localtime($starttime); + my $displayable_endtime = localtime($endtime); + # talk to the user about what we are going to do + $r->print(< +

Student Information

+ + + + + +
First name $firstname
Middle name $middlename
Last name $lastname
Generation $generation
+

Role Information

+ + + + +
Section $section
Start Time $displayable_starttime
End Time $displayable_endtime
+END + # send request(s) to modify data + my $roleresults = 'refused'; + #my $roleresults = &Apache::lonnet::assignrole($sdom,$sname, + # $courseid.'/'.$section, + # 'st', + # $endtime,$starttime); + if ($roleresults =~/refused/) { + $r->print("Your request to change the role information for this ". + "student was refused."); + } elsif ($roleresults !~ /ok/) { + $r->print("An error occurred during the attempt to change the role". + " information for this student. The error reported was ". + $roleresults); + } else { # everything is okay! + $r->print("Student role updated successfully."); + } + # + $r->print(< +END + return; +} + +sub get_enrollment_data { + my ($sname,$sdomain) = @_; + my $courseid = $ENV{'request.course.id'}; + $courseid =~ s:_:/:g; + my %roles = &Apache::lonnet::dump('roles',$sdomain,$sname); + my ($tmp) = keys(%roles); + # Bail out if we were unable to get the students roles + return "666" if ($tmp =~ /^(con_lost|error|no_such_host)/i); + # Go through the roles looking for enrollment in this course + my ($end,$start) = (undef,undef); + my $section = ''; + my $count = scalar(keys(%roles)); + while (my ($course,$role) = each(%roles)) { + &Apache::lonnet::logthis('course = '.$course.' role = '.$role); + if ($course=~ /^\/$courseid\/*\s*(\w+)*_st$/ ) { + # + # Get active role + $section=$1; + (undef,$end,$start)=split(/\_/,$role); + my $now=time; + my $notactive=0; + if ($start) { + if ($now<$start) { $notactive=1; } + } + if ($end) { + if ($now>$end) { $notactive=1; } + } + unless ($notactive) { return ($start,$end,$section); } + } + } + return ($start,$end,$section); +} + +# =================================================== Show student list to drop sub show_drop_list { - my ($r,%currentlist)=@_; + my ($students,$student_data,$r)=@_; my $cid=$ENV{'request.course.id'}; + $r->print(<<'END'); + + + +

+ + + + +END + foreach my $student (@$students) { + my $username = $student_data->{$student.':username'}; + my $domain = $student_data->{$student.':domain'}; + my $section = $student_data->{$student.':section'}; + my $name = $student_data->{$student.':fullname'}; + my $status = $student_data->{$student.':Status'}; + my $id = $student_data->{$student.':id'}; + next if ($status ne 'Active'); + # + $r->print(<<"END"); + + + + + + + + +END } $r->print('
 usernamedomainIDstudent namesection
$username$domain$id$name$section

'); - $r->print(''); + $r->print(<<"END"); +

+   + +

+END + return; } -# ================================================= Drop/Add from uploaded file +# +# Print out the initial form to get the courselist file +# +sub print_first_courselist_upload_form { + my $r=shift; + my $upfile_select=&Apache::loncommon::upfile_select_html(); + my $create_classlist_help = + &Apache::loncommon::help_open_topic("Course_Create_Class_List", + "How do I create a class list from a spreadsheet"); + my $create_csv_help = + &Apache::loncommon::help_open_topic("Course_Convert_To_CSV", + "How do I create a CSV file from a spreadsheet"); + $r->print(< +

Upload a courselist

+$upfile_select +

+ + + +

+$create_classlist_help
+$create_csv_help + +ENDUPFORM + return; +} +# ================================================= Drop/Add from uploaded file sub upfile_drop_add { my $r=shift; &Apache::loncommon::load_tmp_file($r); my @studentdata=&Apache::loncommon::upfile_record_sep(); - my @keyfields=split(/\,/,$ENV{'form.keyfields'}); - my $cid=$ENV{'request.course.id'}; + my @keyfields = split(/\,/,$ENV{'form.keyfields'}); + my $cid = $ENV{'request.course.id'}; my %fields=(); - for (my $i=0;$i<=$ENV{'form.nfields'};$i++) { + for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) { if ($ENV{'form.upfile_associate'} eq 'reverse') { if ($ENV{'form.f'.$i} ne 'none') { $fields{$keyfields[$i]}=$ENV{'form.f'.$i}; @@ -721,20 +1116,35 @@ sub upfile_drop_add { $fields{$ENV{'form.f'.$i}}=$keyfields[$i]; } } - my $startdate=$ENV{'form.startdate'}; - my $enddate=$ENV{'form.enddate'}; + # + my $startdate = $ENV{'form.startdate'}; + my $enddate = $ENV{'form.enddate'}; if ($startdate=~/\D/) { $startdate=''; } - if ($enddate=~/\D/) { $enddate=''; } + if ($enddate=~/\D/) { $enddate=''; } + # Determine domain and desired host (home server) my $domain=$ENV{'form.lcdomain'}; - my $amode=''; - my $genpwd=''; + my $desiredhost = $ENV{'form.lcserver'}; + if (lc($desiredhost) eq 'default') { + $desiredhost = undef; + } else { + my %home_servers = &Apache::loncommon::get_library_servers($domain); + if (! exists($home_servers{$desiredhost})) { + $r->print('Error:'. + 'Invalid home server specified'); + return; + } + } + # Determine authentication mechanism + my $amode = ''; + my $genpwd = ''; if ($ENV{'form.login'} eq 'krb') { - $amode='krb4'; - $genpwd=$ENV{'form.krbdom'}; + $amode='krb'; + $amode.=$ENV{'form.krbver'}; + $genpwd=$ENV{'form.krbarg'}; } elsif ($ENV{'form.login'} eq 'int') { $amode='internal'; - if ((defined($ENV{'form.intpwd'})) && ($ENV{'form.intpwd'})) { - $genpwd=$ENV{'form.intpwd'}; + if ((defined($ENV{'form.intarg'})) && ($ENV{'form.intarg'})) { + $genpwd=$ENV{'form.intarg'}; } } elsif ($ENV{'form.login'} eq 'loc') { $amode='localauth'; @@ -743,20 +1153,23 @@ sub upfile_drop_add { } } unless (($domain=~/\W/) || ($amode eq '')) { + ####################################### + ## Enroll Students ## + ####################################### $r->print('

Enrolling Students

'); my $count=0; my $flushc=0; my %student=(); -# ----------------------------------------------------------- Get new classlist -# --------------------------------------------------------- Enroll new students + # Get new classlist foreach (@studentdata) { my %entries=&Apache::loncommon::record_sep($_); + # Determine student name unless (($entries{$fields{'username'}} eq '') || (!defined($entries{$fields{'username'}}))) { - my $fname=''; my $mname=''; my $lname=''; my $gen=''; + my ($fname, $mname, $lname,$gen) = ('','','',''); if (defined($fields{'names'})) { - ($lname,$fname,$mname)= - ($entries{$fields{'names'}}=~/([^\,]+)\,\s*(\w+)\s*(.*)$/); + ($lname,$fname,$mname)=($entries{$fields{'names'}}=~ + /([^\,]+)\,\s*(\w+)\s*(.*)$/); } else { if (defined($fields{'fname'})) { $fname=$entries{$fields{'fname'}}; @@ -776,6 +1189,7 @@ sub upfile_drop_add { $entries{$fields{'username'}}.' for user '. $fname.' '.$mname.' '.$lname.' '.$gen.'

'); } else { + # determine section number my $sec=''; my $username=$entries{$fields{'username'}}; if (defined($fields{'sec'})) { @@ -783,6 +1197,7 @@ sub upfile_drop_add { $sec=$entries{$fields{'sec'}}; } } + # determine student id number my $id=''; if (defined($fields{'id'})) { if (defined($entries{$fields{'id'}})) { @@ -790,6 +1205,7 @@ sub upfile_drop_add { } $id=~tr/A-Z/a-z/; } + # determine student password my $password=''; if ($genpwd) { $password=$genpwd; @@ -801,14 +1217,16 @@ sub upfile_drop_add { } } if ($password) { - &dropstudent($domain,$username,$cid,$sec); + &modifystudent($domain,$username,$cid,$sec, + $desiredhost); my $reply=&Apache::lonnet::modifystudent ($domain,$username,$id,$amode,$password, $fname,$mname,$lname,$gen,$sec,$enddate, - $startdate,$ENV{'form.forceid'}); - unless ($reply eq 'ok') { - $r->print( - "

Error enrolling $username: $reply

"); + $startdate,$ENV{'form.forceid'},$desiredhost); + if ($reply ne 'ok') { + $r->print('

'. + 'Error enrolling '.$username.': '. + $reply.'

'); } else { $count++; $flushc++; $student{$username}=1; @@ -822,132 +1240,234 @@ sub upfile_drop_add { $r->print("

No password for $username

"); } } - } - } + } + } # end of foreach (@studentdata) $r->print('

Processed Students: '.$count); -# --------------------------------------------------------------- Drop students + ##################################### + # Drop students # + ##################################### if ($ENV{'form.fullup'} eq 'yes') { $r->print('

Dropping Students

'); -# ------------------------------------------------------- Get current classlist - my $classlst=&Apache::lonnet::reply - ('dump:'.$ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist', - $ENV{'course.'.$cid.'.home'}); - my %currentlist=(); - my $now=time; - unless ($classlst=~/^error\:/) { - foreach (split(/\&/,$classlst)) { - my ($name,$value)=split(/\=/,$_); - my ($end,$start)=split(/\:/, - &Apache::lonnet::unescape($value)); - my $active=1; - if (($end) && ($now>$end)) { $active=0; } - if ($active) { - $currentlist{&Apache::lonnet::unescape($name)}=1; - } - } -# ------------------------------------------------ Now got up-to-date classlist + # Get current classlist + my ($error,%currentlist)=&get_current_classlist($r); + if (defined($error)) { + $r->print('
ERROR:$error
'); + } + if (defined(%currentlist)) { + # Drop the students foreach (@studentdata) { my %entries=&Apache::loncommon::record_sep($_); unless (($entries{$fields{'username'}} eq '') || (!defined($entries{$fields{'username'}}))) { - delete($currentlist{ - $entries{$fields{'username'}}.':'. - $domain}); + delete($currentlist{$entries{$fields{'username'}}. + ':'.$domain}); } } -# ----------------------------------------------------------- Print out choices + # Print out list of dropped students &show_drop_list($r,%currentlist); } else { - $r->print('

Could not access classlist: '. - $classlst.'

'); + $r->print("There are no students currently enrolled.\n"); } } -# ------------------------------------------------------------------------ Done + } # end of unless +} + +################################################################### +################################################################### + +=pod + +=item &drop_students + +Inputs: \@droplist, a pointer to an array of students to drop. +Students should be in format of studentname:studentdomain + +Returns: $errors, a string describing any errors encountered. +$successes, a string describing the successful dropping of students. + +=cut + +################################################################### +################################################################### +sub drop_students { + my @droplist = @{shift()}; + my $courseid = $ENV{'request.course.id'}; + my $successes = ''; + my $errors = ''; + foreach (@droplist) { + my ($sname,$sdom)=split(/:/,$_); + my $result = &drop_student($sname,$sdom,$courseid); + if ($result !~ /ok/) { + $errors .= "Error dropping $sname\@$sdom: $result\n"; + } else { + $successes .= "Dropped $sname\@$sdom\n"; + } } + return ($errors,$successes); } +################################################################### +################################################################### -# ================================================================== Phase four +# ================================================================== Phase four sub drop_student_list { my $r=shift; my $count=0; - foreach (keys %ENV) { - if ($_=~/^form\.drop\:/) { - my ($dummy,$uname,$udom)=split(/\:/,$_); - &dropstudent($udom,$uname,$ENV{'request.course.id'}); + my @droplist; + if (ref($ENV{'form.droplist'})) { + @droplist = @{$ENV{'form.droplist'}}; + } else { + @droplist = ($ENV{'form.droplist'}); + } + foreach (@droplist) { + my ($uname,$udom)=split(/\:/,$_); + my $result = &modifystudent($udom,$uname,$ENV{'request.course.id'}); + if ($result eq 'ok' || $result eq 'ok:') { $r->print('Dropped '.$uname.' at '.$udom.'
'); - $count++; + } else { + $r->print('Error dropping '.$uname.' at '.$udom.': '.$result. + '
'); } + $count++; } $r->print('

Dropped '.$count.' student(s).'); $r->print('

Re-enrollment will re-activate data.'); } -# ================================================================ Main Handler +################################################################### +################################################################### + +=pod + +=item &handler + +The typical handler you see in all these modules. Takes $r, the +http request, as an argument. + +The response to the request is governed by two form variables + + form.action form.state response + --------------------------------------------------- + undefined undefined print main menu + upload undefined print courselist upload menu + upload got_file deal with uploaded file, + print the upload managing menu + upload enrolling enroll students based on upload + drop undefined print the classlist ready to drop + drop done drop the selected students + enrollstudent undefined print single student enroll menu + enrollstudent enrolling enroll student + classlist undefined print html classlist + classlist csv print csv classlist + modifystudent undefined print classlist to select student to modify + modifystudent selected print modify student menu + modifystudent done make modifications to student record + +=cut +################################################################### +################################################################### sub handler { - my $r=shift; - $Apache::lonxml::debug=1; - if ($r->header_only) { - $r->content_type('text/html'); - $r->send_http_header; - return OK; - } -# ----------------------------------------------------- Needs to be in a course - if (($ENV{'request.course.fn'}) && - (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'}))) { -# ------------------------------------------------------------------ Start page - $r->content_type('text/html'); - $r->send_http_header; - &header($r); -# --------------------------------------------------- Phase one, initial screen - unless ($ENV{'form.phase'}) { - &menu_phase_one($r); - } -# ------------------------------------------------------------------- Phase two - if ($ENV{'form.associate'} eq 'Reverse Association') { - $ENV{'form.phase'} = 'two'; - if ( $ENV{'form.upfile_associate'} ne 'reverse' ) { - $ENV{'form.upfile_associate'} = 'reverse'; - } else { - $ENV{'form.upfile_associate'} = 'forward'; - } - } - if ($ENV{'form.phase'} eq 'two') { - if ($ENV{'form.fileupload'}) { - &menu_phase_two_upload($r); - } elsif ($ENV{'form.enroll'}) { - &menu_phase_two_enroll($r); - } elsif ($ENV{'form.drop'}) { - &menu_phase_two_drop($r); - } - } -# ----------------------------------------------------------------- Phase three - if ($ENV{'form.phase'} eq 'three') { - if ($ENV{'form.datatoken'}) { - &upfile_drop_add($r); - } - } -# ------------------------------------------------------------------ Phase four - if ($ENV{'form.phase'} eq 'four') { - &drop_student_list($r); - } -# ------------------------------------------------------------------ Phase five - if ($ENV{'form.phase'} eq 'five') { - &enroll_single_student($r); - } -# ------------------------------------------------------------------------- End - $r->print('

'); - } else { -# ----------------------------- Not in a course, or not allowed to modify parms - $ENV{'user.error.msg'}= - "/adm/dropadd:cst:0:0:Cannot drop or add students"; - return HTTP_NOT_ACCEPTABLE; - } - return OK; + my $r=shift; + if ($r->header_only) { + $r->content_type('text/html'); + $r->send_http_header; + return OK; + } + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['action','state']); + # Needs to be in a course + if (! (($ENV{'request.course.fn'}) && + (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'})))) { + # Not in a course, or not allowed to modify parms + $ENV{'user.error.msg'}= + "/adm/dropadd:cst:0:0:Cannot drop or add students"; + return HTTP_NOT_ACCEPTABLE; + } + # + # Only output the header information if they did not request csv format + # + if (exists($ENV{'form.state'}) && ($ENV{'form.state'} eq 'csv')) { + $r->content_type('text/csv'); + } else { + # Start page + $r->content_type('text/html'); + $r->send_http_header; + $r->print(&header()); + } + # + # Main switch on form.action and form.state, as appropriate + if (! exists($ENV{'form.action'})) { + &print_main_menu($r); + } elsif ($ENV{'form.action'} eq 'upload') { + if (! exists($ENV{'form.state'})) { + &print_first_courselist_upload_form($r); + } elsif ($ENV{'form.state'} eq 'got_file') { + &print_upload_manager_form($r); + } elsif ($ENV{'form.state'} eq 'enrolling') { + if ($ENV{'form.datatoken'}) { + &upfile_drop_add($r); + } else { + # Hmmm, this is an error + } + } else { + &print_first_courselist_upload_form($r); + } + } elsif ($ENV{'form.action'} eq 'drop') { + if (! exists($ENV{'form.state'})) { + &print_drop_menu($r); + } elsif ($ENV{'form.state'} eq 'done') { + &drop_student_list($r); + } else { + &menu_phase_two_drop($r); + } + } elsif ($ENV{'form.action'} eq 'enrollstudent') { + if (! exists($ENV{'form.state'})) { + &print_enroll_single_student_form($r); + } elsif ($ENV{'form.state'} eq 'enrolling') { + &enroll_single_student($r); + } else { + &print_enroll_single_student_form($r); + } + } elsif ($ENV{'form.action'} eq 'classlist') { + if (! exists($ENV{'form.state'})) { + &print_html_classlist($r); + } elsif ($ENV{'form.state'} eq 'csv') { + &print_csv_classlist($r); + } else { + &print_html_classlist($r); + } + } elsif ($ENV{'form.action'} eq 'modifystudent') { + if (! exists($ENV{'form.state'})) { + &print_html_classlist($r); + } elsif ($ENV{'form.state'} eq 'selected') { + &print_modify_student_form($r); + } elsif ($ENV{'form.state'} eq 'done') { + &modify_single_student($r); + } else { + &print_html_classlist($r); + } + } else { + # We should not end up here, but I guess it is possible + &Apache::lonnet::logthis("Undetermined state in londropadd.pm. ". + "form.action = ".$ENV{'form.action'}. + "Someone should fix this."); + &print_main_menu($r); + } + # + # Finish up + if (exists($ENV{'form.state'}) && ($ENV{'form.state'} eq 'csv')) { + $r->print("\n"); + } else { + $r->print(''); + } + return OK; } +################################################################### +################################################################### + 1; __END__ + 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.