File:
[LON-CAPA] /
loncom /
interface /
lonuserutils.pm
Revision
1.178:
download - view:
text,
annotated -
select for diffs
Wed Nov 9 00:32:45 2016 UTC (7 years, 9 months ago) by
raeburn
Branches:
MAIN
CVS tags:
HEAD
- Viewing of class roster and enrollment type is available to roles with 'vcl'
priv (via Automated Enrollment), but without ability to switch auto to
manual, and vice versa, or to lock against changes (via disabled attribute).
1: # The LearningOnline Network with CAPA
2: # Utility functions for managing LON-CAPA user accounts
3: #
4: # $Id: lonuserutils.pm,v 1.178 2016/11/09 00:32:45 raeburn Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: #
28: ###############################################################
29: ###############################################################
30:
31: package Apache::lonuserutils;
32:
33: =pod
34:
35: =head1 NAME
36:
37: Apache::lonuserutils.pm
38:
39: =head1 SYNOPSIS
40:
41: Utilities for management of users and custom roles
42:
43: Provides subroutines called by loncreateuser.pm
44:
45: =head1 OVERVIEW
46:
47: =cut
48:
49: use strict;
50: use Apache::lonnet;
51: use Apache::loncommon();
52: use Apache::lonhtmlcommon;
53: use Apache::lonlocal;
54: use Apache::longroup;
55: use HTML::Entities;
56: use LONCAPA qw(:DEFAULT :match);
57:
58: ###############################################################
59: ###############################################################
60: # Drop student from all sections of a course, except optional $csec
61: sub modifystudent {
62: my ($udom,$unam,$courseid,$csec,$desiredhost,$context)=@_;
63: # if $csec is undefined, drop the student from all the courses matching
64: # this one. If $csec is defined, drop them from all other sections of
65: # this course and add them to section $csec
66: my ($cnum,$cdom) = &get_course_identity($courseid);
67: my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
68: my ($tmp) = keys(%roles);
69: # Bail out if we were unable to get the students roles
70: return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
71: # Go through the roles looking for enrollment in this course
72: my $result = '';
73: foreach my $course (keys(%roles)) {
74: if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
75: # We are in this course
76: my $section=$1;
77: $section='' if ($course eq "/$cdom/$cnum".'_st');
78: if (defined($csec) && $section eq $csec) {
79: $result .= 'ok:';
80: } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
81: my (undef,$end,$start)=split(/\_/,$roles{$course});
82: my $now=time;
83: # if this is an active role
84: if (!($start && ($now<$start)) || !($end && ($now>$end))) {
85: my $reply=&Apache::lonnet::modifystudent
86: # dom name id mode pass f m l g
87: ($udom,$unam,'', '', '',undef,undef,undef,undef,
88: $section,time,undef,undef,$desiredhost,'','manual',
89: '',$courseid,'',$context);
90: $result .= $reply.':';
91: }
92: }
93: }
94: }
95: if ($result eq '') {
96: $result = &mt('Unable to find section for this student');
97: } else {
98: $result =~ s/(ok:)+/ok/g;
99: }
100: return $result;
101: }
102:
103: sub modifyuserrole {
104: my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
105: $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
106: $end,$start,$checkid,$inststatus) = @_;
107: my ($scope,$userresult,$authresult,$roleresult,$idresult);
108: if ($setting eq 'course' || $context eq 'course') {
109: $scope = '/'.$cid;
110: $scope =~ s/\_/\//g;
111: if (($role ne 'cc') && ($role ne 'co') && ($sec ne '')) {
112: $scope .='/'.$sec;
113: }
114: } elsif ($context eq 'domain') {
115: $scope = '/'.$env{'request.role.domain'}.'/';
116: } elsif ($context eq 'author') {
117: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
118: }
119: if ($context eq 'domain') {
120: my $uhome = &Apache::lonnet::homeserver($uname,$udom);
121: if ($uhome ne 'no_host') {
122: if (($changeauth eq 'Yes') && (&Apache::lonnet::allowed('mau',$udom))) {
123: if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
124: ($umode eq 'localauth')) {
125: $authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
126: }
127: }
128: if (($forceid) && (&Apache::lonnet::allowed('mau',$udom)) &&
129: ($env{'form.recurseid'}) && ($checkid)) {
130: my %userupdate = (
131: lastname => $last,
132: middlename => $middle,
133: firstname => $first,
134: generation => $gene,
135: id => $uid,
136: );
137: $idresult = &propagate_id_change($uname,$udom,\%userupdate);
138: }
139: }
140: }
141: $userresult =
142: &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
143: $middle,$last,$gene,$forceid,$desiredhome,
144: $email,$inststatus);
145: if ($userresult eq 'ok') {
146: if ($role ne '') {
147: $role =~ s/_/\//g;
148: $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
149: $role,$end,$start,'',
150: '',$context);
151: }
152: }
153: return ($userresult,$authresult,$roleresult,$idresult);
154: }
155:
156: sub propagate_id_change {
157: my ($uname,$udom,$user) = @_;
158: my (@types,@roles);
159: @types = ('active','future');
160: @roles = ('st');
161: my $idresult;
162: my %roleshash = &Apache::lonnet::get_my_roles($uname,
163: $udom,'userroles',\@types,\@roles);
164: my %args = (
165: one_time => 1,
166: );
167: foreach my $item (keys(%roleshash)) {
168: my ($cnum,$cdom,$role) = split(/:/,$item,-1);
169: my ($start,$end) = split(/:/,$roleshash{$item});
170: if (&Apache::lonnet::is_course($cdom,$cnum)) {
171: my $result = &update_classlist($cdom,$cnum,$udom,$uname,$user);
172: my %coursehash =
173: &Apache::lonnet::coursedescription($cdom.'_'.$cnum,\%args);
174: my $cdesc = $coursehash{'description'};
175: if ($cdesc eq '') {
176: $cdesc = $cdom.'_'.$cnum;
177: }
178: if ($result eq 'ok') {
179: $idresult .= &mt('Classlist update for "[_1]" in "[_2]".',$uname.':'.$udom,$cdesc).'<br />'."\n";
180: } else {
181: $idresult .= &mt('Error: "[_1]" during classlist update for "[_2]" in "[_3]".',$result,$uname.':'.$udom,$cdesc).'<br />'."\n";
182: }
183: }
184: }
185: return $idresult;
186: }
187:
188: sub update_classlist {
189: my ($cdom,$cnum,$udom,$uname,$user,$newend) = @_;
190: my ($uid,$classlistentry);
191: my $fullname =
192: &Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'},
193: $user->{'lastname'},$user->{'generation'},
194: 'lastname');
195: my %classhash = &Apache::lonnet::get('classlist',[$uname.':'.$udom],
196: $cdom,$cnum);
197: my @classinfo = split(/:/,$classhash{$uname.':'.$udom});
198: my $ididx=&Apache::loncoursedata::CL_ID() - 2;
199: my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2;
200: my $endidx = &Apache::loncoursedata::CL_END() - 2;
201: my $startidx = &Apache::loncoursedata::CL_START() - 2;
202: for (my $i=0; $i<@classinfo; $i++) {
203: if ($i == $endidx) {
204: if ($newend ne '') {
205: $classlistentry .= $newend.':';
206: } else {
207: $classlistentry .= $classinfo[$i].':';
208: }
209: } elsif ($i == $startidx) {
210: if ($newend ne '') {
211: if ($classinfo[$i] > $newend) {
212: $classlistentry .= $newend.':';
213: } else {
214: $classlistentry .= $classinfo[$i].':';
215: }
216: } else {
217: $classlistentry .= $classinfo[$i].':';
218: }
219: } elsif ($i == $ididx) {
220: if (defined($user->{'id'})) {
221: $classlistentry .= $user->{'id'}.':';
222: } else {
223: $classlistentry .= $classinfo[$i].':';
224: }
225: } elsif ($i == $nameidx) {
226: if (defined($user->{'lastname'})) {
227: $classlistentry .= $fullname.':';
228: } else {
229: $classlistentry .= $classinfo[$i].':';
230: }
231: } else {
232: $classlistentry .= $classinfo[$i].':';
233: }
234: }
235: $classlistentry =~ s/:$//;
236: my $reply=&Apache::lonnet::cput('classlist',
237: {"$uname:$udom" => $classlistentry},
238: $cdom,$cnum);
239: if (($reply eq 'ok') || ($reply eq 'delayed')) {
240: return 'ok';
241: } else {
242: return 'error: '.$reply;
243: }
244: }
245:
246:
247: ###############################################################
248: ###############################################################
249: # build a role type and role selection form
250: sub domain_roles_select {
251: # Set up the role type and role selection boxes when in
252: # domain context
253: #
254: # Role types
255: my @roletypes = ('domain','author','course','community');
256: my %lt = &role_type_names();
257: my $onchangefirst = "updateCols('showrole')";
258: my $onchangesecond = "updateCols('showrole')";
259: #
260: # build up the menu information to be passed to
261: # &Apache::loncommon::linked_select_forms
262: my %select_menus;
263: if ($env{'form.roletype'} eq '') {
264: $env{'form.roletype'} = 'domain';
265: }
266: foreach my $roletype (@roletypes) {
267: # set up the text for this domain
268: $select_menus{$roletype}->{'text'}= $lt{$roletype};
269: my $crstype;
270: if ($roletype eq 'community') {
271: $crstype = 'Community';
272: }
273: # we want a choice of 'default' as the default in the second menu
274: if ($env{'form.roletype'} ne '') {
275: $select_menus{$roletype}->{'default'} = $env{'form.showrole'};
276: } else {
277: $select_menus{$roletype}->{'default'} = 'Any';
278: }
279: # Now build up the other items in the second menu
280: my @roles;
281: if ($roletype eq 'domain') {
282: @roles = &domain_roles();
283: } elsif ($roletype eq 'author') {
284: @roles = &construction_space_roles();
285: } else {
286: my $custom = 1;
287: @roles = &course_roles('domain',undef,$custom,$roletype);
288: }
289: my $order = ['Any',@roles];
290: $select_menus{$roletype}->{'order'} = $order;
291: foreach my $role (@roles) {
292: if ($role eq 'cr') {
293: $select_menus{$roletype}->{'select2'}->{$role} =
294: &mt('Custom role');
295: } else {
296: $select_menus{$roletype}->{'select2'}->{$role} =
297: &Apache::lonnet::plaintext($role,$crstype);
298: }
299: }
300: $select_menus{$roletype}->{'select2'}->{'Any'} = &mt('Any');
301: }
302: my $result = &Apache::loncommon::linked_select_forms
303: ('studentform',(' 'x3).&mt('Role: '),$env{'form.roletype'},
304: 'roletype','showrole',\%select_menus,
305: ['domain','author','course','community'],$onchangefirst,
306: $onchangesecond);
307: return $result;
308: }
309:
310: ###############################################################
311: ###############################################################
312: sub hidden_input {
313: my ($name,$value) = @_;
314: return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
315: }
316:
317: sub print_upload_manager_header {
318: my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission,$crstype,
319: $can_assign)=@_;
320: my $javascript;
321: #
322: if (! exists($env{'form.upfile_associate'})) {
323: $env{'form.upfile_associate'} = 'forward';
324: }
325: if ($env{'form.associate'} eq 'Reverse Association') {
326: if ( $env{'form.upfile_associate'} ne 'reverse' ) {
327: $env{'form.upfile_associate'} = 'reverse';
328: } else {
329: $env{'form.upfile_associate'} = 'forward';
330: }
331: }
332: if ($env{'form.upfile_associate'} eq 'reverse') {
333: $javascript=&upload_manager_javascript_reverse_associate($can_assign);
334: } else {
335: $javascript=&upload_manager_javascript_forward_associate($can_assign);
336: }
337: #
338: # Deal with restored settings
339: my $password_choice = '';
340: if (exists($env{'form.ipwd_choice'}) &&
341: $env{'form.ipwd_choice'} ne '') {
342: # If a column was specified for password, assume it is for an
343: # internal password. This is a bug waiting to be filed (could be
344: # local or krb auth instead of internal) but I do not have the
345: # time to mess around with this now.
346: $password_choice = 'int';
347: }
348: #
349: my $groupslist;
350: if ($context eq 'course') {
351: $groupslist = &get_groupslist();
352: }
353: my $javascript_validations =
354: &javascript_validations('upload',$krbdefdom,$password_choice,undef,
355: $env{'request.role.domain'},$context,
356: $groupslist,$crstype);
357: my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
358: $r->print(
359: '<h3>'.&mt('Identify fields in uploaded list')."</h3>\n".
360: '<p class="LC_info">'.
361: &mt('Total number of records found in file: [_1]'
362: ,'<b>'.$distotal.'</b>').
363: "</p>\n"
364: );
365: if ($distotal == 0) {
366: $r->print('<p class="LC_warning">'.&mt('None found').'</p>');
367: }
368: $r->print(
369: '<p>'.
370: &mt('Enter as many fields as you can.').'<br />'.
371: &mt('The system will inform you and bring you back to this page,[_1]if the data selected are insufficient to add users.','<br />').
372: "</p>\n"
373: );
374: $r->print(&hidden_input('action','upload').
375: &hidden_input('state','got_file').
376: &hidden_input('associate','').
377: &hidden_input('datatoken',$datatoken).
378: &hidden_input('fileupload',$env{'form.fileupload'}).
379: &hidden_input('upfiletype',$env{'form.upfiletype'}).
380: &hidden_input('upfile_associate',$env{'form.upfile_associate'}));
381: $r->print(
382: '<div class="LC_left_float">'.
383: '<fieldset><legend>'.&mt('Functions').'</legend>'.
384: '<label><input type="checkbox" name="noFirstLine"'.$checked.' />'.
385: &mt('Ignore First Line').'</label>'.
386: ' <input type="button" value="'.&mt('Reverse Association').'" '.
387: 'name="Reverse Association" '.
388: 'onclick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />'.
389: '</fieldset></div><br clear="all" />'
390: );
391: $r->print(
392: '<script type="text/javascript" language="Javascript">'."\n".
393: '// <![CDATA['."\n".
394: $javascript."\n".$javascript_validations."\n".
395: '// ]]>'."\n".
396: '</script>'
397: );
398: }
399:
400: ###############################################################
401: ###############################################################
402: sub javascript_validations {
403: my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain,
404: $context,$groupslist,$crstype)=@_;
405: my %param = (
406: kerb_def_dom => $krbdefdom,
407: curr_authtype => $curr_authtype,
408: );
409: if ($mode eq 'upload') {
410: $param{'formname'} = 'studentform';
411: } elsif ($mode eq 'createcourse') {
412: $param{'formname'} = 'ccrs';
413: } elsif ($mode eq 'modifycourse') {
414: $param{'formname'} = 'cmod';
415: $param{'mode'} = 'modifycourse',
416: $param{'curr_autharg'} = $curr_authfield;
417: }
418:
419: my $showcredits;
420: my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
421: if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
422: $showcredits = 1;
423: }
424:
425: my ($setsection_call,$setsections_js);
426: my $finish = " vf.submit();\n";
427: if ($mode eq 'upload') {
428: if (($context eq 'course') || ($context eq 'domain')) {
429: if ($context eq 'course') {
430: if ($env{'request.course.sec'} eq '') {
431: $setsection_call = 'setSections(document.'.$param{'formname'}.",'$crstype'".');';
432: $setsections_js =
433: &setsections_javascript($param{'formname'},$groupslist,
434: $mode,'',$crstype,$showcredits);
435: } else {
436: $setsection_call = "'ok'";
437: }
438: } elsif ($context eq 'domain') {
439: $setsection_call = 'setCourse()';
440: $setsections_js = &dc_setcourse_js($param{'formname'},$mode,
441: $context,$showcredits);
442: }
443: $finish = " var checkSec = $setsection_call\n".
444: " if (checkSec == 'ok') {\n".
445: " vf.submit();\n".
446: " }\n";
447: }
448: }
449: my $authheader = &Apache::loncommon::authform_header(%param);
450:
451: my %alert = &Apache::lonlocal::texthash
452: (username => 'You need to specify the username field.',
453: authen => 'You must choose an authentication type.',
454: krb => 'You need to specify the Kerberos domain.',
455: ipass => 'You need to specify the initial password.',
456: name => 'The optional name field was not specified.',
457: snum => 'The optional student/employee ID field was not specified.',
458: section => 'The optional section field was not specified.',
459: email => 'The optional e-mail address field was not specified.',
460: role => 'The optional role field was not specified.',
461: domain => 'The optional domain field was not specified.',
462: continue => 'Continue adding users?',
463: );
464: if ($showcredits) {
465: $alert{'credits'} = &mt('The optional credits field was not specified');
466: }
467: if (($mode eq 'upload') && ($context eq 'domain')) {
468: $alert{'inststatus'} = &mt('The optional affiliation field was not specified');
469: }
470: &js_escape(\%alert);
471: my $function_name = <<"END";
472: $setsections_js
473:
474: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits) {
475: END
476: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain);
477: my $auth_checks;
478: if ($mode eq 'createcourse') {
479: $auth_checks .= (<<END);
480: if (vf.autoadds[0].checked == true) {
481: if (current.radiovalue == null || current.radiovalue == 'nochange') {
482: alert('$alert{'authen'}');
483: return;
484: }
485: }
486: END
487: } else {
488: $auth_checks .= (<<END);
489: var foundatype=0;
490: if (founduname==0) {
491: alert('$alert{'username'}');
492: return;
493: }
494:
495: END
496: if ($authnum > 1) {
497: $auth_checks .= (<<END);
498: if (current.radiovalue == null || current.radiovalue == '' || current.radiovalue == 'nochange') {
499: // They did not check any of the login radiobuttons.
500: alert('$alert{'authen'}');
501: return;
502: }
503: END
504: }
505: }
506: if ($mode eq 'createcourse') {
507: $auth_checks .= "
508: if ( (vf.autoadds[0].checked == true) &&
509: (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
510: ";
511: } elsif ($mode eq 'modifycourse') {
512: $auth_checks .= "
513: if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') {
514: ";
515: }
516: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
517: $auth_checks .= (<<END);
518: var alertmsg = '';
519: switch (current.radiovalue) {
520: case 'krb':
521: alertmsg = '$alert{'krb'}';
522: break;
523: default:
524: alertmsg = '';
525: }
526: if (alertmsg != '') {
527: alert(alertmsg);
528: return;
529: }
530: }
531: /* regexp here to check for non \d \. in credits */
532: END
533: } else {
534: $auth_checks .= (<<END);
535: foundatype=1;
536: if (current.argfield == null || current.argfield == '') {
537: var alertmsg = '';
538: switch (current.radiovalue) {
539: case 'krb':
540: alertmsg = '$alert{'krb'}';
541: break;
542: case 'loc':
543: case 'fsys':
544: alertmsg = '$alert{'ipass'}';
545: break;
546: case 'fsys':
547: alertmsg = '';
548: break;
549: default:
550: alertmsg = '';
551: }
552: if (alertmsg != '') {
553: alert(alertmsg);
554: return;
555: }
556: }
557: END
558: }
559: my $section_checks;
560: my $optional_checks = '';
561: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
562: $optional_checks = (<<END);
563: vf.submit();
564: }
565: END
566: } else {
567: $section_checks = §ion_check_js();
568: $optional_checks = (<<END);
569: var message='';
570: if (foundname==0) {
571: message='$alert{'name'}';
572: }
573: if (foundid==0) {
574: if (message!='') {
575: message+='\\n';
576: }
577: message+='$alert{'snum'}';
578: }
579: if (foundsec==0) {
580: if (message!='') {
581: message+='\\n';
582: }
583: message+='$alert{'section'}';
584: }
585: if (foundemail==0) {
586: if (message!='') {
587: message+='\\n';
588: }
589: message+='$alert{'email'}';
590: }
591: if (foundrole==0) {
592: if (message!='') {
593: message+='\\n';
594: }
595: message+='$alert{'role'}';
596: }
597: if (founddomain==0) {
598: if (message!='') {
599: message+='\\n';
600: }
601: message+='$alert{'domain'}';
602: }
603: END
604: if ($showcredits) {
605: $optional_checks .= <<END;
606: if (foundcredits==0) {
607: if (message!='') {
608: message+='\\n';
609: }
610: message+='$alert{'credits'}';
611: }
612: END
613: }
614: if (($mode eq 'upload') && ($context eq 'domain')) {
615: $optional_checks .= (<<END);
616:
617: if (foundinststatus==0) {
618: if (message!='') {
619: message+='\\n';
620: }
621: message+='$alert{'inststatus'}';
622: }
623: END
624: }
625: $optional_checks .= (<<END);
626:
627: if (message!='') {
628: message+= '\\n$alert{'continue'}';
629: if (confirm(message)) {
630: vf.state.value='enrolling';
631: $finish
632: }
633: } else {
634: vf.state.value='enrolling';
635: $finish
636: }
637: }
638: END
639: }
640: my $result = $function_name.$auth_checks.$optional_checks."\n".
641: $section_checks.$authheader;
642: return $result;
643: }
644: ###############################################################
645: ###############################################################
646: sub upload_manager_javascript_forward_associate {
647: my ($can_assign) = @_;
648: my ($auth_update,$numbuttons,$argreset);
649: if (ref($can_assign) eq 'HASH') {
650: if ($can_assign->{'krb4'} || $can_assign->{'krb5'}) {
651: $argreset .= " vf.krbarg.value='';\n";
652: $numbuttons ++ ;
653: }
654: if ($can_assign->{'int'}) {
655: $argreset .= " vf.intarg.value='';\n";
656: $numbuttons ++;
657: }
658: if ($can_assign->{'loc'}) {
659: $argreset .= " vf.locarg.value='';\n";
660: $numbuttons ++;
661: }
662: if (!$can_assign->{'int'}) {
663: my $warning = &mt('You may not specify an initial password for each user, as this is only available when new users use LON-CAPA internal authentication.')."\n".
664: &mt('Your current role does not have rights to create users with that authentication type.');
665: &js_escape(\$warning);
666: $auth_update = <<"END";
667: // Currently the initial password field is only supported for internal auth
668: // (see bug 6368).
669: if (nw==9) {
670: eval('vf.f'+tf+'.selectedIndex=0;')
671: alert('$warning');
672: }
673: END
674: } elsif ($numbuttons > 1) {
675: $auth_update = <<"END";
676: // If we set the password, make the password form below correspond to
677: // the new value.
678: if (nw==9) {
679: changed_radio('int',document.studentform);
680: set_auth_radio_buttons('int',document.studentform);
681: $argreset
682: }
683:
684: END
685: }
686: }
687:
688: return(<<ENDPICK);
689: function verify(vf,sec_caller) {
690: var founduname=0;
691: var foundpwd=0;
692: var foundname=0;
693: var foundid=0;
694: var foundsec=0;
695: var foundemail=0;
696: var foundrole=0;
697: var founddomain=0;
698: var foundinststatus=0;
699: var foundcredits=0;
700: var tw;
701: for (i=0;i<=vf.nfields.value;i++) {
702: tw=eval('vf.f'+i+'.selectedIndex');
703: if (tw==1) { founduname=1; }
704: if ((tw>=2) && (tw<=6)) { foundname=1; }
705: if (tw==7) { foundid=1; }
706: if (tw==8) { foundsec=1; }
707: if (tw==9) { foundpwd=1; }
708: if (tw==10) { foundemail=1; }
709: if (tw==11) { foundrole=1; }
710: if (tw==12) { founddomain=1; }
711: if (tw==13) { foundinststatus=1; }
712: if (tw==14) { foundcredits=1; }
713: }
714: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits);
715: }
716:
717: //
718: // vf = this.form
719: // tf = column number
720: //
721: // values of nw
722: //
723: // 0 = none
724: // 1 = username
725: // 2 = names (lastname, firstnames)
726: // 3 = fname (firstname)
727: // 4 = mname (middlename)
728: // 5 = lname (lastname)
729: // 6 = gen (generation)
730: // 7 = id
731: // 8 = section
732: // 9 = ipwd (password)
733: // 10 = email address
734: // 11 = role
735: // 12 = domain
736: // 13 = inststatus
737: // 14 = foundcredits
738:
739: function flip(vf,tf) {
740: var nw=eval('vf.f'+tf+'.selectedIndex');
741: var i;
742: // make sure no other columns are labeled the same as this one
743: for (i=0;i<=vf.nfields.value;i++) {
744: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
745: eval('vf.f'+i+'.selectedIndex=0;')
746: }
747: }
748: // If we set this to 'lastname, firstnames', clear out all the ones
749: // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
750: if (nw==2) {
751: for (i=0;i<=vf.nfields.value;i++) {
752: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
753: (eval('vf.f'+i+'.selectedIndex')<=6)) {
754: eval('vf.f'+i+'.selectedIndex=0;')
755: }
756: }
757: }
758: // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
759: // clear out any that are set to 'lastname, firstnames' (2)
760: if ((nw>=3) && (nw<=6)) {
761: for (i=0;i<=vf.nfields.value;i++) {
762: if (eval('vf.f'+i+'.selectedIndex')==2) {
763: eval('vf.f'+i+'.selectedIndex=0;')
764: }
765: }
766: }
767: $auth_update
768: }
769:
770: function clearpwd(vf) {
771: var i;
772: for (i=0;i<=vf.nfields.value;i++) {
773: if (eval('vf.f'+i+'.selectedIndex')==9) {
774: eval('vf.f'+i+'.selectedIndex=0;')
775: }
776: }
777: }
778:
779: ENDPICK
780: }
781:
782: ###############################################################
783: ###############################################################
784: sub upload_manager_javascript_reverse_associate {
785: my ($can_assign) = @_;
786: my ($auth_update,$numbuttons,$argreset);
787: if (ref($can_assign) eq 'HASH') {
788: if ($can_assign->{'krb4'} || $can_assign->{'krb5'}) {
789: $argreset .= " vf.krbarg.value='';\n";
790: $numbuttons ++ ;
791: }
792: if ($can_assign->{'int'}) {
793: $argreset .= " vf.intarg.value='';\n";
794: $numbuttons ++;
795: }
796: if ($can_assign->{'loc'}) {
797: $argreset .= " vf.locarg.value='';\n";
798: $numbuttons ++;
799: }
800: if (!$can_assign->{'int'}) {
801: my $warning = &mt('You may not specify an initial password, as this is only available when new users use LON-CAPA internal authentication.\n').
802: &mt('Your current role does not have rights to create users with that authentication type.');
803: &js_escape(\$warning);
804: $auth_update = <<"END";
805: // Currently the initial password field is only supported for internal auth
806: // (see bug 6368).
807: if (tf==8 && nw!=0) {
808: eval('vf.f'+tf+'.selectedIndex=0;')
809: alert('$warning');
810: }
811: END
812: } elsif ($numbuttons > 1) {
813: $auth_update = <<"END";
814: // initial password specified, pick internal authentication
815: if (tf==8 && nw!=0) {
816: changed_radio('int',document.studentform);
817: set_auth_radio_buttons('int',document.studentform);
818: $argreset
819: }
820:
821: END
822: }
823: }
824:
825: return(<<ENDPICK);
826: function verify(vf,sec_caller) {
827: var founduname=0;
828: var foundpwd=0;
829: var foundname=0;
830: var foundid=0;
831: var foundsec=0;
832: var foundemail=0;
833: var foundrole=0;
834: var founddomain=0;
835: var foundinststatus=0;
836: var foundcredits=0;
837: var tw;
838: for (i=0;i<=vf.nfields.value;i++) {
839: tw=eval('vf.f'+i+'.selectedIndex');
840: if (i==0 && tw!=0) { founduname=1; }
841: if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
842: if (i==6 && tw!=0) { foundid=1; }
843: if (i==7 && tw!=0) { foundsec=1; }
844: if (i==8 && tw!=0) { foundpwd=1; }
845: if (i==9 && tw!=0) { foundemail=1; }
846: if (i==10 && tw!=0) { foundrole=1; }
847: if (i==11 && tw!=0) { founddomain=1; }
848: if (i==12 && tw!=0) { foundinstatus=1; }
849: if (i==13 && tw!=0) { foundcredits=1; }
850: }
851: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits);
852: }
853:
854: function flip(vf,tf) {
855: var nw=eval('vf.f'+tf+'.selectedIndex');
856: var i;
857: // picked the all one name field, reset the other name ones to blank
858: if (tf==1 && nw!=0) {
859: for (i=2;i<=5;i++) {
860: eval('vf.f'+i+'.selectedIndex=0;')
861: }
862: }
863: //picked one of the piecewise name fields, reset the all in
864: //one field to blank
865: if ((tf>=2) && (tf<=5) && (nw!=0)) {
866: eval('vf.f1.selectedIndex=0;')
867: }
868: $auth_update
869: }
870:
871: function clearpwd(vf) {
872: var i;
873: if (eval('vf.f8.selectedIndex')!=0) {
874: eval('vf.f8.selectedIndex=0;')
875: }
876: }
877: ENDPICK
878: }
879:
880: ###############################################################
881: ###############################################################
882: sub print_upload_manager_footer {
883: my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission,$crstype,
884: $showcredits) = @_;
885: my $form = 'document.studentform';
886: my $formname = 'studentform';
887: my ($krbdef,$krbdefdom) =
888: &Apache::loncommon::get_kerberos_defaults($defdom);
889: my %param = ( formname => $form,
890: kerb_def_dom => $krbdefdom,
891: kerb_def_auth => $krbdef
892: );
893: if (exists($env{'form.ipwd_choice'}) &&
894: defined($env{'form.ipwd_choice'}) &&
895: $env{'form.ipwd_choice'} ne '') {
896: $param{'curr_authtype'} = 'int';
897: }
898: my $krbform = &Apache::loncommon::authform_kerberos(%param);
899: my $intform = &Apache::loncommon::authform_internal(%param);
900: my $locform = &Apache::loncommon::authform_local(%param);
901: my $date_table = &date_setting_table(undef,undef,$context,undef,
902: $formname,$permission,$crstype);
903:
904: my $Str = "\n".'<div class="LC_left_float">';
905: $Str .= &hidden_input('nfields',$i);
906: $Str .= &hidden_input('keyfields',$keyfields);
907:
908: $Str .= '<h3>'.&mt('Options').'</h3>'
909: .&Apache::lonhtmlcommon::start_pick_box();
910:
911: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Login Type'));
912: if ($context eq 'domain') {
913: $Str .= '<p>'
914: .&mt('Change authentication for existing users in domain "[_1]" to these settings?'
915: ,$defdom)
916: .' <span class="LC_nobreak"><label>'
917: .'<input type="radio" name="changeauth" value="No" checked="checked" />'
918: .&mt('No').'</label>'
919: .' <label>'
920: .'<input type="radio" name="changeauth" value="Yes" />'
921: .&mt('Yes').'</label>'
922: .'</span></p>';
923: } else {
924: $Str .= '<p class="LC_info">'."\n".
925: &mt('This will not take effect if the user already exists.').
926: &Apache::loncommon::help_open_topic('Auth_Options').
927: "</p>\n";
928: }
929: $Str .= &set_login($defdom,$krbform,$intform,$locform);
930:
931: my ($home_server_pick,$numlib) =
932: &Apache::loncommon::home_server_form_item($defdom,'lcserver',
933: 'default','hide');
934: if ($numlib > 1) {
935: $Str .= &Apache::lonhtmlcommon::row_closure()
936: .&Apache::lonhtmlcommon::row_title(
937: &mt('LON-CAPA Home Server for New Users'))
938: .&mt('LON-CAPA domain: [_1] with home server:','"'.$defdom.'"')
939: .$home_server_pick
940: .&Apache::lonhtmlcommon::row_closure();
941: } else {
942: $Str .= $home_server_pick.
943: &Apache::lonhtmlcommon::row_closure();
944: }
945:
946: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain'))
947: .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1)
948: .&Apache::lonhtmlcommon::row_closure();
949:
950: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates'))
951: ."<p>\n".$date_table."</p>\n"
952: .&Apache::lonhtmlcommon::row_closure();
953:
954: if ($context eq 'domain') {
955: $Str .= &Apache::lonhtmlcommon::row_title(
956: &mt('Settings for assigning roles'))
957: .&mt('Pick the action to take on roles for these users:').'<br />'
958: .'<span class="LC_nobreak"><label>'
959: .'<input type="radio" name="roleaction" value="norole" checked="checked" />'
960: .' '.&mt('No role changes').'</label>'
961: .' <label>'
962: .'<input type="radio" name="roleaction" value="domain" />'
963: .' '.&mt('Add a domain role').'</label>'
964: .' <label>'
965: .'<input type="radio" name="roleaction" value="course" />'
966: .' '.&mt('Add a course/community role').'</label>'
967: .'</span>';
968: } elsif ($context eq 'author') {
969: $Str .= &Apache::lonhtmlcommon::row_title(
970: &mt('Default role'))
971: .&mt('Choose the role to assign to users without a value specified in the uploaded file.')
972: } elsif ($context eq 'course') {
973: if ($showcredits) {
974: $Str .= &Apache::lonhtmlcommon::row_title(
975: &mt('Default role, section and credits'))
976: .&mt('Choose the role and/or section(s) and/or credits to assign to users without values specified in the uploaded file.');
977: } else {
978: $Str .= &Apache::lonhtmlcommon::row_title(
979: &mt('Default role and section'))
980: .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.');
981: }
982: } else {
983: $Str .= &Apache::lonhtmlcommon::row_title(
984: &mt('Default role and/or section(s)'))
985: .&mt('Role and/or section(s) for users without values specified in the uploaded file.');
986: }
987: if (($context eq 'domain') || ($context eq 'author')) {
988: $Str .= '<br />';
989: my ($options,$cb_script,$coursepick) =
990: &default_role_selector($context,1,'',$showcredits);
991: if ($context eq 'domain') {
992: $Str .= '<p>'
993: .'<b>'.&mt('Domain Level').'</b><br />'
994: .$options
995: .'</p><p>'
996: .'<b>'.&mt('Course Level').'</b>'
997: .'</p>'
998: .$cb_script.$coursepick
999: .&Apache::lonhtmlcommon::row_closure();
1000: } elsif ($context eq 'author') {
1001: $Str .= $options
1002: .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
1003: }
1004: } else {
1005: my ($cnum,$cdom) = &get_course_identity();
1006: my $rowtitle = &mt('section');
1007: my $defaultcredits;
1008: if ($showcredits) {
1009: $defaultcredits = &get_defaultcredits();
1010: }
1011: my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle,$permission,
1012: $context,'upload',$crstype,$showcredits,
1013: $defaultcredits);
1014: $Str .= $secbox
1015: .&Apache::lonhtmlcommon::row_closure();
1016: my %lt;
1017: if ($crstype eq 'Community') {
1018: %lt = &Apache::lonlocal::texthash (
1019: disp => 'Display members with current/future access who are not in the uploaded file',
1020: stus => 'Members selected from this list can be dropped.'
1021: );
1022: } else {
1023: %lt = &Apache::lonlocal::texthash (
1024: disp => 'Display students with current/future access who are not in the uploaded file',
1025: stus => 'Students selected from this list can be dropped.'
1026: );
1027: }
1028: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Full Update'))
1029: .'<label><input type="checkbox" name="fullup" value="yes" />'
1030: .' '.$lt{'disp'}
1031: .'</label><br />'
1032: .$lt{'stus'}
1033: .&Apache::lonhtmlcommon::row_closure();
1034: }
1035: if ($context eq 'course' || $context eq 'domain') {
1036: $Str .= &Apache::lonhtmlcommon::row_title(&mt('Student/Employee ID'))
1037: .&forceid_change($context)
1038: .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
1039: }
1040:
1041: $Str .= &Apache::lonhtmlcommon::end_pick_box();
1042: $Str .= '</div>';
1043:
1044: # Footer
1045: $Str .= '<div class="LC_clear_float_footer">'
1046: .'<hr />';
1047: if ($context eq 'course') {
1048: $Str .= '<p class="LC_info">'
1049: .&mt('Note: This operation may be time consuming when adding several users.')
1050: .'</p>';
1051: }
1052: $Str .= '<p><input type="button"'
1053: .' onclick="javascript:verify(this.form,this.form.csec)"'
1054: .' value="'.&mt('Update Users').'" />'
1055: .'</p>'."\n"
1056: .'</div>';
1057: $r->print($Str);
1058: return;
1059: }
1060:
1061: sub get_defaultcredits {
1062: my ($cdom,$cnum) = @_;
1063:
1064: if ($cdom eq '' || $cnum eq '') {
1065: return unless ($env{'request.course.id'});
1066: $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1067: $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1068: }
1069: return unless(($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/));
1070: my ($defaultcredits,$domdefcredits);
1071: my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
1072: if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
1073: my $instcode = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'};
1074: if ($instcode) {
1075: $domdefcredits = $domdefaults{'officialcredits'};
1076: } elsif ($env{'course.'.$cdom.'_'.$cnum.'.internal.textbook'}) {
1077: $domdefcredits = $domdefaults{'textbookcredits'};
1078: } else {
1079: $domdefcredits = $domdefaults{'unofficialcredits'};
1080: }
1081: } else {
1082: return;
1083: }
1084:
1085: if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
1086: $defaultcredits = $env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'};
1087: } elsif (exists($env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'})) {
1088: $defaultcredits = $env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'};
1089: } else {
1090: my %crsinfo =
1091: &Apache::lonnet::coursedescription("$cdom/$cnum",{'one_time' => 1});
1092: $defaultcredits = $crsinfo{'internal.defaultcredits'};
1093: }
1094: if ($defaultcredits eq '') {
1095: $defaultcredits = $domdefcredits;
1096: }
1097: return $defaultcredits;
1098: }
1099:
1100: sub forceid_change {
1101: my ($context) = @_;
1102: my $output =
1103: '<label><input type="checkbox" name="forceid" value="yes" />'
1104: .&mt('Force change of existing ID')
1105: .'</label>'.&Apache::loncommon::help_open_topic('ForceIDChange')."\n";
1106: if ($context eq 'domain') {
1107: $output .=
1108: '<br />'
1109: .'<label><input type="checkbox" name="recurseid" value="yes" />'
1110: .&mt("Update ID in user's course(s).").'</label>'."\n";
1111: }
1112: return $output;
1113: }
1114:
1115: ###############################################################
1116: ###############################################################
1117: sub print_upload_manager_form {
1118: my ($r,$context,$permission,$crstype,$showcredits) = @_;
1119: my $firstLine;
1120: my $datatoken;
1121: if (!$env{'form.datatoken'}) {
1122: $datatoken=&Apache::loncommon::upfile_store($r);
1123: } else {
1124: $datatoken=$env{'form.datatoken'};
1125: &Apache::loncommon::load_tmp_file($r);
1126: }
1127: my @records=&Apache::loncommon::upfile_record_sep();
1128: if($env{'form.noFirstLine'}){
1129: $firstLine=shift(@records);
1130: }
1131: my $total=$#records;
1132: my $distotal=$total+1;
1133: my $today=time;
1134: my $halfyear=$today+15552000;
1135: #
1136: # Restore memorized settings
1137: my $col_setting_names = { 'username_choice' => 'scalar', # column settings
1138: 'names_choice' => 'scalar',
1139: 'fname_choice' => 'scalar',
1140: 'mname_choice' => 'scalar',
1141: 'lname_choice' => 'scalar',
1142: 'gen_choice' => 'scalar',
1143: 'id_choice' => 'scalar',
1144: 'sec_choice' => 'scalar',
1145: 'ipwd_choice' => 'scalar',
1146: 'email_choice' => 'scalar',
1147: 'role_choice' => 'scalar',
1148: 'domain_choice' => 'scalar',
1149: 'inststatus_choice' => 'scalar',
1150: };
1151: if ($showcredits) {
1152: $col_setting_names->{'credits_choice'} = 'scalar';
1153: }
1154: if ($context eq 'course') {
1155: &Apache::loncommon::restore_course_settings('enrollment_upload',
1156: $col_setting_names);
1157: } else {
1158: &Apache::loncommon::restore_settings($context,'user_upload',
1159: $col_setting_names);
1160: }
1161: my $defdom = $env{'request.role.domain'};
1162: #
1163: # Determine kerberos parameters as appropriate
1164: my ($krbdef,$krbdefdom) =
1165: &Apache::loncommon::get_kerberos_defaults($defdom);
1166: #
1167: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($defdom);
1168: &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context,
1169: $permission,$crstype,\%can_assign);
1170: my $i;
1171: my $keyfields;
1172: if ($total>=0) {
1173: my @field=
1174: (['username',&mt('Username'), $env{'form.username_choice'}],
1175: ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}],
1176: ['fname',&mt('First Name'), $env{'form.fname_choice'}],
1177: ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}],
1178: ['lname',&mt('Last Name'), $env{'form.lname_choice'}],
1179: ['gen', &mt('Generation'), $env{'form.gen_choice'}],
1180: ['id', &mt('Student/Employee ID'),$env{'form.id_choice'}],
1181: ['sec', &mt('Section'), $env{'form.sec_choice'}],
1182: ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}],
1183: ['email',&mt('E-mail Address'), $env{'form.email_choice'}],
1184: ['role',&mt('Role'), $env{'form.role_choice'}],
1185: ['domain',&mt('Domain'), $env{'form.domain_choice'}],
1186: ['inststatus',&mt('Affiliation'), $env{'form.inststatus_choice'}]);
1187: if ($showcredits) {
1188: push(@field,
1189: ['credits',&mt('Student Credits'), $env{'form.credits_choice'}]);
1190: }
1191: if ($env{'form.upfile_associate'} eq 'reverse') {
1192: &Apache::loncommon::csv_print_samples($r,\@records);
1193: $i=&Apache::loncommon::csv_print_select_table($r,\@records,
1194: \@field);
1195: foreach (@field) {
1196: $keyfields.=$_->[0].',';
1197: }
1198: chop($keyfields);
1199: } else {
1200: unshift(@field,['none','']);
1201: $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
1202: \@field);
1203: my %sone=&Apache::loncommon::record_sep($records[0]);
1204: $keyfields=join(',',sort(keys(%sone)));
1205: }
1206: }
1207: &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
1208: $context,$permission,$crstype,$showcredits);
1209: }
1210:
1211: sub setup_date_selectors {
1212: my ($starttime,$endtime,$mode,$nolink,$formname) = @_;
1213: if ($formname eq '') {
1214: $formname = 'studentform';
1215: }
1216: if (! defined($starttime)) {
1217: $starttime = time;
1218: unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
1219: if (exists($env{'course.'.$env{'request.course.id'}.
1220: '.default_enrollment_start_date'})) {
1221: $starttime = $env{'course.'.$env{'request.course.id'}.
1222: '.default_enrollment_start_date'};
1223: }
1224: }
1225: }
1226: if (! defined($endtime)) {
1227: $endtime = time+(6*30*24*60*60); # 6 months from now, approx
1228: unless ($mode eq 'createcourse') {
1229: if (exists($env{'course.'.$env{'request.course.id'}.
1230: '.default_enrollment_end_date'})) {
1231: $endtime = $env{'course.'.$env{'request.course.id'}.
1232: '.default_enrollment_end_date'};
1233: }
1234: }
1235: }
1236:
1237: my $startdateform =
1238: &Apache::lonhtmlcommon::date_setter($formname,'startdate',$starttime,
1239: undef,undef,undef,undef,undef,undef,undef,$nolink);
1240:
1241: my $enddateform =
1242: &Apache::lonhtmlcommon::date_setter($formname,'enddate',$endtime,
1243: undef,undef,undef,undef,undef,undef,undef,$nolink);
1244:
1245: if ($mode eq 'create_enrolldates') {
1246: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1247: 'startenroll',
1248: $starttime);
1249: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1250: 'endenroll',
1251: $endtime);
1252: }
1253: if ($mode eq 'create_defaultdates') {
1254: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1255: 'startaccess',
1256: $starttime);
1257: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
1258: 'endaccess',
1259: $endtime);
1260: }
1261: return ($startdateform,$enddateform);
1262: }
1263:
1264:
1265: sub get_dates_from_form {
1266: my ($startname,$endname) = @_;
1267: if ($startname eq '') {
1268: $startname = 'startdate';
1269: }
1270: if ($endname eq '') {
1271: $endname = 'enddate';
1272: }
1273: my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname);
1274: my $enddate = &Apache::lonhtmlcommon::get_date_from_form($endname);
1275: if ($env{'form.no_end_date'}) {
1276: $enddate = 0;
1277: }
1278: return ($startdate,$enddate);
1279: }
1280:
1281: sub date_setting_table {
1282: my ($starttime,$endtime,$mode,$bulkaction,$formname,$permission,$crstype) = @_;
1283: my $nolink;
1284: if ($bulkaction) {
1285: $nolink = 1;
1286: }
1287: my ($startform,$endform) =
1288: &setup_date_selectors($starttime,$endtime,$mode,$nolink,$formname);
1289: my $dateDefault;
1290: if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
1291: $dateDefault = ' ';
1292: } elsif ($mode ne 'author' && $mode ne 'domain') {
1293: if (($bulkaction eq 'reenable') ||
1294: ($bulkaction eq 'activate') ||
1295: ($bulkaction eq 'chgdates') ||
1296: ($env{'form.action'} eq 'upload')) {
1297: if ($env{'request.course.sec'} eq '') {
1298: $dateDefault = '<span class="LC_nobreak">'.
1299: '<label><input type="checkbox" name="makedatesdefault" value="1" /> ';
1300: if ($crstype eq 'Community') {
1301: $dateDefault .= &mt("make these dates the default access dates for future community enrollment");
1302: } else {
1303: $dateDefault .= &mt("make these dates the default access dates for future course enrollment");
1304: }
1305: $dateDefault .= '</label></span>';
1306: }
1307: }
1308: }
1309: my $perpetual = '<span class="LC_nobreak"><label><input type="checkbox" name="no_end_date"';
1310: if (defined($endtime) && $endtime == 0) {
1311: $perpetual .= ' checked="checked"';
1312: }
1313: $perpetual.= ' /> '.&mt('no ending date').'</label></span>';
1314: if ($mode eq 'create_enrolldates') {
1315: $perpetual = ' ';
1316: }
1317: my $result = &Apache::lonhtmlcommon::start_pick_box()."\n";
1318: $result .= &Apache::lonhtmlcommon::row_title(&mt('Starting Date'),
1319: 'LC_oddrow_value')."\n".
1320: $startform."\n".
1321: &Apache::lonhtmlcommon::row_closure(1).
1322: &Apache::lonhtmlcommon::row_title(&mt('Ending Date'),
1323: 'LC_oddrow_value')."\n".
1324: $endform.' '.$perpetual.
1325: &Apache::lonhtmlcommon::row_closure(1).
1326: &Apache::lonhtmlcommon::end_pick_box();
1327: if ($dateDefault) {
1328: $result .= $dateDefault.'<br />'."\n";
1329: }
1330: return $result;
1331: }
1332:
1333: sub make_dates_default {
1334: my ($startdate,$enddate,$context,$crstype) = @_;
1335: my $result = '';
1336: if ($context eq 'course') {
1337: my ($cnum,$cdom) = &get_course_identity();
1338: my $put_result = &Apache::lonnet::put('environment',
1339: {'default_enrollment_start_date'=>$startdate,
1340: 'default_enrollment_end_date' =>$enddate},$cdom,$cnum);
1341: if ($put_result eq 'ok') {
1342: if ($crstype eq 'Community') {
1343: $result .= &mt('Set default start and end access dates for community.');
1344: } else {
1345: $result .= &mt('Set default start and end access dates for course.');
1346: }
1347: $result .= '<br />'."\n";
1348: #
1349: # Refresh the course environment
1350: &Apache::lonnet::coursedescription($env{'request.course.id'},
1351: {'freshen_cache' => 1});
1352: } else {
1353: if ($crstype eq 'Community') {
1354: $result .= &mt('Unable to set default access dates for community');
1355: } else {
1356: $result .= &mt('Unable to set default access dates for course');
1357: }
1358: $result .= ':'.$put_result.'<br />';
1359: }
1360: }
1361: return $result;
1362: }
1363:
1364: sub default_role_selector {
1365: my ($context,$checkpriv,$crstype,$showcredits) = @_;
1366: my %customroles;
1367: my ($options,$coursepick,$cb_jscript);
1368: if ($context ne 'author') {
1369: %customroles = &my_custom_roles($crstype);
1370: }
1371:
1372: my %lt=&Apache::lonlocal::texthash(
1373: 'rol' => "Role",
1374: 'grs' => "Section",
1375: 'exs' => "Existing sections",
1376: 'new' => "New section",
1377: 'crd' => "Credits",
1378: );
1379: $options = '<select name="defaultrole">'."\n".
1380: ' <option value="">'.&mt('Please select').'</option>'."\n";
1381: if ($context eq 'course') {
1382: $options .= &default_course_roles($context,$checkpriv,$crstype,%customroles);
1383: } elsif ($context eq 'author') {
1384: my @roles = &construction_space_roles($checkpriv);
1385: foreach my $role (@roles) {
1386: my $plrole=&Apache::lonnet::plaintext($role);
1387: $options .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
1388: }
1389: } elsif ($context eq 'domain') {
1390: my @roles = &domain_roles($checkpriv);
1391: foreach my $role (@roles) {
1392: my $plrole=&Apache::lonnet::plaintext($role);
1393: $options .= ' <option value="'.$role.'">'.$plrole.'</option>';
1394: }
1395: my $courseform = &Apache::loncommon::selectcourse_link
1396: ('studentform','dccourse','dcdomain','coursedesc',"$env{'request.role.domain'}",undef,'Course/Community');
1397: my ($credit_elem,$creditsinput);
1398: if ($showcredits) {
1399: $credit_elem = 'credits';
1400: $creditsinput = '<td><input type="text" name="credits" value="" /></td>';
1401: }
1402: $cb_jscript =
1403: &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'},'currsec','studentform','courserole','Course/Community',$credit_elem);
1404: $coursepick = &Apache::loncommon::start_data_table().
1405: &Apache::loncommon::start_data_table_header_row().
1406: '<th>'.$courseform.'</th><th>'.$lt{'rol'}.'</th>'.
1407: '<th>'.$lt{'grs'}.'</th>'.
1408: '<th>'.$lt{'crd'}.'</th>'.
1409: &Apache::loncommon::end_data_table_header_row().
1410: &Apache::loncommon::start_data_table_row()."\n".
1411: '<td><input type="text" name="coursedesc" value="" onfocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc','','','','crstype'".')" /></td>'."\n".
1412: '<td><select name="courserole">'."\n".
1413: &default_course_roles($context,$checkpriv,'Course',%customroles)."\n".
1414: '</select></td><td>'.
1415: '<table class="LC_createuser">'.
1416: '<tr class="LC_section_row"><td valign="top">'.
1417: $lt{'exs'}.'<br /><select name="currsec">'.
1418: ' <option value=""><--'.&mt('Pick course first').
1419: '</select></td>'.
1420: '<td> </td>'.
1421: '<td valign="top">'.$lt{'new'}.'<br />'.
1422: '<input type="text" name="newsec" value="" size="5" />'.
1423: '<input type="hidden" name="groups" value="" />'.
1424: '<input type="hidden" name="sections" value="" />'.
1425: '<input type="hidden" name="origdom" value="'.
1426: $env{'request.role.domain'}.'" />'.
1427: '<input type="hidden" name="dccourse" value="" />'.
1428: '<input type="hidden" name="dcdomain" value="" />'.
1429: '<input type="hidden" name="crstype" value="" />'.
1430: '</td></tr></table></td>'.$creditsinput.
1431: &Apache::loncommon::end_data_table_row().
1432: &Apache::loncommon::end_data_table()."\n";
1433: }
1434: $options .= '</select>';
1435: return ($options,$cb_jscript,$coursepick);
1436: }
1437:
1438: sub default_course_roles {
1439: my ($context,$checkpriv,$crstype,%customroles) = @_;
1440: my $output;
1441: my $custom = 1;
1442: my @roles = &course_roles($context,$checkpriv,$custom,lc($crstype));
1443: foreach my $role (@roles) {
1444: if ($role ne 'cr') {
1445: my $plrole=&Apache::lonnet::plaintext($role,$crstype);
1446: $output .= ' <option value="'.$role.'">'.$plrole.'</option>';
1447: }
1448: }
1449: if (keys(%customroles) > 0) {
1450: if (grep(/^cr$/,@roles)) {
1451: foreach my $cust (sort(keys(%customroles))) {
1452: my $custrole='cr_'.$env{'user.domain'}.
1453: '_'.$env{'user.name'}.'_'.$cust;
1454: $output .= ' <option value="'.$custrole.'">'.$cust.'</option>';
1455: }
1456: }
1457: }
1458: return $output;
1459: }
1460:
1461: sub construction_space_roles {
1462: my ($checkpriv) = @_;
1463: my @allroles = &roles_by_context('author');
1464: my @roles;
1465: if ($checkpriv) {
1466: foreach my $role (@allroles) {
1467: if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) {
1468: push(@roles,$role);
1469: }
1470: }
1471: return @roles;
1472: } else {
1473: return @allroles;
1474: }
1475: }
1476:
1477: sub domain_roles {
1478: my ($checkpriv) = @_;
1479: my @allroles = &roles_by_context('domain');
1480: my @roles;
1481: if ($checkpriv) {
1482: foreach my $role (@allroles) {
1483: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
1484: push(@roles,$role);
1485: }
1486: }
1487: return @roles;
1488: } else {
1489: return @allroles;
1490: }
1491: }
1492:
1493: sub course_roles {
1494: my ($context,$checkpriv,$custom,$roletype) = @_;
1495: my $crstype;
1496: if ($roletype eq 'community') {
1497: $crstype = 'Community' ;
1498: } else {
1499: $crstype = 'Course';
1500: }
1501: my @allroles = &roles_by_context('course',$custom,$crstype);
1502: my @roles;
1503: if ($context eq 'domain') {
1504: @roles = @allroles;
1505: } elsif ($context eq 'course') {
1506: if ($env{'request.course.id'}) {
1507: if ($checkpriv) {
1508: foreach my $role (@allroles) {
1509: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
1510: push(@roles,$role);
1511: } else {
1512: if ((($role ne 'cc') && ($role ne 'co')) && ($env{'request.course.sec'} ne '')) {
1513: if (&Apache::lonnet::allowed('c'.$role,
1514: $env{'request.course.id'}.'/'.
1515: $env{'request.course.sec'})) {
1516: push(@roles,$role);
1517: }
1518: }
1519: }
1520: }
1521: } else {
1522: @roles = @allroles;
1523: }
1524: }
1525: }
1526: return @roles;
1527: }
1528:
1529: sub curr_role_permissions {
1530: my ($context,$setting,$checkpriv,$type) = @_;
1531: my $custom = 1;
1532: my @roles;
1533: if ($context eq 'author') {
1534: @roles = &construction_space_roles($checkpriv);
1535: } elsif ($context eq 'domain') {
1536: if ($setting eq 'course') {
1537: @roles = &course_roles($context,$checkpriv,$custom,$type);
1538: } else {
1539: @roles = &domain_roles($checkpriv);
1540: }
1541: } elsif ($context eq 'course') {
1542: @roles = &course_roles($context,$checkpriv,$custom,$type);
1543: }
1544: return @roles;
1545: }
1546:
1547: # ======================================================= Existing Custom Roles
1548:
1549: sub my_custom_roles {
1550: my ($crstype,$udom,$uname) = @_;
1551: my %returnhash=();
1552: my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
1553: my %rolehash=&Apache::lonnet::dump('roles',$udom,$uname);
1554: foreach my $key (keys(%rolehash)) {
1555: if ($key=~/^rolesdef\_(\w+)$/) {
1556: if ($crstype eq 'Community') {
1557: next if ($rolehash{$key} =~ /bre\&S/);
1558: }
1559: $returnhash{$1}=$1;
1560: }
1561: }
1562: return %returnhash;
1563: }
1564:
1565: sub print_userlist {
1566: my ($r,$mode,$permission,$context,$formname,$totcodes,$codetitles,
1567: $idlist,$idlist_titles,$showcredits) = @_;
1568: my $format = $env{'form.output'};
1569: if (! exists($env{'form.sortby'})) {
1570: $env{'form.sortby'} = 'username';
1571: }
1572: if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) {
1573: $env{'form.Status'} = 'Active';
1574: }
1575: my $onchange = "javascript:updateCols('Status');";
1576: my $status_select = &Apache::lonhtmlcommon::StatusOptions
1577: ($env{'form.Status'},undef,undef,$onchange);
1578:
1579: if ($env{'form.showrole'} eq '') {
1580: if ($context eq 'course') {
1581: $env{'form.showrole'} = 'st';
1582: } else {
1583: $env{'form.showrole'} = 'Any';
1584: }
1585: }
1586: if (! defined($env{'form.output'}) ||
1587: $env{'form.output'} !~ /^(csv|excel|html)$/ ) {
1588: $env{'form.output'} = 'html';
1589: }
1590:
1591: my @statuses;
1592: if ($env{'form.Status'} eq 'Any') {
1593: @statuses = ('previous','active','future');
1594: } elsif ($env{'form.Status'} eq 'Expired') {
1595: @statuses = ('previous');
1596: } elsif ($env{'form.Status'} eq 'Active') {
1597: @statuses = ('active');
1598: } elsif ($env{'form.Status'} eq 'Future') {
1599: @statuses = ('future');
1600: }
1601:
1602: # Interface output
1603: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
1604: '<input type="hidden" name="action" value="'.
1605: $env{'form.action'}.'" />');
1606: $r->print('<div>'."\n");
1607: if ($env{'form.action'} ne 'modifystudent') {
1608: my %lt=&Apache::lonlocal::texthash('csv' => "CSV",
1609: 'excel' => "Excel",
1610: 'html' => 'HTML');
1611: my $output_selector = '<select size="1" name="output" onchange="javascript:updateCols('."'output'".');" >';
1612: foreach my $outputformat ('html','csv','excel') {
1613: my $option = '<option value="'.$outputformat.'"';
1614: if ($outputformat eq $env{'form.output'}) {
1615: $option .= ' selected="selected"';
1616: }
1617: $option .='>'.$lt{$outputformat}.'</option>';
1618: $output_selector .= "\n".$option;
1619: }
1620: $output_selector .= '</select>';
1621: $r->print('<span class="LC_nobreak">'
1622: .&mt('Output Format: [_1]',$output_selector)
1623: .'</span>'.(' 'x3));
1624: }
1625: $r->print('<span class="LC_nobreak">'
1626: .&mt('User Status: [_1]',$status_select)
1627: .'</span>'.(' 'x3)."\n");
1628: my $roleselected = '';
1629: if ($env{'form.showrole'} eq 'Any') {
1630: $roleselected = ' selected="selected"';
1631: }
1632: my ($cnum,$cdom);
1633: $r->print(&role_filter($context));
1634: if ($context eq 'course') {
1635: ($cnum,$cdom) = &get_course_identity();
1636: $r->print(§ion_group_filter($cnum,$cdom));
1637: }
1638: $r->print('</div><div class="LC_left_float">'.
1639: &column_checkboxes($context,$mode,$formname,$showcredits).
1640: '</div>');
1641: if ($env{'form.phase'} eq '') {
1642: $r->print('<br clear="all" />'.
1643: &list_submit_button(&mt('Display List of Users'))."\n".
1644: '<input type="hidden" name="phase" value="" /></form>');
1645: return;
1646: }
1647: if (!(($context eq 'domain') &&
1648: (($env{'form.roletype'} eq 'course') || ($env{'form.roletype'} eq 'community')))) {
1649: $r->print('<br clear="all" />'.
1650: &list_submit_button(&mt('Update Display'))."\n");
1651: }
1652:
1653: my @cols = &infocolumns($context,$mode,$showcredits);
1654: if (!@cols) {
1655: $r->print('<hr style="clear:both;" /><span class="LC_warning">'.
1656: &mt('No user information selected for display.').'</span>'.
1657: '<input type="hidden" name="phase" value="display" /></form>'."\n");
1658: return;
1659: }
1660: my ($indexhash,$keylist) = &make_keylist_array();
1661: my (%userlist,%userinfo,$clearcoursepick,$needauthorquota,$needauthorusage);
1662: if (($context eq 'domain') &&
1663: ($env{'form.roletype'} eq 'course') ||
1664: ($env{'form.roletype'} eq 'community')) {
1665: my ($crstype,$numcodes,$title,$warning);
1666: if ($env{'form.roletype'} eq 'course') {
1667: $crstype = 'Course';
1668: $numcodes = $totcodes;
1669: $title = &mt('Select Courses');
1670: $warning = &mt('Warning: data retrieval for multiple courses can take considerable time, as this operation is not currently optimized.');
1671: } elsif ($env{'form.roletype'} eq 'community') {
1672: $crstype = 'Community';
1673: $numcodes = 0;
1674: $title = &mt('Select Communities');
1675: $warning = &mt('Warning: data retrieval for multiple communities can take considerable time, as this operation is not currently optimized.');
1676: }
1677: my @standardnames = &Apache::loncommon::get_standard_codeitems();
1678: my $courseform =
1679: &Apache::lonhtmlcommon::course_selection($formname,$numcodes,
1680: $codetitles,$idlist,$idlist_titles,$crstype,
1681: \@standardnames);
1682: $r->print('<div class="LC_left_float">'.
1683: '<fieldset><legend>'.$title.'</legend>'."\n".
1684: $courseform."\n".
1685: '</fieldset></div><br clear="all" />'.
1686: '<p><input type="hidden" name="origroletype" value="'.$env{'form.roletype'}.'" />'.
1687: &list_submit_button(&mt('Update Display')).
1688: "\n".'</p><span class="LC_warning">'.$warning.'</span>'."\n");
1689: $clearcoursepick = 0;
1690: if (($env{'form.origroletype'} ne '') &&
1691: ($env{'form.origroletype'} ne $env{'form.roletype'})) {
1692: $clearcoursepick = 1;
1693: }
1694: if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
1695: $r->print('<hr />'.&mt('Searching ...').'<br /> <br />');
1696: }
1697: } else {
1698: $r->print('<hr style="clear:both;" /><div id="searching">'.&mt('Searching ...').'</div>');
1699: }
1700: $r->rflush();
1701: if ($context eq 'course') {
1702: if (($env{'form.showrole'} eq 'st') || ($env{'form.showrole'} eq 'Any')) {
1703: my $classlist = &Apache::loncoursedata::get_classlist();
1704: if (ref($classlist) eq 'HASH') {
1705: %userlist = %{$classlist};
1706: }
1707: }
1708: if ($env{'form.showrole'} ne 'st') {
1709: my $showroles;
1710: if ($env{'form.showrole'} ne 'Any') {
1711: $showroles = [$env{'form.showrole'}];
1712: } else {
1713: $showroles = undef;
1714: }
1715: my $withsec = 1;
1716: my $hidepriv = 1;
1717: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
1718: \@statuses,$showroles,undef,$withsec,$hidepriv);
1719: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1720: \%advrolehash,$permission);
1721: }
1722: } else {
1723: my (%cstr_roles,%dom_roles);
1724: if ($context eq 'author') {
1725: # List co-authors and assistant co-authors
1726: my @possroles = &roles_by_context($context);
1727: %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
1728: \@statuses,\@possroles);
1729: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1730: \%cstr_roles,$permission);
1731: } elsif ($context eq 'domain') {
1732: if ($env{'form.roletype'} eq 'domain') {
1733: if (grep(/^authorusage$/,@cols)) {
1734: $needauthorusage = 1;
1735: }
1736: if (grep(/^authorquota$/,@cols)) {
1737: $needauthorquota = 1;
1738: }
1739: %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'});
1740: foreach my $key (keys(%dom_roles)) {
1741: if (ref($dom_roles{$key}) eq 'HASH') {
1742: &gather_userinfo($context,$format,\%userlist,$indexhash,
1743: \%userinfo,$dom_roles{$key},$permission);
1744: }
1745: }
1746: } elsif ($env{'form.roletype'} eq 'author') {
1747: my %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'},['au']);
1748: my %coauthors;
1749: foreach my $key (keys(%dom_roles)) {
1750: if (ref($dom_roles{$key}) eq 'HASH') {
1751: if ($env{'form.showrole'} eq 'au') {
1752: &gather_userinfo($context,$format,\%userlist,$indexhash,
1753: \%userinfo,$dom_roles{$key},$permission);
1754: } else {
1755: my @possroles;
1756: if ($env{'form.showrole'} eq 'Any') {
1757: @possroles = &roles_by_context('author');
1758: } else {
1759: @possroles = ($env{'form.showrole'});
1760: }
1761: foreach my $author (sort(keys(%{$dom_roles{$key}}))) {
1762: my ($role,$authorname,$authordom) = split(/:/,$author,-1);
1763: my $extent = '/'.$authordom.'/'.$authorname;
1764: %{$coauthors{$extent}} =
1765: &Apache::lonnet::get_my_roles($authorname,
1766: $authordom,undef,\@statuses,\@possroles);
1767: }
1768: &gather_userinfo($context,$format,\%userlist,
1769: $indexhash,\%userinfo,\%coauthors,$permission);
1770: }
1771: }
1772: }
1773: } elsif (($env{'form.roletype'} eq 'course') ||
1774: ($env{'form.roletype'} eq 'community')) {
1775: if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
1776: my %courses = &process_coursepick();
1777: my %allusers;
1778: my $hidepriv = 1;
1779: foreach my $cid (keys(%courses)) {
1780: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
1781: next if ($cnum eq '' || $cdom eq '');
1782: my $custom = 1;
1783: my (@roles,@sections,%access,%users,%userdata,
1784: %statushash);
1785: if ($env{'form.showrole'} eq 'Any') {
1786: @roles = &course_roles($context,undef,$custom,
1787: $env{'form.roletype'});
1788: } else {
1789: @roles = ($env{'form.showrole'});
1790: }
1791: foreach my $role (@roles) {
1792: %{$users{$role}} = ();
1793: }
1794: foreach my $type (@statuses) {
1795: $access{$type} = $type;
1796: }
1797: &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\@sections,\%users,\%userdata,\%statushash,$hidepriv);
1798: foreach my $user (keys(%userdata)) {
1799: next if (ref($userinfo{$user}) eq 'HASH');
1800: foreach my $item ('fullname','id') {
1801: $userinfo{$user}{$item} = $userdata{$user}[$indexhash->{$item}];
1802: }
1803: }
1804: foreach my $role (keys(%users)) {
1805: foreach my $user (keys(%{$users{$role}})) {
1806: my $uniqid = $user.':'.$role;
1807: $allusers{$uniqid}{$cid} = { desc => $cdesc,
1808: secs => $statushash{$user}{$role},
1809: };
1810: }
1811: }
1812: }
1813: &gather_userinfo($context,$format,\%userlist,$indexhash,
1814: \%userinfo,\%allusers,$permission);
1815: } else {
1816: $r->print('<input type="hidden" name="phase" value="'.
1817: $env{'form.phase'}.'" /></form>');
1818: return;
1819: }
1820: }
1821: }
1822: }
1823: if (keys(%userlist) == 0) {
1824: my $msg = '';
1825: if ($context eq 'author') {
1826: $msg = &mt('There are no co-authors to display.');
1827: } elsif ($context eq 'domain') {
1828: if ($env{'form.roletype'} eq 'domain') {
1829: $msg = &mt('There are no users with domain roles to display.');
1830: } elsif ($env{'form.roletype'} eq 'author') {
1831: $msg = &mt('There are no authors or co-authors to display.');
1832: } elsif ($env{'form.roletype'} eq 'course') {
1833: $msg = &mt('There are no course users to display');
1834: } elsif ($env{'form.roletype'} eq 'community') {
1835: $msg = &mt('There are no community users to display');
1836: }
1837: } elsif ($context eq 'course') {
1838: $r->print(&mt('There are no course users to display.')."\n");
1839: }
1840: $r->print('<p class="LC_info">'.$msg.'</p>'."\n") if $msg;
1841: } else {
1842: # Print out the available choices
1843: my $usercount;
1844: if ($env{'form.action'} eq 'modifystudent') {
1845: ($usercount) = &show_users_list($r,$context,'view',$permission,
1846: $env{'form.Status'},\%userlist,$keylist,'',
1847: $showcredits);
1848: } else {
1849: ($usercount) = &show_users_list($r,$context,$env{'form.output'},
1850: $permission,$env{'form.Status'},\%userlist,
1851: $keylist,'',$showcredits,$needauthorquota,$needauthorusage);
1852: }
1853: if (!$usercount) {
1854: $r->print('<br /><span class="LC_info">'
1855: .&mt('There are no users matching the search criteria.')
1856: .'</span>'
1857: );
1858: }
1859: }
1860: $r->print('<input type="hidden" name="phase" value="'.
1861: $env{'form.phase'}.'" /></form>');
1862: return;
1863: }
1864:
1865: sub role_filter {
1866: my ($context) = @_;
1867: my $output;
1868: my $roleselected = '';
1869: if ($env{'form.showrole'} eq 'Any') {
1870: $roleselected = ' selected="selected"';
1871: }
1872: my ($role_select);
1873: if ($context eq 'domain') {
1874: $role_select = &domain_roles_select();
1875: $output = '<span class="LC_nobreak">'
1876: .&mt('Role Type: [_1]',$role_select)
1877: .'</span>';
1878: } else {
1879: $role_select = '<select name="showrole" onchange="javascript:updateCols('."'showrole'".');">'."\n".
1880: '<option value="Any" '.$roleselected.'>'.
1881: &mt('Any role').'</option>';
1882: my ($roletype,$crstype);
1883: if ($context eq 'course') {
1884: $crstype = &Apache::loncommon::course_type();
1885: if ($crstype eq 'Community') {
1886: $roletype = 'community';
1887: } else {
1888: $roletype = 'course';
1889: }
1890: }
1891: my @poss_roles = &curr_role_permissions($context,'','',$roletype);
1892: foreach my $role (@poss_roles) {
1893: $roleselected = '';
1894: if ($role eq $env{'form.showrole'}) {
1895: $roleselected = ' selected="selected"';
1896: }
1897: my $plrole;
1898: if ($role eq 'cr') {
1899: $plrole = &mt('Custom role');
1900: } else {
1901: $plrole=&Apache::lonnet::plaintext($role,$crstype);
1902: }
1903: $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>';
1904: }
1905: $role_select .= '</select>';
1906: $output = '<span class="LC_nobreak">'
1907: .&mt('Role: [_1]',$role_select)
1908: .'</span>';
1909: }
1910: return $output;
1911: }
1912:
1913: sub section_group_filter {
1914: my ($cnum,$cdom) = @_;
1915: my @filters;
1916: if ($env{'request.course.sec'} eq '') {
1917: @filters = ('sec');
1918: }
1919: push(@filters,'grp');
1920: my %name = (
1921: sec => 'secfilter',
1922: grp => 'grpfilter',
1923: );
1924: my %title = &Apache::lonlocal::texthash (
1925: sec => 'Section(s)',
1926: grp => 'Group(s)',
1927: all => 'all',
1928: none => 'none',
1929: );
1930: my $output;
1931: foreach my $item (@filters) {
1932: my ($markup,@options);
1933: if ($env{'form.'.$name{$item}} eq '') {
1934: $env{'form.'.$name{$item}} = 'all';
1935: }
1936: if ($item eq 'sec') {
1937: if (($env{'form.showrole'} eq 'cc') || ($env{'form.showrole'} eq 'co')) {
1938: $env{'form.'.$name{$item}} = 'none';
1939: }
1940: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
1941: @options = sort(keys(%sections_count));
1942: } elsif ($item eq 'grp') {
1943: my %curr_groups = &Apache::longroup::coursegroups();
1944: @options = sort(keys(%curr_groups));
1945: }
1946: if (@options > 0) {
1947: my $currsel;
1948: $markup = '<select name="'.$name{$item}.'">'."\n";
1949: foreach my $option ('all','none',@options) {
1950: $currsel = '';
1951: if ($env{'form.'.$name{$item}} eq $option) {
1952: $currsel = ' selected="selected"';
1953: }
1954: $markup .= ' <option value="'.$option.'"'.$currsel.'>';
1955: if (($option eq 'all') || ($option eq 'none')) {
1956: $markup .= $title{$option};
1957: } else {
1958: $markup .= $option;
1959: }
1960: $markup .= '</option>'."\n";
1961: }
1962: $markup .= '</select>'."\n";
1963: $output .= (' 'x3).'<span class="LC_nobreak">'
1964: .'<label>'.$title{$item}.': '.$markup.'</label>'
1965: .'</span> ';
1966: }
1967: }
1968: return $output;
1969: }
1970:
1971: sub infocolumns {
1972: my ($context,$mode,$showcredits) = @_;
1973: my @cols;
1974: if (($mode eq 'pickauthor') || ($mode eq 'autoenroll')) {
1975: @cols = &get_cols_array($context,$mode,$showcredits);
1976: } else {
1977: my @posscols = &get_cols_array($context,$mode,$showcredits);
1978: if ($env{'form.phase'} ne '') {
1979: my @checkedcols = &Apache::loncommon::get_env_multiple('form.showcol');
1980: foreach my $col (@checkedcols) {
1981: if (grep(/^$col$/,@posscols)) {
1982: push(@cols,$col);
1983: }
1984: }
1985: } else {
1986: @cols = @posscols;
1987: }
1988: }
1989: return @cols;
1990: }
1991:
1992: sub get_cols_array {
1993: my ($context,$mode,$showcredits) = @_;
1994: my @cols;
1995: if ($mode eq 'pickauthor') {
1996: @cols = ('username','fullname','status','email');
1997: } else {
1998: @cols = ('username','domain','id','fullname');
1999: if ($context eq 'course') {
2000: push(@cols,'section');
2001: }
2002: push(@cols,('start','end','role'));
2003: unless (($mode eq 'autoenroll') && ($env{'form.Status'} ne 'Any')) {
2004: push(@cols,'status');
2005: }
2006: if ($context eq 'course') {
2007: push(@cols,'groups');
2008: }
2009: push(@cols,'email');
2010: if (($context eq 'course') && ($mode ne 'autoenroll')) {
2011: if ($showcredits) {
2012: push(@cols,'credits');
2013: }
2014: push(@cols,'lastlogin','clicker');
2015: }
2016: if (($context eq 'course') && ($mode ne 'autoenroll') &&
2017: ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'})) {
2018: push(@cols,'photo');
2019: }
2020: if ($context eq 'domain') {
2021: push (@cols,('authorusage','authorquota','extent'));
2022: }
2023: }
2024: return @cols;
2025: }
2026:
2027: sub column_checkboxes {
2028: my ($context,$mode,$formname,$showcredits) = @_;
2029: my @cols = &get_cols_array($context,$mode,$showcredits);
2030: my @showncols = &Apache::loncommon::get_env_multiple('form.showcol');
2031: my (%disabledchk,%unchecked);
2032: if ($env{'form.phase'} eq '') {
2033: $disabledchk{'status'} = 1;
2034: if ($context eq 'course') {
2035: $disabledchk{'role'} = 1;
2036: $unchecked{'photo'} = 1;
2037: $unchecked{'clicker'} = 1;
2038: if ($showcredits) {
2039: $unchecked{'credits'} = 1;
2040: }
2041: } elsif ($context eq 'domain') {
2042: $unchecked{'extent'} = 1;
2043: }
2044: $unchecked{'start'} = 1;
2045: $unchecked{'end'} = 1;
2046: } else {
2047: if ($env{'form.Status'} ne 'Any') {
2048: $disabledchk{'status'} = 1;
2049: }
2050: if (($env{'form.showrole'} ne 'Any') && ($env{'form.showrole'} ne 'cr')) {
2051: $disabledchk{'role'} = 1;
2052: }
2053: if ($context eq 'domain') {
2054: if (($env{'form.roletype'} eq 'course') ||
2055: ($env{'form.roletype'} eq 'community')) {
2056: $disabledchk{'status'} = 1;
2057: $disabledchk{'authorusage'} = 1;
2058: $disabledchk{'authorquota'} = 1;
2059: } elsif ($env{'form.roletype'} eq 'domain') {
2060: $disabledchk{'extent'} = 1;
2061: }
2062: }
2063: }
2064: my $numposs = scalar(@cols);
2065: my $numinrow = 7;
2066: my %lt = &get_column_names($context);
2067: my $output = '<fieldset><legend>'.&mt('Information to show').'</legend>'."\n".'<span class="LC_nobreak">'.
2068: '<input type="button" onclick="javascript:checkAll(document.'.$formname.'.showcol);" value="'.&mt('check all').'" />'.
2069: (' 'x3).
2070: '<input type="button" onclick="javascript:uncheckAll(document.'.$formname.'.showcol);" value="'.&mt('uncheck all').'" />'.
2071: '</span><table>';
2072:
2073: for (my $i=0; $i<$numposs; $i++) {
2074: my $rem = $i%($numinrow);
2075: if ($rem == 0) {
2076: if ($i > 0) {
2077: $output .= '</tr>';
2078: }
2079: $output .= '<tr>';
2080: }
2081: my $checked;
2082: if ($env{'form.phase'} eq '') {
2083: $checked = ' checked="checked"';
2084: if ($unchecked{$cols[$i]}) {
2085: $checked = '';
2086: }
2087: if ($disabledchk{$cols[$i]}) {
2088: $checked = ' disabled="disabled"';
2089: }
2090: } elsif (grep(/^\Q$cols[$i]\E$/,@showncols)) {
2091: $checked = ' checked="checked"';
2092: } elsif ($disabledchk{$cols[$i]}) {
2093: $checked = ' disabled="disabled"';
2094: }
2095: if ($i == $numposs-1) {
2096: my $colsleft = $numinrow-$rem;
2097: if ($colsleft > 1) {
2098: $output .= '<td colspan="'.$colsleft.'">';
2099: } else {
2100: $output .= '<td>';
2101: }
2102: } else {
2103: $output .= '<td>';
2104: }
2105: my $style;
2106: if ($cols[$i] eq 'extent') {
2107: if (($env{'form.roletype'} eq 'domain') || ($env{'form.roletype'} eq '')) {
2108: $style = ' style="display: none;"';
2109: }
2110: } elsif (($cols[$i] eq 'authorusage') || ($cols[$i] eq 'authorquota')) {
2111: if ($env{'form.roletype'} ne 'domain') {
2112: $style = ' style="display: none;"';
2113: }
2114: }
2115: $output .= '<span id="show'.$cols[$i].'"'.$style.'><label>'.
2116: '<input id="showcol'.$cols[$i].'" type="checkbox" name="showcol" value="'.$cols[$i].'"'.$checked.' /><span id="showcoltext'.$cols[$i].'">'.
2117: $lt{$cols[$i]}.'</span>'.
2118: '</label></span></td>';
2119: }
2120: $output .= '</tr></table></fieldset>';
2121: return $output;
2122: }
2123:
2124: sub list_submit_button {
2125: my ($text) = @_;
2126: return '<input type="button" name="updatedisplay" value="'.$text.'" onclick="javascript:display_update()" />';
2127: }
2128:
2129: sub get_column_names {
2130: my ($context) = @_;
2131: my %lt = &Apache::lonlocal::texthash(
2132: 'username' => "username",
2133: 'domain' => "domain",
2134: 'id' => 'ID',
2135: 'fullname' => "name",
2136: 'section' => "section",
2137: 'groups' => "active groups",
2138: 'start' => "start date",
2139: 'end' => "end date",
2140: 'status' => "status",
2141: 'role' => "role",
2142: 'credits' => "credits",
2143: 'type' => "enroll type/action",
2144: 'email' => "e-mail address",
2145: 'photo' => "photo",
2146: 'lastlogin' => "last login",
2147: 'extent' => "extent",
2148: 'authorusage' => "disk usage (%)",
2149: 'authorquota' => "disk quota (MB)",
2150: 'ca' => "check all",
2151: 'ua' => "uncheck all",
2152: 'clicker' => "clicker-ID",
2153: );
2154: if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
2155: $lt{'extent'} = &mt('course(s): description, section(s), status');
2156: } elsif ($context eq 'domain' && $env{'form.roletype'} eq 'community') {
2157: $lt{'extent'} = &mt('community(s): description, section(s), status');
2158: } elsif (($context eq 'author') ||
2159: ($context eq 'domain' && $env{'form.roletype'} eq 'author')) {
2160: $lt{'extent'} = &mt('author');
2161: }
2162: return %lt;
2163: }
2164:
2165: sub gather_userinfo {
2166: my ($context,$format,$userlist,$indexhash,$userinfo,$rolehash,$permission) = @_;
2167: my $viewablesec;
2168: if ($context eq 'course') {
2169: $viewablesec = &viewable_section($permission);
2170: }
2171: foreach my $item (keys(%{$rolehash})) {
2172: my %userdata;
2173: if ($context eq 'author') {
2174: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
2175: split(/:/,$item);
2176: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
2177: &build_user_record($context,\%userdata,$userinfo,$indexhash,
2178: $item,$userlist);
2179: } elsif ($context eq 'course') {
2180: ($userdata{'username'},$userdata{'domain'},$userdata{'role'},
2181: $userdata{'section'}) = split(/:/,$item,-1);
2182: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
2183: if (($viewablesec ne '') && ($userdata{'section'} ne '')) {
2184: next if ($viewablesec ne $userdata{'section'});
2185: }
2186: &build_user_record($context,\%userdata,$userinfo,$indexhash,
2187: $item,$userlist);
2188: } elsif ($context eq 'domain') {
2189: if ($env{'form.roletype'} eq 'domain') {
2190: ($userdata{'role'},$userdata{'username'},$userdata{'domain'}) =
2191: split(/:/,$item);
2192: ($userdata{'end'},$userdata{'start'})=split(/:/,$rolehash->{$item});
2193: &build_user_record($context,\%userdata,$userinfo,$indexhash,
2194: $item,$userlist);
2195: } elsif ($env{'form.roletype'} eq 'author') {
2196: if (ref($rolehash->{$item}) eq 'HASH') {
2197: $userdata{'extent'} = $item;
2198: foreach my $key (keys(%{$rolehash->{$item}})) {
2199: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) = split(/:/,$key);
2200: ($userdata{'start'},$userdata{'end'}) =
2201: split(/:/,$rolehash->{$item}{$key});
2202: my $uniqid = $key.':'.$item;
2203: &build_user_record($context,\%userdata,$userinfo,
2204: $indexhash,$uniqid,$userlist);
2205: }
2206: }
2207: } elsif (($env{'form.roletype'} eq 'course') ||
2208: ($env{'form.roletype'} eq 'community')) {
2209: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
2210: split(/:/,$item);
2211: if (ref($rolehash->{$item}) eq 'HASH') {
2212: my $numcids = keys(%{$rolehash->{$item}});
2213: foreach my $cid (sort(keys(%{$rolehash->{$item}}))) {
2214: if (ref($rolehash->{$item}{$cid}) eq 'HASH') {
2215: my $spanstart = '';
2216: my $spanend = '; ';
2217: my $space = ', ';
2218: if ($format eq 'html' || $format eq 'view') {
2219: $spanstart = '<span class="LC_nobreak">';
2220: # FIXME: actions on courses disabled for now
2221: # if ($permission->{'cusr'}) {
2222: # if ($numcids > 1) {
2223: # $spanstart .= '<input type="radio" name="'.$item.'" value="'.$cid.'" /> ';
2224: # } else {
2225: # $spanstart .= '<input type="hidden" name="'.$item.'" value="'.$cid.'" /> ';
2226: # }
2227: # }
2228: $spanend = '</span><br />';
2229: $space = ', ';
2230: }
2231: $userdata{'extent'} .= $spanstart.
2232: $rolehash->{$item}{$cid}{'desc'}.$space;
2233: if (ref($rolehash->{$item}{$cid}{'secs'}) eq 'HASH') {
2234: foreach my $sec (sort(keys(%{$rolehash->{$item}{$cid}{'secs'}}))) {
2235: if (($env{'form.Status'} eq 'Any') ||
2236: ($env{'form.Status'} eq $rolehash->{$item}{$cid}{'secs'}{$sec})) {
2237: $userdata{'extent'} .= $sec.$space.$rolehash->{$item}{$cid}{'secs'}{$sec}.$spanend;
2238: $userdata{'status'} = $rolehash->{$item}{$cid}{'secs'}{$sec};
2239: }
2240: }
2241: }
2242: }
2243: }
2244: }
2245: if ($userdata{'status'} ne '') {
2246: &build_user_record($context,\%userdata,$userinfo,
2247: $indexhash,$item,$userlist);
2248: }
2249: }
2250: }
2251: }
2252: return;
2253: }
2254:
2255: sub build_user_record {
2256: my ($context,$userdata,$userinfo,$indexhash,$record_key,$userlist) = @_;
2257: next if ($userdata->{'start'} eq '-1' && $userdata->{'end'} eq '-1');
2258: if (!(($context eq 'domain') && (($env{'form.roletype'} eq 'course')
2259: && ($env{'form.roletype'} eq 'community')))) {
2260: &process_date_info($userdata);
2261: }
2262: my $username = $userdata->{'username'};
2263: my $domain = $userdata->{'domain'};
2264: if (ref($userinfo->{$username.':'.$domain}) eq 'HASH') {
2265: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
2266: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
2267: } else {
2268: &aggregate_user_info($domain,$username,$userinfo);
2269: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
2270: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
2271: }
2272: foreach my $key (keys(%{$indexhash})) {
2273: if (defined($userdata->{$key})) {
2274: $userlist->{$record_key}[$indexhash->{$key}] = $userdata->{$key};
2275: }
2276: }
2277: return;
2278: }
2279:
2280: sub courses_selector {
2281: my ($cdom,$formname) = @_;
2282: my %coursecodes = ();
2283: my %codes = ();
2284: my @codetitles = ();
2285: my %cat_titles = ();
2286: my %cat_order = ();
2287: my %idlist = ();
2288: my %idnums = ();
2289: my %idlist_titles = ();
2290: my $caller = 'global';
2291: my $format_reply;
2292: my $jscript = '';
2293:
2294: my $totcodes = 0;
2295: $totcodes =
2296: &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,
2297: $cdom,$totcodes);
2298: if ($totcodes > 0) {
2299: $format_reply =
2300: &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,
2301: \%codes,\@codetitles,\%cat_titles,\%cat_order);
2302: if ($format_reply eq 'ok') {
2303: my $numtypes = @codetitles;
2304: &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
2305: my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
2306: my $longtitles_str = join('","',@{$longtitles});
2307: my $allidlist = $idlist{$codetitles[0]};
2308: $jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist);
2309: $jscript .= $scripttext;
2310: $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,@codetitles);
2311: }
2312: }
2313: my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom);
2314:
2315: my %elements = (
2316: Year => 'selectbox',
2317: coursepick => 'radio',
2318: coursetotal => 'text',
2319: courselist => 'text',
2320: );
2321: $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements);
2322: if ($env{'form.coursepick'} eq 'category') {
2323: $jscript .= qq|
2324: function setCourseCat(formname) {
2325: if (formname.Year.options[formname.Year.selectedIndex].value == -1) {
2326: return;
2327: }
2328: courseSet('$codetitles[0]');
2329: for (var j=0; j<formname.Semester.length; j++) {
2330: if (formname.Semester.options[j].value == "$env{'form.Semester'}") {
2331: formname.Semester.options[j].selected = true;
2332: }
2333: }
2334: if (formname.Semester.options[formname.Semester.selectedIndex].value == -1) {
2335: return;
2336: }
2337: courseSet('$codetitles[1]');
2338: for (var j=0; j<formname.Department.length; j++) {
2339: if (formname.Department.options[j].value == "$env{'form.Department'}") { formname.Department.options[j].selected = true;
2340: }
2341: }
2342: if (formname.Department.options[formname.Department.selectedIndex].value == -1) {
2343: return;
2344: }
2345: courseSet('$codetitles[2]');
2346: for (var j=0; j<formname.Number.length; j++) {
2347: if (formname.Number.options[j].value == "$env{'form.Number'}") {
2348: formname.Number.options[j].selected = true;
2349: }
2350: }
2351: }
2352: |;
2353: }
2354: return ($cb_jscript,$jscript,$totcodes,\@codetitles,\%idlist,
2355: \%idlist_titles);
2356: }
2357:
2358: sub course_selector_loadcode {
2359: my ($formname) = @_;
2360: my $loadcode;
2361: if ($env{'form.coursepick'} ne '') {
2362: $loadcode = 'javascript:setFormElements(document.'.$formname.')';
2363: if ($env{'form.coursepick'} eq 'category') {
2364: $loadcode .= ';javascript:setCourseCat(document.'.$formname.')';
2365: }
2366: }
2367: return $loadcode;
2368: }
2369:
2370: sub process_coursepick {
2371: my $coursefilter = $env{'form.coursepick'};
2372: my $cdom = $env{'request.role.domain'};
2373: my %courses;
2374: my $crssrch = 'Course';
2375: if ($env{'form.roletype'} eq 'community') {
2376: $crssrch = 'Community';
2377: }
2378: if ($coursefilter eq 'all') {
2379: %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.',
2380: undef,undef,$crssrch);
2381: } elsif ($coursefilter eq 'category') {
2382: my $instcode = &instcode_from_coursefilter();
2383: %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.',
2384: undef,undef,$crssrch);
2385: } elsif ($coursefilter eq 'specific') {
2386: if ($env{'form.coursetotal'} > 1) {
2387: my @course_ids = split(/&&/,$env{'form.courselist'});
2388: foreach my $cid (@course_ids) {
2389: $courses{$cid} = '';
2390: }
2391: } else {
2392: $courses{$env{'form.courselist'}} = '';
2393: }
2394: }
2395: return %courses;
2396: }
2397:
2398: sub instcode_from_coursefilter {
2399: my $instcode = '';
2400: my @cats = ('Semester','Year','Department','Number');
2401: foreach my $category (@cats) {
2402: if (defined($env{'form.'.$category})) {
2403: unless ($env{'form.'.$category} eq '-1') {
2404: $instcode .= $env{'form.'.$category};
2405: }
2406: }
2407: }
2408: if ($instcode eq '') {
2409: $instcode = '.';
2410: }
2411: return $instcode;
2412: }
2413:
2414: sub make_keylist_array {
2415: my ($index,$keylist);
2416: $index->{'domain'} = &Apache::loncoursedata::CL_SDOM();
2417: $index->{'username'} = &Apache::loncoursedata::CL_SNAME();
2418: $index->{'end'} = &Apache::loncoursedata::CL_END();
2419: $index->{'start'} = &Apache::loncoursedata::CL_START();
2420: $index->{'id'} = &Apache::loncoursedata::CL_ID();
2421: $index->{'section'} = &Apache::loncoursedata::CL_SECTION();
2422: $index->{'fullname'} = &Apache::loncoursedata::CL_FULLNAME();
2423: $index->{'status'} = &Apache::loncoursedata::CL_STATUS();
2424: $index->{'type'} = &Apache::loncoursedata::CL_TYPE();
2425: $index->{'lockedtype'} = &Apache::loncoursedata::CL_LOCKEDTYPE();
2426: $index->{'groups'} = &Apache::loncoursedata::CL_GROUP();
2427: $index->{'email'} = &Apache::loncoursedata::CL_PERMANENTEMAIL();
2428: $index->{'role'} = &Apache::loncoursedata::CL_ROLE();
2429: $index->{'extent'} = &Apache::loncoursedata::CL_EXTENT();
2430: $index->{'photo'} = &Apache::loncoursedata::CL_PHOTO();
2431: $index->{'thumbnail'} = &Apache::loncoursedata::CL_THUMBNAIL();
2432: $index->{'credits'} = &Apache::loncoursedata::CL_CREDITS();
2433: $index->{'instsec'} = &Apache::loncoursedata::CL_INSTSEC();
2434: $index->{'authorquota'} = &Apache::loncoursedata::CL_AUTHORQUOTA();
2435: $index->{'authorusage'} = &Apache::loncoursedata::CL_AUTHORUSAGE();
2436: foreach my $key (keys(%{$index})) {
2437: $keylist->[$index->{$key}] = $key;
2438: }
2439: return ($index,$keylist);
2440: }
2441:
2442: sub aggregate_user_info {
2443: my ($udom,$uname,$userinfo) = @_;
2444: my %info=&Apache::lonnet::get('environment',
2445: ['firstname','middlename',
2446: 'lastname','generation','id'],
2447: $udom,$uname);
2448: my ($tmp) = keys(%info);
2449: my ($fullname,$id);
2450: if ($tmp =~/^(con_lost|error|no_such_host)/i) {
2451: $fullname = 'not available';
2452: $id = 'not available';
2453: &Apache::lonnet::logthis('unable to retrieve environment '.
2454: 'for '.$uname.':'.$udom);
2455: } else {
2456: $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
2457: $id = $info{'id'};
2458: }
2459: $userinfo->{$uname.':'.$udom} = {
2460: fullname => $fullname,
2461: id => $id,
2462: };
2463: return;
2464: }
2465:
2466: sub process_date_info {
2467: my ($userdata) = @_;
2468: my $now = time;
2469: $userdata->{'status'} = 'Active';
2470: if ($userdata->{'start'} > 0) {
2471: if ($now < $userdata->{'start'}) {
2472: $userdata->{'status'} = 'Future';
2473: }
2474: }
2475: if ($userdata->{'end'} > 0) {
2476: if ($now > $userdata->{'end'}) {
2477: $userdata->{'status'} = 'Expired';
2478: }
2479: }
2480: return;
2481: }
2482:
2483: sub show_users_list {
2484: my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist,$formname,
2485: $showcredits,$needauthorquota,$needauthorusage)=@_;
2486: if ($formname eq '') {
2487: $formname = 'studentform';
2488: }
2489: my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
2490: #
2491: # Variables for excel output
2492: my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
2493: #
2494: # Variables for csv output
2495: my ($CSVfile,$CSVfilename);
2496: #
2497: my $sortby = $env{'form.sortby'};
2498: my @sortable = ('username','domain','id','fullname','start','end','email','role');
2499: if ($context eq 'course') {
2500: push(@sortable,('section','groups','type'));
2501: if ($showcredits) {
2502: push(@sortable,'credits');
2503: }
2504: } else {
2505: push(@sortable,'extent');
2506: if (($context eq 'domain') && ($env{'form.roletype'} eq 'domain') &&
2507: (($env{'form.showrole'} eq 'Any') || ($env{'form.showrole'} eq 'au'))) {
2508: push(@sortable,('authorusage','authorquota'));
2509: }
2510: }
2511: if ($mode eq 'pickauthor') {
2512: @sortable = ('username','fullname','email','status');
2513: }
2514: my %is_sortable;
2515: map { $is_sortable{$_} = 1; } @sortable;
2516: unless ($is_sortable{$sortby}) {
2517: $sortby = 'username';
2518: }
2519: my $setting = $env{'form.roletype'};
2520: my ($cid,$cdom,$cnum,$classgroups,$crstype,$defaultcredits);
2521: if ($context eq 'course') {
2522: $cid = $env{'request.course.id'};
2523: $crstype = &Apache::loncommon::course_type();
2524: ($cnum,$cdom) = &get_course_identity($cid);
2525: $defaultcredits = $env{'course.'.$cid.'.internal.defaultcredits'};
2526: ($classgroups) = &Apache::loncoursedata::get_group_memberships(
2527: $userlist,$keylist,$cdom,$cnum);
2528: if ($mode eq 'autoenroll') {
2529: $env{'form.showrole'} = 'st';
2530: } else {
2531: if ($env{'course.'.$cid.'.internal.showphoto'}) {
2532: $r->print('
2533: <script type="text/javascript">
2534: // <![CDATA[
2535: function photowindow(photolink) {
2536: var title = "Photo_Viewer";
2537: var options = "scrollbars=1,resizable=1,menubar=0";
2538: options += ",width=240,height=240";
2539: stdeditbrowser = open(photolink,title,options,"1");
2540: stdeditbrowser.focus();
2541: }
2542: // ]]>
2543: </script>
2544: ');
2545: }
2546: }
2547: } elsif ($context eq 'domain') {
2548: if ($setting eq 'community') {
2549: $crstype = 'Community';
2550: } elsif ($setting eq 'course') {
2551: $crstype = 'Course';
2552: }
2553: }
2554: if ($mode ne 'autoenroll' && $mode ne 'pickauthor') {
2555: my $date_sec_selector = &date_section_javascript($context,$setting,$statusmode);
2556: my $verify_action_js = &bulkaction_javascript($formname);
2557: $r->print(<<END);
2558:
2559: <script type="text/javascript" language="Javascript">
2560: // <![CDATA[
2561:
2562: $verify_action_js
2563:
2564: function username_display_launch(username,domain) {
2565: var target;
2566: if (!document.$formname.usernamelink.length) {
2567: target = document.$formname.usernamelink.value;
2568: } else {
2569: for (var i=0; i<document.$formname.usernamelink.length; i++) {
2570: if (document.$formname.usernamelink[i].checked) {
2571: target = document.$formname.usernamelink[i].value;
2572: }
2573: }
2574: }
2575: if (target == 'modify') {
2576: if (document.$formname.userwin.checked == true) {
2577: var url = '/adm/createuser?srchterm='+username+'&srchdomain='+domain+'&phase=get_user_info&action=singleuser&srchin=dom&srchby=uname&srchtype=exact&popup=1';
2578: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
2579: modifywin = window.open(url,'',options,1);
2580: modifywin.focus();
2581: return;
2582: } else {
2583: document.$formname.srchterm.value=username;
2584: document.$formname.srchdomain.value=domain;
2585: document.$formname.phase.value='get_user_info';
2586: document.$formname.action.value = 'singleuser';
2587: document.$formname.submit();
2588: }
2589: }
2590: if (target == 'aboutme') {
2591: if (document.$formname.userwin.checked == true) {
2592: var url = '/adm/'+domain+'/'+username+'/aboutme?popup=1';
2593: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
2594: aboutmewin = window.open(url,'',options,1);
2595: aboutmewin.focus();
2596: return;
2597: } else {
2598: document.location.href = '/adm/'+domain+'/'+username+'/aboutme';
2599: }
2600: }
2601: if (target == 'track') {
2602: if (document.$formname.userwin.checked == true) {
2603: var url = '/adm/trackstudent?selected_student='+username+':'+domain+'&only_body=1';
2604: var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
2605: var trackwin = window.open(url,'',options,1);
2606: trackwin.focus();
2607: return;
2608: } else {
2609: document.location.href = '/adm/trackstudent?selected_student='+username+':'+domain;
2610: }
2611: }
2612: }
2613: // ]]>
2614: </script>
2615: $date_sec_selector
2616: <input type="hidden" name="state" value="$env{'form.state'}" />
2617: END
2618: }
2619: $r->print(<<END);
2620: <input type="hidden" name="sortby" value="$sortby" />
2621: END
2622: my @cols = &infocolumns($context,$mode,$showcredits);
2623: my %coltxt = &get_column_names($context);
2624: my %acttxt = &Apache::lonlocal::texthash(
2625: 'pr' => "Proceed",
2626: 'ac' => "Action to take for selected users",
2627: 'link' => "Behavior of clickable username link for each user",
2628: 'aboutme' => "Display a user's personal information page",
2629: 'owin' => "Open in a new window",
2630: 'modify' => "Modify a user's information",
2631: 'track' => "View a user's recent activity",
2632: );
2633: my %lt = (%coltxt,%acttxt);
2634: my $rolefilter = $env{'form.showrole'};
2635: if ($env{'form.showrole'} eq 'cr') {
2636: $rolefilter = &mt('custom');
2637: } elsif ($env{'form.showrole'} ne 'Any') {
2638: $rolefilter = &Apache::lonnet::plaintext($env{'form.showrole'},$crstype);
2639: }
2640: my $results_description;
2641: if ($mode ne 'autoenroll') {
2642: $results_description = &results_header_row($rolefilter,$statusmode,
2643: $context,$permission,$mode,$crstype);
2644: $r->print('<b>'.$results_description.'</b><br clear="all" />');
2645: }
2646: my ($output,$actionselect,%canchange,%canchangesec);
2647: if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
2648: if ($mode ne 'autoenroll' && $mode ne 'pickauthor') {
2649: if ($permission->{'cusr'}) {
2650: unless (($context eq 'domain') &&
2651: (($setting eq 'course') || ($setting eq 'community'))) {
2652: $actionselect =
2653: &select_actions($context,$setting,$statusmode,$formname);
2654: }
2655: }
2656: $r->print(<<END);
2657: <input type="hidden" name="srchby" value="uname" />
2658: <input type="hidden" name="srchin" value="dom" />
2659: <input type="hidden" name="srchtype" value="exact" />
2660: <input type="hidden" name="srchterm" value="" />
2661: <input type="hidden" name="srchdomain" value="" />
2662: END
2663: if ($actionselect) {
2664: $output .= <<"END";
2665: <div class="LC_left_float"><fieldset><legend>$lt{'ac'}</legend>
2666: $actionselect
2667: <br/><br /><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.$formname.actionlist)" />
2668: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.$formname.actionlist)" /><br /><input type="button" value="$lt{'pr'}" onclick="javascript:verify_action('actionlist')" /></fieldset></div>
2669: END
2670: my @allroles;
2671: if ($env{'form.showrole'} eq 'Any') {
2672: my $custom = 1;
2673: if ($context eq 'domain') {
2674: @allroles = &roles_by_context($setting,$custom,$crstype);
2675: } else {
2676: @allroles = &roles_by_context($context,$custom,$crstype);
2677: }
2678: } else {
2679: @allroles = ($env{'form.showrole'});
2680: }
2681: foreach my $role (@allroles) {
2682: if ($context eq 'domain') {
2683: if ($setting eq 'domain') {
2684: if (&Apache::lonnet::allowed('c'.$role,
2685: $env{'request.role.domain'})) {
2686: $canchange{$role} = 1;
2687: }
2688: } elsif ($setting eq 'author') {
2689: if (&Apache::lonnet::allowed('c'.$role,
2690: $env{'request.role.domain'})) {
2691: $canchange{$role} = 1;
2692: }
2693: }
2694: } elsif ($context eq 'author') {
2695: if (&Apache::lonnet::allowed('c'.$role,
2696: $env{'user.domain'}.'/'.$env{'user.name'})) {
2697: $canchange{$role} = 1;
2698: }
2699: } elsif ($context eq 'course') {
2700: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
2701: $canchange{$role} = 1;
2702: } elsif ($env{'request.course.sec'} ne '') {
2703: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
2704: $canchangesec{$role} = $env{'request.course.sec'};
2705: }
2706: } elsif ((($role eq 'co') && ($crstype eq 'Community')) ||
2707: (($role eq 'cc') && ($crstype eq 'Course'))) {
2708: if (&is_courseowner($env{'request.course.id'},
2709: $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'})) {
2710: $canchange{$role} = 1;
2711: }
2712: }
2713: }
2714: }
2715: }
2716: $output .= '<div class="LC_left_float"><fieldset><legend>'.$lt{'link'}.'</legend>'.
2717: '<table><tr>';
2718: my @linkdests = ('aboutme');
2719: if ($permission->{'cusr'}) {
2720: unshift (@linkdests,'modify');
2721: }
2722: if (&Apache::lonnet::allowed('vsa', $env{'request.course.id'}) ||
2723: &Apache::lonnet::allowed('vsa', $env{'request.course.id'}.'/'.
2724: $env{'request.course.sec'})) {
2725: push(@linkdests,'track');
2726: }
2727:
2728: $output .= '<td>';
2729: my $usernamelink = $env{'form.usernamelink'};
2730: if ($usernamelink eq '') {
2731: $usernamelink = 'aboutme';
2732: }
2733: foreach my $item (@linkdests) {
2734: my $checkedstr = '';
2735: if ($item eq $usernamelink) {
2736: $checkedstr = ' checked="checked"';
2737: }
2738: $output .= '<span class="LC_nobreak"><label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.' /> '.$lt{$item}.'</label></span><br />';
2739: }
2740: my $checkwin;
2741: if ($env{'form.userwin'}) {
2742: $checkwin = ' checked="checked"';
2743: }
2744: $output .=
2745: '</td><td valign="top" style="border-left: 1px solid;">'
2746: .'<span class="LC_nobreak"><label>'
2747: .'<input type="checkbox" name="userwin" value="1"'.$checkwin.' />'.$lt{'owin'}
2748: .'</label></span></td></tr></table></fieldset></div>';
2749: }
2750: $output .= "\n".'<br clear="all" />'."\n".
2751: &Apache::loncommon::start_data_table().
2752: &Apache::loncommon::start_data_table_header_row();
2753: if ($mode eq 'autoenroll') {
2754: $output .= "
2755: <th><a href=\"javascript:document.$formname.sortby.value='type';document.$formname.submit();\">$lt{'type'}</a></th>
2756: ";
2757: } else {
2758: $output .= "\n".'<th> </th>'."\n";
2759: if ($actionselect) {
2760: $output .= '<th class="LC_nobreak" valign="top">'.&mt('Select').'</th>'."\n";
2761: }
2762: }
2763: foreach my $item (@cols) {
2764: $output .= '<th class="LC_nobreak" valign="top">';
2765: if ($is_sortable{$item}) {
2766: $output .= "<a href=\"javascript:document.$formname.sortby.value='$item';document.$formname.submit();\" style=\"text-decoration:none;\">$lt{$item}<span class=\"LC_fontsize_small\"> ▼</span></a>";
2767: } else {
2768: $output .= $lt{$item};
2769: }
2770: $output .= "</th>\n";
2771: }
2772: my %role_types = &role_type_names();
2773: $output .= &Apache::loncommon::end_data_table_header_row();
2774: # Done with the HTML header line
2775: } elsif ($mode eq 'csv') {
2776: #
2777: # Open a file
2778: $CSVfilename = '/prtspool/'.
2779: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
2780: time.'_'.rand(1000000000).'.csv';
2781: unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
2782: $r->log_error("Couldn't open $CSVfilename for output $!");
2783: $r->print(
2784: '<p class="LC_error">'
2785: .&mt('Problems occurred in writing the CSV file.')
2786: .' '.&mt('This error has been logged.')
2787: .' '.&mt('Please alert your LON-CAPA administrator.')
2788: .'</p>'
2789: );
2790: $CSVfile = undef;
2791: }
2792: #
2793: # Write headers and data to file
2794: print $CSVfile '"'.$results_description.'"'."\n";
2795: print $CSVfile '"'.join('","',map {
2796: &Apache::loncommon::csv_translate($lt{$_})
2797: } (@cols))."\"\n";
2798: } elsif ($mode eq 'excel') {
2799: # Create the excel spreadsheet
2800: ($excel_workbook,$excel_filename,$format) =
2801: &Apache::loncommon::create_workbook($r);
2802: return if (! defined($excel_workbook));
2803: $excel_sheet = $excel_workbook->addworksheet('userlist');
2804: $excel_sheet->write($row++,0,$results_description,$format->{'h2'});
2805: #
2806: my @colnames = map {$lt{$_}} (@cols);
2807:
2808: $excel_sheet->write($row++,0,\@colnames,$format->{'bold'});
2809: }
2810:
2811: # Done with header lines in all formats
2812: my %index;
2813: my $i;
2814: foreach my $idx (@$keylist) {
2815: $index{$idx} = $i++;
2816: }
2817: my $usercount = 0;
2818: my ($secfilter,$grpfilter);
2819: if ($context eq 'course') {
2820: $secfilter = $env{'form.secfilter'};
2821: $grpfilter = $env{'form.grpfilter'};
2822: if ($secfilter eq '') {
2823: $secfilter = 'all';
2824: }
2825: if ($grpfilter eq '') {
2826: $grpfilter = 'all';
2827: }
2828: }
2829: my %ltstatus = &Apache::lonlocal::texthash(
2830: Active => 'Active',
2831: Future => 'Future',
2832: Expired => 'Expired',
2833: );
2834: # If this is for a single course get last course "log-in".
2835: my %crslogins;
2836: if ($context eq 'course') {
2837: %crslogins=&Apache::lonnet::dump('nohist_crslastlogin',$cdom,$cnum);
2838: }
2839: # Get groups, role, permanent e-mail so we can sort on them if
2840: # necessary.
2841: foreach my $user (keys(%{$userlist})) {
2842: if ($user eq '' ) {
2843: delete($userlist->{$user});
2844: next;
2845: }
2846: if ($context eq 'domain' && $user eq $env{'request.role.domain'}.'-domainconfig:'.$env{'request.role.domain'}) {
2847: delete($userlist->{$user});
2848: next;
2849: }
2850: my ($uname,$udom,$role,$groups,$email);
2851: if (($statusmode ne 'Any') &&
2852: ($userlist->{$user}->[$index{'status'}] ne $statusmode)) {
2853: delete($userlist->{$user});
2854: next;
2855: }
2856: if ($context eq 'domain') {
2857: if ($env{'form.roletype'} eq 'domain') {
2858: ($role,$uname,$udom) = split(/:/,$user);
2859: if (($uname eq $env{'request.role.domain'}.'-domainconfig') &&
2860: ($udom eq $env{'request.role.domain'})) {
2861: delete($userlist->{$user});
2862: next;
2863: }
2864: } elsif ($env{'form.roletype'} eq 'author') {
2865: ($uname,$udom,$role) = split(/:/,$user,-1);
2866: } elsif (($env{'form.roletype'} eq 'course') ||
2867: ($env{'form.roletype'} eq 'community')) {
2868: ($uname,$udom,$role) = split(/:/,$user);
2869: }
2870: } else {
2871: ($uname,$udom,$role) = split(/:/,$user,-1);
2872: if (($context eq 'course') && $role eq '') {
2873: $role = 'st';
2874: }
2875: }
2876: $userlist->{$user}->[$index{'role'}] = $role;
2877: if (($env{'form.showrole'} ne 'Any') && (!($env{'form.showrole'} eq 'cr' && $role =~ /^cr\//)) && ($role ne $env{'form.showrole'})) {
2878: delete($userlist->{$user});
2879: next;
2880: }
2881: if ($context eq 'course') {
2882: my @ac_groups;
2883: if (ref($classgroups) eq 'HASH') {
2884: $groups = $classgroups->{$user};
2885: }
2886: if (ref($groups->{'active'}) eq 'HASH') {
2887: @ac_groups = keys(%{$groups->{'active'}});
2888: $userlist->{$user}->[$index{'groups'}] = join(', ',@ac_groups);
2889: }
2890: if ($mode ne 'autoenroll') {
2891: my $section = $userlist->{$user}->[$index{'section'}];
2892: if (($env{'request.course.sec'} ne '') &&
2893: ($section ne $env{'request.course.sec'})) {
2894: if ($role eq 'st') {
2895: delete($userlist->{$user});
2896: next;
2897: }
2898: }
2899: if ($secfilter eq 'none') {
2900: if ($section ne '') {
2901: delete($userlist->{$user});
2902: next;
2903: }
2904: } elsif ($secfilter ne 'all') {
2905: if ($section ne $secfilter) {
2906: delete($userlist->{$user});
2907: next;
2908: }
2909: }
2910: if ($grpfilter eq 'none') {
2911: if (@ac_groups > 0) {
2912: delete($userlist->{$user});
2913: next;
2914: }
2915: } elsif ($grpfilter ne 'all') {
2916: if (!grep(/^\Q$grpfilter\E$/,@ac_groups)) {
2917: delete($userlist->{$user});
2918: next;
2919: }
2920: }
2921: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
2922: if ((grep/^photo$/,@cols) && ($role eq 'st')) {
2923: $userlist->{$user}->[$index{'photo'}] =
2924: &Apache::lonnet::retrievestudentphoto($udom,$uname,'jpg');
2925: $userlist->{$user}->[$index{'thumbnail'}] =
2926: &Apache::lonnet::retrievestudentphoto($udom,$uname,
2927: 'gif','thumbnail');
2928: }
2929: }
2930: if (($role eq 'st') && ($defaultcredits)) {
2931: if ($userlist->{$user}->[$index{'credits'}] eq '') {
2932: $userlist->{$user}->[$index{'credits'}] = $defaultcredits;
2933: }
2934: }
2935: }
2936: }
2937: my %emails = &Apache::loncommon::getemails($uname,$udom);
2938: if ($emails{'permanentemail'} =~ /\S/) {
2939: $userlist->{$user}->[$index{'email'}] = $emails{'permanentemail'};
2940: }
2941: if (($context eq 'domain') && ($env{'form.roletype'} eq 'domain') &&
2942: ($role eq 'au')) {
2943: my ($disk_quota,$current_disk_usage,$percent);
2944: if (($needauthorusage) || ($needauthorquota)) {
2945: $disk_quota = &Apache::loncommon::get_user_quota($uname,$udom,'author');
2946: }
2947: if ($needauthorusage) {
2948: $current_disk_usage =
2949: &Apache::lonnet::diskusage($udom,$uname,"$londocroot/priv/$udom/$uname");
2950: if ($disk_quota == 0) {
2951: $percent = 100.0;
2952: } else {
2953: $percent = $current_disk_usage/(10 * $disk_quota);
2954: }
2955: $userlist->{$user}->[$index{'authorusage'}] = sprintf("%.0f",$percent);
2956: }
2957: if ($needauthorquota) {
2958: $userlist->{$user}->[$index{'authorquota'}] = sprintf("%.2f",$disk_quota);
2959: }
2960: }
2961: $usercount ++;
2962: }
2963: my $autocount = 0;
2964: my $manualcount = 0;
2965: my $lockcount = 0;
2966: my $unlockcount = 0;
2967: if ($usercount) {
2968: $r->print($output);
2969: } else {
2970: if ($mode eq 'autoenroll') {
2971: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
2972: } else {
2973: return;
2974: }
2975: }
2976: #
2977: # Sort the users
2978: my $index = $index{$sortby};
2979: my $second = $index{'username'};
2980: my $third = $index{'domain'};
2981: my @sorted_users;
2982: if (($sortby eq 'authorquota') || ($sortby eq 'authorusage')) {
2983: @sorted_users = sort {
2984: $userlist->{$b}->[$index] <=> $userlist->{$a}->[$index] ||
2985: lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second]) ||
2986: lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
2987: } (keys(%$userlist));
2988: } else {
2989: @sorted_users = sort {
2990: lc($userlist->{$a}->[$index]) cmp lc($userlist->{$b}->[$index]) ||
2991: lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second]) ||
2992: lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
2993: } (keys(%$userlist));
2994: }
2995: my $rowcount = 0;
2996: my $disabled;
2997: if ($mode eq 'autoenroll') {
2998: unless ($permission->{'cusr'}) {
2999: $disabled = ' disabled="disabled"';
3000: }
3001: }
3002: foreach my $user (@sorted_users) {
3003: my %in;
3004: my $sdata = $userlist->{$user};
3005: $rowcount ++;
3006: foreach my $item (@{$keylist}) {
3007: $in{$item} = $sdata->[$index{$item}];
3008: }
3009: my $clickers = (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
3010: if ($clickers!~/\w/) { $clickers='-'; }
3011: $in{'clicker'} = $clickers;
3012: my $role = $in{'role'};
3013: $in{'role'}=&Apache::lonnet::plaintext($sdata->[$index{'role'}],$crstype);
3014: unless ($mode eq 'excel') {
3015: if (! defined($in{'start'}) || $in{'start'} == 0) {
3016: $in{'start'} = &mt('none');
3017: } else {
3018: $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
3019: }
3020: if (! defined($in{'end'}) || $in{'end'} == 0) {
3021: $in{'end'} = &mt('none');
3022: } else {
3023: $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
3024: }
3025: }
3026: if ($context eq 'course') {
3027: my $lastlogin = $crslogins{$in{'username'}.':'.$in{'domain'}.':'.$in{'section'}.':'.$role};
3028: if ($lastlogin ne '') {
3029: $in{'lastlogin'} = &Apache::lonlocal::locallocaltime($lastlogin);
3030: }
3031: }
3032: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
3033: $r->print(&Apache::loncommon::start_data_table_row());
3034: my $checkval;
3035: if ($mode eq 'autoenroll') {
3036: my $cellentry;
3037: if ($in{'type'} eq 'auto') {
3038: $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Change').'</label>';
3039: $autocount ++;
3040: } else {
3041: $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><span class="LC_nobreak"><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Change').'</label></span></td></tr><tr><td><span class="LC_nobreak">';
3042: $manualcount ++;
3043: if ($in{'lockedtype'}) {
3044: $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Unlock').'</label>';
3045: $unlockcount ++;
3046: } else {
3047: $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'"'.$disabled.' /> '.&mt('Lock').'</label>';
3048: $lockcount ++;
3049: }
3050: $cellentry .= '</span></td></tr></table>';
3051: }
3052: $r->print("<td>$cellentry</td>\n");
3053: } else {
3054: if ($mode ne 'pickauthor') {
3055: $r->print("<td>$rowcount</td>\n");
3056: }
3057: if ($actionselect) {
3058: my $showcheckbox;
3059: if ($role =~ /^cr\//) {
3060: $showcheckbox = $canchange{'cr'};
3061: } else {
3062: $showcheckbox = $canchange{$role};
3063: }
3064: if (!$showcheckbox) {
3065: if ($context eq 'course') {
3066: if ($canchangesec{$role} ne '') {
3067: if ($canchangesec{$role} eq $in{'section'}) {
3068: $showcheckbox = 1;
3069: }
3070: }
3071: }
3072: }
3073: if ($showcheckbox) {
3074: $checkval = $user;
3075: if ($context eq 'course') {
3076: if (($role eq 'co' || $role eq 'cc') &&
3077: ($user =~ /^\Q$env{'user.name'}:$env{'user.domain'}:$role\E/)) {
3078: $showcheckbox = 0;
3079: } else {
3080: if ($role eq 'st') {
3081: $checkval .= ':st';
3082: }
3083: $checkval .= ':'.$in{'section'};
3084: if ($role eq 'st') {
3085: $checkval .= ':'.$in{'type'}.':'.
3086: $in{'lockedtype'}.':'.
3087: $in{'credits'}.':'.
3088: &escape($in{'instsec'});
3089: }
3090: }
3091: }
3092: if ($showcheckbox) {
3093: $r->print('<td><input type="checkbox" name="'.
3094: 'actionlist" value="'.&HTML::Entities::encode($checkval,'&<>"').'" /></td>');
3095: } else {
3096: $r->print('<td> </td>');
3097: }
3098: } else {
3099: $r->print('<td> </td>');
3100: }
3101: } elsif ($mode eq 'pickauthor') {
3102: $r->print('<td><input type="button" name="chooseauthor" onclick="javascript:gochoose('."'$in{'username'}'".');" value="'.&mt('Select').'" /></td>');
3103: }
3104: }
3105: foreach my $item (@cols) {
3106: if ($item eq 'username') {
3107: $r->print('<td>'.&print_username_link($mode,\%in).'</td>');
3108: } elsif (($item eq 'start' || $item eq 'end') && ($actionselect)) {
3109: $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.&HTML::Entities::encode($checkval.'_'.$item.'" value="'.$sdata->[$index{$item}],'&<>"').'" /></td>'."\n");
3110: } elsif ($item eq 'status') {
3111: my $showitem = $in{$item};
3112: if (defined($ltstatus{$in{$item}})) {
3113: $showitem = $ltstatus{$in{$item}};
3114: }
3115: $r->print('<td>'.$showitem.'</td>'."\n");
3116: } elsif ($item eq 'photo') {
3117: if (($context eq 'course') && ($mode ne 'autoenroll') &&
3118: ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'})) {
3119: if ($role eq 'st') {
3120: $r->print('<td align="right"><a href="javascript:photowindow('."'".$in{'photo'}."'".')"><img src="'.$in{'thumbnail'}.'" border="1" alt="" /></a></td>');
3121: } else {
3122: $r->print('<td> </td>');
3123: }
3124: }
3125: } elsif ($item eq 'clicker') {
3126: if (($context eq 'course') && ($mode ne 'autoenroll')) {
3127: if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
3128: my $clickers =
3129: (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
3130: if ($clickers!~/\w/) { $clickers='-'; }
3131: $r->print('<td>'.$clickers.'</td>');
3132: } else {
3133: $r->print('<td> </td>'."\n");
3134: }
3135: }
3136: } elsif (($item eq 'authorquota') || ($item eq 'authorusage')) {
3137: $r->print('<td align="right">'.$in{$item}.'</td>'."\n");
3138: } else {
3139: $r->print('<td>'.$in{$item}.'</td>'."\n");
3140: }
3141: }
3142: $r->print(&Apache::loncommon::end_data_table_row());
3143: } elsif ($mode eq 'csv') {
3144: next if (! defined($CSVfile));
3145: # no need to bother with $linkto
3146: my @line = ();
3147: foreach my $item (@cols) {
3148: push @line,&Apache::loncommon::csv_translate($in{$item});
3149: }
3150: print $CSVfile '"'.join('","',@line)."\"\n";
3151: } elsif ($mode eq 'excel') {
3152: my $col = 0;
3153: foreach my $item (@cols) {
3154: if ($item eq 'start' || $item eq 'end') {
3155: if ((defined($in{$item})) && ($in{$item} != 0)) {
3156: $excel_sheet->write($row,$col++,
3157: &Apache::lonstathelpers::calc_serial($in{$item}),
3158: $format->{'date'});
3159: } else {
3160: $excel_sheet->write($row,$col++,'none');
3161: }
3162: } else {
3163: $excel_sheet->write($row,$col++,$in{$item});
3164: }
3165: }
3166: $row++;
3167: }
3168: }
3169: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
3170: $r->print(&Apache::loncommon::end_data_table().'<br />');
3171: } elsif ($mode eq 'excel') {
3172: $excel_workbook->close();
3173: $r->print('<p>'.&mt('[_1]Your Excel spreadsheet[_2] is ready for download.', '<a href="'.$excel_filename.'">','</a>')."</p>\n");
3174: } elsif ($mode eq 'csv') {
3175: close($CSVfile);
3176: $r->print('<p>'.&mt('[_1]Your CSV file[_2] is ready for download.', '<a href="'.$CSVfilename.'">','</a>')."</p>\n");
3177: $r->rflush();
3178: }
3179: if ($mode eq 'autoenroll') {
3180: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
3181: } else {
3182: return ($usercount);
3183: }
3184: }
3185:
3186: sub bulkaction_javascript {
3187: my ($formname,$caller) = @_;
3188: my $docstart = 'document';
3189: if ($caller eq 'popup') {
3190: $docstart = 'opener.document';
3191: }
3192: my %lt = &Apache::lonlocal::texthash(
3193: acwi => 'Access will be set to start immediately',
3194: asyo => 'as you did not select an end date in the pop-up window',
3195: accw => 'Access will be set to continue indefinitely',
3196: asyd => 'as you did not select an end date in the pop-up window',
3197: sewi => "Sections will be switched to 'No section'",
3198: ayes => "as you either selected the 'No section' option",
3199: oryo => 'or you did not select a section in the pop-up window',
3200: arol => 'A role with no section will be added',
3201: swbs => 'Sections will be switched to:',
3202: rwba => 'Roles will be added for section(s):',
3203: );
3204: my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox");
3205: my $noaction = &mt("You need to select an action to take for the user(s) you have selected");
3206: my $singconfirm = &mt(' for a single user?');
3207: my $multconfirm = &mt(' for multiple users?');
3208: &js_escape(\$alert);
3209: &js_escape(\$noaction);
3210: &js_escape(\$singconfirm);
3211: &js_escape(\$multconfirm);
3212: my $output = <<"ENDJS";
3213: function verify_action (field) {
3214: var numchecked = 0;
3215: var singconf = '$singconfirm';
3216: var multconf = '$multconfirm';
3217: if ($docstart.$formname.elements[field].length > 0) {
3218: for (i=0; i<$docstart.$formname.elements[field].length; i++) {
3219: if ($docstart.$formname.elements[field][i].checked == true) {
3220: numchecked ++;
3221: }
3222: }
3223: } else {
3224: if ($docstart.$formname.elements[field].checked == true) {
3225: numchecked ++;
3226: }
3227: }
3228: if (numchecked == 0) {
3229: alert("$alert");
3230: return;
3231: } else {
3232: var message = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].text;
3233: var choice = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].value;
3234: if (choice == '') {
3235: alert("$noaction");
3236: return;
3237: } else {
3238: if (numchecked == 1) {
3239: message += singconf;
3240: } else {
3241: message += multconf;
3242: }
3243: ENDJS
3244: if ($caller ne 'popup') {
3245: $output .= <<"NEWWIN";
3246: if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate' || choice == 'chgsec') {
3247: opendatebrowser(document.$formname,'$formname','go');
3248: return;
3249:
3250: } else {
3251: if (confirm(message)) {
3252: document.$formname.phase.value = 'bulkchange';
3253: document.$formname.submit();
3254: return;
3255: }
3256: }
3257: NEWWIN
3258: } else {
3259: $output .= <<"POPUP";
3260: if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate') {
3261: var datemsg = '';
3262: if (($docstart.$formname.startdate_month.value == '') &&
3263: ($docstart.$formname.startdate_day.value == '') &&
3264: ($docstart.$formname.startdate_year.value == '')) {
3265: datemsg = "\\n$lt{'acwi'},\\n$lt{'asyo'}.\\n";
3266: }
3267: if (($docstart.$formname.enddate_month.value == '') &&
3268: ($docstart.$formname.enddate_day.value == '') &&
3269: ($docstart.$formname.enddate_year.value == '')) {
3270: datemsg += "\\n$lt{'accw'},\\n$lt{'asyd'}.\\n";
3271: }
3272: if (datemsg != '') {
3273: message += "\\n"+datemsg;
3274: }
3275: }
3276: if (choice == 'chgsec') {
3277: var rolefilter = $docstart.$formname.showrole.options[$docstart.$formname.showrole.selectedIndex].value;
3278: var retained = $docstart.$formname.retainsec.value;
3279: var secshow = $docstart.$formname.newsecs.value;
3280: if (secshow == '') {
3281: if (rolefilter == 'st' || retained == 0 || retained == "") {
3282: message += "\\n\\n$lt{'sewi'},\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
3283: } else {
3284: message += "\\n\\n$lt{'arol'}\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n";
3285: }
3286: } else {
3287: if (rolefilter == 'st' || retained == 0 || retained == "") {
3288: message += "\\n\\n$lt{'swbs'} "+secshow+".\\n";
3289: } else {
3290: message += "\\n\\n$lt{'rwba'} "+secshow+".\\n";
3291: }
3292: }
3293: }
3294: if (confirm(message)) {
3295: $docstart.$formname.phase.value = 'bulkchange';
3296: $docstart.$formname.submit();
3297: window.close();
3298: }
3299: POPUP
3300: }
3301: $output .= '
3302: }
3303: }
3304: }
3305: ';
3306: return $output;
3307: }
3308:
3309: sub print_username_link {
3310: my ($mode,$in) = @_;
3311: my $output;
3312: if ($mode eq 'autoenroll') {
3313: $output = $in->{'username'};
3314: } else {
3315: $output = '<a href="javascript:username_display_launch('.
3316: "'$in->{'username'}','$in->{'domain'}'".')">'.
3317: $in->{'username'}.'</a>';
3318: }
3319: return $output;
3320: }
3321:
3322: sub role_type_names {
3323: my %lt = &Apache::lonlocal::texthash (
3324: 'domain' => 'Domain Roles',
3325: 'author' => 'Co-Author Roles',
3326: 'course' => 'Course Roles',
3327: 'community' => 'Community Roles',
3328: );
3329: return %lt;
3330: }
3331:
3332: sub select_actions {
3333: my ($context,$setting,$statusmode,$formname) = @_;
3334: my %lt = &Apache::lonlocal::texthash(
3335: revoke => "Revoke user roles",
3336: delete => "Delete user roles",
3337: reenable => "Re-enable expired user roles",
3338: activate => "Make future user roles active now",
3339: chgdates => "Change starting/ending dates",
3340: chgsec => "Change section associated with user roles",
3341: );
3342: # FIXME Add an option to change credits for student roles.
3343: my ($output,$options,%choices);
3344: # FIXME Disable actions for now for roletype=course in domain context
3345: if ($context eq 'domain' && $setting eq 'course') {
3346: return;
3347: }
3348: if ($context eq 'course') {
3349: if ($env{'form.showrole'} ne 'Any') {
3350: my $showactions;
3351: if (&Apache::lonnet::allowed('c'.$env{'form.showrole'},
3352: $env{'request.course.id'})) {
3353: $showactions = 1;
3354: } elsif ($env{'request.course.sec'} ne '') {
3355: if (&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
3356: $showactions = 1;
3357: }
3358: }
3359: unless ($showactions) {
3360: unless (&is_courseowner($env{'request.course.id'},
3361: $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'})) {
3362: return;
3363: }
3364: }
3365: }
3366: }
3367: if ($statusmode eq 'Any') {
3368: $options .= '
3369: <option value="chgdates">'.$lt{'chgdates'}.'</option>';
3370: $choices{'dates'} = 1;
3371: } else {
3372: if ($statusmode eq 'Future') {
3373: $options .= '
3374: <option value="activate">'.$lt{'activate'}.'</option>';
3375: $choices{'dates'} = 1;
3376: } elsif ($statusmode eq 'Expired') {
3377: $options .= '
3378: <option value="reenable">'.$lt{'reenable'}.'</option>';
3379: $choices{'dates'} = 1;
3380: }
3381: if ($statusmode eq 'Active' || $statusmode eq 'Future') {
3382: $options .= '
3383: <option value="chgdates">'.$lt{'chgdates'}.'</option>
3384: <option value="revoke">'.$lt{'revoke'}.'</option>';
3385: $choices{'dates'} = 1;
3386: }
3387: }
3388: if ($context eq 'domain') {
3389: $options .= '
3390: <option value="delete">'.$lt{'delete'}.'</option>';
3391: }
3392: if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course')) {
3393: if (($statusmode ne 'Expired') && ($env{'request.course.sec'} eq '')) {
3394: $options .= '
3395: <option value="chgsec">'.$lt{'chgsec'}.'</option>';
3396: $choices{'sections'} = 1;
3397: }
3398: }
3399: if ($options) {
3400: $output = '<select name="bulkaction">'."\n".
3401: '<option value="" selected="selected">'.
3402: &mt('Please select').'</option>'."\n".$options."\n".'</select>';
3403: if ($choices{'dates'}) {
3404: $output .=
3405: '<input type="hidden" name="startdate_month" value="" />'."\n".
3406: '<input type="hidden" name="startdate_day" value="" />'."\n".
3407: '<input type="hidden" name="startdate_year" value="" />'."\n".
3408: '<input type="hidden" name="startdate_hour" value="" />'."\n".
3409: '<input type="hidden" name="startdate_minute" value="" />'."\n".
3410: '<input type="hidden" name="startdate_second" value="" />'."\n".
3411: '<input type="hidden" name="enddate_month" value="" />'."\n".
3412: '<input type="hidden" name="enddate_day" value="" />'."\n".
3413: '<input type="hidden" name="enddate_year" value="" />'."\n".
3414: '<input type="hidden" name="enddate_hour" value="" />'."\n".
3415: '<input type="hidden" name="enddate_minute" value="" />'."\n".
3416: '<input type="hidden" name="enddate_second" value="" />'."\n".
3417: '<input type="hidden" name="no_end_date" value="" />'."\n";
3418: if ($context eq 'course') {
3419: $output .= '<input type="hidden" name="makedatesdefault" value="" />'."\n";
3420: }
3421: }
3422: if ($choices{'sections'}) {
3423: $output .= '<input type="hidden" name="retainsec" value="" />'."\n".
3424: '<input type="hidden" name="newsecs" value="" />'."\n";
3425: }
3426: }
3427: return $output;
3428: }
3429:
3430: sub date_section_javascript {
3431: my ($context,$setting) = @_;
3432: my $title = 'Date_And_Section_Selector';
3433: my %nopopup = &Apache::lonlocal::texthash (
3434: revoke => "Check the boxes for any users for whom roles are to be revoked, and click 'Proceed'",
3435: delete => "Check the boxes for any users for whom roles are to be deleted, and click 'Proceed'",
3436: none => "Choose an action to take for selected users",
3437: );
3438: my $output = <<"ENDONE";
3439: <script type="text/javascript">
3440: // <![CDATA[
3441: function opendatebrowser(callingform,formname,calledby) {
3442: var bulkaction = callingform.bulkaction.options[callingform.bulkaction.selectedIndex].value;
3443: var url = '/adm/createuser?';
3444: var type = '';
3445: var showrole = callingform.showrole.options[callingform.showrole.selectedIndex].value;
3446: ENDONE
3447: if ($context eq 'domain') {
3448: $output .= '
3449: type = callingform.roletype.options[callingform.roletype.selectedIndex].value;
3450: ';
3451: }
3452: my $width= '700';
3453: my $height = '400';
3454: $output .= <<"ENDTWO";
3455: url += 'action=dateselect&callingform=' + formname +
3456: '&roletype='+type+'&showrole='+showrole +'&bulkaction='+bulkaction;
3457: var title = '$title';
3458: var options = 'scrollbars=1,resizable=1,menubar=0';
3459: options += ',width=$width,height=$height';
3460: stdeditbrowser = open(url,title,options,'1');
3461: stdeditbrowser.focus();
3462: }
3463: // ]]>
3464: </script>
3465: ENDTWO
3466: return $output;
3467: }
3468:
3469: sub date_section_selector {
3470: my ($context,$permission,$crstype,$showcredits) = @_;
3471: my $callingform = $env{'form.callingform'};
3472: my $formname = 'dateselect';
3473: my $groupslist = &get_groupslist();
3474: my $sec_js =
3475: &setsections_javascript($formname,$groupslist,undef,undef,$crstype,
3476: $showcredits);
3477: my $output = <<"END";
3478: <script type="text/javascript">
3479: // <![CDATA[
3480:
3481: $sec_js
3482:
3483: function saveselections(formname) {
3484:
3485: END
3486: if ($env{'form.bulkaction'} eq 'chgsec') {
3487: $output .= <<"END";
3488: if (formname.retainsec.length > 1) {
3489: for (var i=0; i<formname.retainsec.length; i++) {
3490: if (formname.retainsec[i].checked == true) {
3491: opener.document.$callingform.retainsec.value = formname.retainsec[i].value;
3492: }
3493: }
3494: } else {
3495: opener.document.$callingform.retainsec.value = formname.retainsec.value;
3496: }
3497: setSections(formname,'$crstype');
3498: if (seccheck == 'ok') {
3499: opener.document.$callingform.newsecs.value = formname.sections.value;
3500: }
3501: END
3502: } else {
3503: if ($context eq 'course') {
3504: if (($env{'form.bulkaction'} eq 'reenable') ||
3505: ($env{'form.bulkaction'} eq 'activate') ||
3506: ($env{'form.bulkaction'} eq 'chgdates')) {
3507: if ($env{'request.course.sec'} eq '') {
3508: $output .= <<"END";
3509:
3510: if (formname.makedatesdefault.checked == true) {
3511: opener.document.$callingform.makedatesdefault.value = 1;
3512: }
3513: else {
3514: opener.document.$callingform.makedatesdefault.value = 0;
3515: }
3516:
3517: END
3518: }
3519: }
3520: }
3521: $output .= <<"END";
3522: opener.document.$callingform.startdate_month.value = formname.startdate_month.options[formname.startdate_month.selectedIndex].value;
3523: opener.document.$callingform.startdate_day.value = formname.startdate_day.value;
3524: opener.document.$callingform.startdate_year.value = formname.startdate_year.value;
3525: opener.document.$callingform.startdate_hour.value = formname.startdate_hour.options[formname.startdate_hour.selectedIndex].value;
3526: opener.document.$callingform.startdate_minute.value = formname.startdate_minute.value;
3527: opener.document.$callingform.startdate_second.value = formname.startdate_second.value;
3528: opener.document.$callingform.enddate_month.value = formname.enddate_month.options[formname.enddate_month.selectedIndex].value;
3529: opener.document.$callingform.enddate_day.value = formname.enddate_day.value;
3530: opener.document.$callingform.enddate_year.value = formname.enddate_year.value;
3531: opener.document.$callingform.enddate_hour.value = formname.enddate_hour.options[formname.enddate_hour.selectedIndex].value;
3532: opener.document.$callingform.enddate_minute.value = formname.enddate_minute.value;
3533: opener.document.$callingform.enddate_second.value = formname.enddate_second.value;
3534: if (formname.no_end_date.checked) {
3535: opener.document.$callingform.no_end_date.value = '1';
3536: } else {
3537: opener.document.$callingform.no_end_date.value = '0';
3538: }
3539: END
3540: }
3541: my $verify_action_js = &bulkaction_javascript($callingform,'popup');
3542: $output .= <<"ENDJS";
3543: verify_action('actionlist');
3544: }
3545:
3546: $verify_action_js
3547:
3548: // ]]>
3549: </script>
3550: ENDJS
3551: my %lt = &Apache::lonlocal::texthash (
3552: chac => 'Access dates to apply for selected users',
3553: chse => 'Changes in section affiliation to apply to selected users',
3554: 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.',
3555: forn => 'For a course role that is not "student", users may have roles in more than one section at a time.',
3556: reta => "Retain each user's current section affiliations?",
3557: dnap => '(Does not apply to student roles).',
3558: );
3559: my ($date_items,$headertext);
3560: if ($env{'form.bulkaction'} eq 'chgsec') {
3561: $headertext = $lt{'chse'};
3562: } else {
3563: $headertext = $lt{'chac'};
3564: my $starttime;
3565: if (($env{'form.bulkaction'} eq 'activate') ||
3566: ($env{'form.bulkaction'} eq 'reenable')) {
3567: $starttime = time;
3568: }
3569: $date_items = &date_setting_table($starttime,undef,$context,
3570: $env{'form.bulkaction'},$formname,
3571: $permission,$crstype);
3572: }
3573: $output .= '<h3>'.$headertext.'</h3>'.
3574: '<form name="'.$formname.'" method="post" action="">'."\n".
3575: $date_items;
3576: if ($context eq 'course' && $env{'form.bulkaction'} eq 'chgsec') {
3577: my ($cnum,$cdom) = &get_course_identity();
3578: if ($crstype eq 'Community') {
3579: $lt{'fors'} = &mt('For member roles, changing the section will result in a section switch, as members may only be in one section of a community at a time.');
3580: $lt{'forn'} = &mt('For a community role that is not "member", users may have roles in more than one section at a time.');
3581: $lt{'dnap'} = &mt('(Does not apply to member roles).');
3582: }
3583: my $info;
3584: if ($env{'form.showrole'} eq 'st') {
3585: $output .= '<p>'.$lt{'fors'}.'</p>';
3586: } elsif ($env{'form.showrole'} eq 'Any') {
3587: $output .= '<p>'.$lt{'fors'}.'</p>'.
3588: '<p>'.$lt{'forn'}.' ';
3589: $info = $lt{'reta'};
3590: } else {
3591: $output .= '<p>'.$lt{'forn'}.' ';
3592: $info = $lt{'reta'};
3593: }
3594: if ($info) {
3595: $info .= '<span class="LC_nobreak">'.
3596: '<label><input type="radio" name="retainsec" value="1" '.
3597: 'checked="checked" />'.&mt('Yes').'</label> '.
3598: '<label><input type="radio" name="retainsec" value="0" />'.
3599: &mt('No').'</label></span>';
3600: if ($env{'form.showrole'} eq 'Any') {
3601: $info .= '<br />'.$lt{'dnap'};
3602: }
3603: $info .= '</p>';
3604: } else {
3605: $info = '<input type="hidden" name="retainsec" value="0" />';
3606: }
3607: my $rowtitle = &mt('New section to assign');
3608: my $secbox = §ion_picker($cdom,$cnum,$env{'form.showrole'},$rowtitle,
3609: $permission,$context,'chgsec',$crstype);
3610: $output .= $info.$secbox;
3611: }
3612: $output .= '<p>'.
3613: '<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n".
3614: '</form>';
3615: return $output;
3616: }
3617:
3618: sub section_picker {
3619: my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode,$crstype,
3620: $showcredits,$credits) = @_;
3621: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
3622: my $sections_select .= &course_sections(\%sections_count,$role);
3623: my $secbox = '<div>'.&Apache::lonhtmlcommon::start_pick_box()."\n";
3624: if ($mode eq 'upload') {
3625: my ($options,$cb_script,$coursepick) =
3626: &default_role_selector($context,1,$crstype,$showcredits);
3627: $secbox .= &Apache::lonhtmlcommon::row_title(&mt('role'),'LC_oddrow_value').
3628: $options. &Apache::lonhtmlcommon::row_closure(1)."\n";
3629: }
3630: $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n";
3631: if ($env{'request.course.sec'} eq '') {
3632: $secbox .= '<table class="LC_createuser"><tr class="LC_section_row">'."\n".
3633: '<td align="center">'.&mt('Existing sections')."\n".
3634: '<br />'.$sections_select.'</td><td align="center">'.
3635: &mt('New section').'<br />'."\n".
3636: '<input type="text" name="newsec" size="15" value="" />'."\n".
3637: '<input type="hidden" name="sections" value="" />'."\n".
3638: '</td></tr></table>'."\n";
3639: } else {
3640: $secbox .= '<input type="hidden" name="sections" value="'.
3641: $env{'request.course.sec'}.'" />'.
3642: $env{'request.course.sec'};
3643: }
3644: $secbox .= &Apache::lonhtmlcommon::row_closure(1)."\n";
3645: unless ($mode eq 'chgsec') {
3646: if ($showcredits) {
3647: $secbox .=
3648: &Apache::lonhtmlcommon::row_title(&mt('credits (students)'),
3649: 'LC_evenrow_value')."\n".
3650: '<input type="text" name="credits" size="3" value="'.$credits.'" />'."\n".
3651: &Apache::lonhtmlcommon::row_closure(1)."\n";
3652: }
3653: }
3654: $secbox .= &Apache::lonhtmlcommon::end_pick_box().'</div>';
3655: return $secbox;
3656: }
3657:
3658: sub results_header_row {
3659: my ($rolefilter,$statusmode,$context,$permission,$mode,$crstype) = @_;
3660: my ($description,$showfilter);
3661: if ($rolefilter ne 'Any') {
3662: $showfilter = $rolefilter;
3663: }
3664: if ($context eq 'course') {
3665: if ($mode eq 'csv' || $mode eq 'excel') {
3666: if ($crstype eq 'Community') {
3667: $description = &mt('Community - [_1]:',$env{'course.'.$env{'request.course.id'}.'.description'}).' ';
3668: } else {
3669: $description = &mt('Course - [_1]:',$env{'course.'.$env{'request.course.id'}.'.description'}).' ';
3670: }
3671: }
3672: if ($statusmode eq 'Expired') {
3673: if ($crstype eq 'Community') {
3674: $description .= &mt('Users in community with expired [_1] roles',$showfilter);
3675: } else {
3676: $description .= &mt('Users in course with expired [_1] roles',$showfilter);
3677: }
3678: } elsif ($statusmode eq 'Future') {
3679: if ($crstype eq 'Community') {
3680: $description .= &mt('Users in community with future [_1] roles',$showfilter);
3681: } else {
3682: $description .= &mt('Users in course with future [_1] roles',$showfilter);
3683: }
3684: } elsif ($statusmode eq 'Active') {
3685: if ($crstype eq 'Community') {
3686: $description .= &mt('Users in community with active [_1] roles',$showfilter);
3687: } else {
3688: $description .= &mt('Users in course with active [_1] roles',$showfilter);
3689: }
3690: } else {
3691: if ($rolefilter eq 'Any') {
3692: if ($crstype eq 'Community') {
3693: $description .= &mt('All users in community');
3694: } else {
3695: $description .= &mt('All users in course');
3696: }
3697: } else {
3698: if ($crstype eq 'Community') {
3699: $description .= &mt('All users in community with [_1] roles',$rolefilter);
3700: } else {
3701: $description .= &mt('All users in course with [_1] roles',$rolefilter);
3702: }
3703: }
3704: }
3705: my $constraint;
3706: my $viewablesec = &viewable_section($permission);
3707: if ($viewablesec ne '') {
3708: if ($env{'form.showrole'} eq 'st') {
3709: $constraint = &mt('only users in section "[_1]"',$viewablesec);
3710: } elsif (($env{'form.showrole'} ne 'cc') && ($env{'form.showrole'} ne 'co')) {
3711: $constraint = &mt('only users affiliated with no section or section "[_1]"',$viewablesec);
3712: }
3713: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
3714: if ($env{'form.grpfilter'} eq 'none') {
3715: $constraint .= &mt(' and not in any group');
3716: } else {
3717: $constraint .= &mt(' and members of group: "[_1]"',$env{'form.grpfilter'});
3718: }
3719: }
3720: } else {
3721: if (($env{'form.secfilter'} ne 'all') && ($env{'form.secfilter'} ne '')) {
3722: if ($env{'form.secfilter'} eq 'none') {
3723: $constraint = &mt('only users affiliated with no section');
3724: } else {
3725: $constraint = &mt('only users affiliated with section "[_1]"',$env{'form.secfilter'});
3726: }
3727: }
3728: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
3729: if ($env{'form.grpfilter'} eq 'none') {
3730: if ($constraint eq '') {
3731: $constraint = &mt('only users not in any group');
3732: } else {
3733: $constraint .= &mt(' and also not in any group');
3734: }
3735: } else {
3736: if ($constraint eq '') {
3737: $constraint = &mt('only members of group: "[_1]"',$env{'form.grpfilter'});
3738: } else {
3739: $constraint .= &mt(' and also members of group: "[_1]"'.$env{'form.grpfilter'});
3740: }
3741: }
3742: }
3743: }
3744: if ($constraint ne '') {
3745: $description .= ' ('.$constraint.')';
3746: }
3747: } elsif ($context eq 'author') {
3748: $description =
3749: &mt('Author space for [_1]'
3750: ,'<span class="LC_cusr_emph">'
3751: .&Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'})
3752: .'</span>')
3753: .': ';
3754: if ($statusmode eq 'Expired') {
3755: $description .= &mt('Co-authors with expired [_1] roles',$showfilter);
3756: } elsif ($statusmode eq 'Future') {
3757: $description .= &mt('Co-authors with future [_1] roles',$showfilter);
3758: } elsif ($statusmode eq 'Active') {
3759: $description .= &mt('Co-authors with active [_1] roles',$showfilter);
3760: } else {
3761: if ($rolefilter eq 'Any') {
3762: $description .= &mt('All co-authors');
3763: } else {
3764: $description .= &mt('All co-authors with [_1] roles',$rolefilter);
3765: }
3766: }
3767: } elsif ($context eq 'domain') {
3768: my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description');
3769: $description = &mt('Domain - [_1]:',$domdesc).' ';
3770: if ($env{'form.roletype'} eq 'domain') {
3771: if ($statusmode eq 'Expired') {
3772: $description .= &mt('Users in domain with expired [_1] roles',$showfilter);
3773: } elsif ($statusmode eq 'Future') {
3774: $description .= &mt('Users in domain with future [_1] roles',$showfilter);
3775: } elsif ($statusmode eq 'Active') {
3776: $description .= &mt('Users in domain with active [_1] roles',$showfilter);
3777: } else {
3778: if ($rolefilter eq 'Any') {
3779: $description .= &mt('All users in domain');
3780: } else {
3781: $description .= &mt('All users in domain with [_1] roles',$rolefilter);
3782: }
3783: }
3784: } elsif ($env{'form.roletype'} eq 'author') {
3785: if ($statusmode eq 'Expired') {
3786: $description .= &mt('Co-authors in domain with expired [_1] roles',$showfilter);
3787: } elsif ($statusmode eq 'Future') {
3788: $description .= &mt('Co-authors in domain with future [_1] roles',$showfilter);
3789: } elsif ($statusmode eq 'Active') {
3790: $description .= &mt('Co-authors in domain with active [_1] roles',$showfilter);
3791: } else {
3792: if ($rolefilter eq 'Any') {
3793: $description .= &mt('All users with co-author roles in domain',$showfilter);
3794: } else {
3795: $description .= &mt('All co-authors in domain with [_1] roles',$rolefilter);
3796: }
3797: }
3798: } elsif (($env{'form.roletype'} eq 'course') ||
3799: ($env{'form.roletype'} eq 'community')) {
3800: my $coursefilter = $env{'form.coursepick'};
3801: if ($env{'form.roletype'} eq 'course') {
3802: if ($coursefilter eq 'category') {
3803: my $instcode = &instcode_from_coursefilter();
3804: if ($instcode eq '.') {
3805: $description .= &mt('All courses in domain').' - ';
3806: } else {
3807: $description .= &mt('Courses in domain with institutional code: [_1]',$instcode).' - ';
3808: }
3809: } elsif ($coursefilter eq 'selected') {
3810: $description .= &mt('Selected courses in domain').' - ';
3811: } elsif ($coursefilter eq 'all') {
3812: $description .= &mt('All courses in domain').' - ';
3813: }
3814: } elsif ($env{'form.roletype'} eq 'community') {
3815: if ($coursefilter eq 'selected') {
3816: $description .= &mt('Selected communities in domain').' - ';
3817: } elsif ($coursefilter eq 'all') {
3818: $description .= &mt('All communities in domain').' - ';
3819: }
3820: }
3821: if ($statusmode eq 'Expired') {
3822: $description .= &mt('users with expired [_1] roles',$showfilter);
3823: } elsif ($statusmode eq 'Future') {
3824: $description .= &mt('users with future [_1] roles',$showfilter);
3825: } elsif ($statusmode eq 'Active') {
3826: $description .= &mt('users with active [_1] roles',$showfilter);
3827: } else {
3828: if ($rolefilter eq 'Any') {
3829: $description .= &mt('all users');
3830: } else {
3831: $description .= &mt('users with [_1] roles',$rolefilter);
3832: }
3833: }
3834: }
3835: }
3836: return $description;
3837: }
3838:
3839: sub viewable_section {
3840: my ($permission) = @_;
3841: my $viewablesec;
3842: if (ref($permission) eq 'HASH') {
3843: if (exists($permission->{'view_section'})) {
3844: $viewablesec = $permission->{'view_section'};
3845: } elsif (exists($permission->{'cusr_section'})) {
3846: $viewablesec = $permission->{'cusr_section'};
3847: }
3848: }
3849: return $viewablesec;
3850: }
3851:
3852:
3853: #################################################
3854: #################################################
3855: sub show_drop_list {
3856: my ($r,$classlist,$nosort,$permission,$crstype) = @_;
3857: my $cid = $env{'request.course.id'};
3858: my ($cnum,$cdom) = &get_course_identity($cid);
3859: if (! exists($env{'form.sortby'})) {
3860: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
3861: ['sortby']);
3862: }
3863: my $sortby = $env{'form.sortby'};
3864: if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
3865: $sortby = 'username';
3866: }
3867: my $action = "drop";
3868: my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
3869: $r->print(<<END);
3870: <input type="hidden" name="sortby" value="$sortby" />
3871: <input type="hidden" name="action" value="$action" />
3872: <input type="hidden" name="state" value="done" />
3873: <script type="text/javascript" language="Javascript">
3874: // <![CDATA[
3875: $check_uncheck_js
3876: // ]]>
3877: </script>
3878: <input type="hidden" name="phase" value="four" />
3879: END
3880: my ($indexhash,$keylist) = &make_keylist_array();
3881: my $studentcount = 0;
3882: if (ref($classlist) eq 'HASH') {
3883: foreach my $student (keys(%{$classlist})) {
3884: my $sdata = $classlist->{$student};
3885: my $status = $sdata->[$indexhash->{'status'}];
3886: my $section = $sdata->[$indexhash->{'section'}];
3887: if ($status ne 'Active') {
3888: delete($classlist->{$student});
3889: next;
3890: }
3891: if ($env{'request.course.sec'} ne '') {
3892: if ($section ne $env{'request.course.sec'}) {
3893: delete($classlist->{$student});
3894: next;
3895: }
3896: }
3897: $studentcount ++;
3898: }
3899: }
3900: if (!$studentcount) {
3901: my $msg = '';
3902: if ($crstype eq 'Community') {
3903: $msg = &mt('There are no members to drop.');
3904: } else {
3905: $msg = &mt('There are no students to drop.');
3906: }
3907: $r->print('<p class="LC_info">'.$msg.'</p>');
3908: return;
3909: }
3910: my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
3911: $classlist,$keylist,$cdom,$cnum);
3912: my %lt=&Apache::lonlocal::texthash('usrn' => "username",
3913: 'dom' => "domain",
3914: 'id' => "ID",
3915: 'sn' => "student name",
3916: 'mn' => "member name",
3917: 'sec' => "section",
3918: 'start' => "start date",
3919: 'end' => "end date",
3920: 'groups' => "active groups",
3921: );
3922: my $nametitle = $lt{'sn'};
3923: if ($crstype eq 'Community') {
3924: $nametitle = $lt{'mn'};
3925: }
3926: if ($nosort) {
3927: $r->print(&Apache::loncommon::start_data_table().
3928: &Apache::loncommon::start_data_table_header_row());
3929: $r->print(<<END);
3930: <th> </th>
3931: <th>$lt{'usrn'}</th>
3932: <th>$lt{'dom'}</th>
3933: <th>$lt{'id'}</th>
3934: <th>$nametitle</th>
3935: <th>$lt{'sec'}</th>
3936: <th>$lt{'start'}</th>
3937: <th>$lt{'end'}</th>
3938: <th>$lt{'groups'}</th>
3939: END
3940: $r->print(&Apache::loncommon::end_data_table_header_row());
3941: } else {
3942: $r->print(&Apache::loncommon::start_data_table().
3943: &Apache::loncommon::start_data_table_header_row());
3944: $r->print(<<END);
3945: <th> </th>
3946: <th>
3947: <a href="/adm/createuser?action=$action&sortby=username">$lt{'usrn'}</a>
3948: </th><th>
3949: <a href="/adm/createuser?action=$action&sortby=domain">$lt{'dom'}</a>
3950: </th><th>
3951: <a href="/adm/createuser?action=$action&sortby=id">$lt{'id'}</a>
3952: </th><th>
3953: <a href="/adm/createuser?action=$action&sortby=fullname">$nametitle</a>
3954: </th><th>
3955: <a href="/adm/createuser?action=$action&sortby=section">$lt{'sec'}</a>
3956: </th><th>
3957: <a href="/adm/createuser?action=$action&sortby=start">$lt{'start'}</a>
3958: </th><th>
3959: <a href="/adm/createuser?action=$action&sortby=end">$lt{'end'}</a>
3960: </th><th>
3961: <a href="/adm/createuser?action=$action&sortby=groups">$lt{'groups'}</a>
3962: </th>
3963: END
3964: $r->print(&Apache::loncommon::end_data_table_header_row());
3965: }
3966: #
3967: # Sort the students
3968: my $index = $indexhash->{$sortby};
3969: my $second = $indexhash->{'username'};
3970: my $third = $indexhash->{'domain'};
3971: my @Sorted_Students = sort {
3972: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
3973: ||
3974: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
3975: ||
3976: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
3977: } (keys(%{$classlist}));
3978: foreach my $student (@Sorted_Students) {
3979: my $error;
3980: my $sdata = $classlist->{$student};
3981: my $username = $sdata->[$indexhash->{'username'}];
3982: my $domain = $sdata->[$indexhash->{'domain'}];
3983: my $section = $sdata->[$indexhash->{'section'}];
3984: my $name = $sdata->[$indexhash->{'fullname'}];
3985: my $id = $sdata->[$indexhash->{'id'}];
3986: my $start = $sdata->[$indexhash->{'start'}];
3987: my $end = $sdata->[$indexhash->{'end'}];
3988: my $groups = $classgroups->{$student};
3989: my $active_groups;
3990: if (ref($groups->{active}) eq 'HASH') {
3991: $active_groups = join(', ',keys(%{$groups->{'active'}}));
3992: }
3993: if (! defined($start) || $start == 0) {
3994: $start = &mt('none');
3995: } else {
3996: $start = &Apache::lonlocal::locallocaltime($start);
3997: }
3998: if (! defined($end) || $end == 0) {
3999: $end = &mt('none');
4000: } else {
4001: $end = &Apache::lonlocal::locallocaltime($end);
4002: }
4003: my $studentkey = $student.':'.$section;
4004: my $startitem = '<input type="hidden" name="'.$studentkey.'_start" value="'.$sdata->[$indexhash->{'start'}].'" />';
4005: #
4006: $r->print(&Apache::loncommon::start_data_table_row());
4007: $r->print(<<"END");
4008: <td><input type="checkbox" name="droplist" value="$studentkey" /></td>
4009: <td>$username</td>
4010: <td>$domain</td>
4011: <td>$id</td>
4012: <td>$name</td>
4013: <td>$section</td>
4014: <td>$start $startitem</td>
4015: <td>$end</td>
4016: <td>$active_groups</td>
4017: END
4018: $r->print(&Apache::loncommon::end_data_table_row());
4019: }
4020: $r->print(&Apache::loncommon::end_data_table().'<br />');
4021: %lt=&Apache::lonlocal::texthash(
4022: 'dp' => "Drop Students",
4023: 'dm' => "Drop Members",
4024: 'ca' => "check all",
4025: 'ua' => "uncheck all",
4026: );
4027: my $btn = $lt{'dp'};
4028: if ($crstype eq 'Community') {
4029: $btn = $lt{'dm'};
4030: }
4031: $r->print(<<"END");
4032: <p>
4033: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)" />
4034: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)" />
4035: </p>
4036: <p>
4037: <input type="submit" value="$btn" />
4038: </p>
4039: END
4040: return;
4041: }
4042:
4043: #
4044: # Print out the initial form to get the file containing a list of users
4045: #
4046: sub print_first_users_upload_form {
4047: my ($r,$context) = @_;
4048: my $str;
4049: $str = '<input type="hidden" name="phase" value="two" />';
4050: $str .= '<input type="hidden" name="action" value="upload" />';
4051: $str .= '<input type="hidden" name="state" value="got_file" />';
4052:
4053: $str .= &Apache::grades::checkforfile_js();
4054:
4055: $str .= '<h2>'.&mt('Upload a file containing information about users').'</h2>'."\n";
4056:
4057: # Excel and CSV Help
4058: $str .= '<div class="LC_columnSection">'
4059: .&Apache::loncommon::help_open_topic("Course_Create_Class_List",
4060: &mt("How do I create a users list from a spreadsheet"))
4061: .' '.&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
4062: &mt("How do I create a CSV file from a spreadsheet"))
4063: ."</div>\n";
4064: $str .= &Apache::lonhtmlcommon::start_pick_box()
4065: .&Apache::lonhtmlcommon::row_title(&mt('File'));
4066: if (&Apache::lonlocal::current_language() ne 'en') {
4067: if ($context eq 'course') {
4068: $str .= '<p class="LC_info">'."\n"
4069: .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.')."\n"
4070: .'</p>'."\n";
4071: }
4072: }
4073: $str .= &Apache::loncommon::upfile_select_html()
4074: .&Apache::lonhtmlcommon::row_closure()
4075: .&Apache::lonhtmlcommon::row_title(
4076: '<label for="noFirstLine">'
4077: .&mt('Ignore First Line')
4078: .'</label>')
4079: .'<input type="checkbox" name="noFirstLine" id="noFirstLine" />'
4080: .&Apache::lonhtmlcommon::row_closure(1)
4081: .&Apache::lonhtmlcommon::end_pick_box();
4082:
4083: $str .= '<p>'
4084: .'<input type="submit" name="fileupload" value="'.&mt('Next').'"'
4085: .' onclick="javascript:checkUpload(this.form);" />'
4086: .'</p>';
4087:
4088: $r->print($str);
4089: return;
4090: }
4091:
4092: # ================================================= Drop/Add from uploaded file
4093: sub upfile_drop_add {
4094: my ($r,$context,$permission,$showcredits) = @_;
4095: &Apache::loncommon::load_tmp_file($r);
4096: my @userdata=&Apache::loncommon::upfile_record_sep();
4097: if($env{'form.noFirstLine'}){shift(@userdata);}
4098: my @keyfields = split(/\,/,$env{'form.keyfields'});
4099: my %fields=();
4100: for (my $i=0; $i<=$env{'form.nfields'}; $i++) {
4101: if ($env{'form.upfile_associate'} eq 'reverse') {
4102: if ($env{'form.f'.$i} ne 'none') {
4103: $fields{$keyfields[$i]}=$env{'form.f'.$i};
4104: }
4105: } else {
4106: $fields{$env{'form.f'.$i}}=$keyfields[$i];
4107: }
4108: }
4109: if ($env{'form.fullup'} ne 'yes') {
4110: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
4111: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />');
4112: }
4113: #
4114: # Store the field choices away
4115: my @storefields = qw/username names fname mname lname gen id
4116: sec ipwd email role domain inststatus/;
4117: if ($showcredits) {
4118: push (@storefields,'credits');
4119: }
4120: my %fieldstype;
4121: foreach my $field (@storefields) {
4122: $env{'form.'.$field.'_choice'}=$fields{$field};
4123: $fieldstype{$field.'_choice'} = 'scalar';
4124: }
4125: &Apache::loncommon::store_course_settings('enrollment_upload',\%fieldstype);
4126: my ($cid,$crstype,$setting);
4127: if ($context eq 'domain') {
4128: $setting = $env{'form.roleaction'};
4129: }
4130: if ($env{'request.course.id'} ne '') {
4131: $cid = $env{'request.course.id'};
4132: $crstype = &Apache::loncommon::course_type();
4133: } elsif ($setting eq 'course') {
4134: if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) {
4135: $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'};
4136: $crstype = &Apache::loncommon::course_type($cid);
4137: }
4138: }
4139: my ($startdate,$enddate) = &get_dates_from_form();
4140: if ($env{'form.makedatesdefault'}) {
4141: $r->print(&make_dates_default($startdate,$enddate,$context,$crstype));
4142: }
4143: # Determine domain and desired host (home server)
4144: my $defdom=$env{'request.role.domain'};
4145: my $domain;
4146: if ($env{'form.defaultdomain'} ne '') {
4147: $domain = $env{'form.defaultdomain'};
4148: } else {
4149: $domain = $defdom;
4150: }
4151: my $desiredhost = $env{'form.lcserver'};
4152: if (lc($desiredhost) eq 'default') {
4153: $desiredhost = undef;
4154: } else {
4155: my %home_servers = &Apache::lonnet::get_servers($defdom,'library');
4156: if (! exists($home_servers{$desiredhost})) {
4157: $r->print('<span class="LC_error">'.&mt('Error').
4158: &mt('Invalid home server specified').'</span>');
4159: $r->print(&Apache::loncommon::end_page());
4160: return;
4161: }
4162: }
4163: # Determine authentication mechanism
4164: my $changeauth;
4165: if ($context eq 'domain') {
4166: $changeauth = $env{'form.changeauth'};
4167: }
4168: my $amode = '';
4169: my $genpwd = '';
4170: if ($env{'form.login'} eq 'krb') {
4171: $amode='krb';
4172: $amode.=$env{'form.krbver'};
4173: $genpwd=$env{'form.krbarg'};
4174: } elsif ($env{'form.login'} eq 'int') {
4175: $amode='internal';
4176: if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
4177: $genpwd=$env{'form.intarg'};
4178: }
4179: } elsif ($env{'form.login'} eq 'loc') {
4180: $amode='localauth';
4181: if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
4182: $genpwd=$env{'form.locarg'};
4183: }
4184: }
4185: if ($amode =~ /^krb/) {
4186: if (! defined($genpwd) || $genpwd eq '') {
4187: $r->print('<span class="Error">'.
4188: &mt('Unable to enroll users').' '.
4189: &mt('No Kerberos domain was specified.').'</span></p>');
4190: $amode = ''; # This causes the loop below to be skipped
4191: }
4192: }
4193: my ($defaultsec,$defaultrole,$defaultcredits,$commoncredits);
4194: if ($context eq 'domain') {
4195: if ($setting eq 'domain') {
4196: $defaultrole = $env{'form.defaultrole'};
4197: } elsif ($setting eq 'course') {
4198: $defaultrole = $env{'form.courserole'};
4199: $defaultsec = $env{'form.sections'};
4200: if ($showcredits) {
4201: $commoncredits = $env{'form.credits'};
4202: if ($crstype ne 'Community') {
4203: my %coursehash=&Apache::lonnet::coursedescription($cid);
4204: $defaultcredits = $coursehash{'internal.defaultcredits'};
4205: }
4206: }
4207: }
4208: } elsif ($context eq 'author') {
4209: $defaultrole = $env{'form.defaultrole'};
4210: } elsif ($context eq 'course') {
4211: $defaultrole = $env{'form.defaultrole'};
4212: $defaultsec = $env{'form.sections'};
4213: if ($showcredits) {
4214: $commoncredits = $env{'form.credits'};
4215: $defaultcredits = $env{'course.'.$cid.'.internal.defaultcredits'};
4216: }
4217: }
4218: # Check to see if user information can be changed
4219: my @userinfo = ('firstname','middlename','lastname','generation',
4220: 'permanentemail','id');
4221: my %canmodify;
4222: if (&Apache::lonnet::allowed('mau',$domain)) {
4223: push(@userinfo,'inststatus');
4224: foreach my $field (@userinfo) {
4225: $canmodify{$field} = 1;
4226: }
4227: }
4228: my (%userlist,%modifiable_fields,@poss_roles);
4229: my $secidx = &Apache::loncoursedata::CL_SECTION();
4230: my @courseroles = &roles_by_context('course',1,$crstype);
4231: if (!&Apache::lonnet::allowed('mau',$domain)) {
4232: if ($context eq 'course' || $context eq 'author') {
4233: @poss_roles = &curr_role_permissions($context,'','',$crstype);
4234: my @statuses = ('active','future');
4235: my ($indexhash,$keylist) = &make_keylist_array();
4236: my %info;
4237: foreach my $role (@poss_roles) {
4238: %{$modifiable_fields{$role}} = &can_modify_userinfo($context,$domain,
4239: \@userinfo,[$role]);
4240: }
4241: if ($context eq 'course') {
4242: my ($cnum,$cdom) = &get_course_identity();
4243: my $roster = &Apache::loncoursedata::get_classlist();
4244: if (ref($roster) eq 'HASH') {
4245: %userlist = %{$roster};
4246: }
4247: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
4248: \@statuses,\@poss_roles);
4249: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
4250: \%advrolehash,$permission);
4251: } elsif ($context eq 'author') {
4252: my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
4253: \@statuses,\@poss_roles);
4254: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
4255: \%cstr_roles,$permission);
4256:
4257: }
4258: }
4259: }
4260: if ( $domain eq &LONCAPA::clean_domain($domain)
4261: && ($amode ne '')) {
4262: #######################################
4263: ## Add/Modify Users ##
4264: #######################################
4265: if ($context eq 'course') {
4266: $r->print('<h3>'.&mt('Enrolling Users')."</h3>\n<p>\n");
4267: } elsif ($context eq 'author') {
4268: $r->print('<h3>'.&mt('Updating Co-authors')."</h3>\n<p>\n");
4269: } else {
4270: $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n");
4271: }
4272: $r->rflush;
4273:
4274: my %counts = (
4275: user => 0,
4276: auth => 0,
4277: role => 0,
4278: );
4279: my $flushc=0;
4280: my %student=();
4281: my (%curr_groups,@sections,@cleansec,$defaultwarn,$groupwarn);
4282: my %userchg;
4283: if ($context eq 'course' || $setting eq 'course') {
4284: if ($context eq 'course') {
4285: # Get information about course groups
4286: %curr_groups = &Apache::longroup::coursegroups();
4287: } elsif ($setting eq 'course') {
4288: if ($cid) {
4289: %curr_groups =
4290: &Apache::longroup::coursegroups($env{'form.dcdomain'},
4291: $env{'form.dccourse'});
4292: }
4293: }
4294: # determine section number
4295: if ($defaultsec =~ /,/) {
4296: push(@sections,split(/,/,$defaultsec));
4297: } else {
4298: push(@sections,$defaultsec);
4299: }
4300: # remove non alphanumeric values from section
4301: foreach my $item (@sections) {
4302: $item =~ s/\W//g;
4303: if ($item eq "none" || $item eq 'all') {
4304: $defaultwarn = &mt('Default section name [_1] could not be used as it is a reserved word.',$item);
4305: } elsif ($item ne '' && exists($curr_groups{$item})) {
4306: $groupwarn = &mt('Default section name "[_1]" is the name of a course group. Section names and group names must be distinct.',$item);
4307: } elsif ($item ne '') {
4308: push(@cleansec,$item);
4309: }
4310: }
4311: if ($defaultwarn) {
4312: $r->print($defaultwarn.'<br />');
4313: }
4314: if ($groupwarn) {
4315: $r->print($groupwarn.'<br />');
4316: }
4317: }
4318: my (%curr_rules,%got_rules,%alerts,%cancreate);
4319: my %customroles = &my_custom_roles($crstype);
4320: my @permitted_roles =
4321: &roles_on_upload($context,$setting,$crstype,%customroles);
4322: my %longtypes = &Apache::lonlocal::texthash(
4323: official => 'Institutional',
4324: unofficial => 'Non-institutional',
4325: );
4326: my $newuserdom = $env{'request.role.domain'};
4327: map { $cancreate{$_} = &can_create_user($newuserdom,$context,$_); } keys(%longtypes);
4328: # Get new users list
4329: my (%existinguser,%userinfo,%disallow,%rulematch,%inst_results,%alerts,%checkuname);
4330: my $counter = -1;
4331: foreach my $line (@userdata) {
4332: $counter ++;
4333: my @secs;
4334: my %entries=&Apache::loncommon::record_sep($line);
4335: # Determine user name
4336: $entries{$fields{'username'}} =~ s/^\s+|\s+$//g;
4337: unless (($entries{$fields{'username'}} eq '') ||
4338: (!defined($entries{$fields{'username'}}))) {
4339: my ($fname, $mname, $lname,$gen) = ('','','','');
4340: if (defined($fields{'names'})) {
4341: ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
4342: /([^\,]+)\,\s*(\w+)\s*(.*)$/);
4343: } else {
4344: if (defined($fields{'fname'})) {
4345: $fname=$entries{$fields{'fname'}};
4346: }
4347: if (defined($fields{'mname'})) {
4348: $mname=$entries{$fields{'mname'}};
4349: }
4350: if (defined($fields{'lname'})) {
4351: $lname=$entries{$fields{'lname'}};
4352: }
4353: if (defined($fields{'gen'})) {
4354: $gen=$entries{$fields{'gen'}};
4355: }
4356: }
4357:
4358: if ($entries{$fields{'username'}}
4359: ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
4360: my $nowhitespace;
4361: if ($entries{$fields{'username'}} =~ /\s/) {
4362: $nowhitespace = ' - '.&mt('usernames may not contain spaces.');
4363: }
4364: $disallow{$counter} =
4365: &mt('Unacceptable username [_1] for user [_2] [_3] [_4] [_5]',
4366: '"<b>'.$entries{$fields{'username'}}.'</b>"',
4367: $fname,$mname,$lname,$gen).$nowhitespace;
4368: next;
4369: } else {
4370: $entries{$fields{'domain'}} =~ s/^\s+|\s+$//g;
4371: if ($entries{$fields{'domain'}}
4372: ne &LONCAPA::clean_domain($entries{$fields{'domain'}})) {
4373: $disallow{$counter} =
4374: &mt('Unacceptable domain [_1] for user [_2] [_3] [_4] [_5]',
4375: '"<b>'.$entries{$fields{'domain'}}.'</b>"',
4376: $fname,$mname,$lname,$gen);
4377: next;
4378: }
4379: my $username = $entries{$fields{'username'}};
4380: my $userdomain = $entries{$fields{'domain'}};
4381: if ($userdomain eq '') {
4382: $userdomain = $domain;
4383: }
4384: if (defined($fields{'sec'})) {
4385: if (defined($entries{$fields{'sec'}})) {
4386: $entries{$fields{'sec'}} =~ s/\W//g;
4387: my $item = $entries{$fields{'sec'}};
4388: if ($item eq "none" || $item eq 'all') {
4389: $disallow{$counter} =
4390: &mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.',
4391: '<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item);
4392: next;
4393: } elsif (exists($curr_groups{$item})) {
4394: $disallow{$counter} =
4395: &mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.',
4396: '<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item).' '.
4397: &mt('Section names and group names must be distinct.');
4398: next;
4399: } else {
4400: push(@secs,$item);
4401: }
4402: }
4403: }
4404: if ($env{'request.course.sec'} ne '') {
4405: @secs = ($env{'request.course.sec'});
4406: if (ref($userlist{$username.':'.$userdomain}) eq 'ARRAY') {
4407: my $currsec = $userlist{$username.':'.$userdomain}[$secidx];
4408: if ($currsec ne $env{'request.course.sec'}) {
4409: $disallow{$counter} =
4410: &mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".',
4411: '<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$secs[0]);
4412: if ($currsec eq '') {
4413: $disallow{$counter} .=
4414: &mt('This user already has an active/future student role in the course, unaffiliated to any section.');
4415:
4416: } else {
4417: $disallow{$counter} .=
4418: &mt('This user already has an active/future role in section "[_1]" of the course.',$currsec);
4419: }
4420: $disallow{$counter} .=
4421: '<br />'.
4422: &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.',
4423: $secs[0]);
4424: next;
4425: }
4426: }
4427: } elsif ($context eq 'course' || $setting eq 'course') {
4428: if (@secs == 0) {
4429: @secs = @cleansec;
4430: }
4431: }
4432: # determine id number
4433: my $id='';
4434: if (defined($fields{'id'})) {
4435: if (defined($entries{$fields{'id'}})) {
4436: $id=$entries{$fields{'id'}};
4437: }
4438: $id=~tr/A-Z/a-z/;
4439: }
4440: # determine email address
4441: my $email='';
4442: if (defined($fields{'email'})) {
4443: $entries{$fields{'email'}} =~ s/^\s+|\s+$//g;
4444: if (defined($entries{$fields{'email'}})) {
4445: $email=$entries{$fields{'email'}};
4446: unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
4447: }
4448: }
4449: # determine affiliation
4450: my $inststatus='';
4451: if (defined($fields{'inststatus'})) {
4452: if (defined($entries{$fields{'inststatus'}})) {
4453: $inststatus=$entries{$fields{'inststatus'}};
4454: }
4455: }
4456: # determine user password
4457: my $password = $genpwd;
4458: if (defined($fields{'ipwd'})) {
4459: if ($entries{$fields{'ipwd'}}) {
4460: $password=$entries{$fields{'ipwd'}};
4461: }
4462: }
4463: # determine user role
4464: my $role = '';
4465: if (defined($fields{'role'})) {
4466: if ($entries{$fields{'role'}}) {
4467: $entries{$fields{'role'}} =~ s/(\s+$|^\s+)//g;
4468: if ($entries{$fields{'role'}} ne '') {
4469: if (grep(/^\Q$entries{$fields{'role'}}\E$/,@permitted_roles)) {
4470: $role = $entries{$fields{'role'}};
4471: }
4472: }
4473: if ($role eq '') {
4474: my $rolestr = join(', ',@permitted_roles);
4475: $disallow{$counter} =
4476: &mt('[_1]: You do not have permission to add the requested role [_2] for the user.'
4477: ,'<b>'.$entries{$fields{'username'}}.'</b>'
4478: ,$entries{$fields{'role'}})
4479: .'<br />'
4480: .&mt('Allowable role(s) is/are: [_1].',$rolestr);
4481: next;
4482: }
4483: }
4484: }
4485: if ($role eq '') {
4486: $role = $defaultrole;
4487: }
4488: # Clean up whitespace
4489: foreach (\$id,\$fname,\$mname,\$lname,\$gen,\$inststatus) {
4490: $$_ =~ s/(\s+$|^\s+)//g;
4491: }
4492: my $credits;
4493: if ($showcredits) {
4494: if (($role eq 'st') && ($crstype ne 'Community')) {
4495: $credits = $entries{$fields{'credits'}};
4496: if ($credits ne '') {
4497: $credits =~ s/[^\d\.]//g;
4498: }
4499: if ($credits eq '') {
4500: $credits = $commoncredits;
4501: }
4502: if ($credits eq $defaultcredits) {
4503: undef($credits);
4504: }
4505: }
4506: }
4507: # check against rules
4508: my $checkid = 0;
4509: my $newuser = 0;
4510: my $uhome=&Apache::lonnet::homeserver($username,$userdomain);
4511: if ($uhome eq 'no_host') {
4512: if ($userdomain ne $newuserdom) {
4513: if ($context eq 'course') {
4514: $disallow{$counter} =
4515: &mt('[_1]: The domain specified ([_2]) is different to that of the course.',
4516: '<b>'.$username.'</b>',$userdomain);
4517: } elsif ($context eq 'author') {
4518: $disallow{$counter} =
4519: &mt('[_1]: The domain specified ([_2]) is different to that of the author.',
4520: '<b>'.$username.'</b>',$userdomain);
4521: } else {
4522: $disallow{$counter} =
4523: &mt('[_1]: The domain specified ([_2]) is different to that of your current role.',
4524: '<b>'.$username.'</b>',$userdomain);
4525: }
4526: $disallow{$counter} .=
4527: &mt('The user does not already exist, and you may not create a new user in a different domain.');
4528: next;
4529: } else {
4530: unless ($password || $env{'form.login'} eq 'loc') {
4531: $disallow{$counter} =
4532: &mt('[_1]: This is a new user but no default password was provided, and the authentication type requires one.',
4533: '<b>'.$username.'</b>');
4534: next;
4535: }
4536: }
4537: $checkid = 1;
4538: $newuser = 1;
4539: $checkuname{$username.':'.$newuserdom} = { 'newuser' => $newuser, 'id' => $id };
4540: } else {
4541: if ($context eq 'course' || $context eq 'author') {
4542: if ($userdomain eq $domain ) {
4543: if ($role eq '') {
4544: my @checkroles;
4545: foreach my $role (@poss_roles) {
4546: my $endkey;
4547: if ($role ne 'st') {
4548: $endkey = ':'.$role;
4549: }
4550: if (exists($userlist{$username.':'.$userdomain.$endkey})) {
4551: if (!grep(/^\Q$role\E$/,@checkroles)) {
4552: push(@checkroles,$role);
4553: }
4554: }
4555: }
4556: if (@checkroles > 0) {
4557: %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles);
4558: }
4559: } elsif (ref($modifiable_fields{$role}) eq 'HASH') {
4560: %canmodify = %{$modifiable_fields{$role}};
4561: }
4562: }
4563: my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id);
4564: for (my $i=0; $i<@newinfo; $i++) {
4565: if (${$newinfo[$i]} ne '') {
4566: if (!$canmodify{$userinfo[$i]}) {
4567: ${$newinfo[$i]} = '';
4568: }
4569: }
4570: }
4571: }
4572: if ($id) {
4573: $existinguser{$userdomain}{$username} = $id;
4574: }
4575: }
4576: $userinfo{$counter} = {
4577: username => $username,
4578: domain => $userdomain,
4579: fname => $fname,
4580: mname => $mname,
4581: lname => $lname,
4582: gen => $gen,
4583: email => $email,
4584: id => $id,
4585: password => $password,
4586: inststatus => $inststatus,
4587: role => $role,
4588: sections => \@secs,
4589: credits => $credits,
4590: newuser => $newuser,
4591: checkid => $checkid,
4592: };
4593: }
4594: }
4595: } # end of foreach (@userdata)
4596: if ($counter > -1) {
4597: my $total = $counter + 1;
4598: my %checkids;
4599: if ((keys(%existinguser)) || (keys(%checkuname))) {
4600: $r->print(&mt('Please be patient -- checking for institutional data ...'));
4601: $r->rflush();
4602: if (keys(%existinguser)) {
4603: foreach my $dom (keys(%existinguser)) {
4604: if (ref($existinguser{$dom}) eq 'HASH') {
4605: my %idhash = &Apache::lonnet::idrget($dom,keys(%{$existinguser{$dom}}));
4606: foreach my $username (keys(%{$existinguser{$dom}})) {
4607: if ($idhash{$username} ne $existinguser{$dom}{$username}) {
4608: $checkids{$username.':'.$dom} = {
4609: 'id' => $existinguser{$dom}{$username},
4610: };
4611: }
4612: }
4613: if (keys(%checkids)) {
4614: &Apache::loncommon::user_rule_check(\%checkids,{ 'id' => 1 },
4615: \%alerts,\%rulematch,
4616: \%inst_results,\%curr_rules,
4617: \%got_rules);
4618: }
4619: }
4620: }
4621: }
4622: if (keys(%checkuname)) {
4623: &Apache::loncommon::user_rule_check(\%checkuname,{ 'username' => 1, 'id' => 1, },
4624: \%alerts,\%rulematch,\%inst_results,
4625: \%curr_rules,\%got_rules);
4626: }
4627: $r->print(' '.&mt('done').'<br /><br />');
4628: $r->rflush();
4629: }
4630: my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($r,$total);
4631: $r->print('<ul>');
4632: for (my $i=0; $i<=$counter; $i++) {
4633: if ($disallow{$i}) {
4634: $r->print('<li>'.$disallow{$i}.'</li>');
4635: } elsif (ref($userinfo{$i}) eq 'HASH') {
4636: my $password = $userinfo{$i}{'password'};
4637: my $newuser = $userinfo{$i}{'newuser'};
4638: my $checkid = $userinfo{$i}{'checkid'};
4639: my $id = $userinfo{$i}{'id'};
4640: my $role = $userinfo{$i}{'role'};
4641: my @secs;
4642: if (ref($userinfo{$i}{'sections'}) eq 'ARRAY') {
4643: @secs = @{$userinfo{$i}{'sections'}};
4644: }
4645: my $fname = $userinfo{$i}{'fname'};
4646: my $mname = $userinfo{$i}{'mname'};
4647: my $lname = $userinfo{$i}{'lname'};
4648: my $gen = $userinfo{$i}{'gen'};
4649: my $email = $userinfo{$i}{'email'};
4650: my $inststatus = $userinfo{$i}{'inststatus'};
4651: my $credits = $userinfo{$i}{'credits'};
4652: my $username = $userinfo{$i}{'username'};
4653: my $userdomain = $userinfo{$i}{'domain'};
4654: my $user = $username.':'.$userdomain;
4655: if ($newuser) {
4656: if (ref($alerts{'username'}) eq 'HASH') {
4657: if (ref($alerts{'username'}{$userdomain}) eq 'HASH') {
4658: if ($alerts{'username'}{$userdomain}{$username}) {
4659: $r->print('<li>'.
4660: &mt('[_1]: matches the username format at your institution, but is not known to your directory service.','<b>'.$username.'</b>').'<br />'.
4661: &mt('Consequently, the user was not created.').'</li>');
4662: next;
4663: }
4664: }
4665: }
4666: if (ref($inst_results{$user}) eq 'HASH') {
4667: if ($inst_results{$user}{'firstname'} ne '') {
4668: $fname = $inst_results{$user}{'firstname'};
4669: }
4670: if ($inst_results{$user}{'middlename'} ne '') {
4671: $mname = $inst_results{$user}{'middlename'};
4672: }
4673: if ($inst_results{$user}{'lasttname'} ne '') {
4674: $lname = $inst_results{$user}{'lastname'};
4675: }
4676: if ($inst_results{$user}{'permanentemail'} ne '') {
4677: $email = $inst_results{$user}{'permanentemail'};
4678: }
4679: if ($inst_results{$user}{'id'} ne '') {
4680: $id = $inst_results{$user}{'id'};
4681: $checkid = 0;
4682: }
4683: if (ref($inst_results{$user}{'inststatus'}) eq 'ARRAY') {
4684: $inststatus = join(':',@{$inst_results{$user}{'inststatus'}});
4685: }
4686: }
4687: if (($checkid) && ($id ne '')) {
4688: if (ref($alerts{'id'}) eq 'HASH') {
4689: if (ref($alerts{'id'}{$userdomain}) eq 'HASH') {
4690: if ($alerts{'id'}{$userdomain}{$username}) {
4691: $r->print('<li>'.
4692: &mt('[_1]: has a student/employee ID matching the format at your institution, but the ID is not found by your directory service.',
4693: '<b>'.$username.'</b>').'<br />'.
4694: &mt('Consequently, the user was not created.').'</li>');
4695: next;
4696: }
4697: }
4698: }
4699: }
4700: my $usertype = 'unofficial';
4701: if (ref($rulematch{$user}) eq 'HASH') {
4702: if ($rulematch{$user}{'username'}) {
4703: $usertype = 'official';
4704: }
4705: }
4706: unless ($cancreate{$usertype}) {
4707: my $showtype = $longtypes{$usertype};
4708: $r->print('<li>'.
4709: &mt('[_1]: The user does not exist, and you are not permitted to create users of type: [_2].','<b>'.$username.'</b>',$showtype).'</li>');
4710: next;
4711: }
4712: } elsif ($id ne '') {
4713: if (exists($checkids{$user})) {
4714: $checkid = 1;
4715: if (ref($alerts{'id'}) eq 'HASH') {
4716: if (ref($alerts{'id'}{$userdomain}) eq 'HASH') {
4717: if ($alerts{'id'}{$userdomain}{$username}) {
4718: $r->print('<li>'.
4719: &mt('[_1]: has a student/employee ID matching the format at your institution, but the ID is not found by your directory service.',
4720: '<b>'.$username.'</b>').'<br />'.
4721: &mt('Consequently, the ID was not changed.').'</li>');
4722: $id = '';
4723: }
4724: }
4725: }
4726: }
4727: }
4728: my $multiple = 0;
4729: my ($userresult,$authresult,$roleresult,$idresult);
4730: my (%userres,%authres,%roleres,%idres);
4731: my $singlesec = '';
4732: if ($role eq 'st') {
4733: my $sec;
4734: if (ref($userinfo{$i}{'sections'}) eq 'ARRAY') {
4735: if (@secs > 0) {
4736: $sec = $secs[0];
4737: }
4738: }
4739: &modifystudent($userdomain,$username,$cid,$sec,
4740: $desiredhost,$context);
4741: $roleresult =
4742: &Apache::lonnet::modifystudent
4743: ($userdomain,$username,$id,$amode,$password,
4744: $fname,$mname,$lname,$gen,$sec,$enddate,
4745: $startdate,$env{'form.forceid'},
4746: $desiredhost,$email,'manual','',$cid,
4747: '',$context,$inststatus,$credits);
4748: $userresult = $roleresult;
4749: } else {
4750: if ($role ne '') {
4751: if ($context eq 'course' || $setting eq 'course') {
4752: if ($customroles{$role}) {
4753: $role = 'cr_'.$env{'user.domain'}.'_'.
4754: $env{'user.name'}.'_'.$role;
4755: }
4756: if (($role ne 'cc') && ($role ne 'co')) {
4757: if (@secs > 1) {
4758: $multiple = 1;
4759: foreach my $sec (@secs) {
4760: ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
4761: &modifyuserrole($context,$setting,
4762: $changeauth,$cid,$userdomain,$username,
4763: $id,$amode,$password,$fname,
4764: $mname,$lname,$gen,$sec,
4765: $env{'form.forceid'},$desiredhost,
4766: $email,$role,$enddate,
4767: $startdate,$checkid,$inststatus);
4768: }
4769: } elsif (@secs > 0) {
4770: $singlesec = $secs[0];
4771: }
4772: }
4773: }
4774: if (!$multiple) {
4775: ($userresult,$authresult,$roleresult,$idresult) =
4776: &modifyuserrole($context,$setting,
4777: $changeauth,$cid,$userdomain,$username,
4778: $id,$amode,$password,$fname,
4779: $mname,$lname,$gen,$singlesec,
4780: $env{'form.forceid'},$desiredhost,
4781: $email,$role,$enddate,$startdate,
4782: $checkid,$inststatus);
4783: }
4784: }
4785: }
4786: if ($multiple) {
4787: foreach my $sec (sort(keys(%userres))) {
4788: $flushc =
4789: &user_change_result($r,$userres{$sec},$authres{$sec},
4790: $roleres{$sec},$idres{$sec},\%counts,$flushc,
4791: $username,$userdomain,\%userchg);
4792:
4793: }
4794: } else {
4795: $flushc =
4796: &user_change_result($r,$userresult,$authresult,
4797: $roleresult,$idresult,\%counts,$flushc,
4798: $username,$userdomain,\%userchg);
4799: }
4800: }
4801: &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last user');
4802: } # end of loop
4803: $r->print('</ul>');
4804: &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
4805: }
4806: # Flush the course logs so reverse user roles immediately updated
4807: $r->register_cleanup(\&Apache::lonnet::flushcourselogs);
4808: $r->print("</p>\n<p>\n".&mt('Processed [quant,_1,user].',$counts{'user'}).
4809: "</p>\n");
4810: if ($counts{'role'} > 0) {
4811: $r->print("<p>\n".
4812: &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");
4813: } else {
4814: $r->print('<p>'.&mt('No roles added').'</p>');
4815: }
4816: if ($counts{'auth'} > 0) {
4817: $r->print("<p>\n".
4818: &mt('Authentication changed for [_1] existing users.',
4819: $counts{'auth'})."</p>\n");
4820: }
4821: $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules));
4822: #####################################
4823: # Display list of students to drop #
4824: #####################################
4825: if ($env{'form.fullup'} eq 'yes') {
4826: $r->print('<h3>'.&mt('Students to Drop')."</h3>\n");
4827: # Get current classlist
4828: my $classlist = &Apache::loncoursedata::get_classlist();
4829: if (! defined($classlist)) {
4830: $r->print('<form name="studentform" method="post" action="/adm/createuser">'.
4831: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'.
4832: '<p class="LC_info">'.&mt('There are no students with current/future access to the course.').'</p>'.
4833: '</form>'."\n");
4834: } elsif (ref($classlist) eq 'HASH') {
4835: # Remove the students we just added from the list of students.
4836: foreach my $line (@userdata) {
4837: my %entries=&Apache::loncommon::record_sep($line);
4838: unless (($entries{$fields{'username'}} eq '') ||
4839: (!defined($entries{$fields{'username'}}))) {
4840: delete($classlist->{$entries{$fields{'username'}}.
4841: ':'.$domain});
4842: }
4843: }
4844: # Print out list of dropped students.
4845: &show_drop_list($r,$classlist,'nosort',$permission);
4846: }
4847: }
4848: } # end of unless
4849: if ($env{'form.fullup'} ne 'yes') {
4850: $r->print('</form>');
4851: }
4852: }
4853:
4854: sub print_namespacing_alerts {
4855: my ($domain,$alerts,$curr_rules) = @_;
4856: my $output;
4857: if (ref($alerts) eq 'HASH') {
4858: if (keys(%{$alerts}) > 0) {
4859: if (ref($alerts->{'username'}) eq 'HASH') {
4860: foreach my $dom (sort(keys(%{$alerts->{'username'}}))) {
4861: my $count;
4862: if (ref($alerts->{'username'}{$dom}) eq 'HASH') {
4863: $count = keys(%{$alerts->{'username'}{$dom}});
4864: }
4865: my $domdesc = &Apache::lonnet::domain($domain,'description');
4866: if (ref($curr_rules->{$dom}) eq 'HASH') {
4867: $output .= &Apache::loncommon::instrule_disallow_msg(
4868: 'username',$domdesc,$count,'upload');
4869: }
4870: $output .= &Apache::loncommon::user_rule_formats($dom,
4871: $domdesc,$curr_rules->{$dom}{'username'},
4872: 'username');
4873: }
4874: }
4875: if (ref($alerts->{'id'}) eq 'HASH') {
4876: foreach my $dom (sort(keys(%{$alerts->{'id'}}))) {
4877: my $count;
4878: if (ref($alerts->{'id'}{$dom}) eq 'HASH') {
4879: $count = keys(%{$alerts->{'id'}{$dom}});
4880: }
4881: my $domdesc = &Apache::lonnet::domain($domain,'description');
4882: if (ref($curr_rules->{$dom}) eq 'HASH') {
4883: $output .= &Apache::loncommon::instrule_disallow_msg(
4884: 'id',$domdesc,$count,'upload');
4885: }
4886: $output .= &Apache::loncommon::user_rule_formats($dom,
4887: $domdesc,$curr_rules->{$dom}{'id'},'id');
4888: }
4889: }
4890: }
4891: }
4892: }
4893:
4894: sub user_change_result {
4895: my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc,
4896: $username,$userdomain,$userchg) = @_;
4897: my $okresult = 0;
4898: my @status;
4899: if ($userresult ne 'ok') {
4900: if ($userresult =~ /^error:(.+)$/) {
4901: my $error = $1;
4902: push(@status,
4903: &mt('[_1]: Unable to add/modify: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
4904: }
4905: } else {
4906: $counts->{'user'} ++;
4907: $okresult = 1;
4908: }
4909: if ($authresult ne 'ok') {
4910: if ($authresult =~ /^error:(.+)$/) {
4911: my $error = $1;
4912: push(@status,
4913: &mt('[_1]: Unable to modify authentication: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
4914: }
4915: } else {
4916: $counts->{'auth'} ++;
4917: $okresult = 1;
4918: }
4919: if ($roleresult ne 'ok') {
4920: if ($roleresult =~ /^error:(.+)$/) {
4921: my $error = $1;
4922: push(@status,
4923: &mt('[_1]: Unable to add role: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error));
4924: }
4925: } else {
4926: $counts->{'role'} ++;
4927: $okresult = 1;
4928: }
4929: if ($okresult) {
4930: $flushc++;
4931: $userchg->{$username.':'.$userdomain}=1;
4932: if ($flushc>15) {
4933: $r->rflush;
4934: $flushc=0;
4935: }
4936: }
4937: if ($idresult) {
4938: push(@status,$idresult);
4939: }
4940: if (@status) {
4941: $r->print('<li>'.join('<br />',@status).'</li>');
4942: }
4943: return $flushc;
4944: }
4945:
4946: # ========================================================= Menu Phase Two Drop
4947: sub print_drop_menu {
4948: my ($r,$context,$permission,$crstype) = @_;
4949: my $heading;
4950: if ($crstype eq 'Community') {
4951: $heading = &mt("Drop Members");
4952: } else {
4953: $heading = &mt("Drop Students");
4954: }
4955: $r->print('<h3>'.$heading.'</h3>'."\n".
4956: '<form name="studentform" method="post" action="">'."\n");
4957: my $classlist = &Apache::loncoursedata::get_classlist();
4958: if (! defined($classlist)) {
4959: my $msg = '';
4960: if ($crstype eq 'Community') {
4961: $msg = &mt('There are no members currently enrolled.');
4962: } else {
4963: $msg = &mt('There are no students currently enrolled.');
4964: }
4965: $r->print('<p class="LC_info">'.$msg."</p>\n");
4966: } else {
4967: &show_drop_list($r,$classlist,'nosort',$permission,$crstype);
4968: }
4969: $r->print('</form>');
4970: return;
4971: }
4972:
4973: # ================================================================== Phase four
4974:
4975: sub update_user_list {
4976: my ($r,$context,$setting,$choice,$crstype) = @_;
4977: my $now = time;
4978: my $count=0;
4979: if ($context eq 'course') {
4980: $crstype = &Apache::loncommon::course_type();
4981: }
4982: my @changelist;
4983: if ($choice eq 'drop') {
4984: @changelist = &Apache::loncommon::get_env_multiple('form.droplist');
4985: } else {
4986: @changelist = &Apache::loncommon::get_env_multiple('form.actionlist');
4987: }
4988: my %result_text = ( ok => { 'revoke' => 'Revoked',
4989: 'delete' => 'Deleted',
4990: 'reenable' => 'Re-enabled',
4991: 'activate' => 'Activated',
4992: 'chgdates' => 'Changed Access Dates for',
4993: 'chgsec' => 'Changed section(s) for',
4994: 'drop' => 'Dropped',
4995: },
4996: error => {'revoke' => 'revoking',
4997: 'delete' => 'deleting',
4998: 'reenable' => 're-enabling',
4999: 'activate' => 'activating',
5000: 'chgdates' => 'changing access dates for',
5001: 'chgsec' => 'changing section for',
5002: 'drop' => 'dropping',
5003: },
5004: );
5005: my ($startdate,$enddate);
5006: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
5007: ($startdate,$enddate) = &get_dates_from_form();
5008: }
5009: foreach my $item (@changelist) {
5010: my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,
5011: @sections,$scopestem,$singlesec,$showsecs,$warn_singlesec,
5012: $nothingtodo,$keepnosection,$credits,$instsec);
5013: if ($choice eq 'drop') {
5014: ($uname,$udom,$sec) = split(/:/,$item,-1);
5015: $role = 'st';
5016: $cid = $env{'request.course.id'};
5017: $scopestem = '/'.$cid;
5018: $scopestem =~s/\_/\//g;
5019: if ($sec eq '') {
5020: $scope = $scopestem;
5021: } else {
5022: $scope = $scopestem.'/'.$sec;
5023: }
5024: } elsif ($context eq 'course') {
5025: ($uname,$udom,$role,$sec,$type,$locktype,$credits,$instsec) =
5026: split(/\:/,$item,8);
5027: $instsec = &unescape($instsec);
5028: $cid = $env{'request.course.id'};
5029: $scopestem = '/'.$cid;
5030: $scopestem =~s/\_/\//g;
5031: if ($sec eq '') {
5032: $scope = $scopestem;
5033: } else {
5034: $scope = $scopestem.'/'.$sec;
5035: }
5036: } elsif ($context eq 'author') {
5037: ($uname,$udom,$role) = split(/\:/,$item,-1);
5038: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
5039: } elsif ($context eq 'domain') {
5040: if ($setting eq 'domain') {
5041: ($role,$uname,$udom) = split(/\:/,$item,-1);
5042: $scope = '/'.$env{'request.role.domain'}.'/';
5043: } elsif ($setting eq 'author') {
5044: ($uname,$udom,$role,$scope) = split(/\:/,$item);
5045: } elsif ($setting eq 'course') {
5046: ($uname,$udom,$role,$cid,$sec,$type,$locktype,$credits,$instsec) =
5047: split(/\:/,$item,9);
5048: $instsec = &unescape($instsec);
5049: $scope = '/'.$cid;
5050: $scope =~s/\_/\//g;
5051: if ($sec ne '') {
5052: $scope .= '/'.$sec;
5053: }
5054: }
5055: }
5056: my $plrole = &Apache::lonnet::plaintext($role,$crstype);
5057: my $start = $env{'form.'.$item.'_start'};
5058: my $end = $env{'form.'.$item.'_end'};
5059: if ($choice eq 'drop') {
5060: # drop students
5061: $end = $now;
5062: $type = 'manual';
5063: $result =
5064: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context);
5065: } elsif ($choice eq 'revoke') {
5066: # revoke or delete user role
5067: $end = $now;
5068: if ($role eq 'st') {
5069: $result =
5070: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5071: } else {
5072: $result =
5073: &Apache::lonnet::revokerole($udom,$uname,$scope,$role,
5074: '','',$context);
5075: }
5076: } elsif ($choice eq 'delete') {
5077: if ($role eq 'st') {
5078: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5079: }
5080: $result =
5081: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
5082: $start,1,'',$context);
5083: } else {
5084: #reenable, activate, change access dates or change section
5085: if ($choice ne 'chgsec') {
5086: $start = $startdate;
5087: $end = $enddate;
5088: }
5089: if ($choice eq 'reenable') {
5090: if ($role eq 'st') {
5091: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5092: } else {
5093: $result =
5094: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
5095: $now,'','',$context);
5096: }
5097: } elsif ($choice eq 'activate') {
5098: if ($role eq 'st') {
5099: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5100: } else {
5101: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
5102: $now,'','',$context);
5103: }
5104: } elsif ($choice eq 'chgdates') {
5105: if ($role eq 'st') {
5106: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5107: } else {
5108: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
5109: $start,'','',$context);
5110: }
5111: } elsif ($choice eq 'chgsec') {
5112: my (@newsecs,$revresult,$nochg,@retained);
5113: if (($role ne 'cc') && ($role ne 'co')) {
5114: my @secs = sort(split(/,/,$env{'form.newsecs'}));
5115: if (@secs) {
5116: my %curr_groups = &Apache::longroup::coursegroups();
5117: foreach my $sec (@secs) {
5118: next if (($sec =~ /\W/) || ($sec eq 'none') ||
5119: (exists($curr_groups{$sec})));
5120: push(@newsecs,$sec);
5121: }
5122: }
5123: }
5124: # remove existing section if not to be retained.
5125: if (!$env{'form.retainsec'} || ($role eq 'st')) {
5126: if ($sec eq '') {
5127: if (@newsecs == 0) {
5128: $result = 'ok';
5129: $nochg = 1;
5130: $nothingtodo = 1;
5131: } else {
5132: $revresult =
5133: &Apache::lonnet::revokerole($udom,$uname,
5134: $scope,$role,
5135: '','',$context);
5136: }
5137: } else {
5138: if (@newsecs > 0) {
5139: if (grep(/^\Q$sec\E$/,@newsecs)) {
5140: push(@retained,$sec);
5141: } else {
5142: $revresult =
5143: &Apache::lonnet::revokerole($udom,$uname,
5144: $scope,$role,
5145: '','',$context);
5146: }
5147: } else {
5148: $revresult =
5149: &Apache::lonnet::revokerole($udom,$uname,
5150: $scope,$role,
5151: '','',$context);
5152: }
5153: }
5154: } else {
5155: if ($sec eq '') {
5156: $nochg = 1;
5157: $keepnosection = 1;
5158: } else {
5159: push(@retained,$sec);
5160: }
5161: }
5162: # add new sections
5163: my (@diffs,@shownew);
5164: if (@retained) {
5165: @diffs = &Apache::loncommon::compare_arrays(\@retained,\@newsecs);
5166: } else {
5167: @diffs = @newsecs;
5168: }
5169: if (@newsecs == 0) {
5170: if ($nochg) {
5171: $result = 'ok';
5172: $nothingtodo = 1;
5173: } else {
5174: if ($role eq 'st') {
5175: $result =
5176: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5177: } else {
5178: my $newscope = $scopestem;
5179: $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start,'','',$context);
5180: }
5181: }
5182: $showsecs = &mt('No section');
5183: } elsif (@diffs == 0) {
5184: $result = 'ok';
5185: $nothingtodo = 1;
5186: } else {
5187: foreach my $newsec (@newsecs) {
5188: if (!grep(/^\Q$newsec\E$/,@retained)) {
5189: if ($role eq 'st') {
5190: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context,$credits,$instsec);
5191: if (@newsecs > 1) {
5192: my $showsingle;
5193: if ($newsec eq '') {
5194: $showsingle = &mt('No section');
5195: } else {
5196: $showsingle = $newsec;
5197: }
5198: if ($crstype eq 'Community') {
5199: $warn_singlesec = &mt('Although more than one section was indicated, a role was only added for the first section - [_1], as each community member may only be in one section at a time.','<i>'.$showsingle.'</i>');
5200: } else {
5201: $warn_singlesec = &mt('Although more than one section was indicated, a role was only added for the first section - [_1], as each student may only be in one section of a course at a time.','<i>'.$showsingle.'</i>');
5202: }
5203: $showsecs = $showsingle;
5204: last;
5205: } else {
5206: if ($newsec eq '') {
5207: $showsecs = &mt('No section');
5208: } else {
5209: $showsecs = $newsec;
5210: }
5211: }
5212: } else {
5213: my $newscope = $scopestem;
5214: if ($newsec ne '') {
5215: $newscope .= '/'.$newsec;
5216: push(@shownew,$newsec);
5217: }
5218: $result = &Apache::lonnet::assignrole($udom,$uname,
5219: $newscope,$role,$end,$start);
5220:
5221: }
5222: }
5223: }
5224: }
5225: unless ($role eq 'st') {
5226: unless ($showsecs) {
5227: my @tolist = sort(@shownew,@retained);
5228: if ($keepnosection) {
5229: push(@tolist,&mt('No section'));
5230: }
5231: $showsecs = join(', ',@tolist);
5232: }
5233: }
5234: }
5235: }
5236: my $extent = $scope;
5237: if ($choice eq 'drop' || $context eq 'course') {
5238: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
5239: if ($cdesc) {
5240: $extent = $cdesc;
5241: }
5242: }
5243: if ($result eq 'ok' || $result eq 'ok:') {
5244: my $dates;
5245: if (($choice eq 'chgsec') || ($choice eq 'chgdates')) {
5246: $dates = &dates_feedback($start,$end,$now);
5247: }
5248: if ($choice eq 'chgsec') {
5249: if ($nothingtodo) {
5250: $r->print(&mt("Section assignment for role of '[_1]' in [_2] for '[_3]' unchanged.",$plrole,$extent,'<i>'.
5251: &Apache::loncommon::plainname($uname,$udom).
5252: '</i>').' ');
5253: if ($sec eq '') {
5254: $r->print(&mt('[_1]No section[_2] - [_3]','<b>','</b>',$dates));
5255: } else {
5256: $r->print(&mt('Section(s): [_1] - [_2]',
5257: '<b>'.$showsecs.'</b>',$dates));
5258: }
5259: $r->print('<br />');
5260: } else {
5261: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]' to [_4] - [_5]",$plrole,$extent,
5262: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>',
5263: '<b>'.$showsecs.'</b>',$dates).'<br />');
5264: $count ++;
5265: }
5266: if ($warn_singlesec) {
5267: $r->print('<div class="LC_warning">'.$warn_singlesec.'</div>');
5268: }
5269: } elsif ($choice eq 'chgdates') {
5270: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]' - [_4]",$plrole,$extent,
5271: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>',
5272: $dates).'<br />');
5273: $count ++;
5274: } else {
5275: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for '[_3]'.",$plrole,$extent,
5276: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>').
5277: '<br />');
5278: $count ++;
5279: }
5280: } else {
5281: $r->print(
5282: &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for '[_3]': [_4].",
5283: $plrole,$extent,
5284: '<i>'.&Apache::loncommon::plainname($uname,$udom).'</i>',
5285: $result).'<br />');
5286: }
5287: }
5288: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n");
5289: if ($choice eq 'drop') {
5290: $r->print('<input type="hidden" name="action" value="listusers" />'."\n".
5291: '<input type="hidden" name="Status" value="Active" />'."\n".
5292: '<input type="hidden" name="showrole" value="st" />'."\n");
5293: } else {
5294: foreach my $item ('action','sortby','roletype','showrole','Status','secfilter','grpfilter') {
5295: if ($env{'form.'.$item} ne '') {
5296: $r->print('<input type="hidden" name="'.$item.'" value="'.$env{'form.'.$item}.
5297: '" />'."\n");
5298: }
5299: }
5300: }
5301: $r->print('<p><b>'.&mt("$result_text{'ok'}{$choice} [quant,_1,user role,user roles,no user roles].",$count).'</b></p>');
5302: if ($count > 0) {
5303: if ($choice eq 'revoke' || $choice eq 'drop') {
5304: $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.').'</p>');
5305: }
5306: # Flush the course logs so reverse user roles immediately updated
5307: $r->register_cleanup(\&Apache::lonnet::flushcourselogs);
5308: }
5309: if ($env{'form.makedatesdefault'}) {
5310: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
5311: $r->print(&make_dates_default($startdate,$enddate,$context,$crstype));
5312: }
5313: }
5314: my $linktext = &mt('Display User Lists');
5315: if ($choice eq 'drop') {
5316: $linktext = &mt('Display current class roster');
5317: }
5318: $r->print(
5319: &Apache::lonhtmlcommon::actionbox(
5320: ['<a href="javascript:document.studentform.submit()">'.$linktext.'</a>'])
5321: .'</form>'."\n");
5322: }
5323:
5324: sub dates_feedback {
5325: my ($start,$end,$now) = @_;
5326: my $dates;
5327: if ($start < $now) {
5328: if ($end == 0) {
5329: $dates = &mt('role(s) active now; no end date');
5330: } elsif ($end > $now) {
5331: $dates = &mt('role(s) active now; ends [_1].',&Apache::lonlocal::locallocaltime($end));
5332: } else {
5333: $dates = &mt('role(s) expired: [_1].',&Apache::lonlocal::locallocaltime($end));
5334: }
5335: } else {
5336: if ($end == 0 || $end > $now) {
5337: $dates = &mt('future role(s); starts: [_1].',&Apache::lonlocal::locallocaltime($start));
5338: } else {
5339: $dates = &mt('role(s) expired: [_1].',&Apache::lonlocal::locallocaltime($end));
5340: }
5341: }
5342: return $dates;
5343: }
5344:
5345: sub classlist_drop {
5346: my ($scope,$uname,$udom,$now) = @_;
5347: my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
5348: if (&Apache::lonnet::is_course($cdom,$cnum)) {
5349: if (!&active_student_roles($cnum,$cdom,$uname,$udom)) {
5350: my %user;
5351: my $result = &update_classlist($cdom,$cnum,$udom,$uname,\%user,$now);
5352: return &mt('Drop from classlist: [_1]',
5353: '<b>'.$result.'</b>').'<br />';
5354: }
5355: }
5356: }
5357:
5358: sub active_student_roles {
5359: my ($cnum,$cdom,$uname,$udom) = @_;
5360: my %roles =
5361: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
5362: ['future','active'],['st']);
5363: return exists($roles{"$cnum:$cdom:st"});
5364: }
5365:
5366: sub section_check_js {
5367: my $groupslist= &get_groupslist();
5368: my %js_lt = &Apache::lonlocal::texthash(
5369: mayn => 'may not be used as the name for a section, as it is a reserved word.',
5370: plch => 'Please choose a different section name.',
5371: mnot => 'may not be used as a section name, as it is the name of a course group.',
5372: secn => 'Section names and group names must be distinct. Please choose a different section name.',
5373: );
5374: &js_escape(\%js_lt);
5375: return <<"END";
5376: function validate(caller) {
5377: var groups = new Array($groupslist);
5378: var secname = caller.value;
5379: if ((secname == 'all') || (secname == 'none')) {
5380: alert("'"+secname+"' $js_lt{'mayn'}\\n$js_lt{'plch'}");
5381: return 'error';
5382: }
5383: if (secname != '') {
5384: for (var k=0; k<groups.length; k++) {
5385: if (secname == groups[k]) {
5386: alert("'"+secname+"' $js_lt{'mnot'}\\n$js_lt{'secn'}");
5387: return 'error';
5388: }
5389: }
5390: }
5391: return 'ok';
5392: }
5393: END
5394: }
5395:
5396: sub set_login {
5397: my ($dom,$authformkrb,$authformint,$authformloc) = @_;
5398: my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
5399: my $response;
5400: my ($authnum,%can_assign) =
5401: &Apache::loncommon::get_assignable_auth($dom);
5402: if ($authnum) {
5403: $response = &Apache::loncommon::start_data_table();
5404: if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
5405: $response .= &Apache::loncommon::start_data_table_row().
5406: '<td>'.$authformkrb.'</td>'.
5407: &Apache::loncommon::end_data_table_row()."\n";
5408: }
5409: if ($can_assign{'int'}) {
5410: $response .= &Apache::loncommon::start_data_table_row().
5411: '<td>'.$authformint.'</td>'.
5412: &Apache::loncommon::end_data_table_row()."\n"
5413: }
5414: if ($can_assign{'loc'}) {
5415: $response .= &Apache::loncommon::start_data_table_row().
5416: '<td>'.$authformloc.'</td>'.
5417: &Apache::loncommon::end_data_table_row()."\n";
5418: }
5419: $response .= &Apache::loncommon::end_data_table();
5420: }
5421: return $response;
5422: }
5423:
5424: sub course_sections {
5425: my ($sections_count,$role,$current_sec,$disabled) = @_;
5426: my $output = '';
5427: my @sections = (sort {$a <=> $b} keys(%{$sections_count}));
5428: my $numsec = scalar(@sections);
5429: my $is_selected = ' selected="selected"';
5430: if ($numsec <= 1) {
5431: $output = '<select name="currsec_'.$role.'"'.$disabled.'>'."\n".
5432: ' <option value="">'.&mt('Select').'</option>'."\n";
5433: if ($current_sec eq 'none') {
5434: $output .=
5435: ' <option value=""'.$is_selected.'>'.&mt('No section').'</option>'."\n";
5436: } else {
5437: $output .=
5438: ' <option value="">'.&mt('No section').'</option>'."\n";
5439: }
5440: if ($numsec == 1) {
5441: if ($current_sec eq $sections[0]) {
5442: $output .=
5443: ' <option value="'.$sections[0].'"'.$is_selected.'>'.$sections[0].'</option>'."\n";
5444: } else {
5445: $output .=
5446: ' <option value="'.$sections[0].'" >'.$sections[0].'</option>'."\n";
5447: }
5448: }
5449: } else {
5450: $output = '<select name="currsec_'.$role.'" ';
5451: my $multiple = 4;
5452: if (scalar(@sections) < 4) { $multiple = scalar(@sections); }
5453: if ($role eq 'st') {
5454: $output .= $disabled.'>'."\n".
5455: ' <option value="">'.&mt('Select').'</option>'."\n";
5456: if ($current_sec eq 'none') {
5457: $output .=
5458: ' <option value=""'.$is_selected.'>'.&mt('No section')."</option>\n";
5459: } else {
5460: $output .=
5461: ' <option value="">'.&mt('No section')."</option>\n";
5462: }
5463: } else {
5464: $output .= 'multiple="multiple" size="'.$multiple.'"'.$disabled.'>'."\n";
5465: }
5466: foreach my $sec (@sections) {
5467: if ($current_sec eq $sec) {
5468: $output .= '<option value="'.$sec.'"'.$is_selected.'>'.$sec."</option>\n";
5469: } else {
5470: $output .= '<option value="'.$sec.'">'.$sec."</option>\n";
5471: }
5472: }
5473: }
5474: $output .= '</select>';
5475: return $output;
5476: }
5477:
5478: sub get_groupslist {
5479: my $groupslist;
5480: my %curr_groups = &Apache::longroup::coursegroups();
5481: if (%curr_groups) {
5482: $groupslist = join('","',sort(keys(%curr_groups)));
5483: $groupslist = '"'.$groupslist.'"';
5484: }
5485: return $groupslist;
5486: }
5487:
5488: sub setsections_javascript {
5489: my ($formname,$groupslist,$mode,$checkauth,$crstype,$showcredits) = @_;
5490: my ($checkincluded,$finish,$rolecode,$setsection_js);
5491: if ($mode eq 'upload') {
5492: $checkincluded = 'formname.name == "'.$formname.'"';
5493: $finish = "return 'ok';";
5494: $rolecode = "var role = formname.defaultrole.options[formname.defaultrole.selectedIndex].value;\n";
5495: } elsif ($formname eq 'cu') {
5496: if (($crstype eq 'Course') && ($showcredits)) {
5497: $checkincluded = "((role == 'st') && (formname.elements[i-2].checked == true)) || ((role != 'st') && (formname.elements[i-1].checked == true))";
5498: } else {
5499: $checkincluded = 'formname.elements[i-1].checked == true';
5500: }
5501: if ($checkauth) {
5502: $finish = "var authcheck = auth_check();\n".
5503: " if (authcheck == 'ok') {\n".
5504: " formname.submit();\n".
5505: " }\n";
5506: } else {
5507: $finish = 'formname.submit()';
5508: }
5509: $rolecode = "var match = str.split('_');
5510: var role = match[3];\n";
5511: } elsif (($formname eq 'enrollstudent') || ($formname eq 'selfenroll')) {
5512: $checkincluded = 'formname.name == "'.$formname.'"';
5513: if ($checkauth) {
5514: $finish = "var authcheck = auth_check();\n".
5515: " if (authcheck == 'ok') {\n".
5516: " formname.submit();\n".
5517: " }\n";
5518: } else {
5519: $finish = 'formname.submit()';
5520: }
5521: $rolecode = "var match = str.split('_');
5522: var role = match[1];\n";
5523: } else {
5524: $checkincluded = 'formname.name == "'.$formname.'"';
5525: $finish = "seccheck = 'ok';";
5526: $rolecode = "var match = str.split('_');
5527: var role = match[1];\n";
5528: $setsection_js = "var seccheck = 'alert';";
5529: }
5530: my %alerts = &Apache::lonlocal::texthash(
5531: secd => 'Section designations do not apply to Course Coordinator roles.',
5532: sedn => 'Section designations do not apply to Coordinator roles.',
5533: accr => 'A course coordinator role will be added with access to all sections.',
5534: acor => 'A coordinator role will be added with access to all sections',
5535: inea => 'In each course, each user may only have one student role at a time.',
5536: inco => 'In each community, each user may only have one member role at a time.',
5537: youh => 'You had selected',
5538: secs => 'sections.',
5539: plmo => 'Please modify your selections so they include no more than one section.',
5540: mayn => 'may not be used as the name for a section, as it is a reserved word.',
5541: plch => 'Please choose a different section name.',
5542: mnot => 'may not be used as a section name, as it is the name of a course group.',
5543: secn => 'Section names and group names must be distinct. Please choose a different section name.',
5544: nonw => 'Section names may only contain letters or numbers.',
5545: );
5546: &js_escape(\%alerts);
5547: $setsection_js .= <<"ENDSECCODE";
5548:
5549: function setSections(formname,crstype) {
5550: var re1 = /^currsec_/;
5551: var re2 =/\\W/;
5552: var trimleading = /^\\s+/;
5553: var trimtrailing = /\\s+\$/;
5554: var groups = new Array($groupslist);
5555: for (var i=0;i<formname.elements.length;i++) {
5556: var str = formname.elements[i].name;
5557: if (typeof(str) === "undefined") {
5558: continue;
5559: }
5560: var checkcurr = str.match(re1);
5561: if (checkcurr != null) {
5562: var num = i;
5563: $rolecode
5564: if ($checkincluded) {
5565: if (role == 'cc' || role == 'co') {
5566: if (role == 'cc') {
5567: alert("$alerts{'secd'}\\n$alerts{'accr'}");
5568: } else {
5569: alert("$alerts{'sedn'}\\n$alerts{'acor'}");
5570: }
5571: } else {
5572: var sections = '';
5573: var numsec = 0;
5574: var fromexisting = new Array();
5575: for (var j=0; j<formname.elements[num].length; j++) {
5576: if (formname.elements[num].options[j].selected == true ) {
5577: var addsec = formname.elements[num].options[j].value;
5578: if ((addsec != "") && (addsec != null)) {
5579: fromexisting.push(addsec);
5580: if (numsec == 0) {
5581: sections = addsec;
5582: } else {
5583: sections = sections + "," + addsec;
5584: }
5585: numsec ++;
5586: }
5587: }
5588: }
5589: var newsecs = formname.elements[num+1].value;
5590: var validsecs = new Array();
5591: var validsecstr = '';
5592: var badsecs = new Array();
5593: if (newsecs != null && newsecs != "") {
5594: var numsplit;
5595: if (newsecs.indexOf(',') == -1) {
5596: numsplit = new Array(newsecs);
5597: } else {
5598: numsplit = newsecs.split(/,/g);
5599: }
5600: for (var m=0; m<numsplit.length; m++) {
5601: var newsec = numsplit[m];
5602: newsec = newsec.replace(trimleading,'');
5603: newsec = newsec.replace(trimtrailing,'');
5604: if (re2.test(newsec) == true) {
5605: badsecs.push(newsec);
5606: } else {
5607: if (newsec != '') {
5608: var isnew = 1;
5609: if (fromexisting != null) {
5610: for (var n=0; n<fromexisting.length; n++) {
5611: if (newsec == fromexisting[n]) {
5612: isnew = 0;
5613: }
5614: }
5615: }
5616: if (isnew == 1) {
5617: validsecs.push(newsec);
5618: }
5619: }
5620: }
5621: }
5622: if (badsecs.length > 0) {
5623: alert("$alerts{'nonw'}\\n$alerts{'plch'}");
5624: return;
5625: }
5626: numsec = numsec + validsecs.length;
5627: }
5628: if ((role == 'st') && (numsec > 1)) {
5629: if (crstype == 'Community') {
5630: alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}");
5631: } else {
5632: alert("$alerts{'inco'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}");
5633: }
5634: return;
5635: } else {
5636: if (validsecs != null) {
5637: for (var j=0; j<validsecs.length; j++) {
5638: if (validsecstr == '' || validsecstr == null) {
5639: validsecstr = validsecs[j];
5640: } else {
5641: validsecstr += ','+validsecs[j];
5642: }
5643: if ((validsecs[j] == 'all') ||
5644: (validsecs[j] == 'none')) {
5645: alert("'"+validsecs[j]+"' $alerts{'mayn'}\\n$alerts{'plch'}");
5646: return;
5647: }
5648: for (var k=0; k<groups.length; k++) {
5649: if (validsecs[j] == groups[k]) {
5650: alert("'"+validsecs[j]+"' $alerts{'mnot'}\\n$alerts{'secn'}");
5651: return;
5652: }
5653: }
5654: }
5655: }
5656: }
5657: if ((validsecstr != '') && (validsecstr != null)) {
5658: if ((sections == '') || (sections == null)) {
5659: sections = validsecstr;
5660: } else {
5661: sections = sections + "," + validsecstr;
5662: }
5663: }
5664: formname.elements[num+2].value = sections;
5665: }
5666: }
5667: }
5668: }
5669: $finish
5670: }
5671: ENDSECCODE
5672: return $setsection_js;
5673: }
5674:
5675: sub can_create_user {
5676: my ($dom,$context,$usertype) = @_;
5677: my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
5678: my $cancreate = 1;
5679: if (&Apache::lonnet::allowed('mau',$dom)) {
5680: return $cancreate;
5681: } elsif ($context eq 'domain') {
5682: $cancreate = 0;
5683: return $cancreate;
5684: }
5685: if (ref($domconf{'usercreation'}) eq 'HASH') {
5686: if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') {
5687: if ($context eq 'course' || $context eq 'author' || $context eq 'requestcrs') {
5688: my $creation = $domconf{'usercreation'}{'cancreate'}{$context};
5689: if ($creation eq 'none') {
5690: $cancreate = 0;
5691: } elsif ($creation ne 'any') {
5692: if (defined($usertype)) {
5693: if ($creation ne $usertype) {
5694: $cancreate = 0;
5695: }
5696: }
5697: }
5698: }
5699: }
5700: }
5701: return $cancreate;
5702: }
5703:
5704: sub can_modify_userinfo {
5705: my ($context,$dom,$fields,$userroles) = @_;
5706: my %domconfig =
5707: &Apache::lonnet::get_dom('configuration',['usermodification'],
5708: $dom);
5709: my %canmodify;
5710: if (ref($fields) eq 'ARRAY') {
5711: foreach my $field (@{$fields}) {
5712: $canmodify{$field} = 0;
5713: if (&Apache::lonnet::allowed('mau',$dom)) {
5714: $canmodify{$field} = 1;
5715: } else {
5716: if (ref($domconfig{'usermodification'}) eq 'HASH') {
5717: if (ref($domconfig{'usermodification'}{$context}) eq 'HASH') {
5718: if (ref($userroles) eq 'ARRAY') {
5719: foreach my $role (@{$userroles}) {
5720: my $testrole;
5721: if ($context eq 'selfcreate') {
5722: $testrole = $role;
5723: } else {
5724: if ($role =~ /^cr\//) {
5725: $testrole = 'cr';
5726: } else {
5727: $testrole = $role;
5728: }
5729: }
5730: if (ref($domconfig{'usermodification'}{$context}{$testrole}) eq 'HASH') {
5731: if ($domconfig{'usermodification'}{$context}{$testrole}{$field}) {
5732: $canmodify{$field} = 1;
5733: last;
5734: }
5735: }
5736: }
5737: } else {
5738: foreach my $key (keys(%{$domconfig{'usermodification'}{$context}})) {
5739: if (ref($domconfig{'usermodification'}{$context}{$key}) eq 'HASH') {
5740: if ($domconfig{'usermodification'}{$context}{$key}{$field}) {
5741: $canmodify{$field} = 1;
5742: last;
5743: }
5744: }
5745: }
5746: }
5747: }
5748: } elsif ($context eq 'course') {
5749: if (ref($userroles) eq 'ARRAY') {
5750: if (grep(/^st$/,@{$userroles})) {
5751: $canmodify{$field} = 1;
5752: }
5753: } else {
5754: $canmodify{$field} = 1;
5755: }
5756: }
5757: }
5758: }
5759: }
5760: return %canmodify;
5761: }
5762:
5763: sub check_usertype {
5764: my ($dom,$uname,$rules,$curr_rules,$got_rules) = @_;
5765: my $usertype;
5766: if ((ref($got_rules) eq 'HASH') && (ref($curr_rules) eq 'HASH')) {
5767: if (!$got_rules->{$dom}) {
5768: my %domconfig = &Apache::lonnet::get_dom('configuration',
5769: ['usercreation'],$dom);
5770: if (ref($domconfig{'usercreation'}) eq 'HASH') {
5771: foreach my $item ('username','id') {
5772: if (ref($domconfig{'usercreation'}{$item.'_rule'}) eq 'ARRAY') {
5773: $curr_rules->{$dom}{$item} =
5774: $domconfig{'usercreation'}{$item.'_rule'};
5775: }
5776: }
5777: }
5778: $got_rules->{$dom} = 1;
5779: }
5780: if (ref($rules) eq 'HASH') {
5781: my @user_rules;
5782: if (ref($curr_rules->{$dom}{'username'}) eq 'ARRAY') {
5783: foreach my $rule (keys(%{$rules})) {
5784: if (grep(/^\Q$rule\E/,@{$curr_rules->{$dom}{'username'}})) {
5785: push(@user_rules,$rule);
5786: }
5787: }
5788: }
5789: if (@user_rules > 0) {
5790: my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
5791: if (keys(%rule_check) > 0) {
5792: $usertype = 'unofficial';
5793: foreach my $item (keys(%rule_check)) {
5794: if ($rule_check{$item}) {
5795: $usertype = 'official';
5796: last;
5797: }
5798: }
5799: }
5800: }
5801: }
5802: }
5803: return $usertype;
5804: }
5805:
5806: sub roles_by_context {
5807: my ($context,$custom,$crstype) = @_;
5808: my @allroles;
5809: if ($context eq 'course') {
5810: @allroles = ('st');
5811: if ($env{'request.role'} =~ m{^dc\./}) {
5812: push(@allroles,'ad');
5813: }
5814: push(@allroles,('ta','ep','in'));
5815: if ($crstype eq 'Community') {
5816: push(@allroles,'co');
5817: } else {
5818: push(@allroles,'cc');
5819: }
5820: if ($custom) {
5821: push(@allroles,'cr');
5822: }
5823: } elsif ($context eq 'author') {
5824: @allroles = ('ca','aa');
5825: } elsif ($context eq 'domain') {
5826: @allroles = ('li','ad','dg','dh','sc','au','dc');
5827: }
5828: return @allroles;
5829: }
5830:
5831: sub get_permission {
5832: my ($context,$crstype) = @_;
5833: my %permission;
5834: if ($context eq 'course') {
5835: my $custom = 1;
5836: my @allroles = &roles_by_context($context,$custom,$crstype);
5837: foreach my $role (@allroles) {
5838: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
5839: $permission{'cusr'} = 1;
5840: last;
5841: }
5842: }
5843: if (&Apache::lonnet::allowed('ccr',$env{'request.course.id'})) {
5844: $permission{'custom'} = 1;
5845: }
5846: if (&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) {
5847: $permission{'view'} = 1;
5848: }
5849: if (!$permission{'view'}) {
5850: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
5851: $permission{'view'} = &Apache::lonnet::allowed('vcl',$scope);
5852: if ($permission{'view'}) {
5853: $permission{'view_section'} = $env{'request.course.sec'};
5854: }
5855: }
5856: if (!$permission{'cusr'}) {
5857: if ($env{'request.course.sec'} ne '') {
5858: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
5859: $permission{'cusr'} = (&Apache::lonnet::allowed('cst',$scope));
5860: if ($permission{'cusr'}) {
5861: $permission{'cusr_section'} = $env{'request.course.sec'};
5862: }
5863: }
5864: }
5865: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
5866: $permission{'grp_manage'} = 1;
5867: }
5868: if ($permission{'cusr'}) {
5869: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
5870: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
5871: my %coursehash = (
5872: 'internal.selfenrollmgrdc' => $env{'course.'.$env{'request.course.id'}.'.internal.selfenrollmgrdc'},
5873: 'internal.selfenrollmgrcc' => $env{'course.'.$env{'request.course.id'}.'.internal.selfenrollmgrcc'},
5874: 'internal.coursecode' => $env{'course.'.$env{'request.course.id'}.'.internal.coursecode'},
5875: 'internal.textbook' =>$env{'course.'.$env{'request.course.id'}.'.internal.textbook'},
5876: );
5877: my ($managed_by_cc,$managed_by_dc) = &selfenrollment_administration($cdom,$cnum,$crstype,\%coursehash);
5878: if (ref($managed_by_cc) eq 'ARRAY') {
5879: if (@{$managed_by_cc}) {
5880: $permission{'selfenrolladmin'} = 1;
5881: }
5882: }
5883: }
5884: } elsif ($context eq 'author') {
5885: $permission{'cusr'} = &authorpriv($env{'user.name'},$env{'request.role.domain'});
5886: $permission{'view'} = $permission{'cusr'};
5887: } else {
5888: my @allroles = &roles_by_context($context);
5889: foreach my $role (@allroles) {
5890: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
5891: $permission{'cusr'} = 1;
5892: last;
5893: }
5894: }
5895: if (!$permission{'cusr'}) {
5896: if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) {
5897: $permission{'cusr'} = 1;
5898: }
5899: }
5900: if (&Apache::lonnet::allowed('ccr',$env{'request.role.domain'})) {
5901: $permission{'custom'} = 1;
5902: }
5903: if (&Apache::lonnet::allowed('vac',$env{'request.role.domain'})) {
5904: $permission{'activity'} = 1;
5905: }
5906: if (&Apache::lonnet::allowed('vur',$env{'request.role.domain'})) {
5907: $permission{'view'} = 1;
5908: }
5909: }
5910: my $allowed = 0;
5911: foreach my $perm (values(%permission)) {
5912: if ($perm) { $allowed=1; last; }
5913: }
5914: return (\%permission,$allowed);
5915: }
5916:
5917: # ==================================================== Figure out author access
5918:
5919: sub authorpriv {
5920: my ($auname,$audom)=@_;
5921: unless ((&Apache::lonnet::allowed('cca',$audom.'/'.$auname))
5922: || (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } return 1;
5923: }
5924:
5925: sub roles_on_upload {
5926: my ($context,$setting,$crstype,%customroles) = @_;
5927: my (@possible_roles,@permitted_roles);
5928: @possible_roles = &curr_role_permissions($context,$setting,1,$crstype);
5929: foreach my $role (@possible_roles) {
5930: if ($role eq 'cr') {
5931: push(@permitted_roles,keys(%customroles));
5932: } else {
5933: push(@permitted_roles,$role);
5934: }
5935: }
5936: return @permitted_roles;
5937: }
5938:
5939: sub get_course_identity {
5940: my ($cid) = @_;
5941: my ($cnum,$cdom,$cdesc);
5942: if ($cid eq '') {
5943: $cid = $env{'request.course.id'}
5944: }
5945: if ($cid ne '') {
5946: $cnum = $env{'course.'.$cid.'.num'};
5947: $cdom = $env{'course.'.$cid.'.domain'};
5948: $cdesc = $env{'course.'.$cid.'.description'};
5949: if ($cnum eq '' || $cdom eq '') {
5950: my %coursehash =
5951: &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
5952: $cdom = $coursehash{'domain'};
5953: $cnum = $coursehash{'num'};
5954: $cdesc = $coursehash{'description'};
5955: }
5956: }
5957: return ($cnum,$cdom,$cdesc);
5958: }
5959:
5960: sub dc_setcourse_js {
5961: my ($formname,$mode,$context,$showcredits) = @_;
5962: my ($dc_setcourse_code,$authen_check);
5963: my $cctext = &Apache::lonnet::plaintext('cc');
5964: my $cotext = &Apache::lonnet::plaintext('co');
5965: my %alerts = §ioncheck_alerts();
5966: my $role = 'role';
5967: if ($mode eq 'upload') {
5968: $role = 'courserole';
5969: } else {
5970: $authen_check = &verify_authen($formname,$context);
5971: }
5972: $dc_setcourse_code = (<<"SCRIPTTOP");
5973: $authen_check
5974:
5975: function setCourse() {
5976: var course = document.$formname.dccourse.value;
5977: if (course != "") {
5978: if (document.$formname.dcdomain.value != document.$formname.origdom.value) {
5979: alert("$alerts{'curd'}");
5980: return;
5981: }
5982: var userrole = document.$formname.$role.options[document.$formname.$role.selectedIndex].value
5983: var section="";
5984: var numsections = 0;
5985: var newsecs = new Array();
5986: for (var i=0; i<document.$formname.currsec.length; i++) {
5987: if (document.$formname.currsec.options[i].selected == true ) {
5988: if (document.$formname.currsec.options[i].value != "" && document.$formname.currsec.options[i].value != null) {
5989: if (numsections == 0) {
5990: section = document.$formname.currsec.options[i].value
5991: numsections = 1;
5992: }
5993: else {
5994: section = section + "," + document.$formname.currsec.options[i].value
5995: numsections ++;
5996: }
5997: }
5998: }
5999: }
6000: if (document.$formname.newsec.value != "" && document.$formname.newsec.value != null) {
6001: if (numsections == 0) {
6002: section = document.$formname.newsec.value
6003: }
6004: else {
6005: section = section + "," + document.$formname.newsec.value
6006: }
6007: newsecs = document.$formname.newsec.value.split(/,/g);
6008: numsections = numsections + newsecs.length;
6009: }
6010: if ((userrole == 'st') && (numsections > 1)) {
6011: if (document.$formname.crstype.value == 'Community') {
6012: alert("$alerts{'inco'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
6013: } else {
6014: alert("$alerts{'inea'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
6015: }
6016: return;
6017: }
6018: for (var j=0; j<newsecs.length; j++) {
6019: if ((newsecs[j] == 'all') || (newsecs[j] == 'none')) {
6020: alert("'"+newsecs[j]+"' $alerts{'mayn'}.\\n$alerts{'plsc'}.");
6021: return;
6022: }
6023: if (document.$formname.groups.value != '') {
6024: var groups = document.$formname.groups.value.split(/,/g);
6025: for (var k=0; k<groups.length; k++) {
6026: if (newsecs[j] == groups[k]) {
6027: if (document.$formname.crstype.value == 'Community') {
6028: alert("'"+newsecs[j]+"' $alerts{'mayc'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
6029: } else {
6030: alert("'"+newsecs[j]+"' $alerts{'mayt'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
6031: }
6032: return;
6033: }
6034: }
6035: }
6036: }
6037: if ((userrole == 'cc') && (numsections > 0)) {
6038: alert("$alerts{'secd'} $cctext $alerts{'role'}.\\n$alerts{'accr'}.");
6039: section = "";
6040: }
6041: if ((userrole == 'co') && (numsections > 0)) {
6042: alert("$alerts{'secd'} $cotext $alerts{'role'}.\\n$alerts{'accr'}.");
6043: section = "";
6044: }
6045: SCRIPTTOP
6046: if ($mode ne 'upload') {
6047: $dc_setcourse_code .= (<<"SCRIPTMID");
6048: var coursename = "_$env{'request.role.domain'}"+"_"+course+"_"+userrole
6049: var numcourse = getIndex(document.$formname.dccourse);
6050: if (numcourse == "-1") {
6051: if (document.$formname.type == 'Community') {
6052: alert("$alerts{'thwc'}");
6053: } else {
6054: alert("$alerts{'thwa'}");
6055: }
6056: return;
6057: }
6058: else {
6059: document.$formname.elements[numcourse].name = "act"+coursename;
6060: var numnewsec = getIndex(document.$formname.newsec);
6061: if (numnewsec != "-1") {
6062: document.$formname.elements[numnewsec].name = "sec"+coursename;
6063: document.$formname.elements[numnewsec].value = section;
6064: }
6065: var numstart = getIndex(document.$formname.start);
6066: if (numstart != "-1") {
6067: document.$formname.elements[numstart].name = "start"+coursename;
6068: }
6069: var numend = getIndex(document.$formname.end);
6070: if (numend != "-1") {
6071: document.$formname.elements[numend].name = "end"+coursename
6072: }
6073: SCRIPTMID
6074: if ($showcredits) {
6075: $dc_setcourse_code .= <<ENDCRED;
6076: var numcredits = getIndex(document.$formname.credits);
6077: if (numcredits != "-1") {
6078: document.$formname.elements[numcredits].name = "credits"+coursename;
6079: }
6080: ENDCRED
6081: }
6082: $dc_setcourse_code .= <<ENDSCRIPT;
6083: }
6084: }
6085: var authcheck = auth_check();
6086: if (authcheck == 'ok') {
6087: document.$formname.submit();
6088: }
6089: }
6090: ENDSCRIPT
6091: } else {
6092: $dc_setcourse_code .= "
6093: document.$formname.sections.value = section;
6094: }
6095: return 'ok';
6096: }
6097: ";
6098: }
6099: $dc_setcourse_code .= (<<"ENDSCRIPT");
6100:
6101: function getIndex(caller) {
6102: for (var i=0;i<document.$formname.elements.length;i++) {
6103: if (document.$formname.elements[i] == caller) {
6104: return i;
6105: }
6106: }
6107: return -1;
6108: }
6109: ENDSCRIPT
6110: return $dc_setcourse_code;
6111: }
6112:
6113: sub verify_authen {
6114: my ($formname,$context) = @_;
6115: my %alerts = &authcheck_alerts();
6116: my $finish = "return 'ok';";
6117: if ($context eq 'author') {
6118: $finish = "document.$formname.submit();";
6119: }
6120: my $outcome = <<"ENDSCRIPT";
6121:
6122: function auth_check() {
6123: var logintype;
6124: if (document.$formname.login.length) {
6125: if (document.$formname.login.length > 0) {
6126: var loginpicked = 0;
6127: for (var i=0; i<document.$formname.login.length; i++) {
6128: if (document.$formname.login[i].checked == true) {
6129: loginpicked = 1;
6130: logintype = document.$formname.login[i].value;
6131: }
6132: }
6133: if (loginpicked == 0) {
6134: alert("$alerts{'authen'}");
6135: return;
6136: }
6137: }
6138: } else {
6139: logintype = document.$formname.login.value;
6140: }
6141: if (logintype == 'nochange') {
6142: return 'ok';
6143: }
6144: var argpicked = document.$formname.elements[logintype+'arg'].value;
6145: if ((argpicked == null) || (argpicked == '') || (typeof argpicked == 'undefined')) {
6146: var alertmsg = '';
6147: switch (logintype) {
6148: case 'krb':
6149: alertmsg = '$alerts{'krb'}';
6150: break;
6151: case 'int':
6152: alertmsg = '$alerts{'ipass'}';
6153: case 'fsys':
6154: alertmsg = '$alerts{'ipass'}';
6155: break;
6156: case 'loc':
6157: alertmsg = '';
6158: break;
6159: default:
6160: alertmsg = '';
6161: }
6162: if (alertmsg != '') {
6163: alert(alertmsg);
6164: return;
6165: }
6166: }
6167: $finish
6168: }
6169: ENDSCRIPT
6170: }
6171:
6172: sub sectioncheck_alerts {
6173: my %alerts = &Apache::lonlocal::texthash(
6174: curd => 'You must select a course or community in the current domain',
6175: inea => 'In each course, each user may only have one student role at a time',
6176: inco => 'In each community, each user may only have one member role at a time',
6177: youh => 'You had selected',
6178: sect => 'sections',
6179: plsm => 'Please modify your selections so they include no more than one section',
6180: mayn => 'may not be used as the name for a section, as it is a reserved word',
6181: plsc => 'Please choose a different section name',
6182: mayt => 'may not be used as the name for a section, as it is the name of a course group',
6183: mayc => 'may not be used as the name for a section, as it is the name of a community group',
6184: secn => 'Section names and group names must be distinct',
6185: secd => 'Section designations do not apply to ',
6186: role => 'roles',
6187: accr => 'role will be added with access to all sections',
6188: thwa => 'There was a problem with your course selection',
6189: thwc => 'There was a problem with your community selection',
6190: );
6191: &js_escape(\%alerts);
6192: return %alerts;
6193: }
6194:
6195: sub authcheck_alerts {
6196: my %alerts =
6197: &Apache::lonlocal::texthash(
6198: authen => 'You must choose an authentication type.',
6199: krb => 'You need to specify the Kerberos domain.',
6200: ipass => 'You need to specify the initial password.',
6201: );
6202: &js_escape(\%alerts);
6203: return %alerts;
6204: }
6205:
6206: sub is_courseowner {
6207: my ($thiscourse,$courseowner) = @_;
6208: if ($courseowner eq '') {
6209: if ($env{'request.course.id'} eq $thiscourse) {
6210: $courseowner = $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'};
6211: }
6212: }
6213: if ($courseowner ne '') {
6214: if ($courseowner eq $env{'user.name'}.':'.$env{'user.domain'}) {
6215: return 1;
6216: }
6217: }
6218: return;
6219: }
6220:
6221: sub get_selfenroll_titles {
6222: my @row = ('types','registered','enroll_dates','access_dates','section',
6223: 'approval','limit');
6224: my %lt = &Apache::lonlocal::texthash (
6225: types => 'Users allowed to self-enroll',
6226: registered => 'Registration status (official courses)' ,
6227: enroll_dates => 'Dates self-enrollment available',
6228: access_dates => 'Access dates for self-enrolling users',
6229: section => "Self-enrolling users' section",
6230: approval => 'Processing of requests',
6231: limit => 'Enrollment limit',
6232: );
6233: return (\@row,\%lt);
6234: }
6235:
6236: sub selfenroll_default_descs {
6237: my %desc = (
6238: types => {
6239: dom => &mt('Course domain'),
6240: all => &mt('Any domain'),
6241: '' => &mt('None'),
6242: },
6243: limit => {
6244: none => &mt('No limit'),
6245: allstudents => &mt('Limit by total students'),
6246: selfenrolled => &mt('Limit by total self-enrolled'),
6247: },
6248: approval => {
6249: '0' => &mt('Processed automatically'),
6250: '1' => &mt('Queued for approval'),
6251: '2' => &mt('Queued, pending validation'),
6252: },
6253: registered => {
6254: 0 => 'No registration required',
6255: 1 => 'Registered students only',
6256: },
6257: );
6258: return %desc;
6259: }
6260:
6261: sub selfenroll_validation_types {
6262: my @items = ('url','fields','button','markup');
6263: my %names = &Apache::lonlocal::texthash (
6264: url => 'Web address of validation server/script',
6265: fields => 'Form fields to send to validator',
6266: button => 'Text for validation button',
6267: markup => 'Validation description (HTML)',
6268: );
6269: my @fields = ('username','domain','uniquecode','course','coursetype','description');
6270: return (\@items,\%names,\@fields);
6271: }
6272:
6273: sub get_extended_type {
6274: my ($cdom,$cnum,$crstype,$current) = @_;
6275: my $type = 'unofficial';
6276: my %settings;
6277: if (ref($current) eq 'HASH') {
6278: %settings = %{$current};
6279: } else {
6280: %settings = &Apache::lonnet::get('environment',['internal.coursecode','internal.textbook'],$cdom,$cnum);
6281: }
6282: if ($crstype eq 'Community') {
6283: $type = 'community';
6284: } elsif ($crstype eq 'Placement') {
6285: $type = 'placement';
6286: } elsif ($settings{'internal.coursecode'}) {
6287: $type = 'official';
6288: } elsif ($settings{'internal.textbook'}) {
6289: $type = 'textbook';
6290: }
6291: return $type;
6292: }
6293:
6294: sub selfenrollment_administration {
6295: my ($cdom,$cnum,$crstype,$coursehash) = @_;
6296: my %settings;
6297: if (ref($coursehash) eq 'HASH') {
6298: %settings = %{$coursehash};
6299: } else {
6300: %settings = &Apache::lonnet::get('environment',
6301: ['internal.selfenrollmgrdc','internal.selfenrollmgrcc',
6302: 'internal.coursecode','internal.textbook'],$cdom,$cnum);
6303: }
6304: my ($possconfigs) = &get_selfenroll_titles();
6305: my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
6306: my $selfenrolltype = &get_extended_type($cdom,$cnum,$crstype,\%settings);
6307:
6308: my (@in_course,@in_domain);
6309: if ($settings{'internal.selfenrollmgrcc'} ne '') {
6310: @in_course = split(/,/,$settings{'internal.selfenrollmgrcc'});
6311: my @diffs = &Apache::loncommon::compare_arrays($possconfigs,\@in_course);
6312: unless (@diffs) {
6313: return (\@in_course,\@in_domain);
6314: }
6315: }
6316: if ($settings{'internal.selfenrollmgrdc'} ne '') {
6317: my @in_domain = split(/,/,$settings{'internal.selfenrollmgrdc'});
6318: my @diffs = &Apache::loncommon::compare_arrays(\@in_domain,$possconfigs);
6319: unless (@diffs) {
6320: return (\@in_course,\@in_domain);
6321: }
6322: }
6323: my @combined = @in_course;
6324: push(@combined,@in_domain);
6325: my @diffs = &Apache::loncommon::compare_arrays(\@combined,$possconfigs);
6326: unless (@diffs) {
6327: return (\@in_course,\@in_domain);
6328: }
6329: if ($domdefaults{$selfenrolltype.'selfenrolladmdc'} eq '') {
6330: push(@in_course,@diffs);
6331: } else {
6332: my @defaultdc = split(/,/,$domdefaults{$selfenrolltype.'selfenrolladmdc'});
6333: foreach my $item (@diffs) {
6334: if (grep(/^\Q$item\E$/,@defaultdc)) {
6335: push(@in_domain,$item);
6336: } else {
6337: push(@in_course,$item);
6338: }
6339: }
6340: }
6341: return (\@in_course,\@in_domain);
6342: }
6343:
6344: sub custom_role_header {
6345: my ($context,$crstype,$templaterolerefs,$prefix) = @_;
6346: my %lt = &Apache::lonlocal::texthash(
6347: sele => 'Select a Template',
6348: );
6349: my ($context_code,$button_code);
6350: if ($context eq 'domain') {
6351: $context_code = &custom_coursetype_switch($crstype,$prefix);
6352: }
6353: if (ref($templaterolerefs) eq 'ARRAY') {
6354: foreach my $role (@{$templaterolerefs}) {
6355: my $display = 'inline';
6356: if (($context eq 'domain') && ($role eq 'co')) {
6357: $display = 'none';
6358: }
6359: $button_code .= &make_button_code($role,$crstype,$display,$prefix).' ';
6360: }
6361: }
6362: return <<"END";
6363: <div class="LC_left_float">
6364: <fieldset>
6365: <legend>$lt{'sele'}</legend>
6366: $button_code
6367: </fieldset></div>
6368: $context_code
6369: <br clear="all" />
6370: END
6371: }
6372:
6373: sub custom_coursetype_switch {
6374: my ($crstype,$prefix) = @_;
6375: my ($checkedcourse,$checkedcommunity);
6376: if ($crstype eq 'Community') {
6377: $checkedcommunity = ' checked="checked"';
6378: } else {
6379: $checkedcourse = ' checked="checked"';
6380: }
6381: my %lt = &Apache::lonlocal::texthash(
6382: cont => 'Context',
6383: cour => 'Course',
6384: comm => 'Community',
6385: );
6386: return <<"END";
6387: <div class="LC_left_float">
6388: <fieldset>
6389: <legend>$lt{'cont'}</legend>
6390: <label>
6391: <input type="radio" name="${prefix}_custrolecrstype" value="Course"$checkedcourse onclick="javascript:customSwitchType('$prefix');" />
6392: $lt{'cour'}
6393: </label>
6394: <label>
6395: <input type="radio" name="${prefix}_custrolecrstype" value="Community"$checkedcommunity onclick="javascript:customSwitchType('$prefix');" />
6396: $lt{'comm'}
6397: </label>
6398: </fieldset>
6399: </div>
6400: END
6401: }
6402:
6403: sub custom_role_table {
6404: my ($crstype,$full,$levels,$levelscurrent,$prefix) = @_;
6405: return unless ((ref($full) eq 'HASH') && (ref($levels) eq 'HASH') &&
6406: (ref($levelscurrent) eq 'HASH'));
6407: my %lt=&Apache::lonlocal::texthash (
6408: 'prv' => "Privilege",
6409: 'crl' => "Course Level",
6410: 'dml' => "Domain Level",
6411: 'ssl' => "System Level");
6412: my %cr = (
6413: course => '_c',
6414: domain => '_d',
6415: system => '_s',
6416: );
6417:
6418: my $output=&Apache::loncommon::start_data_table().
6419: &Apache::loncommon::start_data_table_header_row().
6420: '<th>'.$lt{'prv'}.'</th><th>'.$lt{'crl'}.'</th><th>'.$lt{'dml'}.
6421: '</th><th>'.$lt{'ssl'}.'</th>'.
6422: &Apache::loncommon::end_data_table_header_row();
6423: foreach my $priv (sort(keys(%{$full}))) {
6424: my $privtext = &Apache::lonnet::plaintext($priv,$crstype);
6425: $output .= &Apache::loncommon::start_data_table_row().
6426: '<td><span id="'.$prefix.$priv.'">'.$privtext.'</span></td>';
6427: foreach my $type ('course','domain','system') {
6428: if (($type eq 'system') && ($priv eq 'bre') && ($crstype eq 'Community')) {
6429: $output .= '<td> </td>';
6430: } else {
6431: $output .= '<td>'.
6432: ($levels->{$type}{$priv}?'<input type="checkbox" id="'.$prefix.$priv.$cr{$type}.'"'.
6433: ' name="'.$prefix.$priv.$cr{$type}.'"'.
6434: ($levelscurrent->{$type}{$priv}?' checked="checked"':'').' />':' ').
6435: '</td>';
6436: }
6437: }
6438: $output .= &Apache::loncommon::end_data_table_row();
6439: }
6440: $output .= &Apache::loncommon::end_data_table();
6441: return $output;
6442: }
6443:
6444: sub custom_role_privs {
6445: my ($privs,$full,$levels,$levelscurrent)= @_;
6446: return unless ((ref($privs) eq 'HASH') && (ref($full) eq 'HASH') &&
6447: (ref($levels) eq 'HASH') && (ref($levelscurrent) eq 'HASH'));
6448: my %cr = (
6449: course => 'cr:c',
6450: domain => 'cr:d',
6451: system => 'cr:s',
6452: );
6453: foreach my $type ('course','domain','system') {
6454: foreach my $item (split(/\:/,$Apache::lonnet::pr{$cr{$type}})) {
6455: my ($priv,$restrict)=split(/\&/,$item);
6456: if (!$restrict) { $restrict='F'; }
6457: $levels->{$type}->{$priv}=$restrict;
6458: if ($privs->{$type}=~/\:$priv/) {
6459: $levelscurrent->{$type}->{$priv}=1;
6460: }
6461: $full->{$priv}=1;
6462: }
6463: }
6464: return;
6465: }
6466:
6467: sub custom_template_roles {
6468: my ($context,$crstype) = @_;
6469: my @template_roles = ("in","ta","ep");
6470: if (($context eq 'domain') || ($context eq 'domprefs')) {
6471: push(@template_roles,"ad");
6472: }
6473: push(@template_roles,"st");
6474: if ($context eq 'domain') {
6475: unshift(@template_roles,('co','cc'));
6476: } else {
6477: if ($crstype eq 'Community') {
6478: unshift(@template_roles,'co');
6479: } else {
6480: unshift(@template_roles,'cc');
6481: }
6482: }
6483: return @template_roles;
6484: }
6485:
6486: sub custom_roledefs_js {
6487: my ($context,$crstype,$formname,$full,$templaterolesref,$jsback) = @_;
6488: my $button_code = "\n";
6489: my $head_script = "\n";
6490: my (%roletitlestr,$rolenamestr);
6491: my %role_titles = (
6492: Course => [],
6493: Community => [],
6494: );
6495: $head_script .= '<script type="text/javascript">'."\n"
6496: .'// <![CDATA['."\n";
6497: if (ref($templaterolesref) eq 'ARRAY') {
6498: if ($context eq 'domain') {
6499: $rolenamestr = join("','",@{$templaterolesref});
6500: }
6501: foreach my $role (@{$templaterolesref}) {
6502: $head_script .= &make_script_template($role,$crstype,$formname);
6503: if ($context eq 'domain') {
6504: foreach my $type ('Course','Community') {
6505: push(@{$role_titles{$type}},&Apache::lonnet::plaintext($role,$type));
6506: }
6507: }
6508: }
6509: }
6510: if ($context eq 'domain') {
6511: foreach my $type ('Course','Community') {
6512: $roletitlestr{$type} = join("','",@{$role_titles{$type}});
6513: }
6514: my %pt = (
6515: Community => {
6516: cst => &mt('Grant/revoke role of Member'),
6517: mdc => &mt('Edit community contents'),
6518: pch => &mt('Post discussion on community resources'),
6519: pfo => &mt('Print for other users and entire community'),
6520: },
6521: Course => {
6522: cst => &mt('Grant/revoke role of Student'),
6523: mdc => &mt('Edit course contents'),
6524: pch => &mt('Post discussion on course resources'),
6525: pfo => &mt('Print for other users and entire course'),
6526: },
6527: );
6528: $head_script .= <<"ENDJS";
6529: function customSwitchType(prefix) {
6530: var privnames = new Array('cst','mdc','pch','pfo');
6531: var privtxtcrs = new Array('$pt{Course}{cst}','$pt{Course}{mdc}','$pt{Course}{pch}','$pt{Course}{pfo}');
6532: var privtxtcom = new Array('$pt{Community}{cst}','$pt{Community}{mdc}','$pt{Community}{pch}','$pt{Community}{pfo}');
6533: var rolenames = new Array('$rolenamestr');
6534: var rolescrs = new Array('$roletitlestr{Course}');
6535: var rolescom = new Array('$roletitlestr{Community}');
6536: var radio = prefix+'_custrolecrstype';
6537: if (document.$formname.elements[radio].length > 1) {
6538: for (var i=0; i<document.$formname.elements[radio].length; i++) {
6539: if (document.$formname.elements[radio][i].checked) {
6540: if ((document.getElementById(prefix+'bre_s')) && (document.getElementById(prefix+'bro_s'))) {
6541: if (document.$formname.elements[radio][i].value == 'Community') {
6542: if (document.getElementById(prefix+'bre_s').checked) {
6543: document.getElementById(prefix+'bro_s').checked = true;
6544: document.getElementById(prefix+'bre_s').checked = false;
6545:
6546: }
6547: document.getElementById(prefix+'bre_s').style.visibility = 'hidden';
6548: } else {
6549: document.getElementById(prefix+'bre_s').style.visibility = 'visible';
6550: if (document.getElementById(prefix+'bro_s').checked) {
6551: document.getElementById(prefix+'bre_s').checked = true;
6552: document.getElementById(prefix+'bro_s').checked = false;
6553: }
6554: }
6555: }
6556: for (var j=0; j<privnames.length; j++) {
6557: if (document.getElementById(prefix+privnames[j])) {
6558: if (document.getElementById(prefix+privnames[j])) {
6559: if (document.$formname.elements[radio][i].value == 'Course') {
6560: document.getElementById(prefix+privnames[j]).innerHTML = privtxtcrs[j];
6561: } else {
6562: document.getElementById(prefix+privnames[j]).innerHTML = privtxtcom[j];
6563: }
6564: }
6565: }
6566: }
6567: for (var j=0; j<rolenames.length; j++) {
6568: if (document.getElementById(prefix+rolenames[j])) {
6569: if (document.getElementById(prefix+rolenames[j])) {
6570: if (document.$formname.elements[radio][i].value == 'Course') {
6571: document.getElementById(prefix+rolenames[j]).value = rolescrs[j];
6572: if (rolenames[j] == 'cc') {
6573: document.getElementById(prefix+rolenames[j]).style.display = 'inline';
6574: }
6575: if (rolenames[j] == 'co') {
6576: document.getElementById(prefix+rolenames[j]).style.display = 'none';
6577: }
6578: } else {
6579: document.getElementById(prefix+rolenames[j]).value = rolescom[j];
6580: if (rolenames[j] == 'cc') {
6581: document.getElementById(prefix+rolenames[j]).style.display = 'none';
6582: }
6583: if (rolenames[j] == 'co') {
6584: document.getElementById(prefix+rolenames[j]).style.display = 'inline';
6585: }
6586: }
6587: }
6588: }
6589: }
6590: }
6591: }
6592: }
6593: return;
6594: }
6595: ENDJS
6596: }
6597: $head_script .= "\n".$jsback."\n"
6598: .'// ]]>'."\n"
6599: .'</script>'."\n";
6600: return $head_script;
6601: }
6602:
6603: # --------------------------------------------------------
6604: sub make_script_template {
6605: my ($role,$crstype,$formname) = @_;
6606: my $return_script = 'function set_'.$role.'(prefix) {'."\n";
6607: my (%full_by_level,%role_priv);
6608: foreach my $level ('c','d','s') {
6609: foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) {
6610: next if (($level eq 's') && ($crstype eq 'Community') && ($item eq 'bre&S'));
6611: my ($priv,$restrict)=split(/\&/,$item);
6612: $full_by_level{$level}{$priv}=1;
6613: }
6614: $role_priv{$level} = {};
6615: my @temp = split(/:/,$Apache::lonnet::pr{$role.':'.$level});
6616: foreach my $priv (@temp) {
6617: my ($priv_item, $dummy) = split(/\&/,$priv);
6618: $role_priv{$level}{$priv_item} = 1;
6619: }
6620: }
6621: my %to_check = (
6622: c => ['c','d','s'],
6623: d => ['d','s'],
6624: s => ['s'],
6625: );
6626: foreach my $level ('c','d','s') {
6627: if (ref($full_by_level{$level}) eq 'HASH') {
6628: foreach my $priv (keys(%{$full_by_level{$level}})) {
6629: my $value = 'false';
6630: if (ref($to_check{$level}) eq 'ARRAY') {
6631: foreach my $lett (@{$to_check{$level}}) {
6632: if (exists($role_priv{$lett}{$priv})) {
6633: $value = 'true';
6634: last;
6635: }
6636: }
6637: $return_script .= "document.$formname.elements[prefix+'".$priv."_".$level."'].checked = $value;\n";
6638: }
6639: }
6640: }
6641: }
6642: $return_script .= '}'."\n";
6643: return ($return_script);
6644: }
6645: # ----------------------------------------------------------
6646: sub make_button_code {
6647: my ($role,$crstype,$display,$prefix) = @_;
6648: my $label = &Apache::lonnet::plaintext($role,$crstype);
6649: my $button_code = '<input type="button" onclick="set_'.$role."('$prefix'".')" '.
6650: 'id="'.$prefix.$role.'" value="'.$label.'" '.
6651: 'style="display:'.$display.'" />';
6652: return ($button_code);
6653: }
6654:
6655: sub custom_role_update {
6656: my ($rolename,$prefix) = @_;
6657: # ------------------------------------------------------- What can be assigned?
6658: my %privs = (
6659: c => '',
6660: d => '',
6661: s => '',
6662: );
6663: foreach my $level (keys(%privs)) {
6664: foreach my $item (split(/\:/,$Apache::lonnet::pr{'cr:'.$level})) {
6665: my ($priv,$restrict)=split(/\&/,$item);
6666: if (!$restrict) { $restrict=''; }
6667: if ($env{'form.'.$prefix.$priv.'_'.$level}) {
6668: $privs{$level} .=':'.$item;
6669: }
6670: }
6671: }
6672: return %privs;
6673: }
6674:
6675: 1;
6676:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>