File:
[LON-CAPA] /
loncom /
interface /
lonuserutils.pm
Revision
1.217:
download - view:
text,
annotated -
select for diffs
Mon Oct 2 21:01:21 2023 UTC (10 months, 2 weeks ago) by
raeburn
Branches:
MAIN
CVS tags:
HEAD
- Bug 6979.
"View As" form in Functions menu includes domain dropdown list if users in
course are from more than one domain. Use course's environment.db to store
comma separated list of unique domains to which course users belong.
1: # The LearningOnline Network with CAPA
2: # Utility functions for managing LON-CAPA user accounts
3: #
4: # $Id: lonuserutils.pm,v 1.217 2023/10/02 21:01:21 raeburn Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: #
28: ###############################################################
29: ###############################################################
30:
31: package Apache::lonuserutils;
32:
33: =pod
34:
35: =head1 NAME
36:
37: Apache::lonuserutils.pm
38:
39: =head1 SYNOPSIS
40:
41: Utilities for management of users and custom roles
42:
43: Provides subroutines called by loncreateuser.pm
44:
45: =head1 OVERVIEW
46:
47: =cut
48:
49: use strict;
50: use Apache::lonnet;
51: use Apache::loncommon();
52: use Apache::lonhtmlcommon;
53: use Apache::loncoursequeueadmin;
54: use Apache::lonlocal;
55: use Apache::longroup;
56: use HTML::Entities;
57: use LONCAPA qw(:DEFAULT :match);
58:
59: ###############################################################
60: ###############################################################
61: # Drop student from all sections of a course, except optional $csec
62: sub modifystudent {
63: my ($udom,$unam,$courseid,$csec,$desiredhost,$context)=@_;
64: # if $csec is undefined, drop the student from all the courses matching
65: # this one. If $csec is defined, drop them from all other sections of
66: # this course and add them to section $csec
67: my ($cnum,$cdom) = &get_course_identity($courseid);
68: my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
69: my ($tmp) = keys(%roles);
70: # Bail out if we were unable to get the students roles
71: return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
72: # Go through the roles looking for enrollment in this course
73: my $result = '';
74: foreach my $course (keys(%roles)) {
75: if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
76: # We are in this course
77: my $section=$1;
78: $section='' if ($course eq "/$cdom/$cnum".'_st');
79: if (defined($csec) && $section eq $csec) {
80: $result .= 'ok:';
81: } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
82: my (undef,$end,$start)=split(/\_/,$roles{$course});
83: my $now=time;
84: # if this is an active role
85: if (!($start && ($now<$start)) || !($end && ($now>$end))) {
86: my $reply=&Apache::lonnet::modifystudent
87: # dom name id mode pass f m l g
88: ($udom,$unam,'', '', '',undef,undef,undef,undef,
89: $section,time,undef,undef,$desiredhost,'','manual',
90: '',$courseid,'',$context);
91: $result .= $reply.':';
92: }
93: }
94: }
95: }
96: if ($result eq '') {
97: $result = &mt('Unable to find section for this student');
98: } else {
99: $result =~ s/(ok:)+/ok/g;
100: }
101: return $result;
102: }
103:
104: sub modifyuserrole {
105: my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
106: $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
107: $end,$start,$checkid,$inststatus) = @_;
108: my ($scope,$userresult,$authresult,$roleresult,$idresult);
109: if ($setting eq 'course' || $context eq 'course') {
110: $scope = '/'.$cid;
111: $scope =~ s/\_/\//g;
112: if (($role ne 'cc') && ($role ne 'co') && ($sec ne '')) {
113: $scope .='/'.$sec;
114: }
115: } elsif ($context eq 'domain') {
116: $scope = '/'.$env{'request.role.domain'}.'/';
117: } elsif ($context eq 'author') {
118: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
119: }
120: if ($context eq 'domain') {
121: my $uhome = &Apache::lonnet::homeserver($uname,$udom);
122: if ($uhome ne 'no_host') {
123: if (($changeauth eq 'Yes') && (&Apache::lonnet::allowed('mau',$udom))) {
124: if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
125: ($umode eq 'localauth')) {
126: $authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
127: }
128: }
129: if (($forceid) && (&Apache::lonnet::allowed('mau',$udom)) &&
130: ($env{'form.recurseid'}) && ($checkid)) {
131: my %userupdate = (
132: lastname => $last,
133: middlename => $middle,
134: firstname => $first,
135: generation => $gene,
136: id => $uid,
137: );
138: $idresult = &propagate_id_change($uname,$udom,\%userupdate);
139: }
140: }
141: }
142: $userresult =
143: &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
144: $middle,$last,$gene,$forceid,$desiredhome,
145: $email,$inststatus);
146: if ($userresult eq 'ok') {
147: if ($role ne '') {
148: $role =~ s/_/\//g;
149: $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
150: $role,$end,$start,'',
151: '',$context);
152: }
153: }
154: return ($userresult,$authresult,$roleresult,$idresult);
155: }
156:
157: sub role_approval {
158: my ($dom,$context,$process_by,$notifydc) = @_;
159: if (ref($process_by) eq 'HASH') {
160: my %domconfig = &Apache::lonnet::get_dom('configuration',['privacy'],$dom);
161: if (ref($domconfig{'privacy'}) eq 'HASH') {
162: if (ref($notifydc) eq 'ARRAY') {
163: if ($domconfig{'privacy'}{'notify'} ne '') {
164: @{$notifydc} = split(/,/,$domconfig{'privacy'}{'notify'});
165: }
166: }
167: if (ref($domconfig{'privacy'}{'approval'}) eq 'HASH') {
168: my %approvalconf = %{$domconfig{'privacy'}{'approval'}};
169: foreach my $key ('instdom','extdom') {
170: if (ref($approvalconf{$key}) eq 'HASH') {
171: if (keys(%{$approvalconf{$key}})) {
172: $process_by->{$key} = $approvalconf{$key}{$context};
173: }
174: }
175: }
176: }
177: }
178: }
179: return;
180: }
181:
182: sub get_instdoms {
183: my ($udom,$instdoms) = @_;
184: return unless (ref($instdoms) eq 'ARRAY');
185: my @intdoms;
186: my %iphost = &Apache::lonnet::get_iphost();
187: my $primary_id = &Apache::lonnet::domain($udom,'primary');
188: my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
189: if (ref($iphost{$primary_ip}) eq 'ARRAY') {
190: foreach my $id (@{$iphost{$primary_ip}}) {
191: my $intdom = &Apache::lonnet::internet_dom($id);
192: unless(grep(/^\Q$intdom\E$/,@intdoms)) {
193: push(@intdoms,$intdom);
194: }
195: }
196: }
197: foreach my $ip (keys(%iphost)) {
198: if (ref($iphost{$ip}) eq 'ARRAY') {
199: foreach my $id (@{$iphost{$ip}}) {
200: my $location = &Apache::lonnet::internet_dom($id);
201: if ($location) {
202: if (grep(/^\Q$location\E$/,@intdoms)) {
203: my $dom = &Apache::lonnet::host_domain($id);
204: unless (grep(/^\Q$dom\E/,@{$instdoms})) {
205: push(@{$instdoms},$dom);
206: }
207: }
208: }
209: }
210: }
211: }
212: return;
213: }
214:
215: sub restricted_dom {
216: my ($context,$key,$udom,$uname,$role,$start,$end,$cdom,$cnum,$csec,$credits,
217: $process_by,$instdoms,$got_role_approvals,$got_instdoms,$reject,$pending,
218: $notifydc,$status,$unauthorized,$currqueued) = @_;
219: return if ($udom eq $cdom);
220: return unless ((ref($process_by) eq 'HASH') && (ref($instdoms) eq 'HASH') &&
221: (ref($got_role_approvals) eq 'HASH') && (ref($got_instdoms) eq 'HASH') &&
222: (ref($reject) eq 'HASH') && (ref($pending) eq 'HASH') &&
223: (ref($notifydc) eq 'HASH') && (ref($status) eq 'HASH') &&
224: (ref($unauthorized) eq 'HASH') && (ref($currqueued) eq 'HASH'));
225: my (%approval,@notify,$gotdata,$skip);
226: if (ref($got_role_approvals->{$context}) eq 'HASH') {
227: if ($got_role_approvals->{$context}{$udom}) {
228: $gotdata = 1;
229: if (ref($process_by->{$context}{$udom}) eq 'HASH') {
230: %approval = %{$process_by->{$context}{$udom}};
231: }
232: }
233: }
234: unless ($gotdata) {
235: &role_approval($udom,$context,\%approval,\@notify);
236: $process_by->{$context} = {
237: $udom => \%approval,
238: };
239: $got_role_approvals->{$context} = {
240: $udom => 1,
241: };
242: $notifydc->{$udom} = \@notify;
243: }
244: if (ref($process_by->{$context}) eq 'HASH') {
245: if (ref($process_by->{$context}{$udom}) eq 'HASH') {
246: my @inst;
247: if ($got_instdoms->{$udom}) {
248: if (ref($instdoms->{$udom}) eq 'ARRAY') {
249: @inst = @{$instdoms->{$udom}};
250: }
251: } else {
252: &get_instdoms(\@inst);
253: $instdoms->{$udom} = \@inst;
254: $got_instdoms->{$udom} = 1;
255: }
256: if (grep(/^\Q$cdom\E$/,@inst)) {
257: if (exists($approval{'instdom'})) {
258: my $rule = $approval{'instdom'};
259: if (($rule eq 'none') || ($rule eq 'user') || ($rule eq 'domain')) {
260: my ($id,$currstatus,$curradj) = &get_othdomreq_status($key,$uname,$udom,$role,$cdom,$cnum,$csec);
261: if (($currstatus ne '') && ($curradj eq $rule)) {
262: $status->{$key}->{$uname.':'.$udom} = $currstatus;
263: }
264: if ($rule eq 'none') {
265: $reject->{$key}->{$uname.':'.$udom} = {
266: cdom => $cdom,
267: cnum => $cnum,
268: csec => $csec,
269: udom => $udom,
270: uname => $uname,
271: role => $role,
272: };
273: $skip = 1;
274: } elsif (($rule eq 'user') || ($rule eq 'domain')) {
275: if ($curradj eq $rule) {
276: unless ($currstatus eq 'approved') {
277: if ($currstatus eq 'rejected') {
278: $unauthorized->{$key}->{$uname.':'.$udom} = {
279: cdom => $cdom,
280: cnum => $cnum,
281: csec => $csec,
282: udom => $udom,
283: uname => $uname,
284: role => $role,
285: };
286: } elsif ($currstatus eq 'pending') {
287: $currqueued->{$key}->{$uname.':'.$udom} = {
288: cdom => $cdom,
289: cnum => $cnum,
290: csec => $csec,
291: udom => $udom,
292: uname => $uname,
293: role => $role,
294: adj => $rule,
295: };
296: }
297: $skip = 1;
298: }
299: } else {
300: $pending->{$key}->{$uname.':'.$udom} = {
301: cdom => $cdom,
302: cnum => $cnum,
303: csec => $csec,
304: udom => $udom,
305: uname => $uname,
306: role => $role,
307: start => $start,
308: end => $end,
309: adj => $rule,
310: };
311: if (($role eq 'st') && ($credits ne '')) {
312: $pending->{$key}->{$uname.':'.$udom}->{'credits'} = $credits;
313: }
314: $skip = 1;
315: }
316: }
317: }
318: }
319: } elsif (exists($approval{'extdom'})) {
320: my $rule = $approval{'extdom'};
321: if (($rule eq 'none') || ($rule eq 'user') || ($rule eq 'domain')) {
322: my ($id,$currstatus,$curradj) = &get_othdomreq_status($key,$uname,$udom,$role,$cdom,$cnum,$csec);
323: if (($currstatus ne '') && ($curradj eq $rule)) {
324: $status->{$key}->{$uname.':'.$udom} = $currstatus;
325: }
326: if ($rule eq 'none') {
327: $reject->{$key}->{$uname.':'.$udom} = {
328: cdom => $cdom,
329: cnum => $cnum,
330: csec => $csec,
331: udom => $udom,
332: uname => $uname,
333: role => $role,
334: };
335: $skip = 1;
336: } elsif (($rule eq 'user') || ($rule eq 'domain')) {
337: if ($curradj eq $rule) {
338: unless ($currstatus eq 'approved') {
339: if ($currstatus eq 'rejected') {
340: $unauthorized->{$key}->{$uname.':'.$udom} = {
341: cdom => $cdom,
342: cnum => $cnum,
343: csec => $csec,
344: udom => $udom,
345: uname => $uname,
346: role => $role,
347: };
348: } elsif ($currstatus eq 'pending') {
349: $currqueued->{$key}->{$uname.':'.$udom} = {
350: cdom => $cdom,
351: cnum => $cnum,
352: csec => $csec,
353: udom => $udom,
354: uname => $uname,
355: role => $role,
356: adj => $rule,
357: };
358: }
359: $skip = 1;
360: }
361: } else {
362: $pending->{$key}->{$uname.':'.$udom} = {
363: cdom => $cdom,
364: cnum => $cnum,
365: csec => $csec,
366: udom => $udom,
367: uname => $uname,
368: role => $role,
369: start => $start,
370: end => $end,
371: adj => $rule,
372: };
373: if (($role eq 'st') && ($credits ne '')) {
374: $pending->{$key}->{$uname.':'.$udom}->{'credits'} = $credits;
375: }
376: $skip = 1;
377: }
378: }
379: }
380: }
381: }
382: }
383: return $skip;
384: }
385:
386: sub get_othdomreq_status {
387: my ($key,$uname,$udom,$role,$cdom,$cnum,$csec) = @_;
388: my $id = $uname.':'.$udom.':'.$role;
389: my ($dbnum,$currstatus,$curradj);
390: if (($role eq 'ca') || ($role eq 'aa')) {
391: $dbnum = $cnum;
392: } elsif ($key eq $cdom.'_'.$role) {
393: $dbnum = &Apache::lonnet::get_domainconfiguser($cdom);
394: } else {
395: $id .= ':'.$csec;
396: $dbnum = $cnum;
397: }
398: my $statusid = 'status&'.$id;
399: my %curr = &Apache::lonnet::get('nohist_othdomqueued',[$id,$statusid],$cdom,$dbnum);
400: if (ref($curr{$id}) eq 'HASH') {
401: $curradj = $curr{$id}{'adj'};
402: }
403: $currstatus = $curr{$statusid};
404: return ($id,$currstatus,$curradj);
405: }
406:
407: sub print_roles_rejected {
408: my ($context,$reject,$unauthorized) = @_;
409: return unless ((ref($reject) eq 'HASH') || (ref($unauthorized) eq 'HASH'));
410: my $output;
411: if (keys(%{$reject}) > 0) {
412: $output = '<p class="LC_warning">'.
413: &mt("The following roles could not be assigned because the user is from another domain, and that domain's policies disallow it").'<ul>';
414: foreach my $key (sort(keys(%{$reject}))) {
415: if (ref($reject->{$key}) eq 'HASH') {
416: foreach my $user (sort(keys(%{$reject->{$key}}))) {
417: if (ref($reject->{$key}->{$user}) eq 'HASH') {
418: my ($crstype,$role,$cdom,$cnum,$csec,$title,$plainrole);
419: $role = $reject->{$key}->{$user}{'role'};
420: $cdom = $reject->{$key}->{$user}{'cdom'};
421: $cnum = $reject->{$key}->{$user}{'cnum'};
422: $csec = $reject->{$key}->{$user}{'csec'};
423: if (($context eq 'domain') && ($cnum ne '')) {
424: if (($role eq 'ca') || ($role eq 'aa')) {
425: $title = &Apache::loncommon::plainname($cnum,$cdom);
426: } else {
427: if (&Apache::lonnet::is_course($cdom,$cnum)) {
428: my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
429: $crstype = $coursedata{'type'};
430: $title = $coursedata{'description'};
431: }
432: }
433: } elsif ($context eq 'course') {
434: $crstype = &Apache::loncommon::course_type();
435: }
436: my $plainrole = &Apache::lonnet::plaintext($role,$crstype);
437: $output .= '<li>'.&mt('User: [_1]',$reject->{$key}->{$user}{'uname'}).' | '.
438: &mt('Domain: [_1]',$reject->{$key}->{$user}{'udom'}).' | '.
439: &mt('Role: [_1]',$plainrole);
440: if ($crstype) {
441: if ($csec ne'') {
442: $output .= ' | '.&mt('Section: [_1]',$csec);
443: }
444: } elsif (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa'))) {
445: $output .= ' | '.&mt('Authoring Space belonging to: [_1]',$title);
446:
447: }
448: if (($context eq 'domain') && ($crstype)) {
449: $output .= ' | '.&mt("$crstype: [_1]",$title);
450: }
451: $output .= '</li>';
452: }
453: }
454: }
455: }
456: $output .= '</ul></p>';
457: }
458: if (keys(%{$unauthorized}) > 0) {
459: $output = '<p class="LC_warning">'.
460: &mt("The following roles could not be assigned because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain, and approval has been withheld.").'<ul>';
461: foreach my $key (sort(keys(%{$unauthorized}))) {
462: if (ref($unauthorized->{$key}) eq 'HASH') {
463: foreach my $user (sort(keys(%{$unauthorized->{$key}}))) {
464: if (ref($unauthorized->{$key}->{$user}) eq 'HASH') {
465: my ($crstype,$role,$cdom,$cnum,$csec,$title,$plainrole);
466: $role = $unauthorized->{$key}->{$user}{'role'};
467: $cdom = $unauthorized->{$key}->{$user}{'cdom'};
468: $cnum = $unauthorized->{$key}->{$user}{'cnum'};
469: $csec = $unauthorized->{$key}->{$user}{'csec'};
470: if (($context eq 'domain') && ($cnum ne '')) {
471: if (($role eq 'ca') || ($role eq 'aa')) {
472: $title = &mt('Authoring Space belonging to: [_1]',
473: &Apache::loncommon::plainname($cnum,$cdom));
474: } else {
475: if (&Apache::lonnet::is_course($cdom,$cnum)) {
476: my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
477: $crstype = $coursedata{'type'};
478: $title = &mt("$crstype: [_1]",$coursedata{'description'});
479: }
480: }
481: } elsif ($context eq 'course') {
482: $crstype = &Apache::loncommon::course_type();
483: }
484: $plainrole = &Apache::lonnet::plaintext($role,$crstype);
485: $output .= '<li>'.&mt('User: [_1]',$unauthorized->{$key}->{$user}{'uname'}).' | '.
486: &mt('Domain: [_1]',$unauthorized->{$key}->{$user}{'udom'}).' | '.
487: &mt('Role: [_1]',$plainrole);
488: if ($crstype) {
489: if ($csec ne'') {
490: $output .= ' | '.&mt('Section: [_1]',$csec);
491: }
492: }
493: if ($title ne '') {
494: $output .= ' | '.$title;
495: }
496: $output .= '</li>';
497: }
498: }
499: }
500: }
501: $output .= '</ul></p>';
502: }
503: return $output;
504: }
505:
506: sub print_roles_queued {
507: my ($context,$pending,$notifydc,$currqueued) = @_;
508: return unless ((ref($pending) eq 'HASH') && (ref($notifydc) eq 'HASH') &&
509: (ref($currqueued) eq 'HASH'));
510: my $output;
511: if (keys(%{$pending}) > 0) {
512: my $now = time;
513: $output = '<p class="LC_warning">'.
514: &mt("The following role assignments have been queued because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain").'<ul>';
515: my (%todom,%touser,%crsqueue,%caqueue,%domqueue);
516: my $requester = $env{'user.name'}.':'.$env{'user.domain'};
517: foreach my $key (sort(keys(%{$pending}))) {
518: if (ref($pending->{$key}) eq 'HASH') {
519: foreach my $user (sort(keys(%{$pending->{$key}}))) {
520: if (ref($pending->{$key}->{$user}) eq 'HASH') {
521: my $role = $pending->{$key}->{$user}{'role'};
522: my $uname = $pending->{$key}->{$user}{'uname'};
523: my $udom = $pending->{$key}->{$user}{'udom'};
524: my $csec = $pending->{$key}->{$user}{'csec'};
525: my $cdom = $pending->{$key}->{$user}{'cdom'};
526: my $cnum = $pending->{$key}->{$user}{'cnum'};
527: my $adj = $pending->{$key}->{$user}{'adj'};
528: my $start = $pending->{$key}->{$user}{'start'};
529: my $end = $pending->{$key}->{$user}{'end'};
530: my $credits = $pending->{$key}->{$user}{'credits'};
531: my $now = time;
532: my ($crstype,$title,$plainrole,$extent,$id,$status);
533: if ($context eq 'course') {
534: $crstype = &Apache::loncommon::course_type();
535: $title = $env{'course.'.$env{'request.course.id'}.'.description'};
536: } elsif ($context eq 'domain') {
537: if (&Apache::lonnet::is_course($cdom,$cnum)) {
538: my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
539: $crstype = $coursedata{'type'};
540: $title = $coursedata{'description'};
541: } elsif (($role eq 'ca') || ($role eq 'aa')) {
542: $title = &Apache::loncommon::plainname($cnum,$cdom);
543: }
544: }
545: $plainrole = &Apache::lonnet::plaintext($role,$crstype);
546: $extent = "/$cdom/$cnum";
547: $id = $uname.':'.$udom.':'.$role;
548: if (($context eq 'course') || ($crstype)) {
549: $id .= ':'.$csec;
550: }
551: $output .= '<li>'.&mt('User: [_1]',$uname).' | '.
552: &mt('Domain: [_1]',$udom).' | '.
553: &mt('Role: [_1]',$plainrole);
554: if ($crstype) {
555: if ($csec ne'') {
556: $output .= ' | '.&mt('Section: [_1]',$csec);
557: }
558: } elsif (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa'))) {
559: $output .= ' | '.&mt('Authoring Space belonging to: [_1]',$title);
560: }
561: if (($context eq 'domain') && ($crstype)) {
562: $output .= ' | '.&mt("$crstype: [_1]",$title);
563: }
564: if (($crstype) && ($csec ne '')) {
565: $extent .= "/$csec";
566: }
567: if ($adj eq 'user') {
568: $output .= '<br />'.&mt('Message sent to user for approval');
569: $touser{$uname.':'.$udom}{'pending:'.$extent.':'.$role} = {
570: timestamp => $now,
571: requester => $requester,
572: start => $start,
573: end => $end,
574: credits => $credits,
575: context => $context,
576: };
577: } elsif ($adj eq 'domain') {
578: $output .= '<br />'.&mt("Message sent to user's domain coordinator for approval");
579: $todom{$udom}{'pending:'.$uname.':'.$extent.':'.$role} = {
580: timestamp => $now,
581: requester => $requester,
582: start => $start,
583: end => $end,
584: credits => $credits,
585: context => $context,
586: };
587: }
588: $output .= '</li>';
589: if (($context eq 'course') || ($crstype)) {
590: $crsqueue{$cdom.'_'.$cnum}{$id} = {
591: timestamp => $now,
592: requester => $requester,
593: adj => $adj,
594: };
595: $crsqueue{$cdom.'_'.$cnum}{'status&'.$id} = 'pending';
596: } elsif (($context eq 'author') ||
597: (($context eq 'domain') && (($role eq 'ca') || ($role eq 'aa')))) {
598: $caqueue{$cnum.':'.$cdom}{$id} = {
599: timestamp => $now,
600: requester => $requester,
601: adj => $adj,
602: };
603: $caqueue{$cnum.':'.$cdom}{'status&'.$id} = 'pending';
604: } elsif ($context eq 'domain') {
605: $domqueue{$id} = {
606: timestamp => $now,
607: requester => $requester,
608: adj => $adj,
609: };
610: $domqueue{'status&'.$id} = 'pending';
611: }
612: }
613: }
614: }
615: }
616: $output .= '</ul></p>';
617: if (keys(%touser)) {
618: foreach my $key (keys(%touser)) {
619: my ($uname,$udom) = split(/:/,$key);
620: if (&Apache::lonnet::put('nohist_queuedrolereqs',$touser{$key},$udom,$uname) eq 'ok') {
621: my $owndomdesc = &Apache::lonnet::domain($udom);
622: &Apache::loncoursequeueadmin::send_selfserve_notification($uname.':'.$udom,
623: '','',$owndomdesc,$now,'othdomroleuser',$requester);
624: }
625: }
626: }
627: if (keys(%todom)) {
628: foreach my $dom (keys(%todom)) {
629: if (ref($todom{$dom}) eq 'HASH') {
630: my $confname = &Apache::lonnet::get_domainconfiguser($dom);
631: if (&Apache::lonnet::put('nohist_queuedrolereqs',$todom{$dom},$dom,$confname) eq 'ok') {
632: if (ref($notifydc->{$dom}) eq 'ARRAY') {
633: if (@{$notifydc->{$dom}} > 0) {
634: my $notifylist = join(',',@{$notifydc->{$dom}});
635: &Apache::loncoursequeueadmin::send_selfserve_notification($notifylist,
636: '','','',$now,'othdomroledc',$requester);
637: }
638: }
639: }
640: }
641: }
642: }
643: if (keys(%crsqueue)) {
644: foreach my $key (keys(%crsqueue)) {
645: my ($cdom,$cnum) = split(/_/,$key);
646: if (ref($crsqueue{$key}) eq 'HASH') {
647: &Apache::lonnet::put('nohist_othdomqueued',$crsqueue{$key},$cdom,$cnum);
648: }
649: }
650: }
651: if (keys(%caqueue)) {
652: foreach my $key (keys(%caqueue)) {
653: my ($auname,$audom) = split(/:/,$key);
654: if (ref($caqueue{$key}) eq 'HASH') {
655: &Apache::lonnet::put('nohist_othdomqueued',$caqueue{$key},$audom,$auname);
656: }
657: }
658: }
659: if (keys(%domqueue)) {
660: my $confname = &Apache::lonnet::get_domainconfiguser($env{'request.role.domain'});
661: &Apache::lonnet::put('nohist_othdomqueued',\%domqueue,$env{'request.role.domain'},$confname);
662: }
663: }
664: if (keys(%{$currqueued}) > 0) {
665: $output = '<p class="LC_warning">'.
666: &mt("The following role assignments were already queued because the user is from another domain, and that domain's policies require approval by the user themselves or by a domain coordinator in that domain").'<ul>';
667: my $requester = $env{'user.name'}.':'.$env{'user.domain'};
668: foreach my $key (sort(keys(%{$currqueued}))) {
669: if (ref($currqueued->{$key}) eq 'HASH') {
670: foreach my $user (sort(keys(%{$currqueued->{$key}}))) {
671: if (ref($currqueued->{$key}->{$user}) eq 'HASH') {
672: my $role = $currqueued->{$key}->{$user}{'role'};
673: my $csec = $currqueued->{$key}->{$user}{'csec'};
674: my $cdom = $currqueued->{$key}->{$user}{'cdom'};
675: my $cnum = $currqueued->{$key}->{$user}{'cnum'};
676: my ($crstype,$title,$plainrole);
677: if ($context eq 'course') {
678: $crstype = &Apache::loncommon::course_type();
679: } elsif (($context eq 'domain') && ($cnum ne '')) {
680: if (($role eq 'ca') || ($role eq 'aa')) {
681: $title = &mt('Authoring Space belonging to: [_1]',
682: &Apache::loncommon::plainname($cnum,$cdom));
683: } elsif (&Apache::lonnet::is_course($cdom,$cnum)) {
684: my %coursedata = &Apache::lonnet::coursedescription($cdom.'_'.$cnum);
685: $crstype = $coursedata{'type'};
686: $title = &mt("$crstype: [_1]",$coursedata{'description'});
687: }
688: }
689: $plainrole = &Apache::lonnet::plaintext($role,$crstype);
690: $output .= '<li>'.&mt('User: [_1]',$currqueued->{$key}->{$user}{'uname'}).' | '.
691: &mt('Domain: [_1]',$currqueued->{$key}->{$user}{'udom'}).' | '.
692: &mt('Role: [_1]',$plainrole);
693: if ($title ne '') {
694: $output .= ' | '.$title;
695: }
696: if ($crstype) {
697: if ($csec ne '') {
698: $output .= ' | '.&mt('Section: [_1]',$csec);
699: }
700: }
701: $output .= '</li>';
702: }
703: }
704: }
705: }
706: $output .= '</ul></p>';
707: }
708: return $output;
709: }
710:
711: sub propagate_id_change {
712: my ($uname,$udom,$user) = @_;
713: my (@types,@roles);
714: @types = ('active','future');
715: @roles = ('st');
716: my $idresult;
717: my %roleshash = &Apache::lonnet::get_my_roles($uname,
718: $udom,'userroles',\@types,\@roles);
719: my %args = (
720: one_time => 1,
721: );
722: foreach my $item (keys(%roleshash)) {
723: my ($cnum,$cdom,$role) = split(/:/,$item,-1);
724: my ($start,$end) = split(/:/,$roleshash{$item});
725: if (&Apache::lonnet::is_course($cdom,$cnum)) {
726: my $result = &update_classlist($cdom,$cnum,$udom,$uname,$user);
727: my %coursehash =
728: &Apache::lonnet::coursedescription($cdom.'_'.$cnum,\%args);
729: my $cdesc = $coursehash{'description'};
730: if ($cdesc eq '') {
731: $cdesc = $cdom.'_'.$cnum;
732: }
733: if ($result eq 'ok') {
734: $idresult .= &mt('Classlist update for "[_1]" in "[_2]".',$uname.':'.$udom,$cdesc).'<br />'."\n";
735: } else {
736: $idresult .= &mt('Error: "[_1]" during classlist update for "[_2]" in "[_3]".',$result,$uname.':'.$udom,$cdesc).'<br />'."\n";
737: }
738: }
739: }
740: return $idresult;
741: }
742:
743: sub update_classlist {
744: my ($cdom,$cnum,$udom,$uname,$user,$newend) = @_;
745: my ($uid,$classlistentry);
746: my $fullname =
747: &Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'},
748: $user->{'lastname'},$user->{'generation'},
749: 'lastname');
750: my %classhash = &Apache::lonnet::get('classlist',[$uname.':'.$udom],
751: $cdom,$cnum);
752: my @classinfo = split(/:/,$classhash{$uname.':'.$udom});
753: my $ididx=&Apache::loncoursedata::CL_ID() - 2;
754: my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2;
755: my $endidx = &Apache::loncoursedata::CL_END() - 2;
756: my $startidx = &Apache::loncoursedata::CL_START() - 2;
757: for (my $i=0; $i<@classinfo; $i++) {
758: if ($i == $endidx) {
759: if ($newend ne '') {
760: $classlistentry .= $newend.':';
761: } else {
762: $classlistentry .= $classinfo[$i].':';
763: }
764: } elsif ($i == $startidx) {
765: if ($newend ne '') {
766: if ($classinfo[$i] > $newend) {
767: $classlistentry .= $newend.':';
768: } else {
769: $classlistentry .= $classinfo[$i].':';
770: }
771: } else {
772: $classlistentry .= $classinfo[$i].':';
773: }
774: } elsif ($i == $ididx) {
775: if (defined($user->{'id'})) {
776: $classlistentry .= $user->{'id'}.':';
777: } else {
778: $classlistentry .= $classinfo[$i].':';
779: }
780: } elsif ($i == $nameidx) {
781: if (defined($user->{'lastname'})) {
782: $classlistentry .= $fullname.':';
783: } else {
784: $classlistentry .= $classinfo[$i].':';
785: }
786: } else {
787: $classlistentry .= $classinfo[$i].':';
788: }
789: }
790: $classlistentry =~ s/:$//;
791: my $reply=&Apache::lonnet::cput('classlist',
792: {"$uname:$udom" => $classlistentry},
793: $cdom,$cnum);
794: if (($reply eq 'ok') || ($reply eq 'delayed')) {
795: return 'ok';
796: } else {
797: return 'error: '.$reply;
798: }
799: }
800:
801:
802: ###############################################################
803: ###############################################################
804: # build a role type and role selection form
805: sub domain_roles_select {
806: # Set up the role type and role selection boxes when in
807: # domain context
808: #
809: # Role types
810: my @roletypes = ('domain','author','course','community');
811: my %lt = &role_type_names();
812: my $onchangefirst = "updateCols('showrole')";
813: my $onchangesecond = "updateCols('showrole')";
814: #
815: # build up the menu information to be passed to
816: # &Apache::loncommon::linked_select_forms
817: my %select_menus;
818: if ($env{'form.roletype'} eq '') {
819: $env{'form.roletype'} = 'domain';
820: }
821: foreach my $roletype (@roletypes) {
822: # set up the text for this domain
823: $select_menus{$roletype}->{'text'}= $lt{$roletype};
824: my $crstype;
825: if ($roletype eq 'community') {
826: $crstype = 'Community';
827: }
828: # we want a choice of 'default' as the default in the second menu
829: if ($env{'form.roletype'} ne '') {
830: $select_menus{$roletype}->{'default'} = $env{'form.showrole'};
831: } else {
832: $select_menus{$roletype}->{'default'} = 'Any';
833: }
834: # Now build up the other items in the second menu
835: my @roles;
836: if ($roletype eq 'domain') {
837: @roles = &domain_roles();
838: } elsif ($roletype eq 'author') {
839: @roles = &construction_space_roles();
840: } else {
841: my $custom = 1;
842: @roles = &course_roles('domain',undef,$custom,$roletype);
843: }
844: my $order = ['Any',@roles];
845: $select_menus{$roletype}->{'order'} = $order;
846: foreach my $role (@roles) {
847: if ($role eq 'cr') {
848: $select_menus{$roletype}->{'select2'}->{$role} =
849: &mt('Custom role');
850: } else {
851: $select_menus{$roletype}->{'select2'}->{$role} =
852: &Apache::lonnet::plaintext($role,$crstype);
853: }
854: }
855: $select_menus{$roletype}->{'select2'}->{'Any'} = &mt('Any');
856: }
857: my $result = &Apache::loncommon::linked_select_forms
858: ('studentform',(' 'x3).&mt('Role: '),$env{'form.roletype'},
859: 'roletype','showrole',\%select_menus,
860: ['domain','author','course','community'],$onchangefirst,
861: $onchangesecond);
862: return $result;
863: }
864:
865: ###############################################################
866: ###############################################################
867: sub hidden_input {
868: my ($name,$value) = @_;
869: return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
870: }
871:
872: sub print_upload_manager_header {
873: my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission,$crstype,
874: $can_assign)=@_;
875: my $javascript;
876: #
877: if (! exists($env{'form.upfile_associate'})) {
878: $env{'form.upfile_associate'} = 'forward';
879: }
880: if ($env{'form.associate'} eq 'Reverse Association') {
881: if ( $env{'form.upfile_associate'} ne 'reverse' ) {
882: $env{'form.upfile_associate'} = 'reverse';
883: } else {
884: $env{'form.upfile_associate'} = 'forward';
885: }
886: }
887: if ($env{'form.upfile_associate'} eq 'reverse') {
888: $javascript=&upload_manager_javascript_reverse_associate($can_assign);
889: } else {
890: $javascript=&upload_manager_javascript_forward_associate($can_assign);
891: }
892: #
893: # Deal with restored settings
894: my $password_choice = '';
895: if (exists($env{'form.ipwd_choice'}) &&
896: $env{'form.ipwd_choice'} ne '') {
897: # If a column was specified for password, assume it is for an
898: # internal password. This is a bug waiting to be filed (could be
899: # local or krb auth instead of internal) but I do not have the
900: # time to mess around with this now.
901: $password_choice = 'int';
902: }
903: #
904: my $groupslist;
905: if ($context eq 'course') {
906: $groupslist = &get_groupslist();
907: }
908: my $javascript_validations =
909: &javascript_validations('upload',$krbdefdom,$password_choice,undef,
910: $env{'request.role.domain'},$context,
911: $groupslist,$crstype);
912: my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
913: $r->print(
914: '<h3>'.&mt('Identify fields in uploaded list')."</h3>\n".
915: '<p class="LC_info">'.
916: &mt('Total number of records found in file: [_1]'
917: ,'<b>'.$distotal.'</b>').
918: "</p>\n"
919: );
920: if ($distotal == 0) {
921: $r->print('<p class="LC_warning">'.&mt('None found').'</p>');
922: }
923: $r->print(
924: '<p>'.
925: &mt('Enter as many fields as you can.').'<br />'.
926: &mt('The system will inform you and bring you back to this page,[_1]if the data selected are insufficient to add users.','<br />').
927: "</p>\n"
928: );
929: $r->print(&hidden_input('action','upload').
930: &hidden_input('state','got_file').
931: &hidden_input('associate','').
932: &hidden_input('datatoken',$datatoken).
933: &hidden_input('fileupload',$env{'form.fileupload'}).
934: &hidden_input('upfiletype',$env{'form.upfiletype'}).
935: &hidden_input('upfile_associate',$env{'form.upfile_associate'}));
936: $r->print(
937: '<div class="LC_left_float">'.
938: '<fieldset><legend>'.&mt('Functions').'</legend>'.
939: '<label><input type="checkbox" name="noFirstLine"'.$checked.' />'.
940: &mt('Ignore First Line').'</label>'.
941: ' <input type="button" value="'.&mt('Reverse Association').'" '.
942: 'name="Reverse Association" '.
943: 'onclick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />'.
944: '</fieldset></div><br clear="all" />'
945: );
946: $r->print(
947: '<script type="text/javascript" language="Javascript">'."\n".
948: '// <![CDATA['."\n".
949: $javascript."\n".$javascript_validations."\n".
950: '// ]]>'."\n".
951: '</script>'
952: );
953: }
954:
955: ###############################################################
956: ###############################################################
957: sub javascript_validations {
958: my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain,
959: $context,$groupslist,$crstype)=@_;
960: my %param = (
961: kerb_def_dom => $krbdefdom,
962: curr_authtype => $curr_authtype,
963: );
964: if ($mode eq 'upload') {
965: $param{'formname'} = 'studentform';
966: } elsif ($mode eq 'createcourse') {
967: $param{'formname'} = 'ccrs';
968: } elsif ($mode eq 'modifycourse') {
969: $param{'formname'} = 'cmod';
970: $param{'mode'} = 'modifycourse',
971: $param{'curr_autharg'} = $curr_authfield;
972: }
973:
974: my $showcredits;
975: my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
976: if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
977: $showcredits = 1;
978: }
979:
980: my ($setsection_call,$setsections_js);
981: my $finish = " vf.submit();\n";
982: if ($mode eq 'upload') {
983: if (($context eq 'course') || ($context eq 'domain')) {
984: if ($context eq 'course') {
985: if ($env{'request.course.sec'} eq '') {
986: $setsection_call = 'setSections(document.'.$param{'formname'}.",'$crstype'".');';
987: $setsections_js =
988: &setsections_javascript($param{'formname'},$groupslist,
989: $mode,'',$crstype,$showcredits);
990: } else {
991: $setsection_call = "'ok'";
992: }
993: } elsif ($context eq 'domain') {
994: $setsection_call = 'setCourse()';
995: $setsections_js = &dc_setcourse_js($param{'formname'},$mode,
996: $context,$showcredits,$domain);
997: }
998: $finish = " var checkSec = $setsection_call\n".
999: " if (checkSec == 'ok') {\n".
1000: " vf.submit();\n".
1001: " }\n";
1002: }
1003: }
1004: my $authheader = &Apache::loncommon::authform_header(%param);
1005:
1006: my %alert = &Apache::lonlocal::texthash
1007: (username => 'You need to specify the username field.',
1008: authen => 'You must choose an authentication type.',
1009: krb => 'You need to specify the Kerberos domain.',
1010: ipass => 'You need to specify the initial password.',
1011: name => 'The optional name field was not specified.',
1012: snum => 'The optional student/employee ID field was not specified.',
1013: section => 'The optional section field was not specified.',
1014: email => 'The optional e-mail address field was not specified.',
1015: role => 'The optional role field was not specified.',
1016: domain => 'The optional domain field was not specified.',
1017: continue => 'Continue adding users?',
1018: );
1019: if ($showcredits) {
1020: $alert{'credits'} = &mt('The optional credits field was not specified');
1021: }
1022: if (($mode eq 'upload') && ($context eq 'domain')) {
1023: $alert{'inststatus'} = &mt('The optional affiliation field was not specified');
1024: }
1025: &js_escape(\%alert);
1026: my $function_name = <<"END";
1027: $setsections_js
1028:
1029: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits) {
1030: END
1031: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain);
1032: my $auth_checks;
1033: if ($mode eq 'createcourse') {
1034: $auth_checks .= (<<END);
1035: if (vf.autoadds[0].checked == true) {
1036: if (current.radiovalue == null || current.radiovalue == 'nochange') {
1037: alert('$alert{'authen'}');
1038: return;
1039: }
1040: }
1041: END
1042: } else {
1043: $auth_checks .= (<<END);
1044: var foundatype=0;
1045: if (founduname==0) {
1046: alert('$alert{'username'}');
1047: return;
1048: }
1049:
1050: END
1051: if ($authnum > 1) {
1052: $auth_checks .= (<<END);
1053: if (current.radiovalue == null || current.radiovalue == '' || current.radiovalue == 'nochange') {
1054: // They did not check any of the login radiobuttons.
1055: alert('$alert{'authen'}');
1056: return;
1057: }
1058: END
1059: }
1060: }
1061: if ($mode eq 'createcourse') {
1062: $auth_checks .= "
1063: if ( (vf.autoadds[0].checked == true) &&
1064: (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
1065: ";
1066: } elsif ($mode eq 'modifycourse') {
1067: $auth_checks .= "
1068: if ((current.argfield !== null) && (current.argfield !== undefined) && (current.argfield !== '') && (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '')) {
1069: ";
1070: }
1071: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1072: $auth_checks .= (<<END);
1073: var alertmsg = '';
1074: switch (current.radiovalue) {
1075: case 'krb':
1076: alertmsg = '$alert{'krb'}';
1077: break;
1078: default:
1079: alertmsg = '';
1080: }
1081: if (alertmsg != '') {
1082: alert(alertmsg);
1083: return;
1084: }
1085: }
1086: /* regexp here to check for non \d \. in credits */
1087: END
1088: } else {
1089: my ($numrules,$intargjs) =
1090: &Apache::loncommon::passwd_validation_js('vf.elements[current.argfield].value',$domain);
1091: $auth_checks .= (<<END);
1092: foundatype=1;
1093: if (current.argfield == null || current.argfield == '') {
1094: // The login radiobutton checked does not have an associated textbox
1095: } else if (vf.elements[current.argfield].value == '') {
1096: var alertmsg = '';
1097: switch (current.radiovalue) {
1098: case 'krb':
1099: alertmsg = '$alert{'krb'}';
1100: break;
1101: case 'int':
1102: alertmsg = '$alert{'ipass'}';
1103: break;
1104: case 'fsys':
1105: alertmsg = '$alert{'ipass'}';
1106: break;
1107: case 'loc':
1108: alertmsg = '';
1109: break;
1110: case 'lti':
1111: default:
1112: alertmsg = '';
1113: }
1114: if (alertmsg != '') {
1115: alert(alertmsg);
1116: return;
1117: }
1118: } else if (current.radiovalue == 'int') {
1119: if ($numrules > 0) {
1120: $intargjs
1121: }
1122: }
1123: END
1124: }
1125: my $section_checks;
1126: my $optional_checks = '';
1127: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1128: $optional_checks = (<<END);
1129: vf.submit();
1130: }
1131: END
1132: } else {
1133: $section_checks = §ion_check_js();
1134: $optional_checks = (<<END);
1135: var message='';
1136: if (foundname==0) {
1137: message='$alert{'name'}';
1138: }
1139: if (foundid==0) {
1140: if (message!='') {
1141: message+='\\n';
1142: }
1143: message+='$alert{'snum'}';
1144: }
1145: if (foundsec==0) {
1146: if (message!='') {
1147: message+='\\n';
1148: }
1149: message+='$alert{'section'}';
1150: }
1151: if (foundemail==0) {
1152: if (message!='') {
1153: message+='\\n';
1154: }
1155: message+='$alert{'email'}';
1156: }
1157: if (foundrole==0) {
1158: if (message!='') {
1159: message+='\\n';
1160: }
1161: message+='$alert{'role'}';
1162: }
1163: if (founddomain==0) {
1164: if (message!='') {
1165: message+='\\n';
1166: }
1167: message+='$alert{'domain'}';
1168: }
1169: END
1170: if ($showcredits) {
1171: $optional_checks .= <<END;
1172: if (foundcredits==0) {
1173: if (message!='') {
1174: message+='\\n';
1175: }
1176: message+='$alert{'credits'}';
1177: }
1178: END
1179: }
1180: if (($mode eq 'upload') && ($context eq 'domain')) {
1181: $optional_checks .= (<<END);
1182:
1183: if (foundinststatus==0) {
1184: if (message!='') {
1185: message+='\\n';
1186: }
1187: message+='$alert{'inststatus'}';
1188: }
1189: END
1190: }
1191: $optional_checks .= (<<END);
1192:
1193: if (message!='') {
1194: message+= '\\n$alert{'continue'}';
1195: if (confirm(message)) {
1196: vf.state.value='enrolling';
1197: $finish
1198: }
1199: } else {
1200: vf.state.value='enrolling';
1201: $finish
1202: }
1203: }
1204: END
1205: }
1206: my $result = $function_name.$auth_checks.$optional_checks."\n".
1207: $section_checks.$authheader;
1208: return $result;
1209: }
1210:
1211: ###############################################################
1212: ###############################################################
1213: sub upload_manager_javascript_forward_associate {
1214: my ($can_assign) = @_;
1215: my ($auth_update,$numbuttons,$argreset);
1216: if (ref($can_assign) eq 'HASH') {
1217: if ($can_assign->{'krb4'} || $can_assign->{'krb5'}) {
1218: $argreset .= " vf.krbarg.value='';\n";
1219: $numbuttons ++ ;
1220: }
1221: if ($can_assign->{'int'}) {
1222: $argreset .= " vf.intarg.value='';\n";
1223: $numbuttons ++;
1224: }
1225: if ($can_assign->{'loc'}) {
1226: $argreset .= " vf.locarg.value='';\n";
1227: $numbuttons ++;
1228: }
1229: if (!$can_assign->{'int'}) {
1230: my $warning = &mt('You may not specify an initial password for each user, as this is only available when new users use LON-CAPA internal authentication.')."\n".
1231: &mt('Your current role does not have rights to create users with that authentication type.');
1232: &js_escape(\$warning);
1233: $auth_update = <<"END";
1234: // Currently the initial password field is only supported for internal auth
1235: // (see bug 6368).
1236: if (nw==9) {
1237: eval('vf.f'+tf+'.selectedIndex=0;')
1238: alert('$warning');
1239: }
1240: END
1241: } elsif ($numbuttons > 1) {
1242: $auth_update = <<"END";
1243: // If we set the password, make the password form below correspond to
1244: // the new value.
1245: if (nw==9) {
1246: changed_radio('int',document.studentform);
1247: set_auth_radio_buttons('int',document.studentform);
1248: $argreset
1249: }
1250:
1251: END
1252: }
1253: }
1254:
1255: return(<<ENDPICK);
1256: function verify(vf,sec_caller) {
1257: var founduname=0;
1258: var foundpwd=0;
1259: var foundname=0;
1260: var foundid=0;
1261: var foundsec=0;
1262: var foundemail=0;
1263: var foundrole=0;
1264: var founddomain=0;
1265: var foundinststatus=0;
1266: var foundcredits=0;
1267: var tw;
1268: for (i=0;i<=vf.nfields.value;i++) {
1269: tw=eval('vf.f'+i+'.selectedIndex');
1270: if (tw==1) { founduname=1; }
1271: if ((tw>=2) && (tw<=6)) { foundname=1; }
1272: if (tw==7) { foundid=1; }
1273: if (tw==8) { foundsec=1; }
1274: if (tw==9) { foundpwd=1; }
1275: if (tw==10) { foundemail=1; }
1276: if (tw==11) { foundrole=1; }
1277: if (tw==12) { founddomain=1; }
1278: if (tw==13) { foundinststatus=1; }
1279: if (tw==14) { foundcredits=1; }
1280: }
1281: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits);
1282: }
1283:
1284: //
1285: // vf = this.form
1286: // tf = column number
1287: //
1288: // values of nw
1289: //
1290: // 0 = none
1291: // 1 = username
1292: // 2 = names (lastname, firstnames)
1293: // 3 = fname (firstname)
1294: // 4 = mname (middlename)
1295: // 5 = lname (lastname)
1296: // 6 = gen (generation)
1297: // 7 = id
1298: // 8 = section
1299: // 9 = ipwd (password)
1300: // 10 = email address
1301: // 11 = role
1302: // 12 = domain
1303: // 13 = inststatus
1304: // 14 = foundcredits
1305:
1306: function flip(vf,tf) {
1307: var nw=eval('vf.f'+tf+'.selectedIndex');
1308: var i;
1309: // make sure no other columns are labeled the same as this one
1310: for (i=0;i<=vf.nfields.value;i++) {
1311: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
1312: eval('vf.f'+i+'.selectedIndex=0;')
1313: }
1314: }
1315: // If we set this to 'lastname, firstnames', clear out all the ones
1316: // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
1317: if (nw==2) {
1318: for (i=0;i<=vf.nfields.value;i++) {
1319: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
1320: (eval('vf.f'+i+'.selectedIndex')<=6)) {
1321: eval('vf.f'+i+'.selectedIndex=0;')
1322: }
1323: }
1324: }
1325: // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
1326: // clear out any that are set to 'lastname, firstnames' (2)
1327: if ((nw>=3) && (nw<=6)) {
1328: for (i=0;i<=vf.nfields.value;i++) {
1329: if (eval('vf.f'+i+'.selectedIndex')==2) {
1330: eval('vf.f'+i+'.selectedIndex=0;')
1331: }
1332: }
1333: }
1334: $auth_update
1335: }
1336:
1337: function clearpwd(vf) {
1338: var i;
1339: for (i=0;i<=vf.nfields.value;i++) {
1340: if (eval('vf.f'+i+'.selectedIndex')==9) {
1341: eval('vf.f'+i+'.selectedIndex=0;')
1342: }
1343: }
1344: }
1345:
1346: ENDPICK
1347: }
1348:
1349: ###############################################################
1350: ###############################################################
1351: sub upload_manager_javascript_reverse_associate {
1352: my ($can_assign) = @_;
1353: my ($auth_update,$numbuttons,$argreset);
1354: if (ref($can_assign) eq 'HASH') {
1355: if ($can_assign->{'krb4'} || $can_assign->{'krb5'}) {
1356: $argreset .= " vf.krbarg.value='';\n";
1357: $numbuttons ++ ;
1358: }
1359: if ($can_assign->{'int'}) {
1360: $argreset .= " vf.intarg.value='';\n";
1361: $numbuttons ++;
1362: }
1363: if ($can_assign->{'loc'}) {
1364: $argreset .= " vf.locarg.value='';\n";
1365: $numbuttons ++;
1366: }
1367: if (!$can_assign->{'int'}) {
1368: my $warning = &mt('You may not specify an initial password, as this is only available when new users use LON-CAPA internal authentication.\n').
1369: &mt('Your current role does not have rights to create users with that authentication type.');
1370: &js_escape(\$warning);
1371: $auth_update = <<"END";
1372: // Currently the initial password field is only supported for internal auth
1373: // (see bug 6368).
1374: if (tf==8 && nw!=0) {
1375: eval('vf.f'+tf+'.selectedIndex=0;')
1376: alert('$warning');
1377: }
1378: END
1379: } elsif ($numbuttons > 1) {
1380: $auth_update = <<"END";
1381: // initial password specified, pick internal authentication
1382: if (tf==8 && nw!=0) {
1383: changed_radio('int',document.studentform);
1384: set_auth_radio_buttons('int',document.studentform);
1385: $argreset
1386: }
1387:
1388: END
1389: }
1390: }
1391:
1392: return(<<ENDPICK);
1393: function verify(vf,sec_caller) {
1394: var founduname=0;
1395: var foundpwd=0;
1396: var foundname=0;
1397: var foundid=0;
1398: var foundsec=0;
1399: var foundemail=0;
1400: var foundrole=0;
1401: var founddomain=0;
1402: var foundinststatus=0;
1403: var foundcredits=0;
1404: var tw;
1405: for (i=0;i<=vf.nfields.value;i++) {
1406: tw=eval('vf.f'+i+'.selectedIndex');
1407: if (i==0 && tw!=0) { founduname=1; }
1408: if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
1409: if (i==6 && tw!=0) { foundid=1; }
1410: if (i==7 && tw!=0) { foundsec=1; }
1411: if (i==8 && tw!=0) { foundpwd=1; }
1412: if (i==9 && tw!=0) { foundemail=1; }
1413: if (i==10 && tw!=0) { foundrole=1; }
1414: if (i==11 && tw!=0) { founddomain=1; }
1415: if (i==12 && tw!=0) { foundinstatus=1; }
1416: if (i==13 && tw!=0) { foundcredits=1; }
1417: }
1418: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits);
1419: }
1420:
1421: function flip(vf,tf) {
1422: var nw=eval('vf.f'+tf+'.selectedIndex');
1423: var i;
1424: // picked the all one name field, reset the other name ones to blank
1425: if (tf==1 && nw!=0) {
1426: for (i=2;i<=5;i++) {
1427: eval('vf.f'+i+'.selectedIndex=0;')
1428: }
1429: }
1430: //picked one of the piecewise name fields, reset the all in
1431: //one field to blank
1432: if ((tf>=2) && (tf<=5) && (nw!=0)) {
1433: eval('vf.f1.selectedIndex=0;')
1434: }
1435: $auth_update
1436: }
1437:
1438: function clearpwd(vf) {
1439: var i;
1440: if (eval('vf.f8.selectedIndex')!=0) {
1441: eval('vf.f8.selectedIndex=0;')
1442: }
1443: }
1444: ENDPICK
1445: }
1446:
1447: ###############################################################
1448: ###############################################################
1449: sub print_upload_manager_footer {
1450: my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission,$crstype,
1451: $showcredits) = @_;
1452: my $form = 'document.studentform';
1453: my $formname = 'studentform';
1454: my ($krbdef,$krbdefdom) =
1455: &Apache::loncommon::get_kerberos_defaults($defdom);
1456: my %param = ( formname => $form,
1457: kerb_def_dom => $krbdefdom,
1458: kerb_def_auth => $krbdef
1459: );
1460: if (exists($env{'form.ipwd_choice'}) &&
1461: defined($env{'form.ipwd_choice'}) &&
1462: $env{'form.ipwd_choice'} ne '') {
1463: $param{'curr_authtype'} = 'int';
1464: }
1465: my $krbform = &Apache::loncommon::authform_kerberos(%param);
1466: my $intform = &Apache::loncommon::authform_internal(%param);
1467: my $locform = &Apache::loncommon::authform_local(%param);
1468: my $ltiform = &Apache::loncommon::authform_lti(%param);
1469: my $date_table = &date_setting_table(undef,undef,$context,undef,
1470: $formname,$permission,$crstype);
1471:
1472: my $Str = "\n".'<div class="LC_left_float">';
1473: $Str .= &hidden_input('nfields',$i);
1474: $Str .= &hidden_input('keyfields',$keyfields);
1475:
1476: $Str .= '<h3>'.&mt('Options').'</h3>'
1477: .&Apache::lonhtmlcommon::start_pick_box();
1478:
1479: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Login Type'));
1480: if ($context eq 'domain') {
1481: $Str .= '<p>'
1482: .&mt('Change authentication for existing users in domain "[_1]" to these settings?'
1483: ,$defdom)
1484: .' <span class="LC_nobreak"><label>'
1485: .'<input type="radio" name="changeauth" value="No" checked="checked" />'
1486: .&mt('No').'</label>'
1487: .' <label>'
1488: .'<input type="radio" name="changeauth" value="Yes" />'
1489: .&mt('Yes').'</label>'
1490: .'</span></p>';
1491: } else {
1492: $Str .= '<p class="LC_info">'."\n".
1493: &mt('This will not take effect if the user already exists.').
1494: &Apache::loncommon::help_open_topic('Auth_Options').
1495: "</p>\n";
1496: }
1497: $Str .= &set_login($defdom,$krbform,$intform,$locform,$ltiform);
1498:
1499: my ($home_server_pick,$numlib) =
1500: &Apache::loncommon::home_server_form_item($defdom,'lcserver',
1501: 'default','hide');
1502: if ($numlib > 1) {
1503: $Str .= &Apache::lonhtmlcommon::row_closure()
1504: .&Apache::lonhtmlcommon::row_title(
1505: &mt('LON-CAPA Home Server for New Users'))
1506: .&mt('LON-CAPA domain: [_1] with home server:','"'.$defdom.'"')
1507: .$home_server_pick
1508: .&Apache::lonhtmlcommon::row_closure();
1509: } else {
1510: $Str .= $home_server_pick.
1511: &Apache::lonhtmlcommon::row_closure();
1512: }
1513:
1514: my ($trusted,$untrusted);
1515: if ($context eq 'course') {
1516: ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('enroll',$defdom);
1517: } elsif ($context eq 'author') {
1518: ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('othcoau',$defdom);
1519: }
1520: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain'))
1521: .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1,undef,$trusted,$untrusted)
1522: .&Apache::lonhtmlcommon::row_closure();
1523:
1524: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates'))
1525: ."<p>\n".$date_table."</p>\n"
1526: .&Apache::lonhtmlcommon::row_closure();
1527:
1528: if ($context eq 'domain') {
1529: $Str .= &Apache::lonhtmlcommon::row_title(
1530: &mt('Settings for assigning roles'))
1531: .&mt('Pick the action to take on roles for these users:').'<br />'
1532: .'<span class="LC_nobreak"><label>'
1533: .'<input type="radio" name="roleaction" value="norole" checked="checked" />'
1534: .' '.&mt('No role changes').'</label>'
1535: .' <label>'
1536: .'<input type="radio" name="roleaction" value="domain" />'
1537: .' '.&mt('Add a domain role').'</label>'
1538: .' <label>'
1539: .'<input type="radio" name="roleaction" value="course" />'
1540: .' '.&mt('Add a course/community role').'</label>'
1541: .'</span>';
1542: } elsif ($context eq 'author') {
1543: $Str .= &Apache::lonhtmlcommon::row_title(
1544: &mt('Default role'))
1545: .&mt('Choose the role to assign to users without a value specified in the uploaded file.')
1546: } elsif ($context eq 'course') {
1547: if ($showcredits) {
1548: $Str .= &Apache::lonhtmlcommon::row_title(
1549: &mt('Default role, section and credits'))
1550: .&mt('Choose the role and/or section(s) and/or credits to assign to users without values specified in the uploaded file.');
1551: } else {
1552: $Str .= &Apache::lonhtmlcommon::row_title(
1553: &mt('Default role and section'))
1554: .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.');
1555: }
1556: } else {
1557: $Str .= &Apache::lonhtmlcommon::row_title(
1558: &mt('Default role and/or section(s)'))
1559: .&mt('Role and/or section(s) for users without values specified in the uploaded file.');
1560: }
1561: if (($context eq 'domain') || ($context eq 'author')) {
1562: $Str .= '<br />';
1563: my ($options,$cb_script,$coursepick) =
1564: &default_role_selector($context,1,'',$showcredits);
1565: if ($context eq 'domain') {
1566: $Str .= '<p>'
1567: .'<b>'.&mt('Domain Level').'</b><br />'
1568: .$options
1569: .'</p><p>'
1570: .'<b>'.&mt('Course Level').'</b>'
1571: .'</p>'
1572: .$cb_script.$coursepick
1573: .&Apache::lonhtmlcommon::row_closure();
1574: } elsif ($context eq 'author') {
1575: $Str .= $options
1576: .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
1577: }
1578: } else {
1579: my ($cnum,$cdom) = &get_course_identity();
1580: my $rowtitle = &mt('section');
1581: my $defaultcredits;
1582: if ($showcredits) {
1583: $defaultcredits = &get_defaultcredits();
1584: }
1585: my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle,$permission,
1586: $context,'upload',$crstype,$showcredits,
1587: $defaultcredits);
1588: $Str .= $secbox
1589: .&Apache::lonhtmlcommon::row_closure();
1590: my %lt;
1591: if ($crstype eq 'Community') {
1592: %lt = &Apache::lonlocal::texthash (
1593: disp => 'Display members with current/future access who are not in the uploaded file',
1594: stus => 'Members selected from this list can be dropped.'
1595: );
1596: } else {
1597: %lt = &Apache::lonlocal::texthash (
1598: disp => 'Display students with current/future access who are not in the uploaded file',
1599: stus => 'Students selected from this list can be dropped.'
1600: );
1601: }
1602: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Full Update'))
1603: .'<label><input type="checkbox" name="fullup" value="yes" />'
1604: .' '.$lt{'disp'}
1605: .'</label><br />'
1606: .$lt{'stus'}
1607: .&Apache::lonhtmlcommon::row_closure();
1608: }
1609: if ($context eq 'course' || $context eq 'domain') {
1610: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Student/Employee ID'))
1611: .&forceid_change($context)
1612: .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
1613: }
1614:
1615: $Str .= &Apache::lonhtmlcommon::end_pick_box();
1616: $Str .= '</div>';
1617:
1618: # Footer
1619: $Str .= '<div class="LC_clear_float_footer">'
1620: .'<hr />';
1621: if ($context eq 'course') {
1622: $Str .= '<p class="LC_info">'
1623: .&mt('Note: This operation may be time consuming when adding several users.')
1624: .'</p>';
1625: }
1626: $Str .= '<p><input type="button"'
1627: .' onclick="javascript:verify(this.form,this.form.csec)"'
1628: .' value="'.&mt('Update Users').'" />'
1629: .'</p>'."\n"
1630: .'</div>';
1631: $r->print($Str);
1632: return;
1633: }
1634:
1635: sub get_defaultcredits {
1636: my ($cdom,$cnum) = @_;
1637:
1638: if ($cdom eq '' || $cnum eq '') {
1639: return unless ($env{'request.course.id'});
1640: $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1641: $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1642: }
1643: return unless(($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/));
1644: my ($defaultcredits,$domdefcredits);
1645: my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
1646: if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
1647: my $instcode = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'};
1648: if ($instcode) {
1649: $domdefcredits = $domdefaults{'officialcredits'};
1650: } elsif ($env{'course.'.$cdom.'_'.$cnum.'.internal.textbook'}) {
1651: $domdefcredits = $domdefaults{'textbookcredits'};
1652: } else {
1653: $domdefcredits = $domdefaults{'unofficialcredits'};
1654: }
1655: } else {
1656: return;
1657: }
1658:
1659: if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
1660: $defaultcredits = $env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'};
1661: } elsif (exists($env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'})) {
1662: $defaultcredits = $env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'};
1663: } else {
1664: my %crsinfo =
1665: &Apache::lonnet::coursedescription("$cdom/$cnum",{'one_time' => 1});
1666: $defaultcredits = $crsinfo{'internal.defaultcredits'};
1667: }
1668: if ($defaultcredits eq '') {
1669: $defaultcredits = $domdefcredits;
1670: }
1671: return $defaultcredits;
1672: }
1673:
1674: sub forceid_change {
1675: my ($context) = @_;
1676: my $output =
1677: '<label><input type="checkbox" name="forceid" value="yes" />'
1678: .&mt('Force change of existing ID')
1679: .'</label>'.&Apache::loncommon::help_open_topic('ForceIDChange')."\n";
1680: if ($context eq 'domain') {
1681: $output .=
1682: '<br />'
1683: .'<label><input type="checkbox" name="recurseid" value="yes" />'
1684: .&mt("Update ID in user's course(s).").'</label>'."\n";
1685: }
1686: return $output;
1687: }
1688:
1689: ###############################################################
1690: ###############################################################
1691: sub print_upload_manager_form {
1692: my ($r,$context,$permission,$crstype,$showcredits) = @_;
1693: my $firstLine;
1694: my $datatoken;
1695: if (!$env{'form.datatoken'}) {
1696: $datatoken=&Apache::loncommon::upfile_store($r);
1697: } else {
1698: $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
1699: if ($datatoken ne '') {
1700: &Apache::loncommon::load_tmp_file($r,$datatoken);
1701: }
1702: }
1703: if ($datatoken eq '') {
1704: $r->print('<p class="LC_error">'.&mt('Error').': '.
1705: &mt('Invalid datatoken').'</p>');
1706: return 'missingdata';
1707: }
1708: my @records=&Apache::loncommon::upfile_record_sep();
1709: if($env{'form.noFirstLine'}){
1710: $firstLine=shift(@records);
1711: }
1712: my $total=$#records;
1713: my $distotal=$total+1;
1714: my $today=time;
1715: my $halfyear=$today+15552000;
1716: #
1717: # Restore memorized settings
1718: my $col_setting_names = { 'username_choice' => 'scalar', # column settings
1719: 'names_choice' => 'scalar',
1720: 'fname_choice' => 'scalar',
1721: 'mname_choice' => 'scalar',
1722: 'lname_choice' => 'scalar',
1723: 'gen_choice' => 'scalar',
1724: 'id_choice' => 'scalar',
1725: 'sec_choice' => 'scalar',
1726: 'ipwd_choice' => 'scalar',
1727: 'email_choice' => 'scalar',
1728: 'role_choice' => 'scalar',
1729: 'domain_choice' => 'scalar',
1730: 'inststatus_choice' => 'scalar',
1731: };
1732: if ($showcredits) {
1733: $col_setting_names->{'credits_choice'} = 'scalar';
1734: }
1735: if ($context eq 'course') {
1736: &Apache::loncommon::restore_course_settings('enrollment_upload',
1737: $col_setting_names);
1738: } else {
1739: &Apache::loncommon::restore_settings($context,'user_upload',
1740: $col_setting_names);
1741: }
1742: my $defdom = $env{'request.role.domain'};
1743: #
1744: # Determine kerberos parameters as appropriate
1745: my ($krbdef,$krbdefdom) =
1746: &Apache::loncommon::get_kerberos_defaults($defdom);
1747: #
1748: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($defdom);
1749: &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context,
1750: $permission,$crstype,\%can_assign);
1751: my $i;
1752: my $keyfields;
1753: if ($total>=0) {
1754: my @field=
1755: (['username',&mt('Username'), $env{'form.username_choice'}],
1756: ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}],
1757: ['fname',&mt('First Name'), $env{'form.fname_choice'}],
1758: ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}],
1759: ['lname',&mt('Last Name'), $env{'form.lname_choice'}],
1760: ['gen', &mt('Generation'), $env{'form.gen_choice'}],
1761: ['id', &mt('Student/Employee ID'),$env{'form.id_choice'}],
1762: ['sec', &mt('Section'), $env{'form.sec_choice'}],
1763: ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}],
1764: ['email',&mt('E-mail Address'), $env{'form.email_choice'}],
1765: ['role',&mt('Role'), $env{'form.role_choice'}],
1766: ['domain',&mt('Domain'), $env{'form.domain_choice'}],
1767: ['inststatus',&mt('Affiliation'), $env{'form.inststatus_choice'}]);
1768: if ($showcredits) {
1769: push(@field,
1770: ['credits',&mt('Student Credits'), $env{'form.credits_choice'}]);
1771: }
1772: if ($env{'form.upfile_associate'} eq 'reverse') {
1773: &Apache::loncommon::csv_print_samples($r,\@records);
1774: $i=&Apache::loncommon::csv_print_select_table($r,\@records,
1775: \@field);
1776: foreach (@field) {
1777: $keyfields.=$_->[0].',';
1778: }
1779: chop($keyfields);
1780: } else {
1781: unshift(@field,['none','']);
1782: $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
1783: \@field);
1784: my %sone=&Apache::loncommon::record_sep($records[0]);
1785: $keyfields=join(',',sort(keys(%sone)));
1786: }
1787: }
1788: &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
1789: $context,$permission,$crstype,$showcredits);
1790: return 'ok';
1791: }
1792:
1793: sub setup_date_selectors {
1794: my ($starttime,$endtime,$mode,$nolink,$formname) = @_;
1795: if ($formname eq '') {
1796: $formname = 'studentform';
1797: }
1798: if (! defined($starttime)) {
1799: $starttime = time;
1800: unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
1801: if (exists($env{'course.'.$env{'request.course.id'}.
1802: '.default_enrollment_start_date'})) {
1803: $starttime = $env{'course.'.$env{'request.course.id'}.
1804: '.default_enrollment_start_date'};
1805: }
1806: }
1807: }
1808: if (! defined($endtime)) {
1809: $endtime = time+(6*30*24*60*60); # 6 months from now, approx
1810: unless ($mode eq 'createcourse') {
1811: if (exists($env{'course.'.$env{'request.course.id'}.
1812: '.default_enrollment_end_date'})) {
1813: $endtime = $env{'course.'.$env{'request.course.id'}.
1814: '.default_enrollment_end_date'};
1815: }
1816: }
1817: }
1818:
1819: my $startdateform =
1820: &Apache::lonhtmlcommon::date_setter($formname,'startdate',$starttime,
1821: undef,undef,undef,undef,undef,undef,undef,$nolink);
1822:
1823: my $enddateform =
1824: &Apache::lonhtmlcommon::date_setter($formname,'enddate',$endtime,
1825: undef,undef,undef,undef,undef,undef,undef,$nolink);
1826:
1827: if ($mode eq 'create_enrolldates') {
1828: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1829: 'startenroll',
1830: $starttime);
1831: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1832: 'endenroll',
1833: $endtime);
1834: }
1835: if ($mode eq 'create_defaultdates') {
1836: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1837: 'startaccess',
1838: $starttime);
1839: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1840: 'endaccess',
1841: $endtime);
1842: }
1843: return ($startdateform,$enddateform);
1844: }
1845:
1846:
1847: sub get_dates_from_form {
1848: my ($startname,$endname) = @_;
1849: if ($startname eq '') {
1850: $startname = 'startdate';
1851: }
1852: if ($endname eq '') {
1853: $endname = 'enddate';
1854: }
1855: my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname);
1856: my $enddate = &Apache::lonhtmlcommon::get_date_from_form($endname);
1857: if ($env{'form.no_end_date'}) {
1858: $enddate = 0;
1859: }
1860: return ($startdate,$enddate);
1861: }
1862:
1863: sub date_setting_table {
1864: my ($starttime,$endtime,$mode,$bulkaction,$formname,$permission,$crstype) = @_;
1865: my $nolink;
1866: if ($bulkaction) {
1867: $nolink = 1;
1868: }
1869: my ($startform,$endform) =
1870: &setup_date_selectors($starttime,$endtime,$mode,$nolink,$formname);
1871: my $dateDefault;
1872: if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
1873: $dateDefault = ' ';
1874: } elsif ($mode ne 'author' && $mode ne 'domain') {
1875: if (($bulkaction eq 'reenable') ||
1876: ($bulkaction eq 'activate') ||
1877: ($bulkaction eq 'chgdates') ||
1878: ($env{'form.action'} eq 'upload')) {
1879: if ($env{'request.course.sec'} eq '') {
1880: $dateDefault = '<span class="LC_nobreak">'.
1881: '<label><input type="checkbox" name="makedatesdefault" value="1" /> ';
1882: if ($crstype eq 'Community') {
1883: $dateDefault .= &mt("make these dates the default access dates for future community enrollment");
1884: } else {
1885: $dateDefault .= &mt("make these dates the default access dates for future course enrollment");
1886: }
1887: $dateDefault .= '</label></span>';
1888: }
1889: }
1890: }
1891: my $perpetual = '<span class="LC_nobreak"><label><input type="checkbox" name="no_end_date"';
1892: if (defined($endtime) && $endtime == 0) {
1893: $perpetual .= ' checked="checked"';
1894: }
1895: $perpetual.= ' /> '.&mt('no ending date').'</label></span>';
1896: if ($mode eq 'create_enrolldates') {
1897: $perpetual = ' ';
1898: }
1899: my $result = &Apache::lonhtmlcommon::start_pick_box()."\n";
1900: $result .= &Apache::lonhtmlcommon::row_title(&mt('Starting Date'),
1901: 'LC_oddrow_value')."\n".
1902: $startform."\n".
1903: &Apache::lonhtmlcommon::row_closure(1).
1904: &Apache::lonhtmlcommon::row_title(&mt('Ending Date'),
1905: 'LC_oddrow_value')."\n".
1906: $endform.' '.$perpetual.
1907: &Apache::lonhtmlcommon::row_closure(1).
1908: &Apache::lonhtmlcommon::end_pick_box();
1909: if ($dateDefault) {
1910: $result .= $dateDefault.'<br />'."\n";
1911: }
1912: return $result;
1913: }
1914:
1915: sub make_dates_default {
1916: my ($startdate,$enddate,$context,$crstype) = @_;
1917: my $result = '';
1918: if ($context eq 'course') {
1919: my ($cnum,$cdom) = &get_course_identity();
1920: my $put_result = &Apache::lonnet::put('environment',
1921: {'default_enrollment_start_date'=>$startdate,
1922: 'default_enrollment_end_date' =>$enddate},$cdom,$cnum);
1923: if ($put_result eq 'ok') {
1924: if ($crstype eq 'Community') {
1925: $result .= &mt('Set default start and end access dates for community.');
1926: } else {
1927: $result .= &mt('Set default start and end access dates for course.');
1928: }
1929: $result .= '<br />'."\n";
1930: #
1931: # Refresh the course environment
1932: &Apache::lonnet::coursedescription($env{'request.course.id'},
1933: {'freshen_cache' => 1});
1934: } else {
1935: if ($crstype eq 'Community') {
1936: $result .= &mt('Unable to set default access dates for community');
1937: } else {
1938: $result .= &mt('Unable to set default access dates for course');
1939: }
1940: $result .= ':'.$put_result.'<br />';
1941: }
1942: }
1943: return $result;
1944: }
1945:
1946: sub default_role_selector {
1947: my ($context,$checkpriv,$crstype,$showcredits) = @_;
1948: my %customroles;
1949: my ($options,$coursepick,$cb_jscript);
1950: if ($context ne 'author') {
1951: %customroles = &my_custom_roles($crstype);
1952: }
1953:
1954: my %lt=&Apache::lonlocal::texthash(
1955: 'rol' => "Role",
1956: 'grs' => "Section",
1957: 'exs' => "Existing sections",
1958: 'new' => "New section",
1959: 'crd' => "Credits",
1960: );
1961: $options = '<select name="defaultrole">'."\n".
1962: ' <option value="">'.&mt('Please select').'</option>'."\n";
1963: if ($context eq 'course') {
1964: $options .= &default_course_roles($context,$checkpriv,$crstype,%customroles);
1965: } elsif ($context eq 'author') {
1966: my @roles = &construction_space_roles($checkpriv);
1967: foreach my $role (@roles) {
1968: my $plrole=&Apache::lonnet::plaintext($role);
1969: $options .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
1970: }
1971: } elsif ($context eq 'domain') {
1972: my @roles = &domain_roles($checkpriv);
1973: foreach my $role (@roles) {
1974: my $plrole=&Apache::lonnet::plaintext($role);
1975: $options .= ' <option value="'.$role.'">'.$plrole.'</option>';
1976: }
1977: my $courseform = &Apache::loncommon::selectcourse_link
1978: ('studentform','dccourse','dcdomain','coursedesc',"$env{'request.role.domain'}",undef,'Course/Community');
1979: my ($credit_elem,$creditsinput);
1980: if ($showcredits) {
1981: $credit_elem = 'credits';
1982: $creditsinput = '<td><input type="text" name="credits" value="" /></td>';
1983: }
1984: $cb_jscript =
1985: &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'},'currsec','studentform','courserole','Course/Community',$credit_elem);
1986: $coursepick = &Apache::loncommon::start_data_table().
1987: &Apache::loncommon::start_data_table_header_row().
1988: '<th>'.$courseform.'</th><th>'.$lt{'rol'}.'</th>'.
1989: '<th>'.$lt{'grs'}.'</th>'.
1990: '<th>'.$lt{'crd'}.'</th>'.
1991: &Apache::loncommon::end_data_table_header_row().
1992: &Apache::loncommon::start_data_table_row()."\n".
1993: '<td><input type="text" name="coursedesc" value="" onfocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc','','','','crstype'".')" /></td>'."\n".
1994: '<td><select name="courserole">'."\n".
1995: &default_course_roles($context,$checkpriv,'Course',%customroles)."\n".
1996: '</select></td><td>'.
1997: '<table class="LC_createuser">'.
1998: '<tr class="LC_section_row"><td valign="top">'.
1999: $lt{'exs'}.'<br /><select name="currsec">'.
2000: ' <option value=""><--'.&mt('Pick course first').
2001: '</select></td>'.
2002: '<td> </td>'.
2003: '<td valign="top">'.$lt{'new'}.'<br />'.
2004: '<input type="text" name="newsec" value="" size="5" />'.
2005: '<input type="hidden" name="groups" value="" />'.
2006: '<input type="hidden" name="sections" value="" />'.
2007: '<input type="hidden" name="origdom" value="'.
2008: $env{'request.role.domain'}.'" />'.
2009: '<input type="hidden" name="dccourse" value="" />'.
2010: '<input type="hidden" name="dcdomain" value="" />'.
2011: '<input type="hidden" name="crstype" value="" />'.
2012: '</td></tr></table></td>'.$creditsinput.
2013: &Apache::loncommon::end_data_table_row().
2014: &Apache::loncommon::end_data_table()."\n";
2015: }
2016: $options .= '</select>';
2017: return ($options,$cb_jscript,$coursepick);
2018: }
2019:
2020: sub default_course_roles {
2021: my ($context,$checkpriv,$crstype,%customroles) = @_;
2022: my $output;
2023: my $custom = 1;
2024: my @roles = &course_roles($context,$checkpriv,$custom,lc($crstype));
2025: foreach my $role (@roles) {
2026: if ($role ne 'cr') {
2027: my $plrole=&Apache::lonnet::plaintext($role,$crstype);
2028: $output .= ' <option value="'.$role.'">'.$plrole.'</option>';
2029: }
2030: }
2031: if (keys(%customroles) > 0) {
2032: if (grep(/^cr$/,@roles)) {
2033: foreach my $cust (sort(keys(%customroles))) {
2034: my $custrole='cr_'.$env{'user.domain'}.
2035: '_'.$env{'user.name'}.'_'.$cust;
2036: $output .= ' <option value="'.$custrole.'">'.$cust.'</option>';
2037: }
2038: }
2039: }
2040: return $output;
2041: }
2042:
2043: sub construction_space_roles {
2044: my ($checkpriv) = @_;
2045: my @allroles = &roles_by_context('author');
2046: my @roles;
2047: if ($checkpriv) {
2048: foreach my $role (@allroles) {
2049: if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) {
2050: push(@roles,$role);
2051: }
2052: }
2053: return @roles;
2054: } else {
2055: return @allroles;
2056: }
2057: }
2058:
2059: sub domain_roles {
2060: my ($checkpriv) = @_;
2061: my @allroles = &roles_by_context('domain');
2062: my @roles;
2063: if ($checkpriv) {
2064: foreach my $role (@allroles) {
2065: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
2066: push(@roles,$role);
2067: }
2068: }
2069: return @roles;
2070: } else {
2071: return @allroles;
2072: }
2073: }
2074:
2075: sub course_roles {
2076: my ($context,$checkpriv,$custom,$roletype) = @_;
2077: my $crstype;
2078: if ($roletype eq 'community') {
2079: $crstype = 'Community' ;
2080: } else {
2081: $crstype = 'Course';
2082: }
2083: my @allroles = &roles_by_context('course',$custom,$crstype);
2084: my @roles;
2085: if ($context eq 'domain') {
2086: @roles = @allroles;
2087: } elsif ($context eq 'course') {
2088: if ($env{'request.course.id'}) {
2089: if ($checkpriv) {
2090: foreach my $role (@allroles) {
2091: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
2092: push(@roles,$role);
2093: } else {
2094: if ((($role ne 'cc') && ($role ne 'co')) && ($env{'request.course.sec'} ne '')) {
2095: if (&Apache::lonnet::allowed('c'.$role,
2096: $env{'request.course.id'}.'/'.
2097: $env{'request.course.sec'})) {
2098: push(@roles,$role);
2099: }
2100: }
2101: }
2102: }
2103: } else {
2104: @roles = @allroles;
2105: }
2106: }
2107: }
2108: return @roles;
2109: }
2110:
2111: sub curr_role_permissions {
2112: my ($context,$setting,$checkpriv,$type) = @_;
2113: my $custom = 1;
2114: my @roles;
2115: if ($context eq 'author') {
2116: @roles = &construction_space_roles($checkpriv);
2117: } elsif ($context eq 'domain') {
2118: if ($setting eq 'course') {
2119: @roles = &course_roles($context,$checkpriv,$custom,$type);
2120: } else {
2121: @roles = &domain_roles($checkpriv);
2122: }
2123: } elsif ($context eq 'course') {
2124: @roles = &course_roles($context,$checkpriv,$custom,$type);
2125: }
2126: return @roles;
2127: }
2128:
2129: # ======================================================= Existing Custom Roles
2130:
2131: sub my_custom_roles {
2132: my ($crstype,$udom,$uname) = @_;
2133: my %returnhash=();
2134: my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
2135: my %rolehash=&Apache::lonnet::dump('roles',$udom,$uname);
2136: foreach my $key (keys(%rolehash)) {
2137: if ($key=~/^rolesdef\_(\w+)$/) {
2138: my $role = $1;
2139: if ($crstype eq 'Community') {
2140: next if ($rolehash{$key} =~ /bre\&S/);
2141: }
2142: $returnhash{$role}=$role;
2143: }
2144: }
2145: return %returnhash;
2146: }
2147:
2148: sub print_userlist {
2149: my ($r,$mode,$permission,$context,$formname,$totcodes,$codetitles,
2150: $idlist,$idlist_titles,$showcredits) = @_;
2151: my $format = $env{'form.output'};
2152: if (! exists($env{'form.sortby'})) {
2153: $env{'form.sortby'} = 'username';
2154: }
2155: if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) {
2156: $env{'form.Status'} = 'Active';
2157: }
2158: my $onchange = "javascript:updateCols('Status');";
2159: my $status_select = &Apache::lonhtmlcommon::StatusOptions
2160: ($env{'form.Status'},undef,undef,$onchange);
2161:
2162: if ($env{'form.showrole'} eq '') {
2163: if ($context eq 'course') {
2164: $env{'form.showrole'} = 'st';
2165: } else {
2166: $env{'form.showrole'} = 'Any';
2167: }
2168: }
2169: if (! defined($env{'form.output'}) ||
2170: $env{'form.output'} !~ /^(csv|excel|html)$/ ) {
2171: $env{'form.output'} = 'html';
2172: }
2173:
2174: my @statuses;
2175: if ($env{'form.Status'} eq 'Any') {
2176: @statuses = ('previous','active','future');
2177: } elsif ($env{'form.Status'} eq 'Expired') {
2178: @statuses = ('previous');
2179: } elsif ($env{'form.Status'} eq 'Active') {
2180: @statuses = ('active');
2181: } elsif ($env{'form.Status'} eq 'Future') {
2182: @statuses = ('future');
2183: }
2184:
2185: # Interface output
2186: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
2187: '<input type="hidden" name="action" value="'.
2188: $env{'form.action'}.'" />');
2189: $r->print('<div>'."\n");
2190: if ($env{'form.action'} ne 'modifystudent') {
2191: my %lt=&Apache::lonlocal::texthash('csv' => "CSV",
2192: 'excel' => "Excel",
2193: 'html' => 'HTML');
2194: my $output_selector = '<select size="1" name="output" onchange="javascript:updateCols('."'output'".');" >';
2195: foreach my $outputformat ('html','csv','excel') {
2196: my $option = '<option value="'.$outputformat.'"';
2197: if ($outputformat eq $env{'form.output'}) {
2198: $option .= ' selected="selected"';
2199: }
2200: $option .='>'.$lt{$outputformat}.'</option>';
2201: $output_selector .= "\n".$option;
2202: }
2203: $output_selector .= '</select>';
2204: $r->print('<span class="LC_nobreak">'
2205: .&mt('Output Format: [_1]',$output_selector)
2206: .'</span>'.(' 'x3));
2207: }
2208: $r->print('<span class="LC_nobreak">'
2209: .&mt('User Status: [_1]',$status_select)
2210: .'</span>'.(' 'x3)."\n");
2211: my $roleselected = '';
2212: if ($env{'form.showrole'} eq 'Any') {
2213: $roleselected = ' selected="selected"';
2214: }
2215: my ($cnum,$cdom);
2216: $r->print(&role_filter($context));
2217: if ($context eq 'course') {
2218: ($cnum,$cdom) = &get_course_identity();
2219: $r->print(§ion_group_filter($cnum,$cdom));
2220: }
2221: $r->print('</div><div class="LC_left_float">'.
2222: &column_checkboxes($context,$mode,$formname,$showcredits).
2223: '</div>');
2224: if ($env{'form.phase'} eq '') {
2225: $r->print('<br clear="all" />'.
2226: &list_submit_button(&mt('Display List of Users'))."\n".
2227: '<input type="hidden" name="phase" value="" /></form>');
2228: return;
2229: }
2230: if (!(($context eq 'domain') &&
2231: (($env{'form.roletype'} eq 'course') || ($env{'form.roletype'} eq 'community')))) {
2232: $r->print('<br clear="all" />'.
2233: &list_submit_button(&mt('Update Display'))."\n");
2234: }
2235:
2236: my @cols = &infocolumns($context,$mode,$showcredits);
2237: if (!@cols) {
2238: $r->print('<hr style="clear:both;" /><span class="LC_warning">'.
2239: &mt('No user information selected for display.').'</span>'.
2240: '<input type="hidden" name="phase" value="display" /></form>'."\n");
2241: return;
2242: }
2243: my ($indexhash,$keylist) = &make_keylist_array();
2244: my (%userlist,%userinfo,$clearcoursepick,$needauthorquota,$needauthorusage);
2245: if (($context eq 'domain') &&
2246: ($env{'form.roletype'} eq 'course') ||
2247: ($env{'form.roletype'} eq 'community')) {
2248: my ($crstype,$numcodes,$title,$warning);
2249: if ($env{'form.roletype'} eq 'course') {
2250: $crstype = 'Course';
2251: $numcodes = $totcodes;
2252: $title = &mt('Select Courses');
2253: $warning = &mt('Warning: data retrieval for multiple courses can take considerable time, as this operation is not currently optimized.');
2254: } elsif ($env{'form.roletype'} eq 'community') {
2255: $crstype = 'Community';
2256: $numcodes = 0;
2257: $title = &mt('Select Communities');
2258: $warning = &mt('Warning: data retrieval for multiple communities can take considerable time, as this operation is not currently optimized.');
2259: }
2260: my @standardnames = &Apache::loncommon::get_standard_codeitems();
2261: my $courseform =
2262: &Apache::lonhtmlcommon::course_selection($formname,$numcodes,
2263: $codetitles,$idlist,$idlist_titles,$crstype,
2264: \@standardnames);
2265: $r->print('<div class="LC_left_float">'.
2266: '<fieldset><legend>'.$title.'</legend>'."\n".
2267: $courseform."\n".
2268: '</fieldset></div><br clear="all" />'.
2269: '<p><input type="hidden" name="origroletype" value="'.$env{'form.roletype'}.'" />'.
2270: &list_submit_button(&mt('Update Display')).
2271: "\n".'</p><span class="LC_warning">'.$warning.'</span>'."\n");
2272: $clearcoursepick = 0;
2273: if (($env{'form.origroletype'} ne '') &&
2274: ($env{'form.origroletype'} ne $env{'form.roletype'})) {
2275: $clearcoursepick = 1;
2276: }
2277: if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
2278: $r->print('<hr />'.&mt('Searching ...').'<br /> <br />');
2279: }
2280: } else {
2281: $r->print('<hr style="clear:both;" /><div id="searching">'.&mt('Searching ...').'</div>');
2282: }
2283: $r->rflush();
2284: if ($context eq 'course') {
2285: if (($env{'form.showrole'} eq 'st') || ($env{'form.showrole'} eq 'Any')) {
2286: my $classlist = &Apache::loncoursedata::get_classlist();
2287: if (ref($classlist) eq 'HASH') {
2288: %userlist = %{$classlist};
2289: }
2290: }
2291: if ($env{'form.showrole'} ne 'st') {
2292: my $showroles;
2293: if ($env{'form.showrole'} ne 'Any') {
2294: $showroles = [$env{'form.showrole'}];
2295: } else {
2296: $showroles = undef;
2297: }
2298: my $withsec = 1;
2299: my $hidepriv = 1;
2300: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
2301: \@statuses,$showroles,undef,$withsec,$hidepriv);
2302: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
2303: \%advrolehash,$permission);
2304: }
2305: } else {
2306: my (%cstr_roles,%dom_roles);
2307: if ($context eq 'author') {
2308: # List co-authors and assistant co-authors
2309: my @possroles = &roles_by_context($context);
2310: %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
2311: \@statuses,\@possroles);
2312: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
2313: \%cstr_roles,$permission);
2314: } elsif ($context eq 'domain') {
2315: if ($env{'form.roletype'} eq 'domain') {
2316: if (grep(/^authorusage$/,@cols)) {
2317: $needauthorusage = 1;
2318: }
2319: if (grep(/^authorquota$/,@cols)) {
2320: $needauthorquota = 1;
2321: }
2322: %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'});
2323: foreach my $key (keys(%dom_roles)) {
2324: if (ref($dom_roles{$key}) eq 'HASH') {
2325: &gather_userinfo($context,$format,\%userlist,$indexhash,
2326: \%userinfo,$dom_roles{$key},$permission);
2327: }
2328: }
2329: } elsif ($env{'form.roletype'} eq 'author') {
2330: my %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'},['au']);
2331: my %coauthors;
2332: foreach my $key (keys(%dom_roles)) {
2333: if (ref($dom_roles{$key}) eq 'HASH') {
2334: if ($env{'form.showrole'} eq 'au') {
2335: &gather_userinfo($context,$format,\%userlist,$indexhash,
2336: \%userinfo,$dom_roles{$key},$permission);
2337: } else {
2338: my @possroles;
2339: if ($env{'form.showrole'} eq 'Any') {
2340: @possroles = &roles_by_context('author');
2341: } else {
2342: @possroles = ($env{'form.showrole'});
2343: }
2344: foreach my $author (sort(keys(%{$dom_roles{$key}}))) {
2345: my ($role,$authorname,$authordom) = split(/:/,$author,-1);
2346: my $extent = '/'.$authordom.'/'.$authorname;
2347: %{$coauthors{$extent}} =
2348: &Apache::lonnet::get_my_roles($authorname,
2349: $authordom,undef,\@statuses,\@possroles);
2350: }
2351: &gather_userinfo($context,$format,\%userlist,
2352: $indexhash,\%userinfo,\%coauthors,$permission);
2353: }
2354: }
2355: }
2356: } elsif (($env{'form.roletype'} eq 'course') ||
2357: ($env{'form.roletype'} eq 'community')) {
2358: if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
2359: my %courses = &process_coursepick();
2360: my %allusers;
2361: my $hidepriv = 1;
2362: foreach my $cid (keys(%courses)) {
2363: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
2364: next if ($cnum eq '' || $cdom eq '');
2365: my $custom = 1;
2366: my (@roles,@sections,%access,%users,%userdata,
2367: %statushash);
2368: if ($env{'form.showrole'} eq 'Any') {
2369: @roles = &course_roles($context,undef,$custom,
2370: $env{'form.roletype'});
2371: } else {
2372: @roles = ($env{'form.showrole'});
2373: }
2374: foreach my $role (@roles) {
2375: %{$users{$role}} = ();
2376: }
2377: foreach my $type (@statuses) {
2378: $access{$type} = $type;
2379: }
2380: &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\@sections,\%users,\%userdata,\%statushash,$hidepriv);
2381: foreach my $user (keys(%userdata)) {
2382: next if (ref($userinfo{$user}) eq 'HASH');
2383: foreach my $item ('fullname','id') {
2384: $userinfo{$user}{$item} = $userdata{$user}[$indexhash->{$item}];
2385: }
2386: }
2387: foreach my $role (keys(%users)) {
2388: foreach my $user (keys(%{$users{$role}})) {
2389: my $uniqid = $user.':'.$role;
2390: $allusers{$uniqid}{$cid} = { desc => $cdesc,
2391: secs => $statushash{$user}{$role},
2392: };
2393: }
2394: }
2395: }
2396: &gather_userinfo($context,$format,\%userlist,$indexhash,
2397: \%userinfo,\%allusers,$permission);
2398: } else {
2399: $r->print('<input type="hidden" name="phase" value="'.
2400: $env{'form.phase'}.'" /></form>');
2401: return;
2402: }
2403: }
2404: }
2405: }
2406: if (keys(%userlist) == 0) {
2407: my $msg = '';
2408: if ($context eq 'author') {
2409: $msg = &mt('There are no co-authors to display.');
2410: } elsif ($context eq 'domain') {
2411: if ($env{'form.roletype'} eq 'domain') {
2412: $msg = &mt('There are no users with domain roles to display.');
2413: } elsif ($env{'form.roletype'} eq 'author') {
2414: $msg = &mt('There are no authors or co-authors to display.');
2415: } elsif ($env{'form.roletype'} eq 'course') {
2416: $msg = &mt('There are no course users to display');
2417: } elsif ($env{'form.roletype'} eq 'community') {
2418: $msg = &mt('There are no community users to display');
2419: }
2420: } elsif ($context eq 'course') {
2421: $r->print(&mt('There are no course users to display.')."\n");
2422: }
2423: $r->print('<p class="LC_info">'.$msg.'</p>'."\n") if $msg;
2424: } else {
2425: # Print out the available choices
2426: my $usercount;
2427: if ($env{'form.action'} eq 'modifystudent') {
2428: ($usercount) = &show_users_list($r,$context,'view',$permission,
2429: $env{'form.Status'},\%userlist,$keylist,'',
2430: $showcredits);
2431: } else {
2432: ($usercount) = &show_users_list($r,$context,$env{'form.output'},
2433: $permission,$env{'form.Status'},\%userlist,
2434: $keylist,'',$showcredits,$needauthorquota,$needauthorusage);
2435: }
2436: if (!$usercount) {
2437: $r->print('<br /><span class="LC_info">'
2438: .&mt('There are no users matching the search criteria.')
2439: .'</span>'
2440: );
2441: }
2442: }
2443: $r->print('<input type="hidden" name="phase" value="'.
2444: $env{'form.phase'}.'" /></form>');
2445: return;
2446: }
2447:
2448: sub role_filter {
2449: my ($context) = @_;
2450: my $output;
2451: my $roleselected = '';
2452: if ($env{'form.showrole'} eq 'Any') {
2453: $roleselected = ' selected="selected"';
2454: }
2455: my ($role_select);
2456: if ($context eq 'domain') {
2457: $role_select = &domain_roles_select();
2458: $output = '<span class="LC_nobreak">'
2459: .&mt('Role Type: [_1]',$role_select)
2460: .'</span>';
2461: } else {
2462: $role_select = '<select name="showrole" onchange="javascript:updateCols('."'showrole'".');">'."\n".
2463: '<option value="Any" '.$roleselected.'>'.
2464: &mt('Any role').'</option>';
2465: my ($roletype,$crstype);
2466: if ($context eq 'course') {
2467: $crstype = &Apache::loncommon::course_type();
2468: if ($crstype eq 'Community') {
2469: $roletype = 'community';
2470: } else {
2471: $roletype = 'course';
2472: }
2473: }
2474: my @poss_roles = &curr_role_permissions($context,'','',$roletype);
2475: foreach my $role (@poss_roles) {
2476: $roleselected = '';
2477: if ($role eq $env{'form.showrole'}) {
2478: $roleselected = ' selected="selected"';
2479: }
2480: my $plrole;
2481: if ($role eq 'cr') {
2482: $plrole = &mt('Custom role');
2483: } else {
2484: $plrole=&Apache::lonnet::plaintext($role,$crstype);
2485: }
2486: $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>';
2487: }
2488: $role_select .= '</select>';
2489: $output = '<span class="LC_nobreak">'
2490: .&mt('Role: [_1]',$role_select)
2491: .'</span>';
2492: }
2493: return $output;
2494: }
2495:
2496: sub section_group_filter {
2497: my ($cnum,$cdom) = @_;
2498: my @filters;
2499: if ($env{'request.course.sec'} eq '') {
2500: @filters = ('sec');
2501: }
2502: push(@filters,'grp');
2503: my %name = (
2504: sec => 'secfilter',
2505: grp => 'grpfilter',
2506: );
2507: my %title = &Apache::lonlocal::texthash (
2508: sec => 'Section(s)',
2509: grp => 'Group(s)',
2510: all => 'all',
2511: none => 'none',
2512: );
2513: my $output;
2514: foreach my $item (@filters) {
2515: my ($markup,@options);
2516: if ($env{'form.'.$name{$item}} eq '') {
2517: $env{'form.'.$name{$item}} = 'all';
2518: }
2519: if ($item eq 'sec') {
2520: if (($env{'form.showrole'} eq 'cc') || ($env{'form.showrole'} eq 'co')) {
2521: $env{'form.'.$name{$item}} = 'none';
2522: }
2523: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
2524: @options = sort(keys(%sections_count));
2525: } elsif ($item eq 'grp') {
2526: my %curr_groups = &Apache::longroup::coursegroups();
2527: @options = sort(keys(%curr_groups));
2528: }
2529: if (@options > 0) {
2530: my $currsel;
2531: $markup = '<select name="'.$name{$item}.'">'."\n";
2532: foreach my $option ('all','none',@options) {
2533: $currsel = '';
2534: if ($env{'form.'.$name{$item}} eq $option) {
2535: $currsel = ' selected="selected"';
2536: }
2537: $markup .= ' <option value="'.$option.'"'.$currsel.'>';
2538: if (($option eq 'all') || ($option eq 'none')) {
2539: $markup .= $title{$option};
2540: } else {
2541: $markup .= $option;
2542: }
2543: $markup .= '</option>'."\n";
2544: }
2545: $markup .= '</select>'."\n";
2546: $output .= (' 'x3).'<span class="LC_nobreak">'
2547: .'<label>'.$title{$item}.': '.$markup.'</label>'
2548: .'</span> ';
2549: }
2550: }
2551: return $output;
2552: }
2553:
2554: sub infocolumns {
2555: my ($context,$mode,$showcredits) = @_;
2556: my @cols;
2557: if (($mode eq 'pickauthor') || ($mode eq 'autoenroll')) {
2558: @cols = &get_cols_array($context,$mode,$showcredits);
2559: } else {
2560: my @posscols = &get_cols_array($context,$mode,$showcredits);
2561: if ($env{'form.phase'} ne '') {
2562: my @checkedcols = &Apache::loncommon::get_env_multiple('form.showcol');
2563: foreach my $col (@checkedcols) {
2564: if (grep(/^$col$/,@posscols)) {
2565: push(@cols,$col);
2566: }
2567: }
2568: } else {
2569: @cols = @posscols;
2570: }
2571: }
2572: return @cols;
2573: }
2574:
2575: sub get_cols_array {
2576: my ($context,$mode,$showcredits) = @_;
2577: my @cols;
2578: if ($mode eq 'pickauthor') {
2579: @cols = ('username','fullname','status','email');
2580: } else {
2581: @cols = ('username','domain','id','fullname');
2582: if ($context eq 'course') {
2583: push(@cols,'section');
2584: }
2585: push(@cols,('start','end','role'));
2586: unless (($mode eq 'autoenroll') && ($env{'form.Status'} ne 'Any')) {
2587: push(@cols,'status');
2588: }
2589: if ($context eq 'course') {
2590: push(@cols,'groups');
2591: }
2592: push(@cols,'email');
2593: if (($context eq 'course') && ($mode ne 'autoenroll')) {
2594: if ($showcredits) {
2595: push(@cols,'credits');
2596: }
2597: push(@cols,'lastlogin','clicker');
2598: }
2599: if (($context eq 'course') && ($mode ne 'autoenroll') &&
2600: ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'})) {
2601: push(@cols,'photo');
2602: }
2603: if ($context eq 'domain') {
2604: push (@cols,('authorusage','authorquota','extent'));
2605: }
2606: }
2607: return @cols;
2608: }
2609:
2610: sub column_checkboxes {
2611: my ($context,$mode,$formname,$showcredits) = @_;
2612: my @cols = &get_cols_array($context,$mode,$showcredits);
2613: my @showncols = &Apache::loncommon::get_env_multiple('form.showcol');
2614: my (%disabledchk,%unchecked);
2615: if ($env{'form.phase'} eq '') {
2616: $disabledchk{'status'} = 1;
2617: if ($context eq 'course') {
2618: $disabledchk{'role'} = 1;
2619: $unchecked{'photo'} = 1;
2620: $unchecked{'clicker'} = 1;
2621: if ($showcredits) {
2622: $unchecked{'credits'} = 1;
2623: }
2624: } elsif ($context eq 'domain') {
2625: $unchecked{'extent'} = 1;
2626: }
2627: $unchecked{'start'} = 1;
2628: $unchecked{'end'} = 1;
2629: } else {
2630: if ($env{'form.Status'} ne 'Any') {
2631: $disabledchk{'status'} = 1;
2632: }
2633: if (($env{'form.showrole'} ne 'Any') && ($env{'form.showrole'} ne 'cr')) {
2634: $disabledchk{'role'} = 1;
2635: }
2636: if ($context eq 'domain') {
2637: if (($env{'form.roletype'} eq 'course') ||
2638: ($env{'form.roletype'} eq 'community')) {
2639: $disabledchk{'status'} = 1;
2640: $disabledchk{'authorusage'} = 1;
2641: $disabledchk{'authorquota'} = 1;
2642: } elsif ($env{'form.roletype'} eq 'domain') {
2643: $disabledchk{'extent'} = 1;
2644: }
2645: }
2646: }
2647: my $numposs = scalar(@cols);
2648: my $numinrow = 7;
2649: my %lt = &get_column_names($context);
2650: my $output = '<fieldset><legend>'.&mt('Information to show').'</legend>'."\n".'<span class="LC_nobreak">'.
2651: '<input type="button" onclick="javascript:checkAll(document.'.$formname.'.showcol);" value="'.&mt('check all').'" />'.
2652: (' 'x3).
2653: '<input type="button" onclick="javascript:uncheckAll(document.'.$formname.'.showcol);" value="'.&mt('uncheck all').'" />'.
2654: '</span><table>';
2655:
2656: for (my $i=0; $i<$numposs; $i++) {
2657: my $rem = $i%($numinrow);
2658: if ($rem == 0) {
2659: if ($i > 0) {
2660: $output .= '</tr>';
2661: }
2662: $output .= '<tr>';
2663: }
2664: my $checked;
2665: if ($env{'form.phase'} eq '') {
2666: $checked = ' checked="checked"';
2667: if ($unchecked{$cols[$i]}) {
2668: $checked = '';
2669: }
2670: if ($disabledchk{$cols[$i]}) {
2671: $checked = ' disabled="disabled"';
2672: }
2673: } elsif (grep(/^\Q$cols[$i]\E$/,@showncols)) {
2674: $checked = ' checked="checked"';
2675: } elsif ($disabledchk{$cols[$i]}) {
2676: $checked = ' disabled="disabled"';
2677: }
2678: if ($i == $numposs-1) {
2679: my $colsleft = $numinrow-$rem;
2680: if ($colsleft > 1) {
2681: $output .= '<td colspan="'.$colsleft.'">';
2682: } else {
2683: $output .= '<td>';
2684: }
2685: } else {
2686: $output .= '<td>';
2687: }
2688: my $style;
2689: if ($cols[$i] eq 'extent') {
2690: if (($env{'form.roletype'} eq 'domain') || ($env{'form.roletype'} eq '')) {
2691: $style = ' style="display: none;"';
2692: }
2693: } elsif (($cols[$i] eq 'authorusage') || ($cols[$i] eq 'authorquota')) {
2694: if ($env{'form.roletype'} ne 'domain') {
2695: $style = ' style="display: none;"';
2696: }
2697: }
2698: $output .= '<span id="show'.$cols[$i].'"'.$style.'><label>'.
2699: '<input id="showcol'.$cols[$i].'" type="checkbox" name="showcol" value="'.$cols[$i].'"'.$checked.' /><span id="showcoltext'.$cols[$i].'">'.
2700: $lt{$cols[$i]}.'</span>'.
2701: '</label></span></td>';
2702: }
2703: $output .= '</tr></table></fieldset>';
2704: return $output;
2705: }
2706:
2707: sub list_submit_button {
2708: my ($text) = @_;
2709: return '<input type="button" name="updatedisplay" value="'.$text.'" onclick="javascript:display_update()" />';
2710: }
2711:
2712: sub get_column_names {
2713: my ($context) = @_;
2714: my %lt = &Apache::lonlocal::texthash(
2715: 'username' => "username",
2716: 'domain' => "domain",
2717: 'id' => 'ID',
2718: 'fullname' => "name",
2719: 'section' => "section",
2720: 'groups' => "active groups",
2721: 'start' => "start date",
2722: 'end' => "end date",
2723: 'status' => "status",
2724: 'role' => "role",
2725: 'credits' => "credits",
2726: 'type' => "enroll type/action",
2727: 'email' => "e-mail address",
2728: 'photo' => "photo",
2729: 'lastlogin' => "last login",
2730: 'extent' => "extent",
2731: 'authorusage' => "disk usage (%)",
2732: 'authorquota' => "disk quota (MB)",
2733: 'ca' => "check all",
2734: 'ua' => "uncheck all",
2735: 'clicker' => "clicker-ID",
2736: );
2737: if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
2738: $lt{'extent'} = &mt('course(s): description, section(s), status');
2739: } elsif ($context eq 'domain' && $env{'form.roletype'} eq 'community') {
2740: $lt{'extent'} = &mt('community(s): description, section(s), status');
2741: } elsif (($context eq 'author') ||
2742: ($context eq 'domain' && $env{'form.roletype'} eq 'author')) {
2743: $lt{'extent'} = &mt('author');
2744: }
2745: return %lt;
2746: }
2747:
2748: sub gather_userinfo {
2749: my ($context,$format,$userlist,$indexhash,$userinfo,$rolehash,$permission) = @_;
2750: my $viewablesec;
2751: if ($context eq 'course') {
2752: $viewablesec = &viewable_section($permission);
2753: }
2754: foreach my $item (keys(%{$rolehash})) {
2755: my %userdata;
2756: if ($context eq 'author') {
2757: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
2758: split(/:/,$item);
2759: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
2760: &build_user_record($context,\%userdata,$userinfo,$indexhash,
2761: $item,$userlist);
2762: } elsif ($context eq 'course') {
2763: ($userdata{'username'},$userdata{'domain'},$userdata{'role'},
2764: $userdata{'section'}) = split(/:/,$item,-1);
2765: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
2766: if (($viewablesec ne '') && ($userdata{'section'} ne '')) {
2767: next if ($viewablesec ne $userdata{'section'});
2768: }
2769: &build_user_record($context,\%userdata,$userinfo,$indexhash,
2770: $item,$userlist);
2771: } elsif ($context eq 'domain') {
2772: if ($env{'form.roletype'} eq 'domain') {
2773: ($userdata{'role'},$userdata{'username'},$userdata{'domain'}) =
2774: split(/:/,$item);
2775: ($userdata{'end'},$userdata{'start'})=split(/:/,$rolehash->{$item});
2776: &build_user_record($context,\%userdata,$userinfo,$indexhash,
2777: $item,$userlist);
2778: } elsif ($env{'form.roletype'} eq 'author') {
2779: if (ref($rolehash->{$item}) eq 'HASH') {
2780: $userdata{'extent'} = $item;
2781: foreach my $key (keys(%{$rolehash->{$item}})) {
2782: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) = split(/:/,$key);
2783: ($userdata{'start'},$userdata{'end'}) =
2784: split(/:/,$rolehash->{$item}{$key});
2785: my $uniqid = $key.':'.$item;
2786: &build_user_record($context,\%userdata,$userinfo,
2787: $indexhash,$uniqid,$userlist);
2788: }
2789: }
2790: } elsif (($env{'form.roletype'} eq 'course') ||
2791: ($env{'form.roletype'} eq 'community')) {
2792: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
2793: split(/:/,$item);
2794: if (ref($rolehash->{$item}) eq 'HASH') {
2795: my $numcids = keys(%{$rolehash->{$item}});
2796: foreach my $cid (sort(keys(%{$rolehash->{$item}}))) {
2797: if (ref($rolehash->{$item}{$cid}) eq 'HASH') {
2798: my $spanstart = '';
2799: my $spanend = '; ';
2800: my $space = ', ';
2801: if ($format eq 'html' || $format eq 'view') {
2802: $spanstart = '<span class="LC_nobreak">';
2803: # FIXME: actions on courses disabled for now
2804: # if ($permission->{'cusr'}) {
2805: # if ($numcids > 1) {
2806: # $spanstart .= '<input type="radio" name="'.$item.'" value="'.$cid.'" /> ';
2807: # } else {
2808: # $spanstart .= '<input type="hidden" name="'.$item.'" value="'.$cid.'" /> ';
2809: # }
2810: # }
2811: $spanend = '</span><br />';
2812: $space = ', ';
2813: }
2814: $userdata{'extent'} .= $spanstart.
2815: $rolehash->{$item}{$cid}{'desc'}.$space;
2816: if (ref($rolehash->{$item}{$cid}{'secs'}) eq 'HASH') {
2817: foreach my $sec (sort(keys(%{$rolehash->{$item}{$cid}{'secs'}}))) {
2818: if (($env{'form.Status'} eq 'Any') ||
2819: ($env{'form.Status'} eq $rolehash->{$item}{$cid}{'secs'}{$sec})) {
2820: $userdata{'extent'} .= $sec.$space.$rolehash->{$item}{$cid}{'secs'}{$sec}.$spanend;
2821: $userdata{'status'} = $rolehash->{$item}{$cid}{'secs'}{$sec};
2822: }
2823: }
2824: }
2825: }
2826: }
2827: }
2828: if ($userdata{'status'} ne '') {
2829: &build_user_record($context,\%userdata,$userinfo,
2830: $indexhash,$item,$userlist);
2831: }
2832: }
2833: }
2834: }
2835: return;
2836: }
2837:
2838: sub build_user_record {
2839: my ($context,$userdata,$userinfo,$indexhash,$record_key,$userlist) = @_;
2840: next if ($userdata->{'start'} eq '-1' && $userdata->{'end'} eq '-1');
2841: if (!(($context eq 'domain') && (($env{'form.roletype'} eq 'course')
2842: && ($env{'form.roletype'} eq 'community')))) {
2843: &process_date_info($userdata);
2844: }
2845: my $username = $userdata->{'username'};
2846: my $domain = $userdata->{'domain'};
2847: if (ref($userinfo->{$username.':'.$domain}) eq 'HASH') {
2848: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
2849: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
2850: } else {
2851: &aggregate_user_info($domain,$username,$userinfo);
2852: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
2853: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
2854: }
2855: foreach my $key (keys(%{$indexhash})) {
2856: if (defined($userdata->{$key})) {
2857: $userlist->{$record_key}[$indexhash->{$key}] = $userdata->{$key};
2858: }
2859: }
2860: return;
2861: }
2862:
2863: sub courses_selector {
2864: my ($cdom,$formname) = @_;
2865: my %codes = ();
2866: my @codetitles = ();
2867: my %cat_titles = ();
2868: my %cat_order = ();
2869: my %idlist = ();
2870: my %idnums = ();
2871: my %idlist_titles = ();
2872: my $caller = 'global';
2873: my $format_reply;
2874: my $jscript = '';
2875:
2876: my $totcodes = 0;
2877: my $instcats = &Apache::lonnet::get_dom_instcats($cdom);
2878: if (ref($instcats) eq 'HASH') {
2879: if ((ref($instcats->{'codetitles'}) eq 'ARRAY') && (ref($instcats->{'codes'}) eq 'HASH') &&
2880: (ref($instcats->{'cat_titles'}) eq 'HASH') && (ref($instcats->{'cat_order'}) eq 'HASH')) {
2881: %codes = %{$instcats->{'codes'}};
2882: @codetitles = @{$instcats->{'codetitles'}};
2883: %cat_titles = %{$instcats->{'cat_titles'}};
2884: %cat_order = %{$instcats->{'cat_order'}};
2885: $totcodes = scalar(keys(%codes));
2886: my $numtypes = @codetitles;
2887: &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
2888: my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
2889: my $longtitles_str = join('","',@{$longtitles});
2890: my $allidlist = $idlist{$codetitles[0]};
2891: $jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist);
2892: $jscript .= $scripttext;
2893: $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,\@codetitles);
2894: }
2895: }
2896: my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom);
2897:
2898: my %elements = (
2899: Year => 'selectbox',
2900: coursepick => 'radio',
2901: coursetotal => 'text',
2902: courselist => 'text',
2903: );
2904: $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements);
2905: if ($env{'form.coursepick'} eq 'category') {
2906: $jscript .= qq|
2907: function setCourseCat(formname) {
2908: if (formname.Year.options[formname.Year.selectedIndex].value == -1) {
2909: return;
2910: }
2911: courseSet('$codetitles[0]');
2912: for (var j=0; j<formname.Semester.length; j++) {
2913: if (formname.Semester.options[j].value == "$env{'form.Semester'}") {
2914: formname.Semester.options[j].selected = true;
2915: }
2916: }
2917: if (formname.Semester.options[formname.Semester.selectedIndex].value == -1) {
2918: return;
2919: }
2920: courseSet('$codetitles[1]');
2921: for (var j=0; j<formname.Department.length; j++) {
2922: if (formname.Department.options[j].value == "$env{'form.Department'}") {
2923: formname.Department.options[j].selected = true;
2924: }
2925: }
2926: if (formname.Department.options[formname.Department.selectedIndex].value == -1) {
2927: return;
2928: }
2929: courseSet('$codetitles[2]');
2930: for (var j=0; j<formname.Number.length; j++) {
2931: if (formname.Number.options[j].value == "$env{'form.Number'}") {
2932: formname.Number.options[j].selected = true;
2933: }
2934: }
2935: }
2936: |;
2937: }
2938: return ($cb_jscript,$jscript,$totcodes,\@codetitles,\%idlist,
2939: \%idlist_titles);
2940: }
2941:
2942: sub course_selector_loadcode {
2943: my ($formname) = @_;
2944: my $loadcode;
2945: if ($env{'form.coursepick'} ne '') {
2946: $loadcode = 'javascript:setFormElements(document.'.$formname.')';
2947: if ($env{'form.coursepick'} eq 'category') {
2948: $loadcode .= ';javascript:setCourseCat(document.'.$formname.')';
2949: }
2950: }
2951: return $loadcode;
2952: }
2953:
2954: sub process_coursepick {
2955: my $coursefilter = $env{'form.coursepick'};
2956: my $cdom = $env{'request.role.domain'};
2957: my %courses;
2958: my $crssrch = 'Course';
2959: if ($env{'form.roletype'} eq 'community') {
2960: $crssrch = 'Community';
2961: }
2962: if ($coursefilter eq 'all') {
2963: %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.',
2964: undef,undef,$crssrch);
2965: } elsif ($coursefilter eq 'category') {
2966: my $instcode = &instcode_from_coursefilter();
2967: %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.',
2968: undef,undef,$crssrch);
2969: } elsif ($coursefilter eq 'specific') {
2970: if ($env{'form.coursetotal'} > 1) {
2971: my @course_ids = split(/&&/,$env{'form.courselist'});
2972: foreach my $cid (@course_ids) {
2973: $courses{$cid} = '';
2974: }
2975: } else {
2976: $courses{$env{'form.courselist'}} = '';
2977: }
2978: }
2979: return %courses;
2980: }
2981:
2982: sub instcode_from_coursefilter {
2983: my $instcode = '';
2984: my @cats = ('Semester','Year','Department','Number');
2985: foreach my $category (@cats) {
2986: if (defined($env{'form.'.$category})) {
2987: unless ($env{'form.'.$category} eq '-1') {
2988: $instcode .= $env{'form.'.$category};
2989: }
2990: }
2991: }
2992: if ($instcode eq '') {
2993: $instcode = '.';
2994: }
2995: return $instcode;
2996: }
2997:
2998: sub make_keylist_array {
2999: my ($index,$keylist);
3000: $index->{'domain'} = &Apache::loncoursedata::CL_SDOM();
3001: $index->{'username'} = &Apache::loncoursedata::CL_SNAME();
3002: $index->{'end'} = &Apache::loncoursedata::CL_END();
3003: $index->{'start'} = &Apache::loncoursedata::CL_START();
3004: $index->{'id'} = &Apache::loncoursedata::CL_ID();
3005: $index->{'section'} = &Apache::loncoursedata::CL_SECTION();
3006: $index->{'fullname'} = &Apache::loncoursedata::CL_FULLNAME();
3007: $index->{'status'} = &Apache::loncoursedata::CL_STATUS();
3008: $index->{'type'} = &Apache::loncoursedata::CL_TYPE();
3009: $index->{'lockedtype'} = &Apache::loncoursedata::CL_LOCKEDTYPE();
3010: $index->{'groups'} = &Apache::loncoursedata::CL_GROUP();
3011: $index->{'email'} = &Apache::loncoursedata::CL_PERMANENTEMAIL();
3012: $index->{'role'} = &Apache::loncoursedata::CL_ROLE();
3013: $index->{'extent'} = &Apache::loncoursedata::CL_EXTENT();
3014: $index->{'photo'} = &Apache::loncoursedata::CL_PHOTO();
3015: $index->{'thumbnail'} = &Apache::loncoursedata::CL_THUMBNAIL();
3016: $index->{'credits'} = &Apache::loncoursedata::CL_CREDITS();
3017: $index->{'instsec'} = &Apache::loncoursedata::CL_INSTSEC();
3018: $index->{'authorquota'} = &Apache::loncoursedata::CL_AUTHORQUOTA();
3019: $index->{'authorusage'} = &Apache::loncoursedata::CL_AUTHORUSAGE();
3020: foreach my $key (keys(%{$index})) {
3021: $keylist->[$index->{$key}] = $key;
3022: }
3023: return ($index,$keylist);
3024: }
3025:
3026: sub aggregate_user_info {
3027: my ($udom,$uname,$userinfo) = @_;
3028: my %info=&Apache::lonnet::get('environment',
3029: ['firstname','middlename',
3030: 'lastname','generation','id'],
3031: $udom,$uname);
3032: my ($tmp) = keys(%info);
3033: my ($fullname,$id);
3034: if ($tmp =~/^(con_lost|error|no_such_host)/i) {
3035: $fullname = 'not available';
3036: $id = 'not available';
3037: &Apache::lonnet::logthis('unable to retrieve environment '.
3038: 'for '.$uname.':'.$udom);
3039: } else {
3040: $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
3041: $id = $info{'id'};
3042: }
3043: $userinfo->{$uname.':'.$udom} = {
3044: fullname => $fullname,
3045: id => $id,
3046: };
3047: return;
3048: }
3049:
3050: sub process_date_info {
3051: my ($userdata) = @_;
3052: my $now = time;
3053: $userdata->{'status'} = 'Active';
3054: if ($userdata->{'start'} > 0) {
3055: if ($now < $userdata->{'start'}) {
3056: $userdata->{'status'} = 'Future';
3057: }
3058: }
3059: if ($userdata->{'end'} > 0) {
3060: if ($now > $userdata->{'end'}) {
3061: $userdata->{'status'} = 'Expired';
3062: }
3063: }
3064: return;
3065: }
3066:
3067: sub show_users_list {
3068: my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist,$formname,
3069: $showcredits,$needauthorquota,$needauthorusage)=@_;
3070: if ($formname eq '') {
3071: $formname = 'studentform';
3072: }
3073: my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
3074: #
3075: # Variables for excel output
3076: my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
3077: #
3078: # Variables for csv output
3079: my ($CSVfile,$CSVfilename);
3080: #
3081: my $sortby = $env{'form.sortby'};
3082: my @sortable = ('username','domain','id','fullname','start','end','email','role');
3083: if ($context eq 'course') {
3084: push(@sortable,('section','groups','type'));
3085: if ($showcredits) {
3086: push(@sortable,'credits');
3087: }
3088: } else {
3089: push(@sortable,'extent');
3090: if (($context eq 'domain') && ($env{'form.roletype'} eq 'domain') &&
3091: (($env{'form.showrole'} eq 'Any') || ($env{'form.showrole'} eq 'au'))) {
3092: push(@sortable,('authorusage','authorquota'));
3093: }
3094: }
3095: if ($mode eq 'pickauthor') {
3096: @sortable = ('username','fullname','email','status');
3097: }
3098: my %is_sortable;
3099: map { $is_sortable{$_} = 1; } @sortable;
3100: unless ($is_sortable{$sortby}) {
3101: $sortby = 'username';
3102: }
3103: my $setting = $env{'form.roletype'};
3104: my ($cid,$cdom,$cnum,$classgroups,$crstype,$defaultcredits);
3105: if ($context eq 'course') {
3106: $cid = $env{'request.course.id'};
3107: $crstype = &Apache::loncommon::course_type();
3108: ($cnum,$cdom) = &get_course_identity($cid);
3109: $defaultcredits = $env{'course.'.$cid.'.internal.defaultcredits'};
3110: ($classgroups) = &Apache::loncoursedata::get_group_memberships(
3111: $userlist,$keylist,$cdom,$cnum);
3112: if ($mode eq 'autoenroll') {
3113: $env{'form.showrole'} = 'st';
3114: } else {
3115: if ($env{'course.'.$cid.'.internal.showphoto'}) {
3116: $r->print('
3117: <script type="text/javascript">
3118: // <![CDATA[
3119: function photowindow(photolink) {
3120: var title = "Photo_Viewer";
3121: var options = "scrollbars=1,resizable=1,menubar=0";
3122: options += ",width=240,height=240";
3123: stdeditbrowser = open(photolink,title,options,"1");
3124: stdeditbrowser.focus();
3125: }
3126: // ]]>
3127: </script>
3128: ');
3129: }
3130: }
3131: } elsif ($context eq 'domain') {
3132: if ($setting eq 'community') {
3133: $crstype = 'Community';
3134: } elsif ($setting eq 'course') {
3135: $crstype = 'Course';
3136: }
3137: }
3138: if ($mode ne 'autoenroll' && $mode ne 'pickauthor') {
3139: my $date_sec_selector = &date_section_javascript($context,$setting,$statusmode);
3140: my $verify_action_js = &bulkaction_javascript($formname);
3141: $r->print(<<END);
3142:
3143: <script type="text/javascript" language="Javascript">
3144: // <![CDATA[
3145:
3146: $verify_action_js
3147:
3148: function username_display_launch(username,domain) {
3149: var target;
3150: if (!document.$formname.usernamelink.length) {
3151: target = document.$formname.usernamelink.value;
3152: } else {
3153: for (var i=0; i<document.$formname.usernamelink.length; i++) {
3154: if (document.$formname.usernamelink[i].checked) {
3155: target = document.$formname.usernamelink[i].value;
3156: }
3157: }
3158: }
3159: if ((target == 'modify') || (target == 'activity')) {
3160: var nextaction = 'singleuser';
3161: if (target == 'activity') {
3162: nextaction = 'accesslogs';
3163: }
3164: if (document.$formname.userwin.checked == true) {
3165: var url = '/adm/createuser?srchterm='+username+'&srchdomain='+domain+'&phase=get_user_info&srchin=dom&srchby=uname&srchtype=exact&popup=1&action='+nextaction;
3166: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
3167: modifywin = window.open(url,'',options,1);
3168: modifywin.focus();
3169: return;
3170: } else {
3171: document.$formname.srchterm.value=username;
3172: document.$formname.srchdomain.value=domain;
3173: document.$formname.phase.value='get_user_info';
3174: document.$formname.action.value = nextaction;
3175: document.$formname.submit();
3176: }
3177: }
3178: if (target == 'aboutme') {
3179: if (document.$formname.userwin.checked == true) {
3180: var url = '/adm/'+domain+'/'+username+'/aboutme?popup=1';
3181: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
3182: aboutmewin = window.open(url,'',options,1);
3183: aboutmewin.focus();
3184: return;
3185: } else {
3186: document.location.href = '/adm/'+domain+'/'+username+'/aboutme';
3187: }
3188: }
3189: if (target == 'track') {
3190: if (document.$formname.userwin.checked == true) {
3191: var url = '/adm/trackstudent?selected_student='+username+':'+domain+'&only_body=1';
3192: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
3193: var trackwin = window.open(url,'',options,1);
3194: trackwin.focus();
3195: return;
3196: } else {
3197: document.location.href = '/adm/trackstudent?selected_student='+username+':'+domain;
3198: }
3199: }
3200: }
3201: // ]]>
3202: </script>
3203: $date_sec_selector
3204: <input type="hidden" name="state" value="$env{'form.state'}" />
3205: END
3206: }
3207: $r->print(<<END);
3208: <input type="hidden" name="sortby" value="$sortby" />
3209: END
3210: my @cols = &infocolumns($context,$mode,$showcredits);
3211: my %coltxt = &get_column_names($context);
3212: my %acttxt = &Apache::lonlocal::texthash(
3213: 'pr' => "Proceed",
3214: 'ac' => "Action to take for selected users",
3215: 'link' => "Behavior of clickable username link for each user",
3216: 'aboutme' => "Display a user's personal information page",
3217: 'owin' => "Open in a new window",
3218: 'modify' => "Modify a user's information",
3219: 'track' => "View a user's recent activity",
3220: 'activity' => "View a user's access log",
3221: );
3222: my %lt = (%coltxt,%acttxt);
3223: my $rolefilter = $env{'form.showrole'};
3224: if ($env{'form.showrole'} eq 'cr') {
3225: $rolefilter = &mt('custom');
3226: } elsif ($env{'form.showrole'} ne 'Any') {
3227: $rolefilter = &Apache::lonnet::plaintext($env{'form.showrole'},$crstype);
3228: }
3229: my $results_description;
3230: if ($mode ne 'autoenroll') {
3231: $results_description = &results_header_row($rolefilter,$statusmode,
3232: $context,$permission,$mode,$crstype);
3233: $r->print('<b>'.$results_description.'</b><br clear="all" />');
3234: }
3235: my ($output,$actionselect,%canchange,%canchangesec);
3236: if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
3237: if ($mode ne 'autoenroll' && $mode ne 'pickauthor') {
3238: if ($permission->{'cusr'}) {
3239: unless (($context eq 'domain') &&
3240: (($setting eq 'course') || ($setting eq 'community'))) {
3241: $actionselect =
3242: &select_actions($context,$setting,$statusmode,$formname);
3243: }
3244: }
3245: $r->print(<<END);
3246: <input type="hidden" name="srchby" value="uname" />
3247: <input type="hidden" name="srchin" value="dom" />
3248: <input type="hidden" name="srchtype" value="exact" />
3249: <input type="hidden" name="srchterm" value="" />
3250: <input type="hidden" name="srchdomain" value="" />
3251: END
3252: if ($actionselect) {
3253: $output .= <<"END";
3254: <div class="LC_left_float"><fieldset><legend>$lt{'ac'}</legend>
3255: $actionselect
3256: <br/><br /><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.$formname.actionlist)" />
3257: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.$formname.actionlist)" /><br /><input type="button" value="$lt{'pr'}" onclick="javascript:verify_action('actionlist')" /></fieldset></div>
3258: END
3259: my @allroles;
3260: if ($env{'form.showrole'} eq 'Any') {
3261: my $custom = 1;
3262: if ($context eq 'domain') {
3263: @allroles = &roles_by_context($setting,$custom,$crstype);
3264: } else {
3265: @allroles = &roles_by_context($context,$custom,$crstype);
3266: }
3267: } else {
3268: @allroles = ($env{'form.showrole'});
3269: }
3270: foreach my $role (@allroles) {
3271: if ($context eq 'domain') {
3272: if ($setting eq 'domain') {
3273: if (&Apache::lonnet::allowed('c'.$role,
3274: $env{'request.role.domain'})) {
3275: $canchange{$role} = 1;
3276: }
3277: } elsif ($setting eq 'author') {
3278: if (&Apache::lonnet::allowed('c'.$role,
3279: $env{'request.role.domain'})) {
3280: $canchange{$role} = 1;
3281: }
3282: }
3283: } elsif ($context eq 'author') {
3284: if (&Apache::lonnet::allowed('c'.$role,
3285: $env{'user.domain'}.'/'.$env{'user.name'})) {
3286: $canchange{$role} = 1;
3287: }
3288: } elsif ($context eq 'course') {
3289: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
3290: $canchange{$role} = 1;
3291: } elsif ($env{'request.course.sec'} ne '') {
3292: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
3293: $canchangesec{$role} = $env{'request.course.sec'};
3294: }
3295: } elsif ((($role eq 'co') && ($crstype eq 'Community')) ||
3296: (($role eq 'cc') && ($crstype eq 'Course'))) {
3297: if (&is_courseowner($env{'request.course.id'},
3298: $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'})) {
3299: $canchange{$role} = 1;
3300: }
3301: }
3302: }
3303: }
3304: }
3305: $output .= '<div class="LC_left_float"><fieldset><legend>'.$lt{'link'}.'</legend>'.
3306: '<table><tr>';
3307: my @linkdests = ('aboutme');
3308: if ($permission->{'cusr'}) {
3309: unshift (@linkdests,'modify');
3310: }
3311: if ($context eq 'course') {
3312: if (&Apache::lonnet::allowed('vsa', $env{'request.course.id'}) ||
3313: &Apache::lonnet::allowed('vsa', $env{'request.course.id'}.'/'.
3314: $env{'request.course.sec'})) {
3315: push(@linkdests,'track');
3316: }
3317: } elsif ($context eq 'domain') {
3318: if (&Apache::lonnet::allowed('vac',$env{'request.role.domain'})) {
3319: push(@linkdests,'activity');
3320: }
3321: }
3322: $output .= '<td>';
3323: my $usernamelink = $env{'form.usernamelink'};
3324: if ($usernamelink eq '') {
3325: $usernamelink = 'aboutme';
3326: }
3327: foreach my $item (@linkdests) {
3328: my $checkedstr = '';
3329: if ($item eq $usernamelink) {
3330: $checkedstr = ' checked="checked"';
3331: }
3332: $output .= '<span class="LC_nobreak"><label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.' /> '.$lt{$item}.'</label></span><br />';
3333: }
3334: my $checkwin;
3335: if ($env{'form.userwin'}) {
3336: $checkwin = ' checked="checked"';
3337: }
3338: $output .=
3339: '</td><td valign="top" style="border-left: 1px solid;">'
3340: .'<span class="LC_nobreak"><label>'
3341: .'<input type="checkbox" name="userwin" value="1"'.$checkwin.' />'.$lt{'owin'}
3342: .'</label></span></td></tr></table></fieldset></div>';
3343: }
3344: $output .= "\n".'<div style="padding:0;clear:both;margin:0;border:0"></div>'."\n".
3345: &Apache::loncommon::start_data_table().
3346: &Apache::loncommon::start_data_table_header_row();
3347: if ($mode eq 'autoenroll') {
3348: $output .= "
3349: <th><a href=\"javascript:document.$formname.sortby.value='type';document.$formname.submit();\">$lt{'type'}</a></th>
3350: ";
3351: } else {
3352: $output .= "\n".'<th> </th>'."\n";
3353: if ($actionselect) {
3354: $output .= '<th class="LC_nobreak" valign="top">'.&mt('Select').'</th>'."\n";
3355: }
3356: }
3357: foreach my $item (@cols) {
3358: $output .= '<th class="LC_nobreak" valign="top">';
3359: if ($is_sortable{$item}) {
3360: $output .= "<a href=\"javascript:document.$formname.sortby.value='$item';document.$formname.submit();\" style=\"text-decoration:none;\">$lt{$item}<span class=\"LC_fontsize_small\"> ▼</span></a>";
3361: } else {
3362: $output .= $lt{$item};
3363: }
3364: $output .= "</th>\n";
3365: }
3366: my %role_types = &role_type_names();
3367: $output .= &Apache::loncommon::end_data_table_header_row();
3368: # Done with the HTML header line
3369: } elsif ($mode eq 'csv') {
3370: #
3371: # Open a file
3372: $CSVfilename = '/prtspool/'.
3373: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
3374: time.'_'.rand(1000000000).'.csv';
3375: unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
3376: $r->log_error("Couldn't open $CSVfilename for output $!");
3377: $r->print(
3378: '<p class="LC_error">'
3379: .&mt('Problems occurred in writing the CSV file.')
3380: .' '.&mt('This error has been logged.')
3381: .' '.&mt('Please alert your LON-CAPA administrator.')
3382: .'</p>'
3383: );
3384: $CSVfile = undef;
3385: }
3386: #
3387: # Write headers and data to file
3388: print $CSVfile '"'.$results_description.'"'."\n";
3389: print $CSVfile '"'.join('","',map {
3390: &Apache::loncommon::csv_translate($lt{$_})
3391: } (@cols))."\"\n";
3392: } elsif ($mode eq 'excel') {
3393: # Create the excel spreadsheet
3394: ($excel_workbook,$excel_filename,$format) =
3395: &Apache::loncommon::create_workbook($r);
3396: return if (! defined($excel_workbook));
3397: $excel_sheet = $excel_workbook->addworksheet('userlist');
3398: $excel_sheet->write($row++,0,$results_description,$format->{'h2'});
3399: #
3400: my @colnames = map {$lt{$_}} (@cols);
3401:
3402: $excel_sheet->write($row++,0,\@colnames,$format->{'bold'});
3403: }
3404:
3405: # Done with header lines in all formats
3406: my %index;
3407: my $i;
3408: foreach my $idx (@$keylist) {
3409: $index{$idx} = $i++;
3410: }
3411: my $usercount = 0;
3412: my ($secfilter,$grpfilter);
3413: if ($context eq 'course') {
3414: $secfilter = $env{'form.secfilter'};
3415: $grpfilter = $env{'form.grpfilter'};
3416: if ($secfilter eq '') {
3417: $secfilter = 'all';
3418: }
3419: if ($grpfilter eq '') {
3420: $grpfilter = 'all';
3421: }
3422: }
3423: my %ltstatus = &Apache::lonlocal::texthash(
3424: Active => 'Active',
3425: Future => 'Future',
3426: Expired => 'Expired',
3427: );
3428: # If this is for a single course get last course "log-in".
3429: my %crslogins;
3430: if ($context eq 'course') {
3431: %crslogins=&Apache::lonnet::dump('nohist_crslastlogin',$cdom,$cnum);
3432: }
3433: # Get groups, role, permanent e-mail so we can sort on them if
3434: # necessary.
3435: foreach my $user (keys(%{$userlist})) {
3436: if ($user eq '' ) {
3437: delete($userlist->{$user});
3438: next;
3439: }
3440: if ($context eq 'domain' && $user eq $env{'request.role.domain'}.'-domainconfig:'.$env{'request.role.domain'}) {
3441: delete($userlist->{$user});
3442: next;
3443: }
3444: my ($uname,$udom,$role,$groups,$email);
3445: if (($statusmode ne 'Any') &&
3446: ($userlist->{$user}->[$index{'status'}] ne $statusmode)) {
3447: delete($userlist->{$user});
3448: next;
3449: }
3450: if ($context eq 'domain') {
3451: if ($env{'form.roletype'} eq 'domain') {
3452: ($role,$uname,$udom) = split(/:/,$user);
3453: if (($uname eq $env{'request.role.domain'}.'-domainconfig') &&
3454: ($udom eq $env{'request.role.domain'})) {
3455: delete($userlist->{$user});
3456: next;
3457: }
3458: } elsif ($env{'form.roletype'} eq 'author') {
3459: ($uname,$udom,$role) = split(/:/,$user,-1);
3460: } elsif (($env{'form.roletype'} eq 'course') ||
3461: ($env{'form.roletype'} eq 'community')) {
3462: ($uname,$udom,$role) = split(/:/,$user);
3463: }
3464: } else {
3465: ($uname,$udom,$role) = split(/:/,$user,-1);
3466: if (($context eq 'course') && $role eq '') {
3467: $role = 'st';
3468: }
3469: }
3470: $userlist->{$user}->[$index{'role'}] = $role;
3471: if (($env{'form.showrole'} ne 'Any') && (!($env{'form.showrole'} eq 'cr' && $role =~ /^cr\//)) && ($role ne $env{'form.showrole'})) {
3472: delete($userlist->{$user});
3473: next;
3474: }
3475: if ($context eq 'course') {
3476: my @ac_groups;
3477: if (ref($classgroups) eq 'HASH') {
3478: $groups = $classgroups->{$user};
3479: }
3480: if (ref($groups->{'active'}) eq 'HASH') {
3481: @ac_groups = keys(%{$groups->{'active'}});
3482: $userlist->{$user}->[$index{'groups'}] = join(', ',@ac_groups);
3483: }
3484: if ($mode ne 'autoenroll') {
3485: my $section = $userlist->{$user}->[$index{'section'}];
3486: if (($env{'request.course.sec'} ne '') &&
3487: ($section ne $env{'request.course.sec'})) {
3488: if ($role eq 'st') {
3489: delete($userlist->{$user});
3490: next;
3491: }
3492: }
3493: if ($secfilter eq 'none') {
3494: if ($section ne '') {
3495: delete($userlist->{$user});
3496: next;
3497: }
3498: } elsif ($secfilter ne 'all') {
3499: if ($section ne $secfilter) {
3500: delete($userlist->{$user});
3501: next;
3502: }
3503: }
3504: if ($grpfilter eq 'none') {
3505: if (@ac_groups > 0) {
3506: delete($userlist->{$user});
3507: next;
3508: }
3509: } elsif ($grpfilter ne 'all') {
3510: if (!grep(/^\Q$grpfilter\E$/,@ac_groups)) {
3511: delete($userlist->{$user});
3512: next;
3513: }
3514: }
3515: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
3516: if ((grep/^photo$/,@cols) && ($role eq 'st')) {
3517: $userlist->{$user}->[$index{'photo'}] =
3518: &Apache::lonnet::retrievestudentphoto($udom,$uname,'jpg');
3519: $userlist->{$user}->[$index{'thumbnail'}] =
3520: &Apache::lonnet::retrievestudentphoto($udom,$uname,
3521: 'gif','thumbnail');
3522: }
3523: }
3524: if (($role eq 'st') && ($defaultcredits)) {
3525: if ($userlist->{$user}->[$index{'credits'}] eq '') {
3526: $userlist->{$user}->[$index{'credits'}] = $defaultcredits;
3527: }
3528: }
3529: }
3530: }
3531: my %emails = &Apache::loncommon::getemails($uname,$udom);
3532: if ($emails{'permanentemail'} =~ /\S/) {
3533: $userlist->{$user}->[$index{'email'}] = $emails{'permanentemail'};
3534: }
3535: if (($context eq 'domain') && ($env{'form.roletype'} eq 'domain') &&
3536: ($role eq 'au')) {
3537: my ($disk_quota,$current_disk_usage,$percent);
3538: if (($needauthorusage) || ($needauthorquota)) {
3539: $disk_quota = &Apache::loncommon::get_user_quota($uname,$udom,'author');
3540: }
3541: if ($needauthorusage) {
3542: $current_disk_usage =
3543: &Apache::lonnet::diskusage($udom,$uname,"$londocroot/priv/$udom/$uname");
3544: if ($disk_quota == 0) {
3545: $percent = 100.0;
3546: } else {
3547: $percent = $current_disk_usage/(10 * $disk_quota);
3548: }
3549: $userlist->{$user}->[$index{'authorusage'}] = sprintf("%.0f",$percent);
3550: }
3551: if ($needauthorquota) {
3552: $userlist->{$user}->[$index{'authorquota'}] = sprintf("%.2f",$disk_quota);
3553: }
3554: }
3555: $usercount ++;
3556: }
3557: my $autocount = 0;
3558: my $manualcount = 0;
3559: my $lockcount = 0;
3560: my $unlockcount = 0;
3561: if ($usercount) {
3562: $r->print($output);
3563: } else {
3564: if ($mode eq 'autoenroll') {
3565: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
3566: } else {
3567: return;
3568: }
3569: }
3570: #
3571: # Sort the users
3572: my $index = $index{$sortby};
3573: my $second = $index{'username'};
3574: my $third = $index{'domain'};
3575: my @sorted_users;
3576: if (($sortby eq 'authorquota') || ($sortby eq 'authorusage')) {
3577: @sorted_users = sort {
3578: $userlist->{$b}->[$index] <=> $userlist->{$a}->[$index] ||
3579: lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second]) ||
3580: lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
3581: } (keys(%$userlist));
3582: } else {
3583: @sorted_users = sort {
3584: lc($userlist->{$a}->[$index]) cmp lc($userlist->{$b}->[$index]) ||
3585: lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second]) ||
3586: lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
3587: } (keys(%$userlist));
3588: }
3589: my $rowcount = 0;
3590: my $disabled;
3591: if ($mode eq 'autoenroll') {
3592: unless ($permission->{'cusr'}) {
3593: $disabled = ' disabled="disabled"';
3594: }
3595: }
3596: foreach my $user (@sorted_users) {
3597: my %in;
3598: my $sdata = $userlist->{$user};
3599: $rowcount ++;
3600: foreach my $item (@{$keylist}) {
3601: $in{$item} = $sdata->[$index{$item}];
3602: }
3603: my $clickers = (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
3604: if ($clickers!~/\w/) { $clickers='-'; }
3605: $in{'clicker'} = $clickers;
3606: my $role = $in{'role'};
3607: $in{'role'}=&Apache::lonnet::plaintext($sdata->[$index{'role'}],$crstype);
3608: unless ($mode eq 'excel') {
3609: if (! defined($in{'start'}) || $in{'start'} == 0) {
3610: $in{'start'} = &mt('none');
3611: } else {
3612: $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
3613: }
3614: if (! defined($in{'end'}) || $in{'end'} == 0) {
3615: $in{'end'} = &mt('none');
3616: } else {
3617: $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
3618: }
3619: }
3620: if ($context eq 'course') {
3621: my $lastlogin = $crslogins{$in{'username'}.':'.$in{'domain'}.':'.$in{'section'}.':'.$role};
3622: if ($lastlogin ne '') {
3623: $in{'lastlogin'} = &Apache::lonlocal::locallocaltime($lastlogin);
3624: }
3625: }
3626: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
3627: $r->print(&Apache::loncommon::start_data_table_row());
3628: my $checkval;
3629: if ($mode eq 'autoenroll') {
3630: my $cellentry;
3631: if ($in{'type'} eq 'auto') {
3632: $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Change').'</label>';
3633: $autocount ++;
3634: } else {
3635: $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><span class="LC_nobreak"><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Change').'</label></span></td></tr><tr><td><span class="LC_nobreak">';
3636: $manualcount ++;
3637: if ($in{'lockedtype'}) {
3638: $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Unlock').'</label>';
3639: $unlockcount ++;
3640: } else {
3641: $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Lock').'</label>';
3642: $lockcount ++;
3643: }
3644: $cellentry .= '</span></td></tr></table>';
3645: }
3646: $r->print("<td>$cellentry</td>\n");
3647: } else {
3648: if ($mode ne 'pickauthor') {
3649: $r->print("<td>$rowcount</td>\n");
3650: }
3651: if ($actionselect) {
3652: my $showcheckbox;
3653: if ($role =~ /^cr\//) {
3654: $showcheckbox = $canchange{'cr'};
3655: } else {
3656: $showcheckbox = $canchange{$role};
3657: }
3658: if (!$showcheckbox) {
3659: if ($context eq 'course') {
3660: if ($canchangesec{$role} ne '') {
3661: if ($canchangesec{$role} eq $in{'section'}) {
3662: $showcheckbox = 1;
3663: }
3664: }
3665: }
3666: }
3667: if ($showcheckbox) {
3668: $checkval = $user;
3669: if ($context eq 'course') {
3670: if (($role eq 'co' || $role eq 'cc') &&
3671: ($user =~ /^\Q$env{'user.name'}:$env{'user.domain'}:$role\E/)) {
3672: $showcheckbox = 0;
3673: } else {
3674: if ($role eq 'st') {
3675: $checkval .= ':st';
3676: }
3677: $checkval .= ':'.$in{'section'};
3678: if ($role eq 'st') {
3679: $checkval .= ':'.$in{'type'}.':'.
3680: $in{'lockedtype'}.':'.
3681: $in{'credits'}.':'.
3682: &escape($in{'instsec'});
3683: }
3684: }
3685: }
3686: if ($showcheckbox) {
3687: $r->print('<td><input type="checkbox" name="'.
3688: 'actionlist" value="'.
3689: &HTML::Entities::encode($checkval,'&<>"').'" />');
3690: foreach my $item ('start','end') {
3691: $r->print('<input type="hidden" name="'.
3692: &HTML::Entities::encode($checkval.'_'.$item,'&<>"').'"'.
3693: ' value="'.$sdata->[$index{$item}].'" />');
3694: }
3695: $r->print('</td>');
3696: } else {
3697: $r->print('<td> </td>');
3698: }
3699: } else {
3700: $r->print('<td> </td>');
3701: }
3702: } elsif ($mode eq 'pickauthor') {
3703: $r->print('<td><input type="button" name="chooseauthor" onclick="javascript:gochoose('."'$in{'username'}'".');" value="'.&mt('Select').'" /></td>');
3704: }
3705: }
3706: foreach my $item (@cols) {
3707: if ($item eq 'username') {
3708: $r->print('<td>'.&print_username_link($mode,\%in).'</td>');
3709: } elsif ($item eq 'status') {
3710: my $showitem = $in{$item};
3711: if (defined($ltstatus{$in{$item}})) {
3712: $showitem = $ltstatus{$in{$item}};
3713: }
3714: $r->print('<td>'.$showitem.'</td>'."\n");
3715: } elsif ($item eq 'photo') {
3716: if (($context eq 'course') && ($mode ne 'autoenroll') &&
3717: ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'})) {
3718: if ($role eq 'st') {
3719: $r->print('<td align="right"><a href="javascript:photowindow('."'".$in{'photo'}."'".')"><img src="'.$in{'thumbnail'}.'" border="1" alt="" /></a></td>');
3720: } else {
3721: $r->print('<td> </td>');
3722: }
3723: }
3724: } elsif ($item eq 'clicker') {
3725: if (($context eq 'course') && ($mode ne 'autoenroll')) {
3726: if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
3727: my $clickers =
3728: (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
3729: if ($clickers!~/\w/) { $clickers='-'; }
3730: $r->print('<td>'.$clickers.'</td>');
3731: } else {
3732: $r->print('<td> </td>'."\n");
3733: }
3734: }
3735: } elsif (($item eq 'authorquota') || ($item eq 'authorusage')) {
3736: $r->print('<td align="right">'.$in{$item}.'</td>'."\n");
3737: } else {
3738: $r->print('<td>'.$in{$item}.'</td>'."\n");
3739: }
3740: }
3741: $r->print(&Apache::loncommon::end_data_table_row());
3742: } elsif ($mode eq 'csv') {
3743: next if (! defined($CSVfile));
3744: # no need to bother with $linkto
3745: my @line = ();
3746: foreach my $item (@cols) {
3747: push @line,&Apache::loncommon::csv_translate($in{$item});
3748: }
3749: print $CSVfile '"'.join('","',@line)."\"\n";
3750: } elsif ($mode eq 'excel') {
3751: my $col = 0;
3752: foreach my $item (@cols) {
3753: if ($item eq 'start' || $item eq 'end') {
3754: if ((defined($in{$item})) && ($in{$item} != 0)) {
3755: $excel_sheet->write($row,$col++,
3756: &Apache::lonstathelpers::calc_serial($in{$item}),
3757: $format->{'date'});
3758: } else {
3759: $excel_sheet->write($row,$col++,'none');
3760: }
3761: } else {
3762: $excel_sheet->write($row,$col++,$in{$item});
3763: }
3764: }
3765: $row++;
3766: }
3767: }
3768: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
3769: $r->print(&Apache::loncommon::end_data_table().'<br />');
3770: } elsif ($mode eq 'excel') {
3771: $excel_workbook->close();
3772: $r->print('<p>'.&mt('[_1]Your Excel spreadsheet[_2] is ready for download.', '<a href="'.$excel_filename.'">','</a>')."</p>\n");
3773: } elsif ($mode eq 'csv') {
3774: close($CSVfile);
3775: $r->print('<p>'.&mt('[_1]Your CSV file[_2] is ready for download.', '<a href="'.$CSVfilename.'">','</a>')."</p>\n");
3776: $r->rflush();
3777: }
3778: if ($mode eq 'autoenroll') {
3779: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
3780: } else {
3781: return ($usercount);
3782: }
3783: }
3784:
3785: sub bulkaction_javascript {
3786: my ($formname,$caller) = @_;
3787: my $docstart = 'document';
3788: if ($caller eq 'popup') {
3789: $docstart = 'opener.document';
3790: }
3791: my %lt = &Apache::lonlocal::texthash(
3792: acwi => 'Access will be set to start immediately',
3793: asyo => 'as you did not select an end date in the pop-up window',
3794: accw => 'Access will be set to continue indefinitely',
3795: asyd => 'as you did not select an end date in the pop-up window',
3796: sewi => "Sections will be switched to 'No section'",
3797: ayes => "as you either selected the 'No section' option",
3798: oryo => 'or you did not select a section in the pop-up window',
3799: arol => 'A role with no section will be added',
3800: swbs => 'Sections will be switched to:',
3801: rwba => 'Roles will be added for section(s):',
3802: );
3803: my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox");
3804: my $noaction = &mt("You need to select an action to take for the user(s) you have selected");
3805: my $singconfirm = &mt(' for a single user?');
3806: my $multconfirm = &mt(' for multiple users?');
3807: &js_escape(\$alert);
3808: &js_escape(\$noaction);
3809: &js_escape(\$singconfirm);
3810: &js_escape(\$multconfirm);
3811: my $output = <<"ENDJS";
3812: function verify_action (field) {
3813: var numchecked = 0;
3814: var singconf = '$singconfirm';
3815: var multconf = '$multconfirm';
3816: if ($docstart.$formname.elements[field].length > 0) {
3817: for (i=0; i<$docstart.$formname.elements[field].length; i++) {
3818: if ($docstart.$formname.elements[field][i].checked == true) {
3819: numchecked ++;
3820: }
3821: }
3822: } else {
3823: if ($docstart.$formname.elements[field].checked == true) {
3824: numchecked ++;
3825: }
3826: }
3827: if (numchecked == 0) {
3828: alert("$alert");
3829: return;
3830: } else {
3831: var message = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].text;
3832: var choice = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].value;
3833: if (choice == '') {
3834: alert("$noaction");
3835: return;
3836: } else {
3837: if (numchecked == 1) {
3838: message += singconf;
3839: } else {
3840: message += multconf;
3841: }
3842: ENDJS
3843: if ($caller ne 'popup') {
3844: $output .= <<"NEWWIN";
3845: if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate' || choice == 'chgsec') {
3846: opendatebrowser(document.$formname,'$formname','go');
3847: return;
3848:
3849: } else {
3850: if (confirm(message)) {
3851: document.$formname.phase.value = 'bulkchange';
3852: document.$formname.submit();
3853: return;
3854: }
3855: }
3856: NEWWIN
3857: } else {
3858: $output .= <<"POPUP";
3859: if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate') {
3860: var datemsg = '';
3861: if (($docstart.$formname.startdate_month.value == '') &&
3862: ($docstart.$formname.startdate_day.value == '') &&
3863: ($docstart.$formname.startdate_year.value == '')) {
3864: datemsg = "\\n$lt{'acwi'},\\n$lt{'asyo'}.\\n";
3865: }
3866: if (($docstart.$formname.enddate_month.value == '') &&
3867: ($docstart.$formname.enddate_day.value == '') &&
3868: ($docstart.$formname.enddate_year.value == '')) {
3869: datemsg += "\\n$lt{'accw'},\\n$lt{'asyd'}.\\n";
3870: }
3871: if (datemsg != '') {
3872: message += "\\n"+datemsg;
3873: }
3874: }
3875: if (choice == 'chgsec') {
3876: var rolefilter = $docstart.$formname.showrole.options[$docstart.$formname.showrole.selectedIndex].value;
3877: var retained = $docstart.$formname.retainsec.value;
3878: var secshow = $docstart.$formname.newsecs.value;
3879: if (secshow == '') {
3880: if (rolefilter == 'st' || retained == 0 || retained == "") {
3881: message += "\\n\\n$lt{'sewi'},\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
3882: } else {
3883: message += "\\n\\n$lt{'arol'}\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
3884: }
3885: } else {
3886: if (rolefilter == 'st' || retained == 0 || retained == "") {
3887: message += "\\n\\n$lt{'swbs'} "+secshow+".\\n";
3888: } else {
3889: message += "\\n\\n$lt{'rwba'} "+secshow+".\\n";
3890: }
3891: }
3892: }
3893: if (confirm(message)) {
3894: $docstart.$formname.phase.value = 'bulkchange';
3895: $docstart.$formname.submit();
3896: window.close();
3897: }
3898: POPUP
3899: }
3900: $output .= '
3901: }
3902: }
3903: }
3904: ';
3905: return $output;
3906: }
3907:
3908: sub print_username_link {
3909: my ($mode,$in) = @_;
3910: my $output;
3911: if ($mode eq 'autoenroll') {
3912: $output = $in->{'username'};
3913: } else {
3914: $output = '<a href="javascript:username_display_launch('.
3915: "'$in->{'username'}','$in->{'domain'}'".')">'.
3916: $in->{'username'}.'</a>';
3917: }
3918: return $output;
3919: }
3920:
3921: sub role_type_names {
3922: my %lt = &Apache::lonlocal::texthash (
3923: 'domain' => 'Domain Roles',
3924: 'author' => 'Co-Author Roles',
3925: 'course' => 'Course Roles',
3926: 'community' => 'Community Roles',
3927: );
3928: return %lt;
3929: }
3930:
3931: sub select_actions {
3932: my ($context,$setting,$statusmode,$formname) = @_;
3933: my %lt = &Apache::lonlocal::texthash(
3934: revoke => "Revoke user roles",
3935: delete => "Delete user roles",
3936: reenable => "Re-enable expired user roles",
3937: activate => "Make future user roles active now",
3938: chgdates => "Change starting/ending dates",
3939: chgsec => "Change section associated with user roles",
3940: );
3941: # FIXME Add an option to change credits for student roles.
3942: my ($output,$options,%choices);
3943: # FIXME Disable actions for now for roletype=course in domain context
3944: if ($context eq 'domain' && $setting eq 'course') {
3945: return;
3946: }
3947: if ($context eq 'course') {
3948: if ($env{'form.showrole'} ne 'Any') {
3949: my $showactions;
3950: if (&Apache::lonnet::allowed('c'.$env{'form.showrole'},
3951: $env{'request.course.id'})) {
3952: $showactions = 1;
3953: } elsif ($env{'request.course.sec'} ne '') {
3954: if (&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
3955: $showactions = 1;
3956: }
3957: }
3958: unless ($showactions) {
3959: unless (&is_courseowner($env{'request.course.id'},
3960: $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'})) {
3961: return;
3962: }
3963: }
3964: }
3965: }
3966: if ($statusmode eq 'Any') {
3967: $options .= '
3968: <option value="chgdates">'.$lt{'chgdates'}.'</option>';
3969: $choices{'dates'} = 1;
3970: } else {
3971: if ($statusmode eq 'Future') {
3972: $options .= '
3973: <option value="activate">'.$lt{'activate'}.'</option>';
3974: $choices{'dates'} = 1;
3975: } elsif ($statusmode eq 'Expired') {
3976: $options .= '
3977: <option value="reenable">'.$lt{'reenable'}.'</option>';
3978: $choices{'dates'} = 1;
3979: }
3980: if ($statusmode eq 'Active' || $statusmode eq 'Future') {
3981: $options .= '
3982: <option value="chgdates">'.$lt{'chgdates'}.'</option>
3983: <option value="revoke">'.$lt{'revoke'}.'</option>';
3984: $choices{'dates'} = 1;
3985: }
3986: }
3987: if ($context eq 'domain') {
3988: $options .= '
3989: <option value="delete">'.$lt{'delete'}.'</option>';
3990: }
3991: if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course')) {
3992: if (($statusmode ne 'Expired') && ($env{'request.course.sec'} eq '')) {
3993: $options .= '
3994: <option value="chgsec">'.$lt{'chgsec'}.'</option>';
3995: $choices{'sections'} = 1;
3996: }
3997: }
3998: if ($options) {
3999: $output = '<select name="bulkaction">'."\n".
4000: '<option value="" selected="selected">'.
4001: &mt('Please select').'</option>'."\n".$options."\n".'</select>';
4002: if ($choices{'dates'}) {
4003: $output .=
4004: '<input type="hidden" name="startdate_month" value="" />'."\n".
4005: '<input type="hidden" name="startdate_day" value="" />'."\n".
4006: '<input type="hidden" name="startdate_year" value="" />'."\n".
4007: '<input type="hidden" name="startdate_hour" value="" />'."\n".
4008: '<input type="hidden" name="startdate_minute" value="" />'."\n".
4009: '<input type="hidden" name="startdate_second" value="" />'."\n".
4010: '<input type="hidden" name="enddate_month" value="" />'."\n".
4011: '<input type="hidden" name="enddate_day" value="" />'."\n".
4012: '<input type="hidden" name="enddate_year" value="" />'."\n".
4013: '<input type="hidden" name="enddate_hour" value="" />'."\n".
4014: '<input type="hidden" name="enddate_minute" value="" />'."\n".
4015: '<input type="hidden" name="enddate_second" value="" />'."\n".
4016: '<input type="hidden" name="no_end_date" value="" />'."\n";
4017: if ($context eq 'course') {
4018: $output .= '<input type="hidden" name="makedatesdefault" value="" />'."\n";
4019: }
4020: }
4021: if ($choices{'sections'}) {
4022: $output .= '<input type="hidden" name="retainsec" value="" />'."\n".
4023: '<input type="hidden" name="newsecs" value="" />'."\n";
4024: }
4025: }
4026: return $output;
4027: }
4028:
4029: sub date_section_javascript {
4030: my ($context,$setting) = @_;
4031: my $title = 'Date_And_Section_Selector';
4032: my %nopopup = &Apache::lonlocal::texthash (
4033: revoke => "Check the boxes for any users for whom roles are to be revoked, and click 'Proceed'",
4034: delete => "Check the boxes for any users for whom roles are to be deleted, and click 'Proceed'",
4035: none => "Choose an action to take for selected users",
4036: );
4037: my $output = <<"ENDONE";
4038: <script type="text/javascript">
4039: // <![CDATA[
4040: function opendatebrowser(callingform,formname,calledby) {
4041: var bulkaction = callingform.bulkaction.options[callingform.bulkaction.selectedIndex].value;
4042: var url = '/adm/createuser?';
4043: var type = '';
4044: var showrole = callingform.showrole.options[callingform.showrole.selectedIndex].value;
4045: ENDONE
4046: if ($context eq 'domain') {
4047: $output .= '
4048: type = callingform.roletype.options[callingform.roletype.selectedIndex].value;
4049: ';
4050: }
4051: my $width= '700';
4052: my $height = '400';
4053: $output .= <<"ENDTWO";
4054: url += 'action=dateselect&callingform=' + formname +
4055: '&roletype='+type+'&showrole='+showrole +'&bulkaction='+bulkaction;
4056: var title = '$title';
4057: var options = 'scrollbars=1,resizable=1,menubar=0';
4058: options += ',width=$width,height=$height';
4059: stdeditbrowser = open(url,title,options,'1');
4060: stdeditbrowser.focus();
4061: }
4062: // ]]>
4063: </script>
4064: ENDTWO
4065: return $output;
4066: }
4067:
4068: sub date_section_selector {
4069: my ($context,$permission,$crstype,$showcredits) = @_;
4070: my $callingform = $env{'form.callingform'};
4071: my $formname = 'dateselect';
4072: my $groupslist = &get_groupslist();
4073: my $sec_js =
4074: &setsections_javascript($formname,$groupslist,undef,undef,$crstype,
4075: $showcredits);
4076: my $output = <<"END";
4077: <script type="text/javascript">
4078: // <![CDATA[
4079:
4080: $sec_js
4081:
4082: function saveselections(formname) {
4083:
4084: END
4085: if ($env{'form.bulkaction'} eq 'chgsec') {
4086: $output .= <<"END";
4087: if (formname.retainsec.length > 1) {
4088: for (var i=0; i<formname.retainsec.length; i++) {
4089: if (formname.retainsec[i].checked == true) {
4090: opener.document.$callingform.retainsec.value = formname.retainsec[i].value;
4091: }
4092: }
4093: } else {
4094: opener.document.$callingform.retainsec.value = formname.retainsec.value;
4095: }
4096: setSections(formname,'$crstype');
4097: if (seccheck == 'ok') {
4098: opener.document.$callingform.newsecs.value = formname.sections.value;
4099: } else {
4100: return;
4101: }
4102: END
4103: } else {
4104: if ($context eq 'course') {
4105: if (($env{'form.bulkaction'} eq 'reenable') ||
4106: ($env{'form.bulkaction'} eq 'activate') ||
4107: ($env{'form.bulkaction'} eq 'chgdates')) {
4108: if ($env{'request.course.sec'} eq '') {
4109: $output .= <<"END";
4110:
4111: if (formname.makedatesdefault.checked == true) {
4112: opener.document.$callingform.makedatesdefault.value = 1;
4113: }
4114: else {
4115: opener.document.$callingform.makedatesdefault.value = 0;
4116: }
4117:
4118: END
4119: }
4120: }
4121: }
4122: $output .= <<"END";
4123: opener.document.$callingform.startdate_month.value = formname.startdate_month.options[formname.startdate_month.selectedIndex].value;
4124: opener.document.$callingform.startdate_day.value = formname.startdate_day.value;
4125: opener.document.$callingform.startdate_year.value = formname.startdate_year.value;
4126: opener.document.$callingform.startdate_hour.value = formname.startdate_hour.options[formname.startdate_hour.selectedIndex].value;
4127: opener.document.$callingform.startdate_minute.value = formname.startdate_minute.value;
4128: opener.document.$callingform.startdate_second.value = formname.startdate_second.value;
4129: opener.document.$callingform.enddate_month.value = formname.enddate_month.options[formname.enddate_month.selectedIndex].value;
4130: opener.document.$callingform.enddate_day.value = formname.enddate_day.value;
4131: opener.document.$callingform.enddate_year.value = formname.enddate_year.value;
4132: opener.document.$callingform.enddate_hour.value = formname.enddate_hour.options[formname.enddate_hour.selectedIndex].value;
4133: opener.document.$callingform.enddate_minute.value = formname.enddate_minute.value;
4134: opener.document.$callingform.enddate_second.value = formname.enddate_second.value;
4135: if (formname.no_end_date.checked) {
4136: opener.document.$callingform.no_end_date.value = '1';
4137: } else {
4138: opener.document.$callingform.no_end_date.value = '0';
4139: }
4140: END
4141: }
4142: my $verify_action_js = &bulkaction_javascript($callingform,'popup');
4143: $output .= <<"ENDJS";
4144: verify_action('actionlist');
4145: }
4146:
4147: $verify_action_js
4148:
4149: // ]]>
4150: </script>
4151: ENDJS
4152: my %lt = &Apache::lonlocal::texthash (
4153: chac => 'Access dates to apply for selected users',
4154: chse => 'Changes in section affiliation to apply to selected users',
4155: fors => 'For student roles, changing the section will result in a section switch as students may only be in one section of a course at a time.',
4156: forn => 'For a course role that is not "student", users may have roles in more than one section at a time.',
4157: reta => "Retain each user's current section affiliations?",
4158: dnap => '(Does not apply to student roles).',
4159: );
4160: my ($date_items,$headertext);
4161: if ($env{'form.bulkaction'} eq 'chgsec') {
4162: $headertext = $lt{'chse'};
4163: } else {
4164: $headertext = $lt{'chac'};
4165: my $starttime;
4166: if (($env{'form.bulkaction'} eq 'activate') ||
4167: ($env{'form.bulkaction'} eq 'reenable')) {
4168: $starttime = time;
4169: }
4170: $date_items = &date_setting_table($starttime,undef,$context,
4171: $env{'form.bulkaction'},$formname,
4172: $permission,$crstype);
4173: }
4174: $output .= '<h3>'.$headertext.'</h3>'.
4175: '<form name="'.$formname.'" method="post" action="">'."\n".
4176: $date_items;
4177: if ($context eq 'course' && $env{'form.bulkaction'} eq 'chgsec') {
4178: my ($cnum,$cdom) = &get_course_identity();
4179: if ($crstype eq 'Community') {
4180: $lt{'fors'} = &mt('For member roles, changing the section will result in a section switch, as members may only be in one section of a community at a time.');
4181: $lt{'forn'} = &mt('For a community role that is not "member", users may have roles in more than one section at a time.');
4182: $lt{'dnap'} = &mt('(Does not apply to member roles).');
4183: }
4184: my $info;
4185: if ($env{'form.showrole'} eq 'st') {
4186: $output .= '<p>'.$lt{'fors'}.'</p>';
4187: } elsif ($env{'form.showrole'} eq 'Any') {
4188: $output .= '<p>'.$lt{'fors'}.'</p>'.
4189: '<p>'.$lt{'forn'}.' ';
4190: $info = $lt{'reta'};
4191: } else {
4192: $output .= '<p>'.$lt{'forn'}.' ';
4193: $info = $lt{'reta'};
4194: }
4195: if ($info) {
4196: $info .= '<span class="LC_nobreak">'.
4197: '<label><input type="radio" name="retainsec" value="1" '.
4198: 'checked="checked" />'.&mt('Yes').'</label> '.
4199: '<label><input type="radio" name="retainsec" value="0" />'.
4200: &mt('No').'</label></span>';
4201: if ($env{'form.showrole'} eq 'Any') {
4202: $info .= '<br />'.$lt{'dnap'};
4203: }
4204: $info .= '</p>';
4205: } else {
4206: $info = '<input type="hidden" name="retainsec" value="0" />';
4207: }
4208: my $rowtitle = &mt('New section to assign');
4209: my $secbox = §ion_picker($cdom,$cnum,$env{'form.showrole'},$rowtitle,
4210: $permission,$context,'chgsec',$crstype);
4211: $output .= $info.$secbox;
4212: }
4213: $output .= '<p>'.
4214: '<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n".
4215: '</form>';
4216: return $output;
4217: }
4218:
4219: sub section_picker {
4220: my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode,$crstype,
4221: $showcredits,$credits) = @_;
4222: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
4223: my $sections_select .= &course_sections(\%sections_count,$role);
4224: my $secbox = '<div>'.&Apache::lonhtmlcommon::start_pick_box()."\n";
4225: if ($mode eq 'upload') {
4226: my ($options,$cb_script,$coursepick) =
4227: &default_role_selector($context,1,$crstype,$showcredits);
4228: $secbox .= &Apache::lonhtmlcommon::row_title(&mt('role'),'LC_oddrow_value').
4229: $options. &Apache::lonhtmlcommon::row_closure(1)."\n";
4230: }
4231: $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n";
4232: if ($env{'request.course.sec'} eq '') {
4233: $secbox .= '<table class="LC_createuser"><tr class="LC_section_row">'."\n".
4234: '<td align="center">'.&mt('Existing sections')."\n".
4235: '<br />'.$sections_select.'</td><td align="center">'.
4236: &mt('New section').'<br />'."\n".
4237: '<input type="text" name="newsec" size="15" value="" />'."\n".
4238: '<input type="hidden" name="sections" value="" />'."\n".
4239: '</td></tr></table>'."\n";
4240: } else {
4241: $secbox .= '<input type="hidden" name="sections" value="'.
4242: $env{'request.course.sec'}.'" />'.
4243: $env{'request.course.sec'};
4244: }
4245: $secbox .= &Apache::lonhtmlcommon::row_closure(1)."\n";
4246: unless ($mode eq 'chgsec') {
4247: if ($showcredits) {
4248: $secbox .=
4249: &Apache::lonhtmlcommon::row_title(&mt('credits (students)'),
4250: 'LC_evenrow_value')."\n".
4251: '<input type="text" name="credits" size="3" value="'.$credits.'" />'."\n".
4252: &Apache::lonhtmlcommon::row_closure(1)."\n";
4253: }
4254: }
4255: $secbox .= &Apache::lonhtmlcommon::end_pick_box().'</div>';
4256: return $secbox;
4257: }
4258:
4259: sub results_header_row {
4260: my ($rolefilter,$statusmode,$context,$permission,$mode,$crstype) = @_;
4261: my ($description,$showfilter);
4262: if ($rolefilter ne 'Any') {
4263: $showfilter = $rolefilter;
4264: }
4265: if ($context eq 'course') {
4266: if ($mode eq 'csv' || $mode eq 'excel') {
4267: if ($crstype eq 'Community') {
4268: $description = &mt('Community - [_1]:',$env{'course.'.$env{'request.course.id'}.'.description'}).' ';
4269: } else {
4270: $description = &mt('Course - [_1]:',$env{'course.'.$env{'request.course.id'}.'.description'}).' ';
4271: }
4272: }
4273: if ($statusmode eq 'Expired') {
4274: if ($crstype eq 'Community') {
4275: $description .= &mt('Users in community with expired [_1] roles',$showfilter);
4276: } else {
4277: $description .= &mt('Users in course with expired [_1] roles',$showfilter);
4278: }
4279: } elsif ($statusmode eq 'Future') {
4280: if ($crstype eq 'Community') {
4281: $description .= &mt('Users in community with future [_1] roles',$showfilter);
4282: } else {
4283: $description .= &mt('Users in course with future [_1] roles',$showfilter);
4284: }
4285: } elsif ($statusmode eq 'Active') {
4286: if ($crstype eq 'Community') {
4287: $description .= &mt('Users in community with active [_1] roles',$showfilter);
4288: } else {
4289: $description .= &mt('Users in course with active [_1] roles',$showfilter);
4290: }
4291: } else {
4292: if ($rolefilter eq 'Any') {
4293: if ($crstype eq 'Community') {
4294: $description .= &mt('All users in community');
4295: } else {
4296: $description .= &mt('All users in course');
4297: }
4298: } else {
4299: if ($crstype eq 'Community') {
4300: $description .= &mt('All users in community with [_1] roles',$rolefilter);
4301: } else {
4302: $description .= &mt('All users in course with [_1] roles',$rolefilter);
4303: }
4304: }
4305: }
4306: my $constraint;
4307: my $viewablesec = &viewable_section($permission);
4308: if ($viewablesec ne '') {
4309: if ($env{'form.showrole'} eq 'st') {
4310: $constraint = &mt('only users in section "[_1]"',$viewablesec);
4311: } elsif (($env{'form.showrole'} ne 'cc') && ($env{'form.showrole'} ne 'co')) {
4312: $constraint = &mt('only users affiliated with no section or section "[_1]"',$viewablesec);
4313: }
4314: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
4315: if ($env{'form.grpfilter'} eq 'none') {
4316: $constraint .= &mt(' and not in any group');
4317: } else {
4318: $constraint .= &mt(' and members of group: "[_1]"',$env{'form.grpfilter'});
4319: }
4320: }
4321: } else {
4322: if (($env{'form.secfilter'} ne 'all') && ($env{'form.secfilter'} ne '')) {
4323: if ($env{'form.secfilter'} eq 'none') {
4324: $constraint = &mt('only users affiliated with no section');
4325: } else {
4326: $constraint = &mt('only users affiliated with section "[_1]"',$env{'form.secfilter'});
4327: }
4328: }
4329: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
4330: if ($env{'form.grpfilter'} eq 'none') {
4331: if ($constraint eq '') {
4332: $constraint = &mt('only users not in any group');
4333: } else {
4334: $constraint .= &mt(' and also not in any group');
4335: }
4336: } else {
4337: if ($constraint eq '') {
4338: $constraint = &mt('only members of group: "[_1]"',$env{'form.grpfilter'});
4339: } else {
4340: $constraint .= &mt(' and also members of group: "[_1]"'.$env{'form.grpfilter'});
4341: }
4342: }
4343: }
4344: }
4345: if ($constraint ne '') {
4346: $description .= ' ('.$constraint.')';
4347: }
4348: } elsif ($context eq 'author') {
4349: $description =
4350: &mt('Author space for [_1]'
4351: ,'<span class="LC_cusr_emph">'
4352: .&Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'})
4353: .'</span>')
4354: .': ';
4355: if ($statusmode eq 'Expired') {
4356: $description .= &mt('Co-authors with expired [_1] roles',$showfilter);
4357: } elsif ($statusmode eq 'Future') {
4358: $description .= &mt('Co-authors with future [_1] roles',$showfilter);
4359: } elsif ($statusmode eq 'Active') {
4360: $description .= &mt('Co-authors with active [_1] roles',$showfilter);
4361: } else {
4362: if ($rolefilter eq 'Any') {
4363: $description .= &mt('All co-authors');
4364: } else {
4365: $description .= &mt('All co-authors with [_1] roles',$rolefilter);
4366: }
4367: }
4368: } elsif ($context eq 'domain') {
4369: my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description');
4370: $description = &mt('Domain - [_1]:',$domdesc).' ';
4371: if ($env{'form.roletype'} eq 'domain') {
4372: if ($statusmode eq 'Expired') {
4373: $description .= &mt('Users in domain with expired [_1] roles',$showfilter);
4374: } elsif ($statusmode eq 'Future') {
4375: $description .= &mt('Users in domain with future [_1] roles',$showfilter);
4376: } elsif ($statusmode eq 'Active') {
4377: $description .= &mt('Users in domain with active [_1] roles',$showfilter);
4378: } else {
4379: if ($rolefilter eq 'Any') {
4380: $description .= &mt('All users in domain');
4381: } else {
4382: $description .= &mt('All users in domain with [_1] roles',$rolefilter);
4383: }
4384: }
4385: } elsif ($env{'form.roletype'} eq 'author') {
4386: if ($statusmode eq 'Expired') {
4387: $description .= &mt('Co-authors in domain with expired [_1] roles',$showfilter);
4388: } elsif ($statusmode eq 'Future') {
4389: $description .= &mt('Co-authors in domain with future [_1] roles',$showfilter);
4390: } elsif ($statusmode eq 'Active') {
4391: $description .= &mt('Co-authors in domain with active [_1] roles',$showfilter);
4392: } else {
4393: if ($rolefilter eq 'Any') {
4394: $description .= &mt('All users with co-author roles in domain',$showfilter);
4395: } else {
4396: $description .= &mt('All co-authors in domain with [_1] roles',$rolefilter);
4397: }
4398: }
4399: } elsif (($env{'form.roletype'} eq 'course') ||
4400: ($env{'form.roletype'} eq 'community')) {
4401: my $coursefilter = $env{'form.coursepick'};
4402: if ($env{'form.roletype'} eq 'course') {
4403: if ($coursefilter eq 'category') {
4404: my $instcode = &instcode_from_coursefilter();
4405: if ($instcode eq '.') {
4406: $description .= &mt('All courses in domain').' - ';
4407: } else {
4408: $description .= &mt('Courses in domain with institutional code: [_1]',$instcode).' - ';
4409: }
4410: } elsif ($coursefilter eq 'selected') {
4411: $description .= &mt('Selected courses in domain').' - ';
4412: } elsif ($coursefilter eq 'all') {
4413: $description .= &mt('All courses in domain').' - ';
4414: }
4415: } elsif ($env{'form.roletype'} eq 'community') {
4416: if ($coursefilter eq 'selected') {
4417: $description .= &mt('Selected communities in domain').' - ';
4418: } elsif ($coursefilter eq 'all') {
4419: $description .= &mt('All communities in domain').' - ';
4420: }
4421: }
4422: if ($statusmode eq 'Expired') {
4423: $description .= &mt('users with expired [_1] roles',$showfilter);
4424: } elsif ($statusmode eq 'Future') {
4425: $description .= &mt('users with future [_1] roles',$showfilter);
4426: } elsif ($statusmode eq 'Active') {
4427: $description .= &mt('users with active [_1] roles',$showfilter);
4428: } else {
4429: if ($rolefilter eq 'Any') {
4430: $description .= &mt('all users');
4431: } else {
4432: $description .= &mt('users with [_1] roles',$rolefilter);
4433: }
4434: }
4435: }
4436: }
4437: return $description;
4438: }
4439:
4440: sub viewable_section {
4441: my ($permission) = @_;
4442: my $viewablesec;
4443: if (ref($permission) eq 'HASH') {
4444: if (exists($permission->{'view_section'})) {
4445: $viewablesec = $permission->{'view_section'};
4446: } elsif (exists($permission->{'cusr_section'})) {
4447: $viewablesec = $permission->{'cusr_section'};
4448: }
4449: }
4450: return $viewablesec;
4451: }
4452:
4453:
4454: #################################################
4455: #################################################
4456: sub show_drop_list {
4457: my ($r,$classlist,$nosort,$permission,$crstype) = @_;
4458: my $cid = $env{'request.course.id'};
4459: my ($cnum,$cdom) = &get_course_identity($cid);
4460: if (! exists($env{'form.sortby'})) {
4461: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
4462: ['sortby']);
4463: }
4464: my $sortby = $env{'form.sortby'};
4465: if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
4466: $sortby = 'username';
4467: }
4468: my $action = "drop";
4469: my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
4470: $r->print(<<END);
4471: <input type="hidden" name="sortby" value="$sortby" />
4472: <input type="hidden" name="action" value="$action" />
4473: <input type="hidden" name="state" value="done" />
4474: <script type="text/javascript" language="Javascript">
4475: // <![CDATA[
4476: $check_uncheck_js
4477: // ]]>
4478: </script>
4479: <input type="hidden" name="phase" value="four" />
4480: END
4481: my ($indexhash,$keylist) = &make_keylist_array();
4482: my $studentcount = 0;
4483: if (ref($classlist) eq 'HASH') {
4484: foreach my $student (keys(%{$classlist})) {
4485: my $sdata = $classlist->{$student};
4486: my $status = $sdata->[$indexhash->{'status'}];
4487: my $section = $sdata->[$indexhash->{'section'}];
4488: if ($status ne 'Active') {
4489: delete($classlist->{$student});
4490: next;
4491: }
4492: if ($env{'request.course.sec'} ne '') {
4493: if ($section ne $env{'request.course.sec'}) {
4494: delete($classlist->{$student});
4495: next;
4496: }
4497: }
4498: $studentcount ++;
4499: }
4500: }
4501: if (!$studentcount) {
4502: my $msg = '';
4503: if ($crstype eq 'Community') {
4504: $msg = &mt('There are no members to drop.');
4505: } else {
4506: $msg = &mt('There are no students to drop.');
4507: }
4508: $r->print('<p class="LC_info">'.$msg.'</p>');
4509: return;
4510: }
4511: my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
4512: $classlist,$keylist,$cdom,$cnum);
4513: my %lt=&Apache::lonlocal::texthash('usrn' => "username",
4514: 'dom' => "domain",
4515: 'id' => "ID",
4516: 'sn' => "student name",
4517: 'mn' => "member name",
4518: 'sec' => "section",
4519: 'start' => "start date",
4520: 'end' => "end date",
4521: 'groups' => "active groups",
4522: );
4523: my $nametitle = $lt{'sn'};
4524: if ($crstype eq 'Community') {
4525: $nametitle = $lt{'mn'};
4526: }
4527: if ($nosort) {
4528: $r->print(&Apache::loncommon::start_data_table().
4529: &Apache::loncommon::start_data_table_header_row());
4530: $r->print(<<END);
4531: <th> </th>
4532: <th>$lt{'usrn'}</th>
4533: <th>$lt{'dom'}</th>
4534: <th>$lt{'id'}</th>
4535: <th>$nametitle</th>
4536: <th>$lt{'sec'}</th>
4537: <th>$lt{'start'}</th>
4538: <th>$lt{'end'}</th>
4539: <th>$lt{'groups'}</th>
4540: END
4541: $r->print(&Apache::loncommon::end_data_table_header_row());
4542: } else {
4543: $r->print(&Apache::loncommon::start_data_table().
4544: &Apache::loncommon::start_data_table_header_row());
4545: $r->print(<<END);
4546: <th> </th>
4547: <th>
4548: <a href="/adm/createuser?action=$action&sortby=username">$lt{'usrn'}</a>
4549: </th><th>
4550: <a href="/adm/createuser?action=$action&sortby=domain">$lt{'dom'}</a>
4551: </th><th>
4552: <a href="/adm/createuser?action=$action&sortby=id">$lt{'id'}</a>
4553: </th><th>
4554: <a href="/adm/createuser?action=$action&sortby=fullname">$nametitle</a>
4555: </th><th>
4556: <a href="/adm/createuser?action=$action&sortby=section">$lt{'sec'}</a>
4557: </th><th>
4558: <a href="/adm/createuser?action=$action&sortby=start">$lt{'start'}</a>
4559: </th><th>
4560: <a href="/adm/createuser?action=$action&sortby=end">$lt{'end'}</a>
4561: </th><th>
4562: <a href="/adm/createuser?action=$action&sortby=groups">$lt{'groups'}</a>
4563: </th>
4564: END
4565: $r->print(&Apache::loncommon::end_data_table_header_row());
4566: }
4567: #
4568: # Sort the students
4569: my $index = $indexhash->{$sortby};
4570: my $second = $indexhash->{'username'};
4571: my $third = $indexhash->{'domain'};
4572: my @Sorted_Students = sort {
4573: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
4574: ||
4575: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
4576: ||
4577: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
4578: } (keys(%{$classlist}));
4579: foreach my $student (@Sorted_Students) {
4580: my $error;
4581: my $sdata = $classlist->{$student};
4582: my $username = $sdata->[$indexhash->{'username'}];
4583: my $domain = $sdata->[$indexhash->{'domain'}];
4584: my $section = $sdata->[$indexhash->{'section'}];
4585: my $name = $sdata->[$indexhash->{'fullname'}];
4586: my $id = $sdata->[$indexhash->{'id'}];
4587: my $start = $sdata->[$indexhash->{'start'}];
4588: my $end = $sdata->[$indexhash->{'end'}];
4589: my $groups = $classgroups->{$student};
4590: my $active_groups;
4591: if (ref($groups->{active}) eq 'HASH') {
4592: $active_groups = join(', ',keys(%{$groups->{'active'}}));
4593: }
4594: if (! defined($start) || $start == 0) {
4595: $start = &mt('none');
4596: } else {
4597: $start = &Apache::lonlocal::locallocaltime($start);
4598: }
4599: if (! defined($end) || $end == 0) {
4600: $end = &mt('none');
4601: } else {
4602: $end = &Apache::lonlocal::locallocaltime($end);
4603: }
4604: my $studentkey = $student.':'.$section;
4605: my $startitem = '<input type="hidden" name="'.$studentkey.'_start" value="'.$sdata->[$indexhash->{'start'}].'" />';
4606: #
4607: $r->print(&Apache::loncommon::start_data_table_row());
4608: $r->print(<<"END");
4609: <td><input type="checkbox" name="droplist" value="$studentkey" /></td>
4610: <td>$username</td>
4611: <td>$domain</td>
4612: <td>$id</td>
4613: <td>$name</td>
4614: <td>$section</td>
4615: <td>$start $startitem</td>
4616: <td>$end</td>
4617: <td>$active_groups</td>
4618: END
4619: $r->print(&Apache::loncommon::end_data_table_row());
4620: }
4621: $r->print(&Apache::loncommon::end_data_table().'<br />');
4622: %lt=&Apache::lonlocal::texthash(
4623: 'dp' => "Drop Students",
4624: 'dm' => "Drop Members",
4625: 'ca' => "check all",
4626: 'ua' => "uncheck all",
4627: );
4628: my $btn = $lt{'dp'};
4629: if ($crstype eq 'Community') {
4630: $btn = $lt{'dm'};
4631: }
4632: $r->print(<<"END");
4633: <p>
4634: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)" />
4635: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)" />
4636: </p>
4637: <p>
4638: <input type="submit" value="$btn" />
4639: </p>
4640: END
4641: return;
4642: }
4643:
4644: #
4645: # Print out the initial form to get the file containing a list of users
4646: #
4647: sub print_first_users_upload_form {
4648: my ($r,$context) = @_;
4649: my $str;
4650: $str = '<input type="hidden" name="phase" value="two" />';
4651: $str .= '<input type="hidden" name="action" value="upload" />';
4652: $str .= '<input type="hidden" name="state" value="got_file" />';
4653:
4654: $str .= &Apache::grades::checkforfile_js();
4655:
4656: $str .= '<h2>'.&mt('Upload a file containing information about users').'</h2>'."\n";
4657:
4658: # Excel and CSV Help
4659: $str .= '<div class="LC_columnSection">'
4660: .&Apache::loncommon::help_open_topic("Course_Create_Class_List",
4661: &mt("How do I create a users list from a spreadsheet"))
4662: .' '.&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
4663: &mt("How do I create a CSV file from a spreadsheet"))
4664: ."</div>\n";
4665: $str .= &Apache::lonhtmlcommon::start_pick_box()
4666: .&Apache::lonhtmlcommon::row_title(&mt('File'));
4667: if (&Apache::lonlocal::current_language() ne 'en') {
4668: if ($context eq 'course') {
4669: $str .= '<p class="LC_info">'."\n"
4670: .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.')."\n"
4671: .'</p>'."\n";
4672: }
4673: }
4674: $str .= &Apache::loncommon::upfile_select_html()
4675: .&Apache::lonhtmlcommon::row_closure()
4676: .&Apache::lonhtmlcommon::row_title(
4677: '<label for="noFirstLine">'
4678: .&mt('Ignore First Line')
4679: .'</label>')
4680: .'<input type="checkbox" name="noFirstLine" id="noFirstLine" />'
4681: .&Apache::lonhtmlcommon::row_closure(1)
4682: .&Apache::lonhtmlcommon::end_pick_box();
4683:
4684: $str .= '<p>'
4685: .'<input type="button" name="fileupload" value="'.&mt('Next').'"'
4686: .' onclick="javascript:checkUpload(this.form);" />'
4687: .'</p>';
4688:
4689: $r->print($str);
4690: return;
4691: }
4692:
4693: # ================================================= Drop/Add from uploaded file
4694: sub upfile_drop_add {
4695: my ($r,$context,$permission,$showcredits) = @_;
4696: my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
4697: if ($datatoken ne '') {
4698: &Apache::loncommon::load_tmp_file($r,$datatoken);
4699: }
4700: my @userdata=&Apache::loncommon::upfile_record_sep();
4701: if($env{'form.noFirstLine'}){shift(@userdata);}
4702: my @keyfields = split(/\,/,$env{'form.keyfields'});
4703: my %fields=();
4704: for (my $i=0; $i<=$env{'form.nfields'}; $i++) {
4705: if ($env{'form.upfile_associate'} eq 'reverse') {
4706: if ($env{'form.f'.$i} ne 'none') {
4707: $fields{$keyfields[$i]}=$env{'form.f'.$i};
4708: }
4709: } else {
4710: $fields{$env{'form.f'.$i}}=$keyfields[$i];
4711: }
4712: }
4713: #
4714: # Store the field choices away
4715: my @storefields = qw/username names fname mname lname gen id
4716: sec ipwd email role domain inststatus/;
4717: if ($showcredits) {
4718: push (@storefields,'credits');
4719: }
4720: my %fieldstype;
4721: foreach my $field (@storefields) {
4722: $env{'form.'.$field.'_choice'}=$fields{$field};
4723: $fieldstype{$field.'_choice'} = 'scalar';
4724: }
4725: &Apache::loncommon::store_course_settings('enrollment_upload',\%fieldstype);
4726: my ($cid,$crstype,$setting,$crsdom,$crsnum,$oldcrsuserdoms);
4727: if ($context eq 'domain') {
4728: $setting = $env{'form.roleaction'};
4729: }
4730: if ($env{'request.course.id'} ne '') {
4731: $cid = $env{'request.course.id'};
4732: $crstype = &Apache::loncommon::course_type();
4733: $crsdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
4734: $crsnum = $env{'course.'.$env{'request.course.id'}.'.num'};
4735: } elsif ($setting eq 'course') {
4736: if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) {
4737: $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'};
4738: $crstype = &Apache::loncommon::course_type($cid);
4739: $crsdom = $env{'form.dcdomain'};
4740: $crsnum = $env{'form.dccourse'};
4741: if (exists($env{'course.'.$cid.'.internal.userdomains'})) {
4742: $oldcrsuserdoms = 1;
4743: }
4744: my %coursedesc = &Apache::lonnet::coursedescription($cid,{ one_time => 1 });
4745: $env{'course.'.$cid.'.internal.userdomains'} = $coursedesc{'internal.userdomains'};
4746: }
4747: }
4748: my ($startdate,$enddate) = &get_dates_from_form();
4749: if ($env{'form.makedatesdefault'}) {
4750: $r->print(&make_dates_default($startdate,$enddate,$context,$crstype));
4751: }
4752: # Determine domain and desired host (home server)
4753: my $defdom=$env{'request.role.domain'};
4754: my $domain;
4755: if ($env{'form.defaultdomain'} ne '') {
4756: if (($context eq 'course') || ($setting eq 'course')) {
4757: if ($env{'form.defaultdomain'} eq $crsdom) {
4758: $domain = $env{'form.defaultdomain'};
4759: } else {
4760: if (&Apache::lonnet::will_trust('enroll',$crsdom,$env{'form.defaultdomain'})) {
4761: $domain = $env{'form.defaultdomain'};
4762: } else {
4763: $r->print('<span class="LC_error">'.&mt('Error').': '.
4764: &mt('Enrollment of users not permitted for specified default domain: [_1].',
4765: &Apache::lonnet::domain($env{'form.defaultdomain'},'description')).'</span>');
4766: return 'untrusted';
4767: }
4768: }
4769: } elsif ($context eq 'author') {
4770: if ($env{'form.defaultdomain'} eq $defdom) {
4771: $domain = $env{'form.defaultdomain'};
4772: } else {
4773: if ((&Apache::lonnet::will_trust('othcoau',$defdom,$env{'form.defaultdomain'})) &&
4774: (&Apache::lonnet::will_trust('coaurem',$env{'form.defaultdomain'},$defdom))) {
4775: $domain = $env{'form.defaultdomain'};
4776: } else {
4777: $r->print('<span class="LC_error">'.&mt('Error').': '.
4778: &mt('Addition of users not permitted for specified default domain: [_1].',
4779: &Apache::lonnet::domain($env{'form.defaultdomain'},'description')).'</span>');
4780: return 'untrusted';
4781: }
4782: }
4783: } elsif (($context eq 'domain') && ($setting eq 'domain')) {
4784: if ($env{'form.defaultdomain'} eq $defdom) {
4785: $domain = $env{'form.defaultdomain'};
4786: } else {
4787: if (&Apache::lonnet::will_trust('domroles',$defdom,$env{'form.defaultdomain'})) {
4788: $domain = $env{'form.defaultdomain'};
4789: } else {
4790: $r->print('<span class="LC_error">'.&mt('Error').': '.
4791: &mt('Addition of users not permitted for specified default domain: [_1].',
4792: &Apache::lonnet::domain($env{'form.defaultdomain'},'description')).'</span>');
4793: return 'untrusted';
4794: }
4795: }
4796: }
4797: } else {
4798: $domain = $defdom;
4799: }
4800: my $desiredhost = $env{'form.lcserver'};
4801: if (lc($desiredhost) eq 'default') {
4802: $desiredhost = undef;
4803: } else {
4804: my %home_servers = &Apache::lonnet::get_servers($defdom,'library');
4805: if (! exists($home_servers{$desiredhost})) {
4806: $r->print('<p class="LC_error">'.&mt('Error').': '.
4807: &mt('Invalid home server specified').'</p>');
4808: return 'invalidhome';
4809: }
4810: }
4811: # Determine authentication mechanism
4812: my $changeauth;
4813: if ($context eq 'domain') {
4814: $changeauth = $env{'form.changeauth'};
4815: }
4816: my $amode = '';
4817: my $genpwd = '';
4818: my @genpwdfail;
4819: if ($env{'form.login'} eq 'krb') {
4820: $amode='krb';
4821: $amode.=$env{'form.krbver'};
4822: $genpwd=$env{'form.krbarg'};
4823: } elsif ($env{'form.login'} eq 'int') {
4824: $amode='internal';
4825: if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
4826: $genpwd=$env{'form.intarg'};
4827: @genpwdfail =
4828: &Apache::loncommon::check_passwd_rules($domain,$genpwd);
4829: }
4830: } elsif ($env{'form.login'} eq 'loc') {
4831: $amode='localauth';
4832: if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
4833: $genpwd=$env{'form.locarg'};
4834: }
4835: } elsif ($env{'form.login'} eq 'lti') {
4836: $amode='lti';
4837: }
4838: if ($amode =~ /^krb/) {
4839: if (! defined($genpwd) || $genpwd eq '') {
4840: $r->print('<span class="Error">'.
4841: &mt('Unable to enroll users').' '.
4842: &mt('No Kerberos domain was specified.').'</span></p>');
4843: $amode = ''; # This causes the loop below to be skipped
4844: }
4845: }
4846: my ($defaultsec,$defaultrole,$defaultcredits,$commoncredits);
4847: if ($context eq 'domain') {
4848: if ($setting eq 'domain') {
4849: $defaultrole = $env{'form.defaultrole'};
4850: } elsif ($setting eq 'course') {
4851: $defaultrole = $env{'form.courserole'};
4852: $defaultsec = $env{'form.sections'};
4853: if ($showcredits) {
4854: $commoncredits = $env{'form.credits'};
4855: if ($crstype ne 'Community') {
4856: my %coursehash=&Apache::lonnet::coursedescription($cid);
4857: $defaultcredits = $coursehash{'internal.defaultcredits'};
4858: }
4859: }
4860: }
4861: } elsif ($context eq 'author') {
4862: $defaultrole = $env{'form.defaultrole'};
4863: } elsif ($context eq 'course') {
4864: $defaultrole = $env{'form.defaultrole'};
4865: $defaultsec = $env{'form.sections'};
4866: if ($showcredits) {
4867: $commoncredits = $env{'form.credits'};
4868: $defaultcredits = $env{'course.'.$cid.'.internal.defaultcredits'};
4869: }
4870: }
4871: # Check to see if user information can be changed
4872: my @userinfo = ('firstname','middlename','lastname','generation',
4873: 'permanentemail','id');
4874: my %canmodify;
4875: if (&Apache::lonnet::allowed('mau',$domain)) {
4876: push(@userinfo,'inststatus');
4877: foreach my $field (@userinfo) {
4878: $canmodify{$field} = 1;
4879: }
4880: }
4881: my (%userlist,%modifiable_fields,@poss_roles);
4882: my $secidx = &Apache::loncoursedata::CL_SECTION();
4883: my @courseroles = &roles_by_context('course',1,$crstype);
4884: if (!&Apache::lonnet::allowed('mau',$domain)) {
4885: if ($context eq 'course' || $context eq 'author') {
4886: @poss_roles = &curr_role_permissions($context,'','',$crstype);
4887: my @statuses = ('active','future');
4888: my ($indexhash,$keylist) = &make_keylist_array();
4889: my %info;
4890: foreach my $role (@poss_roles) {
4891: %{$modifiable_fields{$role}} = &can_modify_userinfo($context,$domain,
4892: \@userinfo,[$role]);
4893: }
4894: if ($context eq 'course') {
4895: my ($cnum,$cdom) = &get_course_identity();
4896: my $roster = &Apache::loncoursedata::get_classlist();
4897: if (ref($roster) eq 'HASH') {
4898: %userlist = %{$roster};
4899: }
4900: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
4901: \@statuses,\@poss_roles);
4902: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
4903: \%advrolehash,$permission);
4904: } elsif ($context eq 'author') {
4905: my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
4906: \@statuses,\@poss_roles);
4907: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
4908: \%cstr_roles,$permission);
4909: }
4910: }
4911: }
4912: if ($datatoken eq '') {
4913: $r->print('<p class="LC_error">'.&mt('Error').': '.
4914: &mt('Invalid datatoken').'</p>');
4915: return 'missingdata';
4916: }
4917: if ( $domain eq &LONCAPA::clean_domain($domain)
4918: && ($amode ne '')) {
4919: #######################################
4920: ## Add/Modify Users ##
4921: #######################################
4922: if ($context eq 'course') {
4923: $r->print('<h3>'.&mt('Enrolling Users')."</h3>\n<p>\n");
4924: } elsif ($context eq 'author') {
4925: $r->print('<h3>'.&mt('Updating Co-authors')."</h3>\n<p>\n");
4926: } else {
4927: $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n");
4928: }
4929: $r->rflush;
4930: my (%got_role_approvals,%got_instdoms,%process_by,%instdoms,
4931: %pending,%reject,%notifydc,%status,%unauthorized,%currqueued);
4932:
4933: my %counts = (
4934: user => 0,
4935: auth => 0,
4936: role => 0,
4937: );
4938: my $flushc=0;
4939: my %student=();
4940: my (%curr_groups,@sections,@cleansec,$defaultwarn,$groupwarn);
4941: my %userchg;
4942: if ($context eq 'course' || $setting eq 'course') {
4943: if ($context eq 'course') {
4944: # Get information about course groups
4945: %curr_groups = &Apache::longroup::coursegroups();
4946: } elsif ($setting eq 'course') {
4947: if ($cid) {
4948: %curr_groups =
4949: &Apache::longroup::coursegroups($env{'form.dcdomain'},
4950: $env{'form.dccourse'});
4951: }
4952: }
4953: # determine section number
4954: if ($defaultsec =~ /,/) {
4955: push(@sections,split(/,/,$defaultsec));
4956: } else {
4957: push(@sections,$defaultsec);
4958: }
4959: # remove non alphanumeric values from section
4960: foreach my $item (@sections) {
4961: $item =~ s/\W//g;
4962: if ($item eq "none" || $item eq 'all') {
4963: $defaultwarn = &mt('Default section name [_1] could not be used as it is a reserved word.',$item);
4964: } elsif ($item ne '' && exists($curr_groups{$item})) {
4965: $groupwarn = &mt('Default section name "[_1]" is the name of a course group. Section names and group names must be distinct.',$item);
4966: } elsif ($item ne '') {
4967: push(@cleansec,$item);
4968: }
4969: }
4970: if ($defaultwarn) {
4971: $r->print($defaultwarn.'<br />');
4972: }
4973: if ($groupwarn) {
4974: $r->print($groupwarn.'<br />');
4975: }
4976: }
4977: my (%curr_rules,%got_rules,%alerts,%cancreate);
4978: my %customroles = &my_custom_roles($crstype);
4979: my @permitted_roles =
4980: &roles_on_upload($context,$setting,$crstype,%customroles);
4981: my %longtypes = &Apache::lonlocal::texthash(
4982: official => 'Institutional',
4983: unofficial => 'Non-institutional',
4984: );
4985: my $newuserdom = $env{'request.role.domain'};
4986: map { $cancreate{$_} = &can_create_user($newuserdom,$context,$_); } keys(%longtypes);
4987: # Get new users list
4988: my (%existinguser,%userinfo,%disallow,%rulematch,%inst_results,%alerts,%checkuname,
4989: %showpasswdrules,$haspasswdmap);
4990: my $counter = -1;
4991: my (%willtrust,%trustchecked);
4992: foreach my $line (@userdata) {
4993: $counter ++;
4994: my @secs;
4995: my %entries=&Apache::loncommon::record_sep($line);
4996: # Determine user name
4997: $entries{$fields{'username'}} =~ s/^\s+|\s+$//g;
4998: unless (($entries{$fields{'username'}} eq '') ||
4999: (!defined($entries{$fields{'username'}}))) {
5000: my ($fname, $mname, $lname,$gen) = ('','','','');
5001: if (defined($fields{'names'})) {
5002: ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
5003: /([^\,]+)\,\s*(\w+)\s*(.*)$/);
5004: } else {
5005: if (defined($fields{'fname'})) {
5006: $fname=$entries{$fields{'fname'}};
5007: }
5008: if (defined($fields{'mname'})) {
5009: $mname=$entries{$fields{'mname'}};
5010: }
5011: if (defined($fields{'lname'})) {
5012: $lname=$entries{$fields{'lname'}};
5013: }
5014: if (defined($fields{'gen'})) {
5015: $gen=$entries{$fields{'gen'}};
5016: }
5017: }
5018:
5019: if ($entries{$fields{'username'}}
5020: ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
5021: my $nowhitespace;
5022: if ($entries{$fields{'username'}} =~ /\s/) {
5023: $nowhitespace = ' - '.&mt('usernames may not contain spaces.');
5024: }
5025: $disallow{$counter} =
5026: &mt('Unacceptable username [_1] for user [_2] [_3] [_4] [_5]',
5027: '"<b>'.$entries{$fields{'username'}}.'</b>"',
5028: $fname,$mname,$lname,$gen).$nowhitespace;
5029: next;
5030: } else {
5031: $entries{$fields{'domain'}} =~ s/^\s+|\s+$//g;
5032: if ($entries{$fields{'domain'}}
5033: ne &LONCAPA::clean_domain($entries{$fields{'domain'}})) {
5034: $disallow{$counter} =
5035: &mt('Unacceptable domain [_1] for user [_2] [_3] [_4] [_5]',
5036: '"<b>'.$entries{$fields{'domain'}}.'</b>"',
5037: $fname,$mname,$lname,$gen);
5038: next;
5039: } elsif ($entries{$fields{'domain'}} ne $domain) {
5040: my $possdom = $entries{$fields{'domain'}};
5041: if ($context eq 'course' || $setting eq 'course') {
5042: unless ($trustchecked{$possdom}) {
5043: $willtrust{$possdom} = &Apache::lonnet::will_trust('enroll',$domain,$possdom);
5044: $trustchecked{$possdom} = 1;
5045: }
5046: } elsif ($context eq 'author') {
5047: unless ($trustchecked{$possdom}) {
5048: $willtrust{$possdom} = &Apache::lonnet::will_trust('othcoau',$domain,$possdom);
5049: }
5050: if ($willtrust{$possdom}) {
5051: $willtrust{$possdom} = &Apache::lonnet::will_trust('coaurem',$possdom,$domain);
5052: }
5053: }
5054: unless ($willtrust{$possdom}) {
5055: $disallow{$counter} =
5056: &mt('Unacceptable domain [_1] for user [_2] [_3] [_4] [_5]',
5057: '"<b>'.$possdom.'</b>"',
5058: $fname,$mname,$lname,$gen);
5059: next;
5060: }
5061: }
5062: my $username = $entries{$fields{'username'}};
5063: my $userdomain = $entries{$fields{'domain'}};
5064: if ($userdomain eq '') {
5065: $userdomain = $domain;
5066: }
5067: if (defined($fields{'sec'})) {
5068: if (defined($entries{$fields{'sec'}})) {
5069: $entries{$fields{'sec'}} =~ s/\W//g;
5070: my $item = $entries{$fields{'sec'}};
5071: if ($item eq "none" || $item eq 'all') {
5072: $disallow{$counter} =
5073: &mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.',
5074: '<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item);
5075: next;
5076: } elsif (exists($curr_groups{$item})) {
5077: $disallow{$counter} =
5078: &mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.',
5079: '<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item).' '.
5080: &mt('Section names and group names must be distinct.');
5081: next;
5082: } else {
5083: push(@secs,$item);
5084: }
5085: }
5086: }
5087: if ($env{'request.course.sec'} ne '') {
5088: @secs = ($env{'request.course.sec'});
5089: if (ref($userlist{$username.':'.$userdomain}) eq 'ARRAY') {
5090: my $currsec = $userlist{$username.':'.$userdomain}[$secidx];
5091: if ($currsec ne $env{'request.course.sec'}) {
5092: $disallow{$counter} =
5093: &mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".',
5094: '<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$secs[0]);
5095: if ($currsec eq '') {
5096: $disallow{$counter} .=
5097: &mt('This user already has an active/future student role in the course, unaffiliated to any section.');
5098:
5099: } else {
5100: $disallow{$counter} .=
5101: &mt('This user already has an active/future role in section "[_1]" of the course.',$currsec);
5102: }
5103: $disallow{$counter} .=
5104: '<br />'.
5105: &mt('Although your current role has privileges to add students to section "[_1]", you do not have privileges to modify existing enrollments in other sections.',
5106: $secs[0]);
5107: next;
5108: }
5109: }
5110: } elsif ($context eq 'course' || $setting eq 'course') {
5111: if (@secs == 0) {
5112: @secs = @cleansec;
5113: }
5114: }
5115: # determine id number
5116: my $id='';
5117: if (defined($fields{'id'})) {
5118: if (defined($entries{$fields{'id'}})) {
5119: $id=$entries{$fields{'id'}};
5120: }
5121: $id=~tr/A-Z/a-z/;
5122: }
5123: # determine email address
5124: my $email='';
5125: if (defined($fields{'email'})) {
5126: $entries{$fields{'email'}} =~ s/^\s+|\s+$//g;
5127: if (defined($entries{$fields{'email'}})) {
5128: $email=$entries{$fields{'email'}};
5129: unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
5130: }
5131: }
5132: # determine affiliation
5133: my $inststatus='';
5134: if (defined($fields{'inststatus'})) {
5135: if (defined($entries{$fields{'inststatus'}})) {
5136: $inststatus=$entries{$fields{'inststatus'}};
5137: }
5138: }
5139: # determine user password
5140: my $password;
5141: my $passwdfromfile;
5142: if (defined($fields{'ipwd'})) {
5143: if ($entries{$fields{'ipwd'}}) {
5144: $password=$entries{$fields{'ipwd'}};
5145: $passwdfromfile = 1;
5146: if ($env{'form.login'} eq 'int') {
5147: my $uhome=&Apache::lonnet::homeserver($username,$userdomain);
5148: if (($uhome eq 'no_host') || ($changeauth)) {
5149: my @brokepwdrules =
5150: &Apache::loncommon::check_passwd_rules($domain,$password);
5151: if (@brokepwdrules) {
5152: $disallow{$counter} = &mt('[_1]: Password included in file for this user did not meet requirements.',
5153: '<b>'.$username.'</b>');
5154: map { $showpasswdrules{$_} = 1; } @brokepwdrules;
5155: next;
5156: }
5157: }
5158: }
5159: }
5160: }
5161: unless ($passwdfromfile) {
5162: if ($env{'form.login'} eq 'int') {
5163: if (@genpwdfail) {
5164: my $uhome=&Apache::lonnet::homeserver($username,$userdomain);
5165: if (($uhome eq 'no_host') || ($changeauth)) {
5166: $disallow{$counter} = &mt('[_1]: No specific password in file for this user; default password did not meet requirements',
5167: '<b>'.$username.'</b>');
5168: unless ($haspasswdmap) {
5169: map { $showpasswdrules{$_} = 1; } @genpwdfail;
5170: $haspasswdmap = 1;
5171: }
5172: }
5173: next;
5174: }
5175: }
5176: $password = $genpwd;
5177: }
5178: # determine user role
5179: my $role = '';
5180: if (defined($fields{'role'})) {
5181: if ($entries{$fields{'role'}}) {
5182: $entries{$fields{'role'}} =~ s/(\s+$|^\s+)//g;
5183: if ($entries{$fields{'role'}} ne '') {
5184: if (grep(/^\Q$entries{$fields{'role'}}\E$/,@permitted_roles)) {
5185: $role = $entries{$fields{'role'}};
5186: }
5187: }
5188: if ($role eq '') {
5189: my $rolestr = join(', ',@permitted_roles);
5190: $disallow{$counter} =
5191: &mt('[_1]: You do not have permission to add the requested role [_2] for the user.'
5192: ,'<b>'.$entries{$fields{'username'}}.'</b>'
5193: ,$entries{$fields{'role'}})
5194: .'<br />'
5195: .&mt('Allowable role(s) is/are: [_1].',$rolestr);
5196: next;
5197: }
5198: }
5199: }
5200: if ($role eq '') {
5201: $role = $defaultrole;
5202: }
5203: # Clean up whitespace
5204: foreach (\$id,\$fname,\$mname,\$lname,\$gen,\$inststatus) {
5205: $$_ =~ s/(\s+$|^\s+)//g;
5206: }
5207: my $credits;
5208: if ($showcredits) {
5209: if (($role eq 'st') && ($crstype ne 'Community')) {
5210: $credits = $entries{$fields{'credits'}};
5211: if ($credits ne '') {
5212: $credits =~ s/[^\d\.]//g;
5213: }
5214: if ($credits eq '') {
5215: $credits = $commoncredits;
5216: }
5217: if ($credits eq $defaultcredits) {
5218: undef($credits);
5219: }
5220: }
5221: }
5222: # check against rules
5223: my $checkid = 0;
5224: my $newuser = 0;
5225: my $uhome=&Apache::lonnet::homeserver($username,$userdomain);
5226: if ($uhome eq 'no_host') {
5227: if ($userdomain ne $newuserdom) {
5228: if ($context eq 'course') {
5229: $disallow{$counter} =
5230: &mt('[_1]: The domain specified ([_2]) is different to that of the course.',
5231: '<b>'.$username.'</b>',$userdomain);
5232: } elsif ($context eq 'author') {
5233: $disallow{$counter} =
5234: &mt('[_1]: The domain specified ([_2]) is different to that of the author.',
5235: '<b>'.$username.'</b>',$userdomain);
5236: } else {
5237: $disallow{$counter} =
5238: &mt('[_1]: The domain specified ([_2]) is different to that of your current role.',
5239: '<b>'.$username.'</b>',$userdomain);
5240: }
5241: $disallow{$counter} .=
5242: &mt('The user does not already exist, and you may not create a new user in a different domain.');
5243: next;
5244: } else {
5245: unless (($password ne '') || ($env{'form.login'} eq 'loc') || ($env{'form.login'} eq 'lti')) {
5246: $disallow{$counter} =
5247: &mt('[_1]: This is a new user but no default password was provided, and the authentication type requires one.',
5248: '<b>'.$username.'</b>');
5249: next;
5250: }
5251: }
5252: $checkid = 1;
5253: $newuser = 1;
5254: $checkuname{$username.':'.$newuserdom} = { 'newuser' => $newuser, 'id' => $id };
5255: } else {
5256: if ($context eq 'course' || $context eq 'author') {
5257: if ($userdomain eq $domain ) {
5258: if ($role eq '') {
5259: my @checkroles;
5260: foreach my $role (@poss_roles) {
5261: my $endkey;
5262: if ($role ne 'st') {
5263: $endkey = ':'.$role;
5264: }
5265: if (exists($userlist{$username.':'.$userdomain.$endkey})) {
5266: if (!grep(/^\Q$role\E$/,@checkroles)) {
5267: push(@checkroles,$role);
5268: }
5269: }
5270: }
5271: if (@checkroles > 0) {
5272: %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles);
5273: }
5274: } elsif (ref($modifiable_fields{$role}) eq 'HASH') {
5275: %canmodify = %{$modifiable_fields{$role}};
5276: }
5277: }
5278: my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id);
5279: for (my $i=0; $i<@newinfo; $i++) {
5280: if (${$newinfo[$i]} ne '') {
5281: if (!$canmodify{$userinfo[$i]}) {
5282: ${$newinfo[$i]} = '';
5283: }
5284: }
5285: }
5286: }
5287: if ($id) {
5288: $existinguser{$userdomain}{$username} = $id;
5289: }
5290: }
5291: $userinfo{$counter} = {
5292: username => $username,
5293: domain => $userdomain,
5294: fname => $fname,
5295: mname => $mname,
5296: lname => $lname,
5297: gen => $gen,
5298: email => $email,
5299: id => $id,
5300: password => $password,
5301: inststatus => $inststatus,
5302: role => $role,
5303: sections => \@secs,
5304: credits => $credits,
5305: newuser => $newuser,
5306: checkid => $checkid,
5307: };
5308: }
5309: }
5310: } # end of foreach (@userdata)
5311: if ($counter > -1) {
5312: my $total = $counter + 1;
5313: my %checkids;
5314: if ((keys(%existinguser)) || (keys(%checkuname))) {
5315: $r->print(&mt('Please be patient -- checking for institutional data ...'));
5316: $r->rflush();
5317: if (keys(%existinguser)) {
5318: foreach my $dom (keys(%existinguser)) {
5319: if (ref($existinguser{$dom}) eq 'HASH') {
5320: my %idhash = &Apache::lonnet::idrget($dom,keys(%{$existinguser{$dom}}));
5321: foreach my $username (keys(%{$existinguser{$dom}})) {
5322: if ($idhash{$username} ne $existinguser{$dom}{$username}) {
5323: $checkids{$username.':'.$dom} = {
5324: 'id' => $existinguser{$dom}{$username},
5325: };
5326: }
5327: }
5328: if (keys(%checkids)) {
5329: &Apache::loncommon::user_rule_check(\%checkids,{ 'id' => 1 },
5330: \%alerts,\%rulematch,
5331: \%inst_results,\%curr_rules,
5332: \%got_rules);
5333: }
5334: }
5335: }
5336: }
5337: if (keys(%checkuname)) {
5338: &Apache::loncommon::user_rule_check(\%checkuname,{ 'username' => 1, 'id' => 1, },
5339: \%alerts,\%rulematch,\%inst_results,
5340: \%curr_rules,\%got_rules);
5341: }
5342: $r->print(' '.&mt('done').'<br /><br />');
5343: $r->rflush();
5344: }
5345: my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($r,$total);
5346: $r->print('<ul>');
5347: for (my $i=0; $i<=$counter; $i++) {
5348: if ($disallow{$i}) {
5349: $r->print('<li>'.$disallow{$i}.'</li>');
5350: } elsif (ref($userinfo{$i}) eq 'HASH') {
5351: my $password = $userinfo{$i}{'password'};
5352: my $newuser = $userinfo{$i}{'newuser'};
5353: my $checkid = $userinfo{$i}{'checkid'};
5354: my $id = $userinfo{$i}{'id'};
5355: my $role = $userinfo{$i}{'role'};
5356: my @secs;
5357: if (ref($userinfo{$i}{'sections'}) eq 'ARRAY') {
5358: @secs = @{$userinfo{$i}{'sections'}};
5359: }
5360: my $fname = $userinfo{$i}{'fname'};
5361: my $mname = $userinfo{$i}{'mname'};
5362: my $lname = $userinfo{$i}{'lname'};
5363: my $gen = $userinfo{$i}{'gen'};
5364: my $email = $userinfo{$i}{'email'};
5365: my $inststatus = $userinfo{$i}{'inststatus'};
5366: my $credits = $userinfo{$i}{'credits'};
5367: my $username = $userinfo{$i}{'username'};
5368: my $userdomain = $userinfo{$i}{'domain'};
5369: my $user = $username.':'.$userdomain;
5370: if ($newuser) {
5371: if (ref($alerts{'username'}) eq 'HASH') {
5372: if (ref($alerts{'username'}{$userdomain}) eq 'HASH') {
5373: if ($alerts{'username'}{$userdomain}{$username}) {
5374: $r->print('<li>'.
5375: &mt('[_1]: matches the username format at your institution, but is not known to your directory service.','<b>'.$username.'</b>').'<br />'.
5376: &mt('Consequently, the user was not created.').'</li>');
5377: next;
5378: }
5379: }
5380: }
5381: if (ref($inst_results{$user}) eq 'HASH') {
5382: if ($inst_results{$user}{'firstname'} ne '') {
5383: $fname = $inst_results{$user}{'firstname'};
5384: }
5385: if ($inst_results{$user}{'middlename'} ne '') {
5386: $mname = $inst_results{$user}{'middlename'};
5387: }
5388: if ($inst_results{$user}{'lasttname'} ne '') {
5389: $lname = $inst_results{$user}{'lastname'};
5390: }
5391: if ($inst_results{$user}{'permanentemail'} ne '') {
5392: $email = $inst_results{$user}{'permanentemail'};
5393: }
5394: if ($inst_results{$user}{'id'} ne '') {
5395: $id = $inst_results{$user}{'id'};
5396: $checkid = 0;
5397: }
5398: if (ref($inst_results{$user}{'inststatus'}) eq 'ARRAY') {
5399: $inststatus = join(':',@{$inst_results{$user}{'inststatus'}});
5400: }
5401: }
5402: if (($checkid) && ($id ne '')) {
5403: if (ref($alerts{'id'}) eq 'HASH') {
5404: if (ref($alerts{'id'}{$userdomain}) eq 'HASH') {
5405: if ($alerts{'id'}{$userdomain}{$username}) {
5406: $r->print('<li>'.
5407: &mt('[_1]: has a student/employee ID matching the format at your institution, but the ID is not found by your directory service.',
5408: '<b>'.$username.'</b>').'<br />'.
5409: &mt('Consequently, the user was not created.').'</li>');
5410: next;
5411: }
5412: }
5413: }
5414: }
5415: my $usertype = 'unofficial';
5416: if (ref($rulematch{$user}) eq 'HASH') {
5417: if ($rulematch{$user}{'username'}) {
5418: $usertype = 'official';
5419: }
5420: }
5421: unless ($cancreate{$usertype}) {
5422: my $showtype = $longtypes{$usertype};
5423: $r->print('<li>'.
5424: &mt('[_1]: The user does not exist, and you are not permitted to create users of type: [_2].','<b>'.$username.'</b>',$showtype).'</li>');
5425: next;
5426: }
5427: } elsif ($id ne '') {
5428: if (exists($checkids{$user})) {
5429: $checkid = 1;
5430: if (ref($alerts{'id'}) eq 'HASH') {
5431: if (ref($alerts{'id'}{$userdomain}) eq 'HASH') {
5432: if ($alerts{'id'}{$userdomain}{$username}) {
5433: $r->print('<li>'.
5434: &mt('[_1]: has a student/employee ID matching the format at your institution, but the ID is not found by your directory service.',
5435: '<b>'.$username.'</b>').'<br />'.
5436: &mt('Consequently, the ID was not changed.').'</li>');
5437: $id = '';
5438: }
5439: }
5440: }
5441: }
5442: }
5443: my $multiple = 0;
5444: my ($userresult,$authresult,$roleresult,$idresult);
5445: my (%userres,%authres,%roleres,%idres);
5446: my $singlesec = '';
5447: if ($role eq 'st') {
5448: if (($context eq 'domain') && ($changeauth eq 'Yes') && (!$newuser)) {
5449: if ((&Apache::lonnet::allowed('mau',$userdomain)) &&
5450: (&Apache::lonnet::homeserver($username,$userdomain) ne 'no_host')) {
5451: if ((($amode =~ /^krb4|krb5|internal$/) && $password ne '') ||
5452: ($amode eq 'localauth')) {
5453: $authresult =
5454: &Apache::lonnet::modifyuserauth($userdomain,$username,$amode,$password);
5455: }
5456: }
5457: }
5458: my $sec;
5459: if (ref($userinfo{$i}{'sections'}) eq 'ARRAY') {
5460: if (@secs > 0) {
5461: $sec = $secs[0];
5462: }
5463: }
5464: if ($userdomain ne $env{'request.role.domain'}) {
5465: my $item = "/$crsdom/$crsnum" ;
5466: if ($sec ne '') {
5467: $item .= "/$sec";
5468: }
5469: $item .= '_st';
5470: next if (&restricted_dom($context,$item,$userdomain,$username,$role,$startdate,
5471: $enddate,$crsdom,$crsnum,$sec,$credits,\%process_by,
5472: \%instdoms,\%got_role_approvals,\%got_instdoms,\%reject,
5473: \%pending,\%notifydc,\%status,\%unauthorized,\%currqueued));
5474: }
5475: &modifystudent($userdomain,$username,$cid,$sec,
5476: $desiredhost,$context);
5477: $roleresult =
5478: &Apache::lonnet::modifystudent
5479: ($userdomain,$username,$id,$amode,$password,
5480: $fname,$mname,$lname,$gen,$sec,$enddate,
5481: $startdate,$env{'form.forceid'},
5482: $desiredhost,$email,'manual','',$cid,
5483: '',$context,$inststatus,$credits);
5484: $userresult = $roleresult;
5485: } else {
5486: my $possrole;
5487: if ($role ne '') {
5488: if ($context eq 'course' || $setting eq 'course') {
5489: if ($customroles{$role}) {
5490: $role = 'cr_'.$env{'user.domain'}.'_'.
5491: $env{'user.name'}.'_'.$role;
5492: }
5493: $possrole = $role;
5494: if ($possrole =~ /^cr_/) {
5495: $possrole =~ s{_}{/}g;
5496: }
5497: if (($role ne 'cc') && ($role ne 'co')) {
5498: if (@secs > 1) {
5499: $multiple = 1;
5500: my $prefix = "/$crsdom/$crsnum";
5501: foreach my $sec (@secs) {
5502: if ($userdomain ne $env{'request.role.domain'}) {
5503: my $item = $prefix;
5504: if ($sec ne '') {
5505: $item .= "/$sec";
5506: }
5507: $item .= '_'.$possrole;
5508: next if (&restricted_dom($context,$item,$userdomain,$username,$possrole,
5509: $startdate,$enddate,$crsdom,$crsnum,$sec,
5510: $credits,\%process_by,\%instdoms,\%got_role_approvals,
5511: \%got_instdoms,\%reject,\%pending,\%notifydc,
5512: \%status,\%unauthorized,\%currqueued));
5513: }
5514: ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
5515: &modifyuserrole($context,$setting,
5516: $changeauth,$cid,$userdomain,$username,
5517: $id,$amode,$password,$fname,
5518: $mname,$lname,$gen,$sec,
5519: $env{'form.forceid'},$desiredhost,
5520: $email,$role,$enddate,
5521: $startdate,$checkid,$inststatus);
5522: }
5523: } elsif (@secs > 0) {
5524: $singlesec = $secs[0];
5525: }
5526: }
5527: } else {
5528: $possrole = $role;
5529: }
5530: }
5531: if (!$multiple) {
5532: if (($userdomain ne $env{'request.role.domain'}) && ($role ne '')) {
5533: my $item = "/$crsdom/$crsnum";
5534: if ($singlesec ne '') {
5535: $item .= "/$singlesec";
5536: }
5537: $item .= '_'.$possrole;
5538: next if (&restricted_dom($context,$item,$userdomain,$username,$possrole,$startdate,$enddate,
5539: $crsdom,$crsnum,$singlesec,$credits,\%process_by,\%instdoms,
5540: \%got_role_approvals,\%got_instdoms,\%reject,\%pending,\%notifydc,
5541: \%status,\%unauthorized,\%currqueued));
5542: }
5543: ($userresult,$authresult,$roleresult,$idresult) =
5544: &modifyuserrole($context,$setting,
5545: $changeauth,$cid,$userdomain,$username,
5546: $id,$amode,$password,$fname,
5547: $mname,$lname,$gen,$singlesec,
5548: $env{'form.forceid'},$desiredhost,
5549: $email,$role,$enddate,$startdate,
5550: $checkid,$inststatus);
5551: }
5552: }
5553: if ($multiple) {
5554: foreach my $sec (sort(keys(%userres))) {
5555: $flushc =
5556: &user_change_result($r,$userres{$sec},$authres{$sec},
5557: $roleres{$sec},$idres{$sec},\%counts,$flushc,
5558: $username,$userdomain,\%userchg);
5559:
5560: }
5561: } else {
5562: $flushc =
5563: &user_change_result($r,$userresult,$authresult,
5564: $roleresult,$idresult,\%counts,$flushc,
5565: $username,$userdomain,\%userchg);
5566: }
5567: }
5568: &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last user');
5569: } # end of loop
5570: $r->print('</ul>');
5571: &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
5572: if (($context eq 'domain') && ($setting eq 'course')) {
5573: unless ($oldcrsuserdoms) {
5574: if (exists($env{'course.'.$cid.'.internal.userdomains'})) {
5575: delete($env{'course.'.$cid.'.internal.userdomains'});
5576: }
5577: }
5578: }
5579: }
5580: # Flush the course logs so reverse user roles immediately updated
5581: $r->register_cleanup(\&Apache::lonnet::flushcourselogs);
5582: $r->print("</p>\n<p>\n".&mt('Processed [quant,_1,user].',$counts{'user'}).
5583: "</p>\n");
5584: if ($counts{'role'} > 0) {
5585: $r->print("<p>\n".
5586: &mt('Roles added for [quant,_1,user].',$counts{'role'}).' '.
5587: &mt('If a user is currently logged-in to LON-CAPA, any new roles which are active will be available when the user next logs in.').
5588: "</p>\n");
5589: } else {
5590: $r->print('<p>'.&mt('No roles added').'</p>');
5591: }
5592: if ($counts{'auth'} > 0) {
5593: $r->print("<p>\n".
5594: &mt('Authentication changed for [_1] existing users.',
5595: $counts{'auth'})."</p>\n");
5596: }
5597: $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules));
5598: $r->print(&passwdrule_alerts($domain,\%showpasswdrules));
5599: if ((keys(%reject)) || (keys(%unauthorized))) {
5600: $r->print(&print_roles_rejected($context,\%reject,\%unauthorized));
5601: }
5602: if ((keys(%pending)) || (keys(%currqueued))) {
5603: $r->print(&print_roles_queued($context,\%pending,\%notifydc,\%currqueued));
5604: }
5605: #####################################
5606: # Display list of students to drop #
5607: #####################################
5608: if ($env{'form.fullup'} eq 'yes') {
5609: $r->print('<h3>'.&mt('Students to Drop')."</h3>\n");
5610: # Get current classlist
5611: my $classlist = &Apache::loncoursedata::get_classlist();
5612: if (! defined($classlist)) {
5613: $r->print('<p class="LC_info">'.
5614: &mt('There are no students with current/future access to the course.').
5615: '</p>'."\n");
5616: } elsif (ref($classlist) eq 'HASH') {
5617: # Remove the students we just added from the list of students.
5618: foreach my $line (@userdata) {
5619: my %entries=&Apache::loncommon::record_sep($line);
5620: unless (($entries{$fields{'username'}} eq '') ||
5621: (!defined($entries{$fields{'username'}}))) {
5622: delete($classlist->{$entries{$fields{'username'}}.
5623: ':'.$domain});
5624: }
5625: }
5626: # Print out list of dropped students.
5627: &show_drop_list($r,$classlist,'nosort',$permission);
5628: }
5629: }
5630: } # end of unless
5631: return 'ok';
5632: }
5633:
5634: sub print_namespacing_alerts {
5635: my ($domain,$alerts,$curr_rules) = @_;
5636: my $output;
5637: if (ref($alerts) eq 'HASH') {
5638: if (keys(%{$alerts}) > 0) {
5639: if (ref($alerts->{'username'}) eq 'HASH') {
5640: foreach my $dom (sort(keys(%{$alerts->{'username'}}))) {
5641: my $count;
5642: if (ref($alerts->{'username'}{$dom}) eq 'HASH') {
5643: $count = keys(%{$alerts->{'username'}{$dom}});
5644: }
5645: my $domdesc = &Apache::lonnet::domain($domain,'description');
5646: if (ref($curr_rules->{$dom}) eq 'HASH') {
5647: $output .= &Apache::loncommon::instrule_disallow_msg(
5648: 'username',$domdesc,$count,'upload');
5649: }
5650: $output .= &Apache::loncommon::user_rule_formats($dom,
5651: $domdesc,$curr_rules->{$dom}{'username'},
5652: 'username');
5653: }
5654: }
5655: if (ref($alerts->{'id'}) eq 'HASH') {
5656: foreach my $dom (sort(keys(%{$alerts->{'id'}}))) {
5657: my $count;
5658: if (ref($alerts->{'id'}{$dom}) eq 'HASH') {
5659: $count = keys(%{$alerts->{'id'}{$dom}});
5660: }
5661: my $domdesc = &Apache::lonnet::domain($domain,'description');
5662: if (ref($curr_rules->{$dom}) eq 'HASH') {
5663: $output .= &Apache::loncommon::instrule_disallow_msg(
5664: 'id',$domdesc,$count,'upload');
5665: }
5666: $output .= &Apache::loncommon::user_rule_formats($dom,
5667: $domdesc,$curr_rules->{$dom}{'id'},'id');
5668: }
5669: }
5670: }
5671: }
5672: }
5673:
5674: sub passwdrule_alerts {
5675: my ($domain,$passwdrules) = @_;
5676: my $warning;
5677: if (ref($passwdrules) eq 'HASH') {
5678: my %showrules = %{$passwdrules};
5679: if (keys(%showrules)) {
5680: my %passwdconf = &Apache::lonnet::get_passwdconf($domain);
5681: $warning = '<b>'.&mt('Password requirement(s) unmet for one or more users:').'</b><ul>';
5682: if ($showrules{'min'}) {
5683: my $min = $passwdconf{'min'};
5684: if ($min eq '') {
5685: $min = $Apache::lonnet::passwdmin;
5686: }
5687: $warning .= '<li>'.&mt('minimum [quant,_1,character]',$min).'</li>';
5688: }
5689: if ($showrules{'max'}) {
5690: $warning .= '<li>'.&mt('maximum [quant,_1,character]',$passwdconf{'max'}).'</li>';
5691: }
5692: if ($showrules{'uc'}) {
5693: $warning .= '<li>'.&mt('contain at least one upper case letter').'</li>';
5694: }
5695: if ($showrules{'lc'}) {
5696: $warning .= '<li>'.&mt('contain at least one lower case letter').'</li>';
5697: }
5698: if ($showrules{'num'}) {
5699: $warning .= '<li>'.&mt('contain at least one number').'</li>';
5700: }
5701: if ($showrules{'spec'}) {
5702: $warning .= '<li>'.&mt('contain at least one non-alphanumeric').'</li>';
5703: }
5704: $warning .= '</ul>';
5705: }
5706: }
5707: return $warning;
5708: }
5709:
5710: sub user_change_result {
5711: my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc,
5712: $username,$userdomain,$userchg) = @_;
5713: my $okresult = 0;
5714: my @status;
5715: if ($userresult ne 'ok') {
5716: if ($userresult =~ /^error:(.+)$/) {
5717: my $error = $1;
5718: push(@status,
5719: &mt('[_1]: Unable to add/modify: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
5720: }
5721: } else {
5722: $counts->{'user'} ++;
5723: $okresult = 1;
5724: }
5725: if ($authresult ne 'ok') {
5726: if ($authresult =~ /^error:(.+)$/) {
5727: my $error = $1;
5728: push(@status,
5729: &mt('[_1]: Unable to modify authentication: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
5730: }
5731: } else {
5732: $counts->{'auth'} ++;
5733: $okresult = 1;
5734: }
5735: if ($roleresult ne 'ok') {
5736: if ($roleresult =~ /^error:(.+)$/) {
5737: my $error = $1;
5738: push(@status,
5739: &mt('[_1]: Unable to add role: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
5740: }
5741: } else {
5742: $counts->{'role'} ++;
5743: $okresult = 1;
5744: }
5745: if ($okresult) {
5746: $flushc++;
5747: $userchg->{$username.':'.$userdomain}=1;
5748: if ($flushc>15) {
5749: $r->rflush;
5750: $flushc=0;
5751: }
5752: }
5753: if ($idresult) {
5754: push(@status,$idresult);
5755: }
5756: if (@status) {
5757: $r->print('<li>'.join('<br />',@status).'</li>');
5758: }
5759: return $flushc;
5760: }
5761:
5762: # ========================================================= Menu Phase Two Drop
5763: sub print_drop_menu {
5764: my ($r,$context,$permission,$crstype) = @_;
5765: my $heading;
5766: if ($crstype eq 'Community') {
5767: $heading = &mt("Drop Members");
5768: } else {
5769: $heading = &mt("Drop Students");
5770: }
5771: $r->print('<h3>'.$heading.'</h3>'."\n".
5772: '<form name="studentform" method="post" action="">'."\n");
5773: my $classlist = &Apache::loncoursedata::get_classlist();
5774: if (! defined($classlist)) {
5775: my $msg = '';
5776: if ($crstype eq 'Community') {
5777: $msg = &mt('There are no members currently enrolled.');
5778: } else {
5779: $msg = &mt('There are no students currently enrolled.');
5780: }
5781: $r->print('<p class="LC_info">'.$msg."</p>\n");
5782: } else {
5783: &show_drop_list($r,$classlist,'nosort',$permission,$crstype);
5784: }
5785: $r->print('</form>');
5786: return;
5787: }
5788:
5789: # ================================================================== Phase four
5790:
5791: sub update_user_list {
5792: my ($r,$context,$setting,$choice,$crstype) = @_;
5793: my $now = time;
5794: my $count=0;
5795: if ($context eq 'course') {
5796: $crstype = &Apache::loncommon::course_type();
5797: }
5798: my (@changelist,%got_role_approvals,%got_instdoms,%process_by,%instdoms,
5799: %pending,%reject,%notifydc,%status,%unauthorized,%currqueued);
5800: if ($choice eq 'drop') {
5801: @changelist = &Apache::loncommon::get_env_multiple('form.droplist');
5802: } else {
5803: @changelist = &Apache::loncommon::get_env_multiple('form.actionlist');
5804: }
5805: my %result_text = ( ok => { 'revoke' => 'Revoked',
5806: 'delete' => 'Deleted',
5807: 'reenable' => 'Re-enabled',
5808: 'activate' => 'Activated',
5809: 'chgdates' => 'Changed Access Dates for',
5810: 'chgsec' => 'Changed section(s) for',
5811: 'drop' => 'Dropped',
5812: },
5813: error => {'revoke' => 'revoking',
5814: 'delete' => 'deleting',
5815: 'reenable' => 're-enabling',
5816: 'activate' => 'activating',
5817: 'chgdates' => 'changing access dates for',
5818: 'chgsec' => 'changing section for',
5819: 'drop' => 'dropping',
5820: },
5821: );
5822: my ($startdate,$enddate);
5823: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
5824: ($startdate,$enddate) = &get_dates_from_form();
5825: }
5826: foreach my $item (@changelist) {
5827: my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,
5828: @sections,$scopestem,$singlesec,$showsecs,$warn_singlesec,
5829: $nothingtodo,$keepnosection,$credits,$instsec,$cdom,$cnum);
5830: if ($choice eq 'drop') {
5831: ($uname,$udom,$sec) = split(/:/,$item,-1);
5832: $role = 'st';
5833: $cid = $env{'request.course.id'};
5834: $scopestem = '/'.$cid;
5835: $scopestem =~s/\_/\//g;
5836: if ($sec eq '') {
5837: $scope = $scopestem;
5838: } else {
5839: $scope = $scopestem.'/'.$sec;
5840: }
5841: } elsif ($context eq 'course') {
5842: ($uname,$udom,$role,$sec,$type,$locktype,$credits,$instsec) =
5843: split(/\:/,$item,8);
5844: $instsec = &unescape($instsec);
5845: $cid = $env{'request.course.id'};
5846: $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5847: $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
5848: $scopestem = '/'.$cid;
5849: $scopestem =~s/\_/\//g;
5850: if ($sec eq '') {
5851: $scope = $scopestem;
5852: } else {
5853: $scope = $scopestem.'/'.$sec;
5854: }
5855: } elsif ($context eq 'author') {
5856: ($uname,$udom,$role) = split(/\:/,$item,-1);
5857: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
5858: $cdom = $env{'user.domain'};
5859: $cnum = $env{'user.name'};
5860: } elsif ($context eq 'domain') {
5861: if ($setting eq 'domain') {
5862: ($role,$uname,$udom) = split(/\:/,$item,-1);
5863: $scope = '/'.$env{'request.role.domain'}.'/';
5864: $cdom = $env{'request.role.domain'};
5865: } elsif ($setting eq 'author') {
5866: ($uname,$udom,$role,$scope) = split(/\:/,$item);
5867: (undef,$cdom,$cnum) = split(/\//,$scope);
5868: } elsif ($setting eq 'course') {
5869: ($uname,$udom,$role,$cid,$sec,$type,$locktype,$credits,$instsec) =
5870: split(/\:/,$item,9);
5871: ($cdom,$cnum) = split('_',$cid);
5872: $instsec = &unescape($instsec);
5873: $scope = '/'.$cid;
5874: $scope =~s/\_/\//g;
5875: if ($sec ne '') {
5876: $scope .= '/'.$sec;
5877: }
5878: }
5879: }
5880: my $plrole = &Apache::lonnet::plaintext($role,$crstype);
5881: my $start = $env{'form.'.$item.'_start'};
5882: my $end = $env{'form.'.$item.'_end'};
5883: if ($choice eq 'drop') {
5884: # drop students
5885: $end = $now;
5886: $type = 'manual';
5887: $result =
5888: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
5889: } elsif ($choice eq 'revoke') {
5890: # revoke or delete user role
5891: $end = $now;
5892: if ($role eq 'st') {
5893: $result =
5894: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5895: } else {
5896: $result =
5897: &Apache::lonnet::revokerole($udom,$uname,$scope,$role,
5898: '','',$context);
5899: }
5900: } elsif ($choice eq 'delete') {
5901: if ($role eq 'st') {
5902: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5903: }
5904: $result =
5905: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
5906: $start,1,'',$context);
5907: } else {
5908: #reenable, activate, change access dates or change section
5909: if ($choice ne 'chgsec') {
5910: $start = $startdate;
5911: $end = $enddate;
5912: }
5913: my $id = $scope.'_'.$role;
5914: if ($choice eq 'reenable') {
5915: next if (&restricted_dom($context,$id,$udom,$uname,$role,$now,$end,$cdom,$cnum,
5916: $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals,
5917: \%got_instdoms,\%reject,\%pending,\%notifydc,
5918: \%status,\%unauthorized,\%currqueued));
5919: if ($role eq 'st') {
5920: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5921: } else {
5922: $result =
5923: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
5924: $now,'','',$context);
5925: }
5926: } elsif ($choice eq 'activate') {
5927: next if (&restricted_dom($context,$id,$udom,$uname,$role,$now,$end,$cdom,$cnum,
5928: $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals,
5929: \%got_instdoms,\%reject,\%pending,\%notifydc,
5930: \%status,\%unauthorized,\%currqueued));
5931: if ($role eq 'st') {
5932: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5933: } else {
5934: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
5935: $now,'','',$context);
5936: }
5937: } elsif ($choice eq 'chgdates') {
5938: next if (&restricted_dom($context,$id,$udom,$uname,$role,$start,$end,$cdom,$cnum,
5939: $sec,$credits,\%process_by,\%instdoms,\%got_role_approvals,
5940: \%got_instdoms,\%reject,\%pending,\%notifydc,
5941: \%status,\%unauthorized,\%currqueued));
5942: if ($role eq 'st') {
5943: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5944: } else {
5945: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
5946: $start,'','',$context);
5947: }
5948: } elsif ($choice eq 'chgsec') {
5949: my (@newsecs,$revresult,$nochg,@retained);
5950: if (($role ne 'cc') && ($role ne 'co')) {
5951: my @secs = sort(split(/,/,$env{'form.newsecs'}));
5952: if (@secs) {
5953: my %curr_groups = &Apache::longroup::coursegroups();
5954: foreach my $sec (@secs) {
5955: next if (($sec =~ /\W/) || ($sec eq 'none') ||
5956: (exists($curr_groups{$sec})));
5957: push(@newsecs,$sec);
5958: }
5959: }
5960: }
5961: # remove existing section if not to be retained.
5962: if (!$env{'form.retainsec'} || ($role eq 'st')) {
5963: if ($sec eq '') {
5964: if (@newsecs == 0) {
5965: $result = 'ok';
5966: $nochg = 1;
5967: $nothingtodo = 1;
5968: } else {
5969: $revresult =
5970: &Apache::lonnet::revokerole($udom,$uname,
5971: $scope,$role,
5972: '','',$context);
5973: }
5974: } else {
5975: if (@newsecs > 0) {
5976: if (grep(/^\Q$sec\E$/,@newsecs)) {
5977: push(@retained,$sec);
5978: } else {
5979: $revresult =
5980: &Apache::lonnet::revokerole($udom,$uname,
5981: $scope,$role,
5982: '','',$context);
5983: }
5984: } else {
5985: $revresult =
5986: &Apache::lonnet::revokerole($udom,$uname,
5987: $scope,$role,
5988: '','',$context);
5989: }
5990: }
5991: } else {
5992: if ($sec eq '') {
5993: $nochg = 1;
5994: $keepnosection = 1;
5995: } else {
5996: push(@retained,$sec);
5997: }
5998: }
5999: # add new sections
6000: my (@diffs,@shownew);
6001: if (@retained) {
6002: @diffs = &Apache::loncommon::compare_arrays(\@retained,\@newsecs);
6003: } else {
6004: @diffs = @newsecs;
6005: }
6006: if (@newsecs == 0) {
6007: if ($nochg) {
6008: $result = 'ok';
6009: $nothingtodo = 1;
6010: } else {
6011: if ($role eq 'st') {
6012: $result =
6013: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
6014: } else {
6015: my $newscope = $scopestem;
6016: $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start,'','',$context);
6017: }
6018: }
6019: $showsecs = &mt('No section');
6020: } elsif (@diffs == 0) {
6021: $result = 'ok';
6022: $nothingtodo = 1;
6023: } else {
6024: foreach my $newsec (@newsecs) {
6025: if (!grep(/^\Q$newsec\E$/,@retained)) {
6026: if ($role eq 'st') {
6027: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
6028: if (@newsecs > 1) {
6029: my $showsingle;
6030: if ($newsec eq '') {
6031: $showsingle = &mt('No section');
6032: } else {
6033: $showsingle = $newsec;
6034: }
6035: if ($crstype eq 'Community') {
6036: $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.','<i>'.$showsingle.'</i>');
6037: } else {
6038: $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.','<i>'.$showsingle.'</i>');
6039: }
6040: $showsecs = $showsingle;
6041: last;
6042: } else {
6043: if ($newsec eq '') {
6044: $showsecs = &mt('No section');
6045: } else {
6046: $showsecs = $newsec;
6047: }
6048: }
6049: } else {
6050: my $newscope = $scopestem;
6051: if ($newsec ne '') {
6052: $newscope .= '/'.$newsec;
6053: push(@shownew,$newsec);
6054: }
6055: $result = &Apache::lonnet::assignrole($udom,$uname,
6056: $newscope,$role,$end,$start);
6057:
6058: }
6059: }
6060: }
6061: }
6062: unless ($role eq 'st') {
6063: unless ($showsecs) {
6064: my @tolist = sort(@shownew,@retained);
6065: if ($keepnosection) {
6066: push(@tolist,&mt('No section'));
6067: }
6068: $showsecs = join(', ',@tolist);
6069: }
6070: }
6071: }
6072: }
6073: my $extent = $scope;
6074: if ($choice eq 'drop' || $context eq 'course') {
6075: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
6076: if ($cdesc) {
6077: $extent = $cdesc;
6078: }
6079: }
6080: if ($result eq 'ok' || $result eq 'ok:') {
6081: my $dates;
6082: if (($choice eq 'chgsec') || ($choice eq 'chgdates')) {
6083: $dates = &dates_feedback($start,$end,$now);
6084: }
6085: if ($choice eq 'chgsec') {
6086: if ($nothingtodo) {
6087: $r->print(&mt("Section assignment for role of '[_1]' in [_2] for '[_3]' unchanged.",$plrole,$extent,'<i>'.
6088: &Apache::loncommon::plainname($uname,$udom).
6089: '</i>').' ');
6090: if ($sec eq '') {
6091: $r->print(&mt('[_1]No section[_2] - [_3]','<b>','</b>',$dates));
6092: } else {
6093: $r->print(&mt('Section(s): [_1] - [_2]',
6094: '<b>'.$showsecs.'</b>',$dates));
6095: }
6096: $r->print('<br />');
6097: } else {
6098: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]' to [_4] - [_5]",$plrole,$extent,
6099: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>',
6100: '<b>'.$showsecs.'</b>',$dates).'<br />');
6101: $count ++;
6102: }
6103: if ($warn_singlesec) {
6104: $r->print('<div class="LC_warning">'.$warn_singlesec.'</div>');
6105: }
6106: } elsif ($choice eq 'chgdates') {
6107: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]' - [_4]",$plrole,$extent,
6108: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>',
6109: $dates).'<br />');
6110: $count ++;
6111: } else {
6112: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]'.",$plrole,$extent,
6113: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>').
6114: '<br />');
6115: $count ++;
6116: }
6117: } else {
6118: $r->print(
6119: &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for '[_3]': [_4].",
6120: $plrole,$extent,
6121: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>',
6122: $result).'<br />');
6123: }
6124: }
6125: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n");
6126: if ($choice eq 'drop') {
6127: $r->print('<input type="hidden" name="action" value="listusers" />'."\n".
6128: '<input type="hidden" name="Status" value="Active" />'."\n".
6129: '<input type="hidden" name="showrole" value="st" />'."\n");
6130: } else {
6131: foreach my $item ('action','sortby','roletype','showrole','Status','secfilter','grpfilter') {
6132: if ($env{'form.'.$item} ne '') {
6133: $r->print('<input type="hidden" name="'.$item.'" value="'.$env{'form.'.$item}.
6134: '" />'."\n");
6135: }
6136: }
6137: }
6138: $r->print('<p><b>'.&mt("$result_text{'ok'}{$choice} [quant,_1,user role,user roles,no user roles].",$count).'</b></p>');
6139: if ($count > 0) {
6140: if ($choice eq 'revoke' || $choice eq 'drop') {
6141: $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.').'</p>');
6142: }
6143: # Flush the course logs so reverse user roles immediately updated
6144: $r->register_cleanup(\&Apache::lonnet::flushcourselogs);
6145: }
6146: if ($env{'form.makedatesdefault'}) {
6147: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
6148: $r->print(&make_dates_default($startdate,$enddate,$context,$crstype));
6149: }
6150: }
6151: if ((keys(%reject)) || (keys(%unauthorized))) {
6152: $r->print(&print_roles_rejected($context,\%reject,\%unauthorized));
6153: }
6154: if ((keys(%pending)) || (keys(%currqueued))) {
6155: $r->print(&print_roles_queued($context,\%pending,\%notifydc,\%currqueued));
6156: }
6157: my $linktext = &mt('Display User Lists');
6158: if ($choice eq 'drop') {
6159: $linktext = &mt('Display current class roster');
6160: }
6161: $r->print(
6162: &Apache::lonhtmlcommon::actionbox(
6163: ['<a href="javascript:document.studentform.submit()">'.$linktext.'</a>'])
6164: .'</form>'."\n");
6165: }
6166:
6167: sub dates_feedback {
6168: my ($start,$end,$now) = @_;
6169: my $dates;
6170: if ($start < $now) {
6171: if ($end == 0) {
6172: $dates = &mt('role(s) active now; no end date');
6173: } elsif ($end > $now) {
6174: $dates = &mt('role(s) active now; ends [_1].',&Apache::lonlocal::locallocaltime($end));
6175: } else {
6176: $dates = &mt('role(s) expired: [_1].',&Apache::lonlocal::locallocaltime($end));
6177: }
6178: } else {
6179: if ($end == 0 || $end > $now) {
6180: $dates = &mt('future role(s); starts: [_1].',&Apache::lonlocal::locallocaltime($start));
6181: } else {
6182: $dates = &mt('role(s) expired: [_1].',&Apache::lonlocal::locallocaltime($end));
6183: }
6184: }
6185: return $dates;
6186: }
6187:
6188: sub classlist_drop {
6189: my ($scope,$uname,$udom,$now) = @_;
6190: my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
6191: if (&Apache::lonnet::is_course($cdom,$cnum)) {
6192: if (!&active_student_roles($cnum,$cdom,$uname,$udom)) {
6193: my %user;
6194: my $result = &update_classlist($cdom,$cnum,$udom,$uname,\%user,$now);
6195: return &mt('Drop from classlist: [_1]',
6196: '<b>'.$result.'</b>').'<br />';
6197: }
6198: }
6199: }
6200:
6201: sub active_student_roles {
6202: my ($cnum,$cdom,$uname,$udom) = @_;
6203: my %roles =
6204: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
6205: ['future','active'],['st']);
6206: return exists($roles{"$cnum:$cdom:st"});
6207: }
6208:
6209: sub section_check_js {
6210: my $groupslist= &get_groupslist();
6211: my %js_lt = &Apache::lonlocal::texthash(
6212: mayn => 'may not be used as the name for a section, as it is a reserved word.',
6213: plch => 'Please choose a different section name.',
6214: mnot => 'may not be used as a section name, as it is the name of a course group.',
6215: secn => 'Section names and group names must be distinct. Please choose a different section name.',
6216: );
6217: &js_escape(\%js_lt);
6218: return <<"END";
6219: function validate(caller) {
6220: var groups = new Array($groupslist);
6221: var secname = caller.value;
6222: if ((secname == 'all') || (secname == 'none')) {
6223: alert("'"+secname+"' $js_lt{'mayn'}\\n$js_lt{'plch'}");
6224: return 'error';
6225: }
6226: if (secname != '') {
6227: for (var k=0; k<groups.length; k++) {
6228: if (secname == groups[k]) {
6229: alert("'"+secname+"' $js_lt{'mnot'}\\n$js_lt{'secn'}");
6230: return 'error';
6231: }
6232: }
6233: }
6234: return 'ok';
6235: }
6236: END
6237: }
6238:
6239: sub set_login {
6240: my ($dom,$authformkrb,$authformint,$authformloc,$authformlti) = @_;
6241: my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
6242: my $response;
6243: my ($authnum,%can_assign) =
6244: &Apache::loncommon::get_assignable_auth($dom);
6245: if ($authnum) {
6246: $response = &Apache::loncommon::start_data_table();
6247: if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
6248: $response .= &Apache::loncommon::start_data_table_row().
6249: '<td>'.$authformkrb.'</td>'.
6250: &Apache::loncommon::end_data_table_row()."\n";
6251: }
6252: if ($can_assign{'int'}) {
6253: $response .= &Apache::loncommon::start_data_table_row().
6254: '<td>'.$authformint.'</td>'.
6255: &Apache::loncommon::end_data_table_row()."\n"
6256: }
6257: if ($can_assign{'loc'}) {
6258: $response .= &Apache::loncommon::start_data_table_row().
6259: '<td>'.$authformloc.'</td>'.
6260: &Apache::loncommon::end_data_table_row()."\n";
6261: }
6262: if ($can_assign{'lti'}) {
6263: $response .= &Apache::loncommon::start_data_table_row().
6264: '<td>'.$authformlti.'</td>'.
6265: &Apache::loncommon::end_data_table_row()."\n";
6266: }
6267: $response .= &Apache::loncommon::end_data_table();
6268: }
6269: return $response;
6270: }
6271:
6272: sub course_sections {
6273: my ($sections_count,$role,$current_sec,$disabled) = @_;
6274: my $output = '';
6275: my @sections = (sort {$a <=> $b} keys(%{$sections_count}));
6276: my $numsec = scalar(@sections);
6277: my $is_selected = ' selected="selected"';
6278: if ($numsec <= 1) {
6279: $output = '<select name="currsec_'.$role.'"'.$disabled.'>'."\n".
6280: ' <option value="">'.&mt('Select').'</option>'."\n";
6281: if ($current_sec eq 'none') {
6282: $output .=
6283: ' <option value=""'.$is_selected.'>'.&mt('No section').'</option>'."\n";
6284: } else {
6285: $output .=
6286: ' <option value="">'.&mt('No section').'</option>'."\n";
6287: }
6288: if ($numsec == 1) {
6289: if ($current_sec eq $sections[0]) {
6290: $output .=
6291: ' <option value="'.$sections[0].'"'.$is_selected.'>'.$sections[0].'</option>'."\n";
6292: } else {
6293: $output .=
6294: ' <option value="'.$sections[0].'" >'.$sections[0].'</option>'."\n";
6295: }
6296: }
6297: } else {
6298: $output = '<select name="currsec_'.$role.'" ';
6299: my $multiple = 4;
6300: if (scalar(@sections) < 4) { $multiple = scalar(@sections); }
6301: if ($role eq 'st') {
6302: $output .= $disabled.'>'."\n".
6303: ' <option value="">'.&mt('Select').'</option>'."\n";
6304: if ($current_sec eq 'none') {
6305: $output .=
6306: ' <option value=""'.$is_selected.'>'.&mt('No section')."</option>\n";
6307: } else {
6308: $output .=
6309: ' <option value="">'.&mt('No section')."</option>\n";
6310: }
6311: } else {
6312: $output .= 'multiple="multiple" size="'.$multiple.'"'.$disabled.'>'."\n";
6313: }
6314: foreach my $sec (@sections) {
6315: if ($current_sec eq $sec) {
6316: $output .= '<option value="'.$sec.'"'.$is_selected.'>'.$sec."</option>\n";
6317: } else {
6318: $output .= '<option value="'.$sec.'">'.$sec."</option>\n";
6319: }
6320: }
6321: }
6322: $output .= '</select>';
6323: return $output;
6324: }
6325:
6326: sub get_groupslist {
6327: my $groupslist;
6328: my %curr_groups = &Apache::longroup::coursegroups();
6329: if (%curr_groups) {
6330: $groupslist = join('","',sort(keys(%curr_groups)));
6331: $groupslist = '"'.$groupslist.'"';
6332: }
6333: return $groupslist;
6334: }
6335:
6336: sub setsections_javascript {
6337: my ($formname,$groupslist,$mode,$checkauth,$crstype,$showcredits) = @_;
6338: my ($checkincluded,$finish,$rolecode,$setsection_js);
6339: if ($mode eq 'upload') {
6340: $checkincluded = 'formname.name == "'.$formname.'"';
6341: $finish = "return 'ok';";
6342: $rolecode = "var role = formname.defaultrole.options[formname.defaultrole.selectedIndex].value;\n";
6343: } elsif ($formname eq 'cu') {
6344: if (($crstype eq 'Course') && ($showcredits)) {
6345: $checkincluded = "((role == 'st') && (formname.elements[i-2].checked == true)) || ((role != 'st') && (formname.elements[i-1].checked == true))";
6346: } else {
6347: $checkincluded = 'formname.elements[i-1].checked == true';
6348: }
6349: if ($checkauth) {
6350: $finish = "var authcheck = auth_check();\n".
6351: " if (authcheck == 'ok') {\n".
6352: " formname.submit();\n".
6353: " }\n";
6354: } else {
6355: $finish = 'formname.submit()';
6356: }
6357: $rolecode = "var match = str.split('_');
6358: var role = match[3];\n";
6359: } elsif (($formname eq 'enrollstudent') || ($formname eq 'selfenroll')) {
6360: $checkincluded = 'formname.name == "'.$formname.'"';
6361: if ($checkauth) {
6362: $finish = "var authcheck = auth_check();\n".
6363: " if (authcheck == 'ok') {\n".
6364: " formname.submit();\n".
6365: " }\n";
6366: } else {
6367: $finish = 'formname.submit()';
6368: }
6369: $rolecode = "var match = str.split('_');
6370: var role = match[1];\n";
6371: } else {
6372: $checkincluded = 'formname.name == "'.$formname.'"';
6373: $finish = "seccheck = 'ok';";
6374: $rolecode = "var match = str.split('_');
6375: var role = match[1];\n";
6376: $setsection_js = "var seccheck = 'alert';";
6377: }
6378: my %alerts = &Apache::lonlocal::texthash(
6379: secd => 'Section designations do not apply to Course Coordinator roles.',
6380: sedn => 'Section designations do not apply to Coordinator roles.',
6381: accr => 'A course coordinator role will be added with access to all sections.',
6382: acor => 'A coordinator role will be added with access to all sections',
6383: inea => 'In each course, each user may only have one student role at a time.',
6384: inco => 'In each community, each user may only have one member role at a time.',
6385: youh => 'You had selected',
6386: secs => 'sections.',
6387: plmo => 'Please modify your selections so they include no more than one section.',
6388: mayn => 'may not be used as the name for a section, as it is a reserved word.',
6389: plch => 'Please choose a different section name.',
6390: mnot => 'may not be used as a section name, as it is the name of a course group.',
6391: secn => 'Section names and group names must be distinct. Please choose a different section name.',
6392: nonw => 'Section names may only contain letters or numbers.',
6393: );
6394: &js_escape(\%alerts);
6395: $setsection_js .= <<"ENDSECCODE";
6396:
6397: function setSections(formname,crstype) {
6398: var re1 = /^currsec_/;
6399: var re2 =/\\W/;
6400: var trimleading = /^\\s+/;
6401: var trimtrailing = /\\s+\$/;
6402: var groups = new Array($groupslist);
6403: for (var i=0;i<formname.elements.length;i++) {
6404: var str = formname.elements[i].name;
6405: if (typeof(str) === "undefined") {
6406: continue;
6407: }
6408: var checkcurr = str.match(re1);
6409: if (checkcurr != null) {
6410: var num = i;
6411: $rolecode
6412: if ($checkincluded) {
6413: if (role == 'cc' || role == 'co') {
6414: if (role == 'cc') {
6415: alert("$alerts{'secd'}\\n$alerts{'accr'}");
6416: } else {
6417: alert("$alerts{'sedn'}\\n$alerts{'acor'}");
6418: }
6419: } else {
6420: var sections = '';
6421: var numsec = 0;
6422: var fromexisting = new Array();
6423: for (var j=0; j<formname.elements[num].length; j++) {
6424: if (formname.elements[num].options[j].selected == true ) {
6425: var addsec = formname.elements[num].options[j].value;
6426: if ((addsec != "") && (addsec != null)) {
6427: fromexisting.push(addsec);
6428: if (numsec == 0) {
6429: sections = addsec;
6430: } else {
6431: sections = sections + "," + addsec;
6432: }
6433: numsec ++;
6434: }
6435: }
6436: }
6437: var newsecs = formname.elements[num+1].value;
6438: var validsecs = new Array();
6439: var validsecstr = '';
6440: var badsecs = new Array();
6441: if (newsecs != null && newsecs != "") {
6442: var numsplit;
6443: if (newsecs.indexOf(',') == -1) {
6444: numsplit = new Array(newsecs);
6445: } else {
6446: numsplit = newsecs.split(/,/g);
6447: }
6448: for (var m=0; m<numsplit.length; m++) {
6449: var newsec = numsplit[m];
6450: newsec = newsec.replace(trimleading,'');
6451: newsec = newsec.replace(trimtrailing,'');
6452: if (re2.test(newsec) == true) {
6453: badsecs.push(newsec);
6454: } else {
6455: if (newsec != '') {
6456: var isnew = 1;
6457: if (fromexisting != null) {
6458: for (var n=0; n<fromexisting.length; n++) {
6459: if (newsec == fromexisting[n]) {
6460: isnew = 0;
6461: }
6462: }
6463: }
6464: if (isnew == 1) {
6465: validsecs.push(newsec);
6466: }
6467: }
6468: }
6469: }
6470: if (badsecs.length > 0) {
6471: alert("$alerts{'nonw'}\\n$alerts{'plch'}");
6472: return;
6473: }
6474: numsec = numsec + validsecs.length;
6475: }
6476: if ((role == 'st') && (numsec > 1)) {
6477: if (crstype == 'Community') {
6478: alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}");
6479: } else {
6480: alert("$alerts{'inco'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}");
6481: }
6482: return;
6483: } else {
6484: if (validsecs != null) {
6485: for (var j=0; j<validsecs.length; j++) {
6486: if (validsecstr == '' || validsecstr == null) {
6487: validsecstr = validsecs[j];
6488: } else {
6489: validsecstr += ','+validsecs[j];
6490: }
6491: if ((validsecs[j] == 'all') ||
6492: (validsecs[j] == 'none')) {
6493: alert("'"+validsecs[j]+"' $alerts{'mayn'}\\n$alerts{'plch'}");
6494: return;
6495: }
6496: for (var k=0; k<groups.length; k++) {
6497: if (validsecs[j] == groups[k]) {
6498: alert("'"+validsecs[j]+"' $alerts{'mnot'}\\n$alerts{'secn'}");
6499: return;
6500: }
6501: }
6502: }
6503: }
6504: }
6505: if ((validsecstr != '') && (validsecstr != null)) {
6506: if ((sections == '') || (sections == null)) {
6507: sections = validsecstr;
6508: } else {
6509: sections = sections + "," + validsecstr;
6510: }
6511: }
6512: formname.elements[num+2].value = sections;
6513: }
6514: }
6515: }
6516: }
6517: $finish
6518: }
6519: ENDSECCODE
6520: return $setsection_js;
6521: }
6522:
6523: sub can_create_user {
6524: my ($dom,$context,$usertype) = @_;
6525: my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
6526: my $cancreate = 1;
6527: if (&Apache::lonnet::allowed('mau',$dom)) {
6528: return $cancreate;
6529: } elsif ($context eq 'domain') {
6530: $cancreate = 0;
6531: return $cancreate;
6532: }
6533: if (ref($domconf{'usercreation'}) eq 'HASH') {
6534: if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') {
6535: if ($context eq 'course' || $context eq 'author' || $context eq 'requestcrs') {
6536: my $creation = $domconf{'usercreation'}{'cancreate'}{$context};
6537: if ($creation eq 'none') {
6538: $cancreate = 0;
6539: } elsif ($creation ne 'any') {
6540: if (defined($usertype)) {
6541: if ($creation ne $usertype) {
6542: $cancreate = 0;
6543: }
6544: }
6545: }
6546: }
6547: }
6548: }
6549: return $cancreate;
6550: }
6551:
6552: sub can_modify_userinfo {
6553: my ($context,$dom,$fields,$userroles) = @_;
6554: my %domconfig =
6555: &Apache::lonnet::get_dom('configuration',['usermodification'],
6556: $dom);
6557: my %canmodify;
6558: if (ref($fields) eq 'ARRAY') {
6559: foreach my $field (@{$fields}) {
6560: $canmodify{$field} = 0;
6561: if (&Apache::lonnet::allowed('mau',$dom)) {
6562: $canmodify{$field} = 1;
6563: } else {
6564: if (ref($domconfig{'usermodification'}) eq 'HASH') {
6565: if (ref($domconfig{'usermodification'}{$context}) eq 'HASH') {
6566: if (ref($userroles) eq 'ARRAY') {
6567: foreach my $role (@{$userroles}) {
6568: my $testrole;
6569: if ($context eq 'selfcreate') {
6570: $testrole = $role;
6571: } else {
6572: if ($role =~ /^cr\//) {
6573: $testrole = 'cr';
6574: } else {
6575: $testrole = $role;
6576: }
6577: }
6578: if (ref($domconfig{'usermodification'}{$context}{$testrole}) eq 'HASH') {
6579: if ($domconfig{'usermodification'}{$context}{$testrole}{$field}) {
6580: $canmodify{$field} = 1;
6581: last;
6582: }
6583: }
6584: }
6585: } else {
6586: foreach my $key (keys(%{$domconfig{'usermodification'}{$context}})) {
6587: if (ref($domconfig{'usermodification'}{$context}{$key}) eq 'HASH') {
6588: if ($domconfig{'usermodification'}{$context}{$key}{$field}) {
6589: $canmodify{$field} = 1;
6590: last;
6591: }
6592: }
6593: }
6594: }
6595: }
6596: } elsif ($context eq 'course') {
6597: if (ref($userroles) eq 'ARRAY') {
6598: if (grep(/^st$/,@{$userroles})) {
6599: $canmodify{$field} = 1;
6600: }
6601: } else {
6602: $canmodify{$field} = 1;
6603: }
6604: }
6605: }
6606: }
6607: }
6608: return %canmodify;
6609: }
6610:
6611: sub can_change_internalpass {
6612: my ($uname,$udom,$crstype,$permission) = @_;
6613: my $canchange;
6614: if (&Apache::lonnet::allowed('mau',$udom)) {
6615: $canchange = 1;
6616: } elsif ((ref($permission) eq 'HASH') && ($permission->{'mip'}) &&
6617: ($udom eq $env{'request.role.domain'})) {
6618: unless ($env{'course.'.$env{'request.course.id'}.'.internal.nopasswdchg'}) {
6619: my ($cnum,$cdom) = &get_course_identity();
6620: if ((&Apache::lonnet::is_course_owner($cdom,$cnum)) && ($udom eq $env{'user.domain'})) {
6621: my @userstatuses = ('default');
6622: my %userenv = &Apache::lonnet::userenvironment($udom,$uname,'inststatus');
6623: if ($userenv{'inststatus'} ne '') {
6624: @userstatuses = split(/:/,$userenv{'inststatus'});
6625: }
6626: my $noupdate = 1;
6627: my %passwdconf = &Apache::lonnet::get_passwdconf($cdom);
6628: if (ref($passwdconf{'crsownerchg'}) eq 'HASH') {
6629: if (ref($passwdconf{'crsownerchg'}{'for'}) eq 'ARRAY') {
6630: foreach my $status (@userstatuses) {
6631: if (grep(/^\Q$status\E$/,@{$passwdconf{'crsownerchg'}{'for'}})) {
6632: undef($noupdate);
6633: last;
6634: }
6635: }
6636: }
6637: }
6638: if ($noupdate) {
6639: return;
6640: }
6641: my %owned = &Apache::lonnet::courseiddump($cdom,'.',1,'.',
6642: $env{'user.name'}.':'.$env{'user.domain'},
6643: undef,undef,undef,'.');
6644: my %roleshash = &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
6645: ['active','future']);
6646: foreach my $key (keys(%roleshash)) {
6647: my ($name,$domain,$role) = split(/:/,$key);
6648: if ($role eq 'st') {
6649: next if (($name eq $cnum) && ($domain eq $cdom));
6650: if ($owned{$domain.'_'.$name}) {
6651: if (ref($owned{$domain.'_'.$name}) eq 'HASH') {
6652: if ($owned{$domain.'_'.$name}{'nopasswdchg'}) {
6653: $noupdate = 1;
6654: last;
6655: }
6656: }
6657: } else {
6658: $noupdate = 1;
6659: last;
6660: }
6661: } else {
6662: $noupdate = 1;
6663: last;
6664: }
6665: }
6666: unless ($noupdate) {
6667: $canchange = 1;
6668: }
6669: }
6670: }
6671: }
6672: return $canchange;
6673: }
6674:
6675: sub check_usertype {
6676: my ($dom,$uname,$rules,$curr_rules,$got_rules) = @_;
6677: my $usertype;
6678: if ((ref($got_rules) eq 'HASH') && (ref($curr_rules) eq 'HASH')) {
6679: if (!$got_rules->{$dom}) {
6680: my %domconfig = &Apache::lonnet::get_dom('configuration',
6681: ['usercreation'],$dom);
6682: if (ref($domconfig{'usercreation'}) eq 'HASH') {
6683: foreach my $item ('username','id') {
6684: if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {
6685: $curr_rules->{$dom}{$item} =
6686: $domconfig{'usercreation'}{$item.'_rule'};
6687: }
6688: }
6689: }
6690: $got_rules->{$dom} = 1;
6691: }
6692: if (ref($rules) eq 'HASH') {
6693: my @user_rules;
6694: if (ref($curr_rules->{$dom}{'username'}) eq 'ARRAY') {
6695: foreach my $rule (keys(%{$rules})) {
6696: if (grep(/^\Q$rule\E/,@{$curr_rules->{$dom}{'username'}})) {
6697: push(@user_rules,$rule);
6698: }
6699: }
6700: }
6701: if (@user_rules > 0) {
6702: my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
6703: if (keys(%rule_check) > 0) {
6704: $usertype = 'unofficial';
6705: foreach my $item (keys(%rule_check)) {
6706: if ($rule_check{$item}) {
6707: $usertype = 'official';
6708: last;
6709: }
6710: }
6711: }
6712: }
6713: }
6714: }
6715: return $usertype;
6716: }
6717:
6718: sub roles_by_context {
6719: my ($context,$custom,$crstype) = @_;
6720: my @allroles;
6721: if ($context eq 'course') {
6722: @allroles = ('st');
6723: if ($env{'request.role'} =~ m{^dc\./}) {
6724: push(@allroles,'ad');
6725: }
6726: push(@allroles,('ta','ep','in'));
6727: if ($crstype eq 'Community') {
6728: push(@allroles,'co');
6729: } else {
6730: push(@allroles,'cc');
6731: }
6732: if ($custom) {
6733: push(@allroles,'cr');
6734: }
6735: } elsif ($context eq 'author') {
6736: @allroles = ('ca','aa');
6737: } elsif ($context eq 'domain') {
6738: @allroles = ('li','ad','dg','dh','da','sc','au','dc');
6739: }
6740: return @allroles;
6741: }
6742:
6743: sub get_permission {
6744: my ($context,$crstype) = @_;
6745: my %permission;
6746: if ($context eq 'course') {
6747: my $custom = 1;
6748: my @allroles = &roles_by_context($context,$custom,$crstype);
6749: foreach my $role (@allroles) {
6750: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
6751: $permission{'cusr'} = 1;
6752: last;
6753: }
6754: }
6755: if (&Apache::lonnet::allowed('ccr',$env{'request.course.id'})) {
6756: $permission{'custom'} = 1;
6757: }
6758: if (&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) {
6759: $permission{'view'} = 1;
6760: }
6761: if (!$permission{'view'}) {
6762: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
6763: $permission{'view'} = &Apache::lonnet::allowed('vcl',$scope);
6764: if ($permission{'view'}) {
6765: $permission{'view_section'} = $env{'request.course.sec'};
6766: }
6767: }
6768: if (!$permission{'cusr'}) {
6769: if ($env{'request.course.sec'} ne '') {
6770: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
6771: $permission{'cusr'} = (&Apache::lonnet::allowed('cst',$scope));
6772: if ($permission{'cusr'}) {
6773: $permission{'cusr_section'} = $env{'request.course.sec'};
6774: }
6775: }
6776: }
6777: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
6778: $permission{'grp_manage'} = 1;
6779: }
6780: if ($permission{'cusr'}) {
6781: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
6782: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
6783: my %coursehash = (
6784: 'internal.selfenrollmgrdc' => $env{'course.'.$env{'request.course.id'}.'.internal.selfenrollmgrdc'},
6785: 'internal.selfenrollmgrcc' => $env{'course.'.$env{'request.course.id'}.'.internal.selfenrollmgrcc'},
6786: 'internal.coursecode' => $env{'course.'.$env{'request.course.id'}.'.internal.coursecode'},
6787: 'internal.textbook' =>$env{'course.'.$env{'request.course.id'}.'.internal.textbook'},
6788: );
6789: my ($managed_by_cc,$managed_by_dc) = &selfenrollment_administration($cdom,$cnum,$crstype,\%coursehash);
6790: if (ref($managed_by_cc) eq 'ARRAY') {
6791: if (@{$managed_by_cc}) {
6792: $permission{'selfenrolladmin'} = 1;
6793: }
6794: }
6795: unless ($permission{'selfenrolladmin'}) {
6796: $permission{'selfenrollview'} = 1;
6797: }
6798: }
6799: if ($env{'request.course.id'}) {
6800: my $user;
6801: if (($env{'user.name'} ne '') && ($env{'user.domain'} ne '')) {
6802: $user = $env{'user.name'}.':'.$env{'user.domain'};
6803: }
6804: if (($user ne '') && ($env{'course.'.$env{'request.course.id'}.'.internal.courseowner'} eq
6805: $user)) {
6806: $permission{'owner'} = 1;
6807: if (&Apache::lonnet::allowed('mip',$env{'request.course.id'})) {
6808: $permission{'mip'} = 1;
6809: }
6810: } elsif (($user ne '') && ($env{'course.'.$env{'request.course.id'}.'.internal.co-owners'} ne '')) {
6811: if (grep(/^\Q$user\E$/,split(/,/,$env{'course.'.$env{'request.course.id'}.'.internal.co-owners'}))) {
6812: $permission{'co-owner'} = 1;
6813: }
6814: }
6815: }
6816: } elsif ($context eq 'author') {
6817: $permission{'cusr'} = &authorpriv($env{'user.name'},$env{'request.role.domain'});
6818: $permission{'view'} = $permission{'cusr'};
6819: } else {
6820: my @allroles = &roles_by_context($context);
6821: foreach my $role (@allroles) {
6822: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
6823: $permission{'cusr'} = 1;
6824: last;
6825: }
6826: }
6827: if (!$permission{'cusr'}) {
6828: if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) {
6829: $permission{'cusr'} = 1;
6830: }
6831: }
6832: if (&Apache::lonnet::allowed('ccr',$env{'request.role.domain'})) {
6833: $permission{'custom'} = 1;
6834: }
6835: if (&Apache::lonnet::allowed('vac',$env{'request.role.domain'})) {
6836: $permission{'activity'} = 1;
6837: }
6838: if (&Apache::lonnet::allowed('vur',$env{'request.role.domain'})) {
6839: $permission{'view'} = 1;
6840: }
6841: if (&Apache::lonnet::allowed('ccc',$env{'request.role.domain'})) {
6842: $permission{'owner'} = 1;
6843: }
6844: }
6845: my $allowed = 0;
6846: foreach my $key (keys(%permission)) {
6847: next if (($key eq 'owner') || ($key eq 'co-owner'));
6848: if ($permission{$key}) { $allowed=1; last; }
6849: }
6850: return (\%permission,$allowed);
6851: }
6852:
6853: # ==================================================== Figure out author access
6854:
6855: sub authorpriv {
6856: my ($auname,$audom)=@_;
6857: unless ((&Apache::lonnet::allowed('cca',$audom.'/'.$auname))
6858: || (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } return 1;
6859: }
6860:
6861: sub roles_on_upload {
6862: my ($context,$setting,$crstype,%customroles) = @_;
6863: my (@possible_roles,@permitted_roles);
6864: @possible_roles = &curr_role_permissions($context,$setting,1,$crstype);
6865: foreach my $role (@possible_roles) {
6866: if ($role eq 'cr') {
6867: push(@permitted_roles,keys(%customroles));
6868: } else {
6869: push(@permitted_roles,$role);
6870: }
6871: }
6872: return @permitted_roles;
6873: }
6874:
6875: sub get_course_identity {
6876: my ($cid) = @_;
6877: my ($cnum,$cdom,$cdesc);
6878: if ($cid eq '') {
6879: $cid = $env{'request.course.id'}
6880: }
6881: if ($cid ne '') {
6882: $cnum = $env{'course.'.$cid.'.num'};
6883: $cdom = $env{'course.'.$cid.'.domain'};
6884: $cdesc = $env{'course.'.$cid.'.description'};
6885: if ($cnum eq '' || $cdom eq '') {
6886: my %coursehash =
6887: &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
6888: $cdom = $coursehash{'domain'};
6889: $cnum = $coursehash{'num'};
6890: $cdesc = $coursehash{'description'};
6891: }
6892: }
6893: return ($cnum,$cdom,$cdesc);
6894: }
6895:
6896: sub dc_setcourse_js {
6897: my ($formname,$mode,$context,$showcredits,$domain) = @_;
6898: my ($dc_setcourse_code,$authen_check);
6899: my $cctext = &Apache::lonnet::plaintext('cc');
6900: my $cotext = &Apache::lonnet::plaintext('co');
6901: my %alerts = §ioncheck_alerts();
6902: my $role = 'role';
6903: if ($mode eq 'upload') {
6904: $role = 'courserole';
6905: } else {
6906: $authen_check = &verify_authen($formname,$context,$domain);
6907: }
6908: $dc_setcourse_code = (<<"SCRIPTTOP");
6909: $authen_check
6910:
6911: function setCourse() {
6912: var course = document.$formname.dccourse.value;
6913: if (course != "") {
6914: if (document.$formname.dcdomain.value != document.$formname.origdom.value) {
6915: alert("$alerts{'curd'}");
6916: return;
6917: }
6918: var userrole = document.$formname.$role.options[document.$formname.$role.selectedIndex].value
6919: var section="";
6920: var numsections = 0;
6921: var newsecs = new Array();
6922: for (var i=0; i<document.$formname.currsec.length; i++) {
6923: if (document.$formname.currsec.options[i].selected == true ) {
6924: if (document.$formname.currsec.options[i].value != "" && document.$formname.currsec.options[i].value != null) {
6925: if (numsections == 0) {
6926: section = document.$formname.currsec.options[i].value
6927: numsections = 1;
6928: }
6929: else {
6930: section = section + "," + document.$formname.currsec.options[i].value
6931: numsections ++;
6932: }
6933: }
6934: }
6935: }
6936: if (document.$formname.newsec.value != "" && document.$formname.newsec.value != null) {
6937: if (numsections == 0) {
6938: section = document.$formname.newsec.value
6939: }
6940: else {
6941: section = section + "," + document.$formname.newsec.value
6942: }
6943: newsecs = document.$formname.newsec.value.split(/,/g);
6944: numsections = numsections + newsecs.length;
6945: }
6946: if ((userrole == 'st') && (numsections > 1)) {
6947: if (document.$formname.crstype.value == 'Community') {
6948: alert("$alerts{'inco'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
6949: } else {
6950: alert("$alerts{'inea'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
6951: }
6952: return;
6953: }
6954: for (var j=0; j<newsecs.length; j++) {
6955: if ((newsecs[j] == 'all') || (newsecs[j] == 'none')) {
6956: alert("'"+newsecs[j]+"' $alerts{'mayn'}.\\n$alerts{'plsc'}.");
6957: return;
6958: }
6959: if (document.$formname.groups.value != '') {
6960: var groups = document.$formname.groups.value.split(/,/g);
6961: for (var k=0; k<groups.length; k++) {
6962: if (newsecs[j] == groups[k]) {
6963: if (document.$formname.crstype.value == 'Community') {
6964: alert("'"+newsecs[j]+"' $alerts{'mayc'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
6965: } else {
6966: alert("'"+newsecs[j]+"' $alerts{'mayt'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
6967: }
6968: return;
6969: }
6970: }
6971: }
6972: }
6973: if ((userrole == 'cc') && (numsections > 0)) {
6974: alert("$alerts{'secd'} $cctext $alerts{'role'}.\\n$alerts{'accr'}.");
6975: section = "";
6976: }
6977: if ((userrole == 'co') && (numsections > 0)) {
6978: alert("$alerts{'secd'} $cotext $alerts{'role'}.\\n$alerts{'accr'}.");
6979: section = "";
6980: }
6981: SCRIPTTOP
6982: if ($mode ne 'upload') {
6983: $dc_setcourse_code .= (<<"SCRIPTMID");
6984: var coursename = "_$env{'request.role.domain'}"+"_"+course+"_"+userrole
6985: var numcourse = getIndex(document.$formname.dccourse);
6986: if (numcourse == "-1") {
6987: if (document.$formname.type == 'Community') {
6988: alert("$alerts{'thwc'}");
6989: } else {
6990: alert("$alerts{'thwa'}");
6991: }
6992: return;
6993: }
6994: else {
6995: document.$formname.elements[numcourse].name = "act"+coursename;
6996: var numnewsec = getIndex(document.$formname.newsec);
6997: if (numnewsec != "-1") {
6998: document.$formname.elements[numnewsec].name = "sec"+coursename;
6999: document.$formname.elements[numnewsec].value = section;
7000: }
7001: var numstart = getIndex(document.$formname.start);
7002: if (numstart != "-1") {
7003: document.$formname.elements[numstart].name = "start"+coursename;
7004: }
7005: var numend = getIndex(document.$formname.end);
7006: if (numend != "-1") {
7007: document.$formname.elements[numend].name = "end"+coursename
7008: }
7009: SCRIPTMID
7010: if ($showcredits) {
7011: $dc_setcourse_code .= <<ENDCRED;
7012: var numcredits = getIndex(document.$formname.credits);
7013: if (numcredits != "-1") {
7014: document.$formname.elements[numcredits].name = "credits"+coursename;
7015: }
7016: ENDCRED
7017: }
7018: $dc_setcourse_code .= <<ENDSCRIPT;
7019: }
7020: }
7021: var authcheck = auth_check();
7022: if (authcheck == 'ok') {
7023: document.$formname.submit();
7024: }
7025: }
7026: ENDSCRIPT
7027: } else {
7028: $dc_setcourse_code .= "
7029: document.$formname.sections.value = section;
7030: }
7031: return 'ok';
7032: }
7033: ";
7034: }
7035: $dc_setcourse_code .= (<<"ENDSCRIPT");
7036:
7037: function getIndex(caller) {
7038: for (var i=0;i<document.$formname.elements.length;i++) {
7039: if (document.$formname.elements[i] == caller) {
7040: return i;
7041: }
7042: }
7043: return -1;
7044: }
7045: ENDSCRIPT
7046: return $dc_setcourse_code;
7047: }
7048:
7049: sub verify_authen {
7050: my ($formname,$context,$domain) = @_;
7051: my %alerts = &authcheck_alerts();
7052: my $finish = "return 'ok';";
7053: if ($context eq 'author') {
7054: $finish = "document.$formname.submit();";
7055: }
7056: my ($numrules,$intargjs) =
7057: &Apache::loncommon::passwd_validation_js('argpicked',$domain);
7058: my $outcome = <<"ENDSCRIPT";
7059:
7060: function auth_check() {
7061: var logintype;
7062: if (document.$formname.login.length) {
7063: if (document.$formname.login.length > 0) {
7064: var loginpicked = 0;
7065: for (var i=0; i<document.$formname.login.length; i++) {
7066: if (document.$formname.login[i].checked == true) {
7067: loginpicked = 1;
7068: logintype = document.$formname.login[i].value;
7069: }
7070: }
7071: if (loginpicked == 0) {
7072: alert("$alerts{'authen'}");
7073: return;
7074: }
7075: }
7076: } else {
7077: logintype = document.$formname.login.value;
7078: }
7079: if (logintype == 'nochange') {
7080: return 'ok';
7081: }
7082: var argpicked = document.$formname.elements[logintype+'arg'].value;
7083: if ((argpicked == null) || (argpicked == '') || (typeof argpicked == 'undefined')) {
7084: var alertmsg = '';
7085: switch (logintype) {
7086: case 'krb':
7087: alertmsg = '$alerts{'krb'}';
7088: break;
7089: case 'int':
7090: alertmsg = '$alerts{'ipass'}';
7091: break;
7092: case 'fsys':
7093: alertmsg = '$alerts{'ipass'}';
7094: break;
7095: case 'loc':
7096: alertmsg = '';
7097: break;
7098: default:
7099: alertmsg = '';
7100: }
7101: if (alertmsg != '') {
7102: alert(alertmsg);
7103: return;
7104: }
7105: } else if (logintype == 'int') {
7106: var numrules = $numrules;
7107: if (numrules > 0) {
7108: $intargjs
7109: }
7110: }
7111: $finish
7112: }
7113: ENDSCRIPT
7114: }
7115:
7116: sub sectioncheck_alerts {
7117: my %alerts = &Apache::lonlocal::texthash(
7118: curd => 'You must select a course or community in the current domain',
7119: inea => 'In each course, each user may only have one student role at a time',
7120: inco => 'In each community, each user may only have one member role at a time',
7121: youh => 'You had selected',
7122: sect => 'sections',
7123: plsm => 'Please modify your selections so they include no more than one section',
7124: mayn => 'may not be used as the name for a section, as it is a reserved word',
7125: plsc => 'Please choose a different section name',
7126: mayt => 'may not be used as the name for a section, as it is the name of a course group',
7127: mayc => 'may not be used as the name for a section, as it is the name of a community group',
7128: secn => 'Section names and group names must be distinct',
7129: secd => 'Section designations do not apply to ',
7130: role => 'roles',
7131: accr => 'role will be added with access to all sections',
7132: thwa => 'There was a problem with your course selection',
7133: thwc => 'There was a problem with your community selection',
7134: );
7135: &js_escape(\%alerts);
7136: return %alerts;
7137: }
7138:
7139: sub authcheck_alerts {
7140: my %alerts =
7141: &Apache::lonlocal::texthash(
7142: authen => 'You must choose an authentication type.',
7143: krb => 'You need to specify the Kerberos domain.',
7144: ipass => 'You need to specify the initial password.',
7145: );
7146: &js_escape(\%alerts);
7147: return %alerts;
7148: }
7149:
7150: sub is_courseowner {
7151: my ($thiscourse,$courseowner) = @_;
7152: if ($courseowner eq '') {
7153: if ($env{'request.course.id'} eq $thiscourse) {
7154: $courseowner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
7155: }
7156: }
7157: if ($courseowner ne '') {
7158: if ($courseowner eq $env{'user.name'}.':'.$env{'user.domain'}) {
7159: return 1;
7160: }
7161: }
7162: return;
7163: }
7164:
7165: sub get_selfenroll_titles {
7166: my @row = ('types','registered','enroll_dates','access_dates','section',
7167: 'approval','limit');
7168: my %lt = &Apache::lonlocal::texthash (
7169: types => 'Users allowed to self-enroll',
7170: registered => 'Registration status (official courses)' ,
7171: enroll_dates => 'Dates self-enrollment available',
7172: access_dates => 'Access dates for self-enrolling users',
7173: section => "Self-enrolling users' section",
7174: approval => 'Processing of requests',
7175: limit => 'Enrollment limit',
7176: );
7177: return (\@row,\%lt);
7178: }
7179:
7180: sub selfenroll_default_descs {
7181: my %desc = (
7182: types => {
7183: dom => &mt('Course domain'),
7184: all => &mt('Any domain'),
7185: '' => &mt('None'),
7186: },
7187: limit => {
7188: none => &mt('No limit'),
7189: allstudents => &mt('Limit by total students'),
7190: selfenrolled => &mt('Limit by total self-enrolled'),
7191: },
7192: approval => {
7193: '0' => &mt('Processed automatically'),
7194: '1' => &mt('Queued for approval'),
7195: '2' => &mt('Queued, pending validation'),
7196: },
7197: registered => {
7198: 0 => 'No registration required',
7199: 1 => 'Registered students only',
7200: },
7201: );
7202: return %desc;
7203: }
7204:
7205: sub selfenroll_validation_types {
7206: my @items = ('url','fields','button','markup');
7207: my %names = &Apache::lonlocal::texthash (
7208: url => 'Web address of validation server/script',
7209: fields => 'Form fields to send to validator',
7210: button => 'Text for validation button',
7211: markup => 'Validation description (HTML)',
7212: );
7213: my @fields = ('username','domain','uniquecode','course','coursetype','description');
7214: return (\@items,\%names,\@fields);
7215: }
7216:
7217: sub get_extended_type {
7218: my ($cdom,$cnum,$crstype,$current) = @_;
7219: my $type = 'unofficial';
7220: my %settings;
7221: if (ref($current) eq 'HASH') {
7222: %settings = %{$current};
7223: } else {
7224: %settings = &Apache::lonnet::get('environment',['internal.coursecode','internal.textbook'],$cdom,$cnum);
7225: }
7226: if ($crstype eq 'Community') {
7227: $type = 'community';
7228: } elsif ($crstype eq 'Placement') {
7229: $type = 'placement';
7230: } elsif ($settings{'internal.coursecode'}) {
7231: $type = 'official';
7232: } elsif ($settings{'internal.textbook'}) {
7233: $type = 'textbook';
7234: }
7235: return $type;
7236: }
7237:
7238: sub selfenrollment_administration {
7239: my ($cdom,$cnum,$crstype,$coursehash) = @_;
7240: my %settings;
7241: if (ref($coursehash) eq 'HASH') {
7242: %settings = %{$coursehash};
7243: } else {
7244: %settings = &Apache::lonnet::get('environment',
7245: ['internal.selfenrollmgrdc','internal.selfenrollmgrcc',
7246: 'internal.coursecode','internal.textbook'],$cdom,$cnum);
7247: }
7248: my ($possconfigs) = &get_selfenroll_titles();
7249: my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
7250: my $selfenrolltype = &get_extended_type($cdom,$cnum,$crstype,\%settings);
7251:
7252: my (@in_course,@in_domain);
7253: if ($settings{'internal.selfenrollmgrcc'} ne '') {
7254: @in_course = split(/,/,$settings{'internal.selfenrollmgrcc'});
7255: my @diffs = &Apache::loncommon::compare_arrays($possconfigs,\@in_course);
7256: unless (@diffs) {
7257: return (\@in_course,\@in_domain);
7258: }
7259: }
7260: if ($settings{'internal.selfenrollmgrdc'} ne '') {
7261: @in_domain = split(/,/,$settings{'internal.selfenrollmgrdc'});
7262: my @diffs = &Apache::loncommon::compare_arrays(\@in_domain,$possconfigs);
7263: unless (@diffs) {
7264: return (\@in_course,\@in_domain);
7265: }
7266: }
7267: my @combined = @in_course;
7268: push(@combined,@in_domain);
7269: my @diffs = &Apache::loncommon::compare_arrays(\@combined,$possconfigs);
7270: unless (@diffs) {
7271: return (\@in_course,\@in_domain);
7272: }
7273: if ($domdefaults{$selfenrolltype.'selfenrolladmdc'} eq '') {
7274: push(@in_course,@diffs);
7275: } else {
7276: my @defaultdc = split(/,/,$domdefaults{$selfenrolltype.'selfenrolladmdc'});
7277: foreach my $item (@diffs) {
7278: if (grep(/^\Q$item\E$/,@defaultdc)) {
7279: push(@in_domain,$item);
7280: } else {
7281: push(@in_course,$item);
7282: }
7283: }
7284: }
7285: return (\@in_course,\@in_domain);
7286: }
7287:
7288: sub custom_role_header {
7289: my ($context,$crstype,$templaterolerefs,$prefix) = @_;
7290: my %lt = &Apache::lonlocal::texthash(
7291: sele => 'Select a Template',
7292: );
7293: my ($context_code,$button_code);
7294: if ($context eq 'domain') {
7295: $context_code = &custom_coursetype_switch($crstype,$prefix);
7296: }
7297: if (ref($templaterolerefs) eq 'ARRAY') {
7298: foreach my $role (@{$templaterolerefs}) {
7299: my $display = 'inline';
7300: if (($context eq 'domain') && ($role eq 'co')) {
7301: $display = 'none';
7302: }
7303: $button_code .= &make_button_code($role,$crstype,$display,$prefix).' ';
7304: }
7305: }
7306: return <<"END";
7307: <div class="LC_left_float">
7308: <fieldset>
7309: <legend>$lt{'sele'}</legend>
7310: $button_code
7311: </fieldset></div>
7312: $context_code
7313: <br clear="all" />
7314: END
7315: }
7316:
7317: sub custom_coursetype_switch {
7318: my ($crstype,$prefix) = @_;
7319: my ($checkedcourse,$checkedcommunity);
7320: if ($crstype eq 'Community') {
7321: $checkedcommunity = ' checked="checked"';
7322: } else {
7323: $checkedcourse = ' checked="checked"';
7324: }
7325: my %lt = &Apache::lonlocal::texthash(
7326: cont => 'Context',
7327: cour => 'Course',
7328: comm => 'Community',
7329: );
7330: return <<"END";
7331: <div class="LC_left_float">
7332: <fieldset>
7333: <legend>$lt{'cont'}</legend>
7334: <label>
7335: <input type="radio" name="${prefix}_custrolecrstype" value="Course"$checkedcourse onclick="javascript:customSwitchType('$prefix');" />
7336: $lt{'cour'}
7337: </label>
7338: <label>
7339: <input type="radio" name="${prefix}_custrolecrstype" value="Community"$checkedcommunity onclick="javascript:customSwitchType('$prefix');" />
7340: $lt{'comm'}
7341: </label>
7342: </fieldset>
7343: </div>
7344: END
7345: }
7346:
7347: sub custom_role_table {
7348: my ($crstype,$full,$levels,$levelscurrent,$prefix,$add_class,$id) = @_;
7349: return unless ((ref($full) eq 'HASH') && (ref($levels) eq 'HASH') &&
7350: (ref($levelscurrent) eq 'HASH'));
7351: my %lt=&Apache::lonlocal::texthash (
7352: 'prv' => "Privilege",
7353: 'crl' => "Course Level",
7354: 'dml' => "Domain Level",
7355: 'ssl' => "System Level");
7356: my %cr = (
7357: course => '_c',
7358: domain => '_d',
7359: system => '_s',
7360: );
7361:
7362: my $output=&Apache::loncommon::start_data_table($add_class,$id).
7363: &Apache::loncommon::start_data_table_header_row().
7364: '<th>'.$lt{'prv'}.'</th><th>'.$lt{'crl'}.'</th><th>'.$lt{'dml'}.
7365: '</th><th>'.$lt{'ssl'}.'</th>'.
7366: &Apache::loncommon::end_data_table_header_row();
7367: foreach my $priv (sort(keys(%{$full}))) {
7368: my $privtext = &Apache::lonnet::plaintext($priv,$crstype);
7369: $output .= &Apache::loncommon::start_data_table_row().
7370: '<td><span id="'.$prefix.$priv.'">'.$privtext.'</span></td>';
7371: foreach my $type ('course','domain','system') {
7372: if (($type eq 'system') && ($priv eq 'bre') && ($crstype eq 'Community')) {
7373: $output .= '<td> </td>';
7374: } else {
7375: $output .= '<td>'.
7376: ($levels->{$type}{$priv}?'<input type="checkbox" id="'.$prefix.$priv.$cr{$type}.'"'.
7377: ' name="'.$prefix.$priv.$cr{$type}.'"'.
7378: ($levelscurrent->{$type}{$priv}?' checked="checked"':'').' />':' ').
7379: '</td>';
7380: }
7381: }
7382: $output .= &Apache::loncommon::end_data_table_row();
7383: }
7384: $output .= &Apache::loncommon::end_data_table();
7385: return $output;
7386: }
7387:
7388: sub custom_role_privs {
7389: my ($privs,$full,$levels,$levelscurrent)= @_;
7390: return unless ((ref($privs) eq 'HASH') && (ref($full) eq 'HASH') &&
7391: (ref($levels) eq 'HASH') && (ref($levelscurrent) eq 'HASH'));
7392: my %cr = (
7393: course => 'cr:c',
7394: domain => 'cr:d',
7395: system => 'cr:s',
7396: );
7397: foreach my $type ('course','domain','system') {
7398: foreach my $item (split(/\:/,$Apache::lonnet::pr{$cr{$type}})) {
7399: my ($priv,$restrict)=split(/\&/,$item);
7400: if (!$restrict) { $restrict='F'; }
7401: $levels->{$type}->{$priv}=$restrict;
7402: if ($privs->{$type}=~/\:$priv/) {
7403: $levelscurrent->{$type}->{$priv}=1;
7404: }
7405: $full->{$priv}=1;
7406: }
7407: }
7408: return;
7409: }
7410:
7411: sub custom_template_roles {
7412: my ($context,$crstype) = @_;
7413: my @template_roles = ("in","ta","ep");
7414: if (($context eq 'domain') || ($context eq 'domprefs')) {
7415: push(@template_roles,"ad");
7416: }
7417: push(@template_roles,"st");
7418: if ($context eq 'domain') {
7419: unshift(@template_roles,('co','cc'));
7420: } else {
7421: if ($crstype eq 'Community') {
7422: unshift(@template_roles,'co');
7423: } else {
7424: unshift(@template_roles,'cc');
7425: }
7426: }
7427: return @template_roles;
7428: }
7429:
7430: sub custom_roledefs_js {
7431: my ($context,$crstype,$formname,$full,$templaterolesref,$jsback) = @_;
7432: my $button_code = "\n";
7433: my $head_script = "\n";
7434: my (%roletitlestr,$rolenamestr);
7435: my %role_titles = (
7436: Course => [],
7437: Community => [],
7438: );
7439: $head_script .= '<script type="text/javascript">'."\n"
7440: .'// <![CDATA['."\n";
7441: if (ref($templaterolesref) eq 'ARRAY') {
7442: if ($context eq 'domain') {
7443: $rolenamestr = join("','",@{$templaterolesref});
7444: }
7445: foreach my $role (@{$templaterolesref}) {
7446: $head_script .= &make_script_template($role,$crstype,$formname);
7447: if ($context eq 'domain') {
7448: foreach my $type ('Course','Community') {
7449: push(@{$role_titles{$type}},&Apache::lonnet::plaintext($role,$type));
7450: }
7451: }
7452: }
7453: }
7454: if ($context eq 'domain') {
7455: foreach my $type ('Course','Community') {
7456: $roletitlestr{$type} = join("','",@{$role_titles{$type}});
7457: }
7458: my %pt = (
7459: Community => {
7460: cst => &mt('Grant/revoke role of Member'),
7461: mdc => &mt('Edit community contents'),
7462: pch => &mt('Post discussion on community resources'),
7463: pfo => &mt('Print for other users and entire community'),
7464: },
7465: Course => {
7466: cst => &mt('Grant/revoke role of Student'),
7467: mdc => &mt('Edit course contents'),
7468: pch => &mt('Post discussion on course resources'),
7469: pfo => &mt('Print for other users and entire course'),
7470: },
7471: );
7472: $head_script .= <<"ENDJS";
7473: function customSwitchType(prefix) {
7474: var privnames = new Array('cst','mdc','pch','pfo');
7475: var privtxtcrs = new Array('$pt{Course}{cst}','$pt{Course}{mdc}','$pt{Course}{pch}','$pt{Course}{pfo}');
7476: var privtxtcom = new Array('$pt{Community}{cst}','$pt{Community}{mdc}','$pt{Community}{pch}','$pt{Community}{pfo}');
7477: var rolenames = new Array('$rolenamestr');
7478: var rolescrs = new Array('$roletitlestr{Course}');
7479: var rolescom = new Array('$roletitlestr{Community}');
7480: var radio = prefix+'_custrolecrstype';
7481: if (document.$formname.elements[radio].length > 1) {
7482: for (var i=0; i<document.$formname.elements[radio].length; i++) {
7483: if (document.$formname.elements[radio][i].checked) {
7484: if ((document.getElementById(prefix+'bre_s')) && (document.getElementById(prefix+'bro_s'))) {
7485: if (document.$formname.elements[radio][i].value == 'Community') {
7486: if (document.getElementById(prefix+'bre_s').checked) {
7487: document.getElementById(prefix+'bro_s').checked = true;
7488: document.getElementById(prefix+'bre_s').checked = false;
7489:
7490: }
7491: document.getElementById(prefix+'bre_s').style.visibility = 'hidden';
7492: } else {
7493: document.getElementById(prefix+'bre_s').style.visibility = 'visible';
7494: if (document.getElementById(prefix+'bro_s').checked) {
7495: document.getElementById(prefix+'bre_s').checked = true;
7496: document.getElementById(prefix+'bro_s').checked = false;
7497: }
7498: }
7499: }
7500: for (var j=0; j<privnames.length; j++) {
7501: if (document.getElementById(prefix+privnames[j])) {
7502: if (document.getElementById(prefix+privnames[j])) {
7503: if (document.$formname.elements[radio][i].value == 'Course') {
7504: document.getElementById(prefix+privnames[j]).innerHTML = privtxtcrs[j];
7505: } else {
7506: document.getElementById(prefix+privnames[j]).innerHTML = privtxtcom[j];
7507: }
7508: }
7509: }
7510: }
7511: for (var j=0; j<rolenames.length; j++) {
7512: if (document.getElementById(prefix+rolenames[j])) {
7513: if (document.getElementById(prefix+rolenames[j])) {
7514: if (document.$formname.elements[radio][i].value == 'Course') {
7515: document.getElementById(prefix+rolenames[j]).value = rolescrs[j];
7516: if (rolenames[j] == 'cc') {
7517: document.getElementById(prefix+rolenames[j]).style.display = 'inline';
7518: }
7519: if (rolenames[j] == 'co') {
7520: document.getElementById(prefix+rolenames[j]).style.display = 'none';
7521: }
7522: } else {
7523: document.getElementById(prefix+rolenames[j]).value = rolescom[j];
7524: if (rolenames[j] == 'cc') {
7525: document.getElementById(prefix+rolenames[j]).style.display = 'none';
7526: }
7527: if (rolenames[j] == 'co') {
7528: document.getElementById(prefix+rolenames[j]).style.display = 'inline';
7529: }
7530: }
7531: }
7532: }
7533: }
7534: }
7535: }
7536: }
7537: return;
7538: }
7539: ENDJS
7540: }
7541: $head_script .= "\n".$jsback."\n"
7542: .'// ]]>'."\n"
7543: .'</script>'."\n";
7544: return $head_script;
7545: }
7546:
7547: # --------------------------------------------------------
7548: sub make_script_template {
7549: my ($role,$crstype,$formname) = @_;
7550: my $return_script = 'function set_'.$role.'(prefix) {'."\n";
7551: my (%full_by_level,%role_priv);
7552: foreach my $level ('c','d','s') {
7553: foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) {
7554: next if (($level eq 's') && ($crstype eq 'Community') && ($item eq 'bre&S'));
7555: my ($priv,$restrict)=split(/\&/,$item);
7556: $full_by_level{$level}{$priv}=1;
7557: }
7558: $role_priv{$level} = {};
7559: my @temp = split(/:/,$Apache::lonnet::pr{$role.':'.$level});
7560: foreach my $priv (@temp) {
7561: my ($priv_item, $dummy) = split(/\&/,$priv);
7562: $role_priv{$level}{$priv_item} = 1;
7563: }
7564: }
7565: my %to_check = (
7566: c => ['c','d','s'],
7567: d => ['d','s'],
7568: s => ['s'],
7569: );
7570: foreach my $level ('c','d','s') {
7571: if (ref($full_by_level{$level}) eq 'HASH') {
7572: foreach my $priv (keys(%{$full_by_level{$level}})) {
7573: my $value = 'false';
7574: if (ref($to_check{$level}) eq 'ARRAY') {
7575: foreach my $lett (@{$to_check{$level}}) {
7576: if (exists($role_priv{$lett}{$priv})) {
7577: $value = 'true';
7578: last;
7579: }
7580: }
7581: $return_script .= "document.$formname.elements[prefix+'".$priv."_".$level."'].checked = $value;\n";
7582: }
7583: }
7584: }
7585: }
7586: $return_script .= '}'."\n";
7587: return ($return_script);
7588: }
7589: # ----------------------------------------------------------
7590: sub make_button_code {
7591: my ($role,$crstype,$display,$prefix) = @_;
7592: my $label = &Apache::lonnet::plaintext($role,$crstype);
7593: my $button_code = '<input type="button" onclick="set_'.$role."('$prefix'".')" '.
7594: 'id="'.$prefix.$role.'" value="'.$label.'" '.
7595: 'style="display:'.$display.'" />';
7596: return ($button_code);
7597: }
7598:
7599: sub custom_role_update {
7600: my ($rolename,$prefix) = @_;
7601: # ------------------------------------------------------- What can be assigned?
7602: my %privs = (
7603: c => '',
7604: d => '',
7605: s => '',
7606: );
7607: foreach my $level (keys(%privs)) {
7608: foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) {
7609: my ($priv,$restrict)=split(/\&/,$item);
7610: if (!$restrict) { $restrict=''; }
7611: if ($env{'form.'.$prefix.$priv.'_'.$level}) {
7612: $privs{$level} .=':'.$item;
7613: }
7614: }
7615: }
7616: return %privs;
7617: }
7618:
7619: sub adhoc_status_types {
7620: my ($cdom,$context,$role,$selectedref,$othertitle,$usertypes,$types,$disabled) = @_;
7621: my $output = &Apache::loncommon::start_data_table();
7622: my $numinrow = 3;
7623: my $rem;
7624: if (ref($types) eq 'ARRAY') {
7625: for (my $i=0; $i<@{$types}; $i++) {
7626: if (defined($usertypes->{$types->[$i]})) {
7627: my $rem = $i%($numinrow);
7628: if ($rem == 0) {
7629: if ($i > 0) {
7630: $output .= &Apache::loncommon::end_data_table_row();
7631: }
7632: $output .= &Apache::loncommon::start_data_table_row();
7633: }
7634: my $check;
7635: if (ref($selectedref) eq 'ARRAY') {
7636: if (grep(/^\Q$types->[$i]\E$/,@{$selectedref})) {
7637: $check = ' checked="checked"';
7638: }
7639: }
7640: $output .= '<td>'.
7641: '<span class="LC_nobreak"><label>'.
7642: '<input type="checkbox" name="'.$context.$role.'_status" '.
7643: 'value="'.$types->[$i].'"'.$check.$disabled.' />'.
7644: $usertypes->{$types->[$i]}.'</label></span></td>';
7645: }
7646: }
7647: $rem = @{$types}%($numinrow);
7648: }
7649: my $colsleft = $numinrow - $rem;
7650: if (($rem == 0) && (@{$types} > 0)) {
7651: $output .= &Apache::loncommon::start_data_table_row();
7652: }
7653: if ($colsleft > 1) {
7654: $output .= '<td colspan="'.$colsleft.'">';
7655: } else {
7656: $output .= '<td>';
7657: }
7658: my $defcheck;
7659: if (ref($selectedref) eq 'ARRAY') {
7660: if (grep(/^default$/,@{$selectedref})) {
7661: $defcheck = ' checked="checked"';
7662: }
7663: }
7664: $output .= '<span class="LC_nobreak"><label>'.
7665: '<input type="checkbox" name="'.$context.$role.'_status"'.
7666: 'value="default"'.$defcheck.$disabled.' />'.
7667: $othertitle.'</label></span></td>'.
7668: &Apache::loncommon::end_data_table_row().
7669: &Apache::loncommon::end_data_table();
7670: return $output;
7671: }
7672:
7673: sub adhoc_staff {
7674: my ($access,$context,$role,$selectedref,$adhocref,$disabled) = @_;
7675: my $output;
7676: if (ref($adhocref) eq 'HASH') {
7677: my %by_fullname;
7678: my $numinrow = 4;
7679: my $rem;
7680: my @personnel = keys(%{$adhocref});
7681: if (@personnel) {
7682: foreach my $person (@personnel) {
7683: my ($uname,$udom) = split(/:/,$person);
7684: my $fullname = &Apache::loncommon::plainname($uname,$udom,'lastname');
7685: $by_fullname{$fullname} = $person;
7686: }
7687: my @sorted = sort(keys(%by_fullname));
7688: my $count = scalar(@sorted);
7689: $output = &Apache::loncommon::start_data_table();
7690: for (my $i=0; $i<$count; $i++) {
7691: my $rem = $i%($numinrow);
7692: if ($rem == 0) {
7693: if ($i > 0) {
7694: $output .= &Apache::loncommon::end_data_table_row();
7695: }
7696: $output .= &Apache::loncommon::start_data_table_row();
7697: }
7698: my $check;
7699: my $user = $by_fullname{$sorted[$i]};
7700: if (ref($selectedref) eq 'ARRAY') {
7701: if (grep(/^\Q$user\E$/,@{$selectedref})) {
7702: $check = ' checked="checked"';
7703: }
7704: }
7705: if ($i == $count-1) {
7706: my $colsleft = $numinrow - $rem;
7707: if ($colsleft > 1) {
7708: $output .= '<td colspan="'.$colsleft.'">';
7709: } else {
7710: $output .= '<td>';
7711: }
7712: } else {
7713: $output .= '<td>';
7714: }
7715: $output .= '<span class="LC_nobreak"><label>'.
7716: '<input type="checkbox" name="'.$context.$role.'_staff_'.$access.'" '.
7717: 'value="'.$user.'"'.$check.$disabled.' />'.$sorted[$i].
7718: '</label></span></td>';
7719: if ($i == $count-1) {
7720: $output .= &Apache::loncommon::end_data_table_row();
7721: }
7722: }
7723: $output .= &Apache::loncommon::end_data_table();
7724: }
7725: }
7726: return $output;
7727: }
7728:
7729:
7730: 1;
7731:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>