--- loncom/interface/domainprefs.pm 2008/02/15 17:02:31 1.42 +++ loncom/interface/domainprefs.pm 2008/05/15 01:56:44 1.51 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.42 2008/02/15 17:02:31 raeburn Exp $ +# $Id: domainprefs.pm,v 1.51 2008/05/15 01:56:44 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,9 +36,11 @@ use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonlocal; -use LONCAPA(); +use Apache::lonmsg(); +use LONCAPA; use LONCAPA::Enrollment; use File::Copy; +use Locale::Language; sub handler { my $r=shift; @@ -68,10 +70,12 @@ sub handler { my %domconfig = &Apache::lonnet::get_dom('configuration',['login','rolecolors', 'quotas','autoenroll','autoupdate','directorysrch', - 'usercreation','usermodification','contacts'],$dom); - my @prefs_order = ('rolecolors','login','quotas','autoenroll', + 'usercreation','usermodification','contacts','defaults', + 'scantron','coursecategories'],$dom); + my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','directorysrch','contacts', - 'usercreation','usermodification'); + 'usercreation','usermodification','scantron', + 'coursecategories'); my %prefs = ( 'rolecolors' => { text => 'Default color schemes', @@ -91,6 +95,12 @@ sub handler { header => [{col1 => 'Item', col2 => '',}], }, + 'defaults' => + { text => 'Default authentication/language', + help => '', + header => [{col1 => 'Setting', + col2 => 'Value'}], + }, 'quotas' => { text => 'Default quotas for user portfolios', help => 'Default_User_Quota', @@ -108,7 +118,7 @@ sub handler { help => 'Domain_Auto_Update', header => [{col1 => 'Setting', col2 => 'Value',}, - {col1 => 'User Population', + {col1 => 'User population', col2 => 'Updataeable user data'}], }, 'directorysrch' => @@ -127,12 +137,12 @@ sub handler { 'usercreation' => { text => 'User creation', help => 'Domain_User_Creation', - header => [{col1 => 'Format Rule Type', - col2 => 'Format Rules in force'}, + header => [{col1 => 'Format rule type', + col2 => 'Format rules in force'}, {col1 => 'User account creation', col2 => 'Usernames which may be created',}, {col1 => 'Context', - col2 => 'Assignable Authentication Types'}], + col2 => 'Assignable authentication types'}], }, 'usermodification' => { text => 'User modification', @@ -142,6 +152,20 @@ sub handler { {col1 => 'Target user has role', col2 => 'User information updateable in course context'}], }, + 'scantron' => + { text => 'Scantron format file', + help => 'Domain_Scantron_Formats', + header => [ {col1 => 'Item', + col2 => '', + }], + }, + 'coursecategories' => + { text => 'Cataloging of courses', + help => 'Domain_Course_Catalog', + header => [ {col1 => 'Categories', + col2 => '', + }], + } ); my @roles = ('student','coordinator','author','admin'); my @actions = &Apache::loncommon::get_env_multiple('form.actions'); @@ -300,9 +324,9 @@ sub handler { $r->print('

'. &mt('Display options').'

'."\n". '

'.&mt('Display using: ')."\n". - '  '. - ''. + '  

'); $r->print(&print_footer($r,$phase,'display','Go')); $r->print(''); @@ -333,6 +357,12 @@ sub process_changes { $output = &modify_usermodification($dom,%domconfig); } elsif ($action eq 'contacts') { $output = &modify_contacts($dom,%domconfig); + } elsif ($action eq 'defaults') { + $output = &modify_defaults($dom,$r); + } elsif ($action eq 'scantron') { + $output = &modify_scantron($r,$dom,$confname,%domconfig); + } elsif ($action eq 'coursecategories') { + $output = &modify_coursecategories($dom,%domconfig); } return $output; } @@ -340,7 +370,11 @@ sub process_changes { sub print_config_box { my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_; my $rowtotal = 0; - my $output = + my $output; + if ($action eq 'coursecategories') { + $output = &coursecategories_javascript($settings); + } + $output .= ''; } + my $colspan = ($action eq 'coursecategories')?' colspan="2"':''; $output .= ' - + '; - $rowtotal ++; + $rowtotal ++; if ($action eq 'login') { $output .= &print_login($dom,$confname,$phase,$settings,\$rowtotal); } elsif ($action eq 'quotas') { @@ -454,6 +489,12 @@ sub print_config_box { $output .= &print_directorysrch($dom,$settings,\$rowtotal); } elsif ($action eq 'contacts') { $output .= &print_contacts($dom,$settings,\$rowtotal); + } elsif ($action eq 'defaults') { + $output .= &print_defaults($dom,\$rowtotal); + } elsif ($action eq 'scantron') { + $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'coursecategories'){ + $output .= &print_coursecategories($dom,$item,$settings,\$rowtotal); } } $output .= ' @@ -474,7 +515,7 @@ function changePage(formname,newphase) { numchecked = 0; if (formname == document.pickactions) { if (formname.actions.length > 0) { - for (var i = 0; i 'on', - 'adminmail' => 'off', - ); - my @toggles = ('coursecatalog','adminmail'); + 'coursecatalog' => 'on', + 'adminmail' => 'off', + 'newuser' => 'off', + ); + my @toggles = ('coursecatalog','adminmail','newuser'); my (%checkedon,%checkedoff); foreach my $item (@toggles) { if ($defaultchecked{$item} eq 'on') { @@ -699,6 +741,7 @@ sub login_choices { &Apache::lonlocal::texthash ( coursecatalog => 'Display Course Catalog link?', adminmail => "Display Administrator's E-mail Address?", + newuser => "Link to create a user account", img => "Header", logo => "Main Logo", domlogo => "Domain Logo", @@ -1096,7 +1139,7 @@ ENDCOL sub print_quotas { my ($dom,$settings,$rowtotal) = @_; my $datatable; - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; my $css_class; if (ref($types) eq 'ARRAY') { @@ -1226,7 +1269,7 @@ sub print_autoupdate { ''; $$rowtotal += 2; } else { - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my @fields = ('lastname','firstname','middlename','gen', 'permanentemail','id'); my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); @@ -1286,7 +1329,7 @@ sub print_directorysrch { } } my ($searchtitles,$titleorder) = &sorted_searchtitles(); - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $numinrow = 4; my $cansrchrow = 0; @@ -1479,22 +1522,42 @@ sub print_usercreation { $rowcount ++; } } + my ($emailrules,$emailruleorder) = + &Apache::lonnet::inst_userrules($dom,'email'); + if (ref($emailrules) eq 'HASH') { + if (keys(%{$emailrules}) > 0) { + $datatable .= &user_formats_row('email',$settings,$emailrules, + $emailruleorder,$numinrow,$rowcount); + $$rowtotal ++; + $rowcount ++; + } + } if ($rowcount == 0) { $datatable .= ''; $$rowtotal ++; $rowcount ++; } } elsif ($position eq 'middle') { - my @creators = ('author','course'); + my @creators = ('author','course','selfcreate'); my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username'); my %lt = &usercreation_types(); my %checked; + my @selfcreate; if (ref($settings) eq 'HASH') { if (ref($settings->{'cancreate'}) eq 'HASH') { foreach my $item (@creators) { $checked{$item} = $settings->{'cancreate'}{$item}; } + if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') { + @selfcreate = @{$settings->{'cancreate'}{'selfcreate'}}; + } elsif ($settings->{'cancreate'}{'selfcreate'} ne '') { + if ($settings->{'cancreate'}{'selfcreate'} eq 'any') { + @selfcreate = ('email','login','sso'); + } elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') { + @selfcreate = ($settings->{'cancreate'}{'selfcreate'}); + } + } } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') { foreach my $item (@creators) { if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) { @@ -1506,8 +1569,10 @@ sub print_usercreation { my $rownum = 0; foreach my $item (@creators) { $rownum ++; - if ($checked{$item} eq '') { - $checked{$item} = 'any'; + if ($item ne 'selfcreate') { + if ($checked{$item} eq '') { + $checked{$item} = 'any'; + } } my $css_class; if ($rownum%2) { @@ -1518,20 +1583,33 @@ sub print_usercreation { $datatable .= ''. ''. @@ -1644,13 +1723,17 @@ sub usercreation_types { my %lt = &Apache::lonlocal::texthash ( author => 'When adding a co-author', course => 'When adding a user to a course', + selfcreate => 'User creates own account', any => 'Any', official => 'Institutional only ', unofficial => 'Non-institutional only', + email => 'Email address', + login => 'Institutional Login', + sso => 'SSO', none => 'None', ); return %lt; -} +} sub authtype_names { my %lt = &Apache::lonlocal::texthash( @@ -1697,6 +1780,479 @@ sub print_usermodification { return $datatable; } +sub print_defaults { + my ($dom,$rowtotal) = @_; + my @items = ('auth_def','auth_arg_def','lang_def'); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my $titles = &defaults_titles(); + my $rownum = 0; + my ($datatable,$css_class); + foreach my $item (@items) { + if ($rownum%2) { + $css_class = ''; + } else { + $css_class = ' class="LC_odd_row" '; + } + $datatable .= ''. + ''; + $rownum ++; + } + $$rowtotal += $rownum; + return $datatable; +} + +sub defaults_titles { + my %titles = &Apache::lonlocal::texthash ( + 'auth_def' => 'Default authentication type', + 'auth_arg_def' => 'Default authentication argument', + 'lang_def' => 'Default language', + ); + return (\%titles); +} + +sub print_scantronformat { + my ($r,$dom,$confname,$settings,$rowtotal) = @_; + my $itemcount = 1; + my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls); + my $switchserver = &check_switchserver($dom,$confname); + my %lt = &Apache::lonlocal::texthash ( + default => 'Default scantron format file error', + custom => 'Custom scantron format file error', + ); + my %scantronfiles = ( + default => 'default.tab', + custom => 'custom.tab', + ); + foreach my $key (keys(%scantronfiles)) { + $scantronurls{$key} = '/res/'.$dom.'/'.$confname.'/scantron/' + .$scantronfiles{$key}; + } + my @defaultinfo = &Apache::lonnet::stat_file($scantronurls{'default'}); + if ((!@defaultinfo) || ($defaultinfo[0] eq 'no_such_dir')) { + if (!$switchserver) { + my $servadm = $r->dir_config('lonAdmEMail'); + my ($configuserok,$author_ok) = &config_check($dom,$confname,$servadm); + if ($configuserok eq 'ok') { + if ($author_ok eq 'ok') { + my %legacyfile = ( + default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab', + custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab', + ); + my %md5chk; + foreach my $type (keys(%legacyfile)) { + $md5chk{$type} = split(/ /,`md5sum $legacyfile{$type}`); + chop($md5chk{$type}); + } + if ($md5chk{'default'} ne $md5chk{'custom'}) { + foreach my $type (keys(%legacyfile)) { + ($scantronurls{$type},$error{$type}) = + &legacy_scantronformat($r,$dom,$confname, + $type,$legacyfile{$type}, + $scantronurls{$type}, + $scantronfiles{$type}); + } + } else { + ($scantronurls{'default'},$error{'default'}) = + &legacy_scantronformat($r,$dom,$confname, + 'default',$legacyfile{'default'}, + $scantronurls{'default'}, + $scantronfiles{'default'}); + } + } + } + } else { + $error{'default'} = &mt("Unable to copy default scantron formatfile to domain's RES space: [_1]",$switchserver); + } + } + if (ref($settings) eq 'HASH') { + if ($settings->{'scantronformat'} eq "/res/$dom/$confname/scantron/custom.tab") { + my @info = &Apache::lonnet::stat_file($settings->{'scantronformat'}); + if ((!@info) || ($info[0] eq 'no_such_dir')) { + $scantronurl = ''; + } else { + $scantronurl = $settings->{'scantronformat'}; + } + $is_custom = 1; + } else { + $scantronurl = $scantronurls{'default'}; + } + } else { + $scantronurl = $scantronurls{'default'}; + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''; + if (!$is_custom) { + $datatable .= '' + .''; + $$rowtotal ++; + return $datatable; +} + +sub legacy_scantronformat { + my ($r,$dom,$confname,$file,$legacyfile,$newurl,$newfile) = @_; + my ($url,$error); + my @statinfo = &Apache::lonnet::stat_file($newurl); + if ((!@statinfo) || ($statinfo[0] eq 'no_such_dir')) { + (my $result,$url) = + &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron', + '','',$newfile); + if ($result ne 'ok') { + $error = &mt("An error occurred publishing the [_1] scantron format file in RES space. Error was: [_2].",$newfile,$result); + } + } + return ($url,$error); +} + +sub print_coursecategories { + my ($dom,$hdritem,$settings,$rowtotal) = @_; + my ($datatable,$css_class); + my $itemcount = 1; + if (ref($settings) eq 'HASH') { + my (@cats,@trails,%allitems,%idx,@jsarray); + &extract_categories($settings,\@cats,\@trails,\%allitems,\%idx,\@jsarray); + my $maxdepth = scalar(@cats); + my $colattrib = ''; + if ($maxdepth > 2) { + $colattrib = ' colspan="2" '; + } + my @path; + if (@cats > 0) { + if (ref($cats[0]) eq 'ARRAY') { + my $numtop = @{$cats[0]}; + my $maxnum = $numtop; + if ((!grep(/^instcode$/,@{$cats[0]})) || ($settings->{'instcode::0'} eq '')) { + $maxnum ++; + } + my $lastidx; + for (my $i=0; $i<$numtop; $i++) { + my $parent = $cats[0][$i]; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $item = &escape($parent).'::0'; + my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$item','$idx{$item}'".');"'; + $lastidx = $idx{$item}; + $datatable .= '' + .' ' + .''; + } else { + $datatable .= $parent + .' '; + } + my $depth = 1; + push(@path,$parent); + $datatable .= &build_category_rows($itemcount,\@cats,$depth,$parent,\@path,\%idx); + pop(@path); + $datatable .= ''; + $itemcount ++; + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','$lastidx'".');"'; + $datatable .= '' + .''."\n"; + $itemcount ++; + if ((!grep(/^instcode$/,@{$cats[0]})) || ($settings->{'instcode::0'} eq '')) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','$lastidx'".');"'; + $datatable .= '' + .''; + } + } + } else { + $datatable .= &initialize_categories($itemcount); + } + } else { + $datatable .= '' + .&initialize_categories($itemcount); + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub coursecategories_javascript { + my ($settings) = @_; + my ($output,$jstext); + if (ref($settings) eq 'HASH') { + my (@cats,@jsarray,%idx); + &gather_categories($settings,\@cats,\%idx,\@jsarray); + if (@jsarray > 0) { + $jstext = ' var categories = Array('.scalar(@jsarray).');'."\n"; + for (my $i=0; $i<@jsarray; $i++) { + if (ref($jsarray[$i]) eq 'ARRAY') { + my $catstr = join('","',@{$jsarray[$i]}); + $jstext .= ' categories['.$i.'] = Array("'.$catstr.'");'."\n"; + } + } + } + } else { + $jstext = ' var categories = Array(1);'."\n". + ' categories[0] = Array("instcode_pos");'."\n"; + } + $output = <<"ENDSCRIPT"; + + +ENDSCRIPT + return $output; +} + +sub initialize_categories { + my ($itemcount) = @_; + my $datatable; + my $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','0'".');"'; + + $datatable = ''; + $itemcount ++; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','0'".');"'; + $datatable .= ''; + return $datatable; +} + +sub build_category_rows { + my ($itemcount,$cats,$depth,$parent,$path,$idx) = @_; + my ($text,$name,$item,$chgstr); + if (ref($cats) eq 'ARRAY') { + my $maxdepth = scalar(@{$cats}); + if (ref($cats->[$depth]) eq 'HASH') { + if (ref($cats->[$depth]{$parent}) eq 'ARRAY') { + my $numchildren = @{$cats->[$depth]{$parent}}; + my $css_class = $itemcount%2?' class="LC_odd_row"':''; + $text .= ''; + } else { + my $higher = $depth-1; + if ($higher == 0) { + $name = &escape($parent).'::'.$higher; + } else { + if (ref($path) eq 'ARRAY') { + $name = &escape($parent).':'.&escape($path->[-2]).':'.$higher; + } + } + my $colspan; + if ($parent ne 'instcode') { + $colspan = $maxdepth - $depth - 1; + $text .= ''; + } + } + } + } + return $text; +} + sub modifiable_userdata_row { my ($context,$role,$settings,$numinrow,$rowcount) = @_; my $rolename; @@ -1814,25 +2370,6 @@ sub users_cansearch_row { return $output; } -sub sorted_inst_types { - my ($dom) = @_; - my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom); - my $othertitle = &mt('All users'); - my @types; - if (ref($order) eq 'ARRAY') { - @types = @{$order}; - } - if (@types == 0) { - if (ref($usertypes) eq 'HASH') { - @types = sort(keys(%{$usertypes})); - } - } - if (keys(%{$usertypes}) > 0) { - $othertitle = &mt('Other users'); - } - return ($othertitle,$usertypes,\@types); -} - sub sorted_searchtitles { my %searchtitles = &Apache::lonlocal::texthash( 'uname' => 'username', @@ -1908,12 +2445,13 @@ sub modify_login { my ($resulttext,$errors,$colchgtext,%changes,%colchanges); my %title = ( coursecatalog => 'Display course catalog', adminmail => 'Display administrator E-mail address', + newuser => 'Link for visitors to create a user account', loginheader => 'Log-in box header'); my @offon = ('off','on'); my %loginhash; ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'], \%domconfig,\%loginhash); - my @toggles = ('coursecatalog','adminmail'); + my @toggles = ('coursecatalog','adminmail','newuser'); foreach my $item (@toggles) { $loginhash{login}{$item} = $env{'form.'.$item}; } @@ -1925,10 +2463,11 @@ sub modify_login { my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash, $dom); if ($putresult eq 'ok') { - my @toggles = ('coursecatalog','adminmail'); + my @toggles = ('coursecatalog','adminmail','newuser'); my %defaultchecked = ( 'coursecatalog' => 'on', 'adminmail' => 'off', + 'newuser' => 'off', ); foreach my $item (@toggles) { if ($defaultchecked{$item} eq 'on') { @@ -2031,7 +2570,7 @@ sub modify_rolecolors { sub modify_colors { my ($r,$dom,$confname,$roles,$domconfig,$confhash) = @_; my (%changes,%choices); - my @bgs = ('pgbg','mainbg','sidebg'); + my @bgs; my @links = ('link','alink','vlink'); my @logintext; my @images; @@ -2046,23 +2585,17 @@ sub modify_colors { } if ($role eq 'login') { @images = ('img','logo','domlogo','login'); + @bgs = ('pgbg','mainbg','sidebg'); } else { @images = ('img'); + @bgs = ('pgbg','tabbg','sidebg'); } $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'}; foreach my $item (@bgs,@links,@logintext) { $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; } - my ($configuserok,$author_ok,$switchserver,%currroles); - my $uhome = &Apache::lonnet::homeserver($confname,$dom,1); - ($configuserok,%currroles) = &check_configuser($uhome,$dom, - $confname,$servadm); - if ($configuserok eq 'ok') { - $switchserver = &check_switchserver($dom,$confname); - if ($switchserver eq '') { - $author_ok = &check_authorstatus($dom,$confname,%currroles); - } - } + my ($configuserok,$author_ok,$switchserver) = + &config_check($dom,$confname,$servadm); my ($width,$height) = &thumb_dimensions(); if (ref($domconfig->{$role}) ne 'HASH') { $domconfig->{$role} = {}; @@ -2094,11 +2627,11 @@ sub modify_colors { $error = &mt("Upload of [_1] image for $role page(s) failed because an error occurred publishing the file in RES space. Error was: [_2].",$choices{img},$result); } } else { - $error = &mt("Upload of [_1] image for $role page(s) failed because an author role could not be assigned to a Domain Configuation user ([_2]) in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$author_ok); + $error = &mt("Upload of [_1] image for $role page(s) failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$author_ok); } } } else { - $error = &mt("Upload of [_1] image for $role page(s) failed because a Domain Configuation user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$configuserok); + $error = &mt("Upload of [_1] image for $role page(s) failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$configuserok); } if ($error) { &Apache::lonnet::logthis($error); @@ -2197,6 +2730,21 @@ sub modify_colors { return ($errors,%changes); } +sub config_check { + my ($dom,$confname,$servadm) = @_; + my ($configuserok,$author_ok,$switchserver,%currroles); + my $uhome = &Apache::lonnet::homeserver($confname,$dom,1); + ($configuserok,%currroles) = &check_configuser($uhome,$dom, + $confname,$servadm); + if ($configuserok eq 'ok') { + $switchserver = &check_switchserver($dom,$confname); + if ($switchserver eq '') { + $author_ok = &check_authorstatus($dom,$confname,%currroles); + } + } + return ($configuserok,$author_ok,$switchserver); +} + sub default_change_checker { my ($role,$images,$links,$bgs,$logintext,$confhash,$changes) = @_; foreach my $item (@{$links}) { @@ -2223,7 +2771,7 @@ sub default_change_checker { if ($confhash->{$role}{'font'}) { $changes->{$role}{'font'} = 1; } -} +} sub display_colorchgs { my ($dom,$changes,$roles,$confhash) = @_; @@ -2328,7 +2876,7 @@ sub check_authorstatus { my $end = 0; $author_ok = &Apache::lonnet::assignrole($dom,$confname,'/'.$dom.'/', - 'au',$end,$start); + 'au',$end,$start,'','','domconfig'); } else { $author_ok = 'ok'; } @@ -2336,7 +2884,7 @@ sub check_authorstatus { } sub publishlogo { - my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight) = @_; + my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_; my ($output,$fname,$logourl); if ($action eq 'upload') { $fname=$env{'form.'.$formname.'.filename'}; @@ -2344,6 +2892,9 @@ sub publishlogo { } else { ($fname) = ($formname =~ /([^\/]+)$/); } + if ($savefileas ne '') { + $fname = $savefileas; + } $fname=&Apache::lonnet::clean_filename($fname); # See if there is anything left unless ($fname) { return ('error: no uploaded file'); } @@ -2371,7 +2922,7 @@ sub publishlogo { !defined(&Apache::loncommon::fileembstyle($1))) { $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1); } elsif ($file=~/\.(\d+)\.(\w+)$/) { - $output = &mt('File name not allowed a rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); + $output = &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); } elsif (-d "$filepath/$file") { $output = &mt('File name is a directory name - rename the file and re-upload'); } else { @@ -2567,7 +3118,7 @@ END sub modify_quotas { my ($dom,%domconfig) = @_; my ($resulttext,%changes); - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my %formhash; foreach my $key (keys(%env)) { if ($key =~ /^form\.quota_(.+)$/) { @@ -2702,7 +3253,7 @@ sub modify_autoupdate { run => 'Auto-update:', classlists => 'Updates to user information in classlists?' ); - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my %fieldtitles = &Apache::lonlocal::texthash ( id => 'Student/Employee ID', permanentemail => 'E-mail address', @@ -2831,7 +3382,7 @@ sub modify_directorysrch { my @cansearch = &Apache::loncommon::get_env_multiple('form.cansearch'); my @searchby = &Apache::loncommon::get_env_multiple('form.searchby'); - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); if (keys(%{$usertypes}) == 0) { @cansearch = ('default'); } else { @@ -3097,30 +3648,96 @@ sub modify_contacts { sub modify_usercreation { my ($dom,%domconfig) = @_; my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate); + my $warningmsg; if (ref($domconfig{'usercreation'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'usercreation'}})) { $curr_usercreation{$key} = $domconfig{'usercreation'}{$key}; } } - my %title = &Apache::lonlocal::texthash ( - author => 'adding co-authors/assistant authors', - course => 'adding users to a course', - ); my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule'); my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule'); - my @contexts = ('author','course'); + my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule'); + my @contexts = ('author','course','selfcreate'); foreach my $item(@contexts) { - $cancreate{$item} = $env{'form.can_createuser_'.$item}; + if ($item eq 'selfcreate') { + @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth'))) { + if (ref($cancreate{$item}) eq 'ARRAY') { + if (grep(/^login$/,@{$cancreate{$item}})) { + $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.&mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.'); + } + } + } + } else { + $cancreate{$item} = $env{'form.can_createuser_'.$item}; + } } if (ref($curr_usercreation{'cancreate'}) eq 'HASH') { foreach my $item (@contexts) { - if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) { - push(@{$changes{'cancreate'}},$item); - } + if ($item eq 'selfcreate') { + if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') { + foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) { + if (!grep(/^$curr$/,@{$cancreate{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } else { + if ($curr_usercreation{'cancreate'}{$item} eq '') { + if (@{$cancreate{$item}} > 0) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } else { + if ($curr_usercreation{'cancreate'}{$item} eq 'any') { + if (@{$cancreate{$item}} < 3) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif ($curr_usercreation{'cancreate'}{$item} eq 'none') { + if (@{$cancreate{$item}} > 0) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif (!grep(/^$curr_usercreation{'cancreate'}{$item}$/,@{$cancreate{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + foreach my $type (@{$cancreate{$item}}) { + if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') { + if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif (($curr_usercreation{'cancreate'}{$item} ne 'any') && + ($curr_usercreation{'cancreate'}{$item} ne 'none')) { + if ($curr_usercreation{'cancreate'}{$item} ne $type) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + } + } else { + if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) { + push(@{$changes{'cancreate'}},$item); + } + } } } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') { foreach my $item (@contexts) { - if (grep(/^\Q$item\E$/,@{$curr_usercreation{'cancreate'}})) { + if (!grep(/^\Q$item\E$/,@{$curr_usercreation{'cancreate'}})) { if ($cancreate{$item} ne 'any') { push(@{$changes{'cancreate'}},$item); } @@ -3131,7 +3748,7 @@ sub modify_usercreation { } } } else { - foreach my $item ('author','course') { + foreach my $item (@contexts) { push(@{$changes{'cancreate'}},$item); } } @@ -3166,10 +3783,25 @@ sub modify_usercreation { push(@{$changes{'id_rule'}},@id_rule); } - my @contexts = ('author','course','domain'); + if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') { + foreach my $type (@{$curr_usercreation{'email_rule'}}) { + if (!grep(/^\Q$type\E$/,@email_rule)) { + push(@{$changes{'email_rule'}},$type); + } + } + foreach my $type (@email_rule) { + if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) { + push(@{$changes{'email_rule'}},$type); + } + } + } else { + push(@{$changes{'email_rule'}},@email_rule); + } + + my @authen_contexts = ('author','course','domain'); my @authtypes = ('int','krb4','krb5','loc'); my %authhash; - foreach my $item (@contexts) { + foreach my $item (@authen_contexts) { my @authallowed = &Apache::loncommon::get_env_multiple('form.'.$item.'_auth'); foreach my $auth (@authtypes) { if (grep(/^\Q$auth\E$/,@authallowed)) { @@ -3180,7 +3812,7 @@ sub modify_usercreation { } } if (ref($curr_usercreation{'authtypes'}) eq 'HASH') { - foreach my $item (@contexts) { + foreach my $item (@authen_contexts) { if (ref($curr_usercreation{'authtypes'}{$item}) eq 'HASH') { foreach my $auth (@authtypes) { if ($authhash{$item}{$auth} ne $curr_usercreation{'authtypes'}{$item}{$auth}) { @@ -3191,7 +3823,7 @@ sub modify_usercreation { } } } else { - foreach my $item (@contexts) { + foreach my $item (@authen_contexts) { push(@{$changes{'authtypes'}},$item); } } @@ -3201,27 +3833,46 @@ sub modify_usercreation { cancreate => \%cancreate, username_rule => \@username_rule, id_rule => \@id_rule, + email_rule => \@email_rule, authtypes => \%authhash, } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash, $dom); + + my %selfcreatetypes = ( + sso => 'users authenticated by institutional single sign on', + login => 'users authenticated by institutional log-in', + email => 'users who provide a valid e-mail address for use as the username', + ); if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').''; $resulttext .= '
  • '.&mt('Authentication types available for assignment to new users').'
    '.$chgtext; @@ -3284,6 +3956,9 @@ sub modify_usercreation { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } + if ($warningmsg ne '') { + $resulttext .= '
    '.$warningmsg.'
    '; + } return $resulttext; } @@ -3387,4 +4062,435 @@ sub modify_usermodification { return $resulttext; } +sub modify_defaults { + my ($dom,$r) = @_; + my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my @items = ('auth_def','auth_arg_def','lang_def'); + my @authtypes = ('internal','krb4','krb5','localauth'); + foreach my $item (@items) { + $newvalues{$item} = $env{'form.'.$item}; + if ($item eq 'auth_def') { + if ($newvalues{$item} ne '') { + if (!grep(/^\Q$newvalues{$item}\E$/,@authtypes)) { + push(@errors,$item); + } + } + } elsif ($item eq 'lang_def') { + if ($newvalues{$item} ne '') { + if ($newvalues{$item} =~ /^(\w+)/) { + my $langcode = $1; + if (code2language($langcode) eq '') { + push(@errors,$item); + } + } else { + push(@errors,$item); + } + } + } + if (grep(/^\Q$item\E$/,@errors)) { + $newvalues{$item} = $domdefaults{$item}; + } elsif ($domdefaults{$item} ne $newvalues{$item}) { + $changes{$item} = 1; + } + } + my %defaults_hash = ( + defaults => { auth_def => $newvalues{'auth_def'}, + auth_arg_def => $newvalues{'auth_arg_def'}, + lang_def => $newvalues{'lang_def'}, + } + ); + my $title = &defaults_titles(); + my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash, + $dom); + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + $resulttext = &mt('Changes made:').''; + $mailmsgtext .= "\n"; + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('domdefaults',$dom, + $defaults_hash{'defaults'},$cachetime); + my $sysmail = $r->dir_config('lonSysEMail'); + &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext); + } else { + $resulttext = &mt('No changes made to default authentication/language settings'); + } + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + if (@errors > 0) { + $resulttext .= '
    '.&mt('The following were left unchanged because the values entered were invalid:'); + foreach my $item (@errors) { + $resulttext .= ' "'.$title->{$item}.'",'; + } + $resulttext =~ s/,$//; + } + return $resulttext; +} + +sub modify_scantron { + my ($r,$dom,$confname,%domconfig) = @_; + my ($resulttext,%confhash,%changes,$errors); + my $custom = 'custom.tab'; + my $default = 'default.tab'; + my $servadm = $r->dir_config('lonAdmEMail'); + my ($configuserok,$author_ok,$switchserver) = + &config_check($dom,$confname,$servadm); + if ($env{'form.scantronformat.filename'} ne '') { + my $error; + if ($configuserok eq 'ok') { + if ($switchserver) { + $error = &mt("Upload of scantron format file is not permitted to this server: [_1]",$switchserver); + } else { + if ($author_ok eq 'ok') { + my ($result,$scantronurl) = + &publishlogo($r,'upload','scantronformat',$dom, + $confname,'scantron','','',$custom); + if ($result eq 'ok') { + $confhash{'scantron'}{'scantronformat'} = $scantronurl; + $changes{'scantronformat'} = 1; + } else { + $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$custom,$result); + } + } else { + $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$custom,$confname,$dom,$author_ok); + } + } + } else { + $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$custom,$confname,$dom,$configuserok); + } + if ($error) { + &Apache::lonnet::logthis($error); + $errors .= '
  • '.$error.'
  • '; + } + } + if (ref($domconfig{'scantron'}) eq 'HASH') { + if ($domconfig{'scantron'}{'scantronformat'} ne '') { + if ($env{'form.scantronformat_del'}) { + $confhash{'scantron'}{'scantronformat'} = ''; + $changes{'scantronformat'} = 1; + } + } + } + if (keys(%confhash) > 0) { + my $putresult = &Apache::lonnet::put_dom('configuration',\%confhash, + $dom); + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + if (ref($confhash{'scantron'}) eq 'HASH') { + $resulttext = &mt('Changes made:').''; + } else { + $resulttext = &mt('Changes made to scantron format file.'); + } + $resulttext .= ''; + &Apache::loncommon::devalidate_domconfig_cache($dom); + } else { + $resulttext = &mt('No changes made to scantron format file'); + } + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + } else { + $resulttext = &mt('No changes made to scantron format file'); + } + if ($errors) { + $resulttext .= &mt('The following errors occurred: ').''; + } + return $resulttext; +} + +sub modify_coursecategories { + my ($dom,%domconfig) = @_; + my ($resulttext,%deletions,%reorderings,%needreordering,%adds,$errors); + my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory'); + if (($domconfig{'coursecategories'}{'instcode::0'} ne '') && ($env{'form.instcode'} == 0)) { + push (@deletecategory,'instcode::0'); + } + my (@predelcats,@predeltrails,%predelallitems); + if (ref($domconfig{'coursecategories'}) eq 'HASH') { + if (@deletecategory > 0) { + #FIXME Need to remove category from all courses using a deleted category + &extract_categories($domconfig{'coursecategories'},\@predelcats,\@predeltrails,\%predelallitems); + foreach my $item (@deletecategory) { + if ($domconfig{'coursecategories'}{$item} ne '') { + delete($domconfig{'coursecategories'}{$item}); + $deletions{$item} = 1; + &recurse_cat_deletes($item,$domconfig{'coursecategories'}, + \%deletions); + } + } + } + foreach my $item (keys(%{$domconfig{'coursecategories'}})) { + my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item); + if ($domconfig{'coursecategories'}{$item} ne $env{'form.'.$item}) { + $reorderings{$item} = 1; + $domconfig{'coursecategories'}{$item} = $env{'form.'.$item}; + } + if ($env{'form.addcategory_name_'.$item} ne '') { + my $newcat = $env{'form.addcategory_name_'.$item}; + my $newdepth = $depth+1; + my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth; + $domconfig{'coursecategories'}{$newitem} = $env{'form.addcategory_pos_'.$item}; + $adds{$newitem} = 1; + } + if ($env{'form.subcat_'.$item} ne '') { + my $newcat = $env{'form.subcat_'.$item}; + my $newdepth = $depth+1; + my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth; + $domconfig{'coursecategories'}{$newitem} = 0; + $adds{$newitem} = 1; + } + } + } + if ($env{'form.instcode'} eq '1') { + if (ref($domconfig{'coursecategories'}) eq 'HASH') { + my $newitem = 'instcode::0'; + if ($domconfig{'coursecategories'}{$newitem} eq '') { + $domconfig{'coursecategories'}{$newitem} = $env{'form.instcode_pos'}; + $adds{$newitem} = 1; + } + } else { + my $newitem = 'instcode::0'; + $domconfig{'coursecategories'}{$newitem} = $env{'form.instcode_pos'}; + $adds{$newitem} = 1; + } + } + if ($env{'form.addcategory_name'} ne '') { + my $newitem = &escape($env{'form.addcategory_name'}).'::0'; + $domconfig{'coursecategories'}{$newitem} = $env{'form.addcategory_pos'}; + $adds{$newitem} = 1; + } + if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) { + my %sort_by_deltrail; + if (keys(%deletions) > 0) { + foreach my $key (keys(%deletions)) { + if ($predelallitems{$key} ne '') { + $sort_by_deltrail{$predelallitems{$key}} = $predeltrails[$predelallitems{$key}]; + } + } + } + my (@chkcats,@chktrails,%chkallitems); + &extract_categories($domconfig{'coursecategories'},\@chkcats,\@chktrails,\%chkallitems); + if (ref($chkcats[0]) eq 'ARRAY') { + my $depth = 0; + my $chg = 0; + for (my $i=0; $i<@{$chkcats[0]}; $i++) { + my $name = $chkcats[0][$i]; + my $item; + if ($name eq '') { + $chg ++; + } else { + $item = &escape($name).'::0'; + if ($chg) { + $domconfig{'coursecategories'}{$item} -= $chg; + } + $depth ++; + &recurse_check(\@chkcats,$domconfig{'coursecategories'},$depth,$name); + $depth --; + } + } + } + my $putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom); + my (@cats,@trails,%allitems); + &extract_categories($domconfig{'coursecategories'},\@cats,\@trails,\%allitems); + if ($putresult eq 'ok') { + $resulttext = &mt('Changes made:').''; + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + } else { + $resulttext = &mt('No changes made to course categories'); + } + return $resulttext; +} + +sub recurse_check { + my ($chkcats,$categories,$depth,$name) = @_; + if (ref($chkcats->[$depth]{$name}) eq 'ARRAY') { + my $chg = 0; + for (my $j=0; $j<@{$chkcats->[$depth]{$name}}; $j++) { + my $category = $chkcats->[$depth]{$name}[$j]; + my $item; + if ($category eq '') { + $chg ++; + } else { + my $deeper = $depth + 1; + $item = &escape($category).':'.&escape($name).':'.$depth; + if ($chg) { + $categories->{$item} -= $chg; + } + &recurse_check($chkcats,$categories,$deeper,$category); + $deeper --; + } + } + } + return; +} + +sub recurse_cat_deletes { + my ($item,$coursecategories,$deletions) = @_; + my ($deleted,$container,$depth) = map { &unescape($_); } split(/:/,$item); + my $subdepth = $depth + 1; + if (ref($coursecategories) eq 'HASH') { + foreach my $subitem (keys(%{$coursecategories})) { + my ($child,$parent,$itemdepth) = map { &unescape($_); } split(/:/,$subitem); + if (($parent eq $deleted) && ($itemdepth == $subdepth)) { + delete($coursecategories->{$subitem}); + $deletions->{$subitem} = 1; + &recurse_cat_deletes($subitem,$coursecategories,$deletions); + } + } + } + return; +} + +sub gather_categories { + my ($categories,$cats,$idx,$jsarray) = @_; + my %counters; + my $num = 0; + foreach my $item (keys(%{$categories})) { + my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item); + if ($container eq '' && $depth == 0) { + $cats->[$depth][$categories->{$item}] = $cat; + } else { + $cats->[$depth]{$container}[$categories->{$item}] = $cat; + } + my ($escitem,$tail) = split(/:/,$item,2); + if ($counters{$tail} eq '') { + $counters{$tail} = $num; + $num ++; + } + if (ref($idx) eq 'HASH') { + $idx->{$item} = $counters{$tail}; + } + if (ref($jsarray) eq 'ARRAY') { + push(@{$jsarray->[$counters{$tail}]},$item); + } + } + return; +} + +sub extract_categories { + my ($categories,$cats,$trails,$allitems,$idx,$jsarray) = @_; + if (ref($categories) eq 'HASH') { + &gather_categories($categories,$cats,$idx,$jsarray); + if (ref($cats->[0]) eq 'ARRAY') { + for (my $i=0; $i<@{$cats->[0]}; $i++) { + my $name = $cats->[0][$i]; + my $item = &escape($name).'::0'; + my $trailstr; + if ($name eq 'instcode') { + $trailstr = &mt('Official courses (with institutional codes)'); + } else { + $trailstr = $name; + } + if ($allitems->{$item} eq '') { + push(@{$trails},$trailstr); + $allitems->{$item} = scalar(@{$trails})-1; + } + my @parents = ($name); + if (ref($cats->[1]{$name}) eq 'ARRAY') { + for (my $j=0; $j<@{$cats->[1]{$name}}; $j++) { + my $category = $cats->[1]{$name}[$j]; + &recurse_categories($cats,2,$category,$trails,$allitems,\@parents); + } + } + } + } + } + return; +} + +sub recurse_categories { + my ($cats,$depth,$category,$trails,$allitems,$parents) = @_; + my $shallower = $depth - 1; + if (ref($cats->[$depth]{$category}) eq 'ARRAY') { + for (my $k=0; $k<@{$cats->[$depth]{$category}}; $k++) { + my $name = $cats->[$depth]{$category}[$k]; + my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower; + my $trailstr = join(' -> ',(@{$parents},$category)); + if ($allitems->{$item} eq '') { + push(@{$trails},$trailstr); + $allitems->{$item} = scalar(@{$trails})-1; + } + my $deeper = $depth+1; + push(@{$parents},$category); + &recurse_categories($cats,$deeper,$name,$trails,$allitems,$parents); + pop(@{$parents}); + } + } else { + my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower; + my $trailstr = join(' -> ',(@{$parents},$category)); + if ($allitems->{$item} eq '') { + push(@{$trails},$trailstr); + $allitems->{$item} = scalar(@{$trails})-1; + } + } + return; +} + 1;
    '.&mt($item->{text}). @@ -440,10 +474,11 @@ sub print_config_box { $output .= ' '.$item->{'header'}->[0]->{'col1'}.''.$item->{'header'}->[0]->{'col2'}.''.$item->{'header'}->[0]->{'col2'}.'
    '.&mt('No format rules have been defined for usernames or IDs in this domain.').'
    '.$lt{$item}. ''; - my @options = ('any'); - if (ref($rules) eq 'HASH') { - if (keys(%{$rules}) > 0) { - push(@options,('official','unofficial')); + my @options; + if ($item eq 'selfcreate') { + push(@options,('email','login','sso')); + } else { + @options = ('any'); + if (ref($rules) eq 'HASH') { + if (keys(%{$rules}) > 0) { + push(@options,('official','unofficial')); + } } + push(@options,'none'); } - push(@options,'none'); foreach my $option (@options) { + my $type = 'radio'; my $check = ' '; - if ($checked{$item} eq $option) { - $check = ' checked="checked" '; + if ($item eq 'selfcreate') { + $type = 'checkbox'; + if (grep(/^\Q$option\E$/,@selfcreate)) { + $check = ' checked="checked" '; + } + } else { + if ($checked{$item} eq $option) { + $check = ' checked="checked" '; + } } $datatable .= '  '; } @@ -1594,6 +1672,7 @@ sub user_formats_row { my %text = ( 'username' => 'new usernames', 'id' => 'IDs', + 'email' => 'self-created accounts (e-mail)', ); my $css_class = $rowcount%2?' class="LC_odd_row"':''; $output = '
    '.$titles->{$item}. + ''; + if ($item eq 'auth_def') { + my @authtypes = ('internal','krb4','krb5','localauth'); + my %shortauth = ( + internal => 'int', + krb4 => 'krb4', + krb5 => 'krb5', + localauth => 'loc' + ); + my %authnames = &authtype_names(); + foreach my $auth (@authtypes) { + my $checked = ' '; + if ($domdefaults{$item} eq $auth) { + $checked = ' checked="checked" '; + } + $datatable .= '  '; + } + } else { + $datatable .= ''; + } + $datatable .= '
    '.&mt('Default in use:').'
    '; + if ($scantronurl) { + $datatable .= ''. + &mt('Default scantron format file').''; + } else { + $datatable = &mt('File unavailable for display'); + } + $datatable .= '
    '.&mt('Upload:').'
    '; + } else { + if (keys(%error) > 0) { + my $errorstr; + foreach my $key (sort(keys(%error))) { + $errorstr .= $lt{$key}.': '.$error{$key}.'
    '; + } + $datatable .= '
    '.$errorstr.''; + } elsif ($scantronurl) { + $datatable .= '' .&mt('Custom scantron format file').'' + .''.&mt('Replace:').'
    '; + } + } + if (keys(%error) == 0) { + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .=' '; + } + } + $datatable .= '
    ' + .''; + if ($parent eq 'instcode') { + $datatable .= ''.&mt('Official courses') + .'
    (' + .&mt('with institutional codes').')
    '.&mt('New:').' ' + .'
    '. + '' + .&mt('Official courses').''.'
    (' + .&mt('with institutional codes').')
     ' + .'
    '.$hdritem->{'header'}->[0]->{'col2'}.'
    ' + .' ' + .&mt('Official courses (with institutional codes)') + .'' + .' 
    ' + .' ' + .&mt('Add category').''.&mt('Name:') + .' 
    '; + my ($idxnum,$parent_name,$parent_item); + my $higher = $depth - 1; + if ($higher == 0) { + $parent_name = &escape($parent).'::'.$higher; + } else { + if (ref($path) eq 'ARRAY') { + $parent_name = &escape($parent).':'.&escape($path->[-2]).':'.$higher; + } + } + $parent_item = 'addcategory_pos_'.$parent_name; + for (my $j=0; $j<=$numchildren; $j++) { + if ($j < $numchildren) { + $name = $cats->[$depth]{$parent}[$j]; + $item = &escape($name).':'.&escape($parent).':'.$depth; + $idxnum = $idx->{$item}; + } else { + $name = $parent_name; + $item = $parent_item; + } + $chgstr = ' onchange="javascript:reorderCats(this.form,'."'$parent_name','$item','$idxnum'".');"'; + $text .= ''; + } + $text .= '
     '; + if ($j < $numchildren) { + my $deeper = $depth+1; + $text .= $name.' ' + .''; + if(ref($path) eq 'ARRAY') { + push(@{$path},$name); + $text .= &build_category_rows($itemcount,$cats,$deeper,$name,$path,$idx); + pop(@{$path}); + } + } else { + $text .= &mt('New:').' '; + } + $text .= '
    '.&mt('Add subcategory:').'