--- loncom/interface/Attic/londropadd.pm 2002/04/16 19:08:49 1.25
+++ loncom/interface/Attic/londropadd.pm 2012/04/24 21:05:15 1.179
@@ -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.179 2012/04/24 21:05:15 droeschl Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -25,283 +25,446 @@
#
# http://www.lon-capa.org/
#
-# (Handler to set parameters for assessments
#
-# (Handler to resolve ambiguous file locations
-#
-# (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
+
+=head1 NAME
+
+Apache::londropadd.pm
+
+=head1 SYNOPSIS
+
+drop & add students
+
+This is part of the LearningOnline Network with CAPA project
+described at http://www.lon-capa.org.
+
+=head1 SUBROUTINES
+
+=over
+
+=cut
package Apache::londropadd;
use strict;
-use Apache::lonnet();
+use Apache::lonnet;
use Apache::loncommon();
+use Apache::lonhtmlcommon();
use Apache::Constants qw(:common :http REDIRECT);
-
-# ================================================================ Print header
+use Spreadsheet::WriteExcel;
+use Apache::lonstathelpers();
+use Apache::lonlocal;
+use Apache::longroup;
+use LONCAPA();
sub header {
- my $r=shift;
- $r->print(<Drop/Add Students
-
+$lt{'email'}: +
+$lt{'sid'}: +
+ +
+$lt{'sec'}: +
+$current_date_description
+$date_table
+ +END + $r->print(&Apache::loncommon::end_page()); + return; +} + + +=pod + +=item modify_single_student() + + modify a single students section + +=cut + +sub modify_single_student { + my ($r) = @_; + # + # Remove non alphanumeric values from the section + $env{'form.section'} =~ s/\W//g; + # + # Do the date defaults first + my ($starttime,$endtime) = &Apache::lonuserutils::get_dates_from_form(); + if ($env{'form.makedatesdefault'}) { + $r->print(&Apache::lonuserutils::make_dates_default($starttime, + $endtime)); + } + # Get the 'sortby' and 'Status' variables so the user goes back to their + # previous screen + my $sortby = $env{'form.sortby'}; + my $status = $env{'form.Status'}; + # + # We always need this information + my $slogin = $env{'form.slogin'}; + my $sdom = $env{'form.sdomain'}; + # + # Get the old data + my %old=&Apache::lonnet::get('environment', + ['firstname','middlename', + 'lastname','generation','id', + 'permanentemail'],$sdom, $slogin); + $old{'section'} = &Apache::lonnet::getsection($sdom,$slogin, + $env{'request.course.id'}); + my ($tmp) = keys(%old); + if ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $r->print(&mt('There was an error determining the environment values for')." $slogin : $sdom."); + return; + } + undef $tmp; + # + # Get the new data + my $firstname = $env{'form.firstname'}; + my $middlename = $env{'form.middlename'}; + my $lastname = $env{'form.lastname'}; + my $generation = $env{'form.generation'}; + my $permanentemail = $env{'form.permanentemail'}; + my $section = $env{'form.section'}; + my $courseid = $env{'request.course.id'}; + my $sid = $env{'form.id'}; + my $displayable_starttime = localtime($starttime); + my $displayable_endtime = localtime($endtime); + # + # check for forceid override + if ((defined($old{'id'})) && ($old{'id'} ne '') && + ($sid ne $old{'id'}) && (! exists($env{'form.forceid'}))) { + $r->print("".&mt('You changed the students id but did not disable the ID change safeguard. The students id will not be changed.').""); + $sid = $old{'id'}; + } + # + # talk to the user about what we are going to do + my %lt=&Apache::lonlocal::texthash( + 'mdu' => "Modifying data for user", + 'si' => "Student Information", + 'fd' => "Field", + 'ov' => "Old Value", + 'nv' => "New Value", + 'fn' => "First name", + 'mn' => "Middle name", + 'ln' => "Last name", + 'gen' => "Generation", + 'em' => "E-mail address", + 'sec' => "Section", + 'ri' => "Role Information", + 'st' => "Start Time", + 'et' => "End Time", + ); + $r->print(<$lt{si} | +||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
+
|
+
$lt{'ri'} | +||||
---|---|---|---|---|
+
|
+
+END
+ #
+ # Send request(s) to modify data (final undef is for 'desiredhost',
+ # which is a moot point because the student already has an account.
+ my $modify_section_results =
+ &Apache::lonuserutils::modifystudent($sdom,$slogin,
+ $env{'request.course.id'},
+ $section,undef);
+ if ($modify_section_results !~ /^ok/) {
+ $r->print(&mt('An error occurred during the attempt to change the section for this student.')."
+
+
+
+$Masd
+END
+ $r->print(&Apache::loncommon::end_page());
+ return;
+}
+
+sub get_enrollment_data {
+ my ($sname,$sdomain) = @_;
+ my $courseid = $env{'request.course.id'};
+ my $cdom = $env{'course.'.$courseid.'.domain'};
+ my $cnum = $env{'course.'.$courseid.'.num'};
+ my %roles = &Apache::lonnet::dump('roles',$sdomain,$sname);
+ my ($tmp) = keys(%roles);
+ # Bail out if we were unable to get the students roles
+ return ('error'.$tmp) 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)) {
+ if ($course=~m{^/\Q$cdom\E/\Q$cnum\E/*\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);
+}
+
+
+=pod
+
+=item show_drop_list()
+
+Display a list of students to drop
+Inputs:
+
+=over 4
+
+=item $r, Apache request
+
+=item $classlist, hash pointer returned from loncoursedata::get_classlist();
+
+=item $keylist, array pointer returned from loncoursedata::get_classlist()
+which describes the order elements are stored in the %$classlist values.
+
+=item $nosort, if true, sorting links are omitted.
+
+=back
+
+=cut
sub show_drop_list {
- my ($r,%currentlist)=@_;
- my $cid=$ENV{'request.course.id'};
+ my ($r,$classlist,$keylist,$nosort)=@_;
+ my $cid=$env{'request.course.id'};
+ if (! exists($env{'form.sortby'})) {
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['sortby']);
+ }
+ my $sortby = $env{'form.sortby'};
+ if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
+ $sortby = 'username';
+ }
+ my $cdom = $env{'course.'.$cid.'.domain'};
+ my $cnum = $env{'course.'.$cid,'.num'};
+ my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
+ $classlist,$keylist,$cdom,$cnum);
+ #
+ my $action = "drop";
+ $r->print(<
+
+END
- $r->print('');
- $r->print('
");
+ }
+ my $roleresults = &Apache::lonnet::modifystudent
+ ($sdom,$slogin,$sid,undef,undef,$firstname,$middlename,$lastname,
+ $generation,$section,$endtime,$starttime,$env{'form.forceid'},
+ undef,$permanentemail);
+ if ($old{'permanentemail'} ne $permanentemail) {
+ &Apache::loncommon::flush_email_cache($slogin,$sdom);
+ }
+ if ($roleresults eq 'refused' ) {
+ $r->print(&mt('Your request to change the role information for this student was refused. You do not appear to have sufficient authority to change student information.'));
+ } elsif ($roleresults !~ /ok/) {
+ $r->print(&mt('An error occurred during the attempt to change the role information for this student.')."
".
+ &mt('The error reported was')." ".
+ $roleresults);
+ &Apache::lonnet::logthis("londropadd:failed attempt to modify student".
+ " data for ".$slogin." : ".$sdom." by ".
+ $env{'user.name'}." : ".$env{'user.domain'}.
+ ":".$roleresults);
+ } else { # everything is okay!
+ $r->print(&mt('Student information updated successfully.')."
".
+ &mt('The student must log out and log in again to see these changes.'));
+ }
+ my $Masd=&mt('Modify another students data');
+ $r->print(<');
- foreach (sort keys %currentlist) {
- my ($sname,$sdom)=split(/\:/,$_);
- my %reply=&Apache::lonnet::idrget($sdom,$sname);
- my $ssec=&Apache::lonnet::usection($sdom,$sname,$cid);
- my @reply=split(/[\&\=]/,&Apache::lonnet::reply
- ('get:'.$sdom.':'.$sname.
- ':environment:firstname&middlename&lastname&generation',
- &Apache::lonnet::homeserver($sname,$sdom)));
- $r->print('
\n");
+my %lt=&Apache::lonlocal::texthash('usrn' => "username",
+ 'dom' => "domain",
+ 'sn' => "student name",
+ 'sec' => "section",
+ 'start' => "start date",
+ 'end' => "end date",
+ 'groups' => "active groups",
+ );
+ if ($nosort) {
+ $r->print(&Apache::loncommon::start_data_table());
+ $r->print(<'.
- $sname.' '.$sdom.' '.
- $reply{$sname}.' '.
- &Apache::lonnet::unescape($reply[2]).' '.
- &Apache::lonnet::unescape($reply[3]).', '.
- &Apache::lonnet::unescape($reply[0]).' '.
- &Apache::lonnet::unescape($reply[1]).
- ' '.
- $ssec."
+ $lt{'usrn'}
+ $lt{'dom'}
+ ID
+ $lt{'sn'}
+ $lt{'sec'}
+ $lt{'start'}
+ $lt{'end'}
+ $lt{'groups'}
+
+END
+
+ } else {
+ $r->print(&Apache::loncommon::start_data_table());
+ $r->print(<
+
+ $lt{'usrn'}
+
+ $lt{'dom'}
+
+ ID
+
+ $lt{'sn'}
+
+ $lt{'sec'}
+
+ $lt{'start'}
+
+ $lt{'end'}
+
+ $lt{'groups'}
+
+
+END
+ }
+ #
+ # Sort the students
+ my %index;
+ my $i;
+ foreach (@$keylist) {
+ $index{$_} = $i++;
}
- $r->print('
');
- $r->print('');
+ $index{'groups'} = scalar(@$keylist);
+ my $index = $index{$sortby};
+ my $second = $index{'username'};
+ my $third = $index{'domain'};
+ my @Sorted_Students = sort {
+ lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
+ ||
+ lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
+ ||
+ lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
+ } (keys(%$classlist));
+ foreach my $student (@Sorted_Students) {
+ my $error;
+ my $sdata = $classlist->{$student};
+ my $username = $sdata->[$index{'username'}];
+ my $domain = $sdata->[$index{'domain'}];
+ my $section = $sdata->[$index{'section'}];
+ my $name = $sdata->[$index{'fullname'}];
+ my $id = $sdata->[$index{'id'}];
+ my $start = $sdata->[$index{'start'}];
+ my $end = $sdata->[$index{'end'}];
+ my $groups = $classgroups->{$student};
+ my $active_groups;
+ if (ref($groups->{active}) eq 'HASH') {
+ $active_groups = join(', ',keys(%{$groups->{'active'}}));
+ }
+ if (! defined($start) || $start == 0) {
+ $start = &mt('none');
+ } else {
+ $start = &Apache::lonlocal::locallocaltime($start);
+ }
+ if (! defined($end) || $end == 0) {
+ $end = &mt('none');
+ } else {
+ $end = &Apache::lonlocal::locallocaltime($end);
+ }
+ my $status = $sdata->[$index{'status'}];
+ next if ($status ne 'Active');
+ #
+ $r->print(&Apache::loncommon::start_data_table_row());
+ $r->print(<<"END");
+
+ $username
+ $domain
+ $id
+ $name
+ $section
+ $start
+ $end
+ $active_groups
+END
+ $r->print(&Apache::loncommon::end_data_table_row());
+ }
+ $r->print(&Apache::loncommon::end_data_table().'
');
+ %lt=&Apache::lonlocal::texthash(
+ 'dp' => "Drop Students",
+ 'ca' => "check all",
+ 'ua' => "uncheck all",
+ );
+ $r->print(<<"END");
+
+ + +
+END + return; +} + + +=pod + +=item print_first_courselist_upload_form() + + Print out the initial form to get the courselist file + +=cut + +sub print_first_courselist_upload_form { + my $r=shift; + my $str; + $str = ''; + $str .= ''; + $str .= ''; + $str .= "\n"; + $str .= ''."\n"; + $str .= '
\n"; + $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List", + &mt("How do I create a class list from a spreadsheet")). + "\n"); my $count=0; my $flushc=0; my %student=(); -# ----------------------------------------------------------- Get new classlist -# --------------------------------------------------------- Enroll new students + # Get information about course groups + my %curr_groups = &Apache::longroup::coursegroups(); + # 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'}}; @@ -771,11 +2485,14 @@ sub upfile_drop_add { $gen=$entries{$fields{'gen'}}; } } - if ($entries{$fields{'username'}}=~/\W/) { - $r->print('
Unacceptable username: '. - $entries{$fields{'username'}}.' for user '. - $fname.' '.$mname.' '.$lname.' '.$gen.'
');
+ if ($entries{$fields{'username'}}
+ ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
+ $r->print('
'.
+ &mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]',
+ $entries{$fields{'username'}},$fname,$mname,$lname,$gen).
+ '');
} else {
+ # determine section number
my $sec='';
my $username=$entries{$fields{'username'}};
if (defined($fields{'sec'})) {
@@ -783,6 +2500,20 @@ sub upfile_drop_add {
$sec=$entries{$fields{'sec'}};
}
}
+ # remove non alphanumeric values from section
+ $sec =~ s/\W//g;
+ if ($sec eq "none" || $sec eq 'all') {
+ $r->print('
'.
+ &mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a reserved word.',
+ $username,$sec,$fname,$mname,$lname,$gen));
+ next;
+ } elsif (($sec ne '') && (exists($curr_groups{$sec}))) {
+ $r->print('
'.
+ &mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a course group. Section names and group names must be distinct.',
+ $username,$sec,$fname,$mname,$lname,$gen));
+ next;
+ }
+ # determine student id number
my $id='';
if (defined($fields{'id'})) {
if (defined($entries{$fields{'id'}})) {
@@ -790,6 +2521,15 @@ sub upfile_drop_add {
}
$id=~tr/A-Z/a-z/;
}
+ # determine email address
+ my $email='';
+ if (defined($fields{'email'})) {
+ if (defined($entries{$fields{'email'}})) {
+ $email=$entries{$fields{'email'}};
+ unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
+ }
+ }
+ # determine student password
my $password='';
if ($genpwd) {
$password=$genpwd;
@@ -800,15 +2540,24 @@ sub upfile_drop_add {
}
}
}
- if ($password) {
- &dropstudent($domain,$username,$cid,$sec);
+ # Clean up whitespace
+ foreach (\$domain,\$username,\$id,\$fname,\$mname,
+ \$lname,\$gen,\$sec) {
+ $$_ =~ s/(\s+$|^\s+)//g;
+ }
+ if ($password || $env{'form.login'} eq 'loc') {
+ &Apache::lonuserutils::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,
+ $email);
+ if ($reply ne 'ok') {
+ $reply =~ s/^error://;
+ $r->print('
'.
+ &mt('[_1]: Unable to enroll: [_2]',$username,$reply));
} else {
$count++; $flushc++;
$student{$username}=1;
@@ -819,135 +2568,366 @@ sub upfile_drop_add {
}
}
} else {
- $r->print("
No password for $username
"); - } - } - } - } - $r->print('
Processed Students: '.$count); -# --------------------------------------------------------------- Drop students - if ($ENV{'form.fullup'} eq 'yes') { - $r->print('
\n".&mt('Processed [quant,_1,student].',$count). + "
\n"); + $r->print("\n". + &mt('If active, the new role will be available when the '. + 'students next log in to LON-CAPA.')."
\n"); + ##################################### + # Drop students # + ##################################### + if ($env{'form.fullup'} eq 'yes') { + $r->print('Dropped '.$count.' student(s).'); - $r->print('
Re-enrollment will re-activate data.'); + $r->print('
'.&mt('Dropped [quant,_1,student].',$count).'
'); + $r->print(''.&mt('Re-enrollment will re-activate data.')) if ($count);
}
-# ================================================================ Main Handler
+sub section_check_js {
+ my $groupslist;
+ my %curr_groups = &Apache::longroup::coursegroups();
+ if (%curr_groups) {
+ $groupslist = join('","',sort(keys(%curr_groups)));
+ }
+ return <<"END";
+function validate(caller) {
+ var groups = new Array("$groupslist");
+ var secname = caller.value;
+ if ((secname == 'all') || (secname == 'none')) {
+ alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
+ return 'error';
+ }
+ if (secname != '') {
+ for (var k=0; k