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