--- loncom/interface/domainprefs.pm 2012/09/25 20:38:47 1.160.6.6 +++ loncom/interface/domainprefs.pm 2013/01/09 21:34:26 1.187 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.160.6.6 2012/09/25 20:38:47 raeburn Exp $ +# $Id: domainprefs.pm,v 1.187 2013/01/09 21:34:26 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -45,7 +45,7 @@ described at http://www.lon-capa.org. =head1 OVERVIEW Each institution using LON-CAPA will typically have a single domain designated -for use by individuals affliated with the institution. Accordingly, each domain +for use by individuals affiliated with the institution. Accordingly, each domain may define a default set of logos and a color scheme which can be used to "brand" the LON-CAPA instance. In addition, an institution will typically have a language and timezone which are used for the majority of courses. @@ -86,7 +86,7 @@ $dom,$settings,$rowtotal,$action. $dom is the domain, $settings is a reference to a hash of current settings for the current context, $rowtotal is a reference to the scalar used to record the -number of rows displayed on the page, and $action is the context (quotas, +number of rows displayed on the page, and $action is the context (quotas, requestcourses or requestauthor). The print_quotas routine was orginally created to display/store information @@ -210,14 +210,20 @@ sub handler { 'quotas','autoenroll','autoupdate','autocreate', 'directorysrch','usercreation','usermodification', 'contacts','defaults','scantron','coursecategories', - 'serverstatuses','requestcourses','usersessions', - 'loadbalancing','requestauthor'],$dom); + 'serverstatuses','requestcourses','helpsettings', + 'coursedefaults','usersessions','loadbalancing', + 'requestauthor'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','autocreate','directorysrch','contacts', 'usercreation','usermodification','scantron', 'requestcourses','requestauthor','coursecategories', - 'serverstatuses','usersessions'); - if (keys(%servers) > 1) { + 'serverstatuses','helpsettings', + 'coursedefaults','usersessions'); + my %existing; + if (ref($domconfig{'loadbalancing'}) eq 'HASH') { + %existing = %{$domconfig{'loadbalancing'}}; + } + if ((keys(%servers) > 1) || (keys(%existing) > 0)) { push(@prefs_order,'loadbalancing'); } my %prefs = ( @@ -349,6 +355,26 @@ sub handler { col3 => 'Specific IPs', }], }, + 'helpsettings' => + {text => 'Help page settings', + help => 'Domain_Configuration_Help_Settings', + header => [{col1 => 'Help Settings (logged-in users)', + col2 => 'Value'}], + }, + 'coursedefaults' => + {text => 'Course/Community defaults', + help => 'Domain_Configuration_Course_Defaults', + header => [{col1 => 'Defaults which can be overridden in each course by a CC', + col2 => 'Value',}, + {col1 => 'Defaults which can be overridden for each course by a DC', + col2 => 'Value',},], + }, + 'privacy' => + {text => 'User Privacy', + help => 'Domain_Configuration_User_Privacy', + header => [{col1 => 'Setting', + col2 => 'Value',}], + }, 'usersessions' => {text => 'User session hosting/offloading', help => 'Domain_Configuration_User_Sessions', @@ -360,11 +386,11 @@ sub handler { col2 => 'Rules'}], }, 'loadbalancing' => - {text => 'Dedicated Load Balancer', + {text => 'Dedicated Load Balancer(s)', help => 'Domain_Configuration_Load_Balancing', - header => [{col1 => 'Server', + header => [{col1 => 'Balancers', col2 => 'Default destinations', - col3 => 'User affliation', + col3 => 'User affiliation', col4 => 'Overrides'}, ], }, @@ -380,26 +406,57 @@ sub handler { col2 => 'Value'}], }; } + my @roles = ('student','coordinator','author','admin'); my @actions = &Apache::loncommon::get_env_multiple('form.actions'); &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:changePage(document.$phase,'pickactions')", text=>"Settings to display/modify"}); my $confname = $dom.'-domainconfig'; + if ($phase eq 'process') { &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles); } elsif ($phase eq 'display') { my $js = &recaptcha_js(); - if (keys(%servers) > 1) { + if ((keys(%servers) > 1) || (keys(%existing) > 0)) { my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); - $js .= &lonbalance_targets_js($dom,$types,\%servers). + $js .= &lonbalance_targets_js($dom,$types,\%servers, + $domconfig{'loadbalancing'}). &new_spares_js(). &common_domprefs_js(). &Apache::loncommon::javascript_array_indexof(); } &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js); } else { +# check if domconfig user exists for the domain. + my $servadm = $r->dir_config('lonAdmEMail'); + my ($configuserok,$author_ok,$switchserver) = + &config_check($dom,$confname,$servadm); + unless ($configuserok eq 'ok') { + &Apache::lonconfigsettings::print_header($r,$phase,$context); + $r->print(&mt('The domain configuration user "[_1]" has yet to be created.', + $confname). + '
' + ); + if ($switchserver) { + $r->print(&mt('Ordinarily, that domain configuration user is created when the ./UPDATE script is run to install LON-CAPA for the first time.'). + '
'. + &mt('However, that does not apply when new domains are added to a multi-domain server, and ./UPDATE has not been run recently.'). + '
'. + &mt('The "[_1]" user can be created automatically when a Domain Coordinator visits the web-based "Set domain configuration" screen, in a session hosted on the primary library server.',$confname). + '
'. + &mt('To do that now, use the following link: [_1]',$switchserver) + ); + } else { + $r->print(&mt('To create that user from the command line run the ./UPDATE script found in the top level directory of the extracted LON-CAPA tarball.'). + '
'. + &mt('Once that is done, you will be able to use the web-based "Set domain configuration" to configure the domain') + ); + } + $r->print(&Apache::loncommon::end_page()); + return OK; + } if (keys(%domconfig) == 0) { my $primarylibserv = &Apache::lonnet::domain($dom,'primary'); my @ids=&Apache::lonnet::current_machine_ids(); @@ -478,6 +535,10 @@ sub process_changes { $output = &modify_quotas($dom,$action,%domconfig); } elsif ($action eq 'requestauthor') { $output = &modify_quotas($dom,$action,%domconfig); + } elsif ($action eq 'helpsettings') { + $output = &modify_helpsettings($r,$dom,$confname,%domconfig); + } elsif ($action eq 'coursedefaults') { + $output = &modify_coursedefaults($dom,%domconfig); } elsif ($action eq 'usersessions') { $output = &modify_usersessions($dom,%domconfig); } elsif ($action eq 'loadbalancing') { @@ -508,7 +569,7 @@ sub print_config_box { if ($numheaders > 1) { my $colspan = ''; my $rightcolspan = ''; - if (($action eq 'rolecolors') || ($action eq 'coursecategories') || + if (($action eq 'rolecolors') || ($action eq 'coursecategories') || (($action eq 'login') && ($numheaders < 3))) { $colspan = ' colspan="2"'; } @@ -547,6 +608,8 @@ sub print_config_box { $output .= &print_usersessions('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'rolecolors') { $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'coursedefaults') { + $output .= &print_coursedefaults('top',$dom,$settings,\$rowtotal); } $output .= ' @@ -776,7 +839,7 @@ sub print_login { ' '.$fontlink. - '    '. - ''; + ' '. + ' '; unless ($role eq 'login') { $datatable .= ''. ''.$choices->{'fontmenu'}.''; @@ -1173,13 +1235,13 @@ sub display_color_options { } else { $datatable .= ' '; } - $fontlink = &color_pick($phase,$role,'fontmenu',$choices->{'fontmenu'},$designs->{'fontmenu'}); + $current_color = $designs->{'fontmenu'} ? + $designs->{'fontmenu'} : $defaults->{'fontmenu'}; $datatable .= ''. - ' '.$fontlink. - '    '. - ''; + ' '. + ' '; } my $switchserver = &check_switchserver($dom,$confname); foreach my $img (@{$images}) { @@ -1306,13 +1368,14 @@ sub display_color_options { } $datatable .= ''. ''; + foreach my $item (@{$bgs}) { - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item}); - $datatable .= ''; } $datatable .= '
'.$link; + $datatable .= ''; + my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item}; if ($designs->{'bgs'}{$item}) { - $datatable .= '    '; + $datatable .= ' '; } - $datatable .= '
'; @@ -1334,13 +1397,13 @@ sub display_color_options { $datatable .= ''. ''; foreach my $item (@{$links}) { - $datatable .= ''; } $$rowtotal += $itemcount; @@ -1470,7 +1533,7 @@ sub print_quotas { } elsif ($context eq 'requestauthor') { @usertools = ('author'); @options = ('norequest','approval','automatic'); - %titles = &authorrequest_titles(); + %titles = &authorrequest_titles(); } else { @usertools = ('aboutme','blog','webdav','portfolio'); %titles = &tool_titles(); @@ -1681,9 +1744,7 @@ sub print_quotas { } elsif ($context eq 'requestauthor') { my $curroption; if (ref($settings) eq 'HASH') { - if (ref($settings->{'requestauthor'}) eq 'HASH') { - $curroption = $settings->{'requestauthor'}; - } + $curroption = $settings->{'default'}; } if (!$curroption) { $curroption = 'norequest'; @@ -1828,8 +1889,8 @@ sub print_quotas { $checked = ' checked="checked"'; } $datatable .= '  '; } } else { @@ -1932,7 +1993,7 @@ sub print_requestmail { $datatable .= ''; + $fullname.' ('.$uname.':'.$udom.')'; } $datatable .= '
'."\n". - &color_pick($phase,$role,$item,$choices->{$item}, - $designs->{'links'}{$item}); + my $color = $designs->{'link'}{$item} ? $designs->{'link'}{$item} : $defaults->{'links'}{$item}; + $datatable .= ''."\n"; + if ($designs->{'links'}{$item}) { - $datatable.='    '; + $datatable.=' '; } - $datatable .= '
'; } else { @@ -2725,7 +2786,10 @@ sub spares_row { $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; $datatable .= ' - '.$server.' when busy, offloads to:'."\n"; + '. + &mt('[_1] when busy, offloads to:' + ,''.$server.''). + "\n"; my (%current,%canselect); my @choices = &possible_newspares($server,$spareid->{$server},$serverhomes,$altids); @@ -2849,16 +2913,13 @@ sub print_loadbalancing { my $numinrow = 1; my $datatable; my %servers = &Apache::lonnet::internet_dom_servers($dom); - my ($currbalancer,$currtargets,$currrules); - if (keys(%servers) > 1) { - if (ref($settings) eq 'HASH') { - $currbalancer = $settings->{'lonhost'}; - $currtargets = $settings->{'targets'}; - $currrules = $settings->{'rules'}; - } else { - ($currbalancer,$currtargets) = - &Apache::lonnet::get_lonbalancer_config(\%servers); - } + my (%currbalancer,%currtargets,%currrules,%existing); + if (ref($settings) eq 'HASH') { + %existing = %{$settings}; + } + if ((keys(%servers) > 1) || (keys(%existing) > 0)) { + &get_loadbalancers_config(\%servers,\%existing,\%currbalancer, + \%currtargets,\%currrules); } else { return; } @@ -2868,104 +2929,190 @@ sub print_loadbalancing { if (ref($types) eq 'ARRAY') { $rownum += scalar(@{$types}); } - my $css_class = ' class="LC_odd_row"'; - my $targets_div_style = 'display: none'; - my $disabled_div_style = 'display: block'; - my $homedom_div_style = 'display: none'; - $datatable = ''. - ''. - '

'. - '
'.&mt('No dedicated Load Balancer').'
'."\n". - '
'.&mt('Offloads to:').'
'; - my ($numspares,@spares) = &count_servers($currbalancer,%servers); - my @sparestypes = ('primary','default'); - my %typetitles = &sparestype_titles(); - foreach my $sparetype (@sparestypes) { - my $targettable; - for (my $i=0; $i<$numspares; $i++) { - my $checked; - if (ref($currtargets) eq 'HASH') { - if (ref($currtargets->{$sparetype}) eq 'ARRAY') { - if (grep(/^\Q$spares[$i]\E$/,@{$currtargets->{$sparetype}})) { - $checked = ' checked="checked"'; + my @css_class = ('LC_odd_row','LC_even_row'); + my $balnum = 0; + my $islast; + my (@toshow,$disabledtext); + if (keys(%currbalancer) > 0) { + @toshow = sort(keys(%currbalancer)); + if (scalar(@toshow) < scalar(keys(%servers)) + 1) { + push(@toshow,''); + } + } else { + @toshow = (''); + $disabledtext = &mt('No existing load balancer'); + } + foreach my $lonhost (@toshow) { + if ($balnum == scalar(@toshow)-1) { + $islast = 1; + } else { + $islast = 0; + } + my $cssidx = $balnum%2; + my $targets_div_style = 'display: none'; + my $disabled_div_style = 'display: block'; + my $homedom_div_style = 'display: none'; + $datatable .= ''. + ''. + '

'; + if ($lonhost eq '') { + $datatable .= ''; + if (keys(%currbalancer) > 0) { + $datatable .= &mt('Add balancer:'); + } else { + $datatable .= &mt('Enable balancer:'); + } + $datatable .= ' '. + ''."\n". + ' '."\n"; + } else { + $datatable .= ''.$lonhost.'
'. + ''. + ''; + $targets_div_style = 'display: block'; + $disabled_div_style = 'display: none'; + if ($dom eq &Apache::lonnet::host_domain($lonhost)) { + $homedom_div_style = 'display: block'; + } + } + $datatable .= '

'. + '
'.$disabledtext.'
'."\n". + '
'.&mt('Offloads to:').'
'; + my ($numspares,@spares) = &count_servers($lonhost,%servers); + my @sparestypes = ('primary','default'); + my %typetitles = &sparestype_titles(); + foreach my $sparetype (@sparestypes) { + my $targettable; + for (my $i=0; $i<$numspares; $i++) { + my $checked; + if (ref($currtargets{$lonhost}) eq 'HASH') { + if (ref($currtargets{$lonhost}{$sparetype}) eq 'ARRAY') { + if (grep(/^\Q$spares[$i]\E$/,@{$currtargets{$lonhost}{$sparetype}})) { + $checked = ' checked="checked"'; + } + } + } + my ($chkboxval,$disabled); + if (($lonhost ne '') && (exists($servers{$lonhost}))) { + $chkboxval = $spares[$i]; + } + if (exists($currbalancer{$spares[$i]})) { + $disabled = ' disabled="disabled"'; + } + $targettable .= + ''; + my $rem = $i%($numinrow); + if ($rem == 0) { + if (($i > 0) && ($i < $numspares-1)) { + $targettable .= ''; + } + if ($i < $numspares-1) { + $targettable .= ''; } } } - my $chkboxval; - if (($currbalancer ne '') && (grep((/^\Q$currbalancer\E$/,keys(%servers))))) { - $chkboxval = $spares[$i]; - } - $targettable .= ''; - my $rem = $i%($numinrow); - if ($rem == 0) { - if ($i > 0) { - $targettable .= ''; - } - $targettable .= ''; + if ($targettable ne '') { + my $rem = $numspares%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $targettable .= ''. + ' '; + } elsif ($colsleft == 1) { + $targettable .= ' '; + } + $datatable .= ''.$typetitles{$sparetype}.'
'. + ''.$targettable.'

'; + } + } + $datatable .= '
'. + &loadbalancing_rules($dom,$intdom,$currrules{$lonhost}, + $othertitle,$usertypes,$types,\%servers, + \%currbalancer,$lonhost, + $targets_div_style,$homedom_div_style, + $css_class[$cssidx],$balnum,$islast); + $$rowtotal += $rownum; + $balnum ++; + } + $datatable .= ''; + return $datatable; +} + +sub get_loadbalancers_config { + my ($servers,$existing,$currbalancer,$currtargets,$currrules) = @_; + return unless ((ref($servers) eq 'HASH') && + (ref($existing) eq 'HASH') && (ref($currbalancer) eq 'HASH') && + (ref($currtargets) eq 'HASH') && (ref($currrules) eq 'HASH')); + if (keys(%{$existing}) > 0) { + my $oldlonhost; + foreach my $key (sort(keys(%{$existing}))) { + if ($key eq 'lonhost') { + $oldlonhost = $existing->{'lonhost'}; + $currbalancer->{$oldlonhost} = 1; + } elsif ($key eq 'targets') { + if ($oldlonhost) { + $currtargets->{$oldlonhost} = $existing->{'targets'}; + } + } elsif ($key eq 'rules') { + if ($oldlonhost) { + $currrules->{$oldlonhost} = $existing->{'rules'}; + } + } elsif (ref($existing->{$key}) eq 'HASH') { + $currbalancer->{$key} = 1; + $currtargets->{$key} = $existing->{$key}{'targets'}; + $currrules->{$key} = $existing->{$key}{'rules'}; } } - if ($targettable ne '') { - my $rem = $numspares%($numinrow); - my $colsleft = $numinrow - $rem; - if ($colsleft > 1 ) { - $targettable .= ''. - ' '; - } elsif ($colsleft == 1) { - $targettable .= ' '; + } else { + my ($balancerref,$targetsref) = + &Apache::lonnet::get_lonbalancer_config($servers); + if ((ref($balancerref) eq 'HASH') && (ref($targetsref) eq 'HASH')) { + foreach my $server (sort(keys(%{$balancerref}))) { + $currbalancer->{$server} = 1; + $currtargets->{$server} = $targetsref->{$server}; } - $datatable .= ''.$typetitles{$sparetype}.'
'. - ''.$targettable.'

'; } } - $datatable .= '
'. - &loadbalancing_rules($dom,$intdom,$currrules,$othertitle, - $usertypes,$types,\%servers,$currbalancer, - $targets_div_style,$homedom_div_style,$css_class); - $$rowtotal += $rownum; - return $datatable; + return; } sub loadbalancing_rules { my ($dom,$intdom,$currrules,$othertitle,$usertypes,$types,$servers, - $currbalancer,$targets_div_style,$homedom_div_style,$css_class) = @_; + $currbalancer,$lonhost,$targets_div_style,$homedom_div_style, + $css_class,$balnum,$islast) = @_; my $output; + my $num = 0; my ($alltypes,$othertypes,$titles) = &loadbalancing_titles($dom,$intdom,$usertypes,$types); if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) { foreach my $type (@{$alltypes}) { + $num ++; my $current; if (ref($currrules) eq 'HASH') { $current = $currrules->{$type}; } if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { - if ($dom ne &Apache::lonnet::host_domain($currbalancer)) { + if ($dom ne &Apache::lonnet::host_domain($lonhost)) { $current = ''; } } $output .= &loadbalance_rule_row($type,$titles->{$type},$current, - $servers,$currbalancer,$dom, - $targets_div_style,$homedom_div_style,$css_class); + $servers,$currbalancer,$lonhost,$dom, + $targets_div_style,$homedom_div_style, + $css_class,$balnum,$num,$islast); } } return $output; @@ -3002,8 +3149,8 @@ sub loadbalancing_titles { } sub loadbalance_rule_row { - my ($type,$title,$current,$servers,$currbalancer,$dom,$targets_div_style, - $homedom_div_style,$css_class) = @_; + my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom, + $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_; my @rulenames = ('default','homeserver'); my %ruletitles = &offloadtype_text(); if ($type eq '_LC_external') { @@ -3016,9 +3163,15 @@ sub loadbalance_rule_row { if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { $style = $homedom_div_style; } + my $space; + if ($islast && $num == 1) { + $space = '
 
'; + } my $output = - '
'.$title.'
'."\n". - '
'."\n"; + ''.$space. + '
'.$title.'
'."\n". + ''.$space. + '
'."\n"; for (my $i=0; $i<@rulenames; $i++) { my $rule = $rulenames[$i]; my ($checked,$extra); @@ -3034,17 +3187,20 @@ sub loadbalance_rule_row { unless ($checked) { $default = ' selected="selected"'; } - $extra = ': '."\n". + ''."\n"; + foreach my $server (sort(keys(%{$servers}))) { + if (ref($currbalancer) eq 'HASH') { + next if (exists($currbalancer->{$server})); + } my $selected; - if ($lonhost eq $current) { + if ($server eq $current) { $selected = ' selected="selected"'; } - $extra .= ''; + $extra .= ''; } $extra .= ''; } @@ -3052,9 +3208,9 @@ sub loadbalance_rule_row { $checked = ' checked="checked"'; } $output .= ''.$extra.'
'."\n"; } @@ -3132,7 +3288,7 @@ sub authorrequest_titles { automatic => 'Automatic approval', ); return %titles; -} +} sub courserequest_conditions { my %conditions = &Apache::lonlocal::texthash ( @@ -3371,9 +3527,9 @@ sub captcha_choice { # # Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit: # https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple -# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) +# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain. -# +# $output .= ''."\n". ''."\n". ''.$pubtext.' '."\n". @@ -4681,7 +4837,7 @@ sub modify_login { } else { my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$newfile{$lang},$result); $errors .= '
  • '.$puberror.'
  • '; - if ((grep(/^\Q$lang\E$/,@currlangs)) && + if ((grep(/^\Q$lang\E$/,@currlangs)) && (!grep(/^\Q$lang\E$/,@delurls))) { $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang}; @@ -4797,7 +4953,7 @@ sub modify_login { } } elsif ($item eq 'captcha') { if (ref($loginhash{'login'}) eq 'HASH') { - my $chgtxt; + my $chgtxt; if ($loginhash{'login'}{$item} eq 'notused') { $chgtxt .= &mt('No CAPTCHA validation in use for helpdesk form.'); } else { @@ -5275,7 +5431,7 @@ sub publishlogo { # See if there is anything left unless ($fname) { return ('error: no uploaded file'); } $fname="$subdir/$fname"; - my $docroot=$r->dir_config('lonDocRoot'); + my $docroot=$r->dir_config('lonDocRoot'); my $filepath="$docroot/priv"; my $relpath = "$dom/$confname"; my ($fnamepath,$file,$fetchthumb); @@ -5283,7 +5439,7 @@ sub publishlogo { if ($fname=~m|/|) { ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|); } - my @parts=split(/\//,"$filepath/$relpath/$fnamepath"); + my @parts=split(/\//,"$filepath/$relpath/$fnamepath"); my $count; for ($count=5;$count<=$#parts;$count++) { $filepath.="/$parts[$count]"; @@ -5454,7 +5610,7 @@ sub write_metadata { print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file; my $mfh; if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) { - foreach (sort keys %metadatafields) { + foreach (sort(keys(%metadatafields))) { unless ($_=~/\./) { my $unikey=$_; $unikey=~/^([A-Za-z]+)/; @@ -5538,7 +5694,7 @@ sub check_switchserver { my @ids=&Apache::lonnet::current_machine_ids(); foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } if (!$allowed) { - $switchserver=''.&mt('Switch Server').''; + $switchserver=''.&mt('Switch Server').''; } return $switchserver; } @@ -5549,7 +5705,7 @@ sub modify_quotas { %limithash,$toolregexp,%conditions,$resulttext,%changes); if ($action eq 'quotas') { $context = 'tools'; - } else { + } else { $context = $action; } if ($context eq 'requestcourses') { @@ -5739,7 +5895,7 @@ sub modify_quotas { &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); $resulttext = &mt('Changes made:').'
      '; - unless (($context eq 'requestcourses') || + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { if (ref($changes{'defaultquota'}) eq 'HASH') { $resulttext .= '
    • '.&mt('Portfolio default quotas').'
        '; @@ -5760,7 +5916,7 @@ sub modify_quotas { my (%haschgs,%inconf); if ($context eq 'requestauthor') { %haschgs = %changes; - %inconf = %confhash; + %inconf = %confhash; } else { if (ref($changes{$item}) eq 'HASH') { %haschgs = %{$changes{$item}}; @@ -5774,7 +5930,7 @@ sub modify_quotas { &Apache::lonnet::usertools_access($env{'user.name'}, $env{'user.domain'}, $item,'reload',$context); - if (($context eq 'requestcourses') || + if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { if ($env{'environment.canrequest.'.$item} ne $newacc) { $newenv{'environment.canrequest.'.$item} = $newacc; @@ -5808,6 +5964,10 @@ sub modify_quotas { $cond = $conditions{$inconf{$type}}; } $resulttext .= '
      • '.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'
      • '; + } elsif ($context eq 'requestauthor') { + $resulttext .= '
      • '.&mt('Set to "[_1]" for "[_2]".', + $titles{$inconf{$type}},$typetitle); + } else { $resulttext .= '
      • '.&mt('Set to be available to [_1]',$typetitle).'
      • '; } @@ -6181,13 +6341,16 @@ sub modify_autocreate { foreach my $item (@types) { if ($changes{$item}) { my $newtxt = $offon[$newvals{$item}]; - $resulttext .= '
      • '.&mt("$title{$item} set to [_1]$newtxt [_2]",'','').'
      • '; + $resulttext .= '
      • '. + &mt("$title{$item} set to [_1]$newtxt [_2]", + '',''). + '
      • '; } } if ($changes{'xmldc'}) { my ($dcname,$dcdom) = split(':',$newvals{'xmldc'}); my $newtxt = &Apache::loncommon::plainname($dcname,$dcdom); - $resulttext .= '
      • '.&mt("$title{'xmldc'} set to [_1]$newtxt [_2]",'','').'
      • '; + $resulttext .= '
      • '.&mt("$title{'xmldc'} set to [_1]",''.$newtxt.'').'
      • '; } $resulttext .= '
      '; } else { @@ -6333,7 +6496,11 @@ sub modify_directorysrch { } else { $chgtext =~ s/\; $//; } - $resulttext .= '
    • '.&mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",$dom,$chgtext).'
    • '; + $resulttext .= + '
    • '. + &mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]", + ''.$dom.'',$chgtext). + '
    • '; } } } @@ -6361,7 +6528,7 @@ sub modify_directorysrch { } } $chgtext =~ s/\; $//; - $resulttext .= '
    • '.&mt("$title{'searchtypes'} set to: \"[_1]\"",$chgtext).'
    • '; + $resulttext .= '
    • '.&mt($title{'searchtypes'}.' set to: "[_1]"',$chgtext).'
    • '; } $resulttext .= '
    '; } else { @@ -6795,7 +6962,7 @@ sub modify_usercreation { if ($captchas{$cancreate{$type}}) { $chgtext .= &mt("Validation for self-creation screen set to $captchas{$cancreate{$type}}."); } else { - $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); + $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); } } } elsif ($type eq 'recaptchakeys') { @@ -6923,7 +7090,7 @@ sub process_captcha { $newsettings->{'captcha'} = 'original'; } if ($current->{'captcha'} ne $newsettings->{'captcha'}) { - if ($container eq 'cancreate') { + if ($container eq 'cancreate') { if (ref($changes->{'cancreate'}) eq 'ARRAY') { push(@{$changes->{'cancreate'}},'captcha'); } elsif (!defined($changes->{'cancreate'})) { @@ -6947,10 +7114,12 @@ sub process_captcha { if (ref($current->{'recaptchakeys'}) eq 'HASH') { $currpub = $current->{'recaptchakeys'}{'public'}; $currpriv = $current->{'recaptchakeys'}{'private'}; - $newsettings->{'recaptchakeys'} = { - public => '', - private => '', - } + unless ($newsettings->{'captcha'} eq 'recaptcha') { + $newsettings->{'recaptchakeys'} = { + public => '', + private => '', + } + } } if (($newpub ne $currpub) || ($newpriv ne $currpriv)) { if ($container eq 'cancreate') { @@ -6960,7 +7129,7 @@ sub process_captcha { $changes->{'cancreate'} = ['recaptchakeys']; } } else { - $changes->{'recaptchakeys'} = 1; + $changes->{'recaptchakeys'} = 1; } } return; @@ -7644,8 +7813,8 @@ sub modify_helpsettings { } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) { $changes{$item} = 1; } - } - if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) { + } + if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) { $helphash{'helpsettings'}{$item} = $env{'form.'.$item}; } } @@ -8036,186 +8205,192 @@ sub modify_loadbalancing { my @sparestypes = ('primary','default'); my %typetitles = &sparestype_titles(); my $resulttext; - if (keys(%servers) > 1) { - my ($currbalancer,$currtargets,$currrules); - if (ref($domconfig{'loadbalancing'}) eq 'HASH') { - $currbalancer = $domconfig{'loadbalancing'}{'lonhost'}; - $currtargets = $domconfig{'loadbalancing'}{'targets'}; - $currrules = $domconfig{'loadbalancing'}{'rules'}; - } else { - ($currbalancer,$currtargets) = - &Apache::lonnet::get_lonbalancer_config(\%servers); - } - my ($saveloadbalancing,%defaultshash,%changes); - my ($alltypes,$othertypes,$titles) = - &loadbalancing_titles($dom,$intdom,$usertypes,$types); - my %ruletitles = &offloadtype_text(); - my $balancer = $env{'form.loadbalancing_lonhost'}; - if (!$servers{$balancer}) { - undef($balancer); - } - if ($currbalancer ne $balancer) { - $changes{'lonhost'} = 1; - } - $defaultshash{'loadbalancing'}{'lonhost'} = $balancer; - if ($balancer ne '') { - unless (ref($domconfig{'loadbalancing'}) eq 'HASH') { - $saveloadbalancing = 1; + my (%currbalancer,%currtargets,%currrules,%existing); + if (ref($domconfig{'loadbalancing'}) eq 'HASH') { + %existing = %{$domconfig{'loadbalancing'}}; + } + &get_loadbalancers_config(\%servers,\%existing,\%currbalancer, + \%currtargets,\%currrules); + my ($saveloadbalancing,%defaultshash,%changes); + my ($alltypes,$othertypes,$titles) = + &loadbalancing_titles($dom,$intdom,$usertypes,$types); + my %ruletitles = &offloadtype_text(); + my @deletions = &Apache::loncommon::get_env_multiple('form.loadbalancing_delete'); + for (my $i=0; $i<$env{'form.loadbalancing_total'}; $i++) { + my $balancer = $env{'form.loadbalancing_lonhost_'.$i}; + if ($balancer eq '') { + next; + } + if (!exists($servers{$balancer})) { + if (exists($currbalancer{$balancer})) { + push(@{$changes{'delete'}},$balancer); } - foreach my $sparetype (@sparestypes) { - my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$sparetype); - my @offloadto; - foreach my $target (@targets) { - if (($servers{$target}) && ($target ne $balancer)) { - if ($sparetype eq 'default') { - if (ref($defaultshash{'loadbalancing'}{'targets'}{'primary'}) eq 'ARRAY') { - next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{'targets'}{'primary'}})); - } - } - unless(grep(/^\Q$target\E$/,@offloadto)) { - push(@offloadto,$target); + next; + } + if ((@deletions > 0) && (grep(/^\Q$i\E$/,@deletions))) { + push(@{$changes{'delete'}},$balancer); + next; + } + if (!exists($currbalancer{$balancer})) { + push(@{$changes{'add'}},$balancer); + } + $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'} = []; + $defaultshash{'loadbalancing'}{$balancer}{'targets'}{'default'} = []; + $defaultshash{'loadbalancing'}{$balancer}{'rules'} = {}; + unless (ref($domconfig{'loadbalancing'}) eq 'HASH') { + $saveloadbalancing = 1; + } + foreach my $sparetype (@sparestypes) { + my @targets = &Apache::loncommon::get_env_multiple('form.loadbalancing_target_'.$i.'_'.$sparetype); + my @offloadto; + foreach my $target (@targets) { + if (($servers{$target}) && ($target ne $balancer)) { + if ($sparetype eq 'default') { + if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}) eq 'ARRAY') { + next if (grep(/^\Q$target\E$/,@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{'primary'}})); } } - $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = \@offloadto; + unless(grep(/^\Q$target\E$/,@offloadto)) { + push(@offloadto,$target); + } } - } - } else { - foreach my $sparetype (@sparestypes) { - $defaultshash{'loadbalancing'}{'targets'}{$sparetype} = []; + $defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype} = \@offloadto; } } - if (ref($currtargets) eq 'HASH') { + if (ref($currtargets{$balancer}) eq 'HASH') { foreach my $sparetype (@sparestypes) { - if (ref($currtargets->{$sparetype}) eq 'ARRAY') { - my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets->{$sparetype},$defaultshash{'loadbalancing'}{'targets'}{$sparetype}); + if (ref($currtargets{$balancer}{$sparetype}) eq 'ARRAY') { + my @targetdiffs = &Apache::loncommon::compare_arrays($currtargets{$balancer}{$sparetype},$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}); if (@targetdiffs > 0) { - $changes{'targets'} = 1; + $changes{'curr'}{$balancer}{'targets'} = 1; } - } elsif (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') { - if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) { - $changes{'targets'} = 1; + } elsif (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') { + if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) { + $changes{'curr'}{$balancer}{'targets'} = 1; } } } } else { - foreach my $sparetype (@sparestypes) { - if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') { - if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) { - $changes{'targets'} = 1; + if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') { + foreach my $sparetype (@sparestypes) { + if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') { + if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) { + $changes{'curr'}{$balancer}{'targets'} = 1; + } } } } } my $ishomedom; - if ($balancer ne '') { - if (&Apache::lonnet::host_domain($balancer) eq $dom) { - $ishomedom = 1; - } + if (&Apache::lonnet::host_domain($balancer) eq $dom) { + $ishomedom = 1; } if (ref($alltypes) eq 'ARRAY') { foreach my $type (@{$alltypes}) { my $rule; - if ($balancer ne '') { - unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && + unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && (!$ishomedom)) { - $rule = $env{'form.loadbalancing_rules_'.$type}; - } - if ($rule eq 'specific') { - $rule = $env{'form.loadbalancing_singleserver_'.$type}; - } + $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type}; } - $defaultshash{'loadbalancing'}{'rules'}{$type} = $rule; - if (ref($currrules) eq 'HASH') { - if ($rule ne $currrules->{$type}) { - $changes{'rules'}{$type} = 1; + if ($rule eq 'specific') { + $rule = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type}; + } + $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type} = $rule; + if (ref($currrules{$balancer}) eq 'HASH') { + if ($rule ne $currrules{$balancer}{$type}) { + $changes{'curr'}{$balancer}{'rules'}{$type} = 1; } } elsif ($rule ne '') { - $changes{'rules'}{$type} = 1; + $changes{'curr'}{$balancer}{'rules'}{$type} = 1; } } } - my $nochgmsg = &mt('No changes made to Load Balancer settings.'); - if ((keys(%changes) > 0) || ($saveloadbalancing)) { - my $putresult = &Apache::lonnet::put_dom('configuration', - \%defaultshash,$dom); - if ($putresult eq 'ok') { - if (keys(%changes) > 0) { - if ($changes{'lonhost'}) { - if ($currbalancer ne '') { - &Apache::lonnet::remote_devalidate_cache($currbalancer,'loadbalancing',$dom); - } - if ($balancer eq '') { - $resulttext .= '
  • '.&mt('Load Balancing with dedicated server discontinued').'
  • '; - } else { - &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); - $resulttext .= '
  • '.&mt('Dedicated Load Balancer server set to [_1]',$balancer); - } - } else { + } + my $nochgmsg = &mt('No changes made to Load Balancer settings.'); + if ((keys(%changes) > 0) || ($saveloadbalancing)) { + unless (ref($defaultshash{'loadbalancing'}) eq 'HASH') { + $defaultshash{'loadbalancing'} = {}; + } + my $putresult = &Apache::lonnet::put_dom('configuration', + \%defaultshash,$dom); + + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + if (ref($changes{'delete'}) eq 'ARRAY') { + foreach my $balancer (sort(@{$changes{'delete'}})) { + $resulttext .= '
  • '.&mt('Load Balancing discontinued for: [_1]',$balancer).'
  • '; &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); } - if (($changes{'targets'}) && ($balancer ne '')) { - my %offloadstr; - foreach my $sparetype (@sparestypes) { - if (ref($defaultshash{'loadbalancing'}{'targets'}{$sparetype}) eq 'ARRAY') { - if (@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}} > 0) { - $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{'targets'}{$sparetype}}); + } + if (ref($changes{'add'}) eq 'ARRAY') { + foreach my $balancer (sort(@{$changes{'add'}})) { + $resulttext .= '
  • '.&mt('Load Balancing enabled for: [_1]',$balancer); + } + } + if (ref($changes{'curr'}) eq 'HASH') { + foreach my $balancer (sort(keys(%{$changes{'curr'}}))) { + if (ref($changes{'curr'}{$balancer}) eq 'HASH') { + if ($changes{'curr'}{$balancer}{'targets'}) { + my %offloadstr; + foreach my $sparetype (@sparestypes) { + if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') { + if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) { + $offloadstr{$sparetype} = join(', ',@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}}); + } + } } - } - } - if (keys(%offloadstr) == 0) { - $resulttext .= '
  • '.&mt("Servers to which Load Balance server offloads set to 'None', by default").'
  • '; - } else { - my $showoffload; - foreach my $sparetype (@sparestypes) { - $showoffload .= ''.$typetitles{$sparetype}.': '; - if (defined($offloadstr{$sparetype})) { - $showoffload .= $offloadstr{$sparetype}; + if (keys(%offloadstr) == 0) { + $resulttext .= '
  • '.&mt("Servers to which Load Balance server offloads set to 'None', by default").'
  • '; } else { - $showoffload .= &mt('None'); + my $showoffload; + foreach my $sparetype (@sparestypes) { + $showoffload .= ''.$typetitles{$sparetype}.': '; + if (defined($offloadstr{$sparetype})) { + $showoffload .= $offloadstr{$sparetype}; + } else { + $showoffload .= &mt('None'); + } + $showoffload .= (' 'x3); + } + $resulttext .= '
  • '.&mt('By default, Load Balancer: [_1] set to offload to - [_2]',$balancer,$showoffload).'
  • '; } - $showoffload .= (' 'x3); } - $resulttext .= '
  • '.&mt('By default, Load Balancer server set to offload to: [_1]',$showoffload).'
  • '; } - } - if ((ref($changes{'rules'}) eq 'HASH') && ($balancer ne '')) { - if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) { - foreach my $type (@{$alltypes}) { - if ($changes{'rules'}{$type}) { - my $rule = $defaultshash{'loadbalancing'}{'rules'}{$type}; - my $balancetext; - if ($rule eq '') { - $balancetext = $ruletitles{'default'}; - } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) { - $balancetext = $ruletitles{$rule}; - } else { - $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{'rules'}{$type}); + if (ref($changes{'curr'}{$balancer}{'rules'}) eq 'HASH') { + if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) { + foreach my $type (@{$alltypes}) { + if ($changes{'curr'}{$balancer}{'rules'}{$type}) { + my $rule = $defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type}; + my $balancetext; + if ($rule eq '') { + $balancetext = $ruletitles{'default'}; + } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) { + $balancetext = $ruletitles{$rule}; + } else { + $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type}); + } + $resulttext .= '
  • '.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'
  • '; } - $resulttext .= '
  • '.&mt('Load Balancing for [_1] set to: [_2]',$titles->{$type},$balancetext).'
  • '; } } } + &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); } - if ($resulttext ne '') { - $resulttext = &mt('Changes made:').'
      '.$resulttext.'
    '; - } else { - $resulttext = $nochgmsg; - } + } + if ($resulttext ne '') { + $resulttext = &mt('Changes made:').'
      '.$resulttext.'
    '; } else { $resulttext = $nochgmsg; - if ($balancer ne '') { - &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); - } } } else { - $resulttext = ''. - &mt('An error occurred: [_1]',$putresult).''; + $resulttext = $nochgmsg; } } else { - $resulttext = $nochgmsg; + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; } } else { - $resulttext = &mt('Load Balancing unavailable as this domain only has one server.'); + $resulttext = $nochgmsg; } return $resulttext; } @@ -8254,7 +8429,7 @@ sub recurse_cat_deletes { delete($coursecategories->{$subitem}); $deletions->{$subitem} = 1; &recurse_cat_deletes($subitem,$coursecategories,$deletions); - } + } } } return; @@ -8320,6 +8495,7 @@ sub active_dc_picker { ''. &Apache::loncommon::plainname($dcname,$dcdom). + ' ('.$dcname.':'.$dcdom.')'. '
    '; } $datatable .= ''; @@ -8371,7 +8547,7 @@ sub count_servers { } sub lonbalance_targets_js { - my ($dom,$types,$servers) = @_; + my ($dom,$types,$servers,$settings) = @_; my $select = &mt('Select'); my ($alltargets,$allishome,$allinsttypes,@alltypes); if (ref($servers) eq 'HASH') { @@ -8393,39 +8569,71 @@ sub lonbalance_targets_js { } push(@alltypes,'default','_LC_adv','_LC_author','_LC_internetdom','_LC_external'); $allinsttypes = join("','",@alltypes); + my (%currbalancer,%currtargets,%currrules,%existing); + if (ref($settings) eq 'HASH') { + %existing = %{$settings}; + } + &get_loadbalancers_config($servers,\%existing,\%currbalancer, + \%currtargets,\%currrules); + my $balancers = join("','",sort(keys(%currbalancer))); return <<"END";