--- loncom/interface/domainprefs.pm 2015/05/21 22:59:16 1.264 +++ loncom/interface/domainprefs.pm 2016/07/25 19:50:30 1.275 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.264 2015/05/21 22:59:16 raeburn Exp $ +# $Id: domainprefs.pm,v 1.275 2016/07/25 19:50:30 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -103,8 +103,8 @@ $datatable - HTML containing form eleme In the case of course requests, radio buttons are displayed for each institutional affiliate type (and also default, and _LC_adv) for each of the course types -(official, unofficial, community, and textbook). In each case the radio buttons -allow the selection of one of four values: +(official, unofficial, community, textbook, and placement). +In each case the radio buttons allow the selection of one of four values: 0, approval, validate, autolimit=N (where N is blank, or a positive integer). which have the following effects: @@ -169,10 +169,12 @@ use Apache::loncoursequeueadmin(); use LONCAPA qw(:DEFAULT :match); use LONCAPA::Enrollment; use LONCAPA::lonauthcgi(); +use LONCAPA::SSL; use File::Copy; use Locale::Language; use DateTime::TimeZone; use DateTime::Locale; +use Time::HiRes qw( sleep ); my $registered_cleanup; my $modified_urls; @@ -215,13 +217,14 @@ sub handler { 'contacts','defaults','scantron','coursecategories', 'serverstatuses','requestcourses','helpsettings', 'coursedefaults','usersessions','loadbalancing', - 'requestauthor','selfenrollment','inststatus'],$dom); + 'requestauthor','selfenrollment','inststatus', + 'ltitools','ssl'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','autocreate','directorysrch','contacts', 'usercreation','selfcreation','usermodification','scantron', 'requestcourses','requestauthor','coursecategories', - 'serverstatuses','helpsettings', - 'coursedefaults','selfenrollment','usersessions'); + 'serverstatuses','helpsettings','coursedefaults', + 'ltitools','selfenrollment','usersessions','ssl'); my %existing; if (ref($domconfig{'loadbalancing'}) eq 'HASH') { %existing = %{$domconfig{'loadbalancing'}}; @@ -472,6 +475,26 @@ sub handler { print => \&print_loadbalancing, modify => \&modify_loadbalancing, }, + 'ltitools' => + {text => 'External Tools (LTI)', + help => 'Domain_configuration_LTI_Tools', + header => [{col1 => 'Setting', + col2 => 'Value',}], + print => \&print_ltitools, + modify => \&modify_ltitools, + }, + 'ssl' => + {text => 'LON-CAPA Network (SSL)', + help => 'Domain_Configuration_Network_SSL', + header => [{col1 => 'Server', + col2 => 'Certificate Status'}, + {col1 => 'Connections to other servers', + col2 => 'Rules'}, + {col1 => "Replicating domain's published content", + col2 => 'Rules'}], + print => \&print_ssl, + modify => \&modify_ssl, + }, ); if (keys(%servers) > 1) { $prefs{'login'} = { text => 'Log-in page options', @@ -645,6 +668,10 @@ sub process_changes { $output = &modify_usersessions($dom,$lastactref,%domconfig); } elsif ($action eq 'loadbalancing') { $output = &modify_loadbalancing($dom,%domconfig); + } elsif ($action eq 'ltitools') { + $output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig); + } elsif ($action eq 'ssl') { + $output = &modify_ssl($dom,$lastactref,%domconfig); } return $output; } @@ -691,7 +718,7 @@ sub print_config_box { $rowtotal ++; if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') || ($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') || - ($action eq 'selfenrollment') || ($action eq 'usersessions')) { + ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl')) { $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'coursecategories') { $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal); @@ -721,7 +748,8 @@ sub print_config_box { $rowtotal ++; if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') || ($action eq 'selfenrollment') || - ($action eq 'usersessions') || ($action eq 'coursecategories')) { + ($action eq 'usersessions') || ($action eq 'coursecategories') || + ($action eq 'ssl')) { if ($action eq 'coursecategories') { $output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal); $colspan = ' colspan="2"'; @@ -904,7 +932,8 @@ sub print_config_box { if ($action eq 'quotas') { $output .= &print_quotas($dom,$settings,\$rowtotal,$action); } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || ($action eq 'directorysrch') || - ($action eq 'contacts') || ($action eq 'serverstatuses') || ($action eq 'loadbalancing')) { + ($action eq 'contacts') || ($action eq 'serverstatuses') || ($action eq 'loadbalancing') || + ($action eq 'ltitools')) { $output .= $item->{'print'}->($dom,$settings,\$rowtotal); } elsif ($action eq 'scantron') { $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal); @@ -1710,7 +1739,7 @@ sub print_quotas { my $typecount = 0; my ($css_class,%titles); if ($context eq 'requestcourses') { - @usertools = ('official','unofficial','community','textbook'); + @usertools = ('official','unofficial','community','textbook','placement'); @options =('norequest','approval','validate','autolimit'); %validations = &Apache::lonnet::auto_courserequest_checks($dom); %titles = &courserequest_titles(); @@ -2162,7 +2191,7 @@ sub print_studentcode { my ($settings,$rowtotal) = @_; my $rownum = 0; my ($output,%current); - my @crstypes = ('official','unofficial','community','textbook'); + my @crstypes = ('official','unofficial','community','textbook','placement'); if (ref($settings) eq 'HASH') { if (ref($settings->{'uniquecode'}) eq 'HASH') { foreach my $type (@crstypes) { @@ -2258,8 +2287,7 @@ sub print_textbookcourses { (' 'x2). ''.&mt('Thumbnail:'); if ($image) { - $datatable .= ''. - $imgsrc. + $datatable .= $imgsrc. ' '. ' '.&mt('Replace:').' '; @@ -2413,10 +2441,78 @@ $jstext{'templates'}; ENDSCRIPT } +sub ltitools_javascript { + my ($settings) = @_; + return unless(ref($settings) eq 'HASH'); + my (%ordered,$total,%jstext); + $total = 0; + foreach my $item (keys(%{$settings})) { + if (ref($settings->{$item}) eq 'HASH') { + my $num = $settings->{$item}{'order'}; + $ordered{$num} = $item; + } + } + $total = scalar(keys(%{$settings})); + my @jsarray = (); + foreach my $item (sort {$a <=> $b } (keys(%ordered))) { + push(@jsarray,$ordered{$item}); + } + my $jstext = ' var ltitools = Array('."'".join("','",@jsarray)."'".');'."\n"; + return <<"ENDSCRIPT"; + + +ENDSCRIPT +} + sub print_autoenroll { my ($dom,$settings,$rowtotal) = @_; my $autorun = &Apache::lonnet::auto_run(undef,$dom), - my ($defdom,$runon,$runoff,$coownerson,$coownersoff); + my ($defdom,$runon,$runoff,$coownerson,$coownersoff,$failsafe); if (ref($settings) eq 'HASH') { if (exists($settings->{'run'})) { if ($settings->{'run'} eq '0') { @@ -2450,6 +2546,9 @@ sub print_autoenroll { if (exists($settings->{'sender_domain'})) { $defdom = $settings->{'sender_domain'}; } + if (exists($settings->{'autofailsafe'})) { + $failsafe = $settings->{'autofailsafe'}; + } } else { if ($autorun) { $runon = ' checked="checked" '; @@ -2485,8 +2584,12 @@ sub print_autoenroll { $coownerson.' value="1" />'.&mt('Yes').' '. ''. - ''; - $$rowtotal += 3; + ''. + ''.&mt('Failsafe for no drops when institutional data missing').''. + ''. + ''; + $$rowtotal += 4; return $datatable; } @@ -2898,6 +3001,352 @@ sub radiobutton_prefs { return ($datatable,$itemcount); } +sub print_ltitools { + my ($dom,$settings,$rowtotal) = @_; + my $rownum = 0; + my $css_class; + my $itemcount = 1; + my $maxnum = 0; + my %ordered; + if (ref($settings) eq 'HASH') { + foreach my $item (keys(%{$settings})) { + if (ref($settings->{$item}) eq 'HASH') { + my $num = $settings->{$item}{'order'}; + $ordered{$num} = $item; + } + } + } + my $confname = $dom.'-domainconfig'; + my $switchserver = &check_switchserver($dom,$confname); + my $maxnum = scalar(keys(%ordered)); + my $datatable = <itools_javascript($settings); + my %lt = <itools_names(); + my @courseroles = ('cc','in','ta','ep','st'); + my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner); + my @fields = ('fullname','firstname','lastname','email','user','roles'); + if (keys(%ordered)) { + my @items = sort { $a <=> $b } keys(%ordered); + for (my $i=0; $i<@items; $i++) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $item = $ordered{$items[$i]}; + my ($title,$key,$secret,$url,$imgsrc,$version); + if (ref($settings->{$item}) eq 'HASH') { + $title = $settings->{$item}->{'title'}; + $url = $settings->{$item}->{'url'}; + $key = $settings->{$item}->{'key'}; + $secret = $settings->{$item}->{'secret'}; + my $image = $settings->{$item}->{'image'}; + if ($image ne '') { + $imgsrc = ''.&mt('Tool Provider icon').''; + } + } + my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"'; + $datatable .= '' + .''.(' 'x2). + ''. + ''. + '
'.&mt('Required settings').''. + ''.$lt{'title'}.': '. + (' 'x2). + ''.$lt{'version'}.': '. + (' 'x2). + ''.$lt{'msgtype'}.': '. + '

'. + ''.$lt{'url'}.':'. + (' 'x2). + ''.$lt{'key'}. + ' '. + (' 'x2). + ''.$lt{'secret'}.':'. + ''. + ''. + ''. + '
'. + '
'.&mt('Optional settings').''. + ''.&mt('Display target:'); + my %currdisp; + if (ref($settings->{$item}->{'display'}) eq 'HASH') { + if ($settings->{$item}->{'display'}->{'target'} eq 'window') { + $currdisp{'window'} = ' checked="checked"'; + } else { + $currdisp{'iframe'} = ' checked="checked"'; + } + if ($settings->{$item}->{'display'}->{'width'} =~ /^(\d+)$/) { + $currdisp{'width'} = $1; + } + if ($settings->{$item}->{'display'}->{'height'} =~ /^(\d+)$/) { + $currdisp{'height'} = $1; + } + } else { + $currdisp{'iframe'} = ' checked="checked"'; + } + foreach my $disp ('iframe','window') { + $datatable .= ''.(' 'x2); + } + $datatable .= (' 'x4); + foreach my $dimen ('width','height') { + $datatable .= ''. + (' 'x2); + } + $datatable .= '
'; + foreach my $extra ('passback','roster') { + my $checkedon = ''; + my $checkedoff = ' checked="checked"'; + if ($settings->{$item}->{$extra}) { + $checkedon = $checkedoff; + $checkedoff = ''; + } + $datatable .= $lt{$extra}.' '. + ''.(' 'x2). + ''.(' 'x4); + } + $datatable .= '

'.$lt{'icon'}.': '; + if ($imgsrc) { + $datatable .= $imgsrc. + ' '. + ' '.&mt('Replace:').' '; + } else { + $datatable .= '('.&mt('if larger than 21x21 pixels, image will be scaled').') '; + } + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; + } + $datatable .= '
'; + my (%checkedfields,%rolemaps); + if (ref($settings->{$item}) eq 'HASH') { + if (ref($settings->{$item}->{'fields'}) eq 'HASH') { + %checkedfields = %{$settings->{$item}->{'fields'}}; + } + if (ref($settings->{$item}->{'roles'}) eq 'HASH') { + %rolemaps = %{$settings->{$item}->{'roles'}}; + $checkedfields{'roles'} = 1; + } + } + $datatable .= '
'.&mt('User data sent on launch').''. + ''; + foreach my $field (@fields) { + my $checked; + if ($checkedfields{$field}) { + $checked = ' checked="checked"'; + } + $datatable .= ''.(' ' x2); + } + $datatable .= '
'. + '
'.&mt('Role mapping').''; + foreach my $role (@courseroles) { + my ($selected,$selectnone); + if (!$rolemaps{$role}) { + $selectnone = ' selected="selected"'; + } + $datatable .= ''; + } + $datatable .= '
'. + &Apache::lonnet::plaintext($role,'Course').'
'. + '
'; + my %courseconfig; + if (ref($settings->{$item}) eq 'HASH') { + if (ref($settings->{$item}->{'crsconf'}) eq 'HASH') { + %courseconfig = %{$settings->{$item}->{'crsconf'}}; + } + } + $datatable .= '
'.&mt('Configurable in course').''; + foreach my $item ('label','title','target') { + my $checked; + if ($courseconfig{$item}) { + $checked = ' checked="checked"'; + } + $datatable .= ''.(' ' x2)."\n"; + } + $datatable .= '
'. + '
'.&mt('Custom items sent on launch').''. + ''; + if (ref($settings->{$item}->{'custom'}) eq 'HASH') { + my %custom = %{$settings->{$item}->{'custom'}}; + if (keys(%custom) > 0) { + foreach my $key (sort(keys(%custom))) { + $datatable .= ''. + ''; + } + } + } + $datatable .= ''; + $datatable .= '
'.&mt('Action').''.&mt('Name').''.&mt('Value').'
'. + ''.$key.'
'. + ''. + '
'."\n"; + $itemcount ++; + } + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"'; + $datatable .= ''."\n". + ''."\n". + ' '."\n". + ''.&mt('Add').''."\n". + ''. + '
'.&mt('Required settings').''. + ''.$lt{'title'}.': '."\n". + (' 'x2). + ''.$lt{'version'}.': '."\n". + (' 'x2). + ''.$lt{'msgtype'}.': '. + '
'. + ''.$lt{'url'}.': '."\n". + (' 'x2). + ''.$lt{'key'}.': '."\n". + (' 'x2). + ''.$lt{'secret'}.':'. + ' '."\n". + '
'. + '
'.&mt('Optional settings').''. + ''.&mt('Display target:'); + my %defaultdisp; + $defaultdisp{'iframe'} = ' checked="checked"'; + foreach my $disp ('iframe','window') { + $datatable .= ''.(' 'x2); + } + $datatable .= (' 'x4); + foreach my $dimen ('width','height') { + $datatable .= ''. + (' 'x2); + } + $datatable .= '
'; + foreach my $extra ('passback','roster') { + $datatable .= $lt{$extra}.' '. + ''.(' 'x2). + ''.(' 'x4); + } + $datatable .= '

'.$lt{'icon'}.': '. + '('.&mt('if larger than 21x21 pixels, image will be scaled').') '; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; + } + $datatable .= '
'. + '
'.&mt('User data sent on launch').''. + ''; + foreach my $field (@fields) { + $datatable .= ''.(' ' x2); + } + $datatable .= '
'. + '
'.&mt('Role mapping').''; + foreach my $role (@courseroles) { + my ($checked,$checkednone); + $datatable .= ''; + } + $datatable .= '
'. + &Apache::lonnet::plaintext($role,'Course').'
'. + '
'. + '
'.&mt('Configurable in course').''; + foreach my $item ('label','title','target') { + $datatable .= ''.(' ' x2)."\n"; + } + $datatable .= '
'. + '
'.&mt('Custom items sent on launch').''. + ''. + ''. + '
'.&mt('Action').''.&mt('Name').''.&mt('Value').'
'. + ''. + '
'."\n". + ''."\n". + ''."\n"; + $itemcount ++; + return $datatable; +} + +sub ltitools_names { + my %lt = &Apache::lonlocal::texthash( + 'title' => 'Title', + 'version' => 'Version', + 'msgtype' => 'Message Type', + 'url' => 'URL', + 'key' => 'Key', + 'secret' => 'Secret', + 'icon' => 'Icon', + 'user' => 'Username:domain', + 'fullname' => 'Full Name', + 'firstname' => 'First Name', + 'lastname' => 'Last Name', + 'email' => 'E-mail', + 'roles' => 'Role', + 'window' => 'Window/Tab', + 'iframe' => 'iFrame', + 'height' => 'Height', + 'width' => 'Width', + 'passback' => 'Tool can return grades:', + 'roster' => 'Tool can retrieve roster:', + 'crstarget' => 'Display target', + 'crslabel' => 'Course label', + 'crstitle' => 'Course title', + ); + return %lt; +} + sub print_coursedefaults { my ($position,$dom,$settings,$rowtotal) = @_; my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles); @@ -3003,7 +3452,7 @@ sub print_coursedefaults { my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout); my $currusecredits = 0; my $postsubmitclient = 1; - my @types = ('official','unofficial','community','textbook'); + my @types = ('official','unofficial','community','textbook','placement'); if (ref($settings) eq 'HASH') { $currdefresponder = $settings->{'anonsurvey_threshold'}; if (ref($settings->{'uploadquota'}) eq 'HASH') { @@ -3137,7 +3586,7 @@ sub print_selfenrollment { my ($position,$dom,$settings,$rowtotal) = @_; my ($css_class,$datatable); my $itemcount = 1; - my @types = ('official','unofficial','community','textbook'); + my @types = ('official','unofficial','community','textbook','placement'); if (($position eq 'top') || ($position eq 'middle')) { my ($rowsref,$titlesref) = &Apache::lonuserutils::get_selfenroll_titles(); my %descs = &Apache::lonuserutils::selfenroll_default_descs(); @@ -3361,8 +3810,8 @@ sub print_validation_rows { sub print_usersessions { my ($position,$dom,$settings,$rowtotal) = @_; my ($css_class,$datatable,%checked,%choices); - my (%by_ip,%by_location,@intdoms); - &build_location_hashes(\@intdoms,\%by_ip,\%by_location); + my (%by_ip,%by_location,@intdoms,@instdoms); + &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms); my @alldoms = &Apache::lonnet::all_domains(); my %serverhomes = %Apache::lonnet::serverhomeIDs; @@ -3500,10 +3949,178 @@ sub print_usersessions { return $datatable; } +sub print_ssl { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + my $lonhost = ''; + my $itemcount = 1; + if ($position eq 'top') { + my %domservers = &Apache::lonnet::get_servers($dom); + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''. + &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs'). + ''; + $itemcount ++; + } else { + my %titles = &ssl_titles(); + my (%by_ip,%by_location,@intdoms,@instdoms); + &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms); + my @alldoms = &Apache::lonnet::all_domains(); + my %serverhomes = %Apache::lonnet::serverhomeIDs; + my @domservers = &Apache::lonnet::get_servers($dom); + my %servers = &Apache::lonnet::internet_dom_servers($dom); + my %altids = &id_for_thisdom(%servers); + if ($position eq 'middle') { + foreach my $type ('dom','intdom','other') { + my %checked; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''.$titles{$type}.''. + ''; + my $skip; + if ($type eq 'dom') { + unless (keys(%servers) > 1) { + $datatable .= &mt('Nothing to set here, as there are no other servers/VMs'); + $skip = 1; + } + } + if ($type eq 'intdom') { + unless (@instdoms > 1) { + $datatable .= &mt('Nothing to set here, as there are no other domains for this institution'); + $skip = 1; + } + } elsif ($type eq 'other') { + if (keys(%by_location) == 0) { + $datatable .= &mt('Nothing to set here, as there are no other institutions'); + $skip = 1; + } + } + unless ($skip) { + $checked{'yes'} = ' checked="checked"'; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'connect'}) eq 'HASH') { + if ($settings->{'connect'}->{$type} =~ /^(no|req)$/) { + $checked{$1} = $checked{'yes'}; + delete($checked{'yes'}); + } + } + } + foreach my $option ('no','yes','req') { + $datatable .= ''.(' 'x2); + } + } + $datatable .= ''; + $itemcount ++; + } + } else { + my $numinrow = 5; + my $prefix = 'replication'; + my @types = ('certreq','nocertreq'); + my (%current,%checkedon,%checkedoff); + my @locations = sort(keys(%by_location)); + foreach my $type (@types) { + $checkedon{$type} = ''; + $checkedoff{$type} = ' checked="checked"'; + } + if (ref($settings) eq 'HASH') { + if (ref($settings->{$prefix}) eq 'HASH') { + foreach my $key (keys(%{$settings->{$prefix}})) { + $current{$key} = $settings->{$prefix}{$key}; + if (ref($current{$key}) eq 'ARRAY') { + $checkedon{$key} = ' checked="checked"'; + $checkedoff{$key} = ''; + } + } + } + } + if (@locations > 0) { + foreach my $type (@types) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ' + '.$titles{$type}.'
+   +   + +
'.(' 'x2)."\n". + ''. + "\n". + '
'; + my $rem; + for (my $i=0; $i<@locations; $i++) { + my ($showloc,$value,$checkedtype); + if (ref($by_location{$locations[$i]}) eq 'ARRAY') { + my $ip = $by_location{$locations[$i]}->[0]; + if (ref($by_ip{$ip}) eq 'ARRAY') { + $value = join(':',@{$by_ip{$ip}}); + $showloc = join(', ',@{$by_ip{$ip}}); + if (ref($current{$type}) eq 'ARRAY') { + foreach my $loc (@{$by_ip{$ip}}) { + if (grep(/^\Q$loc\E$/,@{$current{$type}})) { + $checkedtype = ' checked="checked"'; + last; + } + } + } + } + } + $rem = $i%($numinrow); + if ($rem == 0) { + if ($i > 0) { + $datatable .= ''; + } + $datatable .= ''; + } + $datatable .= ''; + } + $rem = @locations%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $datatable .= ''; + } elsif ($colsleft == 1) { + $datatable .= ''; + } + $datatable .= '
'. + ''. + '  
'; + $itemcount ++; + } + } else { + $datatable .= ''.&mt('Nothing to set here, as there are no other institutions').''; + $itemcount ++; + } + } + } + $$rowtotal += $itemcount; + return $datatable; +} + +sub ssl_titles { + return &Apache::lonlocal::texthash ( + dom => 'LON-CAPA servers/VMs from same domain', + intdom => 'LON-CAPA servers/VMs from same "internet" domain', + other => 'External LON-CAPA servers/VMs', + connect => 'Connections to other servers', + replication => 'Replicating content to other institutions', + certreq => 'Client certificate required, but specific domains exempt', + nocertreq => 'No client certificate required, except for specific domains', + no => 'SSL not used', + yes => 'SSL Optional (used if available)', + req => 'SSL Required', + ); +} + sub build_location_hashes { - my ($intdoms,$by_ip,$by_location) = @_; + my ($intdoms,$by_ip,$by_location,$instdoms) = @_; return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') && - (ref($by_location) eq 'HASH')); + (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY')); my %iphost = &Apache::lonnet::get_iphost(); my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary'); my $primary_ip = &Apache::lonnet::get_host_ip($primary_id); @@ -3520,7 +4137,13 @@ sub build_location_hashes { foreach my $id (@{$iphost{$ip}}) { my $location = &Apache::lonnet::internet_dom($id); if ($location) { - next if (grep(/^\Q$location\E$/,@{$intdoms})); + if (grep(/^\Q$location\E$/,@{$intdoms})) { + my $dom = &Apache::lonnet::host_domain($id); + unless (grep(/^\Q$dom\E/,@{$instdoms})) { + push(@{$instdoms},$dom); + } + next; + } if (ref($by_ip->{$ip}) eq 'ARRAY') { unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) { push(@{$by_ip->{$ip}},$location); @@ -4156,6 +4779,7 @@ sub tool_titles { unofficial => 'Unofficial courses', community => 'Communities', textbook => 'Textbook courses', + placement => 'Placement tests', ); return %titles; } @@ -4166,6 +4790,7 @@ sub courserequest_titles { unofficial => 'Unofficial', community => 'Communities', textbook => 'Textbook', + placement => 'Placement tests', norequest => 'Not allowed', approval => 'Approval by Dom. Coord.', validate => 'With validation', @@ -4555,7 +5180,8 @@ sub email_as_username { sub captcha_choice { my ($context,$settings,$itemcount) = @_; - my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext); + my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext, + $vertext,$currver); my %lt = &captcha_phrases(); $keyentry = 'hidden'; if ($context eq 'cancreate') { @@ -4573,6 +5199,11 @@ sub captcha_choice { $pubtext = $lt{'pub'}; $privtext = $lt{'priv'}; $keyentry = 'text'; + $vertext = $lt{'ver'}; + $currver = $settings->{'recaptchaversion'}; + if ($currver ne '2') { + $currver = 1; + } } if (ref($settings->{'recaptchakeys'}) eq 'HASH') { $currpub = $settings->{'recaptchakeys'}{'public'}; @@ -4606,7 +5237,11 @@ sub captcha_choice { $currpub.'" size="40" />
'."\n". ''.$privtext.' '."\n". ''."\n". + $currpriv.'" size="40" />
'. + ''.$vertext.' '."\n". + '
'. + ''."\n". ''; return $output; } @@ -5140,6 +5775,10 @@ sub print_coursecategories { my $toggle_catscomm_dom = ' checked="checked" '; my $can_catcomm_comm = ' '; my $can_catcomm_dom = ' checked="checked" '; + my $toggle_catsplace_place = ' '; + my $toggle_catsplace_dom = ' checked="checked" '; + my $can_catplace_place = ' '; + my $can_catplace_dom = ' checked="checked" '; if (ref($settings) eq 'HASH') { if ($settings->{'togglecats'} eq 'crs') { @@ -5158,17 +5797,28 @@ sub print_coursecategories { $can_catcomm_comm = $can_catcomm_dom; $can_catcomm_dom = ' '; } + if ($settings->{'togglecatsplace'} eq 'place') { + $toggle_catsplace_place = $toggle_catsplace_dom; + $toggle_catsplace_dom = ' '; + } + if ($settings->{'categorizeplace'} eq 'place') { + $can_catplace_place = $can_catplace_dom; + $can_catplace_dom = ' '; + } } my %title = &Apache::lonlocal::texthash ( - togglecats => 'Show/Hide a course in catalog', - togglecatscomm => 'Show/Hide a community in catalog', - categorize => 'Assign a category to a course', - categorizecomm => 'Assign a category to a community', + togglecats => 'Show/Hide a course in catalog', + togglecatscomm => 'Show/Hide a community in catalog', + togglecatsplace => 'Show/Hide a placement test in catalog', + categorize => 'Assign a category to a course', + categorizecomm => 'Assign a category to a community', + categorizeplace => 'Assign a category to a placement test', ); my %level = &Apache::lonlocal::texthash ( - dom => 'Set in Domain', - crs => 'Set in Course', - comm => 'Set in Community', + dom => 'Set in Domain', + crs => 'Set in Course', + comm => 'Set in Community', + place => 'Set in Placement Test', ); $datatable = ''. ''.$title{'togglecats'}.''. @@ -5198,8 +5848,22 @@ sub print_coursecategories { $can_catcomm_dom.' value="dom" />'.$level{'dom'}.' '. ''. + ''. + ''.$title{'togglecatsplace'}.''. + ' '. + ''. + ''. + ''.$title{'categorizeplace'}.''. + ''. + ' '. + ''. ''; - $$rowtotal += 4; + $$rowtotal += 6; } else { my $css_class; my $itemcount = 1; @@ -5224,12 +5888,15 @@ sub print_coursecategories { my %default_names = ( instcode => &mt('Official courses'), communities => &mt('Communities'), + placement => &mt('Placement Tests'), ); if ((!grep(/^instcode$/,@{$cats[0]})) || ($cathash->{'instcode::0'} eq '') || (!grep(/^communities$/,@{$cats[0]})) || - ($cathash->{'communities::0'} eq '')) { + ($cathash->{'communities::0'} eq '') || + (!grep(/^placement$/,@{$cats[0]})) || + ($cathash->{'placement::0'} eq '')) { $maxnum ++; } my $lastidx; @@ -5250,7 +5917,7 @@ sub print_coursecategories { $datatable .= ''; } $datatable .= ''; - if ($parent eq 'instcode' || $parent eq 'communities') { + if ($parent eq 'instcode' || $parent eq 'communities' || $parent eq 'placement') { $datatable .= '' .$default_names{$parent}.''; if ($parent eq 'instcode') { @@ -5273,7 +5940,7 @@ sub print_coursecategories { $datatable .= ''; - if ($parent eq 'communities') { + if (($parent eq 'communities') || ($parent eq 'placement')) { $datatable .= ''; } $datatable .= ''; @@ -5305,7 +5972,7 @@ sub print_coursecategories { .'' .''."\n"; $itemcount ++; - foreach my $default ('instcode','communities') { + foreach my $default ('instcode','communities','placement') { if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) { $css_class = $itemcount%2?' class="LC_odd_row"':''; my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"'; @@ -5394,9 +6061,9 @@ sub print_serverstatuses { sub serverstatus_pages { return ('userstatus','lonstatus','loncron','server-status','codeversions', - 'checksums','clusterstatus','metadata_keywords','metadata_harvest', - 'takeoffline','takeonline','showenv','toggledebug','ping','domconf', - 'uniquecodes','diskusage','coursecatalog'); + 'checksums','clusterstatus','certstatus','metadata_keywords', + 'metadata_harvest','takeoffline','takeonline','showenv','toggledebug', + 'ping','domconf','uniquecodes','diskusage','coursecatalog'); } sub defaults_javascript { @@ -5486,7 +6153,12 @@ sub coursecategories_javascript { } my $instcode_reserved = &mt('The name: [_1] is a reserved category.','"instcode"'); my $communities_reserved = &mt('The name: [_1] is a reserved category.','"communities"'); - my $choose_again = '\\n'.&mt('Please use a different name for the new top level category.'); + my $placement_reserved = &mt('The name: [_1] is a reserved category.','"placement"'); + my $choose_again = "\n".&mt('Please use a different name for the new top level category.'); + &js_escape(\$instcode_reserved); + &js_escape(\$communities_reserved); + &js_escape(\$placement_reserved); + &js_escape(\$choose_again); $output = <<"ENDSCRIPT";