--- loncom/interface/domainprefs.pm 2016/09/18 19:24:14 1.160.6.72 +++ loncom/interface/domainprefs.pm 2016/02/19 02:39:07 1.269 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.160.6.72 2016/09/18 19:24:14 raeburn Exp $ +# $Id: domainprefs.pm,v 1.269 2016/02/19 02:39:07 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -173,6 +173,7 @@ use File::Copy; use Locale::Language; use DateTime::TimeZone; use DateTime::Locale; +use Time::HiRes qw( sleep ); my $registered_cleanup; my $modified_urls; @@ -213,15 +214,16 @@ sub handler { 'quotas','autoenroll','autoupdate','autocreate', 'directorysrch','usercreation','usermodification', 'contacts','defaults','scantron','coursecategories', - 'serverstatuses','requestcourses','coursedefaults', - 'usersessions','loadbalancing','requestauthor', - 'selfenrollment','inststatus'],$dom); + 'serverstatuses','requestcourses','helpsettings', + 'coursedefaults','usersessions','loadbalancing', + 'requestauthor','selfenrollment','inststatus', + 'ltitools'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','autocreate','directorysrch','contacts', 'usercreation','selfcreation','usermodification','scantron', 'requestcourses','requestauthor','coursecategories', - 'serverstatuses','coursedefaults','selfenrollment', - 'usersessions'); + 'serverstatuses','helpsettings','coursedefaults', + 'ltitools','selfenrollment','usersessions'); my %existing; if (ref($domconfig{'loadbalancing'}) eq 'HASH') { %existing = %{$domconfig{'loadbalancing'}}; @@ -304,11 +306,9 @@ sub handler { modify => \&modify_autocreate, }, 'directorysrch' => - { text => 'Directory searches', + { text => 'Institutional directory searches', help => 'Domain_Configuration_InstDirectory_Search', - header => [{col1 => 'Institutional Directory Setting', - col2 => 'Value',}, - {col1 => 'LON-CAPA Directory Setting', + header => [{col1 => 'Setting', col2 => 'Value',}], print => \&print_directorysrch, modify => \&modify_directorysrch, @@ -413,6 +413,14 @@ sub handler { print => \&print_serverstatuses, modify => \&modify_serverstatuses, }, + 'helpsettings' => + {text => 'Help page settings', + help => 'Domain_Configuration_Help_Settings', + header => [{col1 => 'Help Settings (logged-in users)', + col2 => 'Value'}], + print => \&print_helpsettings, + modify => \&modify_helpsettings, + }, 'coursedefaults' => {text => 'Course/Community defaults', help => 'Domain_Configuration_Course_Defaults', @@ -435,6 +443,14 @@ sub handler { print => \&print_selfenrollment, modify => \&modify_selfenrollment, }, + 'privacy' => + {text => 'User Privacy', + help => 'Domain_Configuration_User_Privacy', + header => [{col1 => 'Setting', + col2 => 'Value',}], + print => \&print_privacy, + modify => \&modify_privacy, + }, 'usersessions' => {text => 'User session hosting/offloading', help => 'Domain_Configuration_User_Sessions', @@ -458,6 +474,15 @@ 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, + }, + ); if (keys(%servers) > 1) { $prefs{'login'} = { text => 'Log-in page options', @@ -621,6 +646,8 @@ sub process_changes { $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); } elsif ($action eq 'requestauthor') { $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); + } elsif ($action eq 'helpsettings') { + $output = &modify_helpsettings($r,$dom,$confname,%domconfig); } elsif ($action eq 'coursedefaults') { $output = &modify_coursedefaults($dom,$lastactref,%domconfig); } elsif ($action eq 'selfenrollment') { @@ -629,6 +656,8 @@ 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); } return $output; } @@ -658,7 +687,6 @@ sub print_config_box { my $colspan = ''; my $rightcolspan = ''; if (($action eq 'rolecolors') || ($action eq 'defaults') || - ($action eq 'directorysrch') || (($action eq 'login') && ($numheaders < 4))) { $colspan = ' colspan="2"'; } @@ -676,7 +704,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 'directorysrch')) { + ($action eq 'selfenrollment') || ($action eq 'usersessions')) { $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'coursecategories') { $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal); @@ -731,7 +759,7 @@ sub print_config_box { } $rowtotal ++; } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults') || - ($action eq 'defaults') || ($action eq 'directorysrch')) { + ($action eq 'defaults')) { $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); } elsif ($action eq 'login') { if ($numheaders == 4) { @@ -844,7 +872,7 @@ sub print_config_box { '; - if ($action eq 'login') { + if (($action eq 'login') || ($action eq 'directorysrch')) { $output .= ' '; } elsif ($action eq 'serverstatuses') { @@ -888,9 +916,9 @@ sub print_config_box { $rowtotal ++; if ($action eq 'quotas') { $output .= &print_quotas($dom,$settings,\$rowtotal,$action); - } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || - ($action eq 'contacts') || ($action eq 'serverstatuses') || - ($action eq 'loadbalancing')) { + } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || ($action eq 'directorysrch') || + ($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); @@ -2244,8 +2272,7 @@ sub print_textbookcourses { (' 'x2). ''.&mt('Thumbnail:'); if ($image) { - $datatable .= ''. - $imgsrc. + $datatable .= $imgsrc. ' '. ' '.&mt('Replace:').' '; @@ -2399,10 +2426,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,$failsafe); + my ($defdom,$runon,$runoff,$coownerson,$coownersoff); if (ref($settings) eq 'HASH') { if (exists($settings->{'run'})) { if ($settings->{'run'} eq '0') { @@ -2436,9 +2531,6 @@ 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" '; @@ -2474,12 +2566,8 @@ sub print_autoenroll { $coownerson.' value="1" />'.&mt('Yes').' '. ''. - ''. - ''. - ''; - $$rowtotal += 4; + ''; + $$rowtotal += 3; return $datatable; } @@ -2608,149 +2696,115 @@ sub print_autocreate { } sub print_directorysrch { - my ($position,$dom,$settings,$rowtotal) = @_; - my $datatable; - if ($position eq 'top') { - my $instsrchon = ' '; - my $instsrchoff = ' checked="checked" '; - my ($exacton,$containson,$beginson); - my $instlocalon = ' '; - my $instlocaloff = ' checked="checked" '; - if (ref($settings) eq 'HASH') { - if ($settings->{'available'} eq '1') { - $instsrchon = $instsrchoff; - $instsrchoff = ' '; - } - if ($settings->{'localonly'} eq '1') { - $instlocalon = $instlocaloff; - $instlocaloff = ' '; - } - if (ref($settings->{'searchtypes'}) eq 'ARRAY') { - foreach my $type (@{$settings->{'searchtypes'}}) { - if ($type eq 'exact') { - $exacton = ' checked="checked" '; - } elsif ($type eq 'contains') { - $containson = ' checked="checked" '; - } elsif ($type eq 'begins') { - $beginson = ' checked="checked" '; - } - } - } else { - if ($settings->{'searchtypes'} eq 'exact') { - $exacton = ' checked="checked" '; - } elsif ($settings->{'searchtypes'} eq 'contains') { - $containson = ' checked="checked" '; - } elsif ($settings->{'searchtypes'} eq 'specify') { + my ($dom,$settings,$rowtotal) = @_; + my $srchon = ' '; + my $srchoff = ' checked="checked" '; + my ($exacton,$containson,$beginson); + my $localon = ' '; + my $localoff = ' checked="checked" '; + if (ref($settings) eq 'HASH') { + if ($settings->{'available'} eq '1') { + $srchon = $srchoff; + $srchoff = ' '; + } + if ($settings->{'localonly'} eq '1') { + $localon = $localoff; + $localoff = ' '; + } + if (ref($settings->{'searchtypes'}) eq 'ARRAY') { + foreach my $type (@{$settings->{'searchtypes'}}) { + if ($type eq 'exact') { $exacton = ' checked="checked" '; + } elsif ($type eq 'contains') { $containson = ' checked="checked" '; + } elsif ($type eq 'begins') { + $beginson = ' checked="checked" '; } } - } - my ($searchtitles,$titleorder) = &sorted_searchtitles(); - my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); - - my $numinrow = 4; - my $cansrchrow = 0; - $datatable=''. - ''. - ''. - ''. - ''. - ''. - ''; - $$rowtotal += 2; - if (ref($usertypes) eq 'HASH') { - if (keys(%{$usertypes}) > 0) { - $datatable .= &insttypes_row($settings,$types,$usertypes,$dom, - $numinrow,$othertitle,'cansearch'); - $cansrchrow = 1; + } else { + if ($settings->{'searchtypes'} eq 'exact') { + $exacton = ' checked="checked" '; + } elsif ($settings->{'searchtypes'} eq 'contains') { + $containson = ' checked="checked" '; + } elsif ($settings->{'searchtypes'} eq 'specify') { + $exacton = ' checked="checked" '; + $containson = ' checked="checked" '; } } - if ($cansrchrow) { - $$rowtotal ++; - $datatable .= ''; - } else { - $datatable .= ''; + } + my ($searchtitles,$titleorder) = &sorted_searchtitles(); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + + my $numinrow = 4; + my $cansrchrow = 0; + my $datatable=''. + ''. + ''. + ''. + ''. + ''. + ''; + $$rowtotal += 2; + if (ref($usertypes) eq 'HASH') { + if (keys(%{$usertypes}) > 0) { + $datatable .= &insttypes_row($settings,$types,$usertypes,$dom, + $numinrow,$othertitle,'cansearch'); + $cansrchrow = 1; } - $datatable .= ''; + $$rowtotal ++; + if ($cansrchrow) { + $datatable .= ''; } else { - my $domsrchon = ' checked="checked" '; - my $domsrchoff = ' '; - my $domlocalon = ' '; - my $domlocaloff = ' checked="checked" '; - if (ref($settings) eq 'HASH') { - if ($settings->{'lclocalonly'} eq '1') { - $domlocalon = $domlocaloff; - $domlocaloff = ' '; - } - if ($settings->{'lcavailable'} eq '0') { - $domsrchoff = $domsrchon; - $domsrchon = ' '; - } - } - $datatable=''. - ''. - ''. - ''. - ''. - ''. - ''; - $$rowtotal += 2; + $datatable .= ''; } + $datatable .= ''. + ''; + $$rowtotal ++; return $datatable; } @@ -2911,7 +2965,7 @@ sub radiobutton_prefs { } else { $datatable .= ''. + ''."\n"; + $itemcount ++; + } + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"'; + $datatable .= ''."\n". + ''."\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:', + ); + return %lt; +} + sub print_coursedefaults { my ($position,$dom,$settings,$rowtotal) = @_; my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles); my $itemcount = 1; my %choices = &Apache::lonlocal::texthash ( + canuse_pdfforms => 'Course/Community users can create/upload PDF forms', uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)', anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', coursecredits => 'Credits can be specified for courses', uselcmath => 'Math preview uses LON-CAPA previewer (javascript) in place of DragMath (Java)', usejsme => 'Molecule editor uses JSME (HTML5) in place of JME (Java)', postsubmit => 'Disable submit button/keypress following student submission', - canclone => "People who may clone a course (besides course's owner and coordinators)", - mysqltables => 'Lifetime (s) of "Temporary" MySQL tables (student performance data) on homeserver', + canclone => "People who may clone a course (besides course's owner and coordinators)", ); my %staticdefaults = ( anonsurvey_threshold => 10, uploadquota => 500, postsubmit => 60, - mysqltables => 172800, ); if ($position eq 'top') { %defaultchecked = ( + 'canuse_pdfforms' => 'off', 'uselcmath' => 'on', 'usejsme' => 'on', - 'canclone' => 'none', + 'canclone' => 'none', ); - @toggles = ('uselcmath','usejsme'); + @toggles = ('canuse_pdfforms','uselcmath','usejsme'); ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, \%choices,$itemcount); $css_class = $itemcount%2?' class="LC_odd_row"':''; @@ -2988,7 +3361,7 @@ sub print_coursedefaults { $currcanclone = $settings->{'canclone'}; } } - } + } foreach my $option (@cloneoptions) { my ($checked,$additional); if ($currcanclone eq $option) { @@ -3027,7 +3400,7 @@ sub print_coursedefaults { $itemcount ++; } else { $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; - my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout,%currmysql); + my ($currdefresponder,%defcredits,%curruploadquota,%deftimeout); my $currusecredits = 0; my $postsubmitclient = 1; my @types = ('official','unofficial','community','textbook'); @@ -3057,7 +3430,7 @@ sub print_coursedefaults { foreach my $type (@types) { if (ref($settings->{'postsubmit'}->{'timeout'}) eq 'HASH') { if ($settings->{'postsubmit'}->{'timeout'}->{$type} =~ /^\d+$/) { - $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type}; + $deftimeout{$type} = $settings->{'postsubmit'}->{'timeout'}->{$type}; } else { $deftimeout{$type} = $staticdefaults{'postsubmit'}; } @@ -3071,15 +3444,6 @@ sub print_coursedefaults { $deftimeout{$type} = $staticdefaults{'postsubmit'}; } } - if (ref($settings->{'mysqltables'}) eq 'HASH') { - foreach my $type (keys(%{$settings->{'mysqltables'}})) { - $currmysql{$type} = $settings->{'mysqltables'}{$type}; - } - } else { - foreach my $type (@types) { - $currmysql{$type} = $staticdefaults{'mysqltables'}; - } - } } else { foreach my $type (@types) { $deftimeout{$type} = $staticdefaults{'postsubmit'}; @@ -3157,27 +3521,13 @@ sub print_coursedefaults { $additional .= '
'.&mt($item->{'header'}->[0]->{'col1'}).'
'.&mt('Failsafe for no drops when institutional data missing').''. - '
'.&mt('Institutional directory search available?').' '. - '
'.&mt('Other domains can search institution?').' '. - '
'.&mt('Directory search available?').' '. + '
'.&mt('Other domains can search?').' '. + '
'.&mt('Supported search methods'). - ''; - foreach my $title (@{$titleorder}) { - if (defined($searchtitles->{$title})) { - my $check = ' '; - if (ref($settings) eq 'HASH') { - if (ref($settings->{'searchby'}) eq 'ARRAY') { - if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) { - $check = ' checked="checked" '; - } + } + if ($cansrchrow) { + $$rowtotal ++; + $datatable .= ''; + } else { + $datatable .= ''; + } + $datatable .= ''; - $$rowtotal ++; - if ($cansrchrow) { - $datatable .= ''; - } else { - $datatable .= ''; - } - $datatable .= ''. - ''; - $$rowtotal ++; + } + $datatable .= '
'.&mt('Supported search methods'). + ''; + foreach my $title (@{$titleorder}) { + if (defined($searchtitles->{$title})) { + my $check = ' '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'searchby'}) eq 'ARRAY') { + if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) { + $check = ' checked="checked" '; } } - $datatable .= ''; } + $datatable .= ''; } - $datatable .= '
'. - ''. + '
'.&mt('Search latitude').''. - ' '. - ' '. - '
'.&mt('LON-CAPA directory search available?').' '. - '
'.&mt('Other domains can search LON-CAPA domain?').' '. - '
'.&mt('Search latitude').''. + ' '. + ' '. + '
'; } - $datatable .= + $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').'
'. + '
'. + '
'.&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". + ''."\n". + ' '."\n". + ''.&mt('Add').''. + '
'.&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('Custom items sent on launch').''. + ''. + ''. + '
'.&mt('Action').''.&mt('Name').''.&mt('Value').'
'. + ''. + '
'."\n"; %defaultchecked = ('postsubmit' => 'on'); @toggles = ('postsubmit'); - $current = { - 'postsubmit' => $postsubmitclient, - }; + my $current = { + 'postsubmit' => $postsubmitclient, + }; ($table,$itemcount) = &radiobutton_prefs($current,\@toggles,\%defaultchecked, \%choices,$itemcount,$onclick,$additional,'left'); $datatable .= $table; - $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; - $datatable .= ''. - $choices{'mysqltables'}. - ''. - ''. - ''; - foreach my $type (@types) { - $datatable .= ''; - } - $datatable .= '
'.&mt($type).'
'. - '
'."\n"; - $itemcount ++; - } $$rowtotal += $itemcount; return $datatable; @@ -3710,7 +4060,7 @@ sub spares_row { '. &mt('[_1] when busy, offloads to:' ,''.$server.'').'
'. - ''."\n". + ''."\n". ''. "\n"; @@ -4606,7 +4956,7 @@ sub email_as_username { sub captcha_choice { my ($context,$settings,$itemcount) = @_; my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext, - $vertext,$currver); + $vertext,$currver); my %lt = &captcha_phrases(); $keyentry = 'hidden'; if ($context eq 'cancreate') { @@ -5461,7 +5811,7 @@ sub serverstatus_pages { sub defaults_javascript { my ($settings) = @_; - return unless (ref($settings) eq 'HASH'); + return unless (ref($settings) eq 'HASH'); if ((ref($settings->{'inststatusorder'}) eq 'ARRAY') && (ref($settings->{'inststatustypes'}) eq 'HASH')) { my $maxnum = scalar(@{$settings->{'inststatusorder'}}); if ($maxnum eq '') { @@ -6203,7 +6553,6 @@ sub modify_login { $errors .= '
  • '.$puberror.'
  • '; if ((grep(/^\Q$lang\E$/,@currlangs)) && (!grep(/^\Q$lang\E$/,@delurls))) { - $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang}; } } @@ -6227,7 +6576,7 @@ sub modify_login { if ($domservers{$lonhost}) { if (ref($domconfig{'login'}{'headtag'}{$lonhost}) eq 'HASH') { $currheadtagurls{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'url'}; - $currexempt{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'exempt'} + $currexempt{$lonhost} = $domconfig{'login'}{'headtag'}{$lonhost}{'exempt'}; } } } @@ -6246,7 +6595,7 @@ sub modify_login { } elsif ($currheadtagurls{$lonhost}) { $loginhash{'login'}{'headtag'}{$lonhost}{'url'} = $currheadtagurls{$lonhost}; if ($currexempt{$lonhost}) { - if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) { + if ((!exists($possexempt{$lonhost})) || ($possexempt{$lonhost} ne $currexempt{$lonhost})) { $changes{'headtag'}{$lonhost} = 1; } } elsif ($possexempt{$lonhost}) { @@ -6297,7 +6646,6 @@ sub modify_login { $errors .= '
  • '.$error.'
  • '; } } - &process_captcha('login',\%changes,$loginhash{'login'},$domconfig{'login'}); my $defaulthelpfile = '/adm/loginproblems.html'; @@ -6456,7 +6804,7 @@ sub modify_login { } elsif ($item eq 'recaptchaversion') { if (ref($loginhash{'login'}) eq 'HASH') { if ($loginhash{'login'}{'captcha'} eq 'recaptcha') { - $resulttext .= '
  • '.&mt('ReCAPTCHA for helpdesk form set to version [_1]',$loginhash{'login'}{'recaptchaversion'}). + $resulttext .= '
  • '.&mt('ReCAPTCHA set to version [_1]',$loginhash{'login'}{'recaptchaversion'}). '
  • '; } } @@ -6479,6 +6827,7 @@ sub modify_login { return $resulttext; } + sub check_exempt_addresses { my ($iplist) = @_; $iplist =~ s/^\s+//; @@ -6951,7 +7300,7 @@ sub check_authorstatus { sub publishlogo { my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_; - my ($output,$fname,$logourl); + my ($output,$fname,$logourl,$madethumb); if ($action eq 'upload') { $fname=$env{'form.'.$formname.'.filename'}; chop($env{'form.'.$formname}); @@ -7079,6 +7428,7 @@ $env{'user.name'}.':'.$env{'user.domain' $r->set_handlers('PerlCleanupHandler' => [\¬ifysubscribed,@{$handlers}]); $registered_cleanup=1; } + $madethumb = 1; } else { print $logfile "\nUnable to write ".$copyfile. ':'.$!."\n"; @@ -7091,7 +7441,7 @@ $env{'user.name'}.':'.$env{'user.domain' $output = $versionresult; } } - return ($output,$logourl); + return ($output,$logourl,$madethumb); } sub logo_versioning { @@ -7388,7 +7738,7 @@ sub modify_quotas { my $newpos = $env{'form.'.$itemid}; $newpos =~ s/\D+//g; foreach my $item ('subject','title','publisher','author') { - next if ((($item eq 'author') || ($item eq 'publisher')) && + next if ((($item eq 'author') || ($item eq 'publisher')) && ($type eq 'templates')); $confhash{$type}{$key}{$item} = $env{'form.'.$type.'_'.$item.'_'.$i}; if ($domconfig{$action}{$type}{$key}{$item} ne $confhash{$type}{$key}{$item}) { @@ -7557,7 +7907,7 @@ sub modify_quotas { } } elsif ($confhash{'validation'}{'dc'} ne '') { $changes{'validation'}{'dc'} = $confhash{'validation'}{'dc'}; - } + } } else { if (ref($domconfig{'requestcourses'}) eq 'HASH') { if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') { @@ -7960,6 +8310,495 @@ sub process_textbook_image { return ($url,$error); } +sub modify_ltitools { + my ($r,$dom,$action,$lastactref,%domconfig) = @_; + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); + my ($newid,@allpos,%changes,%confhash,$errors,$resulttext); + my $confname = $dom.'-domainconfig'; + my $servadm = $r->dir_config('lonAdmEMail'); + my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm); + my (%posslti,%possfield); + my @courseroles = ('cc','in','ta','ep','st'); + my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner); + map { $posslti{$_} = 1; } @ltiroles; + my @allfields = ('fullname','firstname','lastname','email','user','roles'); + map { $possfield{$_} = 1; } @allfields; + my %lt = <itools_names(); + if ($env{'form.ltitools_add'}) { + my $title = $env{'form.ltitools_add_title'}; + $title =~ s/(`)/'/g; + ($newid,my $error) = &get_ltitools_id($dom,$title); + if ($newid) { + my $position = $env{'form.ltitools_add_pos'}; + $position =~ s/\D+//g; + if ($position ne '') { + $allpos[$position] = $newid; + } + $changes{$newid} = 1; + foreach my $item ('title','url','key','secret') { + $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g; + if ($env{'form.ltitools_add_'.$item}) { + $confhash{$newid}{$item} = $env{'form.ltitools_add_'.$item}; + } + } + if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') { + $confhash{$newid}{'version'} = $env{'form.ltitools_add_version'}; + } + if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') { + $confhash{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'}; + } + foreach my $item ('width','height') { + $env{'form.ltitools_add_'.$item} =~ s/^\s+//; + $env{'form.ltitools_add_'.$item} =~ s/\s+$//; + if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) { + $confhash{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item}; + } + } + if ($env{'form.ltitools_add_target'} eq 'window') { + $confhash{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'}; + } else { + $confhash{$newid}{'display'}{'target'} = 'iframe'; + } + foreach my $item ('passback','roster') { + if ($env{'form.ltitools_add_'.$item}) { + $confhash{$newid}{$item} = 1; + } + } + if ($env{'form.ltitools_add_image.filename'} ne '') { + my ($imageurl,$error) = + &process_ltitools_image($r,$dom,$confname,'ltitools_add_image',$dom, + $configuserok,$switchserver,$author_ok); + if ($imageurl) { + $confhash{$newid}{'image'} = $imageurl; + } + if ($error) { + &Apache::lonnet::logthis($error); + $errors .= '
  • '.$error.'
  • '; + } + } + my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_add_fields'); + foreach my $field (@fields) { + if ($possfield{$field}) { + if ($field eq 'roles') { + foreach my $role (@courseroles) { + my $choice = $env{'form.ltitools_add_roles_'.$role}; + if (($choice ne '') && ($posslti{$choice})) { + $confhash{$newid}{'roles'}{$role} = $choice; + if ($role eq 'cc') { + $confhash{$newid}{'roles'}{'co'} = $choice; + } + } + } + } else { + $confhash{$newid}{'fields'}{$field} = 1; + } + } + } + if ($env{'form.ltitools_add_custom'}) { + my $name = $env{'form.ltitools_add_custom_name'}; + my $value = $env{'form.ltitools_add_custom_value'}; + $value =~ s/(`)/'/g; + $name =~ s/(`)/'/g; + $confhash{$newid}{'custom'}{$name} = $value; + } + } else { + my $error = &mt('Failed to acquire unique ID for new external tool'); + $errors .= '
  • '.$error.'
  • '; + } + } + if (ref($domconfig{$action}) eq 'HASH') { + my %deletions; + my @todelete = &Apache::loncommon::get_env_multiple('form.ltitools_del'); + if (@todelete) { + map { $deletions{$_} = 1; } @todelete; + } + my %customadds; + my @newcustom = &Apache::loncommon::get_env_multiple('form.ltitools_customadd'); + if (@newcustom) { + map { $customadds{$_} = 1; } @newcustom; + } + my %imgdeletions; + my @todeleteimages = &Apache::loncommon::get_env_multiple('form.ltitools_image_del'); + if (@todeleteimages) { + map { $imgdeletions{$_} = 1; } @todeleteimages; + } + my $maxnum = $env{'form.ltitools_maxnum'}; + for (my $i=0; $i<=$maxnum; $i++) { + my $itemid = $env{'form.ltitools_id_'.$i}; + if (ref($domconfig{$action}{$itemid}) eq 'HASH') { + if ($deletions{$itemid}) { + if ($domconfig{$action}{$itemid}{'image'}) { + #FIXME need to obsolete item in RES space + } + $changes{$itemid} = $domconfig{$action}{$itemid}{'title'}; + next; + } else { + my $newpos = $env{'form.ltitools_'.$itemid}; + $newpos =~ s/\D+//g; + foreach my $item ('title','url','key','secret') { + $confhash{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i}; + if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) { + $changes{$itemid} = 1; + } + } + if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') { + $confhash{$itemid}{'version'} = $env{'form.ltitools_version_'.$i}; + } + if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') { + $confhash{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i}; + } + foreach my $size ('width','height') { + $env{'form.ltitools_'.$size.'_'.$i} =~ s/^\s+//; + $env{'form.ltitools_'.$size.'_'.$i} =~ s/\s+$//; + if ($env{'form.ltitools_'.$size.'_'.$i} =~ /^\d+$/) { + $confhash{$itemid}{'display'}{$size} = $env{'form.ltitools_'.$size.'_'.$i}; + if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') { + if ($domconfig{$action}{$itemid}{'display'}{$size} ne $confhash{$itemid}{'display'}{$size}) { + $changes{$itemid} = 1; + } + } else { + $changes{$itemid} = 1; + } + } + } + if ($env{'form.ltitools_target_'.$i} eq 'window') { + $confhash{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i}; + } else { + $confhash{$itemid}{'display'}{'target'} = 'iframe'; + } + if (ref($domconfig{$action}{$itemid}{'display'}) eq 'HASH') { + if ($domconfig{$action}{$itemid}{'display'}{'target'} ne $confhash{$itemid}{'display'}{'target'}) { + $changes{$itemid} = 1; + } + } else { + $changes{$itemid} = 1; + } + foreach my $extra ('passback','roster') { + if ($env{'form.ltitools_'.$extra.'_'.$i}) { + $confhash{$itemid}{$extra} = 1; + } + if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) { + $changes{$itemid} = 1; + } + } + my @fields = &Apache::loncommon::get_env_multiple('form.ltitools_fields_'.$i); + foreach my $field (@fields) { + if ($possfield{$field}) { + if ($field eq 'roles') { + foreach my $role (@courseroles) { + my $choice = $env{'form.ltitools_roles_'.$role.'_'.$i}; + if (($choice ne '') && ($posslti{$choice})) { + $confhash{$itemid}{'roles'}{$role} = $choice; + if ($role eq 'cc') { + $confhash{$itemid}{'roles'}{'co'} = $choice; + } + } + if (ref($domconfig{$action}{$itemid}{'roles'}) eq 'HASH') { + if ($domconfig{$action}{$itemid}{'roles'}{$role} ne $confhash{$itemid}{'roles'}{$role}) { + $changes{$itemid} = 1; + } + } elsif ($confhash{$itemid}{'roles'}{$role}) { + $changes{$itemid} = 1; + } + } + } else { + $confhash{$itemid}{'fields'}{$field} = 1; + if (ref($domconfig{$action}{$itemid}{'fields'}) eq 'HASH') { + if ($domconfig{$action}{$itemid}{'fields'}{$field} ne $confhash{$itemid}{'fields'}{$field}) { + $changes{$itemid} = 1; + } + } else { + $changes{$itemid} = 1; + } + } + } + } + $allpos[$newpos] = $itemid; + } + if ($imgdeletions{$itemid}) { + $changes{$itemid} = 1; + #FIXME need to obsolete item in RES space + } elsif ($env{'form.ltitools_image_'.$i.'.filename'}) { + my ($imgurl,$error) = &process_ltitools_image($r,$dom,$confname,'ltitools_image_'.$i, + $itemid,$configuserok,$switchserver, + $author_ok); + if ($imgurl) { + $confhash{$itemid}{'image'} = $imgurl; + $changes{$itemid} = 1; + } + if ($error) { + &Apache::lonnet::logthis($error); + $errors .= '
  • '.$error.'
  • '; + } + } elsif ($domconfig{$action}{$itemid}{'image'}) { + $confhash{$itemid}{'image'} = + $domconfig{$action}{$itemid}{'image'}; + } + if ($customadds{$i}) { + my $name = $env{'form.ltitools_custom_name_'.$i}; + $name =~ s/(`)/'/g; + $name =~ s/^\s+//; + $name =~ s/\s+$//; + my $value = $env{'form.ltitools_custom_value_'.$i}; + $value =~ s/(`)/'/g; + $value =~ s/^\s+//; + $value =~ s/\s+$//; + if ($name ne '') { + $confhash{$itemid}{'custom'}{$name} = $value; + $changes{$itemid} = 1; + } + } + my %customdels; + my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); + if (@customdeletions) { + $changes{$itemid} = 1; + } + map { $customdels{$_} = 1; } @customdeletions; + if (ref($domconfig{$action}{$itemid}{'custom'}) eq 'HASH') { + foreach my $key (keys(%{$domconfig{$action}{$itemid}{'custom'}})) { + unless ($customdels{$key}) { + if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') { + $confhash{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; + } + if ($domconfig{$action}{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) { + $changes{$itemid} = 1; + } + } + } + } + unless ($changes{$itemid}) { + foreach my $key (keys(%{$domconfig{$action}{$itemid}})) { + if (ref($domconfig{$action}{$itemid}{$key}) eq 'HASH') { + if (ref($confhash{$itemid}{$key}) eq 'HASH') { + foreach my $innerkey (keys(%{$domconfig{$action}{$itemid}{$key}})) { + unless (exists($confhash{$itemid}{$key}{$innerkey})) { + $changes{$itemid} = 1; + last; + } + } + } elsif (keys(%{$domconfig{$action}{$itemid}{$key}}) > 0) { + $changes{$itemid} = 1; + } + } + last if ($changes{$itemid}); + } + } + } + } + } + if (@allpos > 0) { + my $idx = 0; + foreach my $itemid (@allpos) { + if ($itemid ne '') { + $confhash{$itemid}{'order'} = $idx; + if (ref($domconfig{$action}) eq 'HASH') { + if (ref($domconfig{$action}{$itemid}) eq 'HASH') { + if ($domconfig{$action}{$itemid}{'order'} ne $idx) { + $changes{$itemid} = 1; + } + } + } + $idx ++; + } + } + } + my %ltitoolshash = ( + $action => { %confhash } + ); + my $putresult = &Apache::lonnet::put_dom('configuration',\%ltitoolshash, + $dom); + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('ltitools',$dom,\%confhash,$cachetime); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'ltitools'} = 1; + } + $resulttext = &mt('Changes made:').''; + } else { + $resulttext = &mt('No changes made.'); + } + } else { + $errors .= '
  • '.&mt('Failed to save changes').'
  • '; + } + if ($errors) { + $resulttext .= &mt('The following errors occurred: ').''; + } + return $resulttext; +} + +sub process_ltitools_image { + my ($r,$dom,$confname,$caller,$itemid,$configuserok,$switchserver,$author_ok) = @_; + my $filename = $env{'form.'.$caller.'.filename'}; + my ($error,$url); + my ($width,$height) = (21,21); + if ($configuserok eq 'ok') { + if ($switchserver) { + $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]', + $switchserver); + } elsif ($author_ok eq 'ok') { + my ($result,$imageurl,$madethumb) = + &publishlogo($r,'upload',$caller,$dom,$confname, + "ltitools/$itemid/icon",$width,$height); + if ($result eq 'ok') { + if ($madethumb) { + my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$}); + my $imagethumb = "$path/tn-".$imagefile; + $url = $imagethumb; + } else { + $url = $imageurl; + } + } else { + $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$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].",$filename,$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].",$filename,$confname,$dom,$configuserok); + } + return ($url,$error); +} + +sub get_ltitools_id { + my ($cdom,$title) = @_; + # get lock on ltitools db + my $lockhash = { + lock => $env{'user.name'}. + ':'.$env{'user.domain'}, + }; + my $tries = 0; + my $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom); + my ($id,$error); + + while (($gotlock ne 'ok') && ($tries<10)) { + $tries ++; + sleep (0.1); + $gotlock = &Apache::lonnet::newput_dom('ltitools',$lockhash,$cdom); + } + if ($gotlock eq 'ok') { + my %currids = &Apache::lonnet::dump_dom('ltitools',$cdom); + if ($currids{'lock'}) { + delete($currids{'lock'}); + if (keys(%currids)) { + my @curr = sort { $a <=> $b } keys(%currids); + if ($curr[-1] =~ /^\d+$/) { + $id = 1 + $curr[-1]; + } + } else { + $id = 1; + } + if ($id) { + unless (&Apache::lonnet::newput_dom('ltitools',{ $id => $title },$cdom) eq 'ok') { + $error = 'nostore'; + } + } else { + $error = 'nonumber'; + } + } + my $dellockoutcome = &Apache::lonnet::del_dom('ltitools',['lock'],$cdom); + } else { + $error = 'nolock'; + } + return ($id,$error); +} + sub modify_autoenroll { my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,%changes); @@ -7972,8 +8811,7 @@ sub modify_autoenroll { my $autorun = &Apache::lonnet::auto_run(undef,$dom), my %title = ( run => 'Auto-enrollment active', sender => 'Sender for notification messages', - coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)', - failsafe => 'Failsafe for no drops if institutional data missing for a section'); + coowners => 'Automatic assignment of co-ownership to instructors of record (institutional data)'); my @offon = ('off','on'); my $sender_uname = $env{'form.sender_uname'}; my $sender_domain = $env{'form.sender_domain'}; @@ -7983,17 +8821,11 @@ sub modify_autoenroll { $sender_domain = ''; } my $coowners = $env{'form.autoassign_coowners'}; - my $failsafe = $env{'form.autoenroll_failsafe'}; - $failsafe =~ s{^\s+|\s+$}{}g; - if ($failsafe =~ /\D/) { - undef($failsafe); - } my %autoenrollhash = ( autoenroll => { 'run' => $env{'form.autoenroll_run'}, 'sender_uname' => $sender_uname, 'sender_domain' => $sender_domain, 'co-owners' => $coowners, - 'autofailsafe' => $failsafe, } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash, @@ -8020,10 +8852,7 @@ sub modify_autoenroll { } } elsif ($coowners) { $changes{'coowners'} = 1; - } - if ($currautoenroll{'autofailsafe'} ne $failsafe) { - $changes{'autofailsafe'} = 1; - } + } if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').''; } else { $resulttext = &mt('No changes made to auto-enrollment settings'); @@ -8334,10 +9152,8 @@ sub modify_directorysrch { $currdirsrch{$key} = $domconfig{'directorysrch'}{$key}; } } - my %title = ( available => 'Institutional directory search available', - localonly => 'Other domains can search institution', - lcavailable => 'LON-CAPA directory search available', - lclocalonly => 'Other domains can search LON-CAPA domain', + my %title = ( available => 'Directory search available', + localonly => 'Other domains can search', searchby => 'Search types', searchtypes => 'Search latitude'); my @offon = ('off','on'); @@ -8411,9 +9227,7 @@ sub modify_directorysrch { my %dirsrch_hash = ( directorysrch => { available => $env{'form.dirsrch_available'}, cansearch => \@cansearch, - localonly => $env{'form.dirsrch_instlocalonly'}, - lclocalonly => $env{'form.dirsrch_domlocalonly'}, - lcavailable => $env{'form.dirsrch_domavailable'}, + localonly => $env{'form.dirsrch_localonly'}, searchby => \@searchby, searchtypes => \@searchtypes, } @@ -8430,47 +9244,24 @@ sub modify_directorysrch { $changes{'available'} = 1; } } - if (exists($currdirsrch{'lcavailable'})) { - if ($currdirsrch{'lcavailable'} ne $env{'form.dirsrch_domavailable'}) { - $changes{'lcavailable'} = 1; - } - } else { - if ($env{'form.dirsrch_lcavailable'} eq '1') { - $changes{'lcavailable'} = 1; - } - } if (exists($currdirsrch{'localonly'})) { - if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_instlocalonly'}) { - $changes{'localonly'} = 1; - } + if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_localonly'}) { + $changes{'localonly'} = 1; + } } else { - if ($env{'form.dirsrch_instlocalonly'} eq '1') { + if ($env{'form.dirsrch_localonly'} eq '1') { $changes{'localonly'} = 1; } } - if (exists($currdirsrch{'lclocalonly'})) { - if ($currdirsrch{'lclocalonly'} ne $env{'form.dirsrch_domlocalonly'}) { - $changes{'lclocalonly'} = 1; - } - } else { - if ($env{'form.dirsrch_domlocalonly'} eq '1') { - $changes{'lclocalonly'} = 1; - } - } if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').''; } else { - $resulttext = &mt('No changes made to directory search settings'); + $resulttext = &mt('No changes made to institution directory search settings'); } } else { $resulttext = ''. @@ -9427,7 +10218,8 @@ sub modify_selfcreation { $chgtext .= ''; } elsif ($type eq 'recaptchaversion') { if ($savecaptcha{'captcha'} eq 'recaptcha') { - $chgtext .= &mt('ReCAPTCHA set to version [_1]',$savecaptcha{$type}); + $chgtext .= '
  • '.&mt('ReCAPTCHA set to version [_1]',$savecaptcha{$type}). + '
  • '; } } elsif ($type eq 'emailusername') { if (ref($cancreate{'emailusername'}) eq 'HASH') { @@ -10485,19 +11277,18 @@ sub modify_coursedefaults { my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,$errors,%changes,%defaultshash); my %defaultchecked = ( + 'canuse_pdfforms' => 'off', 'uselcmath' => 'on', 'usejsme' => 'on' ); - my @toggles = ('uselcmath','usejsme'); + my @toggles = ('canuse_pdfforms','uselcmath','usejsme'); my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial', - 'uploadquota_community','uploadquota_textbook','mysqltables_official', - 'mysqltables_unofficial','mysqltables_community','mysqltables_textbook'); + 'uploadquota_community','uploadquota_textbook'); my @types = ('official','unofficial','community','textbook'); my %staticdefaults = ( anonsurvey_threshold => 10, uploadquota => 500, postsubmit => 60, - mysqltables => 172800, ); $defaultshash{'coursedefaults'} = {}; @@ -10538,12 +11329,12 @@ sub modify_coursedefaults { } $defaultshash{'coursedefaults'}{$item} = $newdef; } else { - my ($setting,$type) = ($item =~ /^(uploadquota|mysqltables)_(\w+)$/); - if (ref($domconfig{'coursedefaults'}{$setting}) eq 'HASH') { - $currdef = $domconfig{'coursedefaults'}{$setting}{$type}; + my ($type) = ($item =~ /^\Quploadquota_\E(\w+)$/); + if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') { + $currdef = $domconfig{'coursedefaults'}{'uploadquota'}{$type}; } $newdef =~ s/[^\w.\-]//g; - $defaultshash{'coursedefaults'}{$setting}{$type} = $newdef; + $defaultshash{'coursedefaults'}{'uploadquota'}{$type} = $newdef; } if ($currdef ne $newdef) { my $staticdef; @@ -10551,10 +11342,9 @@ sub modify_coursedefaults { unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) { $changes{$item} = 1; } - } elsif ($item =~ /^(uploadquota|mysqltables)_/) { - my $setting = $1; - unless (($currdef eq '') && ($newdef == $staticdefaults{$setting})) { - $changes{$setting} = 1; + } else { + unless (($currdef eq '') && ($newdef == $staticdefaults{'uploadquota'})) { + $changes{'uploadquota'} = 1; } } } @@ -10567,7 +11357,7 @@ sub modify_coursedefaults { } } my $newclone; - if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) { + if ($env{'form.canclone'} =~ /^(none|domain|instcode)$/) { $newclone = $env{'form.canclone'}; } if ($newclone eq 'instcode') { @@ -10590,8 +11380,8 @@ sub modify_coursedefaults { $newclone eq ''; } } elsif ($newclone ne '') { - $defaultshash{'coursedefaults'}{'canclone'} = $newclone; - } + $defaultshash{'coursedefaults'}{'canclone'} = $newclone; + } if ($newclone ne $currclone) { $changes{'canclone'} = 1; } @@ -10609,10 +11399,10 @@ sub modify_coursedefaults { $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type}; } } else { - if ($env{'form.coursecredits'} eq '1') { + if ($env{'form.coursecredits'} eq '1') { foreach my $type (@types) { unless ($type eq 'community') { - if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) { + if ($domconfig{'coursedefaults'}{'coursecredits'}{$type} ne $credits{$type}) { $changes{'coursecredits'} = 1; } $defaultshash{'coursedefaults'}{'coursecredits'}{$type} = $credits{$type}; @@ -10655,7 +11445,7 @@ sub modify_coursedefaults { } if (exists($currtimeout{$type})) { if ($timeout ne $currtimeout{$type}) { - $changes{'postsubmit'} = 1; + $changes{'postsubmit'} = 1; } } elsif ($timeout ne '') { $changes{'postsubmit'} = 1; @@ -10677,14 +11467,14 @@ sub modify_coursedefaults { if ($putresult eq 'ok') { if (keys(%changes) > 0) { my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); - if (($changes{'uploadquota'}) || ($changes{'postsubmit'}) || + if (($changes{'canuse_pdfforms'}) || ($changes{'uploadquota'}) || ($changes{'postsubmit'}) || ($changes{'coursecredits'}) || ($changes{'uselcmath'}) || ($changes{'usejsme'}) || - ($changes{'canclone'}) || ($changes{'mysqltables'})) { - foreach my $item ('uselcmath','usejsme') { + ($changes{'canclone'})) { + foreach my $item ('canuse_pdfforms','uselcmath','usejsme') { if ($changes{$item}) { $domdefaults{$item}=$defaultshash{'coursedefaults'}{$item}; } - } + } if ($changes{'coursecredits'}) { if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') { foreach my $type (keys(%{$defaultshash{'coursedefaults'}{'coursecredits'}})) { @@ -10731,7 +11521,13 @@ sub modify_coursedefaults { } $resulttext = &mt('Changes made:').'
      '; foreach my $item (sort(keys(%changes))) { - if ($item eq 'uselcmath') { + if ($item eq 'canuse_pdfforms') { + if ($env{'form.'.$item} eq '1') { + $resulttext .= '
    • '.&mt("Course/Community users can create/upload PDF forms set to 'on'").'
    • '; + } else { + $resulttext .= '
    • '.&mt('Course/Community users can create/upload PDF forms set to "off"').'
    • '; + } + } elsif ($item eq 'uselcmath') { if ($env{'form.'.$item} eq '1') { $resulttext .= '
    • '.&mt('Math preview uses LON-CAPA previewer (javascript), if supported by browser.').'
    • '; } else { @@ -10741,7 +11537,7 @@ sub modify_coursedefaults { if ($env{'form.'.$item} eq '1') { $resulttext .= '
    • '.&mt('Molecule editor uses JSME (HTML5), if supported by browser.').'
    • '; } else { - $resulttext .= '
    • '.&mt('Molecule editor uses JME (Java), if supported by client OS.').'
    • '; + $resulttext .= '
    • '.&mt('Molecule editor uses JME (Java), if supported by client OS.').'
    • '; } } elsif ($item eq 'anonsurvey_threshold') { $resulttext .= '
    • '.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'
    • '; @@ -10758,24 +11554,12 @@ sub modify_coursedefaults { } else { $resulttext .= '
    • '.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'
    • '; } - } elsif ($item eq 'mysqltables') { - if (ref($defaultshash{'coursedefaults'}{'mysqltables'}) eq 'HASH') { - $resulttext .= '
    • '.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver').'
        '. - '
      • '.&mt('Official courses: [_1] s',''.$defaultshash{'coursedefaults'}{'mysqltables'}{'official'}.'').'
      • '. - '
      • '.&mt('Unofficial courses: [_1] s',''.$defaultshash{'coursedefaults'}{'mysqltables'}{'unofficial'}.'').'
      • '. - '
      • '.&mt('Textbook courses: [_1] s',''.$defaultshash{'coursedefaults'}{'mysqltables'}{'textbook'}.'').'
      • '. - '
      • '.&mt('Communities: [_1] s',''.$defaultshash{'coursedefaults'}{'mysqltables'}{'community'}.'').'
      • '. - '
      '. - '
    • '; - } else { - $resulttext .= '
    • '.&mt('Lifetime of "Temporary" MySQL tables (student performance data) on homeserver remains default: [_1] s',$staticdefaults{'uploadquota'}).'
    • '; - } } elsif ($item eq 'postsubmit') { if ($domdefaults{'postsubmit'} eq 'off') { $resulttext .= '
    • '.&mt('Submit button(s) remain enabled on page after student makes submission.'); } else { $resulttext .= '
    • '.&mt('Submit button(s) disabled on page after student makes submission').'; '; - if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') { + if (ref($defaultshash{'coursedefaults'}{'postsubmit'}) eq 'HASH') { $resulttext .= &mt('durations:').'
        '; foreach my $type (@types) { $resulttext .= '
      • '; @@ -10804,7 +11588,7 @@ sub modify_coursedefaults { } $resulttext .= '
      '; } - $resulttext .= '
    • '; + $resulttext .= ''; } } elsif ($item eq 'coursecredits') { if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') { @@ -10832,7 +11616,7 @@ sub modify_coursedefaults { } elsif ($defaultshash{'coursedefaults'}{'canclone'} eq 'domain') { $resulttext .= '
    • '.&mt('By default, a course requester can clone any course from his/her domain.').'
    • '; } else { - $resulttext .= '
    • '.&mt('By default, only course owner and coordinators may clone a course.').'
    • '; + $resulttext .= '
    • '.&mt('By default, only course owner and coordinators may clone a course.').'
    • '; } } } @@ -11287,7 +12071,7 @@ sub modify_usersessions { } } unless ($changes{'offloadnow'}) { - foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) { + foreach my $lonhost (keys(%{$defaultshash{'usersessions'}{'offloadnow'}})) { unless ($domconfig{'usersessions'}{'offloadnow'}{$lonhost}) { $changes{'offloadnow'} = 1; last; @@ -11512,7 +12296,7 @@ sub modify_loadbalancing { } if ($rule eq 'specific') { my $specifiedhost = $env{'form.loadbalancing_singleserver_'.$i.'_'.$type}; - if (exists($servers{$specifiedhost})) { + if (exists($servers{$specifiedhost})) { $rule = $specifiedhost; } } @@ -11588,7 +12372,7 @@ sub modify_loadbalancing { if ($rule eq '') { $balancetext = $ruletitles{'default'}; } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') || - ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) { + ($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) { if (($type eq '_LC_ipchange') || ($type eq '_LC_ipchangesso')) { foreach my $sparetype (@sparestypes) { if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') { @@ -12330,7 +13114,7 @@ function updateCaptcha(caller,context) { privtext.innerHTML = "$lt{'priv'}"; versionitem.type = 'text'; versionitem.size = '3'; - versiontext.innerHTML = "$lt{'ver'}"; + versiontext.innerHTML = "$lt{'ver'}"; } else { pubitem.type = 'hidden'; privitem.type = 'hidden'; @@ -12403,7 +13187,7 @@ sub captcha_phrases { original => 'original (CAPTCHA)', recaptcha => 'successor (ReCAPTCHA)', notused => 'unused', - ver => 'ReCAPTCHA version (1 or 2)', + ver => 'ReCAPTCHA version (1 or 2)', ); } @@ -12413,7 +13197,7 @@ sub devalidate_remote_domconfs { my %servers = &Apache::lonnet::internet_dom_servers($dom); my %thismachine; map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids(); - my @posscached = ('domainconfig','domdefaults'); + my @posscached = ('domainconfig','domdefaults','ltitools'); if (keys(%servers)) { foreach my $server (keys(%servers)) { next if ($thismachine{$server});