--- loncom/interface/domainprefs.pm 2017/10/07 00:50:47 1.314
+++ loncom/interface/domainprefs.pm 2017/12/06 23:41:19 1.321
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.314 2017/10/07 00:50:47 raeburn Exp $
+# $Id: domainprefs.pm,v 1.321 2017/12/06 23:41:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -219,13 +219,14 @@ sub handler {
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
'requestauthor','selfenrollment','inststatus',
- 'ltitools','ssl','trust'],$dom);
+ 'ltitools','ssl','trust','lti'],$dom);
+ my %encconfig =
+ &Apache::lonnet::get_dom('encconfig',['ltitools','lti'],$dom);
if (ref($domconfig{'ltitools'}) eq 'HASH') {
- my %encconfig =
- &Apache::lonnet::get_dom('encconfig',['ltitools'],$dom);
if (ref($encconfig{'ltitools'}) eq 'HASH') {
foreach my $id (keys(%{$domconfig{'ltitools'}})) {
- if (ref($domconfig{'ltitools'}{$id}) eq 'HASH') {
+ if ((ref($domconfig{'ltitools'}{$id}) eq 'HASH') &&
+ (ref($encconfig{'ltitools'}{$id}) eq 'HASH')) {
foreach my $item ('key','secret') {
$domconfig{'ltitools'}{$id}{$item} = $encconfig{'ltitools'}{$id}{$item};
}
@@ -233,12 +234,24 @@ sub handler {
}
}
}
+ if (ref($domconfig{'lti'}) eq 'HASH') {
+ if (ref($encconfig{'lti'}) eq 'HASH') {
+ foreach my $id (keys(%{$domconfig{'lti'}})) {
+ if ((ref($domconfig{'lti'}{$id}) eq 'HASH') &&
+ (ref($encconfig{'lti'}{$id}) eq 'HASH')) {
+ foreach my $item ('key','secret') {
+ $domconfig{'lti'}{$id}{$item} = $encconfig{'lti'}{$id}{$item};
+ }
+ }
+ }
+ }
+ }
my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
'autoupdate','autocreate','directorysrch','contacts',
'usercreation','selfcreation','usermodification','scantron',
'requestcourses','requestauthor','coursecategories',
'serverstatuses','helpsettings','coursedefaults',
- 'ltitools','selfenrollment','usersessions','ssl','trust');
+ 'ltitools','selfenrollment','usersessions','ssl','trust','lti');
my %existing;
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
@@ -545,6 +558,14 @@ sub handler {
print => \&print_trust,
modify => \&modify_trust,
},
+ 'lti' =>
+ {text => 'LTI Provider',
+ help => 'Domain_Configuration_LTI_Provider',
+ header => [{col1 => 'Setting',
+ col2 => 'Value',}],
+ print => \&print_lti,
+ modify => \&modify_lti,
+ },
);
if (keys(%servers) > 1) {
$prefs{'login'} = { text => 'Log-in page options',
@@ -730,6 +751,8 @@ sub process_changes {
$output = &modify_ssl($dom,$lastactref,%domconfig);
} elsif ($action eq 'trust') {
$output = &modify_trust($dom,$lastactref,%domconfig);
+ } elsif ($action eq 'lti') {
+ $output = &modify_lti($r,$dom,$action,$lastactref,%domconfig);
}
return $output;
}
@@ -1065,7 +1088,7 @@ sub print_config_box {
$output .= &print_quotas($dom,$settings,\$rowtotal,$action);
} elsif (($action eq 'autoenroll') || ($action eq 'autocreate') ||
($action eq 'serverstatuses') || ($action eq 'loadbalancing') ||
- ($action eq 'ltitools')) {
+ ($action eq 'ltitools') || ($action eq 'lti')) {
$output .= $item->{'print'}->($dom,$settings,\$rowtotal);
} elsif ($action eq 'scantron') {
$output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal);
@@ -1656,7 +1679,8 @@ sub display_color_options {
if ($fullwidth ne '' && $fullheight ne '') {
if ($fullwidth > $width && $fullheight > $height) {
my $size = $width.'x'.$height;
- system("convert -sample $size $input $output");
+ my @args = ('convert','-sample',$size,$input,$output);
+ system({$args[0]} @args);
$showfile = "/$imgdir/tn-".$filename;
}
}
@@ -2585,7 +2609,10 @@ ENDSCRIPT
sub ltitools_javascript {
my ($settings) = @_;
- return unless(ref($settings) eq 'HASH');
+ my $togglejs = <itools_toggle_js();
+ unless (ref($settings) eq 'HASH') {
+ return $togglejs;
+ }
my (%ordered,$total,%jstext);
$total = 0;
foreach my $item (keys(%{$settings})) {
@@ -2603,7 +2630,7 @@ sub ltitools_javascript {
return <<"ENDSCRIPT";
+$togglejs
+
+ENDSCRIPT
+}
+
+sub ltitools_toggle_js {
+ return <<"ENDSCRIPT";
+
+
+ENDSCRIPT
+}
+
+sub lti_javascript {
+ my ($settings) = @_;
+ my $togglejs = <i_toggle_js();
+ unless (ref($settings) eq 'HASH') {
+ return $togglejs;
+ }
+ my (%ordered,$total,%jstext);
+ $total = 0;
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ $total = scalar(keys(%{$settings}));
+ my @jsarray = ();
+ foreach my $item (sort {$a <=> $b } (keys(%ordered))) {
+ push(@jsarray,$ordered{$item});
+ }
+ my $jstext = ' var lti = Array('."'".join("','",@jsarray)."'".');'."\n";
+ return <<"ENDSCRIPT";
+
+
+$togglejs
+
+ENDSCRIPT
+}
+
+sub lti_toggle_js {
+ return <<"ENDSCRIPT";
+
+
ENDSCRIPT
}
@@ -3124,7 +3352,54 @@ sub print_contacts {
$to{$item}.'" />';
$rownum ++;
}
- } else {
+ } elsif ($position eq 'bottom') {
+ $css_class = $rownum%2?' class="LC_odd_row"':'';
+ $datatable .= '
'.
+ ''.&mt('Extra helpdesk form fields:').' '.
+ &mt('(e-mail, subject, and description always shown)').
+ ' ';
+ if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&
+ (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {
+ $datatable .= '';
+ }
+ $datatable .= ' '."\n";
+ $rownum ++;
+ }
+ unless ($position eq 'top') {
foreach my $type (@mailings) {
$css_class = $rownum%2?' class="LC_odd_row"':'';
$datatable .= ''.
@@ -3184,56 +3459,138 @@ sub print_contacts {
\%choices,$rownum);
$datatable .= $reports;
} elsif ($position eq 'bottom') {
- $css_class = $rownum%2?' class="LC_odd_row"':'';
- $datatable .= ' '.
- ''.&mt('Extra helpdesk form fields:').' '.
- &mt('(e-mail, subject, and description always shown)').
- ' ';
- if ((ref($fields) eq 'ARRAY') && (ref($fieldtitles) eq 'HASH') &&
- (ref($fieldoptions) eq 'HASH') && (ref($possoptions) eq 'HASH')) {
- $datatable .= ''.&mt('Field').' '.&mt('Status').' ';
- foreach my $field (@{$fields}) {
- $datatable .= ''.$fieldtitles->{$field};
- if (($field eq 'screenshot') || ($field eq 'cc')) {
- $datatable .= ' '.&mt('(logged-in users)');
- }
- $datatable .=' ';
- my $clickaction;
- if ($field eq 'screenshot') {
- $clickaction = ' onclick="screenshotSize(this);"';
- }
- if (ref($possoptions->{$field}) eq 'ARRAY') {
- foreach my $option (@{$possoptions->{$field}}) {
- my $checked;
- if ($currfield{$field} eq $option) {
- $checked = ' checked="checked"';
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ my (@posstypes,%usertypeshash);
+ if (ref($types) eq 'ARRAY') {
+ @posstypes = @{$types};
+ }
+ if (@posstypes) {
+ if (ref($usertypes) eq 'HASH') {
+ %usertypeshash = %{$usertypes};
+ }
+ my @overridden;
+ my $numinrow = 4;
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{'overrides'}) eq 'HASH') {
+ foreach my $key (sort(keys(%{$settings->{'overrides'}}))) {
+ if (ref($settings->{'overrides'}{$key}) eq 'HASH') {
+ push(@overridden,$key);
+ foreach my $item (@contacts) {
+ if ($settings->{'overrides'}{$key}{$item}) {
+ $checked{'override_'.$key}{$item} = ' checked="checked" ';
+ }
+ }
+ $otheremails{'override_'.$key} = $settings->{'overrides'}{$key}{'others'};
+ $bccemails{'override_'.$key} = $settings->{'overrides'}{$key}{'bcc'};
+ $includeloc{'override_'.$key} = '';
+ $includestr{'override_'.$key} = '';
+ if ($settings->{'overrides'}{$key}{'include'} ne '') {
+ ($includeloc{'override_'.$key},$includestr{'override_'.$key}) =
+ split(/:/,$settings->{'overrides'}{$key}{'include'},2);
+ $includestr{'override_'.$key} = &unescape($includestr{'override_'.$key});
+ }
}
- $datatable .= ''.
- ' '.$fieldoptions->{$option}.
- ' '.(' 'x2);
}
}
- if ($field eq 'screenshot') {
- my $display;
- if ($currfield{$field} eq 'no') {
- $display = ' style="display:none"';
- }
- $datatable .= ' '.
- ''.&mt('Maximum size for upload (MB)').' '.
- ' ';
+ }
+ my $customclass = 'LC_helpdesk_override';
+ my $optionsprefix = 'LC_options_helpdesk_';
+
+ my $onclicktypes = "toggleHelpdeskRow(this.form,'overrides','$customclass','$optionsprefix');";
+
+ $datatable .= &insttypes_row($settings,$types,$usertypes,$dom,
+ $numinrow,$othertitle,'overrides',
+ \$rownum,$onclicktypes,$customclass);
+ $rownum ++;
+ $usertypeshash{'default'} = $othertitle;
+ foreach my $status (@posstypes) {
+ my $css_class;
+ if ($rownum%2) {
+ $css_class = 'LC_odd_row ';
+ }
+ $css_class .= $customclass;
+ my $rowid = $optionsprefix.$status;
+ my $hidden = 1;
+ my $currstyle = 'display:none';
+ if (grep(/^\Q$status\E$/,@overridden)) {
+ $currstyle = 'display:table-row';
+ $hidden = 0;
+ }
+ my $key = 'override_'.$status;
+ $datatable .= &overridden_helpdesk($checked{$key},$otheremails{$key},$bccemails{$key},
+ $includeloc{$key},$includestr{$key},$status,$rowid,
+ $usertypeshash{$status},$css_class,$currstyle,
+ \@contacts,$short_titles);
+ unless ($hidden) {
+ $rownum ++;
}
- $datatable .= ' ';
}
- $datatable .= '
';
}
- $datatable .= ' '."\n";
- $rownum ++;
}
$$rowtotal += $rownum;
return $datatable;
}
+sub overridden_helpdesk {
+ my ($checked,$otheremails,$bccemails,$includeloc,$includestr,$type,$rowid,
+ $typetitle,$css_class,$rowstyle,$contacts,$short_titles) = @_;
+ my $class = 'LC_left_item';
+ if ($css_class) {
+ $css_class = ' class="'.$css_class.'"';
+ }
+ if ($rowid) {
+ $rowid = ' id="'.$rowid.'"';
+ }
+ if ($rowstyle) {
+ $rowstyle = ' style="'.$rowstyle.'"';
+ }
+ my ($output,$description);
+ $description = &mt('Helpdesk requests from: [_1] in this domain (overrides default)',"$typetitle ");
+ $output = ''.
+ "$description \n".
+ ''.
+ ''.&mt('E-mail recipient(s)').' '.
+ '';
+ if (ref($contacts) eq 'ARRAY') {
+ foreach my $item (@{$contacts}) {
+ my $check;
+ if (ref($checked) eq 'HASH') {
+ $check = $checked->{$item};
+ }
+ my $title;
+ if (ref($short_titles) eq 'HASH') {
+ $title = $short_titles->{$item};
+ }
+ $output .= ''.
+ ' '.$title.' ';
+ }
+ }
+ $output .= ' '.&mt('Others').': '.
+ ' ';
+ my %locchecked;
+ foreach my $loc ('s','b') {
+ if ($includeloc eq $loc) {
+ $locchecked{$loc} = ' checked="checked"';
+ last;
+ }
+ }
+ $output .= ' '.&mt('Bcc:').(' 'x6).
+ ' '.
+ ''.&mt('Optional added text').' '.
+ &mt('Text automatically added to e-mail:').' '.
+ ' '.
+ ''.&mt('Location:').' '.
+ ' '.&mt('in subject').' '.
+ (' 'x2).
+ ' '.&mt('in body').' '.
+ ' '.
+ ' '."\n";
+ return $output;
+}
+
sub contacts_javascript {
return <<"ENDSCRIPT";
@@ -3251,6 +3608,37 @@ function screenshotSize(field) {
return;
}
+function toggleHelpdeskRow(form,checkbox,target,prefix,docount) {
+ if (form.elements[checkbox].length != undefined) {
+ var count = 0;
+ if (docount) {
+ for (var i=0; i
@@ -3724,7 +4112,7 @@ sub print_ltitools {
for (my $i=0; $i<@items; $i++) {
$css_class = $itemcount%2?' class="LC_odd_row"':'';
my $item = $ordered{$items[$i]};
- my ($title,$key,$secret,$url,$imgsrc,$version);
+ my ($title,$key,$secret,$url,$imgsrc);
if (ref($settings->{$item}) eq 'HASH') {
$title = $settings->{$item}->{'title'};
$url = $settings->{$item}->{'url'};
@@ -3735,7 +4123,7 @@ sub print_ltitools {
$imgsrc = ' ';
}
}
- my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_".$item."'".');"';
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_".$item."'".');"';
$datatable .= ''
.'';
for (my $k=0; $k<=$maxnum; $k++) {
@@ -3762,7 +4150,7 @@ sub print_ltitools {
''.$lt{'url'}.': '.
(' 'x2).
- ''.$lt{'key'}.
+ ''.$lt{'key'}.':'.
' '.
(' 'x2).
''.$lt{'secret'}.':'.
@@ -3808,21 +4196,36 @@ sub print_ltitools {
''.$lt{'explanation'}.' '.
'
';
- $datatable .= ' ';
+ 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 = '';
- }
- $datatable .= $lt{$extra}.' '.
- ' '.
- &mt('Yes').' '.(' 'x2).
- ' '.
- &mt('No').' '.(' 'x4);
+ $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}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).
+ ' '.
+ &mt('Yes').'
'.
+ '
';
}
- $datatable .= ''.$lt{'icon'}.': ';
+ $datatable .= ''.$lt{'icon'}.': ';
if ($imgsrc) {
$datatable .= $imgsrc.
'';
- foreach my $item ('label','title','target','linktext','explanation') {
+ foreach my $item ('label','title','target','linktext','explanation','append') {
my $checked;
if ($courseconfig{$item}) {
$checked = ' checked="checked"';
@@ -3922,7 +4325,7 @@ sub print_ltitools {
}
}
$css_class = $itemcount%2?' class="LC_odd_row"':'';
- my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'ltitools_add_pos'".');"';
+ my $chgstr = ' onchange="javascript:reorderLTITools(this.form,'."'ltitools_add_pos'".');"';
$datatable .= ''."\n".
' '."\n".
'';
@@ -3973,14 +4376,28 @@ sub print_ltitools {
''.$lt{'explanation'}.' '.
''.
'
';
+ my %units = (
+ 'passback' => 'days',
+ 'roster' => 'seconds',
+ );
+ my %defaulttimes = (
+ 'passback' => '7',
+ 'roster' => '300',
+ );
foreach my $extra ('passback','roster') {
- $datatable .= $lt{$extra}.' '.
- ' '.
- &mt('Yes').' '.(' 'x2).
- ' '.
- &mt('No').' '.(' 'x4);
+ my $onclick = ' onclick="toggleLTITools(this.form,'."'$extra','add'".');"';
+ $datatable .= ''.$lt{$extra}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).''.
+ ' '.
+ &mt('Yes').'
'.
+ '
';
}
- $datatable .= ''.$lt{'icon'}.': '.
+ $datatable .= ''.$lt{'icon'}.': '.
'('.&mt('if larger than 21x21 pixels, image will be scaled').') ';
if ($switchserver) {
$datatable .= &mt('Upload to library server: [_1]',$switchserver);
@@ -4010,7 +4427,7 @@ sub print_ltitools {
}
$datatable .= ' '.
''.&mt('Configurable in course').' ';
- foreach my $item ('label','title','target','linktext','explanation') {
+ foreach my $item ('label','title','target','linktext','explanation','append') {
$datatable .= ''.
' '.
$lt{'crs'.$item}.' '.(' ' x2)."\n";
@@ -4058,10 +4475,332 @@ sub ltitools_names {
'crstitle' => 'Course title',
'crslinktext' => 'Link Text',
'crsexplanation' => 'Explanation',
+ 'crsappend' => 'Provider URL',
+ );
+ return %lt;
+}
+
+sub print_lti {
+ my ($dom,$settings,$rowtotal) = @_;
+ my $itemcount = 1;
+ my $maxnum = 0;
+ my $css_class;
+ my %ordered;
+ if (ref($settings) eq 'HASH') {
+ foreach my $item (keys(%{$settings})) {
+ if (ref($settings->{$item}) eq 'HASH') {
+ my $num = $settings->{$item}{'order'};
+ $ordered{$num} = $item;
+ }
+ }
+ }
+ my $maxnum = scalar(keys(%ordered));
+ my $datatable = <i_javascript($settings);
+ my %lt = <i_names();
+ 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 ($key,$secret,$lifetime,$consumer,$current);
+ if (ref($settings->{$item}) eq 'HASH') {
+ $key = $settings->{$item}->{'key'};
+ $secret = $settings->{$item}->{'secret'};
+ $lifetime = $settings->{$item}->{'lifetime'};
+ $consumer = $settings->{$item}->{'consumer'};
+ $current = $settings->{$item};
+ }
+ my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_".$item."'".');"';
+ $datatable .= ''
+ .'';
+ for (my $k=0; $k<=$maxnum; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $i) {
+ $selstr = ' selected="selected" ';
+ }
+ $datatable .= ''.$vpos.' ';
+ }
+ $datatable .= ' '.(' 'x2).
+ ' '.
+ &mt('Delete?').' '.
+ ''.
+ ''.&mt('Required settings').' '.
+ ''.$lt{'consumer'}.
+ ': '.
+ (' 'x2).
+ ''.$lt{'version'}.':'.
+ '1.1 '.
+ (' 'x2).
+ ''.$lt{'lifetime'}.': '.
+ ' '.
+ ''.$lt{'key'}.
+ ': '.
+ (' 'x2).
+ ''.$lt{'secret'}.':'.
+ ' '.
+ ' '.&mt('Visible input').' '.
+ ' '.
+ ' '.<i_options($i,$current,%lt).' ';
+ $itemcount ++;
+ }
+ }
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ my $chgstr = ' onchange="javascript:reorderLTI(this.form,'."'lti_pos_add'".');"';
+ $datatable .= ''."\n".
+ ' '."\n".
+ '';
+ for (my $k=0; $k<$maxnum+1; $k++) {
+ my $vpos = $k+1;
+ my $selstr;
+ if ($k == $maxnum) {
+ $selstr = ' selected="selected" ';
+ }
+ $datatable .= ''.$vpos.' ';
+ }
+ $datatable .= ' '."\n".
+ ' '.&mt('Add').' '."\n".
+ ''.
+ ''.&mt('Required settings').' '.
+ ''.$lt{'consumer'}.
+ ': '."\n".
+ (' 'x2).
+ ''.$lt{'version'}.':'.
+ '1.1 '."\n".
+ (' 'x2).
+ ''.$lt{'lifetime'}.': '."\n".
+ ' '.
+ ''.$lt{'key'}.': '."\n".
+ (' 'x2).
+ ''.$lt{'secret'}.': '.
+ ' '.&mt('Visible input').' '."\n".
+ ' '.<i_options('add',undef,%lt).
+ ' '."\n".
+ ' '."\n";
+ $$rowtotal ++;
+ return $datatable;;
+}
+
+sub lti_names {
+ my %lt = &Apache::lonlocal::texthash(
+ 'version' => 'LTI Version',
+ 'url' => 'URL',
+ 'key' => 'Key',
+ 'lifetime' => 'Nonce lifetime (seconds)',
+ 'consumer' => 'LTI Consumer',
+ 'secret' => 'Secret',
+ 'email' => 'Email address',
+ 'sourcedid' => 'User ID',
+ 'other' => 'Other',
+ 'passback' => 'Can return grades to Consumer:',
+ 'roster' => 'Can retrieve roster from Consumer:',
);
return %lt;
}
+sub lti_options {
+ my ($num,$current,%lt) = @_;
+ my (%checked,%rolemaps,$crssecsrc,$userfield,$cidfield);
+ $checked{'mapuser'}{'sourcedid'} = ' checked="checked"';
+ $checked{'mapcrs'}{'course_offering_sourcedid'} = ' checked="checked"';
+ $checked{'makecrs'}{'N'} = ' checked="checked"';
+ $checked{'mapcrstype'} = {};
+ $checked{'makeuser'} = {};
+ $checked{'selfenroll'} = {};
+ $checked{'crssec'} = {};
+ $checked{'crssecsrc'} = {};
+
+ my $userfieldsty = 'none';
+ my $crsfieldsty = 'none';
+ my $crssecfieldsty = 'none';
+ my $secsrcfieldsty = 'none';
+
+ if (ref($current) eq 'HASH') {
+ if (($current->{'mapuser'} ne '') && ($current->{'mapuser'} ne 'lis_person_sourcedid')) {
+ $checked{'mapuser'}{'sourcedid'} = '';
+ if ($current->{'mapuser'} eq 'lis_person_contact_email_primary') {
+ $checked{'mapuser'}{'email'} = ' checked="checked"';
+ } else {
+ $checked{'mapuser'}{'other'} = ' checked="checked"';
+ $userfield = $current->{'mapuser'};
+ $userfieldsty = 'inline-block';
+ }
+ }
+ if (($current->{'mapcrs'} ne '') && ($current->{'mapcrs'} ne 'course_offering_sourcedid')) {
+ $checked{'mapcrs'}{'course_offering_sourcedid'} = '';
+ if ($current->{'mapcrs'} eq 'context_id') {
+ $checked{'mapcrs'}{'context_id'} = ' checked="checked"';
+ } else {
+ $checked{'mapcrs'}{'other'} = ' checked="checked"';
+ $cidfield = $current->{'mapcrs'};
+ $crsfieldsty = 'inline-block';
+ }
+ }
+ if (ref($current->{'mapcrstype'}) eq 'ARRAY') {
+ foreach my $type (@{$current->{'mapcrstype'}}) {
+ $checked{'mapcrstype'}{$type} = ' checked="checked"';
+ }
+ }
+ if ($current->{'makecrs'}) {
+ $checked{'makecrs'}{'Y'} = ' checked="checked"';
+ }
+ if (ref($current->{'makeuser'}) eq 'ARRAY') {
+ foreach my $role (@{$current->{'makeuser'}}) {
+ $checked{'makeuser'}{$role} = ' checked="checked"';
+ }
+ }
+ if (ref($current->{'selfenroll'}) eq 'ARRAY') {
+ foreach my $role (@{$current->{'selfenroll'}}) {
+ $checked{'selfenroll'}{$role} = ' checked="checked"';
+ }
+ }
+ if (ref($current->{'maproles'}) eq 'HASH') {
+ %rolemaps = %{$current->{'maproles'}};
+ }
+ if ($current->{'section'} ne '') {
+ $checked{'crssec'}{'Y'} = ' checked="checked"';
+ $crssecfieldsty = 'inline-block';
+ if ($current->{'section'} eq 'course_section_sourcedid') {
+ $checked{'crssecsrc'}{'sourcedid'} = ' checked="checked"';
+ } else {
+ $checked{'crssecsrc'}{'other'} = ' checked="checked"';
+ $crssecsrc = $current->{'section'};
+ $secsrcfieldsty = 'inline-block';
+ }
+ } else {
+ $checked{'crssec'}{'N'} = ' checked="checked"';
+ }
+ } else {
+ $checked{'makecrs'}{'N'} = ' checked="checked"';
+ $checked{'crssec'}{'N'} = ' checked="checked"';
+ }
+ my @coursetypes = ('official','unofficial','community','textbook','placement');
+ my %coursetypetitles = &Apache::lonlocal::texthash (
+ official => 'Official',
+ unofficial => 'Unofficial',
+ community => 'Community',
+ textbook => 'Textbook',
+ placement => 'Placement Test',
+ );
+ my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
+ my @lticourseroles = qw(Learner Instructor TeachingAssistant Mentor);
+ my @courseroles = ('cc','in','ta','ep','st');
+ my $onclickuser = ' onclick="toggleLTI(this.form,'."'user','$num'".');"';
+ my $onclickcrs = ' onclick="toggleLTI(this.form,'."'crs','$num'".');"';
+ my $onclicksec = ' onclick="toggleLTI(this.form,'."'sec','$num'".');"';
+ my $onclicksecsrc = ' onclick="toggleLTI(this.form,'."'secsrc','$num'".')"';
+ my $output = ''.&mt('Mapping users').' '.
+ ''.&mt('LON-CAPA username').': ';
+ foreach my $option ('sourcedid','email','other') {
+ $output .= ' '.$lt{$option}.' '.
+ ($option eq 'other' ? '' : (' 'x2) );
+ }
+ $output .= '
'.
+ ''.
+ '
'.
+ ''.&mt('Mapping course roles').' ';
+ foreach my $ltirole (@lticourseroles) {
+ my ($selected,$selectnone);
+ if ($rolemaps{$ltirole} eq '') {
+ $selectnone = ' selected="selected"';
+ }
+ $output .= ''.$ltirole.' '.
+ ''.
+ ''.&mt('Select').' ';
+ foreach my $role (@courseroles) {
+ unless ($selectnone) {
+ if ($rolemaps{$ltirole} eq $role) {
+ $selected = ' selected="selected"';
+ } else {
+ $selected = '';
+ }
+ }
+ $output .= ''.
+ &Apache::lonnet::plaintext($role,'Course').
+ ' ';
+ }
+ $output .= ' ';
+ }
+ $output .= '
'.
+ ''.&mt('Roles which may create user accounts').' ';
+ foreach my $ltirole (@ltiroles) {
+ $output .= ' '.$ltirole.' ';
+ }
+ $output .= ' '.
+ ''.&mt('Mapping courses').' '.
+ ''.
+ &mt('Unique course identifier').': ';
+ foreach my $option ('course_offering_sourcedid','context_id','other') {
+ $output .= ' '.$option.' '.
+ ($option eq 'other' ? '' : (' 'x2) );
+ }
+ $output .= '
'.
+ ' '.
+ '
'.
+ ''.&mt('LON-CAPA course type(s)').': ';
+ foreach my $type (@coursetypes) {
+ $output .= ' '.$coursetypetitles{$type}.' '.
+ (' 'x2);
+ }
+ $output .= ' '.
+ ''.&mt('Creating courses').' '.
+ ''.&mt('Course created (if absent) on Instructor access').': '.
+ ' '.&mt('No').' '.(' 'x2).
+ ' '.&mt('Yes').' '.
+ ' '.
+ ''.&mt('Roles which may self-enroll').' ';
+ foreach my $lticrsrole (@lticourseroles) {
+ $output .= ' '.$lticrsrole.' ';
+ }
+ $output .= ' '.
+ ''.&mt('Course options').' '.
+ ''.&mt('Assign users to sections').': '.
+ ' '.&mt('No').' '.(' 'x2).
+ ' '.&mt('Yes').'
'.
+ ''.
+ ' '.
+ '
';
+ foreach my $extra ('passback','roster') {
+ my $checkedon = '';
+ my $checkedoff = ' checked="checked"';
+ if (ref($current) eq 'HASH') {
+ if (($current->{$extra})) {
+ $checkedon = $checkedoff;
+ $checkedoff = '';
+ }
+ }
+ $output .= $lt{$extra}.' '.
+ ' '.
+ &mt('No').' '.(' 'x2).
+ ' '.
+ &mt('Yes').' ';
+ }
+ $output .= ' ';
+# ''.&mt('Assigning author roles').' ';
+#
+# $output .= ' '.
+# ''.&mt('Assigning domain roles').' ';
+ return $output;
+}
+
sub print_coursedefaults {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles);
@@ -4169,7 +4908,7 @@ sub print_coursedefaults {
if ($checked) {
$show = 'block';
}
- $additional = '
'.
+ $additional = '
'.
&mt('Institutional codes for new and cloned course have identical:').
' ';
foreach my $item (@code_order) {
@@ -5484,7 +6223,7 @@ sub loadbalance_rule_row {
}
my $space;
if ($islast && $num == 1) {
- $space = '
';
+ $space = '
';
}
my $output =
''.$space.
@@ -5570,8 +6309,8 @@ sub contact_titles {
'adminemail' => 'Default Server Admin E-mail address',
'errormail' => 'Error reports to be e-mailed to',
'packagesmail' => 'Package update alerts to be e-mailed to',
- 'helpdeskmail' => "Helpdesk requests for this domain's users",
- 'otherdomsmail' => 'Helpdesk requests for other (unconfigured) domains',
+ 'helpdeskmail' => "Helpdesk requests from all users in this domain",
+ 'otherdomsmail' => 'Helpdesk requests from users in other (unconfigured) domains',
'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)',
'requestsmail' => 'E-mail from course requests requiring approval',
'updatesmail' => 'E-mail from nightly check of LON-CAPA module integrity/updates',
@@ -7776,6 +8515,7 @@ sub insttypes_row {
statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)',
lockablenames => 'User preference to lock name',
selfassign => 'Self-reportable affiliations',
+ overrides => "Override domain's helpdesk settings based on requester's affiliation",
);
my $showdom;
if ($context eq 'cansearch') {
@@ -7822,6 +8562,10 @@ sub insttypes_row {
if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) {
$check = ' checked="checked" ';
}
+ } elsif (ref($settings->{$context}) eq 'HASH') {
+ if (ref($settings->{$context}->{$types->[$i]}) eq 'HASH') {
+ $check = ' checked="checked" ';
+ }
} elsif ($context eq 'statustocreate') {
$check = ' checked="checked" ';
}
@@ -7836,29 +8580,38 @@ sub insttypes_row {
$rem = @{$types}%($numinrow);
}
my $colsleft = $numinrow - $rem;
- if (($rem == 0) && (@{$types} > 0)) {
- $output .= ' ';
- }
- if ($colsleft > 1) {
- $output .= '';
+ if ($context eq 'overrides') {
+ if ($colsleft > 1) {
+ $output .= ' ';
+ } else {
+ $output .= ' ';
+ }
+ $output .= ' ';
} else {
- $output .= ' ';
- }
- my $defcheck = ' ';
- if (ref($settings) eq 'HASH') {
- if (ref($settings->{$context}) eq 'ARRAY') {
- if (grep(/^default$/,@{$settings->{$context}})) {
+ if (($rem == 0) && (@{$types} > 0)) {
+ $output .= ' ';
+ }
+ if ($colsleft > 1) {
+ $output .= '';
+ } else {
+ $output .= ' ';
+ }
+ my $defcheck = ' ';
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$context}) eq 'ARRAY') {
+ if (grep(/^default$/,@{$settings->{$context}})) {
+ $defcheck = ' checked="checked" ';
+ }
+ } elsif ($context eq 'statustocreate') {
$defcheck = ' checked="checked" ';
}
- } elsif ($context eq 'statustocreate') {
- $defcheck = ' checked="checked" ';
}
+ $output .= ''.
+ ' '.
+ $othertitle.' ';
}
- $output .= ''.
- ' '.
- $othertitle.' '.
- ' ';
+ $output .= '';
return $output;
}
@@ -8892,14 +9645,14 @@ sub publishlogo {
} else {
my $source = $filepath.'/'.$file;
my $logfile;
- if (!open($logfile,">>$source".'.log')) {
+ if (!open($logfile,">>",$source.'.log')) {
return (&mt('No write permission to Authoring Space'));
}
print $logfile
"\n================= Publish ".localtime()." ================\n".
$env{'user.name'}.':'.$env{'user.domain'}."\n";
# Save the file
- if (!open(FH,'>'.$source)) {
+ if (!open(FH,">",$source)) {
&Apache::lonnet::logthis('Failed to create '.$source);
return (&mt('Failed to create file'));
}
@@ -8960,7 +9713,8 @@ $env{'user.name'}.':'.$env{'user.domain'
if ($fullwidth ne '' && $fullheight ne '') {
if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) {
my $thumbsize = $thumbwidth.'x'.$thumbheight;
- system("convert -sample $thumbsize $inputfile $outfile");
+ my @args = ('convert','-sample',$thumbsize,$inputfile,$outfile);
+ system({$args[0]} @args);
chmod(0660, $filepath.'/tn-'.$file);
if (-e $outfile) {
my $copyfile=$targetdir.'/tn-'.$file;
@@ -9040,7 +9794,7 @@ sub write_metadata {
{
print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file;
my $mfh;
- if (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) {
+ if (open($mfh,">",$targetdir.'/'.$file.'.meta')) {
foreach (sort(keys(%metadatafields))) {
unless ($_=~/\./) {
my $unikey=$_;
@@ -9074,7 +9828,7 @@ sub notifysubscribed {
next unless (ref($targetsource) eq 'ARRAY');
my ($target,$source)=@{$targetsource};
if ($source ne '') {
- if (open(my $logfh,'>>'.$source.'.log')) {
+ if (open(my $logfh,">>",$source.'.log')) {
print $logfh "\nCleanup phase: Notifications\n";
my @subscribed=&subscribed_hosts($target);
foreach my $subhost (@subscribed) {
@@ -9100,7 +9854,7 @@ sub notifysubscribed {
sub subscribed_hosts {
my ($target) = @_;
my @subscribed;
- if (open(my $fh,"<$target.subscription")) {
+ if (open(my $fh,"<","$target.subscription")) {
while (my $subline=<$fh>) {
if ($subline =~ /^($match_lonid):/) {
my $host = $1;
@@ -9927,8 +10681,15 @@ sub modify_ltitools {
$confhash{$newid}{'display'}{'target'} = 'iframe';
}
foreach my $item ('passback','roster') {
- if ($env{'form.ltitools_add_'.$item}) {
+ if ($env{'form.ltitools_'.$item.'_add'}) {
$confhash{$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*$/) {
+ $confhash{$newid}{$item.'valid'} = $lifetime;
+ }
+ }
}
}
if ($env{'form.ltitools_add_image.filename'} ne '') {
@@ -10078,13 +10839,23 @@ sub modify_ltitools {
foreach my $extra ('passback','roster') {
if ($env{'form.ltitools_'.$extra.'_'.$i}) {
$confhash{$itemid}{$extra} = 1;
+ if ($env{'form.ltitools_'.$extra.'valid_'.$i} ne '') {
+ my $lifetime = $env{'form.ltitools_'.$extra.'valid_add'};
+ $lifetime =~ s/^\s+|\s+$//g;
+ if ($lifetime =~ /^\d+\.?\d*$/) {
+ $confhash{$itemid}{$extra.'valid'} = $lifetime;
+ }
+ }
}
if ($domconfig{$action}{$itemid}{$extra} ne $confhash{$itemid}{$extra}) {
$changes{$itemid} = 1;
}
+ if ($domconfig{$action}{$itemid}{$extra.'valid'} ne $confhash{$itemid}{$extra.'valid'}) {
+ $changes{$itemid} = 1;
+ }
}
my @courseconfig = &Apache::loncommon::get_env_multiple('form.ltitools_courseconfig_'.$i);
- foreach my $item ('label','title','target','linktext','explanation') {
+ foreach my $item ('label','title','target','linktext','explanation','append') {
if (grep(/^\Q$item\E$/,@courseconfig)) {
$confhash{$itemid}{'crsconf'}{$item} = 1;
if (ref($domconfig{$action}{$itemid}{'crsconf'}) eq 'HASH') {
@@ -10275,7 +11046,7 @@ sub modify_ltitools {
$resulttext .= ('*'x$num).'';
}
$resulttext .= ''.&mt('Configurable in course:');
- my @possconfig = ('label','title','target','linktext','explanation');
+ my @possconfig = ('label','title','target','linktext','explanation','append');
my $numconfig = 0;
if (ref($confhash{$itemid}{'crsconf'}) eq 'HASH') {
foreach my $item (@possconfig) {
@@ -10293,6 +11064,15 @@ sub modify_ltitools {
$resulttext .= ' '.$lt{$item}.' ';
if ($confhash{$itemid}{$item}) {
$resulttext .= &mt('Yes');
+ if ($confhash{$itemid}{$item.'valid'}) {
+ if ($item eq 'passback') {
+ $resulttext .= ' '.&mt('valid for at least [quant,_1,day] after launch',
+ $confhash{$itemid}{$item.'valid'});
+ } else {
+ $resulttext .= ' '.&mt('valid for at least [quant,_1,second] after launch',
+ $confhash{$itemid}{$item.'valid'});
+ }
+ }
} else {
$resulttext .= &mt('No');
}
@@ -10353,7 +11133,7 @@ sub modify_ltitools {
}
}
if ($customlist) {
- $resulttext .= ' '.&mt('Custom items').':'.$customlist.' ';
+ $resulttext .= ''.&mt('Custom items').': '.$customlist.' ';
}
}
$resulttext .= '';
@@ -10449,6 +11229,422 @@ sub get_ltitools_id {
return ($id,$error);
}
+sub modify_lti {
+ my ($r,$dom,$action,$lastactref,%domconfig) = @_;
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+ my ($newid,@allpos,%changes,%confhash,%encconfig,$errors,$resulttext);
+ my (%posslti,%posslticrs,%posscrstype);
+ my @courseroles = ('cc','in','ta','ep','st');
+ my @ltiroles = qw(Learner Instructor ContentDeveloper TeachingAssistant Mentor Member Manager Administrator);
+ my @lticourseroles = qw(Instructor TeachingAssistant Mentor Learner);
+ my @coursetypes = ('official','unofficial','community','textbook','placement');
+ my %coursetypetitles = &Apache::lonlocal::texthash (
+ official => 'Official',
+ unofficial => 'Unofficial',
+ community => 'Community',
+ textbook => 'Textbook',
+ placement => 'Placement Test',
+ );
+ my %lt = <i_names();
+ map { $posslti{$_} = 1; } @ltiroles;
+ map { $posslticrs{$_} = 1; } @lticourseroles;
+ map { $posscrstype{$_} = 1; } @coursetypes;
+
+ my (@items,%deletions,%itemids);
+ if ($env{'form.lti_add'}) {
+ my $consumer = $env{'form.lti_consumer_add'};
+ $consumer =~ s/(`)/'/g;
+ ($newid,my $error) = &get_lti_id($dom,$consumer);
+ if ($newid) {
+ $itemids{'add'} = $newid;
+ push(@items,'add');
+ $changes{$newid} = 1;
+ } else {
+ my $error = &mt('Failed to acquire unique ID for new LTI configuration');
+ $errors .= ''.$error.' ';
+ }
+ }
+ if (ref($domconfig{$action}) eq 'HASH') {
+ my @todelete = &Apache::loncommon::get_env_multiple('form.lti_del');
+ if (@todelete) {
+ map { $deletions{$_} = 1; } @todelete;
+ }
+ my $maxnum = $env{'form.lti_maxnum'};
+ for (my $i=0; $i<=$maxnum; $i++) {
+ my $itemid = $env{'form.lti_id_'.$i};
+ $itemid =~ s/\D+//g;
+ if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
+ if ($deletions{$itemid}) {
+ $changes{$itemid} = $domconfig{$action}{$itemid}{'consumer'};
+ } else {
+ push(@items,$i);
+ $itemids{$i} = $itemid;
+ }
+ }
+ }
+ }
+ foreach my $idx (@items) {
+ my $itemid = $itemids{$idx};
+ next unless ($itemid);
+ my $position = $env{'form.lti_pos_'.$idx};
+ $position =~ s/\D+//g;
+ if ($position ne '') {
+ $allpos[$position] = $itemid;
+ }
+ foreach my $item ('consumer','key','secret','lifetime') {
+ my $formitem = 'form.lti_'.$item.'_'.$idx;
+ $env{$formitem} =~ s/(`)/'/g;
+ if ($item eq 'lifetime') {
+ $env{$formitem} =~ s/[^\d.]//g;
+ }
+ if ($env{$formitem} ne '') {
+ if (($item eq 'key') || ($item eq 'secret')) {
+ $encconfig{$itemid}{$item} = $env{$formitem};
+ } else {
+ $confhash{$itemid}{$item} = $env{$formitem};
+ unless (($idx eq 'add') || ($changes{$itemid})) {
+ if ($domconfig{$action}{$itemid}{$item} ne $confhash{$itemid}{$item}) {
+ $changes{$itemid} = 1;
+ }
+ }
+ }
+ }
+ }
+ if ($env{'form.lti_version_'.$idx} eq 'LTI-1p0') {
+ $confhash{$itemid}{'version'} = $env{'form.lti_version_'.$idx};
+ }
+ if ($env{'form.lti_mapuser_'.$idx} eq 'sourcedid') {
+ $confhash{$itemid}{'mapuser'} = 'lis_person_sourcedid';
+ } elsif ($env{'form.lti_mapuser_'.$idx} eq 'email') {
+ $confhash{$itemid}{'mapuser'} = 'lis_person_contact_email_primary';
+ } elsif ($env{'form.lti_mapuser_'.$idx} eq 'other') {
+ my $mapuser = $env{'form.lti_customuser_'.$idx};
+ $mapuser =~ s/(`)/'/g;
+ $mapuser =~ s/^\s+|\s+$//g;
+ $confhash{$itemid}{'mapuser'} = $mapuser;
+ }
+ foreach my $ltirole (@lticourseroles) {
+ my $possrole = $env{'form.lti_maprole_'.$ltirole.'_'.$idx};
+ if (grep(/^\Q$possrole\E$/,@courseroles)) {
+ $confhash{$itemid}{'maproles'}{$ltirole} = $possrole;
+ }
+ }
+ my @possmakeuser = &Apache::loncommon::get_env_multiple('form.lti_makeuser_'.$idx);
+ my @makeuser;
+ foreach my $ltirole (sort(@possmakeuser)) {
+ if ($posslti{$ltirole}) {
+ push(@makeuser,$ltirole);
+ }
+ }
+ $confhash{$itemid}{'makeuser'} = \@makeuser;
+ if (($env{'form.lti_mapcrs_'.$idx} eq 'course_offering_sourcedid') ||
+ ($env{'form.lti_mapcrs_'.$idx} eq 'context_id')) {
+ $confhash{$itemid}{'mapcrs'} = $env{'form.lti_mapcrs_'.$idx};
+ } elsif ($env{'form.lti_mapcrs_'.$idx} eq 'other') {
+ my $mapcrs = $env{'form.lti_mapcrsfield_'.$idx};
+ $mapcrs =~ s/(`)/'/g;
+ $mapcrs =~ s/^\s+|\s+$//g;
+ $confhash{$itemid}{'mapcrs'} = $mapcrs;
+ }
+ my @posstypes = &Apache::loncommon::get_env_multiple('form.lti_mapcrstype_'.$idx);
+ my @crstypes;
+ foreach my $type (sort(@posstypes)) {
+ if ($posscrstype{$type}) {
+ push(@crstypes,$type);
+ }
+ }
+ $confhash{$itemid}{'mapcrstype'} = \@crstypes;
+ if ($env{'form.lti_makecrs_'.$idx}) {
+ $confhash{$itemid}{'makecrs'} = 1;
+ }
+ my @possenroll = &Apache::loncommon::get_env_multiple('form.lti_selfenroll_'.$idx);
+ my @selfenroll;
+ foreach my $type (sort(@possenroll)) {
+ if ($posslticrs{$type}) {
+ push(@selfenroll,$type);
+ }
+ }
+ $confhash{$itemid}{'selfenroll'} = \@selfenroll;
+ if ($env{'form.lti_crssec_'.$idx}) {
+ if ($env{'form.lti_crssecsrc_'.$idx} eq 'course_section_sourcedid') {
+ $confhash{$itemid}{'section'} = $env{'form.lti_crssecsrc_'.$idx};
+ } elsif ($env{'form.lti_crssecsrc_'.$idx} eq 'other') {
+ my $section = $env{'form.lti_customsection_'.$idx};
+ $section =~ s/(`)/'/g;
+ $section =~ s/^\s+|\s+$//g;
+ if ($section ne '') {
+ $confhash{$itemid}{'section'} = $section;
+ }
+ }
+ }
+ foreach my $field ('passback','roster') {
+ if ($env{'form.lti_'.$field.'_'.$idx}) {
+ $confhash{$itemid}{$field} = 1;
+ }
+ }
+ unless (($idx eq 'add') || ($changes{$itemid})) {
+ foreach my $field ('mapuser','mapcrs','section','passback','roster') {
+ if ($domconfig{$action}{$itemid}{$field} ne $confhash{$itemid}{$field}) {
+ $changes{$itemid} = 1;
+ }
+ }
+ foreach my $field ('makeuser','mapcrstype','selfenroll') {
+ unless ($changes{$itemid}) {
+ if (ref($domconfig{$action}{$itemid}{$field}) eq 'ARRAY') {
+ if (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
+ my @diffs = &Apache::loncommon::compare_arrays($domconfig{$action}{$itemid}{$field},
+ $confhash{$itemid}{$field});
+ if (@diffs) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (@{$domconfig{$action}{$itemid}{$field}} > 0) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (ref($confhash{$itemid}{$field}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{$field}} > 0) {
+ $changes{$itemid} = 1;
+ }
+ }
+ }
+ }
+ unless ($changes{$itemid}) {
+ if (ref($domconfig{$action}{$itemid}{'maproles'}) eq 'HASH') {
+ if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ foreach my $ltirole (keys(%{$domconfig{$action}{$itemid}{'maproles'}})) {
+ if ($domconfig{$action}{$itemid}{'maproles'}{$ltirole} ne
+ $confhash{$itemid}{'maproles'}{$ltirole}) {
+ $changes{$itemid} = 1;
+ last;
+ }
+ }
+ unless ($changes{$itemid}) {
+ foreach my $ltirole (keys(%{$confhash{$itemid}{'maproles'}})) {
+ if ($confhash{$itemid}{'maproles'}{$ltirole} ne
+ $domconfig{$action}{$itemid}{'maproles'}{$ltirole}) {
+ $changes{$itemid} = 1;
+ last;
+ }
+ }
+ }
+ } elsif (keys(%{$domconfig{$action}{$itemid}{'maproles'}}) > 0) {
+ $changes{$itemid} = 1;
+ }
+ } elsif (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ unless ($changes{$itemid}) {
+ if (keys(%{$confhash{$itemid}{'maproles'}}) > 0) {
+ $changes{$itemid} = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (@allpos > 0) {
+ my $idx = 0;
+ foreach my $itemid (@allpos) {
+ if ($itemid ne '') {
+ $confhash{$itemid}{'order'} = $idx;
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$itemid}) eq 'HASH') {
+ if ($domconfig{$action}{$itemid}{'order'} ne $idx) {
+ $changes{$itemid} = 1;
+ }
+ }
+ }
+ $idx ++;
+ }
+ }
+ }
+ my %ltihash = (
+ $action => { %confhash }
+ );
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%ltihash,
+ $dom);
+ if ($putresult eq 'ok') {
+ my %ltienchash = (
+ $action => { %encconfig }
+ );
+ &Apache::lonnet::put_dom('encconfig',\%ltienchash,$dom);
+ if (keys(%changes) > 0) {
+ my $cachetime = 24*60*60;
+ my %ltiall = %confhash;
+ foreach my $id (keys(%ltiall)) {
+ if (ref($encconfig{$id}) eq 'HASH') {
+ foreach my $item ('key','secret') {
+ $ltiall{$id}{$item} = $encconfig{$id}{$item};
+ }
+ }
+ }
+ &Apache::lonnet::do_cache_new('lti',$dom,\%ltiall,$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'lti'} = 1;
+ }
+ $resulttext = &mt('Changes made:').'';
+ my %bynum;
+ foreach my $itemid (sort(keys(%changes))) {
+ my $position = $confhash{$itemid}{'order'};
+ $bynum{$position} = $itemid;
+ }
+ foreach my $pos (sort { $a <=> $b } keys(%bynum)) {
+ my $itemid = $bynum{$pos};
+ if (ref($confhash{$itemid}) ne 'HASH') {
+ $resulttext .= ''.&mt('Deleted: [_1]',$changes{$itemid}).' ';
+ } else {
+ $resulttext .= ''.$confhash{$itemid}{'consumer'}.' ';
+ my $position = $pos + 1;
+ $resulttext .= ''.&mt('Order: [_1]',$position).' ';
+ foreach my $item ('version','lifetime') {
+ if ($confhash{$itemid}{$item} ne '') {
+ $resulttext .= ''.$lt{$item}.': '.$confhash{$itemid}{$item}.' ';
+ }
+ }
+ if ($encconfig{$itemid}{'key'} ne '') {
+ $resulttext .= ''.$lt{'key'}.': '.$encconfig{$itemid}{'key'}.' ';
+ }
+ if ($encconfig{$itemid}{'secret'} ne '') {
+ $resulttext .= ''.$lt{'secret'}.': ';
+ my $num = length($encconfig{$itemid}{'secret'});
+ $resulttext .= ('*'x$num).' ';
+ }
+ if ($confhash{$itemid}{'mapuser'}) {
+ my $shownmapuser;
+ if ($confhash{$itemid}{'mapuser'} eq 'lis_person_sourcedid') {
+ $shownmapuser = $lt{'sourcedid'}.' (lis_person_sourcedid)';
+ } elsif ($confhash{$itemid}{'mapuser'} eq 'lis_person_contact_email_primary') {
+ $shownmapuser = $lt{'email'}.' (lis_person_contact_email_primary)';
+ } else {
+ $shownmapuser = &mt('Other').' ('.$confhash{$itemid}{'mapuser'}.')';
+ }
+ $resulttext .= ''.&mt('LON-CAPA username').': '.$shownmapuser.' ';
+ }
+ if (ref($confhash{$itemid}{'maproles'}) eq 'HASH') {
+ my $rolemaps;
+ foreach my $role (@ltiroles) {
+ if ($confhash{$itemid}{'maproles'}{$role}) {
+ $rolemaps .= (' 'x2).$role.'='.
+ &Apache::lonnet::plaintext($confhash{$itemid}{'maproles'}{$role},
+ 'Course').',';
+ }
+ }
+ if ($rolemaps) {
+ $rolemaps =~ s/,$//;
+ $resulttext .= ''.&mt('Role mapping:').$rolemaps.' ';
+ }
+ }
+ if (ref($confhash{$itemid}{'makeuser'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'makeuser'}} > 0) {
+ $resulttext .= ''.&mt('Following roles may create user accounts: [_1]',
+ join(', ',@{$confhash{$itemid}{'makeuser'}})).' ';
+ } else {
+ $resulttext .= ''.&mt('User account creation not permitted.').' ';
+ }
+ }
+ if ($confhash{$itemid}{'mapcrs'}) {
+ $resulttext .= ''.&mt('Unique course identifier').': '.$confhash{$itemid}{'mapcrs'}.' ';
+ }
+ if (ref($confhash{$itemid}{'mapcrstype'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'mapcrstype'}} > 0) {
+ $resulttext .= ''.&mt('Mapping for the following LON-CAPA course types: [_1]',
+ join(', ',map { $coursetypetitles{$_}; } @coursetypes)).
+ ' ';
+ } else {
+ $resulttext .= ''.&mt('No mapping to LON-CAPA courses').' ';
+ }
+ }
+ if ($confhash{$itemid}{'makecrs'}) {
+ $resulttext .= ''.&mt('Instructor may create course (if absent).').' ';
+ } else {
+ $resulttext .= ''.&mt('Instructor may not create course (if absent).').' ';
+ }
+ if (ref($confhash{$itemid}{'selfenroll'}) eq 'ARRAY') {
+ if (@{$confhash{$itemid}{'selfenroll'}} > 0) {
+ $resulttext .= ''.&mt('Self-enrollment for following roles: [_1]',
+ join(', ',@{$confhash{$itemid}{'selfenroll'}})).
+ ' ';
+ } else {
+ $resulttext .= ''.&mt('Self-enrollment not permitted').' ';
+ }
+ }
+ if ($confhash{$itemid}{'section'}) {
+ if ($confhash{$itemid}{'section'} eq 'course_section_sourcedid') {
+ $resulttext .= ''.&mt('User section from standard field:').
+ ' (course_section_sourcedid)'.' ';
+ } else {
+ $resulttext .= ''.&mt('User section from:').' '.
+ $confhash{$itemid}{'section'}.' ';
+ }
+ } else {
+ $resulttext .= ''.&mt('No section assignment').' ';
+ }
+ foreach my $item ('passback','roster') {
+ $resulttext .= ''.$lt{$item}.' ';
+ if ($confhash{$itemid}{$item}) {
+ $resulttext .= &mt('Yes');
+ } else {
+ $resulttext .= &mt('No');
+ }
+ $resulttext .= ' ';
+ }
+ $resulttext .= ' ';
+ }
+ }
+ $resulttext .= ' ';
+ } else {
+ $resulttext = &mt('No changes made.');
+ }
+ } else {
+ $errors .= ''.&mt('Failed to save changes').' ';
+ }
+ if ($errors) {
+ $resulttext .= &mt('The following errors occurred: ').'';
+ }
+ return $resulttext;
+}
+
+sub get_lti_id {
+ my ($domain,$consumer) = @_;
+ # get lock on lti db
+ my $lockhash = {
+ lock => $env{'user.name'}.
+ ':'.$env{'user.domain'},
+ };
+ my $tries = 0;
+ my $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
+ my ($id,$error);
+
+ while (($gotlock ne 'ok') && ($tries<10)) {
+ $tries ++;
+ sleep (0.1);
+ $gotlock = &Apache::lonnet::newput_dom('lti',$lockhash,$domain);
+ }
+ if ($gotlock eq 'ok') {
+ my %currids = &Apache::lonnet::dump_dom('lti',$domain);
+ if ($currids{'lock'}) {
+ delete($currids{'lock'});
+ if (keys(%currids)) {
+ my @curr = sort { $a <=> $b } keys(%currids);
+ if ($curr[-1] =~ /^\d+$/) {
+ $id = 1 + $curr[-1];
+ }
+ } else {
+ $id = 1;
+ }
+ if ($id) {
+ unless (&Apache::lonnet::newput_dom('lti',{ $id => $consumer },$domain) eq 'ok') {
+ $error = 'nostore';
+ }
+ } else {
+ $error = 'nonumber';
+ }
+ }
+ my $dellockoutcome = &Apache::lonnet::del_dom('lti',['lock'],$domain);
+ } else {
+ $error = 'nolock';
+ }
+ return ($id,$error);
+}
+
sub modify_autoenroll {
my ($dom,$lastactref,%domconfig) = @_;
my ($resulttext,%changes);
@@ -11074,17 +12270,57 @@ sub modify_contacts {
my $value = $env{'form.helpform_'.$field};
$value =~ s/^\s+|\s+$//g;
if (grep(/^\Q$value\E$/,@{$possoptions->{$field}})) {
- $contacts_hash{contacts}{'helpform'}{$field} = $value;
+ $contacts_hash{'contacts'}{'helpform'}{$field} = $value;
if ($field eq 'screenshot') {
$env{'form.helpform_maxsize'} =~ s/^\s+|\s+$//g;
if ($env{'form.helpform_maxsize'} =~ /^\d+\.?\d*$/) {
- $contacts_hash{contacts}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};
+ $contacts_hash{'contacts'}{'helpform'}{'maxsize'} = $env{'form.helpform_maxsize'};
}
}
}
}
}
}
+ my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom);
+ my (@statuses,%usertypeshash,@overrides);
+ if ((ref($types) eq 'ARRAY') && (@{$types} > 0)) {
+ @statuses = @{$types};
+ if (ref($usertypes) eq 'HASH') {
+ %usertypeshash = %{$usertypes};
+ }
+ }
+ if (@statuses) {
+ my @possoverrides = &Apache::loncommon::get_env_multiple('form.overrides');
+ foreach my $type (@possoverrides) {
+ if (($type ne '') && (grep(/^\Q$type\E$/,@statuses))) {
+ push(@overrides,$type);
+ }
+ }
+ if (@overrides) {
+ foreach my $type (@overrides) {
+ my @standard = &Apache::loncommon::get_env_multiple('form.override_'.$type);
+ foreach my $item (@contacts) {
+ if (grep(/^\Q$item\E$/,@standard)) {
+ $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 1;
+ $newsetting{'override_'.$type}{$item} = 1;
+ } else {
+ $contacts_hash{'contacts'}{'overrides'}{$type}{$item} = 0;
+ $newsetting{'override_'.$type}{$item} = 0;
+ }
+ }
+ $contacts_hash{'contacts'}{'overrides'}{$type}{'others'} = $env{'form.override_'.$type.'_others'};
+ $contacts_hash{'contacts'}{'overrides'}{$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};
+ $newsetting{'override_'.$type}{'others'} = $env{'form.override_'.$type.'_others'};
+ $newsetting{'override_'.$type}{'bcc'} = $env{'form.override_'.$type.'_bcc'};
+ if (($env{'form.override_'.$type.'_includestr'} ne '') && ($env{'form.override_'.$type.'_includeloc'} =~ /^s|b$/)) {
+ $includestr{$type} = $env{'form.override_'.$type.'_includestr'};
+ $includeloc{$type} = $env{'form.override_'.$type.'_includeloc'};
+ $contacts_hash{'contacts'}{'overrides'}{$type}{'include'} = $includeloc{$type}.':'.&escape($includestr{$type});
+ $newsetting{'override_'.$type}{'include'} = $contacts_hash{'contacts'}{'overrides'}{$type}{'include'};
+ }
+ }
+ }
+ }
if (keys(%currsetting) > 0) {
foreach my $item (@contacts) {
if ($to{$item} ne $currsetting{$item}) {
@@ -11139,6 +12375,33 @@ sub modify_contacts {
}
}
}
+ if (@statuses) {
+ if (ref($currsetting{'overrides'}) eq 'HASH') {
+ foreach my $key (keys(%{$currsetting{'overrides'}})) {
+ if (ref($currsetting{'overrides'}{$key}) eq 'HASH') {
+ if (ref($newsetting{'override_'.$key}) eq 'HASH') {
+ foreach my $item (@contacts,'bcc','others','include') {
+ if ($currsetting{'overrides'}{$key}{$item} ne $newsetting{'override_'.$key}{$item}) {
+ push(@{$changes{'overrides'}},$key);
+ last;
+ }
+ }
+ } else {
+ push(@{$changes{'overrides'}},$key);
+ }
+ }
+ }
+ foreach my $key (@overrides) {
+ unless (exists($currsetting{'overrides'}{$key})) {
+ push(@{$changes{'overrides'}},$key);
+ }
+ }
+ } else {
+ foreach my $key (@overrides) {
+ push(@{$changes{'overrides'}},$key);
+ }
+ }
+ }
} else {
my %default;
$default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'};
@@ -11253,6 +12516,60 @@ sub modify_contacts {
$resulttext .= '';
}
}
+ if (ref($changes{'overrides'}) eq 'ARRAY') {
+ my @deletions;
+ foreach my $type (@{$changes{'overrides'}}) {
+ if ($usertypeshash{$type}) {
+ if (grep(/^\Q$type\E/,@overrides)) {
+ $resulttext .= ''.&mt("Overrides based on requester's affiliation set for [_1]",
+ $usertypeshash{$type}).'';
+ if (ref($newsetting{'override_'.$type}) eq 'HASH') {
+ my @text;
+ foreach my $item (@contacts) {
+ if ($newsetting{'override_'.$type}{$item}) {
+ push(@text,$short_titles->{$item});
+ }
+ }
+ if ($newsetting{'override_'.$type}{'others'} ne '') {
+ push(@text,$newsetting{'override_'.$type}{'others'});
+ }
+
+ if (@text) {
+ $resulttext .= &mt('Helpdesk e-mail sent to: [_1]',
+ ''.join(', ',@text).' ');
+ }
+ if ($newsetting{'override_'.$type}{'bcc'} ne '') {
+ my $bcctext;
+ if (@text) {
+ $bcctext = ' '.&mt('with Bcc to');
+ } else {
+ $bcctext = '(Bcc)';
+ }
+ $resulttext .= $bcctext.': '.$newsetting{'override_'.$type}{'bcc'}.' ';
+ } elsif (!@text) {
+ $resulttext .= &mt('Helpdesk e-mail sent to no one');
+ }
+ $resulttext .= ' ';
+ if ($newsetting{'override_'.$type}{'include'} ne '') {
+ my ($loc,$str) = split(/:/,$newsetting{'override_'.$type}{'include'});
+ if ($loc eq 'b') {
+ $resulttext .= ''.&mt('Text automatically added to e-mail body:').' '.&unescape($str).' ';
+ } elsif ($loc eq 's') {
+ $resulttext .= ''.&mt('Text automatically added to e-mail subject:').' '.&unescape($str).' ';
+ }
+ }
+ }
+ $resulttext .= ' ';
+ } else {
+ push(@deletions,$usertypeshash{$type});
+ }
+ }
+ }
+ if (@deletions) {
+ $resulttext .= ''.&mt("Overrides based on requester's affiliation discontinued for: [_1]",
+ join(', ',@deletions)).' ';
+ }
+ }
my @offon = ('off','on');
if ($changes{'reporterrors'}) {
$resulttext .= ''.
@@ -11308,7 +12625,6 @@ sub modify_contacts {
&mt('Max size for file uploaded to help form by logged-in user set to [_1] MB.',
$contacts_hash{'contacts'}{'helpform'}{'maxsize'}).
' ';
-
}
}
$resulttext .= '';