\n"
+ );
}
my ($indexhash,$keylist) = &make_keylist_array();
my (%userlist,%userinfo,$clearcoursepick);
if (($context eq 'domain') &&
- ($env{'form.roletype'} eq 'course') ||
+ ($env{'form.roletype'} eq 'course') ||
($env{'form.roletype'} eq 'community')) {
my ($crstype,$numcodes,$title,$warning);
if ($env{'form.roletype'} eq 'course') {
@@ -1469,9 +1542,11 @@ sub print_userlist {
$title = &mt('Select Communities');
$warning = &mt('Warning: data retrieval for multiple communities can take considerable time, as this operation is not currently optimized.');
}
+ my @standardnames = &Apache::loncommon::get_standard_codeitems();
my $courseform =
&Apache::lonhtmlcommon::course_selection($formname,$numcodes,
- $codetitles,$idlist,$idlist_titles,$crstype);
+ $codetitles,$idlist,$idlist_titles,$crstype,
+ \@standardnames);
$r->print('
';
- $str .= &Apache::loncommon::end_page();
-
$r->print($str);
return;
}
@@ -3743,7 +3818,7 @@ sub upfile_drop_add {
}
my ($startdate,$enddate) = &get_dates_from_form();
if ($env{'form.makedatesdefault'}) {
- $r->print(&make_dates_default($startdate,$enddate,$context,$crstype);
+ $r->print(&make_dates_default($startdate,$enddate,$context,$crstype));
}
# Determine domain and desired host (home server)
my $defdom=$env{'request.role.domain'};
@@ -3802,7 +3877,7 @@ sub upfile_drop_add {
} elsif ($setting eq 'course') {
$defaultrole = $env{'form.courserole'};
$defaultsec = $env{'form.sections'};
- }
+ }
} elsif ($context eq 'author') {
$defaultrole = $env{'form.defaultrole'};
} elsif ($context eq 'course') {
@@ -3909,15 +3984,22 @@ sub upfile_drop_add {
$r->print($groupwarn.' ');
}
}
- my (%curr_rules,%got_rules,%alerts);
+ my (%curr_rules,%got_rules,%alerts,%cancreate);
my %customroles = &my_custom_roles($crstype);
my @permitted_roles =
- &roles_on_upload($context,$setting,$crstype,%customroles);
+ &roles_on_upload($context,$setting,$crstype,%customroles);
+ my %longtypes = &Apache::lonlocal::texthash(
+ official => 'Institutional',
+ unofficial => 'Non-institutional',
+ );
+ my $newuserdom = $env{'request.role.domain'};
+ map { $cancreate{$_} = &can_create_user($newuserdom,$context,$_); } keys(%longtypes);
# Get new users list
foreach my $line (@userdata) {
my @secs;
my %entries=&Apache::loncommon::record_sep($line);
# Determine user name
+ $entries{$fields{'username'}} =~ s/^\s+|\s+$//g;
unless (($entries{$fields{'username'}} eq '') ||
(!defined($entries{$fields{'username'}}))) {
my ($fname, $mname, $lname,$gen) = ('','','','');
@@ -3938,13 +4020,20 @@ sub upfile_drop_add {
$gen=$entries{$fields{'gen'}};
}
}
+
if ($entries{$fields{'username'}}
ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
+ my $nowhitespace;
+ if ($entries{$fields{'username'}} =~ /\s/) {
+ $nowhitespace = ' - '.&mt('usernames may not contain spaces.');
+ }
$r->print(' '.
&mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]',
- ''.$entries{$fields{'username'}}.'',$fname,$mname,$lname,$gen));
+ ''.$entries{$fields{'username'}}.'',$fname,$mname,$lname,$gen).
+ $nowhitespace);
next;
} else {
+ $entries{$fields{'domain'}} =~ s/^\s+|\s+$//g;
if ($entries{$fields{'domain'}}
ne &LONCAPA::clean_domain($entries{$fields{'domain'}})) {
$r->print(' '. ''.$entries{$fields{'domain'}}.
@@ -4003,6 +4092,7 @@ sub upfile_drop_add {
# determine email address
my $email='';
if (defined($fields{'email'})) {
+ $entries{$fields{'email'}} =~ s/^\s+|\s+$//g;
if (defined($entries{$fields{'email'}})) {
$email=$entries{$fields{'email'}};
unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
@@ -4049,7 +4139,7 @@ sub upfile_drop_add {
$role = $defaultrole;
}
# Clean up whitespace
- foreach (\$id,\$fname,\$mname,\$lname,\$gen) {
+ foreach (\$id,\$fname,\$mname,\$lname,\$gen,\$inststatus) {
$$_ =~ s/(\s+$|^\s+)//g;
}
# check against rules
@@ -4058,20 +4148,52 @@ sub upfile_drop_add {
my (%rulematch,%inst_results,%idinst_results);
my $uhome=&Apache::lonnet::homeserver($username,$userdomain);
if ($uhome eq 'no_host') {
- next if ($userdomain ne $domain);
+ if ($userdomain ne $newuserdom) {
+ if ($context eq 'course') {
+ $r->print(' '.
+ &mt('[_1]: The domain specified ([_2]) is different to that of the course.',
+ ''.$username.'',$userdomain).' ');
+ } elsif ($context eq 'author') {
+ $r->print(&mt('[_1]: The domain specified ([_2]) is different to that of the author.',
+ ''.$username.'',$userdomain).' ');
+ } else {
+ $r->print(&mt('[_1]: The domain specified ([_2]) is different to that of your current role.',
+ ''.$username.'',$userdomain).' ');
+ }
+ $r->print(&mt('The user does not already exist, and you may not create a new user in a different domain.'));
+ next;
+ }
$checkid = 1;
$newuser = 1;
+ my $user = $username.':'.$newuserdom;
my $checkhash;
my $checks = { 'username' => 1 };
- $checkhash->{$username.':'.$domain} = { 'newuser' => 1, };
+ $checkhash->{$username.':'.$newuserdom} = { 'newuser' => 1, };
&Apache::loncommon::user_rule_check($checkhash,$checks,
\%alerts,\%rulematch,\%inst_results,\%curr_rules,
\%got_rules);
if (ref($alerts{'username'}) eq 'HASH') {
- if (ref($alerts{'username'}{$domain}) eq 'HASH') {
- next if ($alerts{'username'}{$domain}{$username});
+ if (ref($alerts{'username'}{$newuserdom}) eq 'HASH') {
+ if ($alerts{'username'}{$newuserdom}{$username}) {
+ $r->print(' '.
+ &mt('[_1]: matches the username format at your institution, but is not known to your directory service.',''.$username.'').' '.
+ &mt('Consequently, the user was not created.'));
+ next;
+ }
+ }
+ }
+ my $usertype = 'unofficial';
+ if (ref($rulematch{$user}) eq 'HASH') {
+ if ($rulematch{$user}{'username'}) {
+ $usertype = 'official';
}
}
+ unless ($cancreate{$usertype}) {
+ my $showtype = $longtypes{$usertype};
+ $r->print(' '.
+ &mt('[_1]: The user does not exist, and you are not permitted to create users of type: [_2].',''.$username.'',$showtype));
+ next;
+ }
} else {
if ($context eq 'course' || $context eq 'author') {
if ($userdomain eq $domain ) {
@@ -4122,7 +4244,12 @@ sub upfile_drop_add {
\%got_rules);
if (ref($alerts{'id'}) eq 'HASH') {
if (ref($alerts{'id'}{$userdomain}) eq 'HASH') {
- next if ($alerts{'id'}{$userdomain}{$id});
+ if ($alerts{'id'}{$userdomain}{$id}) {
+ $r->print(&mt('[_1]: has a student/employee ID matching the format at your institution, but the ID is found by your directory service.',
+ ''.$username.'').' '.
+ &mt('Consequently, the user was not created.'));
+ next;
+ }
}
}
}
@@ -4154,7 +4281,7 @@ sub upfile_drop_add {
$role = 'cr_'.$env{'user.domain'}.'_'.
$env{'user.name'}.'_'.$role;
}
- if (($role ne 'cc') && ($role ne 'co')) {
+ if (($role ne 'cc') && ($role ne 'co')) {
if (@secs > 1) {
$multiple = 1;
foreach my $sec (@secs) {
@@ -4217,7 +4344,7 @@ sub upfile_drop_add {
}
} # end of foreach (@userdata)
# Flush the course logs so reverse user roles immediately updated
- &Apache::lonnet::flushcourselogs();
+ $r->register_cleanup(\&Apache::lonnet::flushcourselogs);
$r->print("\n
\n");
if ($counts{'role'} > 0) {
@@ -4381,10 +4508,9 @@ sub print_drop_menu {
# ================================================================== Phase four
sub update_user_list {
- my ($r,$context,$setting,$choice) = @_;
+ my ($r,$context,$setting,$choice,$crstype) = @_;
my $now = time;
my $count=0;
- my $crstype;
if ($context eq 'course') {
$crstype = &Apache::loncommon::course_type();
}
@@ -4399,7 +4525,7 @@ sub update_user_list {
'reenable' => 'Re-enabled',
'activate' => 'Activated',
'chgdates' => 'Changed Access Dates for',
- 'chgsec' => 'Changed section for',
+ 'chgsec' => 'Changed section(s) for',
'drop' => 'Dropped',
},
error => {'revoke' => 'revoking',
@@ -4416,8 +4542,9 @@ sub update_user_list {
($startdate,$enddate) = &get_dates_from_form();
}
foreach my $item (@changelist) {
- my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,@sections,
- $scopestem);
+ my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,
+ @sections,$scopestem,$singlesec,$showsecs,$warn_singlesec,
+ $nothingtodo,$keepnosection);
if ($choice eq 'drop') {
($uname,$udom,$sec) = split(/:/,$item,-1);
$role = 'st';
@@ -4516,14 +4643,23 @@ sub update_user_list {
} elsif ($choice eq 'chgsec') {
my (@newsecs,$revresult,$nochg,@retained);
if (($role ne 'cc') && ($role ne 'co')) {
- @newsecs = split(/,/,$env{'form.newsecs'});
+ my @secs = sort(split(/,/,$env{'form.newsecs'}));
+ if (@secs) {
+ my %curr_groups = &Apache::longroup::coursegroups();
+ foreach my $sec (@secs) {
+ next if (($sec =~ /\W/) || ($sec eq 'none') ||
+ (exists($curr_groups{$sec})));
+ push(@newsecs,$sec);
+ }
+ }
}
# remove existing section if not to be retained.
- if (!$env{'form.retainsec'}) {
+ if (!$env{'form.retainsec'} || ($role eq 'st')) {
if ($sec eq '') {
if (@newsecs == 0) {
- $result = &mt('No change in section assignment (none)');
+ $result = 'ok';
$nochg = 1;
+ $nothingtodo = 1;
} else {
$revresult =
&Apache::lonnet::revokerole($udom,$uname,
@@ -4550,13 +4686,23 @@ sub update_user_list {
} else {
if ($sec eq '') {
$nochg = 1;
- } else {
+ $keepnosection = 1;
+ } else {
push(@retained,$sec);
}
}
# add new sections
+ my (@diffs,@shownew);
+ if (@retained) {
+ @diffs = &Apache::loncommon::compare_arrays(\@retained,\@newsecs);
+ } else {
+ @diffs = @newsecs;
+ }
if (@newsecs == 0) {
- if (!$nochg) {
+ if ($nochg) {
+ $result = 'ok';
+ $nothingtodo = 1;
+ } else {
if ($role eq 'st') {
$result =
&Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context);
@@ -4565,22 +4711,58 @@ sub update_user_list {
$result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start,'','',$context);
}
}
+ $showsecs = &mt('No section');
+ } elsif (@diffs == 0) {
+ $result = 'ok';
+ $nothingtodo = 1;
} else {
- foreach my $newsec (@newsecs) {
+ foreach my $newsec (@newsecs) {
if (!grep(/^\Q$newsec\E$/,@retained)) {
if ($role eq 'st') {
$result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context);
+ if (@newsecs > 1) {
+ my $showsingle;
+ if ($newsec eq '') {
+ $showsingle = &mt('No section');
+ } else {
+ $showsingle = $newsec;
+ }
+ if ($crstype eq 'Community') {
+ $warn_singlesec = &mt('Although more than one section was indicated, a role was only added for the first section - [_1], as each community member may only be in one section at a time.',''.$showsingle.'');
+ } else {
+ $warn_singlesec = &mt('Although more than one section was indicated, a role was only added for the first section - [_1], as each student may only be in one section of a course at a time.',''.$showsingle.'');
+ }
+ $showsecs = $showsingle;
+ last;
+ } else {
+ if ($newsec eq '') {
+ $showsecs = &mt('No section');
+ } else {
+ $showsecs = $newsec;
+ }
+ }
} else {
my $newscope = $scopestem;
if ($newsec ne '') {
$newscope .= '/'.$newsec;
+ push(@shownew,$newsec);
}
$result = &Apache::lonnet::assignrole($udom,$uname,
$newscope,$role,$end,$start);
+
}
}
}
}
+ unless ($role eq 'st') {
+ unless ($showsecs) {
+ my @tolist = sort(@shownew,@retained);
+ if ($keepnosection) {
+ push(@tolist,&mt('No section'));
+ }
+ $showsecs = join(', ',@tolist);
+ }
+ }
}
}
my $extent = $scope;
@@ -4591,13 +4773,48 @@ sub update_user_list {
}
}
if ($result eq 'ok' || $result eq 'ok:') {
- $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for [_3]",
- $plrole,$extent,$uname.':'.$udom).' ');
- $count++;
+ my $dates;
+ if (($choice eq 'chgsec') || ($choice eq 'chgdates')) {
+ $dates = &dates_feedback($start,$end,$now);
+ }
+ if ($choice eq 'chgsec') {
+ if ($nothingtodo) {
+ $r->print(&mt("Section assignment for role of '[_1]' in [_2] for '[_3]' unchanged.",$plrole,$extent,''.
+ &Apache::loncommon::plainname($uname,$udom).
+ '').' ');
+ if ($sec eq '') {
+ $r->print(&mt('[_1]No section[_2] - [_3]','','',$dates));
+ } else {
+ $r->print(&mt('Section(s): [_1] - [_2]',
+ ''.$showsecs.'',$dates));
+ }
+ $r->print(' ');
+ } else {
+ $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]' to [_4] - [_5]",$plrole,$extent,
+ ''.&Apache::loncommon::plainname($uname,$udom).'',
+ ''.$showsecs.'',$dates).' ');
+ $count ++;
+ }
+ if ($warn_singlesec) {
+ $r->print('
'.$warn_singlesec.'
');
+ }
+ } elsif ($choice eq 'chgdates') {
+ $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]' - [_4]",$plrole,$extent,
+ ''.&Apache::loncommon::plainname($uname,$udom).'',
+ $dates).' ');
+ $count ++;
+ } else {
+ $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]'.",$plrole,$extent,
+ ''.&Apache::loncommon::plainname($uname,$udom).'').
+ ' ');
+ $count ++;
+ }
} else {
$r->print(
- &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for [_3]: [_4].",
- $plrole,$extent,$uname.':'.$udom,$result).' ');
+ &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for '[_3]': [_4].",
+ $plrole,$extent,
+ ''.&Apache::loncommon::plainname($uname,$udom).'',
+ $result).' ');
}
}
$r->print(''."\n");
}
+sub dates_feedback {
+ my ($start,$end,$now) = @_;
+ my $dates;
+ if ($start < $now) {
+ if ($end == 0) {
+ $dates .= &mt('role(s) active now; no end date');
+ } elsif ($end > $now) {
+ $dates = &mt('role(s) active now; ends [_1].',&Apache::lonlocal::locallocaltime($end));
+ } else {
+ $dates = &mt('role(s) expired: [_1].',&Apache::lonlocal::locallocaltime($end));
+ }
+ } else {
+ if ($end == 0 || $end > $now) {
+ $dates = &mt('future role(s); starts: [_1].',&Apache::lonlocal::locallocaltime($start));
+ } else {
+ $dates = &mt('role(s) expired: [_1].',&Apache::lonlocal::locallocaltime($end));
+ }
+ }
+ return $dates;
+}
+
sub classlist_drop {
my ($scope,$uname,$udom,$now) = @_;
my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
@@ -4813,7 +5051,7 @@ sub setsections_javascript {
accr => 'A course coordinator role will be added with access to all sections.',
acor => 'A coordinator role will be added with access to all sections',
inea => 'In each course, each user may only have one student role at a time.',
- inec => 'In each community, each user may only have one member role at a time.',
+ inco => 'In each community, each user may only have one member role at a time.',
youh => 'You had selected ',
secs => 'sections.',
plmo => 'Please modify your selections so they include no more than one section.',
@@ -4821,16 +5059,21 @@ sub setsections_javascript {
plch => 'Please choose a different section name.',
mnot => 'may not be used as a section name, as it is the name of a course group.',
secn => 'Section names and group names must be distinct. Please choose a different section name.',
+ nonw => 'Section names may only contain letters or numbers.',
);
$setsection_js .= <<"ENDSECCODE";
function setSections(formname,crstype) {
var re1 = /^currsec_/;
+ var re2 =/\\W/;
+ var trimleading = /^\\s+/;
+ var trimtrailing = /\\s+\$/;
var groups = new Array($groupslist);
for (var i=0;i 0) {
- if (formname.elements[i+1].value != "" && formname.elements[i+1].value != null) {
- sections = sections + "," + formname.elements[i+1].value;
- }
- }
- else {
- sections = formname.elements[i+1].value;
- }
- var newsecs = formname.elements[i+1].value;
- var numsplit;
+ var newsecs = formname.elements[num+1].value;
+ var validsecs = new Array();
+ var validsecstr = '';
+ var badsecs = new Array();
if (newsecs != null && newsecs != "") {
- numsplit = newsecs.split(/,/g);
- numsec = numsec + numsplit.length;
+ var numsplit;
+ if (newsecs.indexOf(',') == -1) {
+ numsplit = new Array(newsecs);
+ } else {
+ numsplit = newsecs.split(/,/g);
+ }
+ for (var m=0; m 0) {
+ alert("$alerts{'nonw'}\\n$alerts{'plch'}");
+ return;
+ }
+ numsec = numsec + validsecs.length;
}
-
if ((role == 'st') && (numsec > 1)) {
if (crstype == 'Community') {
alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}");
@@ -4881,25 +5146,36 @@ function setSections(formname,crstype) {
alert("$alerts{'inco'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}");
}
return;
- }
- else {
- if (numsplit != null) {
- for (var j=0; j 0) {
- my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
- if (keys(%rule_check) > 0) {
- $usertype = 'unofficial';
- foreach my $item (keys(%rule_check)) {
- if ($rule_check{$item}) {
- $usertype = 'official';
- last;
+ if ((ref($got_rules) eq 'HASH') && (ref($curr_rules) eq 'HASH')) {
+ if (!$got_rules->{$dom}) {
+ my %domconfig = &Apache::lonnet::get_dom('configuration',
+ ['usercreation'],$dom);
+ if (ref($domconfig{'usercreation'}) eq 'HASH') {
+ foreach my $item ('username','id') {
+ if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {
+ $curr_rules->{$dom}{$item} =
+ $domconfig{'usercreation'}{$item.'_rule'};
+ }
+ }
+ }
+ $got_rules->{$dom} = 1;
+ }
+ if (ref($rules) eq 'HASH') {
+ my @user_rules;
+ if (ref($curr_rules->{$dom}{'username'}) eq 'ARRAY') {
+ foreach my $rule (keys(%{$rules})) {
+ if (grep(/^\Q$rule\E/,@{$curr_rules->{$dom}{'username'}})) {
+ push(@user_rules,$rule);
+ }
+ }
+ }
+ if (@user_rules > 0) {
+ my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
+ if (keys(%rule_check) > 0) {
+ $usertype = 'unofficial';
+ foreach my $item (keys(%rule_check)) {
+ if ($rule_check{$item}) {
+ $usertype = 'official';
+ last;
+ }
}
}
}
@@ -5355,7 +5653,7 @@ sub sectioncheck_alerts {
my %alerts = &Apache::lonlocal::texthash(
curd => 'You must select a course or community in the current domain',
inea => 'In each course, each user may only have one student role at a time',
- inco => 'In each community, each user may only have one member role at a time',
+ inco => 'In each community, each user may only have one member role at a time',
youh => 'You had selected',
sect => 'sections',
plsm => 'Please modify your selections so they include no more than one section',