--- loncom/interface/courseprefs.pm 2023/09/02 16:12:21 1.49.2.28.2.16 +++ loncom/interface/courseprefs.pm 2023/03/19 16:05:48 1.118 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set configuration settings for a course # -# $Id: courseprefs.pm,v 1.49.2.28.2.16 2023/09/02 16:12:21 raeburn Exp $ +# $Id: courseprefs.pm,v 1.118 2023/03/19 16:05:48 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -316,7 +316,7 @@ sub handler { idnu => 'Course ID or number', unco => 'Unique code', desc => 'Course Description', - cred => 'Student credits', + cred => 'Student credits', ownr => 'Course Owner', cown => 'Course Co-owners', catg => 'Categorize course', @@ -412,7 +412,7 @@ sub handler { my @prefs_order = ('courseinfo','localization','feedback','discussion', 'classlists','appearance','grading','printouts', 'menuitems','ltitools','linkprot','spreadsheet', - 'bridgetasks','other'); + 'bridgetasks','lti','other'); my %prefs = ( 'courseinfo' => { text => $lt{'gens'}, @@ -463,6 +463,7 @@ sub handler { { text => 'Discussion and Chat', help => 'Course_Prefs_Discussions', ordered => ['pch.roles.denied','pch.users.denied', + 'pac.roles.denied','pac.users.denied', 'plc.roles.denied','plc.users.denied', 'allow_limited_html_in_feedback', 'allow_discussion_post_editing', @@ -472,6 +473,8 @@ sub handler { 'pch.users.denied' => 'No Resource Discussion', 'plc.roles.denied' => 'No Chat room use', 'plc.users.denied' => 'No Chat room use', + 'pac.roles.denied' => 'No Anonymous Resource Discussion', + 'pac.users.denied' => 'No Anonymous Resource Discussion', allow_limited_html_in_feedback => 'Allow limited HTML in discussion', allow_discussion_post_editing => 'Users can edit/delete own discussion posts', discussion_post_fonts => 'Discussion post fonts based on likes/unlikes', @@ -519,7 +522,7 @@ sub handler { uselcmath => 'Student formula entry uses inline preview, not DragMath pop-up', usejsme => 'Molecule editor uses JSME (HTML5) in place of JME (Java)', inline_chem => 'Chemical reaction response uses inline preview, not pop-up', - extresource => 'Display of external resources', + extresource => 'Display of external resources', }, }, 'grading' => @@ -540,7 +543,7 @@ sub handler { help => 'Course_Prefs_Printouts', ordered => ['problem_stream_switch','suppress_tries', 'default_paper_size','print_header_format', - 'disableexampointprint'], + 'disableexampointprint','canuse_pdfforms'], itemtext => { problem_stream_switch => 'Allow problems to be split over pages', suppress_tries => 'Suppress number of tries in printing', @@ -574,6 +577,18 @@ sub handler { suppress_embed_prompt => 'Hide upload references prompt if uploading file to portfolio', }, }, + 'lti' => + { + text => 'LTI provider settings', + help => 'Course_Prefs_LTIProvider', + ordered => ['lti.override','lti.topmenu','lti.inlinemenu','lti.lcmenu'], + itemtext => { + 'lti.override' => 'Override domain defaults', + 'lti.topmenu' => 'Display LON-CAPA page header', + 'lti.inlinemenu' => 'Display LON-CAPA inline menu', + 'lti.lcmenu' => 'Menu items', + }, + }, 'menuitems' => { text => 'Menu display', @@ -679,8 +694,6 @@ sub get_allitems { if ($item eq 'feedback') { push(@allitems,(map { $_.'.text'; } @{$prefs{$item}{'ordered'}})); } - } elsif (($item eq 'linkprot') || ($item eq 'ltitools')) { - push(@allitems,$item); } } } @@ -820,6 +833,8 @@ sub print_config_box { $currtools = $settings->{'ltitools'}; } $output .= &print_ltitools($cdom,$cnum,$currtools,\$rowtotal,$crstype,$noedit,'course'); + } elsif ($action eq 'lti') { + $output .= &print_lti($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'menuitems') { $output .= &print_menuitems('bottom',$cdom,$settings,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'linkprot') { @@ -1260,7 +1275,8 @@ sub process_changes { } } } - } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied')) { + } elsif (($entry eq 'plc.roles.denied') || ($entry eq 'pch.roles.denied') || + ($entry eq 'pac.roles.denied')) { my @denied = &Apache::loncommon::get_env_multiple('form.'.$entry); @denied = sort(@denied); my $deniedstr = ''; @@ -1268,7 +1284,8 @@ sub process_changes { $deniedstr = join(',',@denied); } $newvalues{$entry} = $deniedstr; - } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied')) { + } elsif (($entry eq 'plc.users.denied') || ($entry eq 'pch.users.denied') || + ($entry eq 'pac.users.denied')) { my $total = $env{'form.'.$entry.'_total'}; my $userstr = ''; my @denied; @@ -1320,14 +1337,14 @@ sub process_changes { my ($classorder,$classtitles) = &discussion_vote_classes(); my $fontchange = 0; foreach my $class (@{$classorder}) { - my $ext_entry = $entry.'_'.$class; + my $ext_entry = $entry.'_'.$class; my $size = $env{'form.'.$ext_entry.'_size'}; my $unit = $env{'form.'.$ext_entry.'_unit'}; my $weight = $env{'form.'.$ext_entry.'_weight'}; my $style = $env{'form.'.$ext_entry.'_style'}; my $other = $env{'form.'.$ext_entry.'_other'}; $size =~ s/,//g; - $unit =~ s/,//g; + $unit =~ s/,//g; $weight =~ s/,//g; $style =~ s/,//g; $other =~ s/[^\w;:\s\-\%.]//g; @@ -1335,7 +1352,7 @@ sub process_changes { $newvalues{$ext_entry} = join(',',($size.$unit,$weight,$style,$other)); my $current = $values->{$ext_entry}; if ($values->{$ext_entry} eq '') { - $current = ',,,'; + $current = ',,,'; } if ($newvalues{$ext_entry} ne $current) { $changes->{$ext_entry} = $newvalues{$ext_entry}; @@ -1344,7 +1361,7 @@ sub process_changes { } if ($fontchange) { $changes->{$entry} = 1; - } + } } elsif ($entry eq 'nothideprivileged') { my @curr_nothide; my @new_nothide; @@ -1419,7 +1436,7 @@ sub process_changes { my $newtext = $maxnum-1; $newhdr[$env{'form.printfmthdr_pos_'.$newtext}] = $env{'form.printfmthdr_text_'.$newtext}; $newvalues{$entry} = join('',@newhdr); - } elsif (($entry eq 'languages') || + } elsif (($entry eq 'languages') || ($entry eq 'checkforpriv')) { my $settings; my $total = $env{'form.'.$entry.'_total'}; @@ -1435,7 +1452,7 @@ sub process_changes { } if ($env{'form.'.$entry.'_'.$total} ne '') { my $new = $env{'form.'.$entry.'_'.$total}; - if ($entry eq 'languages') { + if ($entry eq 'languages') { my %langchoices = &get_lang_choices(); if ($langchoices{$new}) { $settings .= $new; @@ -1456,6 +1473,38 @@ sub process_changes { $settings =~ s/,$//; } $newvalues{$entry} = $settings; + } elsif ($action eq 'lti') { + if ($entry eq 'lti.override') { + $newvalues{$entry} = $env{'form.'.$entry}; + } elsif (($entry eq 'lti.topmenu') || ($entry eq 'lti.inlinemenu')) { + if ($env{'form.lti.override'}) { + $newvalues{$entry} = $env{'form.'.$entry}; + } else { + $newvalues{$entry} = ''; + } + } elsif ($entry eq 'lti.lcmenu') { + if (($env{'form.lti.override'}) && + (($env{'form.lti.topmenu'}) || ($env{'form.lti.inlinemenu'}))) { + my @lcmenu = &Apache::loncommon::get_env_multiple('form.lti.lcmenu'); + my @newlcmenu; + if (@lcmenu) { + my @menuitems = ('fullname','coursetitle','role','logout','grades'); + foreach my $item (@menuitems) { + next if (($item eq 'grades') && (!$newvalues{'lti.inlinemenu'})); + if (grep(/^\Q$item\E$/,@lcmenu)) { + push(@newlcmenu,$item); + } + } + } + if (@newlcmenu) { + $newvalues{$entry} = join(',',@newlcmenu); + } else { + $newvalues{$entry} = 'none'; + } + } else { + $newvalues{$entry} = ''; + } + } } elsif ($entry eq 'extresource') { if ($env{'form.'.$entry} =~ /^iframe|tab|window$/) { $newvalues{$entry} = $env{'form.'.$entry}; @@ -1502,7 +1551,7 @@ sub process_changes { } else { $newvalues{$entry} = $env{'form.'.$entry}; } - unless (($entry eq 'co-owners') || ($entry eq 'discussion_post_fonts') || + unless (($entry eq 'co-owners') || ($entry eq 'discussion_post_fonts') || ($entry eq 'extresource') || ($entry eq 'timezone')) { if ($newvalues{$entry} ne $values->{$entry}) { $changes->{$entry} = $newvalues{$entry}; @@ -1612,32 +1661,15 @@ sub process_linkprot { } elsif (exists($env{$urlparamname})) { $env{$urlparamname} = ''; } - my $passback = 'form.linkprot_passback_'.$idx; - my $passbackparamname = 'form.linkprot_passbackformat_'.$idx; - if ($env{$passback} == 1) { - unless ($env{$passbackparamname} =~ /^1\.(0|1)$/) { - $env{$passbackparamname} = ''; - } - } elsif (exists($env{$passbackparamname})) { - $env{$passbackparamname} = ''; - } unless ($idx eq 'add') { if ((!$current{'returnurl'} && ($env{$urlparamname} ne '')) || ($current{'returnurl'} && ($env{$urlparamname} eq ''))) { $haschanges{$itemid} = 1; } - if ((!$current{'passback'} && ($env{$passbackparamname} ne '')) || - ($current{'passback'} && ($env{$passbackparamname} eq ''))) { - $haschanges{$itemid} = 1; - } } if ($env{$urlparamname} ne '') { $linkprot{$itemid}{'returnurl'} = $env{$urlparamname}; } - if ($env{$passbackparamname} ne '') { - $linkprot{$itemid}{'passback'} = 1; - $linkprot{$itemid}{'passbackformat'} = $env{$passbackparamname}; - } if ($ltiauth) { my $reqitem = 'form.linkprot_requser_'.$idx; $env{$reqitem} =~ s/(`)/'/g; @@ -1748,7 +1780,7 @@ sub get_linkprot_id { $tries ++; sleep (0.1); if ($context eq 'domain') { - $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom); + $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom); } else { $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum); } @@ -1786,7 +1818,7 @@ sub get_linkprot_id { $error = 'nonumber'; } } - my $dellockoutcome; + my $dellockoutcome; if ($context eq 'domain') { $dellockoutcome = &Apache::lonnet::del_dom('linkprot',['lock'],$cdom); } else { @@ -1851,7 +1883,7 @@ sub process_ltitools { my @allfields = ('fullname','firstname','lastname','email','user','roles'); map { $possfield{$_} = 1; } @allfields; - my ($dest,$privnum,$cipher); + my ($dest,$privnum,$cipher,$errors,%ltitools); ($cipher,$privnum) = &get_credentials($cdom,$cnum,'ltitools',$context); if ($context eq 'domain') { @@ -1979,7 +2011,7 @@ sub process_ltitools { if ($env{$keyitem} ne '') { $ltitools{$newid}{'key'} = $env{$keyitem}; } - my $secretitem = 'form.ltitools_secret_add'; + my $secretitem = 'form.ltitools_add_secret'; $env{$secretitem} =~ s/(`)/'/g; if ($env{$secretitem} ne '') { if ($privnum && $cipher) { @@ -2724,6 +2756,22 @@ sub store_changes { } } $displayname = &mt($text); + } elsif ($item eq 'lti') { + if ($key eq 'lti.lcmenu') { + if ($changes->{$item}{$key} eq 'none') { + $displayval = &mt('None of the configurable menu items displayed'); + } else { + my %ltititles = <imenu_titles(); + $displayval = join(', ', map { $ltititles{$_}; } split(/,/,$changes->{$item}{$key})); + } + } else { + if ($changes->{$item}{$key} eq '1') { + $displayval = &mt('Yes'); + } elsif ($changes->{$item}{$key} eq '') { + $displayval = &mt('No'); + } + } + $displayname = &mt($text); } elsif ($item eq 'menuitems') { unless ($changes->{$item}{$key} eq '') { if ($key eq 'menudefault') { @@ -2828,7 +2876,20 @@ sub store_changes { } } elsif ($changes->{$item}{$key} eq '') { push(@delkeys,$key); - if ($item eq 'menuitems') { + if ($item eq 'lti') { + if (($key eq 'lti.override') || (($key ne 'lti.override') && ($env{'form.lti.override'} ne ''))) { + if (($key eq 'lti.lcmenu') && + ((!$env{'form.lti.topmenu'}) && (!$env{'form.lti.inlinemenu'}))) { + $output .= '
  • '.&mt('LTI settings for menu items only saved if page header and/or inline menu is set to be displayed').'
  • '; + } else { + $output .= '
  • '.&Apache::lonhtmlcommon::confirm_success(&mt('[_1] set to [_2]', + ''.$displayname.'', + "'$displayval'")).'
  • '; + } + } elsif (!exists($changes->{$item}{'lti.override'})) { + $output .= '
  • '.&mt('LTI settings only saved if Override is set to "Yes"').'
  • '; + } + } elsif ($item eq 'menuitems') { if ($key eq 'menudefault') { $output .= '
  • '.&mt("Default collection of menu items set to: 'Standard' (all menus shown)").'
  • '; } elsif ($key eq 'menucollections') { @@ -2881,7 +2942,9 @@ sub store_changes { } if (($key eq 'description') || ($key eq 'cloners') || ($key eq 'hidefromcat') || ($key eq 'categories') || - ($key eq 'co-owners')) { + ($key eq 'co-owners') || ($key eq 'lti.override') || + ($key eq 'lti.topmenu') || ($key eq 'lti.inlinemenu') || + ($key eq 'lti.lcmenu')) { push(@need_env_update,$key); } } @@ -3025,7 +3088,7 @@ sub store_linkprot { my %values = %{$changes->{$id}}; my %desc = &linkprot_names(); my $display; - foreach my $title ('name','lifetime','version','key','secret','returnurl','passbackformat') { + foreach my $title ('name','lifetime','version','key','secret','returnurl') { if (($title eq 'key') || ($title eq 'secret')) { if (ref($ltienc{$id}) eq 'HASH') { if (exists($ltienc{$id}{$title})) { @@ -3043,13 +3106,7 @@ sub store_linkprot { } } elsif ($title eq 'returnurl') { if ($values{$title}) { - $display .= &mt('Return URL parameter').': '.$values{$title}.', '; - } - } elsif ($title eq 'passbackformat') { - if ($values{$title} eq '1.0') { - $display .= &mt('Can return grades to Launcher with Outcomes Service 1.0 format').', '; - } elsif ($values{$title} eq '1.1') { - $display .= &mt('Can return grades to Launcher with Outcomes Service 1.1 format').', '; + $display .= &mt('Return URL parameter').': '.$values{$title}.', '; } } else { $display .= $desc{$title}.': '.$values{$title}.', '; @@ -3166,7 +3223,7 @@ sub store_ltitools { &Apache::lonnet::devalidate_cache_new('courseltitools',$hashid); unless (($home eq 'no_host') || ($home eq '')) { if (grep(/^\Q$home\E$/,@ids)) { - &Apache::lonnet::devalidate_cache_new('crsltitoolsenc',$hashid); + &Apache::lonnet::devalidate_cache_new('courseltitoolsenc',$hashid); } } } else { @@ -3340,6 +3397,8 @@ sub update_env { my @coowners = split(',',$storehash->{'internal.'.$key}); $crsinfo{$env{'request.course.id'}}{'co-owners'} = \@coowners; $count ++; + } elsif ($key =~ /^lti\./) { + &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash->{$key}}); } } if ($count) { @@ -3473,7 +3532,7 @@ sub get_jscript { $local_to_standard{$code_order[$i]} = $standardnames[$i]; } foreach my $cloner (@cloners) { - if (($cloner !~ /^\Q*:\E$match_domain$/) && + if (($cloner !~ /^\Q*:\E$match_domain$/) && ($cloner !~ /^$match_username\:$match_domain$/)) { foreach my $item (split(/\&/,$cloner)) { my ($key,$val) = split(/\=/,$item); @@ -3700,7 +3759,7 @@ function toggleTimeZone() { } ENDSCRIPT $jscript = '