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