--- loncom/interface/courseprefs.pm 2024/02/25 05:53:47 1.49.2.28.2.20 +++ loncom/interface/courseprefs.pm 2022/02/01 18:23:24 1.98 @@ -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.20 2024/02/25 05:53:47 raeburn Exp $ +# $Id: courseprefs.pm,v 1.98 2022/02/01 18:23:24 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -52,16 +52,12 @@ This module is used for configuration of =item process_changes() -=item process_linkprot() - =item get_sec_str() =item check_clone() =item store_changes() -=item store_linkprot() - =item update_env() =item display_disallowed() @@ -116,7 +112,7 @@ This module is used for configuration of =item item_table_row_end() -=item yesno_radio() +=item yes_no_radio() =item select_from_options() @@ -224,8 +220,6 @@ use Apache::lonparmset; use Apache::courseclassifier; use Apache::lonlocal; use LONCAPA qw(:DEFAULT :match); -use Crypt::CBC; -use Time::HiRes qw( sleep ); my $registered_cleanup; my $modified_courses; @@ -294,7 +288,7 @@ sub handler { excc => 'Exclude from community catalog', clon => 'Users allowed to clone community', rept => 'Replacement titles for standard community roles', - time => 'Time Zone where the community is located', + time => 'Timezone where the community is located', date => 'Locale used for community calendar', coco => 'Community Content', copo => 'Community Policy', @@ -316,14 +310,14 @@ 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', excc => 'Exclude from course catalog', clon => 'Users allowed to clone course', rept => 'Replacement titles for standard course roles', - time => 'Time Zone in which the course takes place', + time => 'Timezone in which the course takes place', date => 'Locale used for course calendar', coco => 'Course Content', copo => 'Course Policy', @@ -371,54 +365,16 @@ sub handler { } my %values=&Apache::lonnet::dump('environment',$cdom,$cnum); - my %linkprot=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1); - my %domdefs = &Apache::lonnet::get_domain_defaults($cdom); - unless ($phase eq 'process') { - if (ref($domdefs{'linkprotsuggested'}) eq 'HASH') { - $values{'suggested'} = $domdefs{'linkprotsuggested'}; - } - } - my %ltienc = &Apache::lonnet::dump('nohist_ltienc',$cdom,$cnum,undef,undef,undef,1); - my %ltitools = &Apache::lonnet::dump('ltitools',$cdom,$cnum,undef,undef,undef,1); - my %ltitoolsenc = &Apache::lonnet::dump('nohist_toolsenc',$cdom,$cnum,undef,undef,undef,1); - foreach my $id (keys(%linkprot)) { - if (ref($linkprot{$id}) eq 'HASH') { - if (ref($ltienc{$id}) eq 'HASH') { - $values{'linkprot'}{$id} = { %{$linkprot{$id}}, %{$ltienc{$id}} }; - } else { - $values{'linkprot'}{$id} = $linkprot{$id}; - } - } - unless ($phase eq 'process') { - if (ref($values{'linkprot'}{$id}) eq 'HASH') { - delete($values{'linkprot'}{$id}{'secret'}); - } - } - } - if ($linkprot{'lock'}) { - delete($linkprot{'lock'}); - } - foreach my $id (keys(%ltitools)) { - if (ref($ltitools{$id}) eq 'HASH') { - if (ref($ltitoolsenc{$id}) eq 'HASH') { - $values{'ltitools'}{$id} = { %{$ltitools{$id}}, %{$ltitoolsenc{$id}} }; - } else { - $values{'ltitools'}{$id} = $ltitools{$id}; - } - } - unless ($phase eq 'process') { - if (ref($values{'ltitools'}{$id}) eq 'HASH') { - delete($values{'ltitools'}{$id}{'secret'}); - } - } - } - if ($ltitools{'lock'}) { - delete($ltitools{'lock'}); + my %courselti=&Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1); + if ($courselti{'lock'}) { + delete($courselti{'lock'}); } + $values{'linkprotection'} = \%courselti; my @prefs_order = ('courseinfo','localization','feedback','discussion', 'classlists','appearance','grading','printouts', - 'menuitems','ltitools','linkprot','spreadsheet', - 'bridgetasks','other'); + 'menuitems','linkprotection','spreadsheet','bridgetasks', + 'lti','other'); + my %prefs = ( 'courseinfo' => { text => $lt{'gens'}, @@ -469,6 +425,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', @@ -478,6 +435,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', @@ -514,8 +473,7 @@ sub handler { help => 'Course_Prefs_Display', ordered => ['default_xml_style','pageseparators', 'disable_receipt_display','texengine', - 'tthoptions','uselcmath','usejsme', - 'inline_chem','extresource'], + 'tthoptions','uselcmath','usejsme','inline_chem'], itemtext => { default_xml_style => 'Default XML style file', pageseparators => 'Visibly Separate Items on Pages', @@ -525,7 +483,6 @@ 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', }, }, 'grading' => @@ -546,7 +503,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', @@ -580,6 +537,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', @@ -595,7 +564,7 @@ sub handler { menucollections => 'Menu collections', }, }, - 'linkprot' => + 'linkprotection' => { text => 'Link protection', help => 'Course_Prefs_Linkprotection', @@ -603,14 +572,6 @@ sub handler { col2 => 'Settings', }], }, - 'ltitools' => - { - text => 'External tools', - help => 'Course_Prefs_ExternalTools', - header => [{col1 => 'Item', - col2 => 'Settings', - }], - }, 'other' => { text => 'Other settings', help => 'Course_Prefs_Other', @@ -621,14 +582,10 @@ sub handler { ); if (($phase eq 'process') && ($parm_permission->{'process'})) { my @allitems = &get_allitems(%prefs); - my $result = &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, - \@prefs_order,\%prefs,\%values, - $cnum,undef,\@allitems, - 'coursepref',$parm_permission); - if ((ref($result) eq 'HASH') && (keys(%{$result}))) { - $r->rflush(); - &devalidate_remote_courseprefs($cdom,$cnum,$result); - } + &Apache::lonconfigsettings::make_changes($r,$cdom,$phase,$context, + \@prefs_order,\%prefs,\%values, + $cnum,undef,\@allitems, + 'coursepref',$parm_permission); } elsif (($phase eq 'display') && ($parm_permission->{'display'})) { my $noedit; if (ref($parm_permission) eq 'HASH') { @@ -639,7 +596,7 @@ sub handler { my $jscript = &get_jscript($cid,$cdom,$phase,$crstype,\%values,$noedit); my @allitems = &get_allitems(%prefs); &Apache::lonconfigsettings::display_settings($r,$cdom,$phase,$context, - \@prefs_order,\%prefs,\%values,$cnum,$jscript,\@allitems,$crstype, + \@prefs_order,\%prefs,\%values,undef,$jscript,\@allitems,$crstype, 'coursepref',$parm_permission); } else { &Apache::lonconfigsettings::display_choices($r,$phase,$context, @@ -685,8 +642,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); } } } @@ -694,7 +649,7 @@ sub get_allitems { } sub print_config_box { - my ($r,$cdom,$cnum,$phase,$action,$item,$settings,$allitems,$crstype,$parm_permission) = @_; + my ($r,$cdom,$phase,$action,$item,$settings,$allitems,$crstype,$parm_permission) = @_; my $ordered = $item->{'ordered'}; my $itemtext = $item->{'itemtext'}; my $noedit; @@ -784,38 +739,9 @@ sub print_config_box { '; - if ($action eq 'linkprot') { - if ((ref($settings) eq 'HASH') && (ref($settings->{'suggested'}) eq 'HASH')) { - my $hints; - my $hintcount = 0; - foreach my $key (sort { $a <=> $b } keys(%{$settings->{'suggested'}})) { - if ((ref($settings->{'suggested'}->{$key}) eq 'HASH')) { - if (($settings->{'suggested'}->{$key}-{'name'} ne '') && - ($settings->{'suggested'}->{$key}-{'info'} ne '')) { - my $css_class = $hintcount%2?' class="LC_odd_row"':' class="LC_even_row"'; - $hints .= ''. - ''; - $hintcount ++; - } - } - } - if ($hintcount) { - $output .= ''. - ''. - ''."\n". - ''. - ''. - ''."\n". - $hints; - } - } - } if (exists $item->{'header'}->[0]->{'col1'} || exists $item->{'header'}->[0]->{'col2'}) { - $output .= ' + $output .= ' '; if (($action eq 'courseinfo') || ($action eq 'localization') || @@ -842,23 +768,19 @@ sub print_config_box { } elsif ($action eq 'appearance') { $output .= &print_appearance($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'grading') { - $output .= &print_grading($cdom,$cnum,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); + $output .= &print_grading($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'printouts') { $output .= &print_printouts($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'spreadsheet') { $output .= &print_spreadsheet($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'bridgetasks') { $output .= &print_bridgetasks($cdom,$settings,$ordered,$itemtext,\$rowtotal,$crstype,$noedit); - } elsif ($action eq 'ltitools') { - my $currtools = {}; - if ((ref($settings) eq 'HASH') && (ref($settings->{'ltitools'}))) { - $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') { - $output .= &print_linkprotection($cdom,$cnum,$settings,\$rowtotal,$crstype,$noedit,'course'); + } elsif ($action eq 'linkprotection') { + $output .= &print_linkprotection($cdom,$settings,\$rowtotal,$crstype,$noedit); } elsif ($action eq 'other') { $output .= &print_other($cdom,$settings,$allitems,\$rowtotal,$crstype,$noedit); } @@ -871,8 +793,8 @@ sub print_config_box { } sub process_changes { - my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype,$lastactref) = @_; - my (%newvalues,$errors); + my ($cdom,$cnum,$action,$values,$item,$changes,$allitems,$disallowed,$crstype) = @_; + my (%newvalues,%courselti,$errors); if (ref($item) eq 'HASH') { if (ref($changes) eq 'HASH') { my @ordered; @@ -889,17 +811,20 @@ sub process_changes { } } } - } elsif (($action eq 'linkprot') || ($action eq 'ltitools')) { - if (ref($values->{$action}) eq 'HASH') { - foreach my $id (keys(%{$values->{$action}})) { + } elsif ($action eq 'linkprotection') { + if (ref($values->{'linkprotection'}) eq 'HASH') { + foreach my $id (keys(%{$values->{'linkprotection'}})) { if ($id =~ /^\d+$/) { push(@ordered,$id); + unless (ref($values->{'linkprotection'}->{$id}) eq 'HASH') { + $courselti{$id} = ''; + } } } } @ordered = sort { $a <=> $b } @ordered; - if (($env{'form.'.$action.'_add'}) && ($env{'form.'.$action.'_maxnum'} =~ /^\d+$/)) { - push(@ordered,$env{'form.'.$action.'_maxnum'}); + if (($env{'form.linkprot_add'}) && ($env{'form.linkprot_maxnum'} =~ /^\d+$/)) { + push(@ordered,$env{'form.linkprot_maxnum'}); } } elsif (ref($item->{'ordered'}) eq 'ARRAY') { if ($action eq 'courseinfo') { @@ -1038,15 +963,77 @@ sub process_changes { } elsif ($values->{'menucollections'}) { $changes->{'menucollections'} = ''; } - } elsif ($action eq 'linkprot') { - if (ref($values) eq 'HASH') { - $errors = &process_linkprot($cdom,$cnum,$values->{$action},$changes,'course',$lastactref); - } - } elsif ($action eq 'ltitools') { - if (ref($values) eq 'HASH') { - my $switchserver = &check_switchserver($cdom,$cnum,'course','/adm/courseprefs'); - $errors = &process_ltitools('',$cdom,$cnum,$values->{$action},$changes,'course',$lastactref, - 'ok','','ok'); + } elsif ($action eq 'linkprotection') { + my %menutitles = <imenu_titles(); + my (@items,%deletions,%itemids,%haschanges); + if ($env{'form.linkprot_add'}) { + my $name = $env{'form.linkprot_name_add'}; + $name =~ s/(`)/'/g; + my ($newid,$error) = &get_courselti_id($cdom,$cnum,$name); + if ($newid) { + $itemids{'add'} = $newid; + push(@items,'add'); + $haschanges{$newid} = 1; + } else { + $errors .= ''. + &mt('Failed to acquire unique ID for link protection'). + ''; + } + } + if (ref($values->{'linkprotection'}) eq 'HASH') { + my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del'); + my $maxnum = $env{'form.linkprot_maxnum'}; + for (my $i=0; $i<=$maxnum; $i++) { + my $itemid = $env{'form.linkprot_id_'.$i}; + $itemid =~ s/\D+//g; + if ($itemid) { + if (ref($values->{'linkprotection'}->{$itemid}) eq 'HASH') { + push(@items,$i); + $itemids{$i} = $itemid; + if ((@todelete > 0) && (grep(/^$i$/,@todelete))) { + $deletions{$itemid} = $values->{'linkprotection'}->{$itemid}->{'name'}; + } + } + } + } + } + + foreach my $idx (@items) { + my $itemid = $itemids{$idx}; + next unless ($itemid); + if (exists($deletions{$itemid})) { + $courselti{$itemid} = $deletions{$itemid}; + $haschanges{$itemid} = 1; + next; + } + my %current; + if (ref($values->{'linkprotection'}) eq 'HASH') { + if (ref($values->{'linkprotection'}->{$itemid}) eq 'HASH') { + foreach my $key (keys(%{$values->{'linkprotection'}->{$itemid}})) { + $current{$key} = $values->{'linkprotection'}->{$itemid}->{$key}; + } + } + } + foreach my $inner ('name','key','secret','lifetime','version') { + my $formitem = 'form.linkprot_'.$inner.'_'.$idx; + $env{$formitem} =~ s/(`)/'/g; + if ($inner eq 'lifetime') { + $env{$formitem} =~ s/[^\d.]//g; + } + unless ($idx eq 'add') { + if ($current{$inner} ne $env{$formitem}) { + $haschanges{$itemid} = 1; + } + } + if ($env{$formitem} ne '') { + $courselti{$itemid}{$inner} = $env{$formitem}; + } + } + } + if (keys(%haschanges)) { + foreach my $entry (keys(%haschanges)) { + $changes->{$entry} = $courselti{$entry}; + } } } else { foreach my $entry (@ordered) { @@ -1295,7 +1282,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 = ''; @@ -1303,7 +1291,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; @@ -1355,14 +1344,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; @@ -1370,7 +1359,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}; @@ -1379,7 +1368,7 @@ sub process_changes { } if ($fontchange) { $changes->{$entry} = 1; - } + } } elsif ($entry eq 'nothideprivileged') { my @curr_nothide; my @new_nothide; @@ -1454,7 +1443,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'}; @@ -1470,7 +1459,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; @@ -1491,81 +1480,42 @@ sub process_changes { $settings =~ s/,$//; } $newvalues{$entry} = $settings; - } elsif ($entry eq 'extresource') { - if ($env{'form.'.$entry} =~ /^iframe|tab|window$/) { + } elsif ($action eq 'lti') { + if ($entry eq 'lti.override') { $newvalues{$entry} = $env{'form.'.$entry}; - if ($env{'form.'.$entry} ne 'iframe') { - if ($env{'form.extwintabreuse'}) { - $newvalues{$entry} .= ':1'; - } else { - $newvalues{$entry} .= ':0'; - } - if ($env{'form.'.$entry} eq 'window') { - foreach my $dim ('width','height') { - $env{'form.extreswin'.$dim} =~ s/^\s+|\s+$//g; - if ($env{'form.extreswin'.$dim} =~ /^\d+$/) { - $newvalues{$entry} .= ':'.$env{'form.extreswin'.$dim}; - } else { - $newvalues{$entry} .= ':'; - } - } - } - } - } - unless (($newvalues{$entry} eq 'iframe') && ($values->{$entry} eq '')) { - if ($newvalues{$entry} ne $values->{$entry}) { - $changes->{$entry} = $newvalues{$entry}; - } - } - } elsif ($entry eq 'timezone') { - if ($env{'form.'.$entry}) { - $newvalues{$entry} = $env{'form.'.$entry}; - if ($newvalues{$entry} ne $values->{$entry}) { - $changes->{$entry} = $newvalues{$entry}; + } elsif (($entry eq 'lti.topmenu') || ($entry eq 'lti.inlinemenu')) { + if ($env{'form.lti.override'}) { + $newvalues{$entry} = $env{'form.'.$entry}; + } else { + $newvalues{$entry} = ''; } - if ($env{'form.tzover'}) { - $newvalues{'tzover'} = $env{'form.tzover'}; - if ($newvalues{'tzover'} ne $values->{'tzover'}) { - $changes->{'tzover'} = $newvalues{'tzover'}; - } - } elsif ($values->{'tzover'}) { - $changes->{'tzover'} = ''; - } - } elsif ($values->{$entry}) { - $changes->{$entry} = ''; - } - } elsif ($entry eq 'grading') { - if ($env{'form.'.$entry} eq 'standard') { - if ($env{'form.hidetotals'}) { - my %sections = &Apache::loncommon::get_sections($cdom,$cnum); - if (keys(%sections)) { - my @secs = &Apache::loncommon::get_env_multiple('form.hidetotals_sections'); - if (grep(/^all$/,@secs)) { - $newvalues{'hidetotals'} = 'all'; - } elsif (@secs) { - $newvalues{'hidetotals'} = ''; - foreach my $sec (sort {$a <=> $b} @secs) { - if (exists($sections{$sec})) { - $newvalues{'hidetotals'} .= $sec.',' - } + } 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); } - $newvalues{'hidetotals'} =~ s/,$//; } + } + if (@newlcmenu) { + $newvalues{$entry} = join(',',@newlcmenu); } else { - $newvalues{'hidetotals'} = 'all'; + $newvalues{$entry} = 'none'; } + } else { + $newvalues{$entry} = ''; } } - if ($newvalues{'hidetotals'} ne $values->{'hidetotals'}) { - $changes->{'hidetotals'} = $newvalues{'hidetotals'}; - $changes->{'grading'} = $env{'form.'.$entry}; - } - $newvalues{$entry} = $env{'form.'.$entry}; } else { $newvalues{$entry} = $env{'form.'.$entry}; } - unless (($entry eq 'co-owners') || ($entry eq 'discussion_post_fonts') || - ($entry eq 'extresource') || ($entry eq 'timezone')) { + unless (($entry eq 'co-owners') || ($entry eq 'discussion_post_fonts')) { if ($newvalues{$entry} ne $values->{$entry}) { $changes->{$entry} = $newvalues{$entry}; } @@ -1578,250 +1528,23 @@ sub process_changes { return $errors; } -sub process_linkprot { - my ($cdom,$cnum,$values,$changes,$context,$lastactref) = @_; - my ($dest,$ltiauth,$privnum,$cipher,$errors,%linkprot); - if (ref($values) eq 'HASH') { - foreach my $id (keys(%{$values})) { - if ($id =~ /^\d+$/) { - unless (ref($values->{$id}) eq 'HASH') { - $linkprot{$id} = ''; - } - } - } - } - ($cipher,$privnum) = &get_credentials($cdom,$cnum,'lti',$context); - if ($context eq 'domain') { - $dest = '/adm/domainprefs'; - $ltiauth = 1; - } else { - $dest = '/adm/courseprefs'; - if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) { - $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'}; - } else { - my %domdefs = &Apache::lonnet::get_domain_defaults($cdom); - $ltiauth = $domdefs{'crsltiauth'}; - } - } - my $switchserver = &check_switchserver($cdom,$cnum,$context,$dest); - my (@items,%deletions,%itemids,%haschanges); - if ($env{'form.linkprot_add'}) { - my $name = $env{'form.linkprot_name_add'}; - $name =~ s/(`)/'/g; - my ($newid,$error) = &get_linkprot_id($cdom,$cnum,$name,$context); - if ($newid) { - $itemids{'add'} = $newid; - push(@items,'add'); - $haschanges{$newid} = 1; - } else { - $errors .= ''. - &mt('Failed to acquire unique ID for link protection'). - ''; - } - } - if (ref($values) eq 'HASH') { - my @todelete = &Apache::loncommon::get_env_multiple('form.linkprot_del'); - my $maxnum = $env{'form.linkprot_maxnum'}; - for (my $i=0; $i<$maxnum; $i++) { - my $itemid = $env{'form.linkprot_id_'.$i}; - $itemid =~ s/\D+//g; - if ($itemid) { - if (ref($values->{$itemid}) eq 'HASH') { - push(@items,$i); - $itemids{$i} = $itemid; - if ((@todelete > 0) && (grep(/^$i$/,@todelete))) { - $deletions{$itemid} = $values->{$itemid}->{'name'}; - } - } - } - } - } - foreach my $idx (@items) { - my $itemid = $itemids{$idx}; - next unless ($itemid); - if (exists($deletions{$itemid})) { - $linkprot{$itemid} = $deletions{$itemid}; - $haschanges{$itemid} = 1; - next; - } - my %current; - if (ref($values) eq 'HASH') { - if (ref($values->{$itemid}) eq 'HASH') { - foreach my $key (keys(%{$values->{$itemid}})) { - $current{$key} = $values->{$itemid}->{$key}; - } - } - } - foreach my $inner ('name','lifetime','version') { - my $formitem = 'form.linkprot_'.$inner.'_'.$idx; - $env{$formitem} =~ s/(`)/'/g; - if ($inner eq 'lifetime') { - $env{$formitem} =~ s/[^\d.]//g; - } - unless ($idx eq 'add') { - if ($current{$inner} ne $env{$formitem}) { - $haschanges{$itemid} = 1; - } - } - if ($env{$formitem} ne '') { - $linkprot{$itemid}{$inner} = $env{$formitem}; - } - } - my $urlitem = 'form.linkprot_returnurl_'.$idx; - my $urlparamname = 'form.linkprot_urlparam_'.$idx; - if ($env{$urlitem} == 1) { - $env{$urlparamname} =~ s/(`)/'/g; - } 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; - unless ($idx eq 'add') { - if ((!$current{'requser'} && $env{$reqitem}) || - ($current{'requser'} && !$env{$reqitem})) { - $haschanges{$itemid} = 1; - } - } - if ($env{$reqitem} == 1) { - $linkprot{$itemid}{'requser'} = $env{$reqitem}; - foreach my $inner ('mapuser','notstudent') { - my $formitem = 'form.linkprot_'.$inner.'_'.$idx; - $env{$formitem} =~ s/(`)/'/g; - if ($inner eq 'mapuser') { - if ($env{$formitem} eq 'other') { - my $mapuser = $env{'form.linkprot_customuser_'.$idx}; - $mapuser =~ s/(`)/'/g; - $mapuser =~ s/^\s+|\s+$//g; - if ($mapuser ne '') { - $linkprot{$itemid}{$inner} = $mapuser; - } else { - delete($linkprot{$itemid}{'requser'}); - last; - } - } elsif ($env{$formitem} eq 'sourcedid') { - $linkprot{$itemid}{$inner} = 'lis_person_sourcedid'; - } elsif ($env{$formitem} eq 'email') { - $linkprot{$itemid}{$inner} = 'lis_person_contact_email_primary'; - } - } else { - $linkprot{$itemid}{$inner} = $env{$formitem}; - } - unless ($idx eq 'add') { - if ($current{$inner} ne $linkprot{$itemid}{$inner}) { - $haschanges{$itemid} = 1; - } - } - } - } - } - unless ($switchserver) { - my $keyitem = 'form.linkprot_key_'.$idx; - $env{$keyitem} =~ s/(`)/'/g; - unless ($idx eq 'add') { - if ($current{'key'} ne $env{$keyitem}) { - $haschanges{$itemid} = 1; - } - } - if ($env{$keyitem} ne '') { - $linkprot{$itemid}{'key'} = $env{$keyitem}; - } - my $secretitem = 'form.linkprot_secret_'.$idx; - $env{$secretitem} =~ s/(`)/'/g; - if ($current{'usable'}) { - if ($env{'form.linkprot_changesecret_'.$idx}) { - if ($env{$secretitem} ne '') { - if ($privnum && $cipher) { - $linkprot{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem}); - $linkprot{$itemid}{'cipher'} = $privnum; - } else { - $linkprot{$itemid}{'secret'} = $env{$secretitem}; - } - $haschanges{$itemid} = 1; - } - } else { - $linkprot{$itemid}{'secret'} = $current{'secret'}; - $linkprot{$itemid}{'cipher'} = $current{'cipher'}; - } - } elsif ($env{$secretitem} ne '') { - if ($privnum && $cipher) { - $linkprot{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem}); - $linkprot{$itemid}{'cipher'} = $privnum; - } else { - $linkprot{$itemid}{'secret'} = $env{$secretitem}; - } - $haschanges{$itemid} = 1; - } - } - } - if (keys(%haschanges)) { - foreach my $entry (keys(%haschanges)) { - $changes->{$entry} = $linkprot{$entry}; - } - if (ref($lastactref) eq 'HASH') { - $lastactref->{'courselti'} = 1; - } - } - return $errors; -} - -sub get_linkprot_id { - my ($cdom,$cnum,$name,$context) = @_; - # get lock on lti db in course or linkprot db in domain +sub get_courselti_id { + my ($cdom,$cnum,$name) = @_; + # get lock on lti db in course my $lockhash = { lock => $env{'user.name'}. ':'.$env{'user.domain'}, }; my $tries = 0; - my $gotlock; - if ($context eq 'domain') { - $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom); - } else { - $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum); - } + my $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum); my ($id,$error); while (($gotlock ne 'ok') && ($tries<10)) { $tries ++; sleep (0.1); - if ($context eq 'domain') { - $gotlock = &Apache::lonnet::newput_dom('linkprot',$lockhash,$cdom); - } else { - $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum); - } + $gotlock = &Apache::lonnet::newput('lti',$lockhash,$cdom,$cnum); } if ($gotlock eq 'ok') { - my %currids; - if ($context eq 'domain') { - %currids = &Apache::lonnet::dump_dom('linkprot',$cdom); - } else { - %currids = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1); - } + my %currids = &Apache::lonnet::dump('lti',$cdom,$cnum,undef,undef,undef,1); if ($currids{'lock'}) { delete($currids{'lock'}); if (keys(%currids)) { @@ -1835,629 +1558,20 @@ sub get_linkprot_id { $id = 1; } if ($id) { - if ($context eq 'domain') { - unless (&Apache::lonnet::newput_dom('linkprot',{ $id => $name },$cdom) eq 'ok') { - $error = 'nostore'; - } - } else { - unless (&Apache::lonnet::newput('lti',{ $id => $name },$cdom,$cnum) eq 'ok') { - $error = 'nostore'; - } + unless (&Apache::lonnet::newput('lti',{ $id => $name },$cdom,$cnum) eq 'ok') { + $error = 'nostore'; } } else { $error = 'nonumber'; } } - my $dellockoutcome; - if ($context eq 'domain') { - $dellockoutcome = &Apache::lonnet::del_dom('linkprot',['lock'],$cdom); - } else { - $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum); - } + my $dellockoutcome = &Apache::lonnet::del('lti',['lock'],$cdom,$cnum); } else { $error = 'nolock'; } return ($id,$error); } -sub get_credentials { - my ($cdom,$cnum,$type,$context) = @_; - my ($cipher,$privnum,$home); - my %domdefs = &Apache::lonnet::get_domain_defaults($cdom); - my @ids=&Apache::lonnet::current_machine_ids(); - if ($context eq 'domain') { - $home = &Apache::lonnet::domain($cdom,'primary'); - } else { - $home = &Apache::lonnet::homeserver($cnum,$cdom); - } - my ($hostskey,$domkey,$crskey); - if ($type eq 'ltitools') { - $hostskey = 'toolprivhosts'; - $domkey = 'toolenc_dom'; - $crskey = 'toolenc_crs'; - } else { - $hostskey = 'ltiprivhosts'; - $domkey = 'linkprotenc_dom'; - $crskey = 'linkprotenc_crs'; - } - if ((($context eq 'domain') && ($domdefs{$domkey})) || - (($context eq 'course') && ($domdefs{$crskey}))) { - unless (($home eq 'no_host') || ($home eq '')) { - if (grep(/^\Q$home\E$/,@ids)) { - if (ref($domdefs{$hostskey}) eq 'ARRAY') { - if (grep(/^\Q$home\E$/,@{$domdefs{$hostskey}})) { - my %privhash = &Apache::lonnet::restore_dom($type,'private',$cdom,$home,1); - my $privkey = $privhash{'key'}; - $privnum = $privhash{'version'}; - if (($privnum) && ($privkey ne '')) { - $cipher = Crypt::CBC->new({'key' => $privkey, - 'cipher' => 'DES'}); - } - } - } - } - } - } - return ($cipher,$privnum); -} - -sub process_ltitools { - my ($r,$cdom,$cnum,$values,$changes,$context,$lastactref,$configuserok,$lonhost, - $author_ok,$confname) = @_; - my (%currconfig,$newid,@allpos,%changes,%ltitools,$errors); - - 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 ($dest,$privnum,$cipher); - - ($cipher,$privnum) = &get_credentials($cdom,$cnum,'ltitools',$context); - if ($context eq 'domain') { - $dest = '/adm/domainprefs'; - } else { - $dest = '/adm/courseprefs'; - } - my $switchserver = &check_switchserver($cdom,$cnum,$context,$dest); - - my (@allpos,@items,%deletions,%itemids,%haschanges); - if ($env{'form.ltitools_add'}) { - my $title = $env{'form.ltitools_add_title'}; - $title =~ s/(`)/'/g; - my ($newid,$error) = &Apache::lonnet::get_ltitools_id($context,$cdom,$cnum,$title); - if ($newid) { - my $position = $env{'form.ltitools_add_pos'}; - $position =~ s/\D+//g; - if ($position ne '') { - $allpos[$position] = $newid; - } - $haschanges{$newid} = 1; - foreach my $item ('title','url','lifetime') { - $env{'form.ltitools_add_'.$item} =~ s/(`)/'/g; - if ($item eq 'lifetime') { - $env{'form.ltitools_add_'.$item} =~ s/[^\d.]//g; - } - if ($env{'form.ltitools_add_'.$item}) { - $ltitools{$newid}{$item} = $env{'form.ltitools_add_'.$item}; - } - } - if ($env{'form.ltitools_add_version'} eq 'LTI-1p0') { - $ltitools{$newid}{'version'} = $env{'form.ltitools_add_version'}; - } - if ($env{'form.ltitools_add_msgtype'} eq 'basic-lti-launch-request') { - $ltitools{$newid}{'msgtype'} = $env{'form.ltitools_add_msgtype'}; - } - if ($env{'form.ltitools_add_sigmethod'} eq 'HMAC-SHA256') { - $ltitools{$newid}{'sigmethod'} = $env{'form.ltitools_add_sigmethod'}; - } else { - $ltitools{$newid}{'sigmethod'} = 'HMAC-SHA1'; - } - foreach my $item ('width','height','linktext','explanation') { - $env{'form.ltitools_add_'.$item} =~ s/^\s+//; - $env{'form.ltitools_add_'.$item} =~ s/\s+$//; - if (($item eq 'width') || ($item eq 'height')) { - if ($env{'form.ltitools_add_'.$item} =~ /^\d+$/) { - $ltitools{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item}; - } - } else { - if ($env{'form.ltitools_add_'.$item} ne '') { - $ltitools{$newid}{'display'}{$item} = $env{'form.ltitools_add_'.$item}; - } - } - } - if ($env{'form.ltitools_add_target'} eq 'window') { - $ltitools{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'}; - } elsif ($env{'form.ltitools_add_target'} eq 'tab') { - $ltitools{$newid}{'display'}{'target'} = $env{'form.ltitools_add_target'}; - } else { - $ltitools{$newid}{'display'}{'target'} = 'iframe'; - } - foreach my $item ('passback','roster') { - if ($env{'form.ltitools_'.$item.'_add'}) { - $ltitools{$newid}{$item} = 1; - if ($env{'form.ltitools_'.$item.'valid_add'} ne '') { - my $lifetime = $env{'form.ltitools_'.$item.'valid_add'}; - $lifetime =~ s/^\s+|\s+$//g; - if ($lifetime =~ /^\d+\.?\d*$/) { - $ltitools{$newid}{$item.'valid'} = $lifetime; - } - } - } - } - if ($env{'form.ltitools_add_image.filename'} ne '') { - my ($imageurl,$error) = - &process_ltitools_image($r,$context,$cdom,$cnum,$confname,'ltitools_add_image', - $newid,$configuserok,$lonhost,$author_ok); - if ($imageurl) { - $ltitools{$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})) { - $ltitools{$newid}{'roles'}{$role} = $choice; - if ($role eq 'cc') { - $ltitools{$newid}{'roles'}{'co'} = $choice; - } - } - } - } else { - $ltitools{$newid}{'fields'}{$field} = 1; - } - } - } - if (ref($ltitools{$newid}{'fields'}) eq 'HASH') { - if ($ltitools{$newid}{'fields'}{'user'}) { - if ($env{'form.ltitools_add_userincdom'}) { - $ltitools{$newid}{'incdom'} = 1; - } - } - } - my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_add_courseconfig'); - foreach my $item (@courseconfig) { - $ltitools{$newid}{'crsconf'}{$item} = 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; - $ltitools{$newid}{'custom'}{$name} = $value; - } - unless ($switchserver) { - my $keyitem = 'form.ltitools_add_key'; - $env{$keyitem} =~ s/(`)/'/g; - if ($env{$keyitem} ne '') { - $ltitools{$newid}{'key'} = $env{$keyitem}; - } - my $secretitem = 'form.ltitools_secret_add'; - $env{$secretitem} =~ s/(`)/'/g; - if ($env{$secretitem} ne '') { - if ($privnum && $cipher) { - $ltitools{$newid}{'secret'} = $cipher->encrypt_hex($env{$secretitem}); - $ltitools{$newid}{'cipher'} = $privnum; - } else { - $ltitools{$newid}{'secret'} = $env{$secretitem}; - } - } - } - } else { - $errors .= '
  • '. - &mt('Failed to acquire unique ID for new external tool'). - '
  • '; - } - } - if (ref($values) 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}; - $itemid =~ s/\D+//g; - if (ref($values->{$itemid}) eq 'HASH') { - if ($deletions{$itemid}) { - if ($values->{$itemid}{'image'}) { - #FIXME need to obsolete item in RES space - } - $haschanges{$itemid} = $values->{$itemid}{'title'}; - next; - } else { - my $newpos = $env{'form.ltitools_'.$itemid}; - $newpos =~ s/\D+//g; - foreach my $item ('title','url','lifetime') { - $ltitools{$itemid}{$item} = $env{'form.ltitools_'.$item.'_'.$i}; - if ($values->{$itemid}{$item} ne $ltitools{$itemid}{$item}) { - $haschanges{$itemid} = 1; - } - } - if ($env{'form.ltitools_version_'.$i} eq 'LTI-1p0') { - $ltitools{$itemid}{'version'} = $env{'form.ltitools_version_'.$i}; - } - if ($env{'form.ltitools_msgtype_'.$i} eq 'basic-lti-launch-request') { - $ltitools{$itemid}{'msgtype'} = $env{'form.ltitools_msgtype_'.$i}; - } - if ($env{'form.ltitools_sigmethod_'.$i} eq 'HMAC-SHA256') { - $ltitools{$itemid}{'sigmethod'} = $env{'form.ltitools_sigmethod_'.$i}; - } else { - $ltitools{$itemid}{'sigmethod'} = 'HMAC-SHA1'; - } - if ($values->{$itemid}{'sigmethod'} eq '') { - if ($ltitools{$itemid}{'sigmethod'} ne 'HMAC-SHA1') { - $haschanges{$itemid} = 1; - } - } elsif ($values->{$itemid}{'sigmethod'} ne $ltitools{$itemid}{'sigmethod'}) { - $haschanges{$itemid} = 1; - } - 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+$/) { - $ltitools{$itemid}{'display'}{$size} = $env{'form.ltitools_'.$size.'_'.$i}; - if (ref($values->{$itemid}{'display'}) eq 'HASH') { - if ($values->{$itemid}{'display'}{$size} ne $ltitools{$itemid}{'display'}{$size}) { - $haschanges{$itemid} = 1; - } - } else { - $haschanges{$itemid} = 1; - } - } elsif (ref($values->{$itemid}{'display'}) eq 'HASH') { - if ($values->{$itemid}{'display'}{$size} ne '') { - $haschanges{$itemid} = 1; - } - } - } - foreach my $item ('linktext','explanation') { - $env{'form.ltitools_'.$item.'_'.$i} =~ s/^\s+//; - $env{'form.ltitools_'.$item.'_'.$i} =~ s/\s+$//; - if ($env{'form.ltitools_'.$item.'_'.$i} ne '') { - $ltitools{$itemid}{'display'}{$item} = $env{'form.ltitools_'.$item.'_'.$i}; - if (ref($values->{$itemid}{'display'}) eq 'HASH') { - if ($values->{$itemid}{'display'}{$item} ne $ltitools{$itemid}{'display'}{$item}) { - $haschanges{$itemid} = 1; - } - } else { - $haschanges{$itemid} = 1; - } - } elsif (ref($values->{$itemid}{'display'}) eq 'HASH') { - if ($values->{$itemid}{'display'}{$item} ne '') { - $haschanges{$itemid} = 1; - } - } - } - if ($env{'form.ltitools_target_'.$i} eq 'window') { - $ltitools{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i}; - } elsif ($env{'form.ltitools_target_'.$i} eq 'tab') { - $ltitools{$itemid}{'display'}{'target'} = $env{'form.ltitools_target_'.$i}; - } else { - $ltitools{$itemid}{'display'}{'target'} = 'iframe'; - } - if (ref($values->{$itemid}{'display'}) eq 'HASH') { - if ($values->{$itemid}{'display'}{'target'} ne $ltitools{$itemid}{'display'}{'target'}) { - $haschanges{$itemid} = 1; - } - } else { - $haschanges{$itemid} = 1; - } - foreach my $extra ('passback','roster') { - if ($env{'form.ltitools_'.$extra.'_'.$i}) { - $ltitools{$itemid}{$extra} = 1; - if ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') { - my $lifetime = $env{'form.ltitools_'.$extra.'valid_'.$i}; - $lifetime =~ s/^\s+|\s+$//g; - if ($lifetime =~ /^\d+\.?\d*$/) { - $ltitools{$itemid}{$extra.'valid'} = $lifetime; - } - } - } - if ($values->{$itemid}{$extra} ne $ltitools{$itemid}{$extra}) { - $haschanges{$itemid} = 1; - } - if ($values->{$itemid}{$extra.'valid'} ne $ltitools{$itemid}{$extra.'valid'}) { - $haschanges{$itemid} = 1; - } - } - my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i); - foreach my $item ('label','title','target','linktext','explanation','append') { - if (grep(/^\Q$item\E$/,@courseconfig)) { - $ltitools{$itemid}{'crsconf'}{$item} = 1; - if (ref($values->{$itemid}{'crsconf'}) eq 'HASH') { - if ($values->{$itemid}{'crsconf'}{$item} ne $ltitools{$itemid}{'crsconf'}{$item}) { - $haschanges{$itemid} = 1; - } - } else { - $haschanges{$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})) { - $ltitools{$itemid}{'roles'}{$role} = $choice; - if ($role eq 'cc') { - $ltitools{$itemid}{'roles'}{'co'} = $choice; - } - } - if (ref($values->{$itemid}{'roles'}) eq 'HASH') { - if ($values->{$itemid}{'roles'}{$role} ne $ltitools{$itemid}{'roles'}{$role}) { - $haschanges{$itemid} = 1; - } - } elsif ($ltitools{$itemid}{'roles'}{$role}) { - $haschanges{$itemid} = 1; - } - } - } else { - $ltitools{$itemid}{'fields'}{$field} = 1; - if (ref($values->{$itemid}{'fields'}) eq 'HASH') { - if ($values->{$itemid}{'fields'}{$field} ne $ltitools{$itemid}{'fields'}{$field}) { - $haschanges{$itemid} = 1; - } - } else { - $haschanges{$itemid} = 1; - } - } - } - } - if (ref($ltitools{$itemid}{'fields'}) eq 'HASH') { - if ($ltitools{$itemid}{'fields'}{'user'}) { - if ($env{'form.ltitools_userincdom_'.$i}) { - $ltitools{$itemid}{'incdom'} = 1; - } - if ($values->{$itemid}{'incdom'} ne $ltitools{$itemid}{'incdom'}) { - $haschanges{$itemid} = 1; - } - } - } - $allpos[$newpos] = $itemid; - } - if ($imgdeletions{$itemid}) { - $haschanges{$itemid} = 1; - if ($context eq 'course') { - my $currimgurl = $values->{$itemid}{'image'}; - if ($currimgurl =~ m{^(\Q/uploaded/$cdom/$cnum/toollogo/$itemid\E)/([^/]+)$}) { - my ($path,$imagefile) = ($1,$2); - if ($imagefile =~ /^tn\-(.+)$/) { - my $origimg = $1; - &Apache::lonnet::removeuploadedurl("$path/$origimg"); - } - &Apache::lonnet::removeuploadedurl($currimgurl); - } - } - #FIXME need to obsolete item in RES space - } elsif ($env{'form.ltitools_image_'.$i.'.filename'}) { - my $currimgurl = $values->{$itemid}{'image'}; - my ($imgurl,$error) = &process_ltitools_image($r,$context,$cdom,$cnum,$confname,'ltitools_image_'.$i, - $itemid,$configuserok,$lonhost,$author_ok,$currimgurl); - if ($imgurl) { - $ltitools{$itemid}{'image'} = $imgurl; - $haschanges{$itemid} = 1; - } - if ($error) { - &Apache::lonnet::logthis($error); - $errors .= '
  • '.$error.'
  • '; - } - } elsif ($values->{$itemid}{'image'}) { - $ltitools{$itemid}{'image'} = $values->{$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 '') { - $ltitools{$itemid}{'custom'}{$name} = $value; - $haschanges{$itemid} = 1; - } - } - my %customdels; - my @customdeletions = &Apache::loncommon::get_env_multiple('form.ltitools_customdel_'.$i); - if (@customdeletions) { - $haschanges{$itemid} = 1; - } - map { $customdels{$_} = 1; } @customdeletions; - if (ref($values->{$itemid}{'custom'}) eq 'HASH') { - foreach my $key (keys(%{$values->{$itemid}{'custom'}})) { - unless ($customdels{$key}) { - if ($env{'form.ltitools_customval_'.$key.'_'.$i} ne '') { - $ltitools{$itemid}{'custom'}{$key} = $env{'form.ltitools_customval_'.$key.'_'.$i}; - } - if ($values->{$itemid}{'custom'}{$key} ne $env{'form.ltitools_customval_'.$key.'_'.$i}) { - $haschanges{$itemid} = 1; - } - } - } - } - unless ($switchserver) { - my $keyitem = 'form.ltitools_key_'.$i; - $env{$keyitem} =~ s/(`)/'/g; - if ($values->{$itemid}{'key'} ne $env{$keyitem}) { - $haschanges{$itemid} = 1; - } - if ($env{$keyitem} ne '') { - $ltitools{$itemid}{'key'} = $env{$keyitem}; - } - my $secretitem = 'form.ltitools_secret_'.$i; - $env{$secretitem} =~ s/(`)/'/g; - if ($values->{$itemid}{'usable'}) { - if ($env{'form.ltitools_changesecret_'.$i}) { - if ($env{$secretitem} ne '') { - if ($privnum && $cipher) { - $ltitools{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem}); - $ltitools{$itemid}{'cipher'} = $privnum; - } else { - $ltitools{$itemid}{'secret'} = $env{$secretitem}; - } - $haschanges{$itemid} = 1; - } - } else { - $ltitools{$itemid}{'secret'} = $values->{$itemid}{'secret'}; - $ltitools{$itemid}{'cipher'} = $values->{$itemid}{'cipher'}; - } - } elsif ($env{$secretitem} ne '') { - if ($privnum && $cipher) { - $ltitools{$itemid}{'secret'} = $cipher->encrypt_hex($env{$secretitem}); - $ltitools{$itemid}{'cipher'} = $privnum; - } else { - $ltitools{$itemid}{'secret'} = $env{$secretitem}; - } - $haschanges{$itemid} = 1; - } - } - unless ($haschanges{$itemid}) { - foreach my $key (keys(%{$values->{$itemid}})) { - if (ref($values->{$itemid}{$key}) eq 'HASH') { - if (ref($ltitools{$itemid}{$key}) eq 'HASH') { - foreach my $innerkey (keys(%{$values->{$itemid}{$key}})) { - unless (exists($ltitools{$itemid}{$key}{$innerkey})) { - $haschanges{$itemid} = 1; - last; - } - } - } elsif (keys(%{$values->{$itemid}{$key}}) > 0) { - $haschanges{$itemid} = 1; - } - } - last if ($haschanges{$itemid}); - } - } - } - } - } - if (@allpos > 0) { - my $idx = 0; - foreach my $itemid (@allpos) { - if ($itemid ne '') { - $ltitools{$itemid}{'order'} = $idx; - if (ref($values) eq 'HASH') { - if (ref($values->{$itemid}) eq 'HASH') { - if ($values->{$itemid}{'order'} ne $idx) { - $haschanges{$itemid} = 1; - } - } - } - $idx ++; - } - } - } - if (keys(%haschanges)) { - foreach my $entry (keys(%haschanges)) { - $changes->{$entry} = $ltitools{$entry}; - } - if (ref($lastactref) eq 'HASH') { - $lastactref->{'courseltitools'} = 1; - } - } - return $errors; -} - -sub process_ltitools_image { - my ($r,$context,$dom,$cnum,$confname,$caller,$itemid,$configuserok,$switch,$author_ok,$currimg) = @_; - my $filename = $env{'form.'.$caller.'.filename'}; - my ($error,$url); - my ($width,$height) = (21,21); - if ($configuserok eq 'ok') { - if ($switch) { - $error = &mt('Upload of Tool Provider (LTI) icon is not permitted to this server: [_1]', - $switch); - } elsif ($author_ok eq 'ok') { - my ($result,$imageurl,$madethumb); - if ($context eq 'domain') { - ($result,$imageurl,$madethumb) = - &Apache::lonconfigsettings::publishlogo($r,'upload',$caller,$dom,$confname, - "ltitools/$itemid/icon",$width,$height); - } else { - ($result,$imageurl,$madethumb) = &processlogo($dom,$cnum,$caller,$currimg,$itemid,$width,$height); - } - if ($result eq 'ok') { - if ($madethumb) { - my ($path,$imagefile) = ($imageurl =~ m{^(.+)/([^/]+)$}); - my $imagethumb = "$path/tn-".$imagefile; - $url = $imagethumb; - } else { - $url = $imageurl; - } - } else { - if ($context eq 'domain') { - $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 error occurred. 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 processlogo { - my ($dom,$cnum,$caller,$currimg,$itemid,$width,$height) = @_; - my ($result,$imageurl,$madethumb); - if ($env{"form.$caller.filename"} ne '') { - unless ($caller eq 'ltitools_add_image') { - if ($currimg =~ m{^(\Q/uploaded/$dom/$cnum/toollogo/$itemid\E)/([^/]+)$}) { - my ($path,$imagefile) = ($1,$2); - if ($imagefile =~ /^tn\-(.+)$/) { - my $origimg = $1; - &Apache::lonnet::removeuploadedurl("$path/$origimg"); - } - &Apache::lonnet::removeuploadedurl($currimg); - } - } - $imageurl = &Apache::lonnet::userfileupload($caller,'toollogo',"toollogo/$itemid", - '','','',$cnum,$dom,$width,$height); - if ($imageurl =~ m{^(\Q/uploaded/$dom/$cnum/toollogo/$itemid\E)/([^/]+)$}) { - my ($path,$imagefile) = ($1,$2); - $result = 'ok'; - my $thumburl = "$path/tn-".$imagefile; - my ($rtncode,$info); - my $res = &Apache::lonnet::getuploaded('HEAD',$thumburl,$dom,$cnum,\$info,\$rtncode); - if ($res eq 'ok') { - $madethumb = 1; - } - } elsif ($imageurl eq '/adm/notfound.html') { - undef($imageurl); - $result = 'store failed'; - } elsif ($imageurl =~ /^error: (.+)$/) { - $result = $1; - } - } - return ($result,$imageurl,$madethumb); -} - sub get_sec_str { my ($entry,$num) = @_; my @secs = &Apache::loncommon::get_env_multiple('form.'.$entry.'_sections_'.$num); @@ -2500,15 +1614,12 @@ sub check_clone { sub store_changes { my ($cdom,$cnum,$prefs_order,$actions,$prefs,$values,$changes,$crstype) = @_; my ($chome,$output); - my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot,%oldltitools); + my (%storehash,@delkeys,@need_env_update,@oldcloner,%oldlinkprot); if ((ref($values) eq 'HASH') && (ref($changes) eq 'HASH')) { - if (ref($values->{'linkprot'}) eq 'HASH') { - %oldlinkprot = %{$values->{'linkprot'}}; - } - delete($values->{'linkprot'}); - if (ref($values->{'ltitools'}) eq 'HASH') { - %oldltitools = %{$values->{'ltitools'}}; + if (ref($values->{'linkprotection'}) eq 'HASH') { + %oldlinkprot = %{$values->{'linkprotection'}}; } + delete($values->{'linkprotection'}); %storehash = %{$values}; } else { if ($crstype eq 'Community') { @@ -2521,9 +1632,7 @@ sub store_changes { my ($numchanges,$skipstore); if (ref($changes) eq 'HASH') { $numchanges = scalar(keys(%{$changes})); - if (($numchanges == 1) && (exists($changes->{'linkprot'}))) { - $skipstore = 1; - } elsif (($numchanges == 1) && (exists($changes->{'ltitools'}))) { + if (($numchanges == 1) && (exists($changes->{'linkprotection'}))) { $skipstore = 1; } elsif (!$numchanges) { if ($crstype eq 'Community') { @@ -2546,7 +1655,7 @@ sub store_changes { if (grep(/^\Q$item\E$/,@{$actions})) { $output .= '

    '.&mt($prefs->{$item}{'text'}).'

    '; if (ref($changes->{$item}) eq 'HASH') { - if (keys(%{$changes->{$item}}) > 0) { + if ((keys(%{$changes->{$item}}) > 0) || ($item eq 'linkprotection')) { $output .= &mt('Changes made:').''. ''. &Apache::loncommon::end_data_table_header_row(). &Apache::loncommon::start_data_table_row(). ''); - &releases_by_map($r,$bymap,$topmap,$scopeorder,$lt); - $r->print(&Apache::loncommon::end_data_table_row()); + &releases_by_map($r,$bymap,$topmap,$scopeorder,$lt); + $r->print(&Apache::loncommon::end_data_table_row()); my $it=$navmap->getIterator(undef,undef,undef,1,1,undef); my $curRes; my $depth = 0; @@ -4925,6 +3562,9 @@ sub show_contents_view { if (ref($byresponsetype->{$symb}) eq 'HASH') { $rowspan += scalar(keys(%{$byresponsetype->{$symb}})); } + if (ref($bycrsrestype->{$symb}) eq 'HASH') { + $rowspan += scalar(keys(%{$bycrsrestype->{$symb}})); + } next if (!$rowspan); $icon = ''.
                             &mt('Problem').''; @@ -4989,10 +3629,37 @@ sub show_contents_view { $r->print(''); } $r->print(&Apache::loncommon::end_data_table_row()); + $newrow = 1; + } + if (ref($bycrsrestype->{$symb}) eq 'HASH') { + foreach my $rev (sort(keys(%{$bycrsrestype->{$symb}}))) { + if ($newrow) { + $r->print(&Apache::loncommon::continue_data_table_row()); + } + $r->print(''); + } + $r->print(&Apache::loncommon::end_data_table_row()); } } } } + } + if ($supptools) { + my $icon = ''; + $r->print(&Apache::loncommon::start_data_table_header_row(). + ''. + ''. + &Apache::loncommon::end_data_table_header_row(). + &Apache::loncommon::start_data_table_row(). + ''. + ''. + &Apache::loncommon::end_data_table_row()); + } + if ($showmaincontent || $supptools) { $r->print(&Apache::loncommon::end_data_table()); } return; @@ -5001,7 +3668,7 @@ sub show_contents_view { sub releases_by_map { my ($r,$bymap,$url,$scopeorder,$lt) = @_; return unless ((ref($bymap) eq 'HASH') && (ref($scopeorder) eq 'ARRAY')); - my $newrow = 0; + my $newrow = 0; if (ref($bymap->{$url}) eq 'HASH') { foreach my $rev (sort(keys(%{$bymap->{$url}}))) { if ($newrow) { @@ -5038,18 +3705,67 @@ sub releases_by_map { } sub get_param_description { - my ($stdtype,$value) = @_; - my $name = $value; - my $paramstrings = &Apache::lonparmset::standard_string_options($stdtype); - unless (ref($paramstrings) eq 'ARRAY') { - return $name; + my ($stdtype,$value,$regexp) = @_; + my ($name,$parammatches,$paramstrings,@possibles); + if ($stdtype =~ /^string/) { + $paramstrings = &Apache::lonparmset::standard_string_options($stdtype); + } elsif ($stdtype eq 'date_interval') { + $paramstrings = &Apache::lonparmset::standard_interval_options($stdtype); + } + if ($regexp) { + if ($stdtype =~ /^string/) { + $parammatches = &Apache::lonparmset::standard_string_matches($stdtype); + } elsif ($stdtype eq 'date_interval') { + $parammatches = &Apache::lonparmset::standard_interval_matches($stdtype); + } + if (ref($parammatches) eq 'ARRAY') { + @possibles = @{$parammatches}; + } else { + undef($regexp); + $name = $value; + } } - foreach my $possibilities (@{$paramstrings}) { + unless ($regexp) { + $name = $value; + if (ref($paramstrings) eq 'ARRAY') { + @possibles = @{$paramstrings}; + } else { + if (($stdtype eq 'date_start') || ($stdtype eq 'date_end')) { + if ($name == 0) { + $name = &mt('Never'); + } elsif (($name ne '') && ($name !~ /\D/)) { + $name = &Apache::lonlocal::locallocaltime($name); + } + } + return $name; + } + } + foreach my $possibilities (@possibles) { next unless (ref($possibilities) eq 'ARRAY'); - my ($thing, $description) = @{ $possibilities }; - if ($thing eq $value) { - $name = $description; - last; + my $gotregexmatch = ''; + if ($regexp) { + last if ($gotregexmatch); + my ($item,$pattern) = @{ $possibilities }; + if ($value =~ /$pattern/) { + if (ref($paramstrings) eq 'ARRAY') { + foreach my $possibles (@{$paramstrings}) { + next unless (ref($possibles) eq 'ARRAY'); + my ($thing,$description) = @{$possibles}; + if ($thing eq $item) { + $name = $description; + $gotregexmatch = 1; + last; + } + } + last if ($gotregexmatch); + } + } + } else { + my ($thing,$description) = @{ $possibilities }; + if ($thing eq $value) { + $name = $description; + last; + } } } return $name; @@ -5244,23 +3960,9 @@ sub print_localization { if ($item eq 'timezone') { my $includeempty = 1; my $timezone = &Apache::lonlocal::gettimezone(); - my $onchange; - unless ($noedit) { - $onchange = ' onchange="javascript:toggleTimeZone();"'; - } - my $id = ' id="LC_set_timezone"'; $datatable .= - &Apache::loncommon::select_timezone($item,$timezone,$onchange, - $includeempty,$id,$disabled); - my $tzsty = 'none'; - if ($timezone ne '') { - $tzsty = 'block'; - } - $datatable .= '
    '. - ''. - &mt('Override individual user preference?'). - &yesno_radio('tzover',$settings,undef,1,'',$noedit). - '
    '; + &Apache::loncommon::select_timezone($item,$timezone,undef, + $includeempty,$disabled); } elsif ($item eq 'datelocale') { my $includeempty = 1; my $locale_obj = &Apache::lonlocal::getdatelocale(); @@ -5273,7 +3975,7 @@ sub print_localization { undef,$includeempty,$disabled); } else { if ($settings->{$item} eq '') { - unless ($noedit) { + unless ($noedit) { $datatable .= ''.&Apache::loncommon::end_data_table_row(); - } - $datatable .= &Apache::loncommon::end_data_table().'
    '; + } + $datatable .= &Apache::loncommon::end_data_table().'
    '; } } $datatable .= &item_table_row_end(); @@ -5485,7 +4187,7 @@ sub select_recipient { } sub select_sections { - my ($item,$num,$sections,$selected,$noedit,$allval) = @_; + my ($item,$num,$sections,$selected,$noedit) = @_; my ($output,@currsecs,$allsec,$disabled); if (ref($selected) eq 'ARRAY') { @currsecs = @{$selected}; @@ -5501,24 +4203,16 @@ sub select_sections { my $mult; if (@{$sections} > 1) { $mult = ' multiple="multiple"'; - my $size; if (@{$sections} > 3) { - $size = 4; - } else { - $size = 1 + scalar(@{$sections}); + $mult .= ' size="4"'; } - $mult .= ' size="'.$size.'"'; - } - my $name = $item.'_sections'; - unless ($item eq 'hidetotals') { - $name .= '_'.$num; } - $output = ''. + ' '; foreach my $sec (@{$sections}) { my $is_sel; if ((@currsecs) && (grep(/^\Q$sec\E$/,@currsecs))) { - $is_sel = ' selected="selected"'; + $is_sel = 'selected="selected"'; } $output .= ''; } @@ -5559,6 +4253,20 @@ sub print_discussion { &mt('(specific user(s))'), input => 'checkbox', }, + + 'pac.roles.denied' => { + text => ''.&mt($itemtext->{'pac.roles.denied'}).''. + &Apache::loncommon::help_open_topic("Course_Disable_Anonymous_Discussion").'
    '. + &mt('(role-based)'), + input => 'checkbox', + }, + + 'pac.users.denied' => { + text => ''.&mt($itemtext->{'pac.users.denied'}).'
    '. + &mt('(specific user(s))'), + input => 'checkbox', + }, + 'allow_limited_html_in_feedback' => { text => ''.&mt($itemtext->{'allow_limited_html_in_feedback'}).'', input => 'radio', @@ -5591,7 +4299,7 @@ sub print_discussion { my $colspan; if ($item eq 'allow_limited_html_in_feedback') { $colspan = 2; - } + } $datatable .= &item_table_row_start($items{$item}{text},$count,undef,$colspan); if ($item eq 'plc.roles.denied') { $datatable .= '
    '. ''. ''. - ''. + ''. &Apache::loncommon::end_data_table_row(). &set_discussion_fonts($cdom,$cnum,$item,$settings,$noedit). &Apache::loncommon::end_data_table().'
    '; @@ -5680,7 +4396,7 @@ sub role_checkboxes { my $count = 0; my $disabled; if ($noedit) { - $disabled = ' disabled="disabled"'; + $disabled = ' disabled="disabled"'; } foreach my $role (@roles) { my $checked = ''; @@ -5808,7 +4524,7 @@ sub set_discussion_fonts { sub discussion_vote_classes { my $classorder = ['twoplus','oneplus','zero','oneminus','twominus']; - my %classtitles = &Apache::lonlocal::texthash( + my %classtitles = &Apache::lonlocal::texthash( 'twoplus' => 'Two sigma above mean', 'oneplus' => 'One sigma above mean', 'zero' => 'Within one sigma of mean', @@ -5874,7 +4590,7 @@ sub print_classlists { 'defaultcredits' => { text => ''.&mt($itemtext->{'defaultcredits'}).'', }, - + 'nothideprivileged' => { text => ''.&mt($itemtext->{'nothideprivileged'}).'', input => 'checkbox', @@ -5965,22 +4681,12 @@ sub print_appearance { text => ''.&mt($itemtext->{'inline_chem'}).'', input => 'radio', }, - 'extresource' => { - text => ''.&mt($itemtext->{'extresource'}).'', - input => 'selectbox', - options => { - iframe => 'In iframe', - tab => 'In new tab', - window => 'In pop-up window', - }, - order => ['iframe','tab','window'], - }, ); return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'appearance',$noedit); } sub print_grading { - my ($cdom,$cnum,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { return; } @@ -5991,15 +4697,16 @@ sub print_grading { input => 'selectbox', options => { standard => &mt('Standard: shows points'), + categories => &mt('Categories: shows points according to categories'), external => &mt('External: shows number of completed parts and totals'), externalnototals => &mt('External: shows only number of completed parts'), spreadsheet => &mt('Spreadsheet: (with link to detailed scores)'), }, - order => ['standard','external','externalnototals','spreadsheet'], + order => ['standard','categories','external','externalnototals','spreadsheet'], }, 'rndseed' => { text => ''.&mt($itemtext->{'rndseed'}).''. - '
    '.'
    '. + ''.'
    '. &mt('Modifying this will make problems have different numbers and answers!'). '
    ', input => 'selectbox', @@ -6031,7 +4738,7 @@ sub print_grading { input => 'radio', }, ); - return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'grading',$noedit,$cnum); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'grading',$noedit); } sub print_printouts { @@ -6165,551 +4872,132 @@ sub print_bridgetasks { return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'bridgetasks',$noedit); } -sub print_ltitools { - my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_; - my ($datatable,$disabled,$css_class,$dest); - if ($noedit) { - $disabled = ' disabled="disabled"'; +sub print_lti { + my ($cdom,$settings,$ordered,$itemtext,$rowtotal,$crstype,$noedit) = @_; + unless ((ref($settings) eq 'HASH') && (ref($ordered) eq 'ARRAY') && (ref($itemtext) eq 'HASH')) { + return; } - my $itemcount = 1; - unless ($context eq 'domain') { - my %tooltypes = &Apache::loncommon::usable_exttools(); - unless ($tooltypes{'crs'}) { - my $showtype = 'course'; - if ($crstype eq 'Community') { - $showtype = lc($crstype); - } - $css_class = $itemcount%2?' class="LC_odd_row"':''; - $datatable = '
    '; - $itemcount ++; - return $datatable; } } - my %lt = <itools_names(); - 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; + if ($settings->{'lti.lcmenu'}) { + unless ($settings->{'lti.lcmenu'} eq 'none') { + @current = split(',',$settings->{'lti.lcmenu'}); } + } else { + @current = @domdefs; } - } - - if ($context eq 'domain') { - $dest = '/adm/domainprefs'; } else { - $dest = '/adm/courseprefs'; + @current = @domdefs; } - my ($switchserver,$switchmessage); - $switchserver = &check_switchserver($cdom,$cnum,$context,$dest); - if ($switchserver) { - if ($context eq 'domain') { - $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver); - } elsif ($crstype eq 'Community') { - $switchmessage = &mt("submit from community's home server: [_1].",$switchserver); - } else { - $switchmessage = &mt("submit from course's home server: [_1].",$switchserver); - } + my $numinrow = 3; + my $count = 0; + my $disabled; + if ($noedit) { + $disabled = ' disabled="disabled"'; } - my $maxnum = scalar(keys(%ordered)); - my @courseroles = ('cc','in','ta','ep','st'); - my @ltiroles = qw(Instructor ContentDeveloper TeachingAssistant Learner); - my @fields = ('fullname','firstname','lastname','email','roles','user'); - 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,$url,$usable,$lifetime,$imgsrc,%sigsel); - if (ref($settings->{$item}) eq 'HASH') { - $title = $settings->{$item}->{'title'}; - $url = $settings->{$item}->{'url'}; - $key = $settings->{$item}->{'key'}; - $usable = $settings->{$item}->{'usable'}; - $lifetime = $settings->{$item}->{'lifetime'}; - my $image = $settings->{$item}->{'image'}; - if ($image ne '') { - $imgsrc = ''.&mt('Tool Provider icon').''; - } - if ($settings->{$item}->{'sigmethod'} eq 'HMAC-256') { - $sigsel{'HMAC-256'} = ' selected="selected"'; - } else { - $sigsel{'HMAC-SHA1'} = ' selected="selected"'; - } - } - my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"'; - $datatable .= ''. - ''."\n"; - $itemcount ++; + my $output = '
    '. - $settings->{'suggested'}->{$key}->{'name'}.'
    '.
    -                                      $settings->{'suggested'}->{$key}->{'info'}.
    -                                      '
    '.&mt('Recommendation(s) for specific launcher application(s)').'
    '.&mt('Launcher Application').''.&mt('Recommendation(s)').'
    '.&mt($item->{'header'}->[0]->{'col1'}).''.$rev.''.$lt{$type}.''; @@ -4726,18 +3344,25 @@ sub display_loncaparev_constraints { if (defined($navmap)) { my %anonsubms=&Apache::lonnet::dump('nohist_anonsurveys',$cdom,$cnum); - my $rev_anonsurv=$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'}; + my $rev_anonsurv=$Apache::lonnet::needsrelease{'parameter:type:anonsurvey::'}; my %randtrysubms=&Apache::lonnet::dump('nohist_randomizetry',$cdom,$cnum); - my $rev_randtry=$Apache::lonnet::needsrelease{'parameter:type:randomizetry'}; + my $rev_randtry=$Apache::lonnet::needsrelease{'parameter:type:randomizetry::'}; + my $rev_exttool=$Apache::lonnet::needsrelease{'course:courserestype:exttool'}; my $stdtype=&Apache::lonparmset::standard_parameter_types('type'); my $stdname=&Apache::lonparmset::standard_parameter_names('type'); my $valanon=&get_param_description($stdtype,'anonsurvey'); my $valrandtry=&get_param_description($stdtype,'randomizetry'); my %checkedrev; - foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_problem() },1,0)) { + foreach my $res ($navmap->retrieveResources(undef,sub { $_[0]->is_problem() || $_[0]->is_tool() },1,0)) { my @parts = @{$res->parts()}; my $symb = $res->symb(); my $enclosing_map = &Apache::lonnet::declutter($res->enclosing_map_src()); + if ($res->is_tool()) { + my $rev = $rev_exttool; + $bycrsrestype{$symb}{$rev} = &mt('External Tool'); + $allmaps{$enclosing_map} = 1; + next; + } foreach my $part (@parts) { if (exists($anonsubms{$symb."\0".$part})) { my $rev = $rev_anonsurv; @@ -4788,7 +3413,7 @@ sub display_loncaparev_constraints { &Apache::lonrelrequtils::update_reqd_loncaparev($major,$minor, $reqdmajor,$reqdminor); $checkedrev{$key} = 1; - } + } push(@{$byresponsetype{$symb}{$rev}},$key); $allmaps{$enclosing_map} = 1; } @@ -4825,6 +3450,10 @@ sub display_loncaparev_constraints { } } } + my $suppmap = 'supplemental.sequence'; + my ($suppcount,$supptools,$errors) = (0,0,0); + ($suppcount,$supptools,$errors) = &Apache::loncommon::recurse_supplemental($cnum,$cdom, + $suppmap,$suppcount,$supptools,$errors); my $mapres_header = '

    '. &mt('Requirements for specific folders or resources'). '

    '; @@ -4839,9 +3468,9 @@ sub display_loncaparev_constraints { $r->print($start_page.$top_header); if ($output) { $r->print($output); - if (defined($navmap)) { + if (defined($navmap) || $supptools) { &show_contents_view($r,$navmap,$cid,\%toshow,\%bymap,\%byresource,\%bysubmission, - \%byresponsetype,\@scopeorder,\%lt); + \%byresponsetype,\%bycrsrestype,\@scopeorder,\%lt,$supptools); } $r->print('

    '); } else { @@ -4859,22 +3488,30 @@ sub display_loncaparev_constraints { sub show_contents_view { my ($r,$navmap,$cid,$toshow,$bymap,$byresource,$bysubmission,$byresponsetype, - $scopeorder,$lt) = @_; - if ((keys(%{$toshow}) > 0) || (keys(%{$byresource}) > 0) || - (keys(%{$bysubmission}) > 0) || (keys(%{$byresponsetype}) > 0)) { - my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); - my $whitespace = ''; - my $icon = ''; + $bycrsrestype,$scopeorder,$lt,$supptools) = @_; + my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); + my $whitespace = ''; + my $showmaincontent; + if ((ref($navmap)) && + ((keys(%{$toshow}) > 0) || (keys(%{$byresource}) > 0) || + (keys(%{$bysubmission}) > 0) || (keys(%{$byresponsetype}) > 0) || + (keys(%{$bycrsrestype}) > 0))) { + $showmaincontent = 1; + } + if ($showmaincontent || $supptools) { + $r->print(&Apache::loncommon::start_data_table()); + } + if ($showmaincontent) { + my $icon = ''; my $topmap = $env{'course.'.$cid.'.url'}; - $r->print(&Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(). + $r->print(&Apache::loncommon::start_data_table_header_row(). '
    '.&mt('Location').''.&mt('Release').''.&mt('Attribute/Setting').' '.$icon.' '.&mt('Main Content').''.$rev.''.$bycrsrestype->{$symb}{$rev}.''.&mt('Location').''.&mt('Release').''.&mt('Resource Type').' '.$icon.' '.&mt('Supplemental Content').''. + $Apache::lonrelrequtils::exttool{'major'}.'.'. + $Apache::lonrelrequtils::exttool{'minor'}. + ''.&mt('[quant,_1,External Tool,External Tools]', + $supptools).''. &Apache::loncommon::select_language('languages_0','',1); } @@ -5310,8 +4012,8 @@ sub print_localization { &Apache::loncommon::select_language('languages_'.$num,'',1). ''. ''. @@ -5609,6 +4317,14 @@ sub print_discussion { $datatable .= ''. &user_table($cdom,$item,undef, $settings->{$item},\%lt,$noedit); + } elsif ($item eq 'pac.roles.denied') { + $datatable .= ''. + ''.&role_checkboxes($cdom,$cnum,$item,$settings,undef,undef,$noedit). + '
    '; + } elsif ($item eq 'pac.users.denied') { + $datatable .= '
    '. + &user_table($cdom,$item,undef, + $settings->{$item},\%lt,$noedit); } elsif ($item eq 'allow_limited_html_in_feedback') { $datatable .= &yesno_radio($item,$settings,undef,undef,undef,$noedit); } elsif ($item eq 'allow_discussion_post_editing') { @@ -5628,7 +4344,7 @@ sub print_discussion { ''.&mt('font-size').''.&mt('font-weight').''.&mt('font-style').''.&mt('Other css').''.&mt('Other css').'
    '. - &mt("Definition of external tools is not enabled for this $showtype.").'
    '; - if ($tooltypes{'dom'}) { - $datatable .= &mt("Contact an administrator for the $showtype domain ([_1]) to request this feature be enabled.", - ''.$cdom.''). - '

    '. - &mt("Use of external tools defined at a domain level is enabled, so the $showtype editor can be used to add tool(s), if any have been defined."); + my @menuitems = ('fullname','coursetitle','role','logout','grades'); + my %menutitles = <imenu_titles(); + my ($domdefs,$displaydefs); + if ($env{'request.lti.login'}) { + my %lti = &Apache::lonnet::get_domain_lti($cdom,'provider'); + my @domdefsmenu; + if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') { + if ($lti{$env{'request.lti.login'}}{'topmenu'}) { + $domdefs = &mt('Header shown').', '; + } + if ($lti{$env{'request.lti.login'}}{'inlinemenu'}) { + $domdefs .= &mt('Inline menu shown'); + } + $domdefs =~ s/,\s$//; + if (!$domdefs) { + $domdefs = &mt('No header or inline menu shown'); + } + $domdefs = ' ('.&mt('Domain default').': '.$domdefs.')'; + if (ref($lti{$env{'request.lti.login'}}{'lcmenu'}) eq 'ARRAY') { + @domdefsmenu = @{$lti{$env{'request.lti.login'}}{'lcmenu'}}; + } + } + $displaydefs = &mt('Domain defaults'); + if (@domdefsmenu) { + my @diffs = &Apache::loncommon::compare_arrays(\@menuitems,\@domdefsmenu); + if (@diffs) { + my $missing; + foreach my $item (@menuitems) { + unless (grep(/^\Q$item\E$/,@domdefsmenu)) { + $missing .= ' '.$menutitles{$item}.','; + } + } + $missing =~ s/,$//; + $displaydefs .= ': '.&mt('Not shown').' --'.$missing; } else { - $datatable .= &mt("Use of external tools defined at a domain level is not enabled, either, for this $showtype."). - '

    '. - &mt("Contact an administrator for the $showtype domain ([_1]) to request changes.", - ''.$cdom.''); + $displaydefs .= ': '.&mt('All shown'); + } + } else { + $displaydefs .= ': '.&mt('Not shown').' -- '.join(', ', map { $menutitles{$_}; } @menuitems); + } + } else { + $displaydefs = &mt('Domain defaults only available in LTI context'); + } + my %items = ( + 'lti.override' => { + text => ''.&mt($itemtext->{'lti.override'}).''.$domdefs, + input => 'radio', + }, + 'lti.topmenu' => { + text => ''.&mt($itemtext->{'lti.topmenu'}).'', + input => 'radio', + }, + 'lti.inlinemenu' => { + text => ''.&mt($itemtext->{'lti.inlinemenu'}).'', + input => 'radio', + }, + 'lti.lcmenu' => { + text => ''.&mt($itemtext->{'lti.lcmenu'}).'
    '.$displaydefs, + input => 'custom', + }, + ); + return &make_item_rows($cdom,\%items,$ordered,$settings,$rowtotal,$crstype,'lti',$noedit); +} +sub lcmenu_checkboxes { + my ($cdom,$caller,$settings,$crstype,$noedit) = @_; + my @menuitems = ('fullname','coursetitle','role','logout','grades'); + my %menutitles = <imenu_titles(); + my (@current,@domdefs); + if ($env{'request.lti.login'}) { + my %lti = &Apache::lonnet::get_domain_lti($cdom,'provider'); + if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') { + if (ref($lti{$env{'request.lti.login'}}{'lcmenu'}) eq 'ARRAY') { + @domdefs = @{$lti{$env{'request.lti.login'}}{'lcmenu'}}; } - $datatable .= '
    ' - .''.(' 'x2). - ''. - '
    '.&mt('Required settings').''. - ''.$lt{'title'}.': '. - (' 'x2). - ''.$lt{'version'}.': '. - (' 'x2). - ''.$lt{'msgtype'}.': '. - (' 'x2). - ''.$lt{'sigmethod'}.':'. - '

    '. - ''.$lt{'url'}.':'. - (' 'x2). - ''.$lt{'lifetime'}.':'. - '

    '; - if ($key ne '') { - $datatable .= ''.$lt{'key'}; - if ($noedit) { - $datatable .= ': ['.&mt('not shown').']'; - } elsif ($switchserver) { - $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']'; - } else { - $datatable .= ':'; - } - $datatable .= ' '.(' 'x2); - } elsif (!$switchserver) { - $datatable .= ''.$lt{'key'}.':'. - ''. - ' '.(' 'x2); - } - if ($switchserver) { - if ($usable ne '') { - $datatable .= '
    '. - $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'
    '. - ''.&mt('Change secret?'). - ''. - (' 'x2). - ''.(' 'x2). - ''; - } elsif ($key eq '') { - $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; - } else { - $datatable .= ''.&mt('Secret required').' - '.$switchmessage.''."\n"; - } - $datatable .= ''; - } else { - if ($usable ne '') { - $datatable .= '
    '. - $lt{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'
    '. - ''.&mt('Change?'). - ''. - (' 'x2). - '  '; - } else { - $datatable .= - ''.$lt{'secret'}.':'. - ''. - ''. - ''; - } - } - $datatable .= '
    '. - '
    '.&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"'; - } elsif ($settings->{$item}->{'display'}->{'target'} eq 'tab') { - $currdisp{'tab'} = ' 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; - } - $currdisp{'linktext'} = $settings->{$item}->{'display'}->{'linktext'}; - $currdisp{'explanation'} = $settings->{$item}->{'display'}->{'explanation'}; - } else { - $currdisp{'iframe'} = ' checked="checked"'; - } - foreach my $disp ('iframe','tab','window') { - $datatable .= ''.(' 'x2); - } - $datatable .= (' 'x4); - foreach my $dimen ('width','height') { - $datatable .= ''. - (' 'x2); - } - $datatable .= '
    '. - '
    '.$lt{'linktext'}.'
    '. - '
    '. - '
    '.$lt{'explanation'}.'
    '. - '

    '; - my %units = ( - 'passback' => 'days', - 'roster' => 'seconds', - ); - foreach my $extra ('passback','roster') { - my $validsty = 'none'; - my $currvalid; - my $checkedon = ''; - my $checkedoff = ' checked="checked"'; - if ($settings->{$item}->{$extra}) { - $checkedon = $checkedoff; - $checkedoff = ''; - $validsty = 'inline-block'; - if ($settings->{$item}->{$extra.'valid'} =~ /^\d+\.?\d*$/) { - $currvalid = $settings->{$item}->{$extra.'valid'}; - } - } - my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','$i'".');"'; - $datatable .= '
    '.$lt{$extra}.' '. - ''.(' 'x2). - '
    '. - '
    '. - ''. - &mt("until at least [_1] $units{$extra} after launch", - ''). - '
    '; - } - $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,$userincdom); - if (ref($settings->{$item}) eq 'HASH') { - if (ref($settings->{$item}->{'fields'}) eq 'HASH') { - %checkedfields = %{$settings->{$item}->{'fields'}}; - } - $userincdom = $settings->{$item}->{'incdom'}; - if (ref($settings->{$item}->{'roles'}) eq 'HASH') { - %rolemaps = %{$settings->{$item}->{'roles'}}; - $checkedfields{'roles'} = 1; - } - } - $datatable .= '
    '.&mt('User data sent on launch').''. - ''; - my $userfieldstyle = 'display:none;'; - my $seluserdom = ''; - my $unseluserdom = ' selected="selected"'; - foreach my $field (@fields) { - my ($checked,$onclick,$id,$spacer); - if ($checkedfields{$field}) { - $checked = ' checked="checked"'; - } - if ($field eq 'user') { - $id = ' id="ltitools_user_field_'.$i.'"'; - $onclick = ' onclick="toggleLTITools(this.form,'."'$field','$i'".')"'; - if ($checked) { - $userfieldstyle = 'display:inline-block'; - if ($userincdom) { - $seluserdom = $unseluserdom; - $unseluserdom = ''; - } - } - } else { - $spacer = (' ' x2); - } - $datatable .= ''.$spacer; - } - $datatable .= ''; - $datatable .= '
    '. - ' : '. - '
    '; - $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','linktext','explanation','append') { - my $checked; - if ($courseconfig{$item}) { - $checked = ' checked="checked"'; - } - $datatable .= '  '."\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.'
    '. - ''. - '
    '; + foreach my $item (@menuitems) { + my $checked = ''; + if (grep(/^\Q$item\E$/,@current)) { + $checked = ' checked="checked" '; } + my $rem = $count%($numinrow); + if ($rem == 0) { + if ($count > 0) { + $output .= ''; + } + $output .= ''; + } + $output .= ''; + $count ++; } - $css_class = $itemcount%2?' class="LC_odd_row"':''; - my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"'; - $datatable .= ''."\n". - ''; + } elsif ($colsleft == 1) { + $output .= ''; } - $datatable .= ''. - '
    '.&mt('User data sent on launch').''. - ''; - foreach my $field (@fields) { - my ($id,$onclick,$spacer); - if ($field eq 'user') { - $id = ' id="ltitools_user_field_add"'; - $onclick = ' onclick="toggleLTITools(this.form,'."'$field','add'".')"'; - } else { - $spacer = (' ' x2); - } - $datatable .= ''.$spacer; - } - $datatable .= ''. - '
    '; - $datatable .= '
    '.&mt('Role mapping').'
    '."\n". - ''."\n". - ' '."\n". - ''.&mt('Add').''. - '
    '.&mt('Required settings').''. - ''.$lt{'title'}.': '."\n". - (' 'x2). - ''.$lt{'version'}.': '."\n". - (' 'x2). - ''.$lt{'msgtype'}.': '. - ''.$lt{'sigmethod'}.':'. - '
    '. - ''.$lt{'url'}.': '."\n". - (' 'x2). - ''.$lt{'lifetime'}.':
    '; - if ($switchserver) { - $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; - } else { - $datatable .= ''.$lt{'key'}.': '."\n". - (' 'x2). - ''.$lt{'secret'}.':'. - ' '."\n"; - } - $datatable .= '

    '. - '
    '. - '
    '.&mt('Optional settings').''. - ''.&mt('Display target:'); - my %defaultdisp; - $defaultdisp{'iframe'} = ' checked="checked"'; - foreach my $disp ('iframe','tab','window') { - $datatable .= ''.(' 'x2); - } - $datatable .= (' 'x4); - foreach my $dimen ('width','height') { - $datatable .= ''. - (' 'x2); - } - $datatable .= '
    '. - '
    '.$lt{'linktext'}.'
    '. - '
    '. - '
    '.$lt{'explanation'}.'
    '. - ''. - '

    '; - my %units = ( - 'passback' => 'days', - 'roster' => 'seconds', - ); - my %defaulttimes = ( - 'passback' => '7', - 'roster' => '300', - ); - foreach my $extra ('passback','roster') { - my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','add'".');"'; - $datatable .= '
    '.$lt{$extra}.' '. - ''.(' 'x2).''. - '
    '. - '
    '; - } - $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 .= ''; + my $rem = $count%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $output .= '
    '. + '  
    '; - foreach my $role (@courseroles) { - my ($checked,$checkednone); - $datatable .= ''; - } - $datatable .= '
    '. - &Apache::lonnet::plaintext($role,'Course').'
    '. - '
    '. - '
    '.&mt('Configurable in course').''; - foreach my $item ('label','title','target','linktext','explanation','append') { - $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', - 'sigmethod' => 'Signature Method', - 'url' => 'URL', - 'key' => 'Key', - 'lifetime' => 'Nonce lifetime (s)', - 'secret' => 'Secret', - 'icon' => 'Icon', - 'user' => 'User', - 'fullname' => 'Full Name', - 'firstname' => 'First Name', - 'lastname' => 'Last Name', - 'email' => 'E-mail', - 'roles' => 'Role', - 'window' => 'Window', - 'tab' => 'Tab', - 'iframe' => 'iFrame', - 'height' => 'Height', - 'width' => 'Width', - 'linktext' => 'Default Link Text', - 'explanation' => 'Default Explanation', - 'passback' => 'Tool can return grades:', - 'roster' => 'Tool can retrieve roster:', - 'crstarget' => 'Display target', - 'crslabel' => 'Course label', - 'crstitle' => 'Course title', - 'crslinktext' => 'Link Text', - 'crsexplanation' => 'Explanation', - 'crsappend' => 'Provider URL', - ); - return %lt; + $output .= ''; } sub ltimenu_titles { @@ -6861,8 +5149,8 @@ sub menuitems_categories { my %categories = ( shown => ['top','inline','foot','main'], text => ['name','role','crs','disc','fdbk'], - links => ['pers','logo','comm','roles','help','logout'], - list => ['about','prefs','port','wish','anno','rss','srch','brse'], + links => ['pers','logo','menu','comm','roles','help','logout'], + list => ['about','prefs','port','wish','anno','rss'], inline => ['cont','grades','chat','people','groups','resv','syll','feeds'], ); return (\@order,\%categories); @@ -6886,6 +5174,7 @@ sub menuitems_fields { main => 'Access to main menu', pers => 'Personal', logo => 'LON-CAPA', + menu => 'Home', comm => 'Messages', roles => 'Roles/Courses', help => 'Help', @@ -6901,8 +5190,6 @@ sub menuitems_fields { wish => 'Stored Links', anno => 'Calendar', rss => 'RSS Feeds', - srch => 'Search Library', - brse => 'Browse Library', cont => 'Contents', grades => 'Grades', chat => 'Chat', @@ -6958,7 +5245,7 @@ sub menucollections_display { ''.$menutitles{$category}.''."\n"; if ($category eq 'text') { $output .= ''.&mt('Header Text').'

    '; - } + } foreach my $field (@{$categories{$category}}) { if ($field eq 'disc') { $output .= '
    '.&mt('Footer Text').'

    '; @@ -6981,60 +5268,30 @@ sub menucollections_display { } sub print_linkprotection { - my ($cdom,$cnum,$settings,$rowtotal,$crstype,$noedit,$context) = @_; + my ($cdom,$settings,$rowtotal,$crstype,$noedit) = @_; + unless (ref($settings) eq 'HASH') { + return; + } my %linkprotection; my $count = 0; my $next = 1; - my ($datatable,$disabled,$css_class,$dest); + my ($datatable,$disabled,$css_class); if ($noedit) { $disabled = ' disabled="disabled"'; } - my %desc = &linkprot_names(); - my %lt = &Apache::lonlocal::texthash ( - 'requ' => 'Required settings', - 'opti' => 'Optional settings', - ); + my %lt = &linkprot_names(); my $itemcount = 0; - my $ltiauth; - if ($context eq 'domain') { - $ltiauth = 1; - } else { - if (exists($env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'})) { - $ltiauth = $env{'course.'.$env{'request.course.id'}.'.internal.ltiauth'}; - } else { - my %domdefs = &Apache::lonnet::get_domain_defaults($cdom); - $ltiauth = $domdefs{'crsltiauth'}; - } - } - if ($context eq 'domain') { - $dest = '/adm/domainprefs'; - } else { - $dest = '/adm/courseprefs'; - } - - my ($switchserver,$switchmessage); - $switchserver = &check_switchserver($cdom,$cnum,$context,$dest); - if ($switchserver) { - if ($context eq 'domain') { - $switchmessage = &mt("submit from domain's primary library server: [_1].",$switchserver); - } elsif ($crstype eq 'Community') { - $switchmessage = &mt("submit from community's home server: [_1].",$switchserver); - } else { - $switchmessage = &mt("submit from course's home server: [_1].",$switchserver); - } - } - - if ((ref($settings) eq 'HASH') && (ref($settings->{'linkprot'}) eq 'HASH')) { - if (keys(%{$settings->{'linkprot'}})) { - my @current = sort { $a <=> $b } keys(%{$settings->{'linkprot'}}); + if (ref($settings->{'linkprotection'}) eq 'HASH') { + if (keys(%{$settings->{'linkprotection'}})) { + my @current = sort { $a <=> $b } keys(%{$settings->{'linkprotection'}}); $next += $current[-1]; for (my $i=0; $i<@current; $i++) { my $num = $current[$i]; my %values; - if (ref($settings->{'linkprot'}->{$num}) eq 'HASH') { - %values = %{$settings->{'linkprot'}->{$num}}; + if (ref($settings->{'linkprotection'}->{$num}) eq 'HASH') { + %values = %{$settings->{'linkprotection'}->{$num}}; } else { next; } @@ -7046,150 +5303,24 @@ sub print_linkprotection { $datatable .= ''. ''; - my ($usersty,$onclickrequser,%checkedrequser,$onclickreturnurl,%checkedreturnurl, - $onclickpassback,%checkedpassback,$passbacksty,%checkedpassbackfmt); - $passbacksty = 'none'; - $onclickpassback = ' onclick="toggleLinkProtExtra(this.form,'."'passback','passbackparam','1','inline-block','$i'".');"'; - %checkedpassback = ( - 'no' => ' checked="checked"', - 'yes' => '', - ); - %checkedpassbackfmt = ( - '1p1' => ' checked="checked"', - '1p0' => '', - ); - if ($values{'passback'} ne '') { - $passbacksty = 'inline-block'; - $checkedpassback{'yes'} = ' checked="checked"'; - $checkedpassback{'no'} = ''; - if ($values{'passbackformat'} eq '1.0') { - $checkedpassbackfmt{'1p0'} = ' checked="checked"'; - $checkedpassbackfmt{'1p1'} = ''; - } - } - if ($ltiauth) { - $usersty = 'display:none'; - $onclickrequser = ' onclick="toggleLinkProtExtra(this.form,'."'requser','optional','1','block','$i'".');"'; - %checkedrequser = ( - no => ' checked="checked"', - yes => '', - ); - if ($values{'requser'}) { - $checkedrequser{'yes'} = $checkedrequser{'no'}; - $checkedrequser{'no'} = ''; - } - $datatable .= '
    '.$lt{'requ'}.''; - if ($values{'requser'}) { - $usersty = 'display:inline-block'; - } - } - $onclickreturnurl = ' onclick="toggleLinkProtExtra(this.form,'."'returnurl','divurlparam','1','inline-block','$i'".');"'; - %checkedreturnurl = ( - no => ' checked="checked"', - yes => '', - ); - if ($values{'returnurl'} ne '') { - $checkedreturnurl{'yes'} = $checkedreturnurl{'no'}; - $checkedreturnurl{'no'} = ''; - } - $datatable .= - ''.$desc{'name'}. + &mt('Delete?').''. + ''.$lt{'name'}. ': '. (' 'x2). - ''.$desc{'version'}.':'. ' '."\n". (' 'x2). - ''.$desc{'lifetime'}.':

    '; - if ($values{'key'} ne '') { - $datatable .= ''.$desc{'key'}; - if ($noedit) { - $datatable .= ': ['.&mt('not shown').']'; - } elsif ($switchserver) { - $datatable .= ': ['.&mt('[_1] to view/edit',$switchserver).']'; - } else { - $datatable .= ':'; - } - $datatable .= ' '.(' 'x2); - } elsif (!$switchserver) { - $datatable .= ''.$desc{'key'}.':'. - ''. - ' '.(' 'x2); - } - if ($switchserver) { - if ($values{'usable'} ne '') { - $datatable .= '
    '. - $desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'
    '. - ''.&mt('Change secret?'). - ''. - (' 'x2). - ''.(' 'x2). - ''; - } elsif ($values{'key'} eq '') { - $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; - } else { - $datatable .= ''.&mt('Secret required').' - '.$switchmessage.''."\n"; - } - $datatable .= ''; - } else { - if ($values{'usable'} ne '') { - $datatable .= '
    '. - $desc{'secret'}.': ['.&mt('not shown').'] '.(' 'x2).'
    '. - ''.&mt('Change?'). - ''. - (' 'x2). - '  '; - } else { - $datatable .= - ''.$desc{'secret'}.':'. - ''. - ''. - ''; - } - } - $datatable .= '

    '. - ''.$desc{'passback'}.'?'. - ' '. - '
    '. - '
    '. - ''.&mt('Grade format'). - ''.(' 'x2). - '
    '. - '
    '. - '
    '. - ''.$desc{'returnurl'}.'?'. - ' '. - ''. - '   '; - if ($ltiauth) { - $datatable .= (' 'x2).''.$desc{'requser'}.'?'. - ' '. - ''. - '
    '. - '
    '.$lt{'opti'}.''. - &linkprot_options($i,$itemcount,$disabled,\%values,\%desc). - '
    '; - } - $datatable .= ''; + ''.$lt{'lifetime'}.':'. + '

    '. + ''.$lt{'key'}. + ': '. + (' 'x2). + ''.$lt{'secret'}.':'. + ''. + ''. + ''. + ''; $itemcount ++; } } @@ -7198,212 +5329,33 @@ sub print_linkprotection { $datatable .= ''."\n". ''."\n". ''.&mt('Add').''."\n". - ''; - my ($usersty,$onclickrequser,%checkedrequser,$onclickreturnurl,%checkedreturnurl, - $onclickpassback,%checkedpassback,%checkedpassbackfmt); - if ($ltiauth) { - $usersty = 'display:none'; - $onclickrequser = ' onclick="toggleLinkProtExtra(this.form,'."'requser','optional','1','block','add'".');"'; - %checkedrequser = ( - no => ' checked="checked"', - yes => '', - ); - $datatable .= '
    '.$lt{'requ'}.''; - } - $onclickpassback = ' onclick="toggleLinkProtExtra(this.form,'."'passback','passbackparam','1','inline-block','add'".');"'; - %checkedpassback = ( - 'no' => ' checked="checked"', - 'yes' => '', - ); - %checkedpassbackfmt = ( - '1p1' => ' checked="checked"', - '1p0' => '', - ); - $onclickreturnurl = ' onclick="toggleLinkProtExtra(this.form,'."'returnurl','divurlparam','1','inline-block','add'".');"'; - %checkedreturnurl = ( - no => ' checked="checked"', - yes => '', - ); - $datatable .= ''.$desc{'name'}. + ''. + ''.$lt{'name'}. ': '."\n". (' 'x2). - ''.$desc{'version'}.':'. ' '."\n". (' 'x2). - ''.$desc{'lifetime'}.': '."\n". - '

    '; - if ($switchserver) { - $datatable .= ''.&mt('Key and Secret are required').' - '.$switchmessage.''."\n"; - } else { - $datatable .= ''.$desc{'key'}.': '."\n". - (' 'x2). - ''.$desc{'secret'}.':'. - ' '."\n"; - } - $datatable .= '

    '. - ''.$desc{'passback'}.'?'. - ' '. - ''. - '
    '. - '
    '. - '
    '. - ''.$desc{'returnurl'}.'?'. - ' '. - ''. - '  
    '; - if ($ltiauth) { - $datatable .= (' 'x2).''.$desc{'requser'}.'?'. - ' '. - ''. - '
    '. - '
    '.$lt{'opti'}.''. - &linkprot_options('add',$itemcount,$disabled,{},\%desc). - '
    '; - } - $datatable .= ''; + ''.$lt{'lifetime'}.': '."\n". + '

    '. + ''.$lt{'key'}.': '."\n". + (' 'x2). + ''.$lt{'secret'}.':'. + ' '."\n". + ''; $$rowtotal ++; - return $datatable; + return $datatable;; } sub linkprot_names { - return &Apache::lonlocal::texthash( + my %lt = &Apache::lonlocal::texthash( 'version' => 'LTI Version', 'key' => 'Key', 'lifetime' => 'Nonce lifetime (s)', - 'name' => 'Launcher Application', + 'name' => 'Launcher Application Name', 'secret' => 'Secret', - 'passback' => 'Can return grades to Launcher', - 'returnurl' => 'Launcher return URL', - 'requser' => 'Use identity', - 'email' => 'Email address', - 'sourcedid' => 'User ID', - 'other' => 'Other', - 'auth' => 'Display LON-CAPA login page', - 'reject' => 'Discontinue launch process', ); -} - -sub check_switchserver { - my ($cdom,$cnum,$context,$dest) = @_; - my ($allowed,$switchserver,$home); - if ($context eq 'domain') { - $home = &Apache::lonnet::domain($cdom,'primary'); - } else { - $home = &Apache::lonnet::homeserver($cnum,$cdom); - } - unless (($home eq 'no_host') || ($home eq '')) { - my @ids=&Apache::lonnet::current_machine_ids(); - foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } - if (!$allowed) { - $switchserver=''.&mt('Switch Server').''; - } - } - return $switchserver; -} - -sub linkprot_options { - my ($num,$itemcount,$disabled,$current,$desc) = @_; - my %lt; - if (ref($desc) eq 'HASH') { - %lt = %{$desc}; - } - my $userfieldsty = 'none'; - my (%checked,$userfield); - $checked{'sourcedid'} = ' checked="checked"'; - $checked{'reject'} = ' checked="checked"'; - if (ref($current) eq 'HASH') { - if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) { - $checked{'sourcedid'} = ''; - if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') { - $checked{'email'} = ' checked="checked"'; - } else { - $checked{'other'} = ' checked="checked"'; - $userfield = $current->{'mapuser'}; - $userfieldsty = 'inline-block'; - } - } - if (($current->{'notstudent'} ne '') && ($current->{'notstudent'} ne 'reject')) { - $checked{'reject'} = ''; - $checked{'auth'} = ' checked="checked"'; - } - } - my $onclickuser = ' onclick="toggleLinkProtExtra(this.form,'."'mapuser','userfield','other','inline-block','$num'".');"'; - my $output = '
    '. - &mt('Source of LON-CAPA username in LTI request').': '; - foreach my $option ('sourcedid','email','other') { - $output .= ''. - ($option eq 'other' ? '' : (' 'x2) ); - } - $output .= '
    '. - '
    '. - '
    '; - $output .= '
    '. - '
    '. - &mt('Action when username is not for an enrolled student').': '; - foreach my $option ('reject','auth') { - $output .= ''. - ($option eq 'auth' ? '' : (' 'x2) ); - } - $output .= '
    '; - return $output; -} - -sub print_extresource_row { - my ($item,$config,$curr,$noedit) = @_; - my $onchange; - unless ($noedit) { - $onchange = ' onchange="javascript:toggleExtRes();"'; - } - my $id = 'LC_'.$item; - my ($selected,$reuse,$width,$height) = split(/:/,$curr); - my $output = &select_from_options($item,$config->{'order'}, - $config->{'options'},$selected, - $config->{'nullval'}, - undef,undef,$onchange,$noedit,$id); - my ($checked,$reusesty,$sizesty); - if ($reuse) { - $checked = ' checked="checked"'; - } - $reusesty = 'none'; - $sizesty = 'none'; - if (($selected eq 'window') || ($selected eq 'tab')) { - $reusesty = 'inline-block'; - if ($selected eq 'window') { - $sizesty = 'inline-block'; - } - } - $output .= '
    '. - ''. - ''. - '
    '. - '
    '. - ''.&mt('Window size (optional)').''. - ''. - &mt('width').':px'. - (' ' x 3). - &mt('height').':px'. - '
    '; - return $output; + return %lt; } sub print_other { @@ -7483,7 +5435,7 @@ sub item_table_row_end { } sub yesno_radio { - my ($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit,$onclick,$reverse) = @_; + my ($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit) = @_; my $itemon = ' '; my $itemoff = ' checked="checked" '; if (($valueyes eq '') && ($valueno eq '')) { @@ -7505,22 +5457,12 @@ sub yesno_radio { my $disabled; if ($noedit) { $disabled = ' disabled="disabled"'; - } elsif ($onclick) { - $onclick = ' onclick="'.$onclick.'"'; - } - if ($reverse) { - return ' '. - ''; - } else { - return ' '. - ''; } + return ' '. + ''; } sub select_from_options { @@ -7576,7 +5518,7 @@ sub select_from_options { } sub make_item_rows { - my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype,$caller,$noedit,$cnum) = @_; + my ($cdom,$items,$ordered,$settings,$rowtotal,$crstype,$caller,$noedit) = @_; my $datatable; if ((ref($items) eq 'HASH') && (ref($ordered) eq 'ARRAY')) { my $count = 0; @@ -7587,16 +5529,10 @@ sub make_item_rows { (($caller eq 'printouts') && ($item ne 'print_header_format'))) { $colspan = 2; } - my $rowdesc; - if ($caller eq 'appearance') { - $rowdesc = ''.$items->{$item}{text}.''; - } else { - $rowdesc = $items->{$item}{text}; - } if (exists $items->{$item}{advanced} && $items->{$item}{advanced} == 1) { - $datatable .= &item_table_row_start($rowdesc,$count,"advanced",$colspan); + $datatable .= &item_table_row_start($items->{$item}{text},$count,"advanced",$colspan); } else { - $datatable .= &item_table_row_start($rowdesc,$count,undef,$colspan); + $datatable .= &item_table_row_start($items->{$item}{text},$count,undef,$colspan); } if ($item eq 'defaultcredits') { my $defaultcredits = $env{'course.'.$env{'request.course.id'}.'.internal.defaultcredits'}; @@ -7613,8 +5549,8 @@ sub make_item_rows { $datatable .= &checkforpriv_row($cdom,$item,$settings,$crstype,$noedit); } elsif ($item eq 'print_header_format') { $datatable .= &print_hdrfmt_row($item,$settings,$noedit); - } elsif ($item eq 'extresource') { - $datatable .= &print_extresource_row($item,$items->{$item},$settings->{$item},$noedit); + } elsif ($item eq 'lti.lcmenu') { + $datatable .= &lcmenu_checkboxes($cdom,$item,$settings,$crstype,$noedit); } elsif ($items->{$item}{input} eq 'dates') { my $disabled; if ($noedit) { @@ -7632,68 +5568,21 @@ sub make_item_rows { } $valueyes = "1"; $valueno = "0"; + } elsif (($item eq 'lti.topmenu') || ($item eq 'lti.inlinemenu')) { + $valueyes = '1'; } $datatable .= &yesno_radio($item,$settings,$unsetdefault,$valueyes,$valueno,$noedit); } elsif ($items->{$item}{input} eq 'selectbox') { - my ($id,$onchange); + my $id; if ($caller eq 'menuitems') { $id = $item; - } elsif ($caller eq 'grading') { - if ($item eq 'grading') { - $onchange = ' onchange="javascript:toggleGrading(this.form);"'; - $id = $item; - } } my $curr = $settings->{$item}; $datatable .= &select_from_options($item,$items->{$item}{'order'}, $items->{$item}{'options'},$curr, $items->{$item}{'nullval'}, - undef,undef,$onchange,$noedit,$id); - if ($item eq 'grading') { - my ($unsetdefault,$valueyes,$valueno,$sectionbox); - my $gradingsty = 'none'; - my $gradingsecsty = 'none'; - $unsetdefault = 0; - my (@selsec,@sections,%current); - if ($curr eq 'standard') { - $gradingsty = 'inline-block'; - if (ref($settings) eq 'HASH') { - $current{'hidetotals'} = $settings->{'hidetotals'}; - if ($settings->{'hidetotals'} =~ /^([\w,]+)$/) { - my $secstr = $1; - unless ($secstr eq 'all') { - @selsec = split(/,/,$secstr); - } - $current{'hidetotals'} = 1; - } - } - } - $valueyes = "1"; - $valueno = "0"; - my %sections = &Apache::loncommon::get_sections($cdom,$cnum); - if (keys(%sections)) { - @sections = sort( { $a <=> $b } keys(%sections)); - } - my $onclick = 'javascript:toggleHiddenTotalsSec(this.form);'; - my $sectionbox = '
    '; - my $reverse = 1; - if (@sections) { - $sectionbox .= ' ... '.&mt('hidden in sections').': '. - '
    '. - &select_sections('hidetotals','',\@sections,\@selsec,$noedit,'all'). - '
    '; - } - $sectionbox .= '
    '; - $datatable .= '
    '. - ''. - &mt('Hide Course Points Totals').''. - '
    '. - &yesno_radio('hidetotals',\%current,$unsetdefault,$valueyes,$valueno,$noedit, - $onclick,$reverse).'
    '. - $sectionbox. - '
    '; - } + undef,undef,undef,$noedit,$id); } elsif ($items->{$item}{input} eq 'textbox') { my $disabled; if ($noedit) { @@ -7728,7 +5617,7 @@ sub nothidepriv_row { } } if ($settings->{'checkforpriv'}) { - @checkdoms = split(/,/,$settings->{'checkforpriv'}); + @checkdoms = split(/,/,$settings->{'checkforpriv'}); } } push(@checkdoms,$cdom); @@ -7742,7 +5631,7 @@ sub nothidepriv_row { if ($end == -1 || $start == -1) { next; } - foreach my $dom (@checkdoms) { + foreach my $dom (@checkdoms) { if (&Apache::lonnet::privileged($uname,$udom,\@checkdoms,['dc','su'])) { unless (grep(/^\Q$user\E$/,@privusers)) { push(@privusers,$user); @@ -7818,7 +5707,7 @@ sub checkforpriv_row { my $domdesc = &Apache::lonnet::domain($currdom,'description'); if ($domdesc eq '') { $domdesc = $currdom; - } + } $datatable .= &Apache::loncommon::start_data_table_row(). ''. @@ -7830,13 +5719,13 @@ sub checkforpriv_row { &mt('Delete').''. &Apache::loncommon::end_data_table_row(); $num ++; - unless (grep(/^\Q$currdom\E$/,@excdoms)) { + unless (grep(/^\Q$currdom\E$/,@excdoms)) { push(@excdoms,$currdom); } } } if ((scalar(keys(%domains)) - scalar(@excdoms)) > 0) { - $datatable .= + $datatable .= &Apache::loncommon::start_data_table_row(). ''. &mt('Additional domain:'). '
    '. @@ -7950,7 +5839,7 @@ ENDJS } } my $pos = $currnum+1; - unless ($noedit) { + unless ($noedit) { $output .= ''. ''. @@ -8088,30 +5977,6 @@ sub change_clone { } } } - return; -} - -sub devalidate_remote_courseprefs { - my ($cdom,$cnum,$cachekeys) = @_; - return unless (ref($cachekeys) eq 'HASH'); - my %servers = &Apache::lonnet::internet_dom_servers($cdom); - my %thismachine; - map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids(); - my @posscached = ('courselti','courseltitools'); - if (keys(%servers)) { - foreach my $server (keys(%servers)) { - next if ($thismachine{$server}); - my @cached; - foreach my $name (@posscached) { - if ($cachekeys->{$name}) { - push(@cached,&escape($name).':'.&escape($cdom.'_'.$cnum)); - } - } - if (@cached) { - &Apache::lonnet::remote_devalidate_cache($server,\@cached); - } - } - } return; }