File:
[LON-CAPA] /
loncom /
interface /
lonuserutils.pm
Revision
1.95:
download - view:
text,
annotated -
select for diffs
Mon Aug 3 15:57:25 2009 UTC (15 years ago) by
bisitz
Branches:
MAIN
CVS tags:
HEAD
Upload Classlist/Upload User lists - Consistent and nicer layout: use pick_box
And more optimizations:
- Added headline text "Options" to all options which are now together in one pick_box
- Optimized if/elsif structure for $context (DC/AU/CC) sensitive options
- Added <hr> to separate options pick_box from Button, especially helpful for screens with high horizontal resolution where content floats in two columns.
- Wrapped total number of records message in paragraph
- Added some code line breaks for better readability
- Found $home_server_pick broken - added comment in code
- Wording:
- Little wording optimizations
- Optimized some German translations
- Corresponding adjustments in zh.pm
1: # The LearningOnline Network with CAPA
2: # Utility functions for managing LON-CAPA user accounts
3: #
4: # $Id: lonuserutils.pm,v 1.95 2009/08/03 15:57:25 bisitz 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: use strict;
34: use Apache::lonnet;
35: use Apache::loncommon();
36: use Apache::lonhtmlcommon;
37: use Apache::lonlocal;
38: use Apache::longroup;
39: use LONCAPA qw(:DEFAULT :match);
40:
41: ###############################################################
42: ###############################################################
43: # Drop student from all sections of a course, except optional $csec
44: sub modifystudent {
45: my ($udom,$unam,$courseid,$csec,$desiredhost,$context)=@_;
46: # if $csec is undefined, drop the student from all the courses matching
47: # this one. If $csec is defined, drop them from all other sections of
48: # this course and add them to section $csec
49: my ($cnum,$cdom) = &get_course_identity($courseid);
50: my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
51: my ($tmp) = keys(%roles);
52: # Bail out if we were unable to get the students roles
53: return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
54: # Go through the roles looking for enrollment in this course
55: my $result = '';
56: foreach my $course (keys(%roles)) {
57: if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
58: # We are in this course
59: my $section=$1;
60: $section='' if ($course eq "/$cdom/$cnum".'_st');
61: if (defined($csec) && $section eq $csec) {
62: $result .= 'ok:';
63: } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
64: my (undef,$end,$start)=split(/\_/,$roles{$course});
65: my $now=time;
66: # if this is an active role
67: if (!($start && ($now<$start)) || !($end && ($now>$end))) {
68: my $reply=&Apache::lonnet::modifystudent
69: # dom name id mode pass f m l g
70: ($udom,$unam,'', '', '',undef,undef,undef,undef,
71: $section,time,undef,undef,$desiredhost,'','manual',
72: '',$courseid,'',$context);
73: $result .= $reply.':';
74: }
75: }
76: }
77: }
78: if ($result eq '') {
79: $result = &mt('Unable to find section for this student');
80: } else {
81: $result =~ s/(ok:)+/ok/g;
82: }
83: return $result;
84: }
85:
86: sub modifyuserrole {
87: my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
88: $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
89: $end,$start,$checkid,$inststatus) = @_;
90: my ($scope,$userresult,$authresult,$roleresult,$idresult);
91: if ($setting eq 'course' || $context eq 'course') {
92: $scope = '/'.$cid;
93: $scope =~ s/\_/\//g;
94: if ($role ne 'cc' && $sec ne '') {
95: $scope .='/'.$sec;
96: }
97: } elsif ($context eq 'domain') {
98: $scope = '/'.$env{'request.role.domain'}.'/';
99: } elsif ($context eq 'author') {
100: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
101: }
102: if ($context eq 'domain') {
103: my $uhome = &Apache::lonnet::homeserver($uname,$udom);
104: if ($uhome ne 'no_host') {
105: if (($changeauth eq 'Yes') && (&Apache::lonnet::allowed('mau',$udom))) {
106: if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
107: ($umode eq 'localauth')) {
108: $authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
109: }
110: }
111: if (($forceid) && (&Apache::lonnet::allowed('mau',$udom)) &&
112: ($env{'form.recurseid'}) && ($checkid)) {
113: my %userupdate = (
114: lastname => $last,
115: middlename => $middle,
116: firstname => $first,
117: generation => $gene,
118: id => $uid,
119: );
120: $idresult = &propagate_id_change($uname,$udom,\%userupdate);
121: }
122: }
123: }
124: $userresult =
125: &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
126: $middle,$last,$gene,$forceid,$desiredhome,
127: $email,$inststatus);
128: if ($userresult eq 'ok') {
129: if ($role ne '') {
130: $role =~ s/_/\//g;
131: $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
132: $role,$end,$start,'',
133: '',$context);
134: }
135: }
136: return ($userresult,$authresult,$roleresult,$idresult);
137: }
138:
139: sub propagate_id_change {
140: my ($uname,$udom,$user) = @_;
141: my (@types,@roles);
142: @types = ('active','future');
143: @roles = ('st');
144: my $idresult;
145: my %roleshash = &Apache::lonnet::get_my_roles($uname,
146: $udom,'userroles',\@types,\@roles);
147: my %args = (
148: one_time => 1,
149: );
150: foreach my $item (keys(%roleshash)) {
151: my ($cnum,$cdom,$role) = split(/:/,$item,-1);
152: my ($start,$end) = split(/:/,$roleshash{$item});
153: if (&Apache::lonnet::is_course($cdom,$cnum)) {
154: my $result = &update_classlist($cdom,$cnum,$udom,$uname,$user);
155: my %coursehash =
156: &Apache::lonnet::coursedescription($cdom.'_'.$cnum,\%args);
157: my $cdesc = $coursehash{'description'};
158: if ($cdesc eq '') {
159: $cdesc = $cdom.'_'.$cnum;
160: }
161: if ($result eq 'ok') {
162: $idresult .= &mt('Classlist update for "[_1]" in "[_2]".',$uname.':'.$udom,$cdesc).'<br />'."\n";
163: } else {
164: $idresult .= &mt('Error: "[_1]" during classlist update for "[_2]" in "[_3]".',$result,$uname.':'.$udom,$cdesc).'<br />'."\n";
165: }
166: }
167: }
168: return $idresult;
169: }
170:
171: sub update_classlist {
172: my ($cdom,$cnum,$udom,$uname,$user,$newend) = @_;
173: my ($uid,$classlistentry);
174: my $fullname =
175: &Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'},
176: $user->{'lastname'},$user->{'generation'},
177: 'lastname');
178: my %classhash = &Apache::lonnet::get('classlist',[$uname.':'.$udom],
179: $cdom,$cnum);
180: my @classinfo = split(/:/,$classhash{$uname.':'.$udom});
181: my $ididx=&Apache::loncoursedata::CL_ID() - 2;
182: my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2;
183: my $endidx = &Apache::loncoursedata::CL_END() - 2;
184: my $startidx = &Apache::loncoursedata::CL_START() - 2;
185: for (my $i=0; $i<@classinfo; $i++) {
186: if ($i == $endidx) {
187: if ($newend ne '') {
188: $classlistentry .= $newend.':';
189: } else {
190: $classlistentry .= $classinfo[$i].':';
191: }
192: } elsif ($i == $startidx) {
193: if ($newend ne '') {
194: if ($classinfo[$i] > $newend) {
195: $classlistentry .= $newend.':';
196: } else {
197: $classlistentry .= $classinfo[$i].':';
198: }
199: } else {
200: $classlistentry .= $classinfo[$i].':';
201: }
202: } elsif ($i == $ididx) {
203: if (defined($user->{'id'})) {
204: $classlistentry .= $user->{'id'}.':';
205: } else {
206: $classlistentry .= $classinfo[$i].':';
207: }
208: } elsif ($i == $nameidx) {
209: if (defined($user->{'lastname'})) {
210: $classlistentry .= $fullname.':';
211: } else {
212: $classlistentry .= $classinfo[$i].':';
213: }
214: } else {
215: $classlistentry .= $classinfo[$i].':';
216: }
217: }
218: $classlistentry =~ s/:$//;
219: my $reply=&Apache::lonnet::cput('classlist',
220: {"$uname:$udom" => $classlistentry},
221: $cdom,$cnum);
222: if (($reply eq 'ok') || ($reply eq 'delayed')) {
223: return 'ok';
224: } else {
225: return 'error: '.$reply;
226: }
227: }
228:
229:
230: ###############################################################
231: ###############################################################
232: # build a role type and role selection form
233: sub domain_roles_select {
234: # Set up the role type and role selection boxes when in
235: # domain context
236: #
237: # Role types
238: my @roletypes = ('domain','author','course');
239: my %lt = &role_type_names();
240: #
241: # build up the menu information to be passed to
242: # &Apache::loncommon::linked_select_forms
243: my %select_menus;
244: if ($env{'form.roletype'} eq '') {
245: $env{'form.roletype'} = 'domain';
246: }
247: foreach my $roletype (@roletypes) {
248: # set up the text for this domain
249: $select_menus{$roletype}->{'text'}= $lt{$roletype};
250: # we want a choice of 'default' as the default in the second menu
251: if ($env{'form.roletype'} ne '') {
252: $select_menus{$roletype}->{'default'} = $env{'form.showrole'};
253: } else {
254: $select_menus{$roletype}->{'default'} = 'Any';
255: }
256: # Now build up the other items in the second menu
257: my @roles;
258: if ($roletype eq 'domain') {
259: @roles = &domain_roles();
260: } elsif ($roletype eq 'author') {
261: @roles = &construction_space_roles();
262: } else {
263: my $custom = 1;
264: @roles = &course_roles('domain',undef,$custom);
265: }
266: my $order = ['Any',@roles];
267: $select_menus{$roletype}->{'order'} = $order;
268: foreach my $role (@roles) {
269: if ($role eq 'cr') {
270: $select_menus{$roletype}->{'select2'}->{$role} =
271: &mt('Custom role');
272: } else {
273: $select_menus{$roletype}->{'select2'}->{$role} =
274: &Apache::lonnet::plaintext($role);
275: }
276: }
277: $select_menus{$roletype}->{'select2'}->{'Any'} = &mt('Any');
278: }
279: my $result = &Apache::loncommon::linked_select_forms
280: ('studentform',(' 'x3).&mt('Role: '),$env{'form.roletype'},
281: 'roletype','showrole',\%select_menus,['domain','author','course']);
282: return $result;
283: }
284:
285: ###############################################################
286: ###############################################################
287: sub hidden_input {
288: my ($name,$value) = @_;
289: return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
290: }
291:
292: sub print_upload_manager_header {
293: my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission)=@_;
294: my $javascript;
295: #
296: if (! exists($env{'form.upfile_associate'})) {
297: $env{'form.upfile_associate'} = 'forward';
298: }
299: if ($env{'form.associate'} eq 'Reverse Association') {
300: if ( $env{'form.upfile_associate'} ne 'reverse' ) {
301: $env{'form.upfile_associate'} = 'reverse';
302: } else {
303: $env{'form.upfile_associate'} = 'forward';
304: }
305: }
306: if ($env{'form.upfile_associate'} eq 'reverse') {
307: $javascript=&upload_manager_javascript_reverse_associate();
308: } else {
309: $javascript=&upload_manager_javascript_forward_associate();
310: }
311: #
312: # Deal with restored settings
313: my $password_choice = '';
314: if (exists($env{'form.ipwd_choice'}) &&
315: $env{'form.ipwd_choice'} ne '') {
316: # If a column was specified for password, assume it is for an
317: # internal password. This is a bug waiting to be filed (could be
318: # local or krb auth instead of internal) but I do not have the
319: # time to mess around with this now.
320: $password_choice = 'int';
321: }
322: #
323: my $groupslist;
324: if ($context eq 'course') {
325: $groupslist = &get_groupslist();
326: }
327: my $javascript_validations =
328: &javascript_validations('upload',$krbdefdom,$password_choice,undef,
329: $env{'request.role.domain'},$context,
330: $groupslist);
331: my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
332: $r->print('<p>'
333: .&mt('Total number of records found in file: [_1]'
334: ,'<b>'.$distotal.'</b>')
335: ."</p>\n");
336: $r->print('<div class="LC_left_float"><h3>'.
337: &mt('Identify fields in uploaded list')."</h3>\n");
338: $r->print(&mt('Enter as many fields as you can.<br /> The system will inform you and bring you back to this page, <br /> if the data selected are insufficient to add users.')."<br />\n");
339: $r->print(&hidden_input('action','upload').
340: &hidden_input('state','got_file').
341: &hidden_input('associate','').
342: &hidden_input('datatoken',$datatoken).
343: &hidden_input('fileupload',$env{'form.fileupload'}).
344: &hidden_input('upfiletype',$env{'form.upfiletype'}).
345: &hidden_input('upfile_associate',$env{'form.upfile_associate'}));
346: $r->print('<br /><label><input type="checkbox" name="noFirstLine"'.$checked.' />'.
347: &mt('Ignore First Line').'</label><br />');
348: $r->print('<br /><input type="button" value="'.&mt('Reverse Association').'" '.
349: 'name="Reverse Association" '.
350: 'onClick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />');
351: $r->print("<br /><br />\n".
352: '<script type="text/javascript" language="Javascript">'."\n".
353: $javascript."\n".$javascript_validations.'</script>');
354: }
355:
356: ###############################################################
357: ###############################################################
358: sub javascript_validations {
359: my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain,
360: $context,$groupslist)=@_;
361: my %param = (
362: kerb_def_dom => $krbdefdom,
363: curr_authtype => $curr_authtype,
364: );
365: if ($mode eq 'upload') {
366: $param{'formname'} = 'studentform';
367: } elsif ($mode eq 'createcourse') {
368: $param{'formname'} = 'ccrs';
369: } elsif ($mode eq 'modifycourse') {
370: $param{'formname'} = 'cmod';
371: $param{'mode'} = 'modifycourse',
372: $param{'curr_autharg'} = $curr_authfield;
373: }
374:
375: my ($setsection_call,$setsections_js);
376: my $finish = " vf.submit();\n";
377: if ($mode eq 'upload') {
378: if (($context eq 'course') || ($context eq 'domain')) {
379: if ($context eq 'course') {
380: if ($env{'request.course.sec'} eq '') {
381: $setsection_call = 'setSections(document.'.$param{'formname'}.');';
382: $setsections_js =
383: &setsections_javascript($param{'formname'},$groupslist,
384: $mode);
385: } else {
386: $setsection_call = "'ok'";
387: }
388: } elsif ($context eq 'domain') {
389: $setsection_call = 'setCourse()';
390: $setsections_js = &dc_setcourse_js($param{'formname'},$mode,$context);
391: }
392: $finish = " var checkSec = $setsection_call\n".
393: " if (checkSec == 'ok') {\n".
394: " vf.submit();\n".
395: " }\n";
396: }
397: }
398: my $authheader = &Apache::loncommon::authform_header(%param);
399:
400: my %alert = &Apache::lonlocal::texthash
401: (username => 'You need to specify the username field.',
402: authen => 'You must choose an authentication type.',
403: krb => 'You need to specify the Kerberos domain.',
404: ipass => 'You need to specify the initial password.',
405: name => 'The optional name field was not specified.',
406: snum => 'The optional student/employee ID field was not specified.',
407: section => 'The optional section field was not specified.',
408: email => 'The optional e-mail address field was not specified.',
409: role => 'The optional role field was not specified.',
410: domain => 'The optional domain field was not specified.',
411: continue => 'Continue adding users?',
412: );
413: if (($mode eq 'upload') && ($context eq 'domain')) {
414: $alert{'inststatus'} = &mt('The optional affiliation field was not specified');
415: }
416: my $function_name = <<"END";
417: $setsections_js
418:
419: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus) {
420: END
421: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain);
422: my $auth_checks;
423: if ($mode eq 'createcourse') {
424: $auth_checks .= (<<END);
425: if (vf.autoadds[0].checked == true) {
426: if (current.radiovalue == null || current.radiovalue == 'nochange') {
427: alert('$alert{'authen'}');
428: return;
429: }
430: }
431: END
432: } else {
433: $auth_checks .= (<<END);
434: var foundatype=0;
435: if (founduname==0) {
436: alert('$alert{'username'}');
437: return;
438: }
439:
440: END
441: if ($authnum > 1) {
442: $auth_checks .= (<<END);
443: if (current.radiovalue == null || current.radiovalue == '' || current.radiovalue == 'nochange') {
444: // They did not check any of the login radiobuttons.
445: alert('$alert{'authen'}');
446: return;
447: }
448: END
449: }
450: }
451: if ($mode eq 'createcourse') {
452: $auth_checks .= "
453: if ( (vf.autoadds[0].checked == true) &&
454: (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
455: ";
456: } elsif ($mode eq 'modifycourse') {
457: $auth_checks .= "
458: if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') {
459: ";
460: }
461: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
462: $auth_checks .= (<<END);
463: var alertmsg = '';
464: switch (current.radiovalue) {
465: case 'krb':
466: alertmsg = '$alert{'krb'}';
467: break;
468: default:
469: alertmsg = '';
470: }
471: if (alertmsg != '') {
472: alert(alertmsg);
473: return;
474: }
475: }
476: END
477: } else {
478: $auth_checks .= (<<END);
479: foundatype=1;
480: if (current.argfield == null || current.argfield == '') {
481: var alertmsg = '';
482: switch (current.radiovalue) {
483: case 'krb':
484: alertmsg = '$alert{'krb'}';
485: break;
486: case 'loc':
487: case 'fsys':
488: alertmsg = '$alert{'ipass'}';
489: break;
490: case 'fsys':
491: alertmsg = '';
492: break;
493: default:
494: alertmsg = '';
495: }
496: if (alertmsg != '') {
497: alert(alertmsg);
498: return;
499: }
500: }
501: END
502: }
503: my $section_checks;
504: my $optional_checks = '';
505: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
506: $optional_checks = (<<END);
507: vf.submit();
508: }
509: END
510: } else {
511: $section_checks = §ion_check_js();
512: $optional_checks = (<<END);
513: var message='';
514: if (foundname==0) {
515: message='$alert{'name'}';
516: }
517: if (foundid==0) {
518: if (message!='') {
519: message+='\\n';
520: }
521: message+='$alert{'snum'}';
522: }
523: if (foundsec==0) {
524: if (message!='') {
525: message+='\\n';
526: }
527: }
528: if (foundemail==0) {
529: if (message!='') {
530: message+='\\n';
531: }
532: message+='$alert{'email'}';
533: }
534: if (foundrole==0) {
535: if (message!='') {
536: message+='\\n';
537: }
538: message+='$alert{'role'}';
539: }
540: if (founddomain==0) {
541: if (message!='') {
542: message+='\\n';
543: }
544: message+='$alert{'domain'}';
545: }
546: END
547: if (($mode eq 'upload') && ($context eq 'domain')) {
548: $optional_checks .= (<<END);
549:
550: if (foundinststatus==0) {
551: if (message!='') {
552: message+='\\n';
553: }
554: message+='$alert{'inststatus'}';
555: }
556: END
557: }
558: $optional_checks .= (<<END);
559:
560: if (message!='') {
561: message+= '\\n$alert{'continue'}';
562: if (confirm(message)) {
563: vf.state.value='enrolling';
564: $finish
565: }
566: } else {
567: vf.state.value='enrolling';
568: $finish
569: }
570: }
571: END
572: }
573: my $result = $function_name.$auth_checks.$optional_checks."\n".
574: $section_checks.$authheader;
575: return $result;
576: }
577: ###############################################################
578: ###############################################################
579: sub upload_manager_javascript_forward_associate {
580: return(<<ENDPICK);
581: function verify(vf,sec_caller) {
582: var founduname=0;
583: var foundpwd=0;
584: var foundname=0;
585: var foundid=0;
586: var foundsec=0;
587: var foundemail=0;
588: var foundrole=0;
589: var founddomain=0;
590: var foundinststatus=0;
591: var tw;
592: for (i=0;i<=vf.nfields.value;i++) {
593: tw=eval('vf.f'+i+'.selectedIndex');
594: if (tw==1) { founduname=1; }
595: if ((tw>=2) && (tw<=6)) { foundname=1; }
596: if (tw==7) { foundid=1; }
597: if (tw==8) { foundsec=1; }
598: if (tw==9) { foundpwd=1; }
599: if (tw==10) { foundemail=1; }
600: if (tw==11) { foundrole=1; }
601: if (tw==12) { founddomain=1; }
602: if (tw==13) { foundinststatus=1; }
603: }
604: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus);
605: }
606:
607: //
608: // vf = this.form
609: // tf = column number
610: //
611: // values of nw
612: //
613: // 0 = none
614: // 1 = username
615: // 2 = names (lastname, firstnames)
616: // 3 = fname (firstname)
617: // 4 = mname (middlename)
618: // 5 = lname (lastname)
619: // 6 = gen (generation)
620: // 7 = id
621: // 8 = section
622: // 9 = ipwd (password)
623: // 10 = email address
624: // 11 = role
625: // 12 = domain
626: // 13 = inststatus
627:
628: function flip(vf,tf) {
629: var nw=eval('vf.f'+tf+'.selectedIndex');
630: var i;
631: // make sure no other columns are labeled the same as this one
632: for (i=0;i<=vf.nfields.value;i++) {
633: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
634: eval('vf.f'+i+'.selectedIndex=0;')
635: }
636: }
637: // If we set this to 'lastname, firstnames', clear out all the ones
638: // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
639: if (nw==2) {
640: for (i=0;i<=vf.nfields.value;i++) {
641: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
642: (eval('vf.f'+i+'.selectedIndex')<=6)) {
643: eval('vf.f'+i+'.selectedIndex=0;')
644: }
645: }
646: }
647: // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
648: // clear out any that are set to 'lastname, firstnames' (2)
649: if ((nw>=3) && (nw<=6)) {
650: for (i=0;i<=vf.nfields.value;i++) {
651: if (eval('vf.f'+i+'.selectedIndex')==2) {
652: eval('vf.f'+i+'.selectedIndex=0;')
653: }
654: }
655: }
656: // If we set the password, make the password form below correspond to
657: // the new value.
658: if (nw==9) {
659: changed_radio('int',document.studentform);
660: set_auth_radio_buttons('int',document.studentform);
661: vf.intarg.value='';
662: vf.krbarg.value='';
663: vf.locarg.value='';
664: }
665: }
666:
667: function clearpwd(vf) {
668: var i;
669: for (i=0;i<=vf.nfields.value;i++) {
670: if (eval('vf.f'+i+'.selectedIndex')==9) {
671: eval('vf.f'+i+'.selectedIndex=0;')
672: }
673: }
674: }
675:
676: ENDPICK
677: }
678:
679: ###############################################################
680: ###############################################################
681: sub upload_manager_javascript_reverse_associate {
682: return(<<ENDPICK);
683: function verify(vf,sec_caller) {
684: var founduname=0;
685: var foundpwd=0;
686: var foundname=0;
687: var foundid=0;
688: var foundsec=0;
689: var foundrole=0;
690: var founddomain=0;
691: var foundinststatus=0;
692: var tw;
693: for (i=0;i<=vf.nfields.value;i++) {
694: tw=eval('vf.f'+i+'.selectedIndex');
695: if (i==0 && tw!=0) { founduname=1; }
696: if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
697: if (i==6 && tw!=0) { foundid=1; }
698: if (i==7 && tw!=0) { foundsec=1; }
699: if (i==8 && tw!=0) { foundpwd=1; }
700: if (i==9 && tw!=0) { foundrole=1; }
701: if (i==10 && tw!=0) { founddomain=1; }
702: if (i==13 && tw!=0) { foundinstatus=1; }
703: }
704: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole,founddomain,foundinststatus);
705: }
706:
707: function flip(vf,tf) {
708: var nw=eval('vf.f'+tf+'.selectedIndex');
709: var i;
710: // picked the all one name field, reset the other name ones to blank
711: if (tf==1 && nw!=0) {
712: for (i=2;i<=5;i++) {
713: eval('vf.f'+i+'.selectedIndex=0;')
714: }
715: }
716: //picked one of the piecewise name fields, reset the all in
717: //one field to blank
718: if ((tf>=2) && (tf<=5) && (nw!=0)) {
719: eval('vf.f1.selectedIndex=0;')
720: }
721: // intial password specified, pick internal authentication
722: if (tf==8 && nw!=0) {
723: changed_radio('int',document.studentform);
724: set_auth_radio_buttons('int',document.studentform);
725: vf.krbarg.value='';
726: vf.intarg.value='';
727: vf.locarg.value='';
728: }
729: }
730:
731: function clearpwd(vf) {
732: var i;
733: if (eval('vf.f8.selectedIndex')!=0) {
734: eval('vf.f8.selectedIndex=0;')
735: }
736: }
737: ENDPICK
738: }
739:
740: ###############################################################
741: ###############################################################
742: sub print_upload_manager_footer {
743: my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission) = @_;
744: my $form = 'document.studentform';
745: my $formname = 'studentform';
746: my ($krbdef,$krbdefdom) =
747: &Apache::loncommon::get_kerberos_defaults($defdom);
748: my %param = ( formname => $form,
749: kerb_def_dom => $krbdefdom,
750: kerb_def_auth => $krbdef
751: );
752: if (exists($env{'form.ipwd_choice'}) &&
753: defined($env{'form.ipwd_choice'}) &&
754: $env{'form.ipwd_choice'} ne '') {
755: $param{'curr_authtype'} = 'int';
756: }
757: my $krbform = &Apache::loncommon::authform_kerberos(%param);
758: my $intform = &Apache::loncommon::authform_internal(%param);
759: my $locform = &Apache::loncommon::authform_local(%param);
760: my $date_table = &date_setting_table(undef,undef,$context,undef,
761: $formname,$permission);
762:
763: my $Str = "\n".'<div class="LC_left_float">';
764: $Str .= &hidden_input('nfields',$i);
765: $Str .= &hidden_input('keyfields',$keyfields);
766:
767: $Str .= '<h3>'.&mt('Options').'</h3>'
768: .&Apache::lonhtmlcommon::start_pick_box();
769:
770: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Login Type'));
771: if ($context eq 'domain') {
772: $Str .= '<p>'
773: .&mt('Change authentication for existing users in domain "[_1]" to these settings?'
774: ,$defdom)
775: .' <span class="LC_nobreak"><label>'
776: .'<input type="radio" name="changeauth" value="No" checked="checked" />'
777: .&mt('No').'</label>'
778: .' <label>'
779: .'<input type="radio" name="changeauth" value="Yes" />'
780: .&mt('Yes').'</label>'
781: .'</span></p>';
782: } else {
783: $Str .= '<p class="LC_info">'."\n".
784: &mt('This will not take effect if the user already exists.').
785: &Apache::loncommon::help_open_topic('Auth_Options').
786: "</p>\n";
787: }
788: $Str .= &set_login($defdom,$krbform,$intform,$locform)
789: .&Apache::lonhtmlcommon::row_closure();
790:
791: my ($home_server_pick,$numlib) =
792: &Apache::loncommon::home_server_form_item($defdom,'lcserver',
793: 'default','hide');
794: #FIXME: Broken?!? $home_server_pick returns empty value on prod (2.8.1) and on dev server. SB 2009-08-03
795: if ($numlib > 1) {
796: $Str .= &Apache::lonhtmlcommon::row_title(
797: &mt('LON-CAPA Home Server for New Users'))
798: .&mt('LON-CAPA domain: [_1] with home server:','"'.$defdom.'"')
799: .$home_server_pick
800: .&Apache::lonhtmlcommon::row_closure();
801: } else {
802: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Home Server'))
803: .$home_server_pick
804: .&Apache::lonhtmlcommon::row_closure();
805: }
806:
807: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain'))
808: .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1)
809: .&Apache::lonhtmlcommon::row_closure();
810:
811: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates'))
812: ."<p>\n".$date_table."</p>\n"
813: .&Apache::lonhtmlcommon::row_closure();
814:
815: if ($context eq 'domain') {
816: $Str .= &Apache::lonhtmlcommon::row_title(
817: &mt('Settings for assigning roles'))
818: .&mt('Pick the action to take on roles for these users:').'<br />'
819: .'<span class="LC_nobreak"><label>'
820: .'<input type="radio" name="roleaction" value="norole" checked="checked" />'
821: .' '.&mt('No role changes').'</label>'
822: .' <label>'
823: .'<input type="radio" name="roleaction" value="domain" />'
824: .' '.&mt('Add a domain role').'</label>'
825: .' <label>'
826: .'<input type="radio" name="roleaction" value="course" />'
827: .' '.&mt('Add a course role').'</label>'
828: .'</span>';
829: } elsif ($context eq 'author') {
830: $Str .= &Apache::lonhtmlcommon::row_title(
831: &mt('Default role'))
832: .&mt('Choose the role to assign to users without a value specified in the uploaded file.')
833: } elsif ($context eq 'course') {
834: $Str .= &Apache::lonhtmlcommon::row_title(
835: &mt('Default role and section'))
836: .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.');
837: } else {
838: $Str .= &Apache::lonhtmlcommon::row_title(
839: &mt('Default role and/or section(s)'))
840: .&mt('Role and/or section(s) for users without values specified in the uploaded file.');
841: }
842: if (($context eq 'domain') || ($context eq 'author')) {
843: $Str .= '<br />';
844: my ($options,$cb_script,$coursepick) = &default_role_selector($context,1);
845: if ($context eq 'domain') {
846: $Str .= '<p>'
847: .'<b>'.&mt('Domain Level').'</b><br />'
848: .$options
849: .'</p><p>'
850: .'<b>'.&mt('Course Level').'</b>'
851: .'</p>'
852: .$cb_script.$coursepick
853: .&Apache::lonhtmlcommon::row_closure();
854: } elsif ($context eq 'author') {
855: $Str .= $options
856: .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
857: }
858: } else {
859: my ($cnum,$cdom) = &get_course_identity();
860: my $rowtitle = &mt('section');
861: my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle,
862: $permission,$context,'upload');
863: $Str .= $secbox
864: .&Apache::lonhtmlcommon::row_closure();
865:
866: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Full Update'))
867: .'<label><input type="checkbox" name="fullup" value="yes" />'.
868: ' '.&mt('Display students with current/future access who are not in the uploaded file.')
869: .'</label><br />'
870: .&mt('Students selected from this list can be dropped.')
871: .&Apache::lonhtmlcommon::row_closure();
872: }
873: if ($context eq 'course' || $context eq 'domain') {
874: $Str .= &forceid_change($context);
875: }
876:
877: $Str .= &Apache::lonhtmlcommon::end_pick_box();
878: $Str .= '</div>';
879:
880: # Footer
881: $Str .= '<div class="LC_clear_float_footer">'
882: .'<hr />';
883: if ($context eq 'course') {
884: $Str .= '<p class="LC_info">'
885: .&mt('Note: For large courses, this operation may be time consuming.')
886: .'</p>';
887: }
888: $Str .= '<p><input type="button"'
889: .'onClick="javascript:verify(this.form,this.form.csec)" '
890: .'value="'.&mt('Update Users').'" />'
891: .'</p>'."\n"
892: .'</div>';
893: $r->print($Str);
894: return;
895: }
896:
897: sub forceid_change {
898: my ($context) = @_;
899: my $output =
900: &Apache::lonhtmlcommon::row_title(&mt('Student/Employee ID'))
901: .'<label><input type="checkbox" name="forceid" value="yes" />'
902: .&mt('Disable Student/Employee ID Safeguard and force change of conflicting IDs')
903: .'</label><br />'."\n"
904: .&mt('(only do if you know what you are doing.)')."\n";
905: if ($context eq 'domain') {
906: $output .= '<br /><label><input type="checkbox" name="recurseid"'.
907: ' value="yes" />'.
908: &mt('Update student/employee ID in courses in which user is active/future student,[_1](if forcing change).','<br />').
909: '</label>'."\n";
910: }
911: $output .= &Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
912: return $output;
913: }
914:
915: ###############################################################
916: ###############################################################
917: sub print_upload_manager_form {
918: my ($r,$context,$permission) = @_;
919: my $firstLine;
920: my $datatoken;
921: if (!$env{'form.datatoken'}) {
922: $datatoken=&Apache::loncommon::upfile_store($r);
923: } else {
924: $datatoken=$env{'form.datatoken'};
925: &Apache::loncommon::load_tmp_file($r);
926: }
927: my @records=&Apache::loncommon::upfile_record_sep();
928: if($env{'form.noFirstLine'}){
929: $firstLine=shift(@records);
930: }
931: my $total=$#records;
932: my $distotal=$total+1;
933: my $today=time;
934: my $halfyear=$today+15552000;
935: #
936: # Restore memorized settings
937: my $col_setting_names = { 'username_choice' => 'scalar', # column settings
938: 'names_choice' => 'scalar',
939: 'fname_choice' => 'scalar',
940: 'mname_choice' => 'scalar',
941: 'lname_choice' => 'scalar',
942: 'gen_choice' => 'scalar',
943: 'id_choice' => 'scalar',
944: 'sec_choice' => 'scalar',
945: 'ipwd_choice' => 'scalar',
946: 'email_choice' => 'scalar',
947: 'role_choice' => 'scalar',
948: 'domain_choice' => 'scalar',
949: 'inststatus_choice' => 'scalar',
950: };
951: my $defdom = $env{'request.role.domain'};
952: if ($context eq 'course') {
953: &Apache::loncommon::restore_course_settings('enrollment_upload',
954: $col_setting_names);
955: } else {
956: &Apache::loncommon::restore_settings($context,'user_upload',
957: $col_setting_names);
958: }
959: #
960: # Determine kerberos parameters as appropriate
961: my ($krbdef,$krbdefdom) =
962: &Apache::loncommon::get_kerberos_defaults($defdom);
963: #
964: &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context,
965: $permission);
966: my $i;
967: my $keyfields;
968: if ($total>=0) {
969: my @field=
970: (['username',&mt('Username'), $env{'form.username_choice'}],
971: ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}],
972: ['fname',&mt('First Name'), $env{'form.fname_choice'}],
973: ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}],
974: ['lname',&mt('Last Name'), $env{'form.lname_choice'}],
975: ['gen', &mt('Generation'), $env{'form.gen_choice'}],
976: ['id', &mt('Student/Employee ID'),$env{'form.id_choice'}],
977: ['sec', &mt('Section'), $env{'form.sec_choice'}],
978: ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}],
979: ['email',&mt('E-mail Address'), $env{'form.email_choice'}],
980: ['role',&mt('Role'), $env{'form.role_choice'}],
981: ['domain',&mt('Domain'), $env{'form.domain_choice'}],
982: ['inststatus',&mt('Affiliation'), $env{'form.inststatus_choice'}]);
983: if ($env{'form.upfile_associate'} eq 'reverse') {
984: &Apache::loncommon::csv_print_samples($r,\@records);
985: $i=&Apache::loncommon::csv_print_select_table($r,\@records,
986: \@field);
987: foreach (@field) {
988: $keyfields.=$_->[0].',';
989: }
990: chop($keyfields);
991: } else {
992: unshift(@field,['none','']);
993: $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
994: \@field);
995: my %sone=&Apache::loncommon::record_sep($records[0]);
996: $keyfields=join(',',sort(keys(%sone)));
997: }
998: }
999: $r->print('</div>');
1000: &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
1001: $context,$permission);
1002: }
1003:
1004: sub setup_date_selectors {
1005: my ($starttime,$endtime,$mode,$nolink,$formname) = @_;
1006: if ($formname eq '') {
1007: $formname = 'studentform';
1008: }
1009: if (! defined($starttime)) {
1010: $starttime = time;
1011: unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
1012: if (exists($env{'course.'.$env{'request.course.id'}.
1013: '.default_enrollment_start_date'})) {
1014: $starttime = $env{'course.'.$env{'request.course.id'}.
1015: '.default_enrollment_start_date'};
1016: }
1017: }
1018: }
1019: if (! defined($endtime)) {
1020: $endtime = time+(6*30*24*60*60); # 6 months from now, approx
1021: unless ($mode eq 'createcourse') {
1022: if (exists($env{'course.'.$env{'request.course.id'}.
1023: '.default_enrollment_end_date'})) {
1024: $endtime = $env{'course.'.$env{'request.course.id'}.
1025: '.default_enrollment_end_date'};
1026: }
1027: }
1028: }
1029:
1030: my $startdateform =
1031: &Apache::lonhtmlcommon::date_setter($formname,'startdate',$starttime,
1032: undef,undef,undef,undef,undef,undef,undef,$nolink);
1033:
1034: my $enddateform =
1035: &Apache::lonhtmlcommon::date_setter($formname,'enddate',$endtime,
1036: undef,undef,undef,undef,undef,undef,undef,$nolink);
1037:
1038: if ($mode eq 'create_enrolldates') {
1039: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1040: 'startenroll',
1041: $starttime);
1042: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1043: 'endenroll',
1044: $endtime);
1045: }
1046: if ($mode eq 'create_defaultdates') {
1047: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1048: 'startaccess',
1049: $starttime);
1050: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1051: 'endaccess',
1052: $endtime);
1053: }
1054: return ($startdateform,$enddateform);
1055: }
1056:
1057:
1058: sub get_dates_from_form {
1059: my ($startname,$endname) = @_;
1060: if ($startname eq '') {
1061: $startname = 'startdate';
1062: }
1063: if ($endname eq '') {
1064: $endname = 'enddate';
1065: }
1066: my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname);
1067: my $enddate = &Apache::lonhtmlcommon::get_date_from_form($endname);
1068: if ($env{'form.no_end_date'}) {
1069: $enddate = 0;
1070: }
1071: return ($startdate,$enddate);
1072: }
1073:
1074: sub date_setting_table {
1075: my ($starttime,$endtime,$mode,$bulkaction,$formname,$permission) = @_;
1076: my $nolink;
1077: if ($bulkaction) {
1078: $nolink = 1;
1079: }
1080: my ($startform,$endform) =
1081: &setup_date_selectors($starttime,$endtime,$mode,$nolink,$formname);
1082: my $dateDefault;
1083: if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
1084: $dateDefault = ' ';
1085: } elsif ($mode ne 'author' && $mode ne 'domain') {
1086: if (($bulkaction eq 'reenable') ||
1087: ($bulkaction eq 'activate') ||
1088: ($bulkaction eq 'chgdates') ||
1089: ($env{'form.action'} eq 'upload')) {
1090: if ($env{'request.course.sec'} eq '') {
1091: $dateDefault = '<span class="LC_nobreak">'.
1092: '<label><input type="checkbox" name="makedatesdefault" value="1" /> '.
1093: &mt('make these dates the default access dates for future student enrollment').
1094: '</label></span>';
1095: }
1096: }
1097: }
1098: my $perpetual = '<span class="LC_nobreak"><label><input type="checkbox" name="no_end_date"';
1099: if (defined($endtime) && $endtime == 0) {
1100: $perpetual .= ' checked="checked"';
1101: }
1102: $perpetual.= ' /> '.&mt('no ending date').'</label></span>';
1103: if ($mode eq 'create_enrolldates') {
1104: $perpetual = ' ';
1105: }
1106: my $result = &Apache::lonhtmlcommon::start_pick_box()."\n";
1107: $result .= &Apache::lonhtmlcommon::row_title(&mt('Starting Date'),
1108: 'LC_oddrow_value')."\n".
1109: $startform."\n".
1110: &Apache::lonhtmlcommon::row_closure(1).
1111: &Apache::lonhtmlcommon::row_title(&mt('Ending Date'),
1112: 'LC_oddrow_value')."\n".
1113: $endform.' '.$perpetual.
1114: &Apache::lonhtmlcommon::row_closure(1).
1115: &Apache::lonhtmlcommon::end_pick_box();
1116: if ($dateDefault) {
1117: $result .= $dateDefault.'<br />'."\n";
1118: }
1119: return $result;
1120: }
1121:
1122: sub make_dates_default {
1123: my ($startdate,$enddate,$context) = @_;
1124: my $result = '';
1125: if ($context eq 'course') {
1126: my ($cnum,$cdom) = &get_course_identity();
1127: my $put_result = &Apache::lonnet::put('environment',
1128: {'default_enrollment_start_date'=>$startdate,
1129: 'default_enrollment_end_date' =>$enddate},$cdom,$cnum);
1130: if ($put_result eq 'ok') {
1131: $result .= &mt('Set default start and end access dates for course.').
1132: '<br />'."\n";
1133: #
1134: # Refresh the course environment
1135: &Apache::lonnet::coursedescription($env{'request.course.id'},
1136: {'freshen_cache' => 1});
1137: } else {
1138: $result .= &mt('Unable to set default access dates for course.').":".$put_result.
1139: '<br />';
1140: }
1141: }
1142: return $result;
1143: }
1144:
1145: sub default_role_selector {
1146: my ($context,$checkpriv) = @_;
1147: my %customroles;
1148: my ($options,$coursepick,$cb_jscript);
1149: if ($context ne 'author') {
1150: %customroles = &my_custom_roles();
1151: }
1152:
1153: my %lt=&Apache::lonlocal::texthash(
1154: 'rol' => "Role",
1155: 'grs' => "Section",
1156: 'exs' => "Existing sections",
1157: 'new' => "New section",
1158: );
1159: $options = '<select name="defaultrole">'."\n".
1160: ' <option value="">'.&mt('Please select').'</option>'."\n";
1161: if ($context eq 'course') {
1162: $options .= &default_course_roles($context,$checkpriv,%customroles);
1163: } elsif ($context eq 'author') {
1164: my @roles = &construction_space_roles($checkpriv);
1165: foreach my $role (@roles) {
1166: my $plrole=&Apache::lonnet::plaintext($role);
1167: $options .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
1168: }
1169: } elsif ($context eq 'domain') {
1170: my @roles = &domain_roles($checkpriv);
1171: foreach my $role (@roles) {
1172: my $plrole=&Apache::lonnet::plaintext($role);
1173: $options .= ' <option value="'.$role.'">'.$plrole.'</option>';
1174: }
1175: my $courseform = &Apache::loncommon::selectcourse_link
1176: ('studentform','dccourse','dcdomain','coursedesc',"$env{'request.role.domain'}",undef,'Course');
1177: $cb_jscript =
1178: &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'},'currsec','studentform');
1179: $coursepick = &Apache::loncommon::start_data_table().
1180: &Apache::loncommon::start_data_table_header_row().
1181: '<th>'.$courseform.'</th><th>'.$lt{'rol'}.'</th>'.
1182: '<th>'.$lt{'grs'}.'</th>'.
1183: &Apache::loncommon::end_data_table_header_row().
1184: &Apache::loncommon::start_data_table_row()."\n".
1185: '<td><input type="text" name="coursedesc" value="" onFocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc',''".')" /></td>'."\n".
1186: '<td><select name="courserole">'."\n".
1187: &default_course_roles($context,$checkpriv,%customroles)."\n".
1188: '</select></td><td>'.
1189: '<table class="LC_createuser">'.
1190: '<tr class="LC_section_row"><td valign"top">'.
1191: $lt{'exs'}.'<br /><select name="currsec">'.
1192: ' <option value=""><--'.&mt('Pick course first').
1193: '</select></td>'.
1194: '<td> </td>'.
1195: '<td valign="top">'.$lt{'new'}.'<br />'.
1196: '<input type="text" name="newsec" value="" size="5" />'.
1197: '<input type="hidden" name="groups" value="" />'.
1198: '<input type="hidden" name="sections" value="" />'.
1199: '<input type="hidden" name="origdom" value="'.
1200: $env{'request.role.domain'}.'" />'.
1201: '<input type="hidden" name="dccourse" value="" />'.
1202: '<input type="hidden" name="dcdomain" value="" />'.
1203: '</td></tr></table></td>'.
1204: &Apache::loncommon::end_data_table_row().
1205: &Apache::loncommon::end_data_table()."\n";
1206: }
1207: $options .= '</select>';
1208: return ($options,$cb_jscript,$coursepick);
1209: }
1210:
1211: sub default_course_roles {
1212: my ($context,$checkpriv,%customroles) = @_;
1213: my $output;
1214: my $custom = 1;
1215: my @roles = &course_roles($context,$checkpriv,$custom);
1216: foreach my $role (@roles) {
1217: if ($role ne 'cr') {
1218: my $plrole=&Apache::lonnet::plaintext($role);
1219: $output .= ' <option value="'.$role.'">'.$plrole.'</option>';
1220: }
1221: }
1222: if (keys(%customroles) > 0) {
1223: if (grep(/^cr$/,@roles)) {
1224: foreach my $cust (sort(keys(%customroles))) {
1225: my $custrole='cr_'.$env{'user.domain'}.
1226: '_'.$env{'user.name'}.'_'.$cust;
1227: $output .= ' <option value="'.$custrole.'">'.$cust.'</option>';
1228: }
1229: }
1230: }
1231: return $output;
1232: }
1233:
1234: sub construction_space_roles {
1235: my ($checkpriv) = @_;
1236: my @allroles = &roles_by_context('author');
1237: my @roles;
1238: if ($checkpriv) {
1239: foreach my $role (@allroles) {
1240: if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) {
1241: push(@roles,$role);
1242: }
1243: }
1244: return @roles;
1245: } else {
1246: return @allroles;
1247: }
1248: }
1249:
1250: sub domain_roles {
1251: my ($checkpriv) = @_;
1252: my @allroles = &roles_by_context('domain');
1253: my @roles;
1254: if ($checkpriv) {
1255: foreach my $role (@allroles) {
1256: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
1257: push(@roles,$role);
1258: }
1259: }
1260: return @roles;
1261: } else {
1262: return @allroles;
1263: }
1264: }
1265:
1266: sub course_roles {
1267: my ($context,$checkpriv,$custom) = @_;
1268: my @allroles = &roles_by_context('course',$custom);
1269: my @roles;
1270: if ($context eq 'domain') {
1271: @roles = @allroles;
1272: } elsif ($context eq 'course') {
1273: if ($env{'request.course.id'}) {
1274: if ($checkpriv) {
1275: foreach my $role (@allroles) {
1276: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
1277: push(@roles,$role);
1278: } else {
1279: if ($role ne 'cc' && $env{'request.course.sec'} ne '') {
1280: if (&Apache::lonnet::allowed('c'.$role,
1281: $env{'request.course.id'}.'/'.
1282: $env{'request.course.sec'})) {
1283: push(@roles,$role);
1284: }
1285: }
1286: }
1287: }
1288: } else {
1289: @roles = @allroles;
1290: }
1291: }
1292: }
1293: return @roles;
1294: }
1295:
1296: sub curr_role_permissions {
1297: my ($context,$setting,$checkpriv) = @_;
1298: my $custom = 1;
1299: my @roles;
1300: if ($context eq 'author') {
1301: @roles = &construction_space_roles($checkpriv);
1302: } elsif ($context eq 'domain') {
1303: if ($setting eq 'course') {
1304: @roles = &course_roles($context,$checkpriv,$custom);
1305: } else {
1306: @roles = &domain_roles($checkpriv);
1307: }
1308: } elsif ($context eq 'course') {
1309: @roles = &course_roles($context,$checkpriv,$custom);
1310: }
1311: return @roles;
1312: }
1313:
1314: # ======================================================= Existing Custom Roles
1315:
1316: sub my_custom_roles {
1317: my %returnhash=();
1318: my %rolehash=&Apache::lonnet::dump('roles');
1319: foreach my $key (keys %rolehash) {
1320: if ($key=~/^rolesdef\_(\w+)$/) {
1321: $returnhash{$1}=$1;
1322: }
1323: }
1324: return %returnhash;
1325: }
1326:
1327: sub print_userlist {
1328: my ($r,$mode,$permission,$context,$formname,$totcodes,$codetitles,
1329: $idlist,$idlist_titles) = @_;
1330: my $format = $env{'form.output'};
1331: if (! exists($env{'form.sortby'})) {
1332: $env{'form.sortby'} = 'username';
1333: }
1334: if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) {
1335: $env{'form.Status'} = 'Active';
1336: }
1337: my $status_select = &Apache::lonhtmlcommon::StatusOptions
1338: ($env{'form.Status'});
1339:
1340: if ($env{'form.showrole'} eq '') {
1341: if ($context eq 'course') {
1342: $env{'form.showrole'} = 'st';
1343: } else {
1344: $env{'form.showrole'} = 'Any';
1345: }
1346: }
1347: if (! defined($env{'form.output'}) ||
1348: $env{'form.output'} !~ /^(csv|excel|html)$/ ) {
1349: $env{'form.output'} = 'html';
1350: }
1351:
1352: my @statuses;
1353: if ($env{'form.Status'} eq 'Any') {
1354: @statuses = ('previous','active','future');
1355: } elsif ($env{'form.Status'} eq 'Expired') {
1356: @statuses = ('previous');
1357: } elsif ($env{'form.Status'} eq 'Active') {
1358: @statuses = ('active');
1359: } elsif ($env{'form.Status'} eq 'Future') {
1360: @statuses = ('future');
1361: }
1362:
1363: # if ($context eq 'course') {
1364: # $r->print(&display_adv_courseroles());
1365: # }
1366: #
1367: # Interface output
1368: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
1369: '<input type="hidden" name="action" value="'.
1370: $env{'form.action'}.'" />');
1371: $r->print("<p>\n");
1372: if ($env{'form.action'} ne 'modifystudent') {
1373: my %lt=&Apache::lonlocal::texthash('csv' => "CSV",
1374: 'excel' => "Excel",
1375: 'html' => 'HTML');
1376: my $output_selector = '<select size="1" name="output" >';
1377: foreach my $outputformat ('html','csv','excel') {
1378: my $option = '<option value="'.$outputformat.'" ';
1379: if ($outputformat eq $env{'form.output'}) {
1380: $option .= 'selected ';
1381: }
1382: $option .='>'.$lt{$outputformat}.'</option>';
1383: $output_selector .= "\n".$option;
1384: }
1385: $output_selector .= '</select>';
1386: $r->print('<label><span class="LC_nobreak">'
1387: .&mt('Output Format: [_1]',$output_selector)
1388: .'</span></label>'.(' 'x3));
1389: }
1390: $r->print('<label><span class="LC_nobreak">'
1391: .&mt('User Status: [_1]',$status_select)
1392: .'</span></label>'.(' 'x3)."\n");
1393: my $roleselected = '';
1394: if ($env{'form.showrole'} eq 'Any') {
1395: $roleselected = ' selected="selected"';
1396: }
1397: my ($cnum,$cdom);
1398: $r->print(&role_filter($context));
1399: if ($context eq 'course') {
1400: ($cnum,$cdom) = &get_course_identity();
1401: $r->print(§ion_group_filter($cnum,$cdom));
1402: }
1403: if ($env{'form.phase'} eq '') {
1404: $r->print('<br /><br />'.&list_submit_button(&mt('Display List of Users')).
1405: "\n</p>\n".
1406: '<input type="hidden" name="phase" value="" /></form>');
1407: return;
1408: }
1409: if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
1410: $r->print(' '.&list_submit_button(&mt('Update Display')).
1411: "\n</p>\n");
1412: }
1413: my ($indexhash,$keylist) = &make_keylist_array();
1414: my (%userlist,%userinfo);
1415: if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
1416: my $courseform =
1417: &Apache::lonhtmlcommon::course_selection($formname,$totcodes,
1418: $codetitles,$idlist,$idlist_titles);
1419: $r->print('<p>'.&Apache::lonhtmlcommon::start_pick_box()."\n".
1420: &Apache::lonhtmlcommon::start_pick_box()."\n".
1421: &Apache::lonhtmlcommon::row_title(&mt('Select Course(s)'),
1422: 'LC_oddrow_value')."\n".
1423: $courseform."\n".
1424: &Apache::lonhtmlcommon::row_closure(1).
1425: &Apache::lonhtmlcommon::end_pick_box().'</p>'.
1426: '<p>'.&list_submit_button(&mt('Update Display')).
1427: "\n".'</p><span class="LC_warning">'.&mt('Warning: data retrieval for multiple courses can take considerable time, as this operation is not currently optimized.').'</span>'."\n");
1428: if ($env{'form.coursepick'}) {
1429: $r->print('<hr />'.&mt('Searching').' ...<br /> <br />');
1430: }
1431: } else {
1432: $r->print('<hr />'.&mt('Searching').' ...<br /> <br />');
1433: }
1434: $r->rflush();
1435: if ($context eq 'course') {
1436: if (($env{'form.showrole'} eq 'st') || ($env{'form.showrole'} eq 'Any')) {
1437: my $classlist = &Apache::loncoursedata::get_classlist();
1438: if (ref($classlist) eq 'HASH') {
1439: %userlist = %{$classlist};
1440: }
1441: }
1442: if ($env{'form.showrole'} ne 'st') {
1443: my $showroles;
1444: if ($env{'form.showrole'} ne 'Any') {
1445: $showroles = [$env{'form.showrole'}];
1446: } else {
1447: $showroles = undef;
1448: }
1449: my $withsec = 1;
1450: my $hidepriv = 1;
1451: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
1452: \@statuses,$showroles,undef,$withsec,$hidepriv);
1453: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1454: \%advrolehash,$permission);
1455: }
1456: } else {
1457: my (%cstr_roles,%dom_roles);
1458: if ($context eq 'author') {
1459: # List co-authors and assistant co-authors
1460: my @possroles = &roles_by_context($context);
1461: %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
1462: \@statuses,\@possroles);
1463: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1464: \%cstr_roles,$permission);
1465: } elsif ($context eq 'domain') {
1466: if ($env{'form.roletype'} eq 'domain') {
1467: %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'});
1468: foreach my $key (keys(%dom_roles)) {
1469: if (ref($dom_roles{$key}) eq 'HASH') {
1470: &gather_userinfo($context,$format,\%userlist,$indexhash,
1471: \%userinfo,$dom_roles{$key},$permission);
1472: }
1473: }
1474: } elsif ($env{'form.roletype'} eq 'author') {
1475: my %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'},['au']);
1476: my %coauthors;
1477: foreach my $key (keys(%dom_roles)) {
1478: if (ref($dom_roles{$key}) eq 'HASH') {
1479: if ($env{'form.showrole'} eq 'au') {
1480: &gather_userinfo($context,$format,\%userlist,$indexhash,
1481: \%userinfo,$dom_roles{$key},$permission);
1482: } else {
1483: my @possroles;
1484: if ($env{'form.showrole'} eq 'Any') {
1485: @possroles = &roles_by_context('author');
1486: } else {
1487: @possroles = ($env{'form.showrole'});
1488: }
1489: foreach my $author (sort(keys(%{$dom_roles{$key}}))) {
1490: my ($role,$authorname,$authordom) = split(/:/,$author,-1);
1491: my $extent = '/'.$authordom.'/'.$authorname;
1492: %{$coauthors{$extent}} =
1493: &Apache::lonnet::get_my_roles($authorname,
1494: $authordom,undef,\@statuses,\@possroles);
1495: }
1496: &gather_userinfo($context,$format,\%userlist,
1497: $indexhash,\%userinfo,\%coauthors,$permission);
1498: }
1499: }
1500: }
1501: } elsif ($env{'form.roletype'} eq 'course') {
1502: if ($env{'form.coursepick'}) {
1503: my %courses = &process_coursepick();
1504: my %allusers;
1505: my $hidepriv = 1;
1506: foreach my $cid (keys(%courses)) {
1507: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
1508: next if ($cnum eq '' || $cdom eq '');
1509: my $custom = 1;
1510: my (@roles,@sections,%access,%users,%userdata,
1511: %statushash);
1512: if ($env{'form.showrole'} eq 'Any') {
1513: @roles = &course_roles($context,undef,$custom);
1514: } else {
1515: @roles = ($env{'form.showrole'});
1516: }
1517: foreach my $role (@roles) {
1518: %{$users{$role}} = ();
1519: }
1520: foreach my $type (@statuses) {
1521: $access{$type} = $type;
1522: }
1523: &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\@sections,\%users,\%userdata,\%statushash,$hidepriv);
1524: foreach my $user (keys(%userdata)) {
1525: next if (ref($userinfo{$user}) eq 'HASH');
1526: foreach my $item ('fullname','id') {
1527: $userinfo{$user}{$item} = $userdata{$user}[$indexhash->{$item}];
1528: }
1529: }
1530: foreach my $role (keys(%users)) {
1531: foreach my $user (keys(%{$users{$role}})) {
1532: my $uniqid = $user.':'.$role;
1533: $allusers{$uniqid}{$cid} = { desc => $cdesc,
1534: secs => $statushash{$user}{$role},
1535: };
1536: }
1537: }
1538: }
1539: &gather_userinfo($context,$format,\%userlist,$indexhash,
1540: \%userinfo,\%allusers,$permission);
1541: } else {
1542: $r->print('<input type="hidden" name="phase" value="'.
1543: $env{'form.phase'}.'" /></form>');
1544: return;
1545: }
1546: }
1547: }
1548: }
1549: if (keys(%userlist) == 0) {
1550: if ($context eq 'author') {
1551: $r->print(&mt('There are no co-authors to display.')."\n");
1552: } elsif ($context eq 'domain') {
1553: if ($env{'form.roletype'} eq 'domain') {
1554: $r->print(&mt('There are no users with domain roles to display.')."\n");
1555: } elsif ($env{'form.roletype'} eq 'author') {
1556: $r->print(&mt('There are no authors or co-authors to display.')."\n");
1557: } elsif ($env{'form.roletype'} eq 'course') {
1558: $r->print(&mt('There are no course users to display')."\n");
1559: }
1560: } elsif ($context eq 'course') {
1561: $r->print(&mt('There are no course users to display.')."\n");
1562: }
1563: } else {
1564: # Print out the available choices
1565: my $usercount;
1566: if ($env{'form.action'} eq 'modifystudent') {
1567: ($usercount) = &show_users_list($r,$context,'view',$permission,
1568: $env{'form.Status'},\%userlist,$keylist);
1569: } else {
1570: ($usercount) = &show_users_list($r,$context,$env{'form.output'},
1571: $permission,$env{'form.Status'},\%userlist,$keylist);
1572: }
1573: if (!$usercount) {
1574: $r->print('<br /><span class="LC_warning">'
1575: .&mt('There are no users matching the search criteria.')
1576: .'</span>'
1577: );
1578: }
1579: }
1580: $r->print('<input type="hidden" name="phase" value="'.
1581: $env{'form.phase'}.'" /></form>');
1582: }
1583:
1584: sub role_filter {
1585: my ($context) = @_;
1586: my $output;
1587: my $roleselected = '';
1588: if ($env{'form.showrole'} eq 'Any') {
1589: $roleselected = ' selected="selected"';
1590: }
1591: my ($role_select);
1592: if ($context eq 'domain') {
1593: $role_select = &domain_roles_select();
1594: $output = '<label><span class="LC_nobreak">'
1595: .&mt('Role Type: [_1]',$role_select)
1596: .'</span></label>';
1597: } else {
1598: $role_select = '<select name="showrole">'."\n".
1599: '<option value="Any" '.$roleselected.'>'.
1600: &mt('Any role').'</option>';
1601: my @poss_roles = &curr_role_permissions($context);
1602: foreach my $role (@poss_roles) {
1603: $roleselected = '';
1604: if ($role eq $env{'form.showrole'}) {
1605: $roleselected = ' selected="selected"';
1606: }
1607: my $plrole;
1608: if ($role eq 'cr') {
1609: $plrole = &mt('Custom role');
1610: } else {
1611: $plrole=&Apache::lonnet::plaintext($role);
1612: }
1613: $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>';
1614: }
1615: $role_select .= '</select>';
1616: $output = '<label><span class="LC_nobreak">'
1617: .&mt('Role: [_1]',$role_select)
1618: .'</span></label>';
1619: }
1620: return $output;
1621: }
1622:
1623: sub section_group_filter {
1624: my ($cnum,$cdom) = @_;
1625: my @filters;
1626: if ($env{'request.course.sec'} eq '') {
1627: @filters = ('sec');
1628: }
1629: push(@filters,'grp');
1630: my %name = (
1631: sec => 'secfilter',
1632: grp => 'grpfilter',
1633: );
1634: my %title = &Apache::lonlocal::texthash (
1635: sec => 'Section(s)',
1636: grp => 'Group(s)',
1637: all => 'all',
1638: none => 'none',
1639: );
1640: my $output;
1641: foreach my $item (@filters) {
1642: my ($markup,@options);
1643: if ($env{'form.'.$name{$item}} eq '') {
1644: $env{'form.'.$name{$item}} = 'all';
1645: }
1646: if ($item eq 'sec') {
1647: if ($env{'form.showrole'} eq 'cc') {
1648: $env{'form.'.$name{$item}} = 'none';
1649: }
1650: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
1651: @options = sort(keys(%sections_count));
1652: } elsif ($item eq 'grp') {
1653: my %curr_groups = &Apache::longroup::coursegroups();
1654: @options = sort(keys(%curr_groups));
1655: }
1656: if (@options > 0) {
1657: my $currsel;
1658: $markup = '<select name="'.$name{$item}.'" />'."\n";
1659: foreach my $option ('all','none',@options) {
1660: $currsel = '';
1661: if ($env{'form.'.$name{$item}} eq $option) {
1662: $currsel = ' selected="selected" ';
1663: }
1664: $markup .= ' <option value="'.$option.'"'.$currsel.'>';
1665: if (($option eq 'all') || ($option eq 'none')) {
1666: $markup .= $title{$option};
1667: } else {
1668: $markup .= $option;
1669: }
1670: $markup .= '</option>'."\n";
1671: }
1672: $markup .= '</select>'."\n";
1673: $output .= (' 'x3).'<label>'.$title{$item}.': '.$markup.'</label>';
1674: }
1675: }
1676: return $output;
1677: }
1678:
1679: sub list_submit_button {
1680: my ($text) = @_;
1681: return '<input type="button" name="updatedisplay" value="'.$text.'" onclick="javascript:display_update()" />';
1682: }
1683:
1684: sub gather_userinfo {
1685: my ($context,$format,$userlist,$indexhash,$userinfo,$rolehash,$permission) = @_;
1686: my $viewablesec;
1687: if ($context eq 'course') {
1688: $viewablesec = &viewable_section($permission);
1689: }
1690: foreach my $item (keys(%{$rolehash})) {
1691: my %userdata;
1692: if ($context eq 'author') {
1693: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
1694: split(/:/,$item);
1695: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
1696: &build_user_record($context,\%userdata,$userinfo,$indexhash,
1697: $item,$userlist);
1698: } elsif ($context eq 'course') {
1699: ($userdata{'username'},$userdata{'domain'},$userdata{'role'},
1700: $userdata{'section'}) = split(/:/,$item,-1);
1701: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
1702: if (($viewablesec ne '') && ($userdata{'section'} ne '')) {
1703: next if ($viewablesec ne $userdata{'section'});
1704: }
1705: &build_user_record($context,\%userdata,$userinfo,$indexhash,
1706: $item,$userlist);
1707: } elsif ($context eq 'domain') {
1708: if ($env{'form.roletype'} eq 'domain') {
1709: ($userdata{'role'},$userdata{'username'},$userdata{'domain'}) =
1710: split(/:/,$item);
1711: ($userdata{'end'},$userdata{'start'})=split(/:/,$rolehash->{$item});
1712: &build_user_record($context,\%userdata,$userinfo,$indexhash,
1713: $item,$userlist);
1714: } elsif ($env{'form.roletype'} eq 'author') {
1715: if (ref($rolehash->{$item}) eq 'HASH') {
1716: $userdata{'extent'} = $item;
1717: foreach my $key (keys(%{$rolehash->{$item}})) {
1718: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) = split(/:/,$key);
1719: ($userdata{'start'},$userdata{'end'}) =
1720: split(/:/,$rolehash->{$item}{$key});
1721: my $uniqid = $key.':'.$item;
1722: &build_user_record($context,\%userdata,$userinfo,
1723: $indexhash,$uniqid,$userlist);
1724: }
1725: }
1726: } elsif ($env{'form.roletype'} eq 'course') {
1727: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
1728: split(/:/,$item);
1729: if (ref($rolehash->{$item}) eq 'HASH') {
1730: my $numcids = keys(%{$rolehash->{$item}});
1731: foreach my $cid (sort(keys(%{$rolehash->{$item}}))) {
1732: if (ref($rolehash->{$item}{$cid}) eq 'HASH') {
1733: my $spanstart = '';
1734: my $spanend = '; ';
1735: my $space = ', ';
1736: if ($format eq 'html' || $format eq 'view') {
1737: $spanstart = '<span class="LC_nobreak">';
1738: # FIXME: actions on courses disabled for now
1739: # if ($permission->{'cusr'}) {
1740: # if ($numcids > 1) {
1741: # $spanstart .= '<input type="radio" name="'.$item.'" value="'.$cid.'" /> ';
1742: # } else {
1743: # $spanstart .= '<input type="hidden" name="'.$item.'" value="'.$cid.'" /> ';
1744: # }
1745: # }
1746: $spanend = '</span><br />';
1747: $space = ', ';
1748: }
1749: $userdata{'extent'} .= $spanstart.
1750: $rolehash->{$item}{$cid}{'desc'}.$space;
1751: if (ref($rolehash->{$item}{$cid}{'secs'}) eq 'HASH') {
1752: foreach my $sec (sort(keys(%{$rolehash->{$item}{$cid}{'secs'}}))) {
1753: if (($env{'form.Status'} eq 'Any') ||
1754: ($env{'form.Status'} eq $rolehash->{$item}{$cid}{'secs'}{$sec})) {
1755: $userdata{'extent'} .= $sec.$space.$rolehash->{$item}{$cid}{'secs'}{$sec}.$spanend;
1756: $userdata{'status'} = $rolehash->{$item}{$cid}{'secs'}{$sec};
1757: }
1758: }
1759: }
1760: }
1761: }
1762: }
1763: if ($userdata{'status'} ne '') {
1764: &build_user_record($context,\%userdata,$userinfo,
1765: $indexhash,$item,$userlist);
1766: }
1767: }
1768: }
1769: }
1770: return;
1771: }
1772:
1773: sub build_user_record {
1774: my ($context,$userdata,$userinfo,$indexhash,$record_key,$userlist) = @_;
1775: next if ($userdata->{'start'} eq '-1' && $userdata->{'end'} eq '-1');
1776: if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
1777: &process_date_info($userdata);
1778: }
1779: my $username = $userdata->{'username'};
1780: my $domain = $userdata->{'domain'};
1781: if (ref($userinfo->{$username.':'.$domain}) eq 'HASH') {
1782: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
1783: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
1784: } else {
1785: &aggregate_user_info($domain,$username,$userinfo);
1786: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
1787: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
1788: }
1789: foreach my $key (keys(%{$indexhash})) {
1790: if (defined($userdata->{$key})) {
1791: $userlist->{$record_key}[$indexhash->{$key}] = $userdata->{$key};
1792: }
1793: }
1794: return;
1795: }
1796:
1797: sub courses_selector {
1798: my ($cdom,$formname) = @_;
1799: my %coursecodes = ();
1800: my %codes = ();
1801: my @codetitles = ();
1802: my %cat_titles = ();
1803: my %cat_order = ();
1804: my %idlist = ();
1805: my %idnums = ();
1806: my %idlist_titles = ();
1807: my $caller = 'global';
1808: my $format_reply;
1809: my $jscript = '';
1810:
1811: my $totcodes = 0;
1812: $totcodes =
1813: &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,
1814: $cdom,$totcodes);
1815: if ($totcodes > 0) {
1816: $format_reply =
1817: &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,
1818: \%codes,\@codetitles,\%cat_titles,\%cat_order);
1819: if ($format_reply eq 'ok') {
1820: my $numtypes = @codetitles;
1821: &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
1822: my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
1823: my $longtitles_str = join('","',@{$longtitles});
1824: my $allidlist = $idlist{$codetitles[0]};
1825: $jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist);
1826: $jscript .= $scripttext;
1827: $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,@codetitles);
1828: }
1829: }
1830: my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom);
1831:
1832: my %elements = (
1833: Year => 'selectbox',
1834: coursepick => 'radio',
1835: coursetotal => 'text',
1836: courselist => 'text',
1837: );
1838: $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements);
1839: if ($env{'form.coursepick'} eq 'category') {
1840: $jscript .= qq|
1841: function setCourseCat(formname) {
1842: if (formname.Year.options[formname.Year.selectedIndex].value == -1) {
1843: return;
1844: }
1845: courseSet('Year');
1846: for (var j=0; j<formname.Semester.length; j++) {
1847: if (formname.Semester.options[j].value == "$env{'form.Semester'}") {
1848: formname.Semester.options[j].selected = true;
1849: }
1850: }
1851: if (formname.Semester.options[formname.Semester.selectedIndex].value == -1) {
1852: return;
1853: }
1854: courseSet('Semester');
1855: for (var j=0; j<formname.Department.length; j++) {
1856: if (formname.Department.options[j].value == "$env{'form.Department'}") { formname.Department.options[j].selected = true;
1857: }
1858: }
1859: if (formname.Department.options[formname.Department.selectedIndex].value == -1) {
1860: return;
1861: }
1862: courseSet('Department');
1863: for (var j=0; j<formname.Number.length; j++) {
1864: if (formname.Number.options[j].value == "$env{'form.Number'}") {
1865: formname.Number.options[j].selected = true;
1866: }
1867: }
1868: }
1869: |;
1870: }
1871: return ($cb_jscript,$jscript,$totcodes,\@codetitles,\%idlist,
1872: \%idlist_titles);
1873: }
1874:
1875: sub course_selector_loadcode {
1876: my ($formname) = @_;
1877: my $loadcode;
1878: if ($env{'form.coursepick'} ne '') {
1879: $loadcode = 'javascript:setFormElements(document.'.$formname.')';
1880: if ($env{'form.coursepick'} eq 'category') {
1881: $loadcode .= ';javascript:setCourseCat(document.'.$formname.')';
1882: }
1883: }
1884: return $loadcode;
1885: }
1886:
1887: sub process_coursepick {
1888: my $coursefilter = $env{'form.coursepick'};
1889: my $cdom = $env{'request.role.domain'};
1890: my %courses;
1891: if ($coursefilter eq 'all') {
1892: %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.',
1893: undef,undef,'Course');
1894: } elsif ($coursefilter eq 'category') {
1895: my $instcode = &instcode_from_coursefilter();
1896: %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.',
1897: undef,undef,'Course');
1898: } elsif ($coursefilter eq 'specific') {
1899: if ($env{'form.coursetotal'} > 1) {
1900: my @course_ids = split(/&&/,$env{'form.courselist'});
1901: foreach my $cid (@course_ids) {
1902: $courses{$cid} = '';
1903: }
1904: } else {
1905: $courses{$env{'form.courselist'}} = '';
1906: }
1907: }
1908: return %courses;
1909: }
1910:
1911: sub instcode_from_coursefilter {
1912: my $instcode = '';
1913: my @cats = ('Semester','Year','Department','Number');
1914: foreach my $category (@cats) {
1915: if (defined($env{'form.'.$category})) {
1916: unless ($env{'form.'.$category} eq '-1') {
1917: $instcode .= $env{'form.'.$category};
1918: }
1919: }
1920: }
1921: if ($instcode eq '') {
1922: $instcode = '.';
1923: }
1924: return $instcode;
1925: }
1926:
1927: sub display_adv_courseroles {
1928: my $output;
1929: #
1930: # List course personnel
1931: my %coursepersonnel =
1932: &Apache::lonnet::get_course_adv_roles($env{'request.course.id'});
1933: #
1934: $output = '<br />'.&Apache::loncommon::start_data_table();
1935: foreach my $role (sort(keys(%coursepersonnel))) {
1936: next if ($role =~ /^\s*$/);
1937: $output .= &Apache::loncommon::start_data_table_row().
1938: '<td>'.$role.'</td><td>';
1939: foreach my $user (split(',',$coursepersonnel{$role})) {
1940: my ($puname,$pudom)=split(':',$user);
1941: $output .= ' '.&Apache::loncommon::aboutmewrapper(
1942: &Apache::loncommon::plainname($puname,$pudom),
1943: $puname,$pudom);
1944: }
1945: $output .= '</td>'.&Apache::loncommon::end_data_table_row();
1946: }
1947: $output .= &Apache::loncommon::end_data_table();
1948: }
1949:
1950: sub make_keylist_array {
1951: my ($index,$keylist);
1952: $index->{'domain'} = &Apache::loncoursedata::CL_SDOM();
1953: $index->{'username'} = &Apache::loncoursedata::CL_SNAME();
1954: $index->{'end'} = &Apache::loncoursedata::CL_END();
1955: $index->{'start'} = &Apache::loncoursedata::CL_START();
1956: $index->{'id'} = &Apache::loncoursedata::CL_ID();
1957: $index->{'section'} = &Apache::loncoursedata::CL_SECTION();
1958: $index->{'fullname'} = &Apache::loncoursedata::CL_FULLNAME();
1959: $index->{'status'} = &Apache::loncoursedata::CL_STATUS();
1960: $index->{'type'} = &Apache::loncoursedata::CL_TYPE();
1961: $index->{'lockedtype'} = &Apache::loncoursedata::CL_LOCKEDTYPE();
1962: $index->{'groups'} = &Apache::loncoursedata::CL_GROUP();
1963: $index->{'email'} = &Apache::loncoursedata::CL_PERMANENTEMAIL();
1964: $index->{'role'} = &Apache::loncoursedata::CL_ROLE();
1965: $index->{'extent'} = &Apache::loncoursedata::CL_EXTENT();
1966: $index->{'photo'} = &Apache::loncoursedata::CL_PHOTO();
1967: $index->{'thumbnail'} = &Apache::loncoursedata::CL_THUMBNAIL();
1968: foreach my $key (keys(%{$index})) {
1969: $keylist->[$index->{$key}] = $key;
1970: }
1971: return ($index,$keylist);
1972: }
1973:
1974: sub aggregate_user_info {
1975: my ($udom,$uname,$userinfo) = @_;
1976: my %info=&Apache::lonnet::get('environment',
1977: ['firstname','middlename',
1978: 'lastname','generation','id'],
1979: $udom,$uname);
1980: my ($tmp) = keys(%info);
1981: my ($fullname,$id);
1982: if ($tmp =~/^(con_lost|error|no_such_host)/i) {
1983: $fullname = 'not available';
1984: $id = 'not available';
1985: &Apache::lonnet::logthis('unable to retrieve environment '.
1986: 'for '.$uname.':'.$udom);
1987: } else {
1988: $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
1989: $id = $info{'id'};
1990: }
1991: $userinfo->{$uname.':'.$udom} = {
1992: fullname => $fullname,
1993: id => $id,
1994: };
1995: return;
1996: }
1997:
1998: sub process_date_info {
1999: my ($userdata) = @_;
2000: my $now = time;
2001: $userdata->{'status'} = 'Active';
2002: if ($userdata->{'start'} > 0) {
2003: if ($now < $userdata->{'start'}) {
2004: $userdata->{'status'} = 'Future';
2005: }
2006: }
2007: if ($userdata->{'end'} > 0) {
2008: if ($now > $userdata->{'end'}) {
2009: $userdata->{'status'} = 'Expired';
2010: }
2011: }
2012: return;
2013: }
2014:
2015: sub show_users_list {
2016: my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist,$formname)=@_;
2017: if ($formname eq '') {
2018: $formname = 'studentform';
2019: }
2020: #
2021: # Variables for excel output
2022: my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
2023: #
2024: # Variables for csv output
2025: my ($CSVfile,$CSVfilename);
2026: #
2027: my $sortby = $env{'form.sortby'};
2028: my @sortable = ('username','domain','id','fullname','start','end','email','role');
2029: if ($context eq 'course') {
2030: push(@sortable,('section','groups','type'));
2031: } else {
2032: push(@sortable,'extent');
2033: }
2034: if ($mode eq 'pickauthor') {
2035: @sortable = ('username','fullname','email','status');
2036: }
2037: if (!grep(/^\Q$sortby\E$/,@sortable)) {
2038: $sortby = 'username';
2039: }
2040: my $setting = $env{'form.roletype'};
2041: my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers);
2042: if ($context eq 'course') {
2043: $cid = $env{'request.course.id'};
2044: ($cnum,$cdom) = &get_course_identity($cid);
2045: ($classgroups) = &Apache::loncoursedata::get_group_memberships(
2046: $userlist,$keylist,$cdom,$cnum);
2047: if ($mode eq 'autoenroll') {
2048: $env{'form.showrole'} = 'st';
2049: } else {
2050: if (! exists($env{'form.displayphotos'})) {
2051: $env{'form.displayphotos'} = 'off';
2052: }
2053: $displayphotos = $env{'form.displayphotos'};
2054: if (! exists($env{'form.displayclickers'})) {
2055: $env{'form.displayclickers'} = 'off';
2056: }
2057: $displayclickers = $env{'form.displayclickers'};
2058: if ($env{'course.'.$cid.'.internal.showphoto'}) {
2059: $r->print('
2060: <script type="text/javascript">
2061: function photowindow(photolink) {
2062: var title = "Photo_Viewer";
2063: var options = "scrollbars=1,resizable=1,menubar=0";
2064: options += ",width=240,height=240";
2065: stdeditbrowser = open(photolink,title,options,"1");
2066: stdeditbrowser.focus();
2067: }
2068: </script>
2069: ');
2070: }
2071: $r->print(<<END);
2072: <input type="hidden" name="displayphotos" value="$displayphotos" />
2073: <input type="hidden" name="displayclickers" value="$displayclickers" />
2074: END
2075: }
2076: }
2077: if ($mode ne 'autoenroll' && $mode ne 'pickauthor') {
2078: my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
2079: my $date_sec_selector = &date_section_javascript($context,$setting,$statusmode);
2080: my $verify_action_js = &bulkaction_javascript($formname);
2081: $r->print(<<END);
2082:
2083: <script type="text/javascript" language="Javascript">
2084: $check_uncheck_js
2085:
2086: $verify_action_js
2087:
2088: function username_display_launch(username,domain) {
2089: var target;
2090: for (var i=0; i<document.$formname.usernamelink.length; i++) {
2091: if (document.$formname.usernamelink[i].checked) {
2092: target = document.$formname.usernamelink[i].value;
2093: }
2094: }
2095: if (target == 'modify') {
2096: if (document.$formname.userwin.checked == true) {
2097: var url = '/adm/createuser?srchterm='+username+'&srchdomain='+domain+'&phase=get_user_info&action=singleuser&srchin=dom&srchby=uname&srchtype=exact&popup=1';
2098: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
2099: modifywin = window.open(url,'',options,1);
2100: modifywin.focus();
2101: return;
2102: } else {
2103: document.$formname.srchterm.value=username;
2104: document.$formname.srchdomain.value=domain;
2105: document.$formname.phase.value='get_user_info';
2106: document.$formname.action.value = 'singleuser';
2107: document.$formname.submit();
2108: }
2109: }
2110: if (target == 'aboutme') {
2111: if (document.$formname.userwin.checked == true) {
2112: var url = '/adm/'+domain+'/'+username+'/aboutme?popup=1';
2113: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
2114: aboutmewin = window.open(url,'',options,1);
2115: aboutmewin.focus();
2116: return;
2117: } else {
2118: document.location.href = '/adm/'+domain+'/'+username+'/aboutme';
2119: }
2120: }
2121: }
2122: </script>
2123: $date_sec_selector
2124: <input type="hidden" name="state" value="$env{'form.state'}" />
2125: END
2126: }
2127: $r->print(<<END);
2128: <input type="hidden" name="sortby" value="$sortby" />
2129: END
2130:
2131: my %lt=&Apache::lonlocal::texthash(
2132: 'username' => "username",
2133: 'domain' => "domain",
2134: 'id' => 'ID',
2135: 'fullname' => "name",
2136: 'section' => "section",
2137: 'groups' => "active groups",
2138: 'start' => "start date",
2139: 'end' => "end date",
2140: 'status' => "status",
2141: 'role' => "role",
2142: 'type' => "enroll type/action",
2143: 'email' => "e-mail address",
2144: 'photo' => "photo",
2145: 'extent' => "extent",
2146: 'pr' => "Proceed",
2147: 'ca' => "check all",
2148: 'ua' => "uncheck all",
2149: 'ac' => "Action to take for selected users",
2150: 'link' => "Behavior of clickable username link for each user",
2151: 'aboutme' => "Display a user's personal information page",
2152: 'owin' => "Open in a new window",
2153: 'modify' => "Modify a user's information",
2154: 'clicker' => "Clicker-ID",
2155: );
2156: if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
2157: $lt{'extent'} = &mt('Course(s): description, section(s), status');
2158: } elsif ($context eq 'author') {
2159: $lt{'extent'} = &mt('Author');
2160: }
2161: my @cols;
2162: if ($mode eq 'pickauthor') {
2163: @cols = ('username','fullname','status','email');
2164: } else {
2165: @cols = ('username','domain','id','fullname');
2166: if ($context eq 'course') {
2167: push(@cols,'section');
2168: }
2169: if (!($context eq 'domain' && $env{'form.roletype'} eq 'course')) {
2170: push(@cols,('start','end'));
2171: }
2172: if ($env{'form.showrole'} eq 'Any' || $env{'form.showrole'} eq 'cr') {
2173: push(@cols,'role');
2174: }
2175: if ($context eq 'domain' && ($env{'form.roletype'} eq 'author' ||
2176: $env{'form.roletype'} eq 'course')) {
2177: push (@cols,'extent');
2178: }
2179: if (($statusmode eq 'Any') &&
2180: (!($context eq 'domain' && $env{'form.roletype'} eq 'course'))) {
2181: push(@cols,'status');
2182: }
2183: if ($context eq 'course') {
2184: push(@cols,'groups');
2185: }
2186: push(@cols,'email');
2187: }
2188:
2189: my $rolefilter = $env{'form.showrole'};
2190: if ($env{'form.showrole'} eq 'cr') {
2191: $rolefilter = &mt('custom');
2192: } elsif ($env{'form.showrole'} ne 'Any') {
2193: $rolefilter = &Apache::lonnet::plaintext($env{'form.showrole'});
2194: }
2195: my $results_description;
2196: if ($mode ne 'autoenroll') {
2197: $results_description = &results_header_row($rolefilter,$statusmode,
2198: $context,$permission,$mode);
2199: $r->print('<b>'.$results_description.'</b><br /><br />');
2200: }
2201: my ($output,$actionselect,%canchange,%canchangesec);
2202: if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
2203: if ($mode ne 'autoenroll' && $mode ne 'pickauthor') {
2204: if ($permission->{'cusr'}) {
2205: $actionselect = &select_actions($context,$setting,$statusmode,$formname);
2206: }
2207: $r->print(<<END);
2208: <input type="hidden" name="srchby" value="uname" />
2209: <input type="hidden" name="srchin" value="dom" />
2210: <input type="hidden" name="srchtype" value="exact" />
2211: <input type="hidden" name="srchterm" value="" />
2212: <input type="hidden" name="srchdomain" value="" />
2213: END
2214: if ($actionselect) {
2215: $output .= <<"END";
2216: <div class="LC_left_float"><fieldset><legend>$lt{'ac'}</legend>
2217: $actionselect
2218: <br/><br /><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.$formname.actionlist)" />
2219: <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>
2220: END
2221: my @allroles;
2222: if ($env{'form.showrole'} eq 'Any') {
2223: my $custom = 1;
2224: if ($context eq 'domain') {
2225: @allroles = &roles_by_context($setting,$custom);
2226: } else {
2227: @allroles = &roles_by_context($context,$custom);
2228: }
2229: } else {
2230: @allroles = ($env{'form.showrole'});
2231: }
2232: foreach my $role (@allroles) {
2233: if ($context eq 'domain') {
2234: if ($setting eq 'domain') {
2235: if (&Apache::lonnet::allowed('c'.$role,
2236: $env{'request.role.domain'})) {
2237: $canchange{$role} = 1;
2238: }
2239: } elsif ($setting eq 'author') {
2240: if (&Apache::lonnet::allowed('c'.$role,
2241: $env{'request.role.domain'})) {
2242: $canchange{$role} = 1;
2243: }
2244: }
2245: } elsif ($context eq 'author') {
2246: if (&Apache::lonnet::allowed('c'.$role,
2247: $env{'user.domain'}.'/'.$env{'user.name'})) {
2248: $canchange{$role} = 1;
2249: }
2250: } elsif ($context eq 'course') {
2251: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
2252: $canchange{$role} = 1;
2253: } elsif ($env{'request.course.sec'} ne '') {
2254: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
2255: $canchangesec{$role} = $env{'request.course.sec'};
2256: }
2257: }
2258: }
2259: }
2260: }
2261: $output .= '<div class="LC_left_float"><fieldset><legend>'.$lt{'link'}.'</legend>'.
2262: '<table><tr>';
2263: my @linkdests = ('aboutme');
2264: if ($permission->{'cusr'}) {
2265: unshift (@linkdests,'modify');
2266: }
2267: $output .= '<td>';
2268: my $usernamelink = $env{'form.usernamelink'};
2269: if ($usernamelink eq '') {
2270: $usernamelink = 'aboutme';
2271: }
2272: foreach my $item (@linkdests) {
2273: my $checkedstr = '';
2274: if ($item eq $usernamelink) {
2275: $checkedstr = ' checked="checked"';
2276: }
2277: $output .= '<span class="LC_nobreak"><label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.' /> '.$lt{$item}.'</label></span><br />';
2278: }
2279: my $checkwin;
2280: if ($env{'form.userwin'}) {
2281: $checkwin = ' checked="checked"';
2282: }
2283: $output .= '</td><td valign="top"><span class="LC_nobreak"><input type="checkbox" name="userwin" value="1"'.$checkwin.' />'.$lt{'owin'}.'</span></td></tr></table></fieldset></div>';
2284: }
2285: $output .= "\n".'<div class="LC_clear_float_footer"> </div>'."\n".
2286: &Apache::loncommon::start_data_table().
2287: &Apache::loncommon::start_data_table_header_row();
2288: if ($mode eq 'autoenroll') {
2289: $output .= "
2290: <th><a href=\"javascript:document.$formname.sortby.value='type';document.$formname.submit();\">$lt{'type'}</a></th>
2291: ";
2292: } else {
2293: if ($mode eq 'pickauthor') {
2294: $output .= "\n".'<th> </th>'."\n";
2295: } else {
2296: $output .= "\n".'<th>'.&mt('Count').'</th>'."\n";
2297: }
2298: if ($actionselect) {
2299: $output .= '<th>'.&mt('Select').'</th>'."\n";
2300: }
2301: }
2302: foreach my $item (@cols) {
2303: $output .= "<th><a href=\"javascript:document.$formname.sortby.value='$item';document.$formname.submit();\">$lt{$item}</a></th>\n";
2304: }
2305: my %role_types = &role_type_names();
2306: if ($context eq 'course' && $mode ne 'autoenroll') {
2307: if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
2308: # Clicker display on or off?
2309: my %clicker_options = (
2310: 'on' => 'Show',
2311: 'off' => 'Hide',
2312: );
2313: my $clickerchg = 'on';
2314: if ($displayclickers eq 'on') {
2315: $clickerchg = 'off';
2316: }
2317: $output .= ' <th>'."\n".' '
2318: .&mt('[_1]'.$clicker_options{$clickerchg}.'[_2] clicker id'
2319: ,'<a href="javascript:document.'.$formname.'.displayclickers.value='
2320: ."'".$clickerchg."'".';document.'.$formname.'.submit();">'
2321: ,'</a>')
2322: ."\n".' </th>'."\n";
2323:
2324: # Photo display on or off?
2325: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
2326: my %photo_options = &Apache::lonlocal::texthash(
2327: 'on' => 'Show',
2328: 'off' => 'Hide',
2329: );
2330: my $photochg = 'on';
2331: if ($displayphotos eq 'on') {
2332: $photochg = 'off';
2333: }
2334: $output .= ' <th>'."\n".' '.
2335: '<a href="javascript:document.'.$formname.'.displayphotos.value='.
2336: "'".$photochg."'".';document.'.$formname.'.submit();">'.
2337: $photo_options{$photochg}.'</a> '.$lt{'photo'}."\n".
2338: ' </th>'."\n";
2339: }
2340: }
2341: }
2342: $output .= &Apache::loncommon::end_data_table_header_row();
2343: # Done with the HTML header line
2344: } elsif ($mode eq 'csv') {
2345: #
2346: # Open a file
2347: $CSVfilename = '/prtspool/'.
2348: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
2349: time.'_'.rand(1000000000).'.csv';
2350: unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
2351: $r->log_error("Couldn't open $CSVfilename for output $!");
2352: $r->print(&mt('Problems occurred in writing the CSV file. '
2353: .'This error has been logged. '
2354: .'Please alert your LON-CAPA administrator.'));
2355: $CSVfile = undef;
2356: }
2357: #
2358: push @cols,'clicker';
2359: # Write headers and data to file
2360: print $CSVfile '"'.$results_description.'"'."\n";
2361: print $CSVfile '"'.join('","',map {
2362: &Apache::loncommon::csv_translate($lt{$_})
2363: } (@cols))."\"\n";
2364: } elsif ($mode eq 'excel') {
2365: push @cols,'clicker';
2366: # Create the excel spreadsheet
2367: ($excel_workbook,$excel_filename,$format) =
2368: &Apache::loncommon::create_workbook($r);
2369: return if (! defined($excel_workbook));
2370: $excel_sheet = $excel_workbook->addworksheet('userlist');
2371: $excel_sheet->write($row++,0,$results_description,$format->{'h2'});
2372: #
2373: my @colnames = map {$lt{$_}} (@cols);
2374:
2375: $excel_sheet->write($row++,0,\@colnames,$format->{'bold'});
2376: }
2377:
2378: # Done with header lines in all formats
2379: my %index;
2380: my $i;
2381: foreach my $idx (@$keylist) {
2382: $index{$idx} = $i++;
2383: }
2384: my $usercount = 0;
2385: my ($secfilter,$grpfilter);
2386: if ($context eq 'course') {
2387: $secfilter = $env{'form.secfilter'};
2388: $grpfilter = $env{'form.grpfilter'};
2389: if ($secfilter eq '') {
2390: $secfilter = 'all';
2391: }
2392: if ($grpfilter eq '') {
2393: $grpfilter = 'all';
2394: }
2395: }
2396: my %ltstatus = &Apache::lonlocal::texthash(
2397: Active => 'Active',
2398: Future => 'Future',
2399: Expired => 'Expired',
2400: );
2401: # Get groups, role, permanent e-mail so we can sort on them if
2402: # necessary.
2403: foreach my $user (keys(%{$userlist})) {
2404: if ($user eq '' ) {
2405: delete($userlist->{$user});
2406: next;
2407: }
2408: if ($context eq 'domain' && $user eq $env{'request.role.domain'}.'-domainconfig:'.$env{'request.role.domain'}) {
2409: delete($userlist->{$user});
2410: next;
2411: }
2412: my ($uname,$udom,$role,$groups,$email);
2413: if (($statusmode ne 'Any') &&
2414: ($userlist->{$user}->[$index{'status'}] ne $statusmode)) {
2415: delete($userlist->{$user});
2416: next;
2417: }
2418: if ($context eq 'domain') {
2419: if ($env{'form.roletype'} eq 'domain') {
2420: ($role,$uname,$udom) = split(/:/,$user);
2421: if (($uname eq $env{'request.role.domain'}.'-domainconfig') &&
2422: ($udom eq $env{'request.role.domain'})) {
2423: delete($userlist->{$user});
2424: next;
2425: }
2426: } elsif ($env{'form.roletype'} eq 'author') {
2427: ($uname,$udom,$role) = split(/:/,$user,-1);
2428: } elsif ($env{'form.roletype'} eq 'course') {
2429: ($uname,$udom,$role) = split(/:/,$user);
2430: }
2431: } else {
2432: ($uname,$udom,$role) = split(/:/,$user,-1);
2433: if (($context eq 'course') && $role eq '') {
2434: $role = 'st';
2435: }
2436: }
2437: $userlist->{$user}->[$index{'role'}] = $role;
2438: if (($env{'form.showrole'} ne 'Any') && (!($env{'form.showrole'} eq 'cr' && $role =~ /^cr\//)) && ($role ne $env{'form.showrole'})) {
2439: delete($userlist->{$user});
2440: next;
2441: }
2442: if ($context eq 'course') {
2443: my @ac_groups;
2444: if (ref($classgroups) eq 'HASH') {
2445: $groups = $classgroups->{$user};
2446: }
2447: if (ref($groups->{'active'}) eq 'HASH') {
2448: @ac_groups = keys(%{$groups->{'active'}});
2449: $userlist->{$user}->[$index{'groups'}] = join(', ',@ac_groups);
2450: }
2451: if ($mode ne 'autoenroll') {
2452: my $section = $userlist->{$user}->[$index{'section'}];
2453: if (($env{'request.course.sec'} ne '') &&
2454: ($section ne $env{'request.course.sec'})) {
2455: if ($role eq 'st') {
2456: delete($userlist->{$user});
2457: next;
2458: }
2459: }
2460: if ($secfilter eq 'none') {
2461: if ($section ne '') {
2462: delete($userlist->{$user});
2463: next;
2464: }
2465: } elsif ($secfilter ne 'all') {
2466: if ($section ne $secfilter) {
2467: delete($userlist->{$user});
2468: next;
2469: }
2470: }
2471: if ($grpfilter eq 'none') {
2472: if (@ac_groups > 0) {
2473: delete($userlist->{$user});
2474: next;
2475: }
2476: } elsif ($grpfilter ne 'all') {
2477: if (!grep(/^\Q$grpfilter\E$/,@ac_groups)) {
2478: delete($userlist->{$user});
2479: next;
2480: }
2481: }
2482: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
2483: if (($displayphotos eq 'on') && ($role eq 'st')) {
2484: $userlist->{$user}->[$index{'photo'}] =
2485: &Apache::lonnet::retrievestudentphoto($udom,$uname,'jpg');
2486: $userlist->{$user}->[$index{'thumbnail'}] =
2487: &Apache::lonnet::retrievestudentphoto($udom,$uname,
2488: 'gif','thumbnail');
2489: }
2490: }
2491: }
2492: }
2493: my %emails = &Apache::loncommon::getemails($uname,$udom);
2494: if ($emails{'permanentemail'} =~ /\S/) {
2495: $userlist->{$user}->[$index{'email'}] = $emails{'permanentemail'};
2496: }
2497: $usercount ++;
2498: }
2499: my $autocount = 0;
2500: my $manualcount = 0;
2501: my $lockcount = 0;
2502: my $unlockcount = 0;
2503: if ($usercount) {
2504: $r->print($output);
2505: } else {
2506: if ($mode eq 'autoenroll') {
2507: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
2508: } else {
2509: return;
2510: }
2511: }
2512: #
2513: # Sort the users
2514: my $index = $index{$sortby};
2515: my $second = $index{'username'};
2516: my $third = $index{'domain'};
2517: my @sorted_users = sort {
2518: lc($userlist->{$a}->[$index]) cmp lc($userlist->{$b}->[$index])
2519: ||
2520: lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second]) ||
2521: lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
2522: } (keys(%$userlist));
2523: my $rowcount = 0;
2524: foreach my $user (@sorted_users) {
2525: my %in;
2526: my $sdata = $userlist->{$user};
2527: $rowcount ++;
2528: foreach my $item (@{$keylist}) {
2529: $in{$item} = $sdata->[$index{$item}];
2530: }
2531: my $clickers = (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
2532: if ($clickers!~/\w/) { $clickers='-'; }
2533: $in{'clicker'} = $clickers;
2534: my $role = $in{'role'};
2535: $in{'role'}=&Apache::lonnet::plaintext($sdata->[$index{'role'}]);
2536: if (! defined($in{'start'}) || $in{'start'} == 0) {
2537: $in{'start'} = &mt('none');
2538: } else {
2539: $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
2540: }
2541: if (! defined($in{'end'}) || $in{'end'} == 0) {
2542: $in{'end'} = &mt('none');
2543: } else {
2544: $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
2545: }
2546: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
2547: $r->print(&Apache::loncommon::start_data_table_row());
2548: my $checkval;
2549: if ($mode eq 'autoenroll') {
2550: my $cellentry;
2551: if ($in{'type'} eq 'auto') {
2552: $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'" /> Change</label>';
2553: $autocount ++;
2554: } else {
2555: $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'}.'" /> Change</label></span></td></tr><tr><td><span class="LC_nobreak">';
2556: $manualcount ++;
2557: if ($in{'lockedtype'}) {
2558: $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Unlock').'</label>';
2559: $unlockcount ++;
2560: } else {
2561: $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Lock').'</label>';
2562: $lockcount ++;
2563: }
2564: $cellentry .= '</span></td></tr></table>';
2565: }
2566: $r->print("<td>$cellentry</td>\n");
2567: } else {
2568: if ($mode ne 'pickauthor') {
2569: $r->print("<td>$rowcount</td>\n");
2570: }
2571: if ($actionselect) {
2572: my $showcheckbox;
2573: if ($role =~ /^cr\//) {
2574: $showcheckbox = $canchange{'cr'};
2575: } else {
2576: $showcheckbox = $canchange{$role};
2577: }
2578: if (!$showcheckbox) {
2579: if ($context eq 'course') {
2580: if ($canchangesec{$role} ne '') {
2581: if ($canchangesec{$role} eq $in{'section'}) {
2582: $showcheckbox = 1;
2583: }
2584: }
2585: }
2586: }
2587: if ($showcheckbox) {
2588: $checkval = $user;
2589: if ($context eq 'course') {
2590: if ($role eq 'st') {
2591: $checkval .= ':st';
2592: }
2593: $checkval .= ':'.$in{'section'};
2594: if ($role eq 'st') {
2595: $checkval .= ':'.$in{'type'}.':'.
2596: $in{'lockedtype'};
2597: }
2598: }
2599: $r->print('<td><input type="checkbox" name="'.
2600: 'actionlist" value="'.$checkval.'" /></td>');
2601: } else {
2602: $r->print('<td> </td>');
2603: }
2604: } elsif ($mode eq 'pickauthor') {
2605: $r->print('<td><input type="button" name="chooseauthor" onclick="javascript:gochoose('."'$in{'username'}'".');" value="'.&mt('Select').'" /></td>');
2606: }
2607: }
2608: foreach my $item (@cols) {
2609: if ($item eq 'username') {
2610: $r->print('<td>'.&print_username_link($mode,\%in).'</td>');
2611: } elsif (($item eq 'start' || $item eq 'end') && ($actionselect)) {
2612: $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.$checkval.'_'.$item.'" value="'.$sdata->[$index{$item}].'" /></td>'."\n");
2613: } elsif ($item eq 'status') {
2614: my $showitem = $in{$item};
2615: if (defined($ltstatus{$in{$item}})) {
2616: $showitem = $ltstatus{$in{$item}};
2617: }
2618: $r->print('<td>'.$showitem.'</td>'."\n");
2619: } else {
2620: $r->print('<td>'.$in{$item}.'</td>'."\n");
2621: }
2622: }
2623: if (($context eq 'course') && ($mode ne 'autoenroll')) {
2624: if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
2625: if ($displayclickers eq 'on') {
2626: my $clickers =
2627: (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
2628: if ($clickers!~/\w/) { $clickers='-'; }
2629: $r->print('<td>'.$clickers.'</td>');
2630: } else {
2631: $r->print(' <td> </td> ');
2632: }
2633: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
2634: if ($displayphotos eq 'on' && $role eq 'st' && $in{'photo'} ne '') {
2635: $r->print(' <td align="right"><a href="javascript:photowindow('."'".$in{'photo'}."'".')"><img src="'.$in{'thumbnail'}.'" border="1" alt="" /></a></td>');
2636: } else {
2637: $r->print(' <td> </td> ');
2638: }
2639: }
2640: }
2641: }
2642: $r->print(&Apache::loncommon::end_data_table_row());
2643: } elsif ($mode eq 'csv') {
2644: next if (! defined($CSVfile));
2645: # no need to bother with $linkto
2646: if (! defined($in{'start'}) || $in{'start'} == 0) {
2647: $in{'start'} = &mt('none');
2648: } else {
2649: $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
2650: }
2651: if (! defined($in{'end'}) || $in{'end'} == 0) {
2652: $in{'end'} = &mt('none');
2653: } else {
2654: $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
2655: }
2656: my @line = ();
2657: foreach my $item (@cols) {
2658: push @line,&Apache::loncommon::csv_translate($in{$item});
2659: }
2660: print $CSVfile '"'.join('","',@line)."\"\n";
2661: } elsif ($mode eq 'excel') {
2662: my $col = 0;
2663: foreach my $item (@cols) {
2664: if ($item eq 'start' || $item eq 'end') {
2665: if (defined($item) && $item != 0) {
2666: $excel_sheet->write($row,$col++,
2667: &Apache::lonstathelpers::calc_serial($in{item}),
2668: $format->{'date'});
2669: } else {
2670: $excel_sheet->write($row,$col++,'none');
2671: }
2672: } else {
2673: $excel_sheet->write($row,$col++,$in{$item});
2674: }
2675: }
2676: $row++;
2677: }
2678: }
2679: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
2680: $r->print(&Apache::loncommon::end_data_table().'<br />');
2681: } elsif ($mode eq 'excel') {
2682: $excel_workbook->close();
2683: $r->print(&mt('[_1]Your Excel spreadsheet[_2] is ready for download.', '<p><a href="'.$excel_filename.'">','</a>')."</p>\n");
2684: } elsif ($mode eq 'csv') {
2685: close($CSVfile);
2686: $r->print(&mt('[_1]Your CSV file[_2] is ready for download.', '<p><a href="'.$CSVfilename.'">','</a>')."</p>\n");
2687: $r->rflush();
2688: }
2689: if ($mode eq 'autoenroll') {
2690: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
2691: } else {
2692: return ($usercount);
2693: }
2694: }
2695:
2696: sub bulkaction_javascript {
2697: my ($formname,$caller) = @_;
2698: my $docstart = 'document';
2699: if ($caller eq 'popup') {
2700: $docstart = 'opener.document';
2701: }
2702: my %lt = &Apache::lonlocal::texthash(
2703: acwi => 'Access will be set to start immediately',
2704: asyo => 'as you did not select an end date in the pop-up window',
2705: accw => 'Access will be set to continue indefinitely',
2706: asyd => 'as you did not select an end date in the pop-up window',
2707: sewi => "Sections will be switched to 'No section'",
2708: ayes => "as you either selected the 'No section' option",
2709: oryo => 'or you did not select a section in the pop-up window',
2710: arol => 'A role with no section will be added',
2711: swbs => 'Sections will be switched to:',
2712: rwba => 'Roles will be added for section(s):',
2713: );
2714: my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox");
2715: my $noaction = &mt("You need to select an action to take for the user(s) you have selected");
2716: my $singconfirm = &mt(' for a single user?');
2717: my $multconfirm = &mt(' for multiple users?');
2718: my $output = <<"ENDJS";
2719: function verify_action (field) {
2720: var numchecked = 0;
2721: var singconf = '$singconfirm';
2722: var multconf = '$multconfirm';
2723: if ($docstart.$formname.elements[field].length > 0) {
2724: for (i=0; i<$docstart.$formname.elements[field].length; i++) {
2725: if ($docstart.$formname.elements[field][i].checked == true) {
2726: numchecked ++;
2727: }
2728: }
2729: } else {
2730: if ($docstart.$formname.elements[field].checked == true) {
2731: numchecked ++;
2732: }
2733: }
2734: if (numchecked == 0) {
2735: alert("$alert");
2736: return;
2737: } else {
2738: var message = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].text;
2739: var choice = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].value;
2740: if (choice == '') {
2741: alert("$noaction");
2742: return;
2743: } else {
2744: if (numchecked == 1) {
2745: message += singconf;
2746: } else {
2747: message += multconf;
2748: }
2749: ENDJS
2750: if ($caller ne 'popup') {
2751: $output .= <<"NEWWIN";
2752: if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate' || choice == 'chgsec') {
2753: opendatebrowser(document.$formname,'$formname','go');
2754: return;
2755:
2756: } else {
2757: if (confirm(message)) {
2758: document.$formname.phase.value = 'bulkchange';
2759: document.$formname.submit();
2760: return;
2761: }
2762: }
2763: NEWWIN
2764: } else {
2765: $output .= <<"POPUP";
2766: if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate') {
2767: var datemsg = '';
2768: if (($docstart.$formname.startdate_month.value == '') &&
2769: ($docstart.$formname.startdate_day.value == '') &&
2770: ($docstart.$formname.startdate_year.value == '')) {
2771: datemsg = "\\n$lt{'acwi'},\\n$lt{'asyo'}.\\n";
2772: }
2773: if (($docstart.$formname.enddate_month.value == '') &&
2774: ($docstart.$formname.enddate_day.value == '') &&
2775: ($docstart.$formname.enddate_year.value == '')) {
2776: datemsg += "\\n$lt{'accw'},\\n$lt{'asyd'}.\\n";
2777: }
2778: if (datemsg != '') {
2779: message += "\\n"+datemsg;
2780: }
2781: }
2782: if (choice == 'chgsec') {
2783: var rolefilter = $docstart.$formname.showrole.options[$docstart.$formname.showrole.selectedIndex].value;
2784: var retained = $docstart.$formname.retainsec.value;
2785: var secshow = $docstart.$formname.newsecs.value;
2786: if (secshow == '') {
2787: if (rolefilter == 'st' || retained == 0 || retained == "") {
2788: message += "\\n\\n$lt{'sewi'},\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
2789: } else {
2790: message += "\\n\\n$lt{'arol'}\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
2791: }
2792: } else {
2793: if (rolefilter == 'st' || retained == 0 || retained == "") {
2794: message += "\\n\\n$lt{'swbs'} "+secshow+".\\n";
2795: } else {
2796: message += "\\n\\n$lt{'rwba'} "+secshow+".\\n";
2797: }
2798: }
2799: }
2800: if (confirm(message)) {
2801: $docstart.$formname.phase.value = 'bulkchange';
2802: $docstart.$formname.submit();
2803: window.close();
2804: }
2805: POPUP
2806: }
2807: $output .= '
2808: }
2809: }
2810: }
2811: ';
2812: return $output;
2813: }
2814:
2815: sub print_username_link {
2816: my ($mode,$in) = @_;
2817: my $output;
2818: if ($mode eq 'autoenroll') {
2819: $output = $in->{'username'};
2820: } else {
2821: $output = '<a href="javascript:username_display_launch('.
2822: "'$in->{'username'}','$in->{'domain'}'".')" />'.
2823: $in->{'username'}.'</a>';
2824: }
2825: return $output;
2826: }
2827:
2828: sub role_type_names {
2829: my %lt = &Apache::lonlocal::texthash (
2830: 'domain' => 'Domain Roles',
2831: 'author' => 'Co-Author Roles',
2832: 'course' => 'Course Roles',
2833: );
2834: return %lt;
2835: }
2836:
2837: sub select_actions {
2838: my ($context,$setting,$statusmode,$formname) = @_;
2839: my %lt = &Apache::lonlocal::texthash(
2840: revoke => "Revoke user roles",
2841: delete => "Delete user roles",
2842: reenable => "Re-enable expired user roles",
2843: activate => "Make future user roles active now",
2844: chgdates => "Change starting/ending dates",
2845: chgsec => "Change section associated with user roles",
2846: );
2847: my ($output,$options,%choices);
2848: # FIXME Disable actions for now for roletype=course in domain context
2849: if ($context eq 'domain' && $setting eq 'course') {
2850: return;
2851: }
2852: if ($context eq 'course') {
2853: if ($env{'form.showrole'} ne 'Any') {
2854: if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},
2855: $env{'request.course.id'})) {
2856: if ($env{'request.course.sec'} eq '') {
2857: return;
2858: } else {
2859: if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
2860: return;
2861: }
2862: }
2863: }
2864: }
2865: }
2866: if ($statusmode eq 'Any') {
2867: $options .= '
2868: <option value="chgdates">'.$lt{'chgdates'}.'</option>';
2869: $choices{'dates'} = 1;
2870: } else {
2871: if ($statusmode eq 'Future') {
2872: $options .= '
2873: <option value="activate">'.$lt{'activate'}.'</option>';
2874: $choices{'dates'} = 1;
2875: } elsif ($statusmode eq 'Expired') {
2876: $options .= '
2877: <option value="reenable">'.$lt{'reenable'}.'</option>';
2878: $choices{'dates'} = 1;
2879: }
2880: if ($statusmode eq 'Active' || $statusmode eq 'Future') {
2881: $options .= '
2882: <option value="chgdates">'.$lt{'chgdates'}.'</option>
2883: <option value="revoke">'.$lt{'revoke'}.'</option>';
2884: $choices{'dates'} = 1;
2885: }
2886: }
2887: if ($context eq 'domain') {
2888: $options .= '
2889: <option value="delete">'.$lt{'delete'}.'</option>';
2890: }
2891: if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course')) {
2892: if (($statusmode ne 'Expired') && ($env{'request.course.sec'} eq '')) {
2893: $options .= '
2894: <option value="chgsec">'.$lt{'chgsec'}.'</option>';
2895: $choices{'sections'} = 1;
2896: }
2897: }
2898: if ($options) {
2899: $output = '<select name="bulkaction">'."\n".
2900: '<option value="" selected="selected">'.
2901: &mt('Please select').'</option>'."\n".$options."\n".'</select>';
2902: if ($choices{'dates'}) {
2903: $output .=
2904: '<input type="hidden" name="startdate_month" value="" />'."\n".
2905: '<input type="hidden" name="startdate_day" value="" />'."\n".
2906: '<input type="hidden" name="startdate_year" value="" />'."\n".
2907: '<input type="hidden" name="startdate_hour" value="" />'."\n".
2908: '<input type="hidden" name="startdate_minute" value="" />'."\n".
2909: '<input type="hidden" name="startdate_second" value="" />'."\n".
2910: '<input type="hidden" name="enddate_month" value="" />'."\n".
2911: '<input type="hidden" name="enddate_day" value="" />'."\n".
2912: '<input type="hidden" name="enddate_year" value="" />'."\n".
2913: '<input type="hidden" name="enddate_hour" value="" />'."\n".
2914: '<input type="hidden" name="enddate_minute" value="" />'."\n".
2915: '<input type="hidden" name="enddate_second" value="" />'."\n".
2916: '<input type="hidden" name="no_end_date" value="" />'."\n";
2917: if ($context eq 'course') {
2918: $output .= '<input type="hidden" name="makedatesdefault" value="" />'."\n";
2919: }
2920: }
2921: if ($choices{'sections'}) {
2922: $output .= '<input type="hidden" name="retainsec" value="" />'."\n".
2923: '<input type="hidden" name="newsecs" value="" />'."\n";
2924: }
2925: }
2926: return $output;
2927: }
2928:
2929: sub date_section_javascript {
2930: my ($context,$setting) = @_;
2931: my $title = 'Date_And_Section_Selector';
2932: my %nopopup = &Apache::lonlocal::texthash (
2933: revoke => "Check the boxes for any users for whom roles are to be revoked, and click 'Proceed'",
2934: delete => "Check the boxes for any users for whom roles are to be deleted, and click 'Proceed'",
2935: none => "Choose an action to take for selected users",
2936: );
2937: my $output = '
2938: <script type="text/javascript">'."\n";
2939: $output .= <<"ENDONE";
2940: function opendatebrowser(callingform,formname,calledby) {
2941: var bulkaction = callingform.bulkaction.options[callingform.bulkaction.selectedIndex].value;
2942: var url = '/adm/createuser?';
2943: var type = '';
2944: var showrole = callingform.showrole.options[callingform.showrole.selectedIndex].value;
2945: ENDONE
2946: if ($context eq 'domain') {
2947: $output .= '
2948: type = callingform.roletype.options[callingform.roletype.selectedIndex].value;
2949: ';
2950: }
2951: my $width= '700';
2952: my $height = '400';
2953: $output .= <<"ENDTWO";
2954: url += 'action=dateselect&callingform=' + formname +
2955: '&roletype='+type+'&showrole='+showrole +'&bulkaction='+bulkaction;
2956: var title = '$title';
2957: var options = 'scrollbars=1,resizable=1,menubar=0';
2958: options += ',width=$width,height=$height';
2959: stdeditbrowser = open(url,title,options,'1');
2960: stdeditbrowser.focus();
2961: }
2962: </script>
2963: ENDTWO
2964: return $output;
2965: }
2966:
2967: sub date_section_selector {
2968: my ($context,$permission) = @_;
2969: my $callingform = $env{'form.callingform'};
2970: my $formname = 'dateselect';
2971: my $groupslist = &get_groupslist();
2972: my $sec_js = &setsections_javascript($formname,$groupslist);
2973: my $output = <<"END";
2974: <script type="text/javascript">
2975:
2976: $sec_js
2977:
2978: function saveselections(formname) {
2979:
2980: END
2981: if ($env{'form.bulkaction'} eq 'chgsec') {
2982: $output .= <<"END";
2983: if (formname.retainsec.length > 1) {
2984: for (var i=0; i<formname.retainsec.length; i++) {
2985: if (formname.retainsec[i].checked == true) {
2986: opener.document.$callingform.retainsec.value = formname.retainsec[i].value;
2987: }
2988: }
2989: } else {
2990: opener.document.$callingform.retainsec.value = formname.retainsec.value;
2991: }
2992: setSections(formname);
2993: if (seccheck == 'ok') {
2994: opener.document.$callingform.newsecs.value = formname.sections.value;
2995: }
2996: END
2997: } else {
2998: if ($context eq 'course') {
2999: if (($env{'form.bulkaction'} eq 'reenable') ||
3000: ($env{'form.bulkaction'} eq 'activate') ||
3001: ($env{'form.bulkaction'} eq 'chgdates')) {
3002: if ($env{'request.course.sec'} eq '') {
3003: $output .= <<"END";
3004:
3005: if (formname.makedatesdefault.checked == true) {
3006: opener.document.$callingform.makedatesdefault.value = 1;
3007: }
3008: else {
3009: opener.document.$callingform.makedatesdefault.value = 0;
3010: }
3011:
3012: END
3013: }
3014: }
3015: }
3016: $output .= <<"END";
3017: opener.document.$callingform.startdate_month.value = formname.startdate_month.options[formname.startdate_month.selectedIndex].value;
3018: opener.document.$callingform.startdate_day.value = formname.startdate_day.value;
3019: opener.document.$callingform.startdate_year.value = formname.startdate_year.value;
3020: opener.document.$callingform.startdate_hour.value = formname.startdate_hour.options[formname.startdate_hour.selectedIndex].value;
3021: opener.document.$callingform.startdate_minute.value = formname.startdate_minute.value;
3022: opener.document.$callingform.startdate_second.value = formname.startdate_second.value;
3023: opener.document.$callingform.enddate_month.value = formname.enddate_month.options[formname.enddate_month.selectedIndex].value;
3024: opener.document.$callingform.enddate_day.value = formname.enddate_day.value;
3025: opener.document.$callingform.enddate_year.value = formname.enddate_year.value;
3026: opener.document.$callingform.enddate_hour.value = formname.enddate_hour.options[formname.enddate_hour.selectedIndex].value;
3027: opener.document.$callingform.enddate_minute.value = formname.enddate_minute.value;
3028: opener.document.$callingform.enddate_second.value = formname.enddate_second.value;
3029: if (formname.no_end_date.checked) {
3030: opener.document.$callingform.no_end_date.value = '1';
3031: } else {
3032: opener.document.$callingform.no_end_date.value = '0';
3033: }
3034: END
3035: }
3036: my $verify_action_js = &bulkaction_javascript($callingform,'popup');
3037: $output .= <<"ENDJS";
3038: verify_action('actionlist');
3039: }
3040:
3041: $verify_action_js
3042:
3043: </script>
3044: ENDJS
3045: my %lt = &Apache::lonlocal::texthash (
3046: chac => 'Access dates to apply for selected users',
3047: chse => 'Changes in section affiliation to apply to selected users',
3048: 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.',
3049: forn => 'For a role in a course that is not a student role, a user may have roles in more than one section of a course at a time.',
3050: reta => "Retain each user's current section affiliations?",
3051: dnap => '(Does not apply to student roles).',
3052: );
3053: my ($date_items,$headertext);
3054: if ($env{'form.bulkaction'} eq 'chgsec') {
3055: $headertext = $lt{'chse'};
3056: } else {
3057: $headertext = $lt{'chac'};
3058: my $starttime;
3059: if (($env{'form.bulkaction'} eq 'activate') ||
3060: ($env{'form.bulkaction'} eq 'reenable')) {
3061: $starttime = time;
3062: }
3063: $date_items = &date_setting_table($starttime,undef,$context,
3064: $env{'form.bulkaction'},$formname,
3065: $permission);
3066: }
3067: $output .= '<h3>'.$headertext.'</h3>'.
3068: '<form name="'.$formname.'" method="post">'."\n".
3069: $date_items;
3070: if ($context eq 'course' && $env{'form.bulkaction'} eq 'chgsec') {
3071: my ($cnum,$cdom) = &get_course_identity();
3072: my $info;
3073: if ($env{'form.showrole'} eq 'st') {
3074: $output .= '<p>'.$lt{'fors'}.'</p>';
3075: } elsif ($env{'form.showrole'} eq 'Any') {
3076: $output .= '<p>'.$lt{'fors'}.'</p>'.
3077: '<p>'.$lt{'forn'}.' ';
3078: $info = $lt{'reta'};
3079: } else {
3080: $output .= '<p>'.$lt{'forn'}.' ';
3081: $info = $lt{'reta'};
3082: }
3083: if ($info) {
3084: $info .= '<span class="LC_nobreak">'.
3085: '<label><input type="radio" name="retainsec" value="1" '.
3086: 'checked="checked" />'.&mt('Yes').'</label> '.
3087: '<label><input type="radio" name="retainsec" value="0" />'.
3088: &mt('No').'</label></span>';
3089: if ($env{'form.showrole'} eq 'Any') {
3090: $info .= '<br />'.$lt{'dnap'};
3091: }
3092: $info .= '</p>';
3093: } else {
3094: $info = '<input type="hidden" name="retainsec" value="0" />';
3095: }
3096: my $rowtitle = &mt('New section to assign');
3097: my $secbox = §ion_picker($cdom,$cnum,$env{'form.showrole'},$rowtitle,$permission,$context);
3098: $output .= $info.$secbox;
3099: }
3100: $output .= '<p>'.
3101: '<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n".
3102: '</form>';
3103: return $output;
3104: }
3105:
3106: sub section_picker {
3107: my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode) = @_;
3108: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
3109: my $sections_select .= &course_sections(\%sections_count,$role);
3110: my $secbox = '<p>'.&Apache::lonhtmlcommon::start_pick_box()."\n";
3111: if ($mode eq 'upload') {
3112: my ($options,$cb_script,$coursepick) =
3113: &default_role_selector($context,1);
3114: $secbox .= &Apache::lonhtmlcommon::row_title(&mt('role'),'LC_oddrow_value').
3115: $options. &Apache::lonhtmlcommon::row_closure(1)."\n";
3116: }
3117: $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n";
3118: if ($env{'request.course.sec'} eq '') {
3119: $secbox .= '<table class="LC_createuser"><tr class="LC_section_row">'."\n".
3120: '<td align="center">'.&mt('Existing sections')."\n".
3121: '<br />'.$sections_select.'</td><td align="center">'.
3122: &mt('New section').'<br />'."\n".
3123: '<input type="text" name="newsec" size="15" />'."\n".
3124: '<input type="hidden" name="sections" value="" />'."\n".
3125: '</td></tr></table>'."\n";
3126: } else {
3127: $secbox .= '<input type="hidden" name="sections" value="'.
3128: $env{'request.course.sec'}.'" />'.
3129: $env{'request.course.sec'};
3130: }
3131: $secbox .= &Apache::lonhtmlcommon::row_closure(1)."\n".
3132: &Apache::lonhtmlcommon::end_pick_box().'</p>';
3133: return $secbox;
3134: }
3135:
3136: sub results_header_row {
3137: my ($rolefilter,$statusmode,$context,$permission,$mode) = @_;
3138: my ($description,$showfilter);
3139: if ($rolefilter ne 'Any') {
3140: $showfilter = $rolefilter;
3141: }
3142: if ($context eq 'course') {
3143: if ($mode eq 'csv' || $mode eq 'excel') {
3144: $description = &mt('Course - [_1]:',$env{'course.'.$env{'request.course.id'}.'.description'}).' ';
3145: }
3146: if ($statusmode eq 'Expired') {
3147: $description .= &mt('Users in course with expired [_1] roles',$showfilter);
3148: } elsif ($statusmode eq 'Future') {
3149: $description .= &mt('Users in course with future [_1] roles',$showfilter);
3150: } elsif ($statusmode eq 'Active') {
3151: $description .= &mt('Users in course with active [_1] roles',$showfilter);
3152: } else {
3153: if ($rolefilter eq 'Any') {
3154: $description .= &mt('All users in course');
3155: } else {
3156: $description .= &mt('All users in course with [_1] roles',$rolefilter);
3157: }
3158: }
3159: my $constraint;
3160: my $viewablesec = &viewable_section($permission);
3161: if ($viewablesec ne '') {
3162: if ($env{'form.showrole'} eq 'st') {
3163: $constraint = &mt('only users in section "[_1]"',$viewablesec);
3164: } elsif ($env{'form.showrole'} ne 'cc') {
3165: $constraint = &mt('only users affiliated with no section or section "[_1]"',$viewablesec);
3166: }
3167: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
3168: if ($env{'form.grpfilter'} eq 'none') {
3169: $constraint .= &mt(' and not in any group');
3170: } else {
3171: $constraint .= &mt(' and members of group: "[_1]"',$env{'form.grpfilter'});
3172: }
3173: }
3174: } else {
3175: if (($env{'form.secfilter'} ne 'all') && ($env{'form.secfilter'} ne '')) {
3176: if ($env{'form.secfilter'} eq 'none') {
3177: $constraint = &mt('only users affiliated with no section');
3178: } else {
3179: $constraint = &mt('only users affiliated with section "[_1]"',$env{'form.secfilter'});
3180: }
3181: }
3182: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
3183: if ($env{'form.grpfilter'} eq 'none') {
3184: if ($constraint eq '') {
3185: $constraint = &mt('only users not in any group');
3186: } else {
3187: $constraint .= &mt(' and also not in any group');
3188: }
3189: } else {
3190: if ($constraint eq '') {
3191: $constraint = &mt('only members of group: "[_1]"',$env{'form.grpfilter'});
3192: } else {
3193: $constraint .= &mt(' and also members of group: "[_1]"'.$env{'form.grpfilter'});
3194: }
3195: }
3196: }
3197: }
3198: if ($constraint ne '') {
3199: $description .= ' ('.$constraint.')';
3200: }
3201: } elsif ($context eq 'author') {
3202: $description =
3203: &mt('Author space for [_1]'
3204: ,'<span class="LC_cusr_emph">'
3205: .&Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'})
3206: .'</span>')
3207: .': ';
3208: if ($statusmode eq 'Expired') {
3209: $description .= &mt('Co-authors with expired [_1] roles',$showfilter);
3210: } elsif ($statusmode eq 'Future') {
3211: $description .= &mt('Co-authors with future [_1] roles',$showfilter);
3212: } elsif ($statusmode eq 'Active') {
3213: $description .= &mt('Co-authors with active [_1] roles',$showfilter);
3214: } else {
3215: if ($rolefilter eq 'Any') {
3216: $description .= &mt('All co-authors');
3217: } else {
3218: $description .= &mt('All co-authors with [_1] roles',$rolefilter);
3219: }
3220: }
3221: } elsif ($context eq 'domain') {
3222: my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description');
3223: $description = &mt('Domain - [_1]:',$domdesc).' ';
3224: if ($env{'form.roletype'} eq 'domain') {
3225: if ($statusmode eq 'Expired') {
3226: $description .= &mt('Users in domain with expired [_1] roles',$showfilter);
3227: } elsif ($statusmode eq 'Future') {
3228: $description .= &mt('Users in domain with future [_1] roles',$showfilter);
3229: } elsif ($statusmode eq 'Active') {
3230: $description .= &mt('Users in domain with active [_1] roles',$showfilter);
3231: } else {
3232: if ($rolefilter eq 'Any') {
3233: $description .= &mt('All users in domain');
3234: } else {
3235: $description .= &mt('All users in domain with [_1] roles',$rolefilter);
3236: }
3237: }
3238: } elsif ($env{'form.roletype'} eq 'author') {
3239: if ($statusmode eq 'Expired') {
3240: $description .= &mt('Co-authors in domain with expired [_1] roles',$showfilter);
3241: } elsif ($statusmode eq 'Future') {
3242: $description .= &mt('Co-authors in domain with future [_1] roles',$showfilter);
3243: } elsif ($statusmode eq 'Active') {
3244: $description .= &mt('Co-authors in domain with active [_1] roles',$showfilter);
3245: } else {
3246: if ($rolefilter eq 'Any') {
3247: $description .= &mt('All users with co-author roles in domain',$showfilter);
3248: } else {
3249: $description .= &mt('All co-authors in domain with [_1] roles',$rolefilter);
3250: }
3251: }
3252: } elsif ($env{'form.roletype'} eq 'course') {
3253: my $coursefilter = $env{'form.coursepick'};
3254: if ($coursefilter eq 'category') {
3255: my $instcode = &instcode_from_coursefilter();
3256: if ($instcode eq '.') {
3257: $description .= &mt('All courses in domain').' - ';
3258: } else {
3259: $description .= &mt('Courses in domain with institutional code: [_1]',$instcode).' - ';
3260: }
3261: } elsif ($coursefilter eq 'selected') {
3262: $description .= &mt('Selected courses in domain').' - ';
3263: } elsif ($coursefilter eq 'all') {
3264: $description .= &mt('All courses in domain').' - ';
3265: }
3266: if ($statusmode eq 'Expired') {
3267: $description .= &mt('users with expired [_1] roles',$showfilter);
3268: } elsif ($statusmode eq 'Future') {
3269: $description .= &mt('users with future [_1] roles',$showfilter);
3270: } elsif ($statusmode eq 'Active') {
3271: $description .= &mt('users with active [_1] roles',$showfilter);
3272: } else {
3273: if ($rolefilter eq 'Any') {
3274: $description .= &mt('all users');
3275: } else {
3276: $description .= &mt('users with [_1] roles',$rolefilter);
3277: }
3278: }
3279: }
3280: }
3281: return $description;
3282: }
3283:
3284: sub viewable_section {
3285: my ($permission) = @_;
3286: my $viewablesec;
3287: if (ref($permission) eq 'HASH') {
3288: if (exists($permission->{'view_section'})) {
3289: $viewablesec = $permission->{'view_section'};
3290: } elsif (exists($permission->{'cusr_section'})) {
3291: $viewablesec = $permission->{'cusr_section'};
3292: }
3293: }
3294: return $viewablesec;
3295: }
3296:
3297:
3298: #################################################
3299: #################################################
3300: sub show_drop_list {
3301: my ($r,$classlist,$nosort,$permission) = @_;
3302: my $cid = $env{'request.course.id'};
3303: my ($cnum,$cdom) = &get_course_identity($cid);
3304: if (! exists($env{'form.sortby'})) {
3305: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
3306: ['sortby']);
3307: }
3308: my $sortby = $env{'form.sortby'};
3309: if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
3310: $sortby = 'username';
3311: }
3312: my $action = "drop";
3313: my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
3314: $r->print(<<END);
3315: <input type="hidden" name="sortby" value="$sortby" />
3316: <input type="hidden" name="action" value="$action" />
3317: <input type="hidden" name="state" value="done" />
3318: <script type="text/javascript" language="Javascript">
3319: $check_uncheck_js
3320: </script>
3321: <p>
3322: <input type="hidden" name="phase" value="four" />
3323: END
3324: my ($indexhash,$keylist) = &make_keylist_array();
3325: my $studentcount = 0;
3326: if (ref($classlist) eq 'HASH') {
3327: foreach my $student (keys(%{$classlist})) {
3328: my $sdata = $classlist->{$student};
3329: my $status = $sdata->[$indexhash->{'status'}];
3330: my $section = $sdata->[$indexhash->{'section'}];
3331: if ($status ne 'Active') {
3332: delete($classlist->{$student});
3333: next;
3334: }
3335: if ($env{'request.course.sec'} ne '') {
3336: if ($section ne $env{'request.course.sec'}) {
3337: delete($classlist->{$student});
3338: next;
3339: }
3340: }
3341: $studentcount ++;
3342: }
3343: }
3344: if (!$studentcount) {
3345: $r->print(&mt('There are no students to drop.'));
3346: return;
3347: }
3348: my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
3349: $classlist,$keylist,$cdom,$cnum);
3350: my %lt=&Apache::lonlocal::texthash('usrn' => "username",
3351: 'dom' => "domain",
3352: 'sn' => "student name",
3353: 'sec' => "section",
3354: 'start' => "start date",
3355: 'end' => "end date",
3356: 'groups' => "active groups",
3357: );
3358: if ($nosort) {
3359: $r->print(&Apache::loncommon::start_data_table().
3360: &Apache::loncommon::start_data_table_header_row());
3361: $r->print(<<END);
3362: <th> </th>
3363: <th>$lt{'usrn'}</th>
3364: <th>$lt{'dom'}</th>
3365: <th>ID</th>
3366: <th>$lt{'sn'}</th>
3367: <th>$lt{'sec'}</th>
3368: <th>$lt{'start'}</th>
3369: <th>$lt{'end'}</th>
3370: <th>$lt{'groups'}</th>
3371: END
3372: $r->print(&Apache::loncommon::end_data_table_header_row());
3373: } else {
3374: $r->print(&Apache::loncommon::start_data_table().
3375: &Apache::loncommon::start_data_table_header_row());
3376: $r->print(<<END);
3377: <th> </th>
3378: <th>
3379: <a href="/adm/createuser?action=$action&sortby=username">$lt{'usrn'}</a>
3380: </th><th>
3381: <a href="/adm/createuser?action=$action&sortby=domain">$lt{'dom'}</a>
3382: </th><th>
3383: <a href="/adm/createuser?action=$action&sortby=id">ID</a>
3384: </th><th>
3385: <a href="/adm/createuser?action=$action&sortby=fullname">$lt{'sn'}</a>
3386: </th><th>
3387: <a href="/adm/createuser?action=$action&sortby=section">$lt{'sec'}</a>
3388: </th><th>
3389: <a href="/adm/createuser?action=$action&sortby=start">$lt{'start'}</a>
3390: </th><th>
3391: <a href="/adm/createuser?action=$action&sortby=end">$lt{'end'}</a>
3392: </th><th>
3393: <a href="/adm/createuser?action=$action&sortby=groups">$lt{'groups'}</a>
3394: </th>
3395: END
3396: $r->print(&Apache::loncommon::end_data_table_header_row());
3397: }
3398: #
3399: # Sort the students
3400: my $index = $indexhash->{$sortby};
3401: my $second = $indexhash->{'username'};
3402: my $third = $indexhash->{'domain'};
3403: my @Sorted_Students = sort {
3404: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
3405: ||
3406: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
3407: ||
3408: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
3409: } (keys(%{$classlist}));
3410: foreach my $student (@Sorted_Students) {
3411: my $error;
3412: my $sdata = $classlist->{$student};
3413: my $username = $sdata->[$indexhash->{'username'}];
3414: my $domain = $sdata->[$indexhash->{'domain'}];
3415: my $section = $sdata->[$indexhash->{'section'}];
3416: my $name = $sdata->[$indexhash->{'fullname'}];
3417: my $id = $sdata->[$indexhash->{'id'}];
3418: my $start = $sdata->[$indexhash->{'start'}];
3419: my $end = $sdata->[$indexhash->{'end'}];
3420: my $groups = $classgroups->{$student};
3421: my $active_groups;
3422: if (ref($groups->{active}) eq 'HASH') {
3423: $active_groups = join(', ',keys(%{$groups->{'active'}}));
3424: }
3425: if (! defined($start) || $start == 0) {
3426: $start = &mt('none');
3427: } else {
3428: $start = &Apache::lonlocal::locallocaltime($start);
3429: }
3430: if (! defined($end) || $end == 0) {
3431: $end = &mt('none');
3432: } else {
3433: $end = &Apache::lonlocal::locallocaltime($end);
3434: }
3435: my $studentkey = $student.':'.$section;
3436: my $startitem = '<input type="hidden" name="'.$studentkey.'_start" value="'.$sdata->[$indexhash->{'start'}].'" />';
3437: #
3438: $r->print(&Apache::loncommon::start_data_table_row());
3439: $r->print(<<"END");
3440: <td><input type="checkbox" name="droplist" value="$studentkey" /></td>
3441: <td>$username</td>
3442: <td>$domain</td>
3443: <td>$id</td>
3444: <td>$name</td>
3445: <td>$section</td>
3446: <td>$start $startitem</td>
3447: <td>$end</td>
3448: <td>$active_groups</td>
3449: END
3450: $r->print(&Apache::loncommon::end_data_table_row());
3451: }
3452: $r->print(&Apache::loncommon::end_data_table().'<br />');
3453: %lt=&Apache::lonlocal::texthash(
3454: 'dp' => "Drop Students",
3455: 'ca' => "check all",
3456: 'ua' => "uncheck all",
3457: );
3458: $r->print(<<"END");
3459: </p>
3460: <p>
3461: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)" />
3462: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)" />
3463: </p>
3464: <p>
3465: <input type="submit" value="$lt{'dp'}" />
3466: </p>
3467: END
3468: return;
3469: }
3470:
3471: #
3472: # Print out the initial form to get the file containing a list of users
3473: #
3474: sub print_first_users_upload_form {
3475: my ($r,$context) = @_;
3476: my $str;
3477: $str = '<input type="hidden" name="phase" value="two" />';
3478: $str .= '<input type="hidden" name="action" value="upload" />';
3479: $str .= '<input type="hidden" name="state" value="got_file" />';
3480:
3481: $str .= '<h2>'.&mt('Upload a file containing information about users').'</h2>'."\n";
3482:
3483: # Excel and CSV Help
3484: $str .= '<p>'
3485: .&Apache::loncommon::help_open_topic("Course_Create_Class_List",
3486: &mt("How do I create a users list from a spreadsheet"))
3487: ."<br />\n"
3488: .&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
3489: &mt("How do I create a CSV file from a spreadsheet"))
3490: ."</p>\n";
3491:
3492: $str .= &Apache::lonhtmlcommon::start_pick_box()
3493: .&Apache::lonhtmlcommon::row_title(&mt('File'))
3494: .'<p class="LC_info">'."\n"
3495: .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.')."\n"
3496: .'</p>'."\n"
3497: .&Apache::loncommon::upfile_select_html()
3498: .&Apache::lonhtmlcommon::row_closure()
3499: .&Apache::lonhtmlcommon::row_title(
3500: '<label for="noFirstLine">'
3501: .&mt('Ignore First Line')
3502: .'</label>')
3503: .'<input type="checkbox" name="noFirstLine" id="noFirstLine" />'
3504: .&Apache::lonhtmlcommon::row_closure(1)
3505: .&Apache::lonhtmlcommon::end_pick_box();
3506:
3507: $str .= '<p>'
3508: .'<input type="submit" name="fileupload" value="'.&mt('Next').'" />'
3509: .'</p>';
3510:
3511: $str .= &Apache::loncommon::end_page();
3512:
3513: $r->print($str);
3514: return;
3515: }
3516:
3517: # ================================================= Drop/Add from uploaded file
3518: sub upfile_drop_add {
3519: my ($r,$context,$permission) = @_;
3520: &Apache::loncommon::load_tmp_file($r);
3521: my @userdata=&Apache::loncommon::upfile_record_sep();
3522: if($env{'form.noFirstLine'}){shift(@userdata);}
3523: my @keyfields = split(/\,/,$env{'form.keyfields'});
3524: my %fields=();
3525: for (my $i=0; $i<=$env{'form.nfields'}; $i++) {
3526: if ($env{'form.upfile_associate'} eq 'reverse') {
3527: if ($env{'form.f'.$i} ne 'none') {
3528: $fields{$keyfields[$i]}=$env{'form.f'.$i};
3529: }
3530: } else {
3531: $fields{$env{'form.f'.$i}}=$keyfields[$i];
3532: }
3533: }
3534: if ($env{'form.fullup'} ne 'yes') {
3535: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
3536: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />');
3537: }
3538: #
3539: # Store the field choices away
3540: foreach my $field (qw/username names
3541: fname mname lname gen id sec ipwd email role domain/) {
3542: $env{'form.'.$field.'_choice'}=$fields{$field};
3543: }
3544: &Apache::loncommon::store_course_settings('enrollment_upload',
3545: { 'username_choice' => 'scalar',
3546: 'names_choice' => 'scalar',
3547: 'fname_choice' => 'scalar',
3548: 'mname_choice' => 'scalar',
3549: 'lname_choice' => 'scalar',
3550: 'gen_choice' => 'scalar',
3551: 'id_choice' => 'scalar',
3552: 'sec_choice' => 'scalar',
3553: 'ipwd_choice' => 'scalar',
3554: 'email_choice' => 'scalar',
3555: 'role_choice' => 'scalar',
3556: 'domain_choice' => 'scalar',
3557: 'inststatus_choice' => 'scalar'});
3558: #
3559: my ($startdate,$enddate) = &get_dates_from_form();
3560: if ($env{'form.makedatesdefault'}) {
3561: $r->print(&make_dates_default($startdate,$enddate,$context));
3562: }
3563: # Determine domain and desired host (home server)
3564: my $defdom=$env{'request.role.domain'};
3565: my $domain;
3566: if ($env{'form.defaultdomain'} ne '') {
3567: $domain = $env{'form.defaultdomain'};
3568: } else {
3569: $domain = $defdom;
3570: }
3571: my $desiredhost = $env{'form.lcserver'};
3572: if (lc($desiredhost) eq 'default') {
3573: $desiredhost = undef;
3574: } else {
3575: my %home_servers = &Apache::lonnet::get_servers($defdom,'library');
3576: if (! exists($home_servers{$desiredhost})) {
3577: $r->print('<span class="LC_error">'.&mt('Error').
3578: &mt('Invalid home server specified').'</span>');
3579: $r->print(&Apache::loncommon::end_page());
3580: return;
3581: }
3582: }
3583: # Determine authentication mechanism
3584: my $changeauth;
3585: if ($context eq 'domain') {
3586: $changeauth = $env{'form.changeauth'};
3587: }
3588: my $amode = '';
3589: my $genpwd = '';
3590: if ($env{'form.login'} eq 'krb') {
3591: $amode='krb';
3592: $amode.=$env{'form.krbver'};
3593: $genpwd=$env{'form.krbarg'};
3594: } elsif ($env{'form.login'} eq 'int') {
3595: $amode='internal';
3596: if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
3597: $genpwd=$env{'form.intarg'};
3598: }
3599: } elsif ($env{'form.login'} eq 'loc') {
3600: $amode='localauth';
3601: if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
3602: $genpwd=$env{'form.locarg'};
3603: }
3604: }
3605: if ($amode =~ /^krb/) {
3606: if (! defined($genpwd) || $genpwd eq '') {
3607: $r->print('<span class="Error">'.
3608: &mt('Unable to enroll users').' '.
3609: &mt('No Kerberos domain was specified.').'</span></p>');
3610: $amode = ''; # This causes the loop below to be skipped
3611: }
3612: }
3613: my ($cid,$defaultsec,$defaultrole,$setting);
3614: if ($context eq 'domain') {
3615: $setting = $env{'form.roleaction'};
3616: if ($setting eq 'domain') {
3617: $defaultrole = $env{'form.defaultrole'};
3618: } elsif ($setting eq 'course') {
3619: $defaultrole = $env{'form.courserole'};
3620: $defaultsec = $env{'form.sections'};
3621: }
3622: } elsif ($context eq 'author') {
3623: $defaultrole = $env{'form.defaultrole'};
3624: } elsif ($context eq 'course') {
3625: $defaultrole = $env{'form.defaultrole'};
3626: $defaultsec = $env{'form.sections'};
3627: }
3628: if ($env{'request.course.id'} ne '') {
3629: $cid = $env{'request.course.id'};
3630: } elsif ($setting eq 'course') {
3631: if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) {
3632: $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'};
3633: }
3634: }
3635: # Check to see if user information can be changed
3636: my @userinfo = ('firstname','middlename','lastname','generation',
3637: 'permanentemail','id');
3638: my %canmodify;
3639: if (&Apache::lonnet::allowed('mau',$domain)) {
3640: push(@userinfo,'inststatus');
3641: foreach my $field (@userinfo) {
3642: $canmodify{$field} = 1;
3643: }
3644: }
3645: my (%userlist,%modifiable_fields,@poss_roles);
3646: my $secidx = &Apache::loncoursedata::CL_SECTION();
3647: my @courseroles = &roles_by_context('course',1);
3648: if (!&Apache::lonnet::allowed('mau',$domain)) {
3649: if ($context eq 'course' || $context eq 'author') {
3650: @poss_roles = &curr_role_permissions($context);
3651: my @statuses = ('active','future');
3652: my ($indexhash,$keylist) = &make_keylist_array();
3653: my %info;
3654: foreach my $role (@poss_roles) {
3655: %{$modifiable_fields{$role}} = &can_modify_userinfo($context,$domain,
3656: \@userinfo,[$role]);
3657: }
3658: if ($context eq 'course') {
3659: my ($cnum,$cdom) = &get_course_identity();
3660: my $roster = &Apache::loncoursedata::get_classlist();
3661: if (ref($roster) eq 'HASH') {
3662: %userlist = %{$roster};
3663: }
3664: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
3665: \@statuses,\@poss_roles);
3666: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
3667: \%advrolehash,$permission);
3668: } elsif ($context eq 'author') {
3669: my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
3670: \@statuses,\@poss_roles);
3671: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
3672: \%cstr_roles,$permission);
3673:
3674: }
3675: }
3676: }
3677: if ( $domain eq &LONCAPA::clean_domain($domain)
3678: && ($amode ne '')) {
3679: #######################################
3680: ## Add/Modify Users ##
3681: #######################################
3682: if ($context eq 'course') {
3683: $r->print('<h3>'.&mt('Enrolling Users')."</h3>\n<p>\n");
3684: } elsif ($context eq 'author') {
3685: $r->print('<h3>'.&mt('Updating Co-authors')."</h3>\n<p>\n");
3686: } else {
3687: $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n");
3688: }
3689: $r->rflush;
3690:
3691: my %counts = (
3692: user => 0,
3693: auth => 0,
3694: role => 0,
3695: );
3696: my $flushc=0;
3697: my %student=();
3698: my (%curr_groups,@sections,@cleansec,$defaultwarn,$groupwarn);
3699: my %userchg;
3700: if ($context eq 'course' || $setting eq 'course') {
3701: if ($context eq 'course') {
3702: # Get information about course groups
3703: %curr_groups = &Apache::longroup::coursegroups();
3704: } elsif ($setting eq 'course') {
3705: if ($cid) {
3706: %curr_groups =
3707: &Apache::longroup::coursegroups($env{'form.dcdomain'},
3708: $env{'form.dccourse'});
3709: }
3710: }
3711: # determine section number
3712: if ($defaultsec =~ /,/) {
3713: push(@sections,split(/,/,$defaultsec));
3714: } else {
3715: push(@sections,$defaultsec);
3716: }
3717: # remove non alphanumeric values from section
3718: foreach my $item (@sections) {
3719: $item =~ s/\W//g;
3720: if ($item eq "none" || $item eq 'all') {
3721: $defaultwarn = &mt('Default section name [_1] could not be used as it is a reserved word.',$item);
3722: } elsif ($item ne '' && exists($curr_groups{$item})) {
3723: $groupwarn = &mt('Default section name "[_1]" is the name of a course group. Section names and group names must be distinct.',$item);
3724: } elsif ($item ne '') {
3725: push(@cleansec,$item);
3726: }
3727: }
3728: if ($defaultwarn) {
3729: $r->print($defaultwarn.'<br />');
3730: }
3731: if ($groupwarn) {
3732: $r->print($groupwarn.'<br />');
3733: }
3734: }
3735: my (%curr_rules,%got_rules,%alerts);
3736: my %customroles = &my_custom_roles();
3737: my @permitted_roles = &roles_on_upload($context,$setting,%customroles);
3738: # Get new users list
3739: foreach my $line (@userdata) {
3740: my @secs;
3741: my %entries=&Apache::loncommon::record_sep($line);
3742: # Determine user name
3743: unless (($entries{$fields{'username'}} eq '') ||
3744: (!defined($entries{$fields{'username'}}))) {
3745: my ($fname, $mname, $lname,$gen) = ('','','','');
3746: if (defined($fields{'names'})) {
3747: ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
3748: /([^\,]+)\,\s*(\w+)\s*(.*)$/);
3749: } else {
3750: if (defined($fields{'fname'})) {
3751: $fname=$entries{$fields{'fname'}};
3752: }
3753: if (defined($fields{'mname'})) {
3754: $mname=$entries{$fields{'mname'}};
3755: }
3756: if (defined($fields{'lname'})) {
3757: $lname=$entries{$fields{'lname'}};
3758: }
3759: if (defined($fields{'gen'})) {
3760: $gen=$entries{$fields{'gen'}};
3761: }
3762: }
3763: if ($entries{$fields{'username'}}
3764: ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
3765: $r->print('<br />'.
3766: &mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]',
3767: '<b>'.$entries{$fields{'username'}}.'</b>',$fname,$mname,$lname,$gen));
3768: next;
3769: } else {
3770: if ($entries{$fields{'domain'}}
3771: ne &LONCAPA::clean_domain($entries{$fields{'domain'}})) {
3772: $r->print('<br />'. '<b>'.$entries{$fields{'domain'}}.
3773: '</b>: '.&mt('Unacceptable domain for user [_2] [_3] [_4] [_5]',$fname,$mname,$lname,$gen));
3774: next;
3775: }
3776: my $username = $entries{$fields{'username'}};
3777: my $userdomain = $entries{$fields{'domain'}};
3778: if ($userdomain eq '') {
3779: $userdomain = $domain;
3780: }
3781: if (defined($fields{'sec'})) {
3782: if (defined($entries{$fields{'sec'}})) {
3783: $entries{$fields{'sec'}} =~ s/\W//g;
3784: my $item = $entries{$fields{'sec'}};
3785: if ($item eq "none" || $item eq 'all') {
3786: $r->print('<br />'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.','<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item));
3787: next;
3788: } elsif (exists($curr_groups{$item})) {
3789: $r->print('<br />'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.','<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item).' '.&mt('Section names and group names must be distinct.'));
3790: next;
3791: } else {
3792: push(@secs,$item);
3793: }
3794: }
3795: }
3796: if ($env{'request.course.sec'} ne '') {
3797: @secs = ($env{'request.course.sec'});
3798: if (ref($userlist{$username.':'.$userdomain}) eq 'ARRAY') {
3799: my $currsec = $userlist{$username.':'.$userdomain}[$secidx];
3800: if ($currsec ne $env{'request.course.sec'}) {
3801: $r->print('<br />'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".','<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$secs[0]).'<br />');
3802: if ($currsec eq '') {
3803: $r->print(&mt('This user already has an active/future student role in the course, unaffiliated to any section.'));
3804:
3805: } else {
3806: $r->print(&mt('This user already has an active/future role in section "[_1]" of the course.',$currsec));
3807: }
3808: $r->print('<br />'.&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.',$secs[0]).'<br />');
3809: next;
3810: }
3811: }
3812: } elsif ($context eq 'course' || $setting eq 'course') {
3813: if (@secs == 0) {
3814: @secs = @cleansec;
3815: }
3816: }
3817: # determine id number
3818: my $id='';
3819: if (defined($fields{'id'})) {
3820: if (defined($entries{$fields{'id'}})) {
3821: $id=$entries{$fields{'id'}};
3822: }
3823: $id=~tr/A-Z/a-z/;
3824: }
3825: # determine email address
3826: my $email='';
3827: if (defined($fields{'email'})) {
3828: if (defined($entries{$fields{'email'}})) {
3829: $email=$entries{$fields{'email'}};
3830: unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
3831: }
3832: }
3833: # determine affiliation
3834: my $inststatus='';
3835: if (defined($fields{'inststatus'})) {
3836: if (defined($entries{$fields{'inststatus'}})) {
3837: $inststatus=$entries{$fields{'inststatus'}};
3838: }
3839: }
3840: # determine user password
3841: my $password = $genpwd;
3842: if (defined($fields{'ipwd'})) {
3843: if ($entries{$fields{'ipwd'}}) {
3844: $password=$entries{$fields{'ipwd'}};
3845: }
3846: }
3847: # determine user role
3848: my $role = '';
3849: if (defined($fields{'role'})) {
3850: if ($entries{$fields{'role'}}) {
3851: $entries{$fields{'role'}} =~ s/(\s+$|^\s+)//g;
3852: if ($entries{$fields{'role'}} ne '') {
3853: if (grep(/^\Q$entries{$fields{'role'}}\E$/,@permitted_roles)) {
3854: $role = $entries{$fields{'role'}};
3855: }
3856: }
3857: if ($role eq '') {
3858: my $rolestr = join(', ',@permitted_roles);
3859: $r->print('<br />'
3860: .&mt('[_1]: You do not have permission to add the requested role [_2] for the user.'
3861: ,'<b>'.$entries{$fields{'username'}}.'</b>'
3862: ,$entries{$fields{'role'}})
3863: .'<br />'
3864: .&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n"
3865: );
3866: next;
3867: }
3868: }
3869: }
3870: if ($role eq '') {
3871: $role = $defaultrole;
3872: }
3873: # Clean up whitespace
3874: foreach (\$id,\$fname,\$mname,\$lname,\$gen) {
3875: $$_ =~ s/(\s+$|^\s+)//g;
3876: }
3877: # check against rules
3878: my $checkid = 0;
3879: my $newuser = 0;
3880: my (%rulematch,%inst_results,%idinst_results);
3881: my $uhome=&Apache::lonnet::homeserver($username,$userdomain);
3882: if ($uhome eq 'no_host') {
3883: next if ($userdomain ne $domain);
3884: $checkid = 1;
3885: $newuser = 1;
3886: my $checkhash;
3887: my $checks = { 'username' => 1 };
3888: $checkhash->{$username.':'.$domain} = { 'newuser' => 1, };
3889: &Apache::loncommon::user_rule_check($checkhash,$checks,
3890: \%alerts,\%rulematch,\%inst_results,\%curr_rules,
3891: \%got_rules);
3892: if (ref($alerts{'username'}) eq 'HASH') {
3893: if (ref($alerts{'username'}{$domain}) eq 'HASH') {
3894: next if ($alerts{'username'}{$domain}{$username});
3895: }
3896: }
3897: } else {
3898: if ($context eq 'course' || $context eq 'author') {
3899: if ($userdomain eq $domain ) {
3900: if ($role eq '') {
3901: my @checkroles;
3902: foreach my $role (@poss_roles) {
3903: my $endkey;
3904: if ($role ne 'st') {
3905: $endkey = ':'.$role;
3906: }
3907: if (exists($userlist{$username.':'.$userdomain.$endkey})) {
3908: if (!grep(/^\Q$role\E$/,@checkroles)) {
3909: push(@checkroles,$role);
3910: }
3911: }
3912: }
3913: if (@checkroles > 0) {
3914: %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles);
3915: }
3916: } elsif (ref($modifiable_fields{$role}) eq 'HASH') {
3917: %canmodify = %{$modifiable_fields{$role}};
3918: }
3919: }
3920: my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id);
3921: for (my $i=0; $i<@newinfo; $i++) {
3922: if (${$newinfo[$i]} ne '') {
3923: if (!$canmodify{$userinfo[$i]}) {
3924: ${$newinfo[$i]} = '';
3925: }
3926: }
3927: }
3928: }
3929: }
3930: if ($id ne '') {
3931: if (!$newuser) {
3932: my %idhash = &Apache::lonnet::idrget($userdomain,($username));
3933: if ($idhash{$username} ne $id) {
3934: $checkid = 1;
3935: }
3936: }
3937: if ($checkid) {
3938: my $checkhash;
3939: my $checks = { 'id' => 1 };
3940: $checkhash->{$username.':'.$userdomain} = { 'newuser' => $newuser,
3941: 'id' => $id };
3942: &Apache::loncommon::user_rule_check($checkhash,$checks,
3943: \%alerts,\%rulematch,\%idinst_results,\%curr_rules,
3944: \%got_rules);
3945: if (ref($alerts{'id'}) eq 'HASH') {
3946: if (ref($alerts{'id'}{$userdomain}) eq 'HASH') {
3947: next if ($alerts{'id'}{$userdomain}{$id});
3948: }
3949: }
3950: }
3951: }
3952: if ($password || $env{'form.login'} eq 'loc') {
3953: my $multiple = 0;
3954: my ($userresult,$authresult,$roleresult,$idresult);
3955: my (%userres,%authres,%roleres,%idres);
3956: my $singlesec = '';
3957: if ($role eq 'st') {
3958: my $sec;
3959: if (@secs > 0) {
3960: $sec = $secs[0];
3961: }
3962: &modifystudent($userdomain,$username,$cid,$sec,
3963: $desiredhost,$context);
3964: $roleresult =
3965: &Apache::lonnet::modifystudent
3966: ($userdomain,$username,$id,$amode,$password,
3967: $fname,$mname,$lname,$gen,$sec,$enddate,
3968: $startdate,$env{'form.forceid'},
3969: $desiredhost,$email,'manual','',$cid,
3970: '',$context,$inststatus);
3971: $userresult = $roleresult;
3972: } else {
3973: if ($role ne '') {
3974: if ($context eq 'course' || $setting eq 'course') {
3975: if ($customroles{$role}) {
3976: $role = 'cr_'.$env{'user.domain'}.'_'.
3977: $env{'user.name'}.'_'.$role;
3978: }
3979: if ($role ne 'cc') {
3980: if (@secs > 1) {
3981: $multiple = 1;
3982: foreach my $sec (@secs) {
3983: ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
3984: &modifyuserrole($context,$setting,
3985: $changeauth,$cid,$userdomain,$username,
3986: $id,$amode,$password,$fname,
3987: $mname,$lname,$gen,$sec,
3988: $env{'form.forceid'},$desiredhost,
3989: $email,$role,$enddate,
3990: $startdate,$checkid,$inststatus);
3991: }
3992: } elsif (@secs > 0) {
3993: $singlesec = $secs[0];
3994: }
3995: }
3996: }
3997: }
3998: if (!$multiple) {
3999: ($userresult,$authresult,$roleresult,$idresult) =
4000: &modifyuserrole($context,$setting,
4001: $changeauth,$cid,$userdomain,$username,
4002: $id,$amode,$password,$fname,
4003: $mname,$lname,$gen,$singlesec,
4004: $env{'form.forceid'},$desiredhost,
4005: $email,$role,$enddate,$startdate,
4006: $checkid,$inststatus);
4007: }
4008: }
4009: if ($multiple) {
4010: foreach my $sec (sort(keys(%userres))) {
4011: $flushc =
4012: &user_change_result($r,$userres{$sec},$authres{$sec},
4013: $roleres{$sec},$idres{$sec},\%counts,$flushc,
4014: $username,$userdomain,\%userchg);
4015:
4016: }
4017: } else {
4018: $flushc =
4019: &user_change_result($r,$userresult,$authresult,
4020: $roleresult,$idresult,\%counts,$flushc,
4021: $username,$userdomain,\%userchg);
4022: }
4023: } else {
4024: if ($context eq 'course') {
4025: $r->print('<br />'.
4026: &mt('[_1]: Unable to enroll. No password specified.','<b>'.$username.'</b>')
4027: );
4028: } elsif ($context eq 'author') {
4029: $r->print('<br />'.
4030: &mt('[_1]: Unable to add co-author. No password specified.','<b>'.$username.'</b>')
4031: );
4032: } else {
4033: $r->print('<br />'.
4034: &mt('[_1]: Unable to add user. No password specified.','<b>'.$username.'</b>')
4035: );
4036: }
4037: }
4038: }
4039: }
4040: } # end of foreach (@userdata)
4041: # Flush the course logs so reverse user roles immediately updated
4042: &Apache::lonnet::flushcourselogs();
4043: $r->print("</p>\n<p>\n".&mt('Processed [quant,_1,user].',$counts{'user'}).
4044: "</p>\n");
4045: if ($counts{'role'} > 0) {
4046: $r->print("<p>\n".
4047: &mt('Roles added for [quant,_1,user].',$counts{'role'}).' '.&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.')."</p>\n");
4048: } else {
4049: $r->print('<p>'.&mt('No roles added').'</p>');
4050: }
4051: if ($counts{'auth'} > 0) {
4052: $r->print("<p>\n".
4053: &mt('Authentication changed for [_1] existing users.',
4054: $counts{'auth'})."</p>\n");
4055: }
4056: $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules));
4057: #####################################
4058: # Display list of students to drop #
4059: #####################################
4060: if ($env{'form.fullup'} eq 'yes') {
4061: $r->print('<h3>'.&mt('Students to Drop')."</h3>\n");
4062: # Get current classlist
4063: my $classlist = &Apache::loncoursedata::get_classlist();
4064: if (! defined($classlist)) {
4065: $r->print('<form name="studentform" method="post" action="/adm/createuser" />'.
4066: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'.
4067: &mt('There are no students with current/future access to the course.').
4068: '</form>'."\n");
4069: } elsif (ref($classlist) eq 'HASH') {
4070: # Remove the students we just added from the list of students.
4071: foreach my $line (@userdata) {
4072: my %entries=&Apache::loncommon::record_sep($line);
4073: unless (($entries{$fields{'username'}} eq '') ||
4074: (!defined($entries{$fields{'username'}}))) {
4075: delete($classlist->{$entries{$fields{'username'}}.
4076: ':'.$domain});
4077: }
4078: }
4079: # Print out list of dropped students.
4080: &show_drop_list($r,$classlist,'nosort',$permission);
4081: }
4082: }
4083: } # end of unless
4084: if ($env{'form.fullup'} ne 'yes') {
4085: $r->print('</form>');
4086: }
4087: }
4088:
4089: sub print_namespacing_alerts {
4090: my ($domain,$alerts,$curr_rules) = @_;
4091: my $output;
4092: if (ref($alerts) eq 'HASH') {
4093: if (keys(%{$alerts}) > 0) {
4094: if (ref($alerts->{'username'}) eq 'HASH') {
4095: foreach my $dom (sort(keys(%{$alerts->{'username'}}))) {
4096: my $count;
4097: if (ref($alerts->{'username'}{$dom}) eq 'HASH') {
4098: $count = keys(%{$alerts->{'username'}{$dom}});
4099: }
4100: my $domdesc = &Apache::lonnet::domain($domain,'description');
4101: if (ref($curr_rules->{$dom}) eq 'HASH') {
4102: $output .= &Apache::loncommon::instrule_disallow_msg(
4103: 'username',$domdesc,$count,'upload');
4104: }
4105: $output .= &Apache::loncommon::user_rule_formats($dom,
4106: $domdesc,$curr_rules->{$dom}{'username'},
4107: 'username');
4108: }
4109: }
4110: if (ref($alerts->{'id'}) eq 'HASH') {
4111: foreach my $dom (sort(keys(%{$alerts->{'id'}}))) {
4112: my $count;
4113: if (ref($alerts->{'id'}{$dom}) eq 'HASH') {
4114: $count = keys(%{$alerts->{'id'}{$dom}});
4115: }
4116: my $domdesc = &Apache::lonnet::domain($domain,'description');
4117: if (ref($curr_rules->{$dom}) eq 'HASH') {
4118: $output .= &Apache::loncommon::instrule_disallow_msg(
4119: 'id',$domdesc,$count,'upload');
4120: }
4121: $output .= &Apache::loncommon::user_rule_formats($dom,
4122: $domdesc,$curr_rules->{$dom}{'id'},'id');
4123: }
4124: }
4125: }
4126: }
4127: }
4128:
4129: sub user_change_result {
4130: my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc,
4131: $username,$userdomain,$userchg) = @_;
4132: my $okresult = 0;
4133: if ($userresult ne 'ok') {
4134: if ($userresult =~ /^error:(.+)$/) {
4135: my $error = $1;
4136: $r->print('<br />'.
4137: &mt('[_1]: Unable to add/modify: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
4138: }
4139: } else {
4140: $counts->{'user'} ++;
4141: $okresult = 1;
4142: }
4143: if ($authresult ne 'ok') {
4144: if ($authresult =~ /^error:(.+)$/) {
4145: my $error = $1;
4146: $r->print('<br />'.
4147: &mt('[_1]: Unable to modify authentication: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
4148: }
4149: } else {
4150: $counts->{'auth'} ++;
4151: $okresult = 1;
4152: }
4153: if ($roleresult ne 'ok') {
4154: if ($roleresult =~ /^error:(.+)$/) {
4155: my $error = $1;
4156: $r->print('<br />'.
4157: &mt('[_1]: Unable to add role: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
4158: }
4159: } else {
4160: $counts->{'role'} ++;
4161: $okresult = 1;
4162: }
4163: if ($okresult) {
4164: $flushc++;
4165: $userchg->{$username.':'.$userdomain}=1;
4166: $r->print('. ');
4167: if ($flushc>15) {
4168: $r->rflush;
4169: $flushc=0;
4170: }
4171: }
4172: if ($idresult) {
4173: $r->print($idresult);
4174: }
4175: return $flushc;
4176: }
4177:
4178: # ========================================================= Menu Phase Two Drop
4179: sub print_drop_menu {
4180: my ($r,$context,$permission) = @_;
4181: $r->print('<h3>'.&mt("Drop Students").'</h3>'."\n".
4182: '<form name="studentform" method="post">'."\n");
4183: my $classlist = &Apache::loncoursedata::get_classlist();
4184: if (! defined($classlist)) {
4185: $r->print(&mt('There are no students currently enrolled.')."\n");
4186: } else {
4187: &show_drop_list($r,$classlist,'nosort',$permission);
4188: }
4189: $r->print('</form>'. &Apache::loncommon::end_page());
4190: return;
4191: }
4192:
4193: # ================================================================== Phase four
4194:
4195: sub update_user_list {
4196: my ($r,$context,$setting,$choice) = @_;
4197: my $now = time;
4198: my $count=0;
4199: my @changelist;
4200: if ($choice eq 'drop') {
4201: @changelist = &Apache::loncommon::get_env_multiple('form.droplist');
4202: } else {
4203: @changelist = &Apache::loncommon::get_env_multiple('form.actionlist');
4204: }
4205: my %result_text = ( ok => { 'revoke' => 'Revoked',
4206: 'delete' => 'Deleted',
4207: 'reenable' => 'Re-enabled',
4208: 'activate' => 'Activated',
4209: 'chgdates' => 'Changed Access Dates for',
4210: 'chgsec' => 'Changed section for',
4211: 'drop' => 'Dropped',
4212: },
4213: error => {'revoke' => 'revoking',
4214: 'delete' => 'deleting',
4215: 'reenable' => 're-enabling',
4216: 'activate' => 'activating',
4217: 'chgdates' => 'changing access dates for',
4218: 'chgsec' => 'changing section for',
4219: 'drop' => 'dropping',
4220: },
4221: );
4222: my ($startdate,$enddate);
4223: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
4224: ($startdate,$enddate) = &get_dates_from_form();
4225: }
4226: foreach my $item (@changelist) {
4227: my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,@sections,
4228: $scopestem);
4229: if ($choice eq 'drop') {
4230: ($uname,$udom,$sec) = split(/:/,$item,-1);
4231: $role = 'st';
4232: $cid = $env{'request.course.id'};
4233: $scopestem = '/'.$cid;
4234: $scopestem =~s/\_/\//g;
4235: if ($sec eq '') {
4236: $scope = $scopestem;
4237: } else {
4238: $scope = $scopestem.'/'.$sec;
4239: }
4240: } elsif ($context eq 'course') {
4241: ($uname,$udom,$role,$sec,$type,$locktype) = split(/\:/,$item,-1);
4242: $cid = $env{'request.course.id'};
4243: $scopestem = '/'.$cid;
4244: $scopestem =~s/\_/\//g;
4245: if ($sec eq '') {
4246: $scope = $scopestem;
4247: } else {
4248: $scope = $scopestem.'/'.$sec;
4249: }
4250: } elsif ($context eq 'author') {
4251: ($uname,$udom,$role) = split(/\:/,$item,-1);
4252: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
4253: } elsif ($context eq 'domain') {
4254: if ($setting eq 'domain') {
4255: ($role,$uname,$udom) = split(/\:/,$item,-1);
4256: $scope = '/'.$env{'request.role.domain'}.'/';
4257: } elsif ($setting eq 'author') {
4258: ($uname,$udom,$role,$scope) = split(/\:/,$item);
4259: } elsif ($setting eq 'course') {
4260: ($uname,$udom,$role,$cid,$sec,$type,$locktype) =
4261: split(/\:/,$item);
4262: $scope = '/'.$cid;
4263: $scope =~s/\_/\//g;
4264: if ($sec ne '') {
4265: $scope .= '/'.$sec;
4266: }
4267: }
4268: }
4269: my $plrole = &Apache::lonnet::plaintext($role);
4270: my $start = $env{'form.'.$item.'_start'};
4271: my $end = $env{'form.'.$item.'_end'};
4272: if ($choice eq 'drop') {
4273: # drop students
4274: $end = $now;
4275: $type = 'manual';
4276: $result =
4277: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
4278: } elsif ($choice eq 'revoke') {
4279: # revoke or delete user role
4280: $end = $now;
4281: if ($role eq 'st') {
4282: $result =
4283: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
4284: } else {
4285: $result =
4286: &Apache::lonnet::revokerole($udom,$uname,$scope,$role,
4287: '','',$context);
4288: }
4289: } elsif ($choice eq 'delete') {
4290: if ($role eq 'st') {
4291: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid,'',$context);
4292: }
4293: $result =
4294: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
4295: $start,1,'',$context);
4296: } else {
4297: #reenable, activate, change access dates or change section
4298: if ($choice ne 'chgsec') {
4299: $start = $startdate;
4300: $end = $enddate;
4301: }
4302: if ($choice eq 'reenable') {
4303: if ($role eq 'st') {
4304: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
4305: } else {
4306: $result =
4307: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
4308: $now,'','',$context);
4309: }
4310: } elsif ($choice eq 'activate') {
4311: if ($role eq 'st') {
4312: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
4313: } else {
4314: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
4315: $now,'','',$context);
4316: }
4317: } elsif ($choice eq 'chgdates') {
4318: if ($role eq 'st') {
4319: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
4320: } else {
4321: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
4322: $start,'','',$context);
4323: }
4324: } elsif ($choice eq 'chgsec') {
4325: my (@newsecs,$revresult,$nochg,@retained);
4326: if ($role ne 'cc') {
4327: @newsecs = split(/,/,$env{'form.newsecs'});
4328: }
4329: # remove existing section if not to be retained.
4330: if (!$env{'form.retainsec'}) {
4331: if ($sec eq '') {
4332: if (@newsecs == 0) {
4333: $result = &mt('No change in section assignment (none)');
4334: $nochg = 1;
4335: } else {
4336: $revresult =
4337: &Apache::lonnet::revokerole($udom,$uname,
4338: $scope,$role,
4339: '','',$context);
4340: }
4341: } else {
4342: if (@newsecs > 0) {
4343: if (grep(/^\Q$sec\E$/,@newsecs)) {
4344: push(@retained,$sec);
4345: } else {
4346: $revresult =
4347: &Apache::lonnet::revokerole($udom,$uname,
4348: $scope,$role,
4349: '','',$context);
4350: }
4351: } else {
4352: $revresult =
4353: &Apache::lonnet::revokerole($udom,$uname,
4354: $scope,$role,
4355: '','',$context);
4356: }
4357: }
4358: } else {
4359: if ($sec eq '') {
4360: $nochg = 1;
4361: } else {
4362: push(@retained,$sec);
4363: }
4364: }
4365: # add new sections
4366: if (@newsecs == 0) {
4367: if (!$nochg) {
4368: if ($role eq 'st') {
4369: $result =
4370: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context);
4371: } else {
4372: my $newscope = $scopestem;
4373: $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start,'','',$context);
4374: }
4375: }
4376: } else {
4377: foreach my $newsec (@newsecs) {
4378: if (!grep(/^\Q$newsec\E$/,@retained)) {
4379: if ($role eq 'st') {
4380: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context);
4381: } else {
4382: my $newscope = $scopestem;
4383: if ($newsec ne '') {
4384: $newscope .= '/'.$newsec;
4385: }
4386: $result = &Apache::lonnet::assignrole($udom,$uname,
4387: $newscope,$role,$end,$start);
4388: }
4389: }
4390: }
4391: }
4392: }
4393: }
4394: my $extent = $scope;
4395: if ($choice eq 'drop' || $context eq 'course') {
4396: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
4397: if ($cdesc) {
4398: $extent = $cdesc;
4399: }
4400: }
4401: if ($result eq 'ok' || $result eq 'ok:') {
4402: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for [_3]",
4403: $plrole,$extent,$uname.':'.$udom).'<br />');
4404: $count++;
4405: } else {
4406: $r->print(
4407: &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for [_3]: [_4].",
4408: $plrole,$extent,$uname.':'.$udom,$result).'<br />');
4409: }
4410: }
4411: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n");
4412: if ($choice eq 'drop') {
4413: $r->print('<input type="hidden" name="action" value="listusers" />'."\n".
4414: '<input type="hidden" name="Status" value="Active" />'."\n".
4415: '<input type="hidden" name="showrole" value="st" />'."\n");
4416: } else {
4417: foreach my $item ('action','sortby','roletype','showrole','Status','secfilter','grpfilter') {
4418: if ($env{'form.'.$item} ne '') {
4419: $r->print('<input type="hidden" name="'.$item.'" value="'.$env{'form.'.$item}.
4420: '" />'."\n");
4421: }
4422: }
4423: }
4424: $r->print('<p><b>'.&mt("$result_text{'ok'}{$choice} role(s) for [quant,_1,user,users,no users].",$count).'</b></p>');
4425: if ($count > 0) {
4426: if ($choice eq 'revoke' || $choice eq 'drop') {
4427: $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.').'</p>');
4428: }
4429: # Flush the course logs so reverse user roles immediately updated
4430: &Apache::lonnet::flushcourselogs();
4431: }
4432: if ($env{'form.makedatesdefault'}) {
4433: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
4434: $r->print(&make_dates_default($startdate,$enddate,$context));
4435: }
4436: }
4437: my $linktext = &mt('Display User Lists');
4438: if ($choice eq 'drop') {
4439: $linktext = &mt('Display current class roster');
4440: }
4441: $r->print('<a href="javascript:document.studentform.submit()">'.$linktext.'</a></form>'."\n");
4442: }
4443:
4444: sub classlist_drop {
4445: my ($scope,$uname,$udom,$now) = @_;
4446: my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
4447: if (&Apache::lonnet::is_course($cdom,$cnum)) {
4448: if (!&active_student_roles($cnum,$cdom,$uname,$udom)) {
4449: my %user;
4450: my $result = &update_classlist($cdom,$cnum,$udom,$uname,\%user,$now);
4451: return &mt('Drop from classlist: [_1]',
4452: '<b>'.$result.'</b>').'<br />';
4453: }
4454: }
4455: }
4456:
4457: sub active_student_roles {
4458: my ($cnum,$cdom,$uname,$udom) = @_;
4459: my %roles =
4460: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
4461: ['future','active'],['st']);
4462: return exists($roles{"$cnum:$cdom:st"});
4463: }
4464:
4465: sub section_check_js {
4466: my $groupslist= &get_groupslist();
4467: return <<"END";
4468: function validate(caller) {
4469: var groups = new Array($groupslist);
4470: var secname = caller.value;
4471: if ((secname == 'all') || (secname == 'none')) {
4472: alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
4473: return 'error';
4474: }
4475: if (secname != '') {
4476: for (var k=0; k<groups.length; k++) {
4477: if (secname == groups[k]) {
4478: alert("'"+secname+"' may not be used as the name for a section, as it is the name of a course group.\\nSection names and group names must be distinct. Please choose a different section name.");
4479: return 'error';
4480: }
4481: }
4482: }
4483: return 'ok';
4484: }
4485: END
4486: }
4487:
4488: sub set_login {
4489: my ($dom,$authformkrb,$authformint,$authformloc) = @_;
4490: my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
4491: my $response;
4492: my ($authnum,%can_assign) =
4493: &Apache::loncommon::get_assignable_auth($dom);
4494: if ($authnum) {
4495: $response = &Apache::loncommon::start_data_table();
4496: if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
4497: $response .= &Apache::loncommon::start_data_table_row().
4498: '<td>'.$authformkrb.'</td>'.
4499: &Apache::loncommon::end_data_table_row()."\n";
4500: }
4501: if ($can_assign{'int'}) {
4502: $response .= &Apache::loncommon::start_data_table_row().
4503: '<td>'.$authformint.'</td>'.
4504: &Apache::loncommon::end_data_table_row()."\n"
4505: }
4506: if ($can_assign{'loc'}) {
4507: $response .= &Apache::loncommon::start_data_table_row().
4508: '<td>'.$authformloc.'</td>'.
4509: &Apache::loncommon::end_data_table_row()."\n";
4510: }
4511: $response .= &Apache::loncommon::end_data_table();
4512: }
4513: return $response;
4514: }
4515:
4516: sub course_sections {
4517: my ($sections_count,$role,$current_sec) = @_;
4518: my $output = '';
4519: my @sections = (sort {$a <=> $b} keys %{$sections_count});
4520: my $numsec = scalar(@sections);
4521: my $is_selected = ' selected="selected"';
4522: if ($numsec <= 1) {
4523: $output = '<select name="currsec_'.$role.'" >'."\n".
4524: ' <option value="">'.&mt('Select').'</option>'."\n";
4525: if ($current_sec eq 'none') {
4526: $output .=
4527: ' <option value=""'.$is_selected.'>'.&mt('No section').'</option>'."\n";
4528: } else {
4529: $output .=
4530: ' <option value="">'.&mt('No section').'</option>'."\n";
4531: }
4532: if ($numsec == 1) {
4533: if ($current_sec eq $sections[0]) {
4534: $output .=
4535: ' <option value="'.$sections[0].'"'.$is_selected.'>'.$sections[0].'</option>'."\n";
4536: } else {
4537: $output .=
4538: ' <option value="'.$sections[0].'" >'.$sections[0].'</option>'."\n";
4539: }
4540: }
4541: } else {
4542: $output = '<select name="currsec_'.$role.'" ';
4543: my $multiple = 4;
4544: if (scalar(@sections) < 4) { $multiple = scalar(@sections); }
4545: if ($role eq 'st') {
4546: $output .= '>'."\n".
4547: ' <option value="">'.&mt('Select').'</option>'."\n";
4548: if ($current_sec eq 'none') {
4549: $output .=
4550: ' <option value=""'.$is_selected.'>'.&mt('No section')."</option>\n";
4551: } else {
4552: $output .=
4553: ' <option value="">'.&mt('No section')."</option>\n";
4554: }
4555: } else {
4556: $output .= 'multiple="multiple" size="'.$multiple.'">'."\n";
4557: }
4558: foreach my $sec (@sections) {
4559: if ($current_sec eq $sec) {
4560: $output .= '<option value="'.$sec.'"'.$is_selected.'>'.$sec."</option>\n";
4561: } else {
4562: $output .= '<option value="'.$sec.'">'.$sec."</option>\n";
4563: }
4564: }
4565: }
4566: $output .= '</select>';
4567: return $output;
4568: }
4569:
4570: sub get_groupslist {
4571: my $groupslist;
4572: my %curr_groups = &Apache::longroup::coursegroups();
4573: if (%curr_groups) {
4574: $groupslist = join('","',sort(keys(%curr_groups)));
4575: $groupslist = '"'.$groupslist.'"';
4576: }
4577: return $groupslist;
4578: }
4579:
4580: sub setsections_javascript {
4581: my ($formname,$groupslist,$mode,$checkauth) = @_;
4582: my ($checkincluded,$finish,$rolecode,$setsection_js);
4583: if ($mode eq 'upload') {
4584: $checkincluded = 'formname.name == "'.$formname.'"';
4585: $finish = "return 'ok';";
4586: $rolecode = "var role = formname.defaultrole.options[formname.defaultrole.selectedIndex].value;\n";
4587: } elsif ($formname eq 'cu') {
4588: $checkincluded = 'formname.elements[i-1].checked == true';
4589: if ($checkauth) {
4590: $finish = "var authcheck = auth_check();\n".
4591: " if (authcheck == 'ok') {\n".
4592: " formname.submit();\n".
4593: " }\n";
4594: } else {
4595: $finish = 'formname.submit()';
4596: }
4597: $rolecode = "var match = str.split('_');
4598: var role = match[3];\n";
4599: } elsif ($formname eq 'enrollstudent') {
4600: $checkincluded = 'formname.name == "'.$formname.'"';
4601: if ($checkauth) {
4602: $finish = "var authcheck = auth_check();\n".
4603: " if (authcheck == 'ok') {\n".
4604: " formname.submit();\n".
4605: " }\n";
4606: } else {
4607: $finish = 'formname.submit()';
4608: }
4609: $rolecode = "var match = str.split('_');
4610: var role = match[1];\n";
4611: } else {
4612: $checkincluded = 'formname.name == "'.$formname.'"';
4613: $finish = "seccheck = 'ok';";
4614: $rolecode = "var match = str.split('_');
4615: var role = match[1];\n";
4616: $setsection_js = "var seccheck = 'alert';";
4617: }
4618: my %alerts = &Apache::lonlocal::texthash(
4619: secd => 'Section designations do not apply to Course Coordinator roles.',
4620: accr => 'A course coordinator role will be added with access to all sections.',
4621: inea => 'In each course, each user may only have one student role at a time.',
4622: youh => 'You had selected ',
4623: secs => 'sections.',
4624: plmo => 'Please modify your selections so they include no more than one section.',
4625: mayn => 'may not be used as the name for a section, as it is a reserved word.',
4626: plch => 'Please choose a different section name.',
4627: mnot => 'may not be used as a section name, as it is the name of a course group.',
4628: secn => 'Section names and group names must be distinct. Please choose a different section name.',
4629: );
4630: $setsection_js .= <<"ENDSECCODE";
4631:
4632: function setSections(formname) {
4633: var re1 = /^currsec_/;
4634: var groups = new Array($groupslist);
4635: for (var i=0;i<formname.elements.length;i++) {
4636: var str = formname.elements[i].name;
4637: var checkcurr = str.match(re1);
4638: if (checkcurr != null) {
4639: if ($checkincluded) {
4640: $rolecode
4641: if (role == 'cc') {
4642: alert("$alerts{'secd'}\\n$alerts{'accr'}");
4643: }
4644: else {
4645: var sections = '';
4646: var numsec = 0;
4647: var sections;
4648: for (var j=0; j<formname.elements[i].length; j++) {
4649: if (formname.elements[i].options[j].selected == true ) {
4650: if (formname.elements[i].options[j].value != "") {
4651: if (numsec == 0) {
4652: if (formname.elements[i].options[j].value != "") {
4653: sections = formname.elements[i].options[j].value;
4654: numsec ++;
4655: }
4656: }
4657: else {
4658: sections = sections + "," + formname.elements[i].options[j].value
4659: numsec ++;
4660: }
4661: }
4662: }
4663: }
4664: if (numsec > 0) {
4665: if (formname.elements[i+1].value != "" && formname.elements[i+1].value != null) {
4666: sections = sections + "," + formname.elements[i+1].value;
4667: }
4668: }
4669: else {
4670: sections = formname.elements[i+1].value;
4671: }
4672: var newsecs = formname.elements[i+1].value;
4673: var numsplit;
4674: if (newsecs != null && newsecs != "") {
4675: numsplit = newsecs.split(/,/g);
4676: numsec = numsec + numsplit.length;
4677: }
4678:
4679: if ((role == 'st') && (numsec > 1)) {
4680: alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}")
4681: return;
4682: }
4683: else {
4684: if (numsplit != null) {
4685: for (var j=0; j<numsplit.length; j++) {
4686: if ((numsplit[j] == 'all') ||
4687: (numsplit[j] == 'none')) {
4688: alert("'"+numsplit[j]+"' $alerts{'mayn'}\\n$alerts{'plch'}");
4689: return;
4690: }
4691: for (var k=0; k<groups.length; k++) {
4692: if (numsplit[j] == groups[k]) {
4693: alert("'"+numsplit[j]+"' $alerts{'mnot'}\\n$alerts{'secn'}");
4694: return;
4695: }
4696: }
4697: }
4698: }
4699: formname.elements[i+2].value = sections;
4700: }
4701: }
4702: }
4703: }
4704: }
4705: $finish
4706: }
4707: ENDSECCODE
4708: return $setsection_js;
4709: }
4710:
4711: sub can_create_user {
4712: my ($dom,$context,$usertype) = @_;
4713: my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
4714: my $cancreate = 1;
4715: if (&Apache::lonnet::allowed('mau',$dom)) {
4716: return $cancreate;
4717: }
4718: if (ref($domconf{'usercreation'}) eq 'HASH') {
4719: if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') {
4720: if ($context eq 'course' || $context eq 'author') {
4721: my $creation = $domconf{'usercreation'}{'cancreate'}{$context};
4722: if ($creation eq 'none') {
4723: $cancreate = 0;
4724: } elsif ($creation ne 'any') {
4725: if (defined($usertype)) {
4726: if ($creation ne $usertype) {
4727: $cancreate = 0;
4728: }
4729: }
4730: }
4731: }
4732: }
4733: }
4734: return $cancreate;
4735: }
4736:
4737: sub can_modify_userinfo {
4738: my ($context,$dom,$fields,$userroles) = @_;
4739: my %domconfig =
4740: &Apache::lonnet::get_dom('configuration',['usermodification'],
4741: $dom);
4742: my %canmodify;
4743: if (ref($fields) eq 'ARRAY') {
4744: foreach my $field (@{$fields}) {
4745: $canmodify{$field} = 0;
4746: if (&Apache::lonnet::allowed('mau',$dom)) {
4747: $canmodify{$field} = 1;
4748: } else {
4749: if (ref($domconfig{'usermodification'}) eq 'HASH') {
4750: if (ref($domconfig{'usermodification'}{$context}) eq 'HASH') {
4751: if (ref($userroles) eq 'ARRAY') {
4752: foreach my $role (@{$userroles}) {
4753: my $testrole;
4754: if ($context eq 'selfcreate') {
4755: $testrole = $role;
4756: } else {
4757: if ($role =~ /^cr\//) {
4758: $testrole = 'cr';
4759: } else {
4760: $testrole = $role;
4761: }
4762: }
4763: if (ref($domconfig{'usermodification'}{$context}{$testrole}) eq 'HASH') {
4764: if ($domconfig{'usermodification'}{$context}{$testrole}{$field}) {
4765: $canmodify{$field} = 1;
4766: last;
4767: }
4768: }
4769: }
4770: } else {
4771: foreach my $key (keys(%{$domconfig{'usermodification'}{$context}})) {
4772: if (ref($domconfig{'usermodification'}{$context}{$key}) eq 'HASH') {
4773: if ($domconfig{'usermodification'}{$context}{$key}{$field}) {
4774: $canmodify{$field} = 1;
4775: last;
4776: }
4777: }
4778: }
4779: }
4780: }
4781: } elsif ($context eq 'course') {
4782: if (ref($userroles) eq 'ARRAY') {
4783: if (grep(/^st$/,@{$userroles})) {
4784: $canmodify{$field} = 1;
4785: }
4786: } else {
4787: $canmodify{$field} = 1;
4788: }
4789: }
4790: }
4791: }
4792: }
4793: return %canmodify;
4794: }
4795:
4796: sub check_usertype {
4797: my ($dom,$uname,$rules) = @_;
4798: my $usertype;
4799: if (ref($rules) eq 'HASH') {
4800: my @user_rules = keys(%{$rules});
4801: if (@user_rules > 0) {
4802: my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
4803: if (keys(%rule_check) > 0) {
4804: $usertype = 'unofficial';
4805: foreach my $item (keys(%rule_check)) {
4806: if ($rule_check{$item}) {
4807: $usertype = 'official';
4808: last;
4809: }
4810: }
4811: }
4812: }
4813: }
4814: return $usertype;
4815: }
4816:
4817: sub roles_by_context {
4818: my ($context,$custom) = @_;
4819: my @allroles;
4820: if ($context eq 'course') {
4821: @allroles = ('st','ad','ta','ep','in','cc');
4822: if ($custom) {
4823: push(@allroles,'cr');
4824: }
4825: } elsif ($context eq 'author') {
4826: @allroles = ('ca','aa');
4827: } elsif ($context eq 'domain') {
4828: @allroles = ('li','dg','sc','au','dc');
4829: }
4830: return @allroles;
4831: }
4832:
4833: sub get_permission {
4834: my ($context,$roles) = @_;
4835: my %permission;
4836: if ($context eq 'course') {
4837: my $custom = 1;
4838: my @allroles = &roles_by_context($context,$custom);
4839: foreach my $role (@allroles) {
4840: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
4841: $permission{'cusr'} = 1;
4842: last;
4843: }
4844: }
4845: if (&Apache::lonnet::allowed('ccr',$env{'request.course.id'})) {
4846: $permission{'custom'} = 1;
4847: }
4848: if (&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) {
4849: $permission{'view'} = 1;
4850: }
4851: if (!$permission{'view'}) {
4852: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
4853: $permission{'view'} = &Apache::lonnet::allowed('vcl',$scope);
4854: if ($permission{'view'}) {
4855: $permission{'view_section'} = $env{'request.course.sec'};
4856: }
4857: }
4858: if (!$permission{'cusr'}) {
4859: if ($env{'request.course.sec'} ne '') {
4860: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
4861: $permission{'cusr'} = (&Apache::lonnet::allowed('cst',$scope));
4862: if ($permission{'cusr'}) {
4863: $permission{'cusr_section'} = $env{'request.course.sec'};
4864: }
4865: }
4866: }
4867: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4868: $permission{'grp_manage'} = 1;
4869: }
4870: } elsif ($context eq 'author') {
4871: $permission{'cusr'} = &authorpriv($env{'user.name'},$env{'request.role.domain'});
4872: $permission{'view'} = $permission{'cusr'};
4873: } else {
4874: my @allroles = &roles_by_context($context);
4875: foreach my $role (@allroles) {
4876: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
4877: $permission{'cusr'} = 1;
4878: last;
4879: }
4880: }
4881: if (!$permission{'cusr'}) {
4882: if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) {
4883: $permission{'cusr'} = 1;
4884: }
4885: }
4886: if (&Apache::lonnet::allowed('ccr',$env{'request.role.domain'})) {
4887: $permission{'custom'} = 1;
4888: }
4889: $permission{'view'} = $permission{'cusr'};
4890: }
4891: my $allowed = 0;
4892: foreach my $perm (values(%permission)) {
4893: if ($perm) { $allowed=1; last; }
4894: }
4895: return (\%permission,$allowed);
4896: }
4897:
4898: # ==================================================== Figure out author access
4899:
4900: sub authorpriv {
4901: my ($auname,$audom)=@_;
4902: unless ((&Apache::lonnet::allowed('cca',$audom.'/'.$auname))
4903: || (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } return 1;
4904: }
4905:
4906: sub roles_on_upload {
4907: my ($context,$setting,%customroles) = @_;
4908: my (@possible_roles,@permitted_roles);
4909: @possible_roles = &curr_role_permissions($context,$setting,1);
4910: foreach my $role (@possible_roles) {
4911: if ($role eq 'cr') {
4912: push(@permitted_roles,keys(%customroles));
4913: } else {
4914: push(@permitted_roles,$role);
4915: }
4916: }
4917: return @permitted_roles;
4918: }
4919:
4920: sub get_course_identity {
4921: my ($cid) = @_;
4922: my ($cnum,$cdom,$cdesc);
4923: if ($cid eq '') {
4924: $cid = $env{'request.course.id'}
4925: }
4926: if ($cid ne '') {
4927: $cnum = $env{'course.'.$cid.'.num'};
4928: $cdom = $env{'course.'.$cid.'.domain'};
4929: $cdesc = $env{'course.'.$cid.'.description'};
4930: if ($cnum eq '' || $cdom eq '') {
4931: my %coursehash =
4932: &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
4933: $cdom = $coursehash{'domain'};
4934: $cnum = $coursehash{'num'};
4935: $cdesc = $coursehash{'description'};
4936: }
4937: }
4938: return ($cnum,$cdom,$cdesc);
4939: }
4940:
4941: sub dc_setcourse_js {
4942: my ($formname,$mode,$context) = @_;
4943: my ($dc_setcourse_code,$authen_check);
4944: my $cctext = &Apache::lonnet::plaintext('cc');
4945: my %alerts = §ioncheck_alerts();
4946: my $role = 'role';
4947: if ($mode eq 'upload') {
4948: $role = 'courserole';
4949: } else {
4950: $authen_check = &verify_authen($formname,$context);
4951: }
4952: $dc_setcourse_code = (<<"SCRIPTTOP");
4953: $authen_check
4954:
4955: function setCourse() {
4956: var course = document.$formname.dccourse.value;
4957: if (course != "") {
4958: if (document.$formname.dcdomain.value != document.$formname.origdom.value) {
4959: alert("$alerts{'curd'}");
4960: return;
4961: }
4962: var userrole = document.$formname.$role.options[document.$formname.$role.selectedIndex].value
4963: var section="";
4964: var numsections = 0;
4965: var newsecs = new Array();
4966: for (var i=0; i<document.$formname.currsec.length; i++) {
4967: if (document.$formname.currsec.options[i].selected == true ) {
4968: if (document.$formname.currsec.options[i].value != "" && document.$formname.currsec.options[i].value != null) {
4969: if (numsections == 0) {
4970: section = document.$formname.currsec.options[i].value
4971: numsections = 1;
4972: }
4973: else {
4974: section = section + "," + document.$formname.currsec.options[i].value
4975: numsections ++;
4976: }
4977: }
4978: }
4979: }
4980: if (document.$formname.newsec.value != "" && document.$formname.newsec.value != null) {
4981: if (numsections == 0) {
4982: section = document.$formname.newsec.value
4983: }
4984: else {
4985: section = section + "," + document.$formname.newsec.value
4986: }
4987: newsecs = document.$formname.newsec.value.split(/,/g);
4988: numsections = numsections + newsecs.length;
4989: }
4990: if ((userrole == 'st') && (numsections > 1)) {
4991: alert("$alerts{'inea'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
4992: return;
4993: }
4994: for (var j=0; j<newsecs.length; j++) {
4995: if ((newsecs[j] == 'all') || (newsecs[j] == 'none')) {
4996: alert("'"+newsecs[j]+"' $alerts{'mayn'}.\\n$alerts{'plsc'}.");
4997: return;
4998: }
4999: if (document.$formname.groups.value != '') {
5000: var groups = document.$formname.groups.value.split(/,/g);
5001: for (var k=0; k<groups.length; k++) {
5002: if (newsecs[j] == groups[k]) {
5003: alert("'"+newsecs[j]+"' $alerts{'mayt'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
5004: return;
5005: }
5006: }
5007: }
5008: }
5009: if ((userrole == 'cc') && (numsections > 0)) {
5010: alert("$alerts{'secd'} $cctext $alerts{'role'}.\\n$alerts{'accr'}.");
5011: section = "";
5012: }
5013: SCRIPTTOP
5014: if ($mode ne 'upload') {
5015: $dc_setcourse_code .= (<<"ENDSCRIPT");
5016: var coursename = "_$env{'request.role.domain'}"+"_"+course+"_"+userrole
5017: var numcourse = getIndex(document.$formname.dccourse);
5018: if (numcourse == "-1") {
5019: alert("$alerts{'thwa'}");
5020: return;
5021: }
5022: else {
5023: document.$formname.elements[numcourse].name = "act"+coursename;
5024: var numnewsec = getIndex(document.$formname.newsec);
5025: if (numnewsec != "-1") {
5026: document.$formname.elements[numnewsec].name = "sec"+coursename;
5027: document.$formname.elements[numnewsec].value = section;
5028: }
5029: var numstart = getIndex(document.$formname.start);
5030: if (numstart != "-1") {
5031: document.$formname.elements[numstart].name = "start"+coursename;
5032: }
5033: var numend = getIndex(document.$formname.end);
5034: if (numend != "-1") {
5035: document.$formname.elements[numend].name = "end"+coursename
5036: }
5037: }
5038: }
5039: var authcheck = auth_check();
5040: if (authcheck == 'ok') {
5041: document.$formname.submit();
5042: }
5043: }
5044: ENDSCRIPT
5045: } else {
5046: $dc_setcourse_code .= "
5047: document.$formname.sections.value = section;
5048: }
5049: return 'ok';
5050: }
5051: ";
5052: }
5053: $dc_setcourse_code .= (<<"ENDSCRIPT");
5054:
5055: function getIndex(caller) {
5056: for (var i=0;i<document.$formname.elements.length;i++) {
5057: if (document.$formname.elements[i] == caller) {
5058: return i;
5059: }
5060: }
5061: return -1;
5062: }
5063: ENDSCRIPT
5064: return $dc_setcourse_code;
5065: }
5066:
5067: sub verify_authen {
5068: my ($formname,$context) = @_;
5069: my %alerts = &authcheck_alerts();
5070: my $finish = "return 'ok';";
5071: if ($context eq 'author') {
5072: $finish = "document.$formname.submit();";
5073: }
5074: my $outcome = <<"ENDSCRIPT";
5075:
5076: function auth_check() {
5077: var logintype;
5078: if (document.$formname.login.length) {
5079: if (document.$formname.login.length > 0) {
5080: var loginpicked = 0;
5081: for (var i=0; i<document.$formname.login.length; i++) {
5082: if (document.$formname.login[i].checked == true) {
5083: loginpicked = 1;
5084: logintype = document.$formname.login[i].value;
5085: }
5086: }
5087: if (loginpicked == 0) {
5088: alert("$alerts{'authen'}");
5089: return;
5090: }
5091: }
5092: } else {
5093: logintype = document.$formname.login.value;
5094: }
5095: if (logintype == 'nochange') {
5096: return 'ok';
5097: }
5098: var argpicked = document.$formname.elements[logintype+'arg'].value;
5099: if ((argpicked == null) || (argpicked == '') || (typeof argpicked == 'undefined')) {
5100: var alertmsg = '';
5101: switch (logintype) {
5102: case 'krb':
5103: alertmsg = '$alerts{'krb'}';
5104: break;
5105: case 'int':
5106: alertmsg = '$alerts{'ipass'}';
5107: case 'fsys':
5108: alertmsg = '$alerts{'ipass'}';
5109: break;
5110: case 'loc':
5111: alertmsg = '';
5112: break;
5113: default:
5114: alertmsg = '';
5115: }
5116: if (alertmsg != '') {
5117: alert(alertmsg);
5118: return;
5119: }
5120: }
5121: $finish
5122: }
5123: ENDSCRIPT
5124: }
5125:
5126: sub sectioncheck_alerts {
5127: my %alerts = &Apache::lonlocal::texthash(
5128: curd => 'You must select a course in the current domain',
5129: inea => 'In each course, each user may only have one student role at a time',
5130: youh => 'You had selected',
5131: sect => 'sections',
5132: plsm => 'Please modify your selections so they include no more than one section',
5133: mayn => 'may not be used as the name for a section, as it is a reserved word',
5134: plsc => 'Please choose a different section name',
5135: mayt => 'may not be used as the name for a section, as it is the name of a course group',
5136: secn => 'Section names and group names must be distinct',
5137: secd => 'Section designations do not apply to ',
5138: role => 'roles',
5139: accr => 'role will be added with access to all sections',
5140: thwa => 'There was a problem with your course selection'
5141: );
5142: return %alerts;
5143: }
5144:
5145: sub authcheck_alerts {
5146: my %alerts =
5147: &Apache::lonlocal::texthash(
5148: authen => 'You must choose an authentication type.',
5149: krb => 'You need to specify the Kerberos domain.',
5150: ipass => 'You need to specify the initial password.',
5151: );
5152: return %alerts;
5153: }
5154:
5155: 1;
5156:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>