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