# The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # # $Id: domainprefs.pm,v 1.49 2008/05/08 22:13:32 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA# # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # ############################################################### ############################################################## package Apache::domainprefs; use strict; use Apache::Constants qw(:common :http); use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonlocal; use Apache::lonmsg(); use LONCAPA; use LONCAPA::Enrollment; use File::Copy; use Locale::Language; sub handler { my $r=shift; if ($r->header_only) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK; } my $dom = $env{'request.role.domain'}; my $domdesc = &Apache::lonnet::domain($dom,'description'); if (&Apache::lonnet::allowed('mau',$dom)) { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; } else { $env{'user.error.msg'}= "/adm/domainprefs:mau:0:0:Cannot modify domain settings"; return HTTP_NOT_ACCEPTABLE; } &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['phase']); my $phase = 'pickactions'; if ( exists($env{'form.phase'}) ) { $phase = $env{'form.phase'}; } my %domconfig = &Apache::lonnet::get_dom('configuration',['login','rolecolors', 'quotas','autoenroll','autoupdate','directorysrch', 'usercreation','usermodification','contacts','defaults', 'scantron','coursecategories'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','directorysrch','contacts', 'usercreation','usermodification','scantron', 'coursecategories'); my %prefs = ( 'rolecolors' => { text => 'Default color schemes', help => 'Default_Color_Schemes', header => [{col1 => 'Student Settings', col2 => '',}, {col1 => 'Coordinator Settings', col2 => '',}, {col1 => 'Author Settings', col2 => '',}, {col1 => 'Administrator Settings', col2 => '',}], }, 'login' => { text => 'Log-in page options', help => 'Domain_Log-in_Page', header => [{col1 => 'Item', col2 => '',}], }, 'defaults' => { text => 'Default authentication/language', help => '', header => [{col1 => 'Setting', col2 => 'Value'}], }, 'quotas' => { text => 'Default quotas for user portfolios', help => 'Default_User_Quota', header => [{col1 => 'User type', col2 => 'Default quota'}], }, 'autoenroll' => { text => 'Auto-enrollment settings', help => 'Domain_Auto_Enrollment', header => [{col1 => 'Configuration setting', col2 => 'Value(s)'}], }, 'autoupdate' => { text => 'Auto-update settings', help => 'Domain_Auto_Update', header => [{col1 => 'Setting', col2 => 'Value',}, {col1 => 'User population', col2 => 'Updataeable user data'}], }, 'directorysrch' => { text => 'Institutional directory searches', help => 'Domain_Directory_Search', header => [{col1 => 'Setting', col2 => 'Value',}], }, 'contacts' => { text => 'Contact Information', help => 'Domain_Contact_Information', header => [{col1 => 'Setting', col2 => 'Value',}], }, 'usercreation' => { text => 'User creation', help => 'Domain_User_Creation', header => [{col1 => 'Format rule type', col2 => 'Format rules in force'}, {col1 => 'User account creation', col2 => 'Usernames which may be created',}, {col1 => 'Context', col2 => 'Assignable authentication types'}], }, 'usermodification' => { text => 'User modification', help => 'Domain_User_Modification', header => [{col1 => 'Target user has role', col2 => 'User information updateable in author context'}, {col1 => 'Target user has role', col2 => 'User information updateable in course context'}], }, 'scantron' => { text => 'Scantron format file', help => 'Domain_Scantron_Formats', header => [ {col1 => 'Item', col2 => '', }], }, 'coursecategories' => { text => 'Cataloging of courses', help => 'Domain_Course_Catalog', header => [ {col1 => 'Categories', col2 => '', }], } ); my @roles = ('student','coordinator','author','admin'); my @actions = &Apache::loncommon::get_env_multiple('form.actions'); &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:changePage(document.$phase,'pickactions')", text=>"Pick functionality"}); my $confname = $dom.'-domainconfig'; if ($phase eq 'process') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:changePage(document.$phase,'display')", text=>"Domain Configuration"}, {href=>"javascript:changePage(document.$phase,'$phase')", text=>"Updated"}); &print_header($r,$phase); foreach my $item (@prefs_order) { if (grep(/^\Q$item\E$/,@actions)) { $r->print('

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

'. &process_changes($r,$dom,$confname,$item, \@roles,%domconfig)); } } $r->print('

'); &print_footer($r,$phase,'display','Back to configuration display', \@actions); $r->print('

'); } elsif ($phase eq 'display') { &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:changePage(document.$phase,'display')", text=>"Domain Configuration"}); &print_header($r,$phase); if (@actions > 0) { my $rowsum = 0; my (%output,%rowtotal,@items); my $halfway = @actions/2; foreach my $item (@prefs_order) { if (grep(/^\Q$item\E$/,@actions)) { push(@items,$item); ($output{$item},$rowtotal{$item}) = &print_config_box($r,$dom,$confname,$phase, $item,$prefs{$item}, $domconfig{$item}); $rowsum += $rowtotal{$item}; } } my $colend; my $halfway = $rowsum/2; my $aggregate = 0; my $sumleft = 0; my $sumright = 0; my $crossover; for (my $i=0; $i<@items; $i++) { $aggregate += $rowtotal{$items[$i]}; if ($aggregate > $halfway) { $crossover = $i; last; } } for (my $i=0; $i<$crossover; $i++) { $sumleft += $rowtotal{$items[$i]}; } for (my $i=$crossover+1; $i<@items; $i++) { $sumright += $rowtotal{$items[$i]}; } if ((@items > 1) && ($env{'form.numcols'} == 2)) { my $sumdiff = $sumright - $sumleft; if ($sumdiff > 0) { $colend = $crossover + 1; } else { $colend = $crossover; } } else { $colend = @items; } $r->print('

'); for (my $i=0; $i<$colend; $i++) { $r->print($output{$items[$i]}); } $r->print(''); if ($colend < @items) { for (my $i=$colend; $i<@items; $i++) { $r->print($output{$items[$i]}); } } $r->print('

'); $r->print(&print_footer($r,$phase,'process','Save',\@actions)); } else { $r->print(''. ''."\n". ''.&mt('No settings chosen'). ''); } $r->print(''); $r->print(&Apache::loncommon::end_page()); } else { if ($phase eq '') { $phase = 'pickactions'; } my %helphash; &print_header($r,$phase); if (keys(%domconfig) == 0) { my $primarylibserv = &Apache::lonnet::domain($dom,'primary'); my @ids=&Apache::lonnet::current_machine_ids(); if (!grep(/^\Q$primarylibserv\E$/,@ids)) { my %designhash = &Apache::loncommon::get_domainconf($dom); my @loginimages = ('img','logo','domlogo','login'); my $custom_img_count = 0; foreach my $img (@loginimages) { if ($designhash{$dom.'.login.'.$img} ne '') { $custom_img_count ++; } } foreach my $role (@roles) { if ($designhash{$dom.'.'.$role.'.img'} ne '') { $custom_img_count ++; } } if ($custom_img_count > 0) { my $switch_server = &check_switchserver($dom,$confname); $r->print( &mt('Domain configuration settings have yet to be saved for this domain via the web-based domain preferences interface.').'
'. &mt("While this remains so, you must switch to the domain's primary library server in order to update settings.").'

'. &mt("Thereafter, (with a Domain Coordinator role selected in the domain) you will be able to update settings when logged in to any server in the LON-CAPA network.").'
'. &mt("However, you will still need to switch to the domain's primary library server to upload new images or logos.").'

'); if ($switch_server) { $r->print($switch_server.' '.&mt('to primary library server for domain: [_1]',$dom)); } return OK; } } } $r->print('

'.&mt('Functionality to display/modify').'

'); $r->print(''."\n".'

  '. '

'); my ($numitems,$midpoint,$seconddiv,$count); $numitems = @prefs_order; $midpoint = int($numitems/2); if ($numitems%2) { $midpoint ++; } $count = 0; foreach my $item (@prefs_order) { $r->print('

'); $count ++; if ((!$seconddiv) && ($count >= $midpoint)) { $r->print('
'."\n".'
'."\n"); $seconddiv = 1; } } $r->print('

'. &mt('Display options').'

'."\n". '

'.&mt('Display using: ')."\n". '  

'); $r->print(&print_footer($r,$phase,'display','Go')); $r->print(''); $r->print(&Apache::loncommon::end_page()); } return OK; } sub process_changes { my ($r,$dom,$confname,$action,$roles,%domconfig) = @_; my $output; if ($action eq 'login') { $output = &modify_login($r,$dom,$confname,%domconfig); } elsif ($action eq 'rolecolors') { $output = &modify_rolecolors($r,$dom,$confname,$roles, %domconfig); } elsif ($action eq 'quotas') { $output = &modify_quotas($dom,%domconfig); } elsif ($action eq 'autoenroll') { $output = &modify_autoenroll($dom,%domconfig); } elsif ($action eq 'autoupdate') { $output = &modify_autoupdate($dom,%domconfig); } elsif ($action eq 'directorysrch') { $output = &modify_directorysrch($dom,%domconfig); } elsif ($action eq 'usercreation') { $output = &modify_usercreation($dom,%domconfig); } elsif ($action eq 'usermodification') { $output = &modify_usermodification($dom,%domconfig); } elsif ($action eq 'contacts') { $output = &modify_contacts($dom,%domconfig); } elsif ($action eq 'defaults') { $output = &modify_defaults($dom,$r); } elsif ($action eq 'scantron') { $output = &modify_scantron($r,$dom,$confname,%domconfig); } elsif ($action eq 'coursecategories') { $output = &modify_coursecategories($dom,%domconfig); } return $output; } sub print_config_box { my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_; my $rowtotal = 0; my $output; if ($action eq 'coursecategories') { $output = &coursecategories_javascript($settings); } $output .= ''; # # FIXME - put the help link back in when the help files exist # # '); $rowtotal ++; if (($action eq 'autoupdate') || ($action eq 'rolecolors') || ($action eq 'usercreation') || ($action eq 'usermodification')) { my $colspan = ($action eq 'rolecolors')?' colspan="2"':''; $output .= ' '. ''; $itemcount ++; } $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext,$loginheader); $datatable .= '
'.&mt($item->{text}). ' 
'.&mt($item->{text}).' '. # &Apache::loncommon::help_open_topic($item->{'help'}).'
'; $rowtotal ++; if ($action eq 'autoupdate') { $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'usercreation') { $output .= &print_usercreation('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'usermodification') { $output .= &print_usermodification('top',$dom,$settings,\$rowtotal); } else { $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal); } $output .= '
'.$item->{'header'}->[0]->{'col1'}.' '.$item->{'header'}->[0]->{'col2'}.'
'; $rowtotal ++; if ($action eq 'autoupdate') { $output .= &print_autoupdate('bottom',$dom,$settings,\$rowtotal); } elsif ($action eq 'usercreation') { $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).'
'.$item->{'header'}->[1]->{'col1'}.' '.$item->{'header'}->[1]->{'col2'}.'
'. &print_usercreation('bottom',$dom,$settings,\$rowtotal); $rowtotal ++; } elsif ($action eq 'usermodification') { $output .= &print_usermodification('bottom',$dom,$settings,\$rowtotal); } else { $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
'.$item->{'header'}->[2]->{'col1'}.' '.$item->{'header'}->[2]->{'col2'}.'
'. &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
'.$item->{'header'}->[2]->{'col1'}.' '.$item->{'header'}->[2]->{'col2'}.'
'. &print_rolecolors($phase,'admin',$dom,$confname,$settings,\$rowtotal); $rowtotal += 2; } } else { $output .= '
'.$item->{'header'}->[3]->{'col1'}.' '.$item->{'header'}->[3]->{'col2'}.'
'; if (($action eq 'login') || ($action eq 'directorysrch')) { $output .= ' '; } else { $output .= ' '; } my $colspan = ($action eq 'coursecategories')?' colspan="2"':''; $output .= ' '; $rowtotal ++; if ($action eq 'login') { $output .= &print_login($dom,$confname,$phase,$settings,\$rowtotal); } elsif ($action eq 'quotas') { $output .= &print_quotas($dom,$settings,\$rowtotal); } elsif ($action eq 'autoenroll') { $output .= &print_autoenroll($dom,$settings,\$rowtotal); } elsif ($action eq 'directorysrch') { $output .= &print_directorysrch($dom,$settings,\$rowtotal); } elsif ($action eq 'contacts') { $output .= &print_contacts($dom,$settings,\$rowtotal); } elsif ($action eq 'defaults') { $output .= &print_defaults($dom,\$rowtotal); } elsif ($action eq 'scantron') { $output .= &print_scantronformat($r,$dom,$confname,$settings,\$rowtotal); } elsif ($action eq 'coursecategories'){ $output .= &print_coursecategories($dom,$item,$settings,\$rowtotal); } } $output .= '
'.$item->{'header'}->[0]->{'col1'}.''.$item->{'header'}->[0]->{'col1'}.''.$item->{'header'}->[0]->{'col2'}.'

'; return ($output,$rowtotal); } sub print_header { my ($r,$phase) = @_; my $alert = &mt('You must select at least one functionality type to display.'); my $js = ' '; my $additem; if ($phase eq 'pickactions') { my %loaditems = ( 'onload' => "javascript:getViewportDims(document.$phase.width,document.$phase.height);setDisplayColumns();setFormElements(document.pickactions);", ); $additem = {'add_entries' => \%loaditems,}; } else { my %loaditems = ( 'onload' => "javascript:getViewportDims(document.$phase.width,document.$phase.height);", ); $additem = {'add_entries' => \%loaditems,}; } $r->print(&Apache::loncommon::start_page('View/Modify Domain Settings', $js,$additem)); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Domain Settings')); $r->print('
'); $r->print('
'); return; } sub print_footer { my ($r,$phase,$newphase,$button_text,$actions) = @_; $button_text = &mt($button_text); $r->print(''. ''. ''); if (($phase eq 'display') || ($phase eq 'process')) { if (ref($actions) eq 'ARRAY') { foreach my $item (@{$actions}) { $r->print('')."\n"; } } $r->print(''); } my $dest='"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; if ($phase eq 'process') { $r->print('

'.$button_text.'

'); } else { my $onclick; if ($phase eq 'display') { $onclick = '"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; } else { $onclick = '"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; } $r->print('

'); } if ($phase eq 'process') { $r->print('
'.&Apache::loncommon::end_page()); } return; } sub print_login { my ($dom,$confname,$phase,$settings,$rowtotal) = @_; my %choices = &login_choices(); my %defaultchecked = ( 'coursecatalog' => 'on', 'adminmail' => 'off', 'newuser' => 'off', ); my @toggles = ('coursecatalog','adminmail','newuser'); my (%checkedon,%checkedoff); foreach my $item (@toggles) { if ($defaultchecked{$item} eq 'on') { $checkedon{$item} = ' checked="checked" '; $checkedoff{$item} = ' '; } elsif ($defaultchecked{$item} eq 'off') { $checkedoff{$item} = ' checked="checked" '; $checkedon{$item} = ' '; } } my $loginheader = 'image'; my @images = ('img','logo','domlogo','login'); my @logintext = ('textcol','bgcol'); my @bgs = ('pgbg','mainbg','sidebg'); my @links = ('link','alink','vlink'); my %designhash = &Apache::loncommon::get_domainconf($dom); my %defaultdesign = %Apache::loncommon::defaultdesign; my (%is_custom,%designs); my %defaults = ( font => $defaultdesign{'login.font'}, ); foreach my $item (@images) { $defaults{$item} = $defaultdesign{'login.'.$item}; } foreach my $item (@bgs) { $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item}; } foreach my $item (@logintext) { $defaults{'logintext'}{$item} = $defaultdesign{'login.'.$item}; } foreach my $item (@links) { $defaults{'links'}{$item} = $defaultdesign{'login.'.$item}; } if (ref($settings) eq 'HASH') { foreach my $item (@toggles) { if ($settings->{$item} eq '1') { $checkedon{$item} = ' checked="checked" '; $checkedoff{$item} = ' '; } elsif ($settings->{$item} eq '0') { $checkedoff{$item} = ' checked="checked" '; $checkedon{$item} = ' '; } } foreach my $item (@images) { if ($settings->{$item} ne '') { $designs{$item} = $settings->{$item}; $is_custom{$item} = 1; } } foreach my $item (@logintext) { if ($settings->{$item} ne '') { $designs{'logintext'}{$item} = $settings->{$item}; $is_custom{$item} = 1; } } if ($settings->{'loginheader'} ne '') { $loginheader = $settings->{'loginheader'}; } if ($settings->{'font'} ne '') { $designs{'font'} = $settings->{'font'}; $is_custom{'font'} = 1; } foreach my $item (@bgs) { if ($settings->{$item} ne '') { $designs{'bgs'}{$item} = $settings->{$item}; $is_custom{$item} = 1; } } foreach my $item (@links) { if ($settings->{$item} ne '') { $designs{'links'}{$item} = $settings->{$item}; $is_custom{$item} = 1; } } } else { if ($designhash{$dom.'.login.font'} ne '') { $designs{'font'} = $designhash{$dom.'.login.font'}; $is_custom{'font'} = 1; } foreach my $item (@images) { if ($designhash{$dom.'.login.'.$item} ne '') { $designs{$item} = $designhash{$dom.'.login.'.$item}; $is_custom{$item} = 1; } } foreach my $item (@bgs) { if ($designhash{$dom.'.login.'.$item} ne '') { $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item}; $is_custom{$item} = 1; } } foreach my $item (@links) { if ($designhash{$dom.'.login.'.$item} ne '') { $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item}; $is_custom{$item} = 1; } } } my %alt_text = &Apache::lonlocal::texthash ( img => 'Log-in banner', logo => 'Institution Logo', domlogo => 'Domain Logo', login => 'Login box'); my $itemcount = 1; my ($css_class,$datatable); foreach my $item (@toggles) { $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= '
'.$choices{$item}. ''. ' 
'; return $datatable; } sub login_choices { my %choices = &Apache::lonlocal::texthash ( coursecatalog => 'Display Course Catalog link?', adminmail => "Display Administrator's E-mail Address?", newuser => "Link to create a user account", img => "Header", logo => "Main Logo", domlogo => "Domain Logo", login => "Log-in Header", textcol => "Text color", bgcol => "Box color", bgs => "Background colors", links => "Link colors", font => "Font color", pgbg => "Page", mainbg => "Main panel", sidebg => "Side panel", link => "Link", alink => "Active link", vlink => "Visited link", ); return %choices; } sub print_rolecolors { my ($phase,$role,$dom,$confname,$settings,$rowtotal) = @_; my %choices = &color_font_choices(); my @bgs = ('pgbg','tabbg','sidebg'); my @links = ('link','alink','vlink'); my @images = ('img'); my %alt_text = &Apache::lonlocal::texthash(img => "Banner for $role role"); my %designhash = &Apache::loncommon::get_domainconf($dom); my %defaultdesign = %Apache::loncommon::defaultdesign; my (%is_custom,%designs); my %defaults = ( img => $defaultdesign{$role.'.img'}, font => $defaultdesign{$role.'.font'}, ); foreach my $item (@bgs) { $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; } foreach my $item (@links) { $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item}; } if (ref($settings) eq 'HASH') { if (ref($settings->{$role}) eq 'HASH') { if ($settings->{$role}->{'img'} ne '') { $designs{'img'} = $settings->{$role}->{'img'}; $is_custom{'img'} = 1; } if ($settings->{$role}->{'font'} ne '') { $designs{'font'} = $settings->{$role}->{'font'}; $is_custom{'font'} = 1; } foreach my $item (@bgs) { if ($settings->{$role}->{$item} ne '') { $designs{'bgs'}{$item} = $settings->{$role}->{$item}; $is_custom{$item} = 1; } } foreach my $item (@links) { if ($settings->{$role}->{$item} ne '') { $designs{'links'}{$item} = $settings->{$role}->{$item}; $is_custom{$item} = 1; } } } } else { if ($designhash{$dom.'.'.$role.'.img'} ne '') { $designs{img} = $designhash{$dom.'.'.$role.'.img'}; $is_custom{'img'} = 1; } if ($designhash{$dom.'.'.$role.'.font'} ne '') { $designs{font} = $designhash{$dom.'.'.$role.'.font'}; $is_custom{'font'} = 1; } foreach my $item (@bgs) { if ($designhash{$dom.'.'.$role.'.'.$item} ne '') { $designs{'bgs'}{$item} = $designhash{$dom.'.'.$role.'.'.$item}; $is_custom{$item} = 1; } } foreach my $item (@links) { if ($designhash{$dom.'.'.$role.'.'.$item} ne '') { $designs{'links'}{$item} = $designhash{$dom.'.'.$role.'.'.$item}; $is_custom{$item} = 1; } } } my $itemcount = 1; my $datatable = &display_color_options($dom,$confname,$phase,$role,$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal); $datatable .= ''; return $datatable; } sub display_color_options { my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs, $images,$bgs,$links,$alt_text,$rowtotal,$logintext,$loginheader) = @_; my $css_class = $itemcount%2?' class="LC_odd_row"':''; my $datatable = ''. ''.$choices->{'font'}.''; if (!$is_custom->{'font'}) { $datatable .= ''.&mt('Default in use:').' '.$defaults->{'font'}.''; } else { $datatable .= ' '; } my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'}); $datatable .= ''. ' '.$fontlink. '    '. ''; my $switchserver = &check_switchserver($dom,$confname); foreach my $img (@{$images}) { $itemcount ++; $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$choices->{$img}.''; my ($imgfile,$img_import,$login_hdr_pick,$logincolors); if ($designs->{$img} ne '') { $imgfile = $designs->{$img}; $img_import = ($imgfile =~ m{^/adm/}); } else { $imgfile = $defaults->{$img}; } if ($img eq 'login') { $login_hdr_pick = &login_header_options($img,$role,$defaults,$is_custom,$choices, $loginheader); $logincolors = &login_text_colors($img,$role,$logintext,$phase,$choices,$designs); } if ($imgfile) { my ($showfile,$fullsize); if ($imgfile =~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) { my $urldir = $1; my $filename = $2; my @info = &Apache::lonnet::stat_file($designs->{$img}); if (@info) { my $thumbfile = 'tn-'.$filename; my @thumb=&Apache::lonnet::stat_file($urldir.'/'.$thumbfile); if (@thumb) { $showfile = $urldir.'/'.$thumbfile; } else { $showfile = $imgfile; } } else { $showfile = ''; } } elsif ($imgfile =~ m-^/(adm/[^/]+)/([^/]+)$-) { $showfile = $imgfile; my $imgdir = $1; my $filename = $2; if (-e "/home/httpd/html/$imgdir/tn-".$filename) { $showfile = "/$imgdir/tn-".$filename; } else { my $input = "/home/httpd/html".$imgfile; my $output = '/home/httpd/html/'.$imgdir.'/tn-'.$filename; if (!-e $output) { my ($width,$height) = &thumb_dimensions(); my ($fullwidth,$fullheight) = &check_dimensions($input); if ($fullwidth ne '' && $fullheight ne '') { if ($fullwidth > $width && $fullheight > $height) { my $size = $width.'x'.$height; system("convert -sample $size $input $output"); $showfile = '/'.$imgdir.'/tn-'.$filename; } } } } } if ($showfile) { if ($showfile =~ m{^/(adm|res)/}) { if ($showfile =~ m{^/res/}) { my $local_showfile = &Apache::lonnet::filelocation('',$showfile); &Apache::lonnet::repcopy($local_showfile); } $showfile = &Apache::loncommon::lonhttpdurl($showfile); } if ($imgfile) { if ($imgfile =~ m{^/(adm|res)/}) { if ($imgfile =~ m{^/res/}) { my $local_imgfile = &Apache::lonnet::filelocation('',$imgfile); &Apache::lonnet::repcopy($local_imgfile); } $fullsize = &Apache::loncommon::lonhttpdurl($imgfile); } else { $fullsize = $imgfile; } } $datatable .= ''; if ($img eq 'login') { $datatable .= $login_hdr_pick; } $datatable .= &image_changes($is_custom->{$img},$alt_text->{$img},$img_import, $showfile,$fullsize,$role,$img,$imgfile,$logincolors); } else { $datatable .= '
'. &mt('Upload:'); } } else { $datatable .= '
'. &mt('Upload:'); } if ($switchserver) { $datatable .= &mt('Upload to library server: [_1]',$switchserver); } else { $datatable .=' '; } $datatable .= ''; } $itemcount ++; $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$choices->{'bgs'}.''; my $bgs_def; foreach my $item (@{$bgs}) { if (!$is_custom->{$item}) { $bgs_def .= ''.$choices->{$item}.'    
'.$defaults->{'bgs'}{$item}.''; } } if ($bgs_def) { $datatable .= ''.&mt('Default(s) in use:').'
'.$bgs_def.'
'; } else { $datatable .= ' '; } $datatable .= ''. ''; foreach my $item (@{$bgs}) { my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item}); $datatable .= ''; } $datatable .= '
'.$link; if ($designs->{'bgs'}{$item}) { $datatable .= '    '; } $datatable .= '
'; $itemcount ++; $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$choices->{'links'}.''; my $links_def; foreach my $item (@{$links}) { if (!$is_custom->{$item}) { $links_def .= ''.$choices->{$item}.'
'.$defaults->{'links'}{$item}.''; } } if ($links_def) { $datatable .= ''.&mt('Default(s) in use:').'
'.$links_def.'
'; } else { $datatable .= ' '; } $datatable .= ''. ''; foreach my $item (@{$links}) { $datatable .= ''; } $$rowtotal += $itemcount; return $datatable; } sub login_header_options { my ($img,$role,$defaults,$is_custom,$choices,$loginheader) = @_; my $image_checked = ' checked="checked" '; my $text_checked = ' '; if ($loginheader eq 'text') { $image_checked = ' '; $text_checked = ' checked="checked" '; } my $output = '   '. '
'."\n"; if ((!$is_custom->{'textcol'}) || (!$is_custom->{'bgcol'})) { $output .= &mt('Text default(s)').':
'; if (!$is_custom->{'textcol'}) { $output .= $choices->{'textcol'}.': '.$defaults->{'logintext'}{'textcol'}. '   '; } if (!$is_custom->{'bgcol'}) { $output .= $choices->{'bgcol'}.': '. '   '; } $output .= '
'; } $output .='
'; return $output; } sub login_text_colors { my ($img,$role,$logintext,$phase,$choices,$designs) = @_; my $color_menu = '
'."\n". &color_pick($phase,$role,$item,$choices->{$item}, $designs->{'links'}{$item}); if ($designs->{'links'}{$item}) { $datatable.='    '; } $datatable .= '
'; foreach my $item (@{$logintext}) { my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item}); $color_menu .= ''. ''; } $color_menu .= '
'.$link; if ($designs->{'logintext'}{$item}) { $color_menu .= '    '; } $color_menu .= '
 

'; return $color_menu; } sub image_changes { my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_; my $output; if (!$is_custom) { if ($img eq 'login') { $output .= &mt('Default image:').'
'; } else { $output .= &mt('Default in use:').'
'; } } if ($img_import) { $output .= ''; } $output .= ''.$alt_text.''; if ($is_custom) { $output .= ''.$logincolors.' '.&mt('Replace:').'
'; } else { $output .= ''.$logincolors.&mt('Upload:').'
'; } return $output; } sub color_pick { my ($phase,$role,$item,$desc,$curcol) = @_; my $link = ''.$desc.''; return $link; } sub color_pick_js { my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition(); my $output = <<"ENDCOL"; function pclose() { parmwin=window.open("/adm/rat/empty.html","LONCAPAparms","height=350,width=350,scrollbars=no,menubar=no"); parmwin.close(); } $pjump_def function psub() { pclose(); if (document.parmform.pres_marker.value!='') { if (document.parmform.pres_type.value!='') { eval('document.display.'+ document.parmform.pres_marker.value+ '.value=document.parmform.pres_value.value;'); } } else { document.parmform.pres_value.value=''; document.parmform.pres_marker.value=''; } } function get_id (span_id) { if (document.getElementById) { return document.getElementById(span_id); } if (document.all) { return document.all[span_id]; } return false; } function colchg_span (span_id_str,new_color_item) { var span_ref = get_id(span_id_str); if (span_ref.style) { span_ref = span_ref.style; } span_ref.background = new_color_item.value; span_ref.backgroundColor = new_color_item.value; span_ref.bgColor = new_color_item.value; } ENDCOL return $output; } sub print_quotas { my ($dom,$settings,$rowtotal) = @_; my $datatable; my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; my $css_class; if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { if (defined($usertypes->{$type})) { $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$usertypes->{$type}.''. ''. ' Mb'; } } } my $defaultquota = '20'; if (ref($settings) eq 'HASH') { if (defined($settings->{'default'})) { $defaultquota = $settings->{'default'}; } } $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. ''.$othertitle.''. ''. ' Mb'; $$rowtotal += $typecount; return $datatable; } sub print_autoenroll { my ($dom,$settings,$rowtotal) = @_; my $autorun = &Apache::lonnet::auto_run(undef,$dom), my ($defdom,$runon,$runoff); if (ref($settings) eq 'HASH') { if (exists($settings->{'run'})) { if ($settings->{'run'} eq '0') { $runoff = ' checked="checked" '; $runon = ' '; } else { $runon = ' checked="checked" '; $runoff = ' '; } } else { if ($autorun) { $runon = ' checked="checked" '; $runoff = ' '; } else { $runoff = ' checked="checked" '; $runon = ' '; } } if (exists($settings->{'sender_domain'})) { $defdom = $settings->{'sender_domain'}; } } else { if ($autorun) { $runon = ' checked="checked" '; $runoff = ' '; } else { $runoff = ' checked="checked" '; $runon = ' '; } } my $domform = &Apache::loncommon::select_dom_form($defdom,'sender_domain',1); my $notif_sender; if (ref($settings) eq 'HASH') { $notif_sender = $settings->{'sender_uname'}; } my $datatable=''. ''.&mt('Auto-enrollment active?').''. ' '. ''. ''. ''.&mt('Notification messages - sender'). ''. &mt('username').': '. '  '.&mt('domain'). ': '.$domform.''; $$rowtotal += 2; return $datatable; } sub print_autoupdate { my ($position,$dom,$settings,$rowtotal) = @_; my $datatable; if ($position eq 'top') { my $updateon = ' '; my $updateoff = ' checked="checked" '; my $classlistson = ' '; my $classlistsoff = ' checked="checked" '; if (ref($settings) eq 'HASH') { if ($settings->{'run'} eq '1') { $updateon = $updateoff; $updateoff = ' '; } if ($settings->{'classlists'} eq '1') { $classlistson = $classlistsoff; $classlistsoff = ' '; } } my %title = ( run => 'Auto-update active?', classlists => 'Update information in classlists?', ); $datatable = ''. ''.&mt($title{'run'}).''. ' '. ''. ''. ''.&mt($title{'classlists'}).''. ''. ' '. ''. ''; $$rowtotal += 2; } else { my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my @fields = ('lastname','firstname','middlename','gen', 'permanentemail','id'); my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); my $numrows = 0; if (ref($types) eq 'ARRAY') { if (@{$types} > 0) { $datatable = &usertype_update_row($settings,$usertypes,\%fieldtitles, \@fields,$types,\$numrows); $$rowtotal += @{$types}; } } $datatable .= &usertype_update_row($settings,{'default' => $othertitle}, \%fieldtitles,\@fields,['default'], \$numrows); $$rowtotal ++; } return $datatable; } sub print_directorysrch { my ($dom,$settings,$rowtotal) = @_; my $srchon = ' '; my $srchoff = ' checked="checked" '; my ($exacton,$containson,$beginson); my $localon = ' '; my $localoff = ' checked="checked" '; if (ref($settings) eq 'HASH') { if ($settings->{'available'} eq '1') { $srchon = $srchoff; $srchoff = ' '; } if ($settings->{'localonly'} eq '1') { $localon = $localoff; $localoff = ' '; } if (ref($settings->{'searchtypes'}) eq 'ARRAY') { foreach my $type (@{$settings->{'searchtypes'}}) { if ($type eq 'exact') { $exacton = ' checked="checked" '; } elsif ($type eq 'contains') { $containson = ' checked="checked" '; } elsif ($type eq 'begins') { $beginson = ' checked="checked" '; } } } else { if ($settings->{'searchtypes'} eq 'exact') { $exacton = ' checked="checked" '; } elsif ($settings->{'searchtypes'} eq 'contains') { $containson = ' checked="checked" '; } elsif ($settings->{'searchtypes'} eq 'specify') { $exacton = ' checked="checked" '; $containson = ' checked="checked" '; } } } my ($searchtitles,$titleorder) = &sorted_searchtitles(); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $numinrow = 4; my $cansrchrow = 0; my $datatable=''. ''.&mt('Directory search available?').''. ' '. ''. ''. ''.&mt('Other domains can search?').''. ' '. ''. ''; $$rowtotal += 2; if (ref($usertypes) eq 'HASH') { if (keys(%{$usertypes}) > 0) { $datatable .= &users_cansearch_row($settings,$types,$usertypes,$dom, $numinrow,$othertitle); $cansrchrow = 1; } } if ($cansrchrow) { $$rowtotal ++; $datatable .= ''; } else { $datatable .= ''; } $datatable .= ''.&mt('Supported search methods'). ''; foreach my $title (@{$titleorder}) { if (defined($searchtitles->{$title})) { my $check = ' '; if (ref($settings) eq 'HASH') { if (ref($settings->{'searchby'}) eq 'ARRAY') { if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) { $check = ' checked="checked" '; } } } $datatable .= ''; } } $datatable .= '
'. '
'; $$rowtotal ++; if ($cansrchrow) { $datatable .= ''; } else { $datatable .= ''; } $datatable .= ''.&mt('Search latitude').''. ''. ' '. ' '. ''; $$rowtotal ++; return $datatable; } sub print_contacts { my ($dom,$settings,$rowtotal) = @_; my $datatable; my @contacts = ('adminemail','supportemail'); my (%checked,%to,%otheremails); my @mailings = ('errormail','packagesmail','helpdeskmail'); foreach my $type (@mailings) { $otheremails{$type} = ''; } if (ref($settings) eq 'HASH') { foreach my $item (@contacts) { if (exists($settings->{$item})) { $to{$item} = $settings->{$item}; } } foreach my $type (@mailings) { if (exists($settings->{$type})) { if (ref($settings->{$type}) eq 'HASH') { foreach my $item (@contacts) { if ($settings->{$type}{$item}) { $checked{$type}{$item} = ' checked="checked" '; } } $otheremails{$type} = $settings->{$type}{'others'}; } } } } else { $to{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'}; $to{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'}; $checked{'errormail'}{'adminemail'} = ' checked="checked" '; $checked{'packagesmail'}{'adminemail'} = ' checked="checked" '; $checked{'helpdeskmail'}{'supportemail'} = ' checked="checked" '; } my ($titles,$short_titles) = &contact_titles(); my $rownum = 0; my $css_class; foreach my $item (@contacts) { if ($rownum%2) { $css_class = ''; } else { $css_class = ' class="LC_odd_row" '; } $datatable .= ''. ''.$titles->{$item}. ''. ''; $rownum ++; } foreach my $type (@mailings) { if ($rownum%2) { $css_class = ''; } else { $css_class = ' class="LC_odd_row" '; } $datatable .= ''. ''. $titles->{$type}.': '. ''. ''; foreach my $item (@contacts) { $datatable .= ' '; } $datatable .= '
'.&mt('Others').':  '. ''. ''."\n"; $rownum ++; } $$rowtotal += $rownum; return $datatable; } sub contact_titles { my %titles = &Apache::lonlocal::texthash ( 'supportemail' => 'Support E-mail address', '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 to be e-mailed to' ); my %short_titles = &Apache::lonlocal::texthash ( adminemail => 'Admin E-mail address', supportemail => 'Support E-mail', ); return (\%titles,\%short_titles); } sub print_usercreation { my ($position,$dom,$settings,$rowtotal) = @_; my $numinrow = 4; my $datatable; if ($position eq 'top') { $$rowtotal ++; my $rowcount = 0; my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username'); if (ref($rules) eq 'HASH') { if (keys(%{$rules}) > 0) { $datatable .= &user_formats_row('username',$settings,$rules, $ruleorder,$numinrow,$rowcount); $$rowtotal ++; $rowcount ++; } } my ($idrules,$idruleorder) = &Apache::lonnet::inst_userrules($dom,'id'); if (ref($idrules) eq 'HASH') { if (keys(%{$idrules}) > 0) { $datatable .= &user_formats_row('id',$settings,$idrules, $idruleorder,$numinrow,$rowcount); $$rowtotal ++; $rowcount ++; } } my ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email'); if (ref($emailrules) eq 'HASH') { if (keys(%{$emailrules}) > 0) { $datatable .= &user_formats_row('email',$settings,$emailrules, $emailruleorder,$numinrow,$rowcount); $$rowtotal ++; $rowcount ++; } } if ($rowcount == 0) { $datatable .= ''.&mt('No format rules have been defined for usernames or IDs in this domain.').''; $$rowtotal ++; $rowcount ++; } } elsif ($position eq 'middle') { my @creators = ('author','course','selfcreate'); my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username'); my %lt = &usercreation_types(); my %checked; if (ref($settings) eq 'HASH') { if (ref($settings->{'cancreate'}) eq 'HASH') { foreach my $item (@creators) { $checked{$item} = $settings->{'cancreate'}{$item}; } } elsif (ref($settings->{'cancreate'}) eq 'ARRAY') { foreach my $item (@creators) { if (grep(/^\Q$item\E$/,@{$settings->{'cancreate'}})) { $checked{$item} = 'none'; } } } } my $rownum = 0; foreach my $item (@creators) { $rownum ++; if ($checked{$item} eq '') { if ($item eq 'selfcreate') { $checked{$item} = 'none'; } else { $checked{$item} = 'any'; } } my $css_class; if ($rownum%2) { $css_class = ''; } else { $css_class = ' class="LC_odd_row" '; } $datatable .= ''. ''.$lt{$item}. ''; my @options = ('any'); if ($item eq 'selfcreate') { push(@options,('email','login','sso')); } else { if (ref($rules) eq 'HASH') { if (keys(%{$rules}) > 0) { push(@options,('official','unofficial')); } } } push(@options,'none'); foreach my $option (@options) { my $check = ' '; if ($checked{$item} eq $option) { $check = ' checked="checked" '; } $datatable .= '  '; } $datatable .= ''; } } else { my @contexts = ('author','course','domain'); my @authtypes = ('int','krb4','krb5','loc'); my %checked; if (ref($settings) eq 'HASH') { if (ref($settings->{'authtypes'}) eq 'HASH') { foreach my $item (@contexts) { if (ref($settings->{'authtypes'}{$item}) eq 'HASH') { foreach my $auth (@authtypes) { if ($settings->{'authtypes'}{$item}{$auth}) { $checked{$item}{$auth} = ' checked="checked" '; } } } } } } else { foreach my $item (@contexts) { foreach my $auth (@authtypes) { $checked{$item}{$auth} = ' checked="checked" '; } } } my %title = &context_names(); my %authname = &authtype_names(); my $rownum = 0; my $css_class; foreach my $item (@contexts) { if ($rownum%2) { $css_class = ''; } else { $css_class = ' class="LC_odd_row" '; } $datatable .= ''. ''.$title{$item}. ''. ''; foreach my $auth (@authtypes) { $datatable .= ' '; } $datatable .= ''; $rownum ++; } $$rowtotal += $rownum; } return $datatable; } sub user_formats_row { my ($type,$settings,$rules,$ruleorder,$numinrow,$rowcount) = @_; my $output; my %text = ( 'username' => 'new usernames', 'id' => 'IDs', 'email' => 'self-created accounts (e-mail)', ); my $css_class = $rowcount%2?' class="LC_odd_row"':''; $output = ''. ''. &mt("Format rules to check for $text{$type}: "). ''. ''; my $rem; if (ref($ruleorder) eq 'ARRAY') { for (my $i=0; $i<@{$ruleorder}; $i++) { if (ref($rules->{$ruleorder->[$i]}) eq 'HASH') { my $rem = $i%($numinrow); if ($rem == 0) { if ($i > 0) { $output .= ''; } $output .= ''; } my $check = ' '; if (ref($settings) eq 'HASH') { if (ref($settings->{$type.'_rule'}) eq 'ARRAY') { if (grep(/^\Q$ruleorder->[$i]\E$/,@{$settings->{$type.'_rule'}})) { $check = ' checked="checked" '; } } } $output .= ''; } } $rem = @{$ruleorder}%($numinrow); } my $colsleft = $numinrow - $rem; if ($colsleft > 1 ) { $output .= ''; } elsif ($colsleft == 1) { $output .= ''; } $output .= '
'. ''. '  
'; return $output; } sub usercreation_types { my %lt = &Apache::lonlocal::texthash ( author => 'When adding a co-author', course => 'When adding a user to a course', selfcreate => 'User creates own account', any => 'Any', official => 'Institutional only ', unofficial => 'Non-institutional only', email => 'Email address', login => 'Institutional Login', sso => 'SSO', none => 'None', ); return %lt; } sub authtype_names { my %lt = &Apache::lonlocal::texthash( int => 'Internal', krb4 => 'Kerberos 4', krb5 => 'Kerberos 5', loc => 'Local', ); return %lt; } sub context_names { my %context_title = &Apache::lonlocal::texthash( author => 'Creating users when an Author', course => 'Creating users when in a course', domain => 'Creating users when a Domain Coordinator', ); return %context_title; } sub print_usermodification { my ($position,$dom,$settings,$rowtotal) = @_; my $numinrow = 4; my ($context,$datatable,$rowcount); if ($position eq 'top') { $rowcount = 0; $context = 'author'; foreach my $role ('ca','aa') { $datatable .= &modifiable_userdata_row($context,$role,$settings, $numinrow,$rowcount); $$rowtotal ++; $rowcount ++; } } else { $context = 'course'; $rowcount = 0; foreach my $role ('st','ep','ta','in','cr') { $datatable .= &modifiable_userdata_row($context,$role,$settings, $numinrow,$rowcount); $$rowtotal ++; $rowcount ++; } } return $datatable; } sub print_defaults { my ($dom,$rowtotal) = @_; my @items = ('auth_def','auth_arg_def','lang_def'); my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); my $titles = &defaults_titles(); my $rownum = 0; my ($datatable,$css_class); foreach my $item (@items) { if ($rownum%2) { $css_class = ''; } else { $css_class = ' class="LC_odd_row" '; } $datatable .= ''. ''.$titles->{$item}. ''; if ($item eq 'auth_def') { my @authtypes = ('internal','krb4','krb5','localauth'); my %shortauth = ( internal => 'int', krb4 => 'krb4', krb5 => 'krb5', localauth => 'loc' ); my %authnames = &authtype_names(); foreach my $auth (@authtypes) { my $checked = ' '; if ($domdefaults{$item} eq $auth) { $checked = ' checked="checked" '; } $datatable .= '  '; } } else { $datatable .= ''; } $datatable .= ''; $rownum ++; } $$rowtotal += $rownum; return $datatable; } sub defaults_titles { my %titles = &Apache::lonlocal::texthash ( 'auth_def' => 'Default authentication type', 'auth_arg_def' => 'Default authentication argument', 'lang_def' => 'Default language', ); return (\%titles); } sub print_scantronformat { my ($r,$dom,$confname,$settings,$rowtotal) = @_; my $itemcount = 1; my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls); my $switchserver = &check_switchserver($dom,$confname); my %lt = &Apache::lonlocal::texthash ( default => 'Default scantron format file error', custom => 'Custom scantron format file error', ); my %scantronfiles = ( default => 'default.tab', custom => 'custom.tab', ); foreach my $key (keys(%scantronfiles)) { $scantronurls{$key} = '/res/'.$dom.'/'.$confname.'/scantron/' .$scantronfiles{$key}; } my @defaultinfo = &Apache::lonnet::stat_file($scantronurls{'default'}); if ((!@defaultinfo) || ($defaultinfo[0] eq 'no_such_dir')) { if (!$switchserver) { my $servadm = $r->dir_config('lonAdmEMail'); my ($configuserok,$author_ok) = &config_check($dom,$confname,$servadm); if ($configuserok eq 'ok') { if ($author_ok eq 'ok') { my %legacyfile = ( default => $Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab', custom => $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab', ); my %md5chk; foreach my $type (keys(%legacyfile)) { $md5chk{$type} = split(/ /,`md5sum $legacyfile{$type}`); chop($md5chk{$type}); } if ($md5chk{'default'} ne $md5chk{'custom'}) { foreach my $type (keys(%legacyfile)) { ($scantronurls{$type},$error{$type}) = &legacy_scantronformat($r,$dom,$confname, $type,$legacyfile{$type}, $scantronurls{$type}, $scantronfiles{$type}); } } else { ($scantronurls{'default'},$error{'default'}) = &legacy_scantronformat($r,$dom,$confname, 'default',$legacyfile{'default'}, $scantronurls{'default'}, $scantronfiles{'default'}); } } } } else { $error{'default'} = &mt("Unable to copy default scantron formatfile to domain's RES space: [_1]",$switchserver); } } if (ref($settings) eq 'HASH') { if ($settings->{'scantronformat'} eq "/res/$dom/$confname/scantron/custom.tab") { my @info = &Apache::lonnet::stat_file($settings->{'scantronformat'}); if ((!@info) || ($info[0] eq 'no_such_dir')) { $scantronurl = ''; } else { $scantronurl = $settings->{'scantronformat'}; } $is_custom = 1; } else { $scantronurl = $scantronurls{'default'}; } } else { $scantronurl = $scantronurls{'default'}; } $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= ''; if (!$is_custom) { $datatable .= ''.&mt('Default in use:').'
'; if ($scantronurl) { $datatable .= ''. &mt('Default scantron format file').''; } else { $datatable = &mt('File unavailable for display'); } $datatable .= ''.&mt('Upload:').'
'; } else { if (keys(%error) > 0) { my $errorstr; foreach my $key (sort(keys(%error))) { $errorstr .= $lt{$key}.': '.$error{$key}.'
'; } $datatable .= ''.$errorstr.''; } elsif ($scantronurl) { $datatable .= '' .&mt('Custom scantron format file').'' .'' .''.&mt('Replace:').'
'; } } if (keys(%error) == 0) { if ($switchserver) { $datatable .= &mt('Upload to library server: [_1]',$switchserver); } else { $datatable .=' '; } } $datatable .= ''; $$rowtotal ++; return $datatable; } sub legacy_scantronformat { my ($r,$dom,$confname,$file,$legacyfile,$newurl,$newfile) = @_; my ($url,$error); my @statinfo = &Apache::lonnet::stat_file($newurl); if ((!@statinfo) || ($statinfo[0] eq 'no_such_dir')) { (my $result,$url) = &publishlogo($r,'copy',$legacyfile,$dom,$confname,'scantron', '','',$newfile); if ($result ne 'ok') { $error = &mt("An error occurred publishing the [_1] scantron format file in RES space. Error was: [_2].",$newfile,$result); } } return ($url,$error); } sub print_coursecategories { my ($dom,$hdritem,$settings,$rowtotal) = @_; my ($datatable,$css_class); my $itemcount = 1; if (ref($settings) eq 'HASH') { my (@cats,@trails,%allitems,%idx,@jsarray); &extract_categories($settings,\@cats,\@trails,\%allitems,\%idx,\@jsarray); my $maxdepth = scalar(@cats); my $colattrib = ''; if ($maxdepth > 2) { $colattrib = ' colspan="2" '; } my @path; if (@cats > 0) { if (ref($cats[0]) eq 'ARRAY') { my $numtop = @{$cats[0]}; my $maxnum = $numtop; if ((!grep(/^instcode$/,@{$cats[0]})) || ($settings->{'instcode::0'} eq '')) { $maxnum ++; } my $lastidx; for (my $i=0; $i<$numtop; $i++) { my $parent = $cats[0][$i]; $css_class = $itemcount%2?' class="LC_odd_row"':''; my $item = &escape($parent).'::0'; my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$item','$idx{$item}'".');"'; $lastidx = $idx{$item}; $datatable .= '' .''; if ($parent eq 'instcode') { $datatable .= ''.&mt('Official courses') .'
(' .&mt('with institutional codes').')' .' ' .''; } else { $datatable .= $parent .' 
'; } my $depth = 1; push(@path,$parent); $datatable .= &build_category_rows($itemcount,\@cats,$depth,$parent,\@path,\%idx); pop(@path); $datatable .= ''; $itemcount ++; } $css_class = $itemcount%2?' class="LC_odd_row"':''; my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','$lastidx'".');"'; $datatable .= ''.&mt('New:').' ' .'' .''."\n"; $itemcount ++; if ((!grep(/^instcode$/,@{$cats[0]})) || ($settings->{'instcode::0'} eq '')) { $css_class = $itemcount%2?' class="LC_odd_row"':''; my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','$lastidx'".');"'; $datatable .= ''. '' .&mt('Official courses').''.'
(' .&mt('with institutional codes').')' .' ' .''; } } } else { $datatable .= &initialize_categories($itemcount); } } else { $datatable .= ''.$hdritem->{'header'}->[0]->{'col2'}.'' .&initialize_categories($itemcount); } $$rowtotal += $itemcount; return $datatable; } sub coursecategories_javascript { my ($settings) = @_; my ($output,$jstext); if (ref($settings) eq 'HASH') { my (@cats,@jsarray,%idx); &gather_categories($settings,\@cats,\%idx,\@jsarray); if (@jsarray > 0) { $jstext = ' var categories = Array('.scalar(@jsarray).');'."\n"; for (my $i=0; $i<@jsarray; $i++) { if (ref($jsarray[$i]) eq 'ARRAY') { my $catstr = join('","',@{$jsarray[$i]}); $jstext .= ' categories['.$i.'] = Array("'.$catstr.'");'."\n"; } } } } else { $jstext = ' var categories = Array(1);'."\n". ' categories[0] = Array("instcode_pos");'."\n"; } $output = <<"ENDSCRIPT"; ENDSCRIPT return $output; } sub initialize_categories { my ($itemcount) = @_; my $datatable; my $css_class = $itemcount%2?' class="LC_odd_row"':''; my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','instcode_pos','0'".');"'; $datatable = '' .' ' .&mt('Official courses (with institutional codes)') .'' .' '; $itemcount ++; $css_class = $itemcount%2?' class="LC_odd_row"':''; $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','addcategory_pos','0'".');"'; $datatable .= '' .' ' .&mt('Add category').''.&mt('Name:') .' '; return $datatable; } sub build_category_rows { my ($itemcount,$cats,$depth,$parent,$path,$idx) = @_; my ($text,$name,$item,$chgstr); if (ref($cats) eq 'ARRAY') { my $maxdepth = scalar(@{$cats}); if (ref($cats->[$depth]) eq 'HASH') { if (ref($cats->[$depth]{$parent}) eq 'ARRAY') { my $numchildren = @{$cats->[$depth]{$parent}}; my $css_class = $itemcount%2?' class="LC_odd_row"':''; $text .= ''; my ($idxnum,$parent_name,$parent_item); my $higher = $depth - 1; if ($higher == 0) { $parent_name = &escape($parent).'::'.$higher; } else { if (ref($path) eq 'ARRAY') { $parent_name = &escape($parent).':'.&escape($path->[-2]).':'.$higher; } } $parent_item = 'addcategory_pos_'.$parent_name; for (my $j=0; $j<=$numchildren; $j++) { if ($j < $numchildren) { $name = $cats->[$depth]{$parent}[$j]; $item = &escape($name).':'.&escape($parent).':'.$depth; $idxnum = $idx->{$item}; } else { $name = $parent_name; $item = $parent_item; } $chgstr = ' onchange="javascript:reorderCats(this.form,'."'$parent_name','$item','$idxnum'".');"'; $text .= ''; } $text .= '
 '; if ($j < $numchildren) { my $deeper = $depth+1; $text .= $name.' ' .''; if(ref($path) eq 'ARRAY') { push(@{$path},$name); $text .= &build_category_rows($itemcount,$cats,$deeper,$name,$path,$idx); pop(@{$path}); } } else { $text .= &mt('New:').' '; } $text .= '
'; } else { my $higher = $depth-1; if ($higher == 0) { $name = &escape($parent).'::'.$higher; } else { if (ref($path) eq 'ARRAY') { $name = &escape($parent).':'.&escape($path->[-2]).':'.$higher; } } my $colspan; if ($parent ne 'instcode') { $colspan = $maxdepth - $depth - 1; $text .= ''.&mt('Add subcategory:').''; } } } } return $text; } sub modifiable_userdata_row { my ($context,$role,$settings,$numinrow,$rowcount) = @_; my $rolename; if ($role eq 'cr') { $rolename = &mt('Custom role'); } else { $rolename = &Apache::lonnet::plaintext($role); } my @fields = ('lastname','firstname','middlename','generation', 'permanentemail','id'); my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); my $output; my $css_class = $rowcount%2?' class="LC_odd_row"':''; $output = ''. ''.$rolename.''. ''; my $rem; my %checks; if (ref($settings) eq 'HASH') { if (ref($settings->{$context}) eq 'HASH') { if (ref($settings->{$context}->{$role}) eq 'HASH') { foreach my $field (@fields) { if ($settings->{$context}->{$role}->{$field}) { $checks{$field} = ' checked="checked" '; } } } } } for (my $i=0; $i<@fields; $i++) { my $rem = $i%($numinrow); if ($rem == 0) { if ($i > 0) { $output .= ''; } $output .= ''; } my $check = ' '; if (exists($checks{$fields[$i]})) { $check = $checks{$fields[$i]} } else { if ($role eq 'st') { if (ref($settings) ne 'HASH') { $check = ' checked="checked" '; } } } $output .= ''; $rem = @fields%($numinrow); } my $colsleft = $numinrow - $rem; if ($colsleft > 1 ) { $output .= ''; } elsif ($colsleft == 1) { $output .= ''; } $output .= '
'. ''. '  
'; return $output; } sub users_cansearch_row { my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle) = @_; my $output = ''. ''.&mt('Users allowed to search').' ('.$dom.')'. ''; my $rem; if (ref($types) eq 'ARRAY') { for (my $i=0; $i<@{$types}; $i++) { if (defined($usertypes->{$types->[$i]})) { my $rem = $i%($numinrow); if ($rem == 0) { if ($i > 0) { $output .= ''; } $output .= ''; } my $check = ' '; if (ref($settings->{'cansearch'}) eq 'ARRAY') { if (grep(/^\Q$types->[$i]\E$/,@{$settings->{'cansearch'}})) { $check = ' checked="checked" '; } } $output .= ''; } } $rem = @{$types}%($numinrow); } my $colsleft = $numinrow - $rem; if ($colsleft > 1) { $output .= ''. '
'. ''; } else { $output .= ''; } my $defcheck = ' '; if (ref($settings->{'cansearch'}) eq 'ARRAY') { if (grep(/^default$/,@{$settings->{'cansearch'}})) { $defcheck = ' checked="checked" '; } } $output .= '
'; return $output; } sub sorted_searchtitles { my %searchtitles = &Apache::lonlocal::texthash( 'uname' => 'username', 'lastname' => 'last name', 'lastfirst' => 'last name, first name', ); my @titleorder = ('uname','lastname','lastfirst'); return (\%searchtitles,\@titleorder); } sub sorted_searchtypes { my %srchtypes_desc = ( exact => 'is exact match', contains => 'contains ..', begins => 'begins with ..', ); my @srchtypeorder = ('exact','begins','contains'); return (\%srchtypes_desc,\@srchtypeorder); } sub usertype_update_row { my ($settings,$usertypes,$fieldtitles,$fields,$types,$rownums) = @_; my $datatable; my $numinrow = 4; foreach my $type (@{$types}) { if (defined($usertypes->{$type})) { $$rownums ++; my $css_class = $$rownums%2?' class="LC_odd_row"':''; $datatable .= ''.$usertypes->{$type}. ''; for (my $i=0; $i<@{$fields}; $i++) { my $rem = $i%($numinrow); if ($rem == 0) { if ($i > 0) { $datatable .= ''; } $datatable .= ''; } my $check = ' '; if (ref($settings) eq 'HASH') { if (ref($settings->{'fields'}) eq 'HASH') { if (ref($settings->{'fields'}{$type}) eq 'ARRAY') { if (grep(/^\Q$fields->[$i]\E$/,@{$settings->{'fields'}{$type}})) { $check = ' checked="checked" '; } } } } if ($i == @{$fields}-1) { my $colsleft = $numinrow - $rem; if ($colsleft > 1) { $datatable .= ''; } $datatable .= '
'; } else { $datatable .= ''; } } else { $datatable .= ''; } $datatable .= '
'; } } return $datatable; } sub modify_login { my ($r,$dom,$confname,%domconfig) = @_; my ($resulttext,$errors,$colchgtext,%changes,%colchanges); my %title = ( coursecatalog => 'Display course catalog', adminmail => 'Display administrator E-mail address', newuser => 'Link for visitors to create a user account', loginheader => 'Log-in box header'); my @offon = ('off','on'); my %loginhash; ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'], \%domconfig,\%loginhash); my @toggles = ('coursecatalog','adminmail','newuser'); foreach my $item (@toggles) { $loginhash{login}{$item} = $env{'form.'.$item}; } $loginhash{login}{loginheader} = $env{'form.loginheader'}; if (ref($colchanges{'login'}) eq 'HASH') { $colchgtext = &display_colorchgs($dom,\%colchanges,['login'], \%loginhash); } my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash, $dom); if ($putresult eq 'ok') { my @toggles = ('coursecatalog','adminmail','newuser'); my %defaultchecked = ( 'coursecatalog' => 'on', 'adminmail' => 'off', 'newuser' => 'off', ); foreach my $item (@toggles) { if ($defaultchecked{$item} eq 'on') { if (($domconfig{'login'}{$item} eq '0') && ($env{'form.'.$item} eq '1')) { $changes{$item} = 1; } elsif (($domconfig{'login'}{$item} eq '' || $domconfig{'login'}{$item} eq '1') && ($env{'form.'.$item} eq '0')) { $changes{$item} = 1; } } elsif ($defaultchecked{$item} eq 'off') { if (($domconfig{'login'}{$item} eq '1') && ($env{'form.'.$item} eq '0')) { $changes{$item} = 1; } elsif (($domconfig{'login'}{$item} eq '' || $domconfig{'login'}{$item} eq '0') && ($env{'form.'.$item} eq '1')) { $changes{$item} = 1; } } } if (($domconfig{'login'}{'loginheader'} eq 'text') && ($env{'form.loginheader'} eq 'image')) { $changes{'loginheader'} = 1; } elsif (($domconfig{'login'}{'loginheader'} eq '' || $domconfig{'login'}{'loginheader'} eq 'image') && ($env{'form.loginheader'} eq 'text')) { $changes{'loginheader'} = 1; } if (keys(%changes) > 0 || $colchgtext) { &Apache::loncommon::devalidate_domconfig_cache($dom); $resulttext = &mt('Changes made:').'
    '; foreach my $item (sort(keys(%changes))) { if ($item eq 'loginheader') { $resulttext .= '
  • '.&mt("$title{$item} set to $env{'form.loginheader'}").'
  • '; } else { $resulttext .= '
  • '.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'
  • '; } } $resulttext .= $colchgtext.'
'; } else { $resulttext = &mt('No changes made to log-in page settings'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } if ($errors) { $resulttext .= '
'.&mt('The following errors occurred: ').'
    '. $errors.'
'; } return $resulttext; } sub color_font_choices { my %choices = &Apache::lonlocal::texthash ( img => "Header", bgs => "Background colors", links => "Link colors", font => "Font color", pgbg => "Page", tabbg => "Header", sidebg => "Border", link => "Link", alink => "Active link", vlink => "Visited link", ); return %choices; } sub modify_rolecolors { my ($r,$dom,$confname,$roles,%domconfig) = @_; my ($resulttext,%rolehash); $rolehash{'rolecolors'} = {}; my ($errors,%changes) = &modify_colors($r,$dom,$confname,$roles, $domconfig{'rolecolors'},$rolehash{'rolecolors'}); my $putresult = &Apache::lonnet::put_dom('configuration',\%rolehash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { &Apache::loncommon::devalidate_domconfig_cache($dom); $resulttext = &display_colorchgs($dom,\%changes,$roles, $rolehash{'rolecolors'}); } else { $resulttext = &mt('No changes made to default color schemes'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } if ($errors) { $resulttext .= &mt('The following errors occurred: ').'
    '. $errors.'
'; } return $resulttext; } sub modify_colors { my ($r,$dom,$confname,$roles,$domconfig,$confhash) = @_; my (%changes,%choices); my @bgs = ('pgbg','mainbg','sidebg'); my @links = ('link','alink','vlink'); my @logintext; my @images; my $servadm = $r->dir_config('lonAdmEMail'); my $errors; foreach my $role (@{$roles}) { if ($role eq 'login') { %choices = &login_choices(); @logintext = ('textcol','bgcol'); } else { %choices = &color_font_choices(); } if ($role eq 'login') { @images = ('img','logo','domlogo','login'); } else { @images = ('img'); } $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'}; foreach my $item (@bgs,@links,@logintext) { $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; } my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm); my ($width,$height) = &thumb_dimensions(); if (ref($domconfig->{$role}) ne 'HASH') { $domconfig->{$role} = {}; } foreach my $img (@images) { if ( ! $env{'form.'.$role.'_'.$img.'.filename'} && !defined($domconfig->{$role}{$img}) && !$env{'form.'.$role.'_del_'.$img} && $env{'form.'.$role.'_import_'.$img}) { # import the old configured image from the .tab setting # if they haven't provided a new one $domconfig->{$role}{$img} = $env{'form.'.$role.'_import_'.$img}; } if ($env{'form.'.$role.'_'.$img.'.filename'} ne '') { my $error; if ($configuserok eq 'ok') { if ($switchserver) { $error = &mt("Upload of [_1] image for $role page(s) is not permitted to this server: [_2]",$choices{$img},$switchserver); } else { if ($author_ok eq 'ok') { my ($result,$logourl) = &publishlogo($r,'upload',$role.'_'.$img, $dom,$confname,$img,$width,$height); if ($result eq 'ok') { $confhash->{$role}{$img} = $logourl; $changes{$role}{'images'}{$img} = 1; } else { $error = &mt("Upload of [_1] image for $role page(s) failed because an error occurred publishing the file in RES space. Error was: [_2].",$choices{img},$result); } } else { $error = &mt("Upload of [_1] image for $role page(s) failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$author_ok); } } } else { $error = &mt("Upload of [_1] image for $role page(s) failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$configuserok); } if ($error) { &Apache::lonnet::logthis($error); $errors .= '
  • '.$error.'
  • '; } } elsif ($domconfig->{$role}{$img} ne '') { if ($domconfig->{$role}{$img} !~ m-^(/res/\Q$dom\E/\Q$confname\E/\Q$img\E)/([^/]+)$-) { my $error; if ($configuserok eq 'ok') { # is confname an author? if ($switchserver eq '') { if ($author_ok eq 'ok') { my ($result,$logourl) = &publishlogo($r,'copy',$domconfig->{$role}{$img}, $dom,$confname,$img,$width,$height); if ($result eq 'ok') { $confhash->{$role}{$img} = $logourl; $changes{$role}{'images'}{$img} = 1; } } } } } } } if (ref($domconfig) eq 'HASH') { if (ref($domconfig->{$role}) eq 'HASH') { foreach my $img (@images) { if ($domconfig->{$role}{$img} ne '') { if ($env{'form.'.$role.'_del_'.$img}) { $confhash->{$role}{$img} = ''; $changes{$role}{'images'}{$img} = 1; } else { if ($confhash->{$role}{$img} eq '') { $confhash->{$role}{$img} = $domconfig->{$role}{$img}; } } } else { if ($env{'form.'.$role.'_del_'.$img}) { $confhash->{$role}{$img} = ''; $changes{$role}{'images'}{$img} = 1; } } } if ($domconfig->{$role}{'font'} ne '') { if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) { $changes{$role}{'font'} = 1; } } else { if ($confhash->{$role}{'font'}) { $changes{$role}{'font'} = 1; } } foreach my $item (@bgs) { if ($domconfig->{$role}{$item} ne '') { if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) { $changes{$role}{'bgs'}{$item} = 1; } } else { if ($confhash->{$role}{$item}) { $changes{$role}{'bgs'}{$item} = 1; } } } foreach my $item (@links) { if ($domconfig->{$role}{$item} ne '') { if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) { $changes{$role}{'links'}{$item} = 1; } } else { if ($confhash->{$role}{$item}) { $changes{$role}{'links'}{$item} = 1; } } } foreach my $item (@logintext) { if ($domconfig->{$role}{$item} ne '') { if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) { $changes{$role}{'logintext'}{$item} = 1; } } else { if ($confhash->{$role}{$item}) { $changes{$role}{'logintext'}{$item} = 1; } } } } else { &default_change_checker($role,\@images,\@links,\@bgs, \@logintext,$confhash,\%changes); } } else { &default_change_checker($role,\@images,\@links,\@bgs, \@logintext,$confhash,\%changes); } } return ($errors,%changes); } sub config_check { my ($dom,$confname,$servadm) = @_; my ($configuserok,$author_ok,$switchserver,%currroles); my $uhome = &Apache::lonnet::homeserver($confname,$dom,1); ($configuserok,%currroles) = &check_configuser($uhome,$dom, $confname,$servadm); if ($configuserok eq 'ok') { $switchserver = &check_switchserver($dom,$confname); if ($switchserver eq '') { $author_ok = &check_authorstatus($dom,$confname,%currroles); } } return ($configuserok,$author_ok,$switchserver); } sub default_change_checker { my ($role,$images,$links,$bgs,$logintext,$confhash,$changes) = @_; foreach my $item (@{$links}) { if ($confhash->{$role}{$item}) { $changes->{$role}{'links'}{$item} = 1; } } foreach my $item (@{$bgs}) { if ($confhash->{$role}{$item}) { $changes->{$role}{'bgs'}{$item} = 1; } } foreach my $item (@{$logintext}) { if ($confhash->{$role}{$item}) { $changes->{$role}{'logintext'}{$item} = 1; } } foreach my $img (@{$images}) { if ($env{'form.'.$role.'_del_'.$img}) { $confhash->{$role}{$img} = ''; $changes->{$role}{'images'}{$img} = 1; } } if ($confhash->{$role}{'font'}) { $changes->{$role}{'font'} = 1; } } sub display_colorchgs { my ($dom,$changes,$roles,$confhash) = @_; my (%choices,$resulttext); if (!grep(/^login$/,@{$roles})) { $resulttext = &mt('Changes made:').'
    '; } foreach my $role (@{$roles}) { if ($role eq 'login') { %choices = &login_choices(); } else { %choices = &color_font_choices(); } if (ref($changes->{$role}) eq 'HASH') { if ($role ne 'login') { $resulttext .= '

    '.&mt($role).'

    '; } foreach my $key (sort(keys(%{$changes->{$role}}))) { if ($role ne 'login') { $resulttext .= '
      '; } if (ref($changes->{$role}{$key}) eq 'HASH') { if ($role ne 'login') { $resulttext .= '
    • '.&mt($choices{$key}).':
        '; } foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) { if ($confhash->{$role}{$item} eq '') { $resulttext .= '
      • '.&mt("$choices{$item} set to default").'
      • '; } else { my $newitem = $confhash->{$role}{$item}; if ($key eq 'images') { $newitem = ''.$choices{$item}.''; } $resulttext .= '
      • '.&mt("$choices{$item} set to [_1]",$newitem).'
      • '; } } if ($role ne 'login') { $resulttext .= '
    • '; } } else { if ($confhash->{$role}{$key} eq '') { $resulttext .= '
    • '.&mt("$choices{$key} set to default").'
    • '; } else { $resulttext .= '
    • '.&mt("$choices{$key} set to [_1]",$confhash->{$role}{$key}).'
    • '; } } if ($role ne 'login') { $resulttext .= '
    '; } } } } return $resulttext; } sub thumb_dimensions { return ('200','50'); } sub check_dimensions { my ($inputfile) = @_; my ($fullwidth,$fullheight); if ($inputfile =~ m|^[/\w.\-]+$|) { if (open(PIPE,"identify $inputfile 2>&1 |")) { my $imageinfo = ; if (!close(PIPE)) { &Apache::lonnet::logthis("Failed to close PIPE opened to retrieve image information for $inputfile"); } chomp($imageinfo); my ($fullsize) = ($imageinfo =~ /^\Q$inputfile\E\s+\w+\s+(\d+x\d+)/); if ($fullsize) { ($fullwidth,$fullheight) = split(/x/,$fullsize); } } } return ($fullwidth,$fullheight); } sub check_configuser { my ($uhome,$dom,$confname,$servadm) = @_; my ($configuserok,%currroles); if ($uhome eq 'no_host') { srand( time() ^ ($$ + ($$ << 15)) ); # Seed rand. my $configpass = &LONCAPA::Enrollment::create_password(); $configuserok = &Apache::lonnet::modifyuser($dom,$confname,'','internal', $configpass,'','','','','',undef,$servadm); } else { $configuserok = 'ok'; %currroles = &Apache::lonnet::get_my_roles($confname,$dom,'userroles'); } return ($configuserok,%currroles); } sub check_authorstatus { my ($dom,$confname,%currroles) = @_; my $author_ok; if (!$currroles{':'.$dom.':au'}) { my $start = time; my $end = 0; $author_ok = &Apache::lonnet::assignrole($dom,$confname,'/'.$dom.'/', 'au',$end,$start,'','','domconfig'); } else { $author_ok = 'ok'; } return $author_ok; } sub publishlogo { my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_; my ($output,$fname,$logourl); if ($action eq 'upload') { $fname=$env{'form.'.$formname.'.filename'}; chop($env{'form.'.$formname}); } else { ($fname) = ($formname =~ /([^\/]+)$/); } if ($savefileas ne '') { $fname = $savefileas; } $fname=&Apache::lonnet::clean_filename($fname); # See if there is anything left unless ($fname) { return ('error: no uploaded file'); } $fname="$subdir/$fname"; my $filepath='/home/'.$confname.'/public_html'; my ($fnamepath,$file,$fetchthumb); $file=$fname; if ($fname=~m|/|) { ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|); } my @parts=split(/\//,$filepath.'/'.$fnamepath); my $count; for ($count=4;$count<=$#parts;$count++) { $filepath.="/$parts[$count]"; if ((-e $filepath)!=1) { mkdir($filepath,02770); } } # Check for bad extension and disallow upload if ($file=~/\.(\w+)$/ && (&Apache::loncommon::fileembstyle($1) eq 'hdn')) { $output = &mt('Invalid file extension ([_1]) - reserved for LONCAPA use.',$1); } elsif ($file=~/\.(\w+)$/ && !defined(&Apache::loncommon::fileembstyle($1))) { $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1); } elsif ($file=~/\.(\d+)\.(\w+)$/) { $output = &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); } elsif (-d "$filepath/$file") { $output = &mt('File name is a directory name - rename the file and re-upload'); } else { my $source = $filepath.'/'.$file; my $logfile; if (!open($logfile,">>$source".'.log')) { return (&mt('No write permission to Construction Space')); } print $logfile "\n================= Publish ".localtime()." ================\n". $env{'user.name'}.':'.$env{'user.domain'}."\n"; # Save the file if (!open(FH,'>'.$source)) { &Apache::lonnet::logthis('Failed to create '.$source); return (&mt('Failed to create file')); } if ($action eq 'upload') { if (!print FH ($env{'form.'.$formname})) { &Apache::lonnet::logthis('Failed to write to '.$source); return (&mt('Failed to write file')); } } else { my $original = &Apache::lonnet::filelocation('',$formname); if(!copy($original,$source)) { &Apache::lonnet::logthis('Failed to copy '.$original.' to '.$source); return (&mt('Failed to write file')); } } close(FH); chmod(0660, $source); # Permissions to rw-rw---. my $docroot=$r->dir_config('lonDocRoot'); my $targetdir=$docroot.'/res/'.$dom.'/'.$confname .'/'.$fnamepath; my $copyfile=$targetdir.'/'.$file; my @parts=split(/\//,$targetdir); my $path="/$parts[1]/$parts[2]/$parts[3]/$parts[4]"; for (my $count=5;$count<=$#parts;$count++) { $path.="/$parts[$count]"; if (!-e $path) { print $logfile "\nCreating directory ".$path; mkdir($path,02770); } } my $versionresult; if (-e $copyfile) { $versionresult = &logo_versioning($targetdir,$file,$logfile); } else { $versionresult = 'ok'; } if ($versionresult eq 'ok') { if (copy($source,$copyfile)) { print $logfile "\nCopied original source to ".$copyfile."\n"; $output = 'ok'; &write_metadata($dom,$confname,$formname,$targetdir,$file,$logfile); $logourl = '/res/'.$dom.'/'.$confname.'/'.$fname; } else { print $logfile "\nUnable to write ".$copyfile.':'.$!."\n"; $output = &mt('Failed to copy file to RES space').", $!"; } if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) { my $inputfile = $filepath.'/'.$file; my $outfile = $filepath.'/'.'tn-'.$file; my ($fullwidth,$fullheight) = &check_dimensions($inputfile); if ($fullwidth ne '' && $fullheight ne '') { if ($fullwidth > $thumbwidth && $fullheight > $thumbheight) { my $thumbsize = $thumbwidth.'x'.$thumbheight; system("convert -sample $thumbsize $inputfile $outfile"); chmod(0660, $filepath.'/tn-'.$file); if (-e $outfile) { my $copyfile=$targetdir.'/tn-'.$file; if (copy($outfile,$copyfile)) { print $logfile "\nCopied source to ".$copyfile."\n"; &write_metadata($dom,$confname,$formname, $targetdir,'tn-'.$file,$logfile); } else { print $logfile "\nUnable to write ".$copyfile. ':'.$!."\n"; } } } } } } else { $output = $versionresult; } } return ($output,$logourl); } sub logo_versioning { my ($targetdir,$file,$logfile) = @_; my $target = $targetdir.'/'.$file; my ($maxversion,$fn,$extn,$output); $maxversion = 0; if ($file =~ /^(.+)\.(\w+)$/) { $fn=$1; $extn=$2; } opendir(DIR,$targetdir); while (my $filename=readdir(DIR)) { if ($filename=~/\Q$fn\E\.(\d+)\.\Q$extn\E$/) { $maxversion=($1>$maxversion)?$1:$maxversion; } } $maxversion++; print $logfile "\nCreating old version ".$maxversion."\n"; my $copyfile=$targetdir.'/'.$fn.'.'.$maxversion.'.'.$extn; if (copy($target,$copyfile)) { print $logfile "Copied old target to ".$copyfile."\n"; $copyfile=$copyfile.'.meta'; if (copy($target.'.meta',$copyfile)) { print $logfile "Copied old target metadata to ".$copyfile."\n"; $output = 'ok'; } else { print $logfile "Unable to write metadata ".$copyfile.':'.$!."\n"; $output = &mt('Failed to copy old meta').", $!, "; } } else { print $logfile "Unable to write ".$copyfile.':'.$!."\n"; $output = &mt('Failed to copy old target').", $!, "; } return $output; } sub write_metadata { my ($dom,$confname,$formname,$targetdir,$file,$logfile) = @_; my (%metadatafields,%metadatakeys,$output); $metadatafields{'title'}=$formname; $metadatafields{'creationdate'}=time; $metadatafields{'lastrevisiondate'}=time; $metadatafields{'copyright'}='public'; $metadatafields{'modifyinguser'}=$env{'user.name'}.':'. $env{'user.domain'}; $metadatafields{'authorspace'}=$confname.':'.$dom; $metadatafields{'domain'}=$dom; { print $logfile "\nWrite metadata file for ".$targetdir.'/'.$file; my $mfh; unless (open($mfh,'>'.$targetdir.'/'.$file.'.meta')) { $output = &mt('Could not write metadata'); } foreach (sort keys %metadatafields) { unless ($_=~/\./) { my $unikey=$_; $unikey=~/^([A-Za-z]+)/; my $tag=$1; $tag=~tr/A-Z/a-z/; print $mfh "\n\<$tag"; foreach (split(/\,/,$metadatakeys{$unikey})) { my $value=$metadatafields{$unikey.'.'.$_}; $value=~s/\"/\'\'/g; print $mfh ' '.$_.'="'.$value.'"'; } print $mfh '>'. &HTML::Entities::encode($metadatafields{$unikey},'<>&"') .''; } } $output = 'ok'; print $logfile "\nWrote metadata"; close($mfh); } } sub check_switchserver { my ($dom,$confname) = @_; my ($allowed,$switchserver); my $home = &Apache::lonnet::homeserver($confname,$dom); if ($home eq 'no_host') { $home = &Apache::lonnet::domain($dom,'primary'); } 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 javascript_set_colnums { return < 1100) { document.pickactions.numcols[1].checked = true; } else { document.pickactions.numcols[0].checked = true; } } END } sub modify_quotas { my ($dom,%domconfig) = @_; my ($resulttext,%changes); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my %formhash; foreach my $key (keys(%env)) { if ($key =~ /^form\.quota_(.+)$/) { $formhash{$1} = $env{$key}; } } $formhash{'default'} = $env{'form.defaultquota'}; if (ref($domconfig{'quotas'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'quotas'}})) { if (exists($formhash{$key})) { if ($formhash{$key} ne $domconfig{'quotas'}{$key}) { $changes{$key} = 1; } } else { $formhash{$key} = $domconfig{'quotas'}{$key}; } } } foreach my $key (keys(%formhash)) { if ($formhash{$key} ne '') { if (!exists($domconfig{'quotas'}{$key})) { $changes{$key} = 1; } } } my %quotahash = ( quotas => {%formhash}, ); my $putresult = &Apache::lonnet::put_dom('configuration',\%quotahash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; foreach my $type (@{$types},'default') { if (defined($changes{$type})) { my $typetitle = $usertypes->{$type}; if ($type eq 'default') { $typetitle = $othertitle; } $resulttext .= '
    • '.&mt('[_1] set to [_2] Mb',$typetitle,$formhash{$type}).'
    • '; } } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to default quotas'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } return $resulttext; } sub modify_autoenroll { my ($dom,%domconfig) = @_; my ($resulttext,%changes); my %currautoenroll; if (ref($domconfig{'autoenroll'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'autoenroll'}})) { $currautoenroll{$key} = $domconfig{'autoenroll'}{$key}; } } my $autorun = &Apache::lonnet::auto_run(undef,$dom), my %title = ( run => 'Auto-enrollment active', sender => 'Sender for notification messages'); my @offon = ('off','on'); my $sender_uname = $env{'form.sender_uname'}; my $sender_domain = $env{'form.sender_domain'}; if ($sender_domain eq '') { $sender_uname = ''; } elsif ($sender_uname eq '') { $sender_domain = ''; } my %autoenrollhash = ( autoenroll => { run => $env{'form.autoenroll_run'}, sender_uname => $sender_uname, sender_domain => $sender_domain, } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%autoenrollhash, $dom); if ($putresult eq 'ok') { if (exists($currautoenroll{'run'})) { if ($currautoenroll{'run'} ne $env{'form.autoenroll_run'}) { $changes{'run'} = 1; } } elsif ($autorun) { if ($env{'form.autoenroll_run'} ne '1') { $changes{'run'} = 1; } } if ($currautoenroll{'sender_uname'} ne $sender_uname) { $changes{'sender'} = 1; } if ($currautoenroll{'sender_domain'} ne $sender_domain) { $changes{'sender'} = 1; } if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; if ($changes{'run'}) { $resulttext .= '
    • '.&mt("$title{'run'} set to $offon[$env{'form.autoenroll_run'}]").'
    • '; } if ($changes{'sender'}) { if ($sender_uname eq '' || $sender_domain eq '') { $resulttext .= '
    • '.&mt("$title{'sender'} set to default (course owner).").'
    • '; } else { $resulttext .= '
    • '.&mt("$title{'sender'} set to [_1]",$sender_uname.':'.$sender_domain).'
    • '; } } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to auto-enrollment settings'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } return $resulttext; } sub modify_autoupdate { my ($dom,%domconfig) = @_; my ($resulttext,%currautoupdate,%fields,%changes); if (ref($domconfig{'autoupdate'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'autoupdate'}})) { $currautoupdate{$key} = $domconfig{'autoupdate'}{$key}; } } my @offon = ('off','on'); my %title = &Apache::lonlocal::texthash ( run => 'Auto-update:', classlists => 'Updates to user information in classlists?' ); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my %fieldtitles = &Apache::lonlocal::texthash ( id => 'Student/Employee ID', permanentemail => 'E-mail address', lastname => 'Last Name', firstname => 'First Name', middlename => 'Middle Name', gen => 'Generation', ); my $othertitle = &mt('All users'); if (keys(%{$usertypes}) > 0) { $othertitle = &mt('Other users'); } foreach my $key (keys(%env)) { if ($key =~ /^form\.updateable_(.+)_([^_]+)$/) { push(@{$fields{$1}},$2); } } my %updatehash = ( autoupdate => { run => $env{'form.autoupdate_run'}, classlists => $env{'form.classlists'}, fields => {%fields}, } ); foreach my $key (keys(%currautoupdate)) { if (($key eq 'run') || ($key eq 'classlists')) { if (exists($updatehash{autoupdate}{$key})) { if ($currautoupdate{$key} ne $updatehash{autoupdate}{$key}) { $changes{$key} = 1; } } } elsif ($key eq 'fields') { if (ref($currautoupdate{$key}) eq 'HASH') { foreach my $item (@{$types},'default') { if (ref($currautoupdate{$key}{$item}) eq 'ARRAY') { my $change = 0; foreach my $type (@{$currautoupdate{$key}{$item}}) { if (!exists($fields{$item})) { $change = 1; } elsif (ref($fields{$item}) eq 'ARRAY') { if (!grep(/^\Q$type\E$/,@{$fields{$item}})) { $change = 1; } } } if ($change) { push(@{$changes{$key}},$item); } } } } } } foreach my $item (@{$types},'default') { if (defined($fields{$item})) { if (ref($currautoupdate{'fields'}) eq 'HASH') { if (!exists($currautoupdate{'fields'}{$item})) { push(@{$changes{'fields'}},$item); } } else { push(@{$changes{'fields'}},$item); } } } my $putresult = &Apache::lonnet::put_dom('configuration',\%updatehash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; foreach my $key (sort(keys(%changes))) { if (ref($changes{$key}) eq 'ARRAY') { foreach my $item (@{$changes{$key}}) { my @newvalues; foreach my $type (@{$fields{$item}}) { push(@newvalues,$fieldtitles{$type}); } my $newvaluestr; if (@newvalues > 0) { $newvaluestr = join(', ',@newvalues); } else { $newvaluestr = &mt('none'); } if ($item eq 'default') { $resulttext .= '
    • '.&mt("Updates for '[_1]' set to: '[_2]'",$othertitle,$newvaluestr).'
    • '; } else { $resulttext .= '
    • '.&mt("Updates for '[_1]' set to: '[_2]'",$usertypes->{$item},$newvaluestr).'
    • '; } } } else { my $newvalue; if ($key eq 'run') { $newvalue = $offon[$env{'form.autoupdate_run'}]; } else { $newvalue = $offon[$env{'form.'.$key}]; } $resulttext .= '
    • '.&mt("[_1] set to $newvalue",$title{$key}).'
    • '; } } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to autoupdates'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } return $resulttext; } sub modify_directorysrch { my ($dom,%domconfig) = @_; my ($resulttext,%changes); my %currdirsrch; if (ref($domconfig{'directorysrch'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'directorysrch'}})) { $currdirsrch{$key} = $domconfig{'directorysrch'}{$key}; } } my %title = ( available => 'Directory search available', localonly => 'Other domains can search', searchby => 'Search types', searchtypes => 'Search latitude'); my @offon = ('off','on'); my @otherdoms = ('Yes','No'); my @searchtypes = &Apache::loncommon::get_env_multiple('form.searchtypes'); my @cansearch = &Apache::loncommon::get_env_multiple('form.cansearch'); my @searchby = &Apache::loncommon::get_env_multiple('form.searchby'); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); if (keys(%{$usertypes}) == 0) { @cansearch = ('default'); } else { if (ref($currdirsrch{'cansearch'}) eq 'ARRAY') { foreach my $type (@{$currdirsrch{'cansearch'}}) { if (!grep(/^\Q$type\E$/,@cansearch)) { push(@{$changes{'cansearch'}},$type); } } foreach my $type (@cansearch) { if (!grep(/^\Q$type\E$/,@{$currdirsrch{'cansearch'}})) { push(@{$changes{'cansearch'}},$type); } } } else { push(@{$changes{'cansearch'}},@cansearch); } } if (ref($currdirsrch{'searchby'}) eq 'ARRAY') { foreach my $by (@{$currdirsrch{'searchby'}}) { if (!grep(/^\Q$by\E$/,@searchby)) { push(@{$changes{'searchby'}},$by); } } foreach my $by (@searchby) { if (!grep(/^\Q$by\E$/,@{$currdirsrch{'searchby'}})) { push(@{$changes{'searchby'}},$by); } } } else { push(@{$changes{'searchby'}},@searchby); } if (ref($currdirsrch{'searchtypes'}) eq 'ARRAY') { foreach my $type (@{$currdirsrch{'searchtypes'}}) { if (!grep(/^\Q$type\E$/,@searchtypes)) { push(@{$changes{'searchtypes'}},$type); } } foreach my $type (@searchtypes) { if (!grep(/^\Q$type\E$/,@{$currdirsrch{'searchtypes'}})) { push(@{$changes{'searchtypes'}},$type); } } } else { if (exists($currdirsrch{'searchtypes'})) { foreach my $type (@searchtypes) { if ($type ne $currdirsrch{'searchtypes'}) { push(@{$changes{'searchtypes'}},$type); } } if (!grep(/^\Q$currdirsrch{'searchtypes'}\E/,@searchtypes)) { push(@{$changes{'searchtypes'}},$currdirsrch{'searchtypes'}); } } else { push(@{$changes{'searchtypes'}},@searchtypes); } } my %dirsrch_hash = ( directorysrch => { available => $env{'form.dirsrch_available'}, cansearch => \@cansearch, localonly => $env{'form.dirsrch_localonly'}, searchby => \@searchby, searchtypes => \@searchtypes, } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%dirsrch_hash, $dom); if ($putresult eq 'ok') { if (exists($currdirsrch{'available'})) { if ($currdirsrch{'available'} ne $env{'form.dirsrch_available'}) { $changes{'available'} = 1; } } else { if ($env{'form.dirsrch_available'} eq '1') { $changes{'available'} = 1; } } if (exists($currdirsrch{'localonly'})) { if ($currdirsrch{'localonly'} ne $env{'form.dirsrch_localonly'}) { $changes{'localonly'} = 1; } } else { if ($env{'form.dirsrch_localonly'} eq '1') { $changes{'localonly'} = 1; } } if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; if ($changes{'available'}) { $resulttext .= '
    • '.&mt("$title{'available'} set to: $offon[$env{'form.dirsrch_available'}]").'
    • '; } if ($changes{'localonly'}) { $resulttext .= '
    • '.&mt("$title{'localonly'} set to: $otherdoms[$env{'form.dirsrch_localonly'}]").'
    • '; } if (ref($changes{'cansearch'}) eq 'ARRAY') { my $chgtext; if (ref($usertypes) eq 'HASH') { if (keys(%{$usertypes}) > 0) { foreach my $type (@{$types}) { if (grep(/^\Q$type\E$/,@cansearch)) { $chgtext .= $usertypes->{$type}.'; '; } } if (grep(/^default$/,@cansearch)) { $chgtext .= $othertitle; } else { $chgtext =~ s/\; $//; } $resulttext .= '
    • '.&mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]",$dom,$chgtext).'
    • '; } } } if (ref($changes{'searchby'}) eq 'ARRAY') { my ($searchtitles,$titleorder) = &sorted_searchtitles(); my $chgtext; foreach my $type (@{$titleorder}) { if (grep(/^\Q$type\E$/,@searchby)) { if (defined($searchtitles->{$type})) { $chgtext .= $searchtitles->{$type}.'; '; } } } $chgtext =~ s/\; $//; $resulttext .= '
    • '.&mt("$title{'searchby'} set to: [_1]",$chgtext).'
    • '; } if (ref($changes{'searchtypes'}) eq 'ARRAY') { my ($srchtypes_desc,$srchtypeorder) = &sorted_searchtypes(); my $chgtext; foreach my $type (@{$srchtypeorder}) { if (grep(/^\Q$type\E$/,@searchtypes)) { if (defined($srchtypes_desc->{$type})) { $chgtext .= $srchtypes_desc->{$type}.'; '; } } } $chgtext =~ s/\; $//; $resulttext .= '
    • '.&mt("$title{'searchtypes'} set to: \"[_1]\"",$chgtext).'
    • '; } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to institution directory search settings'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } return $resulttext; } sub modify_contacts { my ($dom,%domconfig) = @_; my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash); if (ref($domconfig{'contacts'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'contacts'}})) { $currsetting{$key} = $domconfig{'contacts'}{$key}; } } my (%others,%to); my @contacts = ('supportemail','adminemail'); my @mailings = ('errormail','packagesmail','helpdeskmail'); foreach my $type (@mailings) { @{$newsetting{$type}} = &Apache::loncommon::get_env_multiple('form.'.$type); foreach my $item (@contacts) { if (grep(/^\Q$item\E$/,@{$newsetting{$type}})) { $contacts_hash{contacts}{$type}{$item} = 1; } else { $contacts_hash{contacts}{$type}{$item} = 0; } } $others{$type} = $env{'form.'.$type.'_others'}; $contacts_hash{contacts}{$type}{'others'} = $others{$type}; } foreach my $item (@contacts) { $to{$item} = $env{'form.'.$item}; $contacts_hash{'contacts'}{$item} = $to{$item}; } if (keys(%currsetting) > 0) { foreach my $item (@contacts) { if ($to{$item} ne $currsetting{$item}) { $changes{$item} = 1; } } foreach my $type (@mailings) { foreach my $item (@contacts) { if (ref($currsetting{$type}) eq 'HASH') { if ($currsetting{$type}{$item} ne $contacts_hash{contacts}{$type}{$item}) { push(@{$changes{$type}},$item); } } else { push(@{$changes{$type}},@{$newsetting{$type}}); } } if ($others{$type} ne $currsetting{$type}{'others'}) { push(@{$changes{$type}},'others'); } } } else { my %default; $default{'supportemail'} = $Apache::lonnet::perlvar{'lonSupportEMail'}; $default{'adminemail'} = $Apache::lonnet::perlvar{'lonAdmEMail'}; $default{'errormail'} = 'adminemail'; $default{'packagesmail'} = 'adminemail'; $default{'helpdeskmail'} = 'supportemail'; foreach my $item (@contacts) { if ($to{$item} ne $default{$item}) { $changes{$item} = 1; } } foreach my $type (@mailings) { if ((@{$newsetting{$type}} != 1) || ($newsetting{$type}[0] ne $default{$type})) { push(@{$changes{$type}},@{$newsetting{$type}}); } if ($others{$type} ne '') { push(@{$changes{$type}},'others'); } } } my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { my ($titles,$short_titles) = &contact_titles(); $resulttext = &mt('Changes made:').'
      '; foreach my $item (@contacts) { if ($changes{$item}) { $resulttext .= '
    • '.$titles->{$item}. &mt(' set to: '). ''. $to{$item}.'
    • '; } } foreach my $type (@mailings) { if (ref($changes{$type}) eq 'ARRAY') { $resulttext .= '
    • '.$titles->{$type}.': '; my @text; foreach my $item (@{$newsetting{$type}}) { push(@text,$short_titles->{$item}); } if ($others{$type} ne '') { push(@text,$others{$type}); } $resulttext .= ''. join(', ',@text).'
    • '; } } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to contact information'); } } else { $resulttext = ''. &mt('An error occurred: [_1].',$putresult).''; } return $resulttext; } sub modify_usercreation { my ($dom,%domconfig) = @_; my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate); my $warningmsg; if (ref($domconfig{'usercreation'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'usercreation'}})) { $curr_usercreation{$key} = $domconfig{'usercreation'}{$key}; } } my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule'); my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule'); my @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule'); my @contexts = ('author','course','selfcreate'); foreach my $item(@contexts) { $cancreate{$item} = $env{'form.can_createuser_'.$item}; if ($item eq 'selfcreate') { my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth'))) { if (($cancreate{$item} eq 'any') || ($cancreate{$item} eq 'login')) { $warningmsg = &mt('Although account creation has been set to be available for institutional logins, currently default authentication in this domain has not been set to support this.').' '.&mt('You need to set the default authentication type to Kerberos 4 or 5 (with a Kerberos domain specified), or to Local authentication, if the localauth module has been customized in your domain to authenticate institutional logins.'); } } } } if (ref($curr_usercreation{'cancreate'}) eq 'HASH') { foreach my $item (@contexts) { if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) { push(@{$changes{'cancreate'}},$item); } } } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') { foreach my $item (@contexts) { if (!grep(/^\Q$item\E$/,@{$curr_usercreation{'cancreate'}})) { if ($cancreate{$item} ne 'any') { push(@{$changes{'cancreate'}},$item); } } else { if ($cancreate{$item} ne 'none') { push(@{$changes{'cancreate'}},$item); } } } } else { foreach my $item (@contexts) { push(@{$changes{'cancreate'}},$item); } } if (ref($curr_usercreation{'username_rule'}) eq 'ARRAY') { foreach my $type (@{$curr_usercreation{'username_rule'}}) { if (!grep(/^\Q$type\E$/,@username_rule)) { push(@{$changes{'username_rule'}},$type); } } foreach my $type (@username_rule) { if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'username_rule'}})) { push(@{$changes{'username_rule'}},$type); } } } else { push(@{$changes{'username_rule'}},@username_rule); } if (ref($curr_usercreation{'id_rule'}) eq 'ARRAY') { foreach my $type (@{$curr_usercreation{'id_rule'}}) { if (!grep(/^\Q$type\E$/,@id_rule)) { push(@{$changes{'id_rule'}},$type); } } foreach my $type (@id_rule) { if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'id_rule'}})) { push(@{$changes{'id_rule'}},$type); } } } else { push(@{$changes{'id_rule'}},@id_rule); } if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') { foreach my $type (@{$curr_usercreation{'email_rule'}}) { if (!grep(/^\Q$type\E$/,@email_rule)) { push(@{$changes{'email_rule'}},$type); } } foreach my $type (@email_rule) { if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) { push(@{$changes{'email_rule'}},$type); } } } else { push(@{$changes{'email_rule'}},@email_rule); } my @authen_contexts = ('author','course','domain'); my @authtypes = ('int','krb4','krb5','loc'); my %authhash; foreach my $item (@authen_contexts) { my @authallowed = &Apache::loncommon::get_env_multiple('form.'.$item.'_auth'); foreach my $auth (@authtypes) { if (grep(/^\Q$auth\E$/,@authallowed)) { $authhash{$item}{$auth} = 1; } else { $authhash{$item}{$auth} = 0; } } } if (ref($curr_usercreation{'authtypes'}) eq 'HASH') { foreach my $item (@authen_contexts) { if (ref($curr_usercreation{'authtypes'}{$item}) eq 'HASH') { foreach my $auth (@authtypes) { if ($authhash{$item}{$auth} ne $curr_usercreation{'authtypes'}{$item}{$auth}) { push(@{$changes{'authtypes'}},$item); last; } } } } } else { foreach my $item (@authen_contexts) { push(@{$changes{'authtypes'}},$item); } } my %usercreation_hash = ( usercreation => { cancreate => \%cancreate, username_rule => \@username_rule, id_rule => \@id_rule, email_rule => \@email_rule, authtypes => \%authhash, } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; if (ref($changes{'cancreate'}) eq 'ARRAY') { my %lt = &usercreation_types(); foreach my $type (@{$changes{'cancreate'}}) { my $chgtext = $lt{$type}.', '; if ($type eq 'selfcreate') { if ($cancreate{$type} eq 'none') { $chgtext .= &mt('creation of a new user account is not permitted.'); } elsif ($cancreate{$type} eq 'any') { $chgtext .= &mt('creation of a new account is permitted for users authenticated by institutional log-in and SSO, and also for e-mail addresses used as usernames.'); } elsif ($cancreate{$type} eq 'login') { $chgtext .= &mt('creation of a new account is only permitted for users authenticated by institutional log-in.'); } elsif ($cancreate{$type} eq 'sso') { $chgtext .= &mt('creation of a new account is only permitted for users authenticated by institutional single sign on.'); } elsif ($cancreate{$type} eq 'email') { $chgtext .= &mt('creation of a new account is only permitted for users who provide a valid e-mail address for use as the username.'); } } else { if ($cancreate{$type} eq 'none') { $chgtext .= &mt('creation of new users is not permitted, except by a Domain Coordinator.'); } elsif ($cancreate{$type} eq 'any') { $chgtext .= &mt('creation of new users is permitted for both institutional and non-institutional usernames.'); } elsif ($cancreate{$type} eq 'official') { $chgtext .= &mt('creation of new users is only permitted for institutional usernames.'); } elsif ($cancreate{$type} eq 'unofficial') { $chgtext .= &mt('creation of new users is only permitted for non-institutional usernames.'); } } $resulttext .= '
    • '.$chgtext.'
    • '; } } if (ref($changes{'username_rule'}) eq 'ARRAY') { my ($rules,$ruleorder) = &Apache::lonnet::inst_userrules($dom,'username'); my $chgtext = '
        '; foreach my $type (@username_rule) { if (ref($rules->{$type}) eq 'HASH') { $chgtext .= '
      • '.$rules->{$type}{'name'}.'
      • '; } } $chgtext .= '
      '; if (@username_rule > 0) { $resulttext .= '
    • '.&mt('Usernames with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'
    • '; } else { $resulttext .= '
    • '.&mt('There are now no username formats restricted to verified users in the institutional directory.').'
    • '; } } if (ref($changes{'id_rule'}) eq 'ARRAY') { my ($idrules,$idruleorder) = &Apache::lonnet::inst_userrules($dom,'id'); my $chgtext = '
        '; foreach my $type (@id_rule) { if (ref($idrules->{$type}) eq 'HASH') { $chgtext .= '
      • '.$idrules->{$type}{'name'}.'
      • '; } } $chgtext .= '
      '; if (@id_rule > 0) { $resulttext .= '
    • '.&mt('IDs with the following formats are restricted to verified users in the institutional directory: ').$chgtext.'
    • '; } else { $resulttext .= '
    • '.&mt('There are now no ID formats restricted to verified users in the institutional directory.').'
    • '; } } if (ref($changes{'email_rule'}) eq 'ARRAY') { my ($emailrules,$emailruleorder) = &Apache::lonnet::inst_userrules($dom,'email'); my $chgtext = '
        '; foreach my $type (@email_rule) { if (ref($emailrules->{$type}) eq 'HASH') { $chgtext .= '
      • '.$emailrules->{$type}{'name'}.'
      • '; } } $chgtext .= '
      '; if (@email_rule > 0) { $resulttext .= '
    • '.&mt('Accounts may not be created by users self-enrolling with e-mail addresses of the following types: ').$chgtext.'
    • '; } else { $resulttext .= '
    • '.&mt('There are now no restrictions on e-mail addresses which may be used as a username when self-enrolling.').'
    • '; } } my %authname = &authtype_names(); my %context_title = &context_names(); if (ref($changes{'authtypes'}) eq 'ARRAY') { my $chgtext = '
        '; foreach my $type (@{$changes{'authtypes'}}) { my @allowed; $chgtext .= '
      • '.$context_title{$type}.' - '.&mt('assignable authentication types: '); foreach my $auth (@authtypes) { if ($authhash{$type}{$auth}) { push(@allowed,$authname{$auth}); } } if (@allowed > 0) { $chgtext .= join(', ',@allowed).'
      • '; } else { $chgtext .= &mt('none').''; } } $chgtext .= '
      '; $resulttext .= '
    • '.&mt('Authentication types available for assignment to new users').'
      '.$chgtext; $resulttext .= '
    • '; } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to user creation settings'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } if ($warningmsg ne '') { $resulttext .= '
    '.$warningmsg.'
    '; } return $resulttext; } sub modify_usermodification { my ($dom,%domconfig) = @_; my ($resulttext,%curr_usermodification,%changes); if (ref($domconfig{'usermodification'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'usermodification'}})) { $curr_usermodification{$key} = $domconfig{'usermodification'}{$key}; } } my @contexts = ('author','course'); my %context_title = ( author => 'In author context', course => 'In course context', ); my @fields = ('lastname','firstname','middlename','generation', 'permanentemail','id'); my %roles = ( author => ['ca','aa'], course => ['st','ep','ta','in','cr'], ); my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); my %modifyhash; foreach my $context (@contexts) { foreach my $role (@{$roles{$context}}) { my @modifiable = &Apache::loncommon::get_env_multiple('form.canmodify_'.$role); foreach my $item (@fields) { if (grep(/^\Q$item\E$/,@modifiable)) { $modifyhash{$context}{$role}{$item} = 1; } else { $modifyhash{$context}{$role}{$item} = 0; } } } if (ref($curr_usermodification{$context}) eq 'HASH') { foreach my $role (@{$roles{$context}}) { if (ref($curr_usermodification{$context}{$role}) eq 'HASH') { foreach my $field (@fields) { if ($modifyhash{$context}{$role}{$field} ne $curr_usermodification{$context}{$role}{$field}) { push(@{$changes{$context}},$role); last; } } } } } else { foreach my $context (@contexts) { foreach my $role (@{$roles{$context}}) { push(@{$changes{$context}},$role); } } } } my %usermodification_hash = ( usermodification => \%modifyhash, ); my $putresult = &Apache::lonnet::put_dom('configuration', \%usermodification_hash,$dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made: ').'
      '; foreach my $context (@contexts) { if (ref($changes{$context}) eq 'ARRAY') { $resulttext .= '
    • '.$context_title{$context}.':
        '; if (ref($changes{$context}) eq 'ARRAY') { foreach my $role (@{$changes{$context}}) { my $rolename; if ($role eq 'cr') { $rolename = &mt('Custom'); } else { $rolename = &Apache::lonnet::plaintext($role); } my @modifiable; $resulttext .= '
      • '.&mt('Target user with [_1] role',$rolename).' - '.&mt('modifiable fields: '); foreach my $field (@fields) { if ($modifyhash{$context}{$role}{$field}) { push(@modifiable,$fieldtitles{$field}); } } if (@modifiable > 0) { $resulttext .= join(', ',@modifiable); } else { $resulttext .= &mt('none'); } $resulttext .= '
      • '; } $resulttext .= '
    • '; } } } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to user modification settings'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } return $resulttext; } sub modify_defaults { my ($dom,$r) = @_; my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors); my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); my @items = ('auth_def','auth_arg_def','lang_def'); my @authtypes = ('internal','krb4','krb5','localauth'); foreach my $item (@items) { $newvalues{$item} = $env{'form.'.$item}; if ($item eq 'auth_def') { if ($newvalues{$item} ne '') { if (!grep(/^\Q$newvalues{$item}\E$/,@authtypes)) { push(@errors,$item); } } } elsif ($item eq 'lang_def') { if ($newvalues{$item} ne '') { if ($newvalues{$item} =~ /^(\w+)/) { my $langcode = $1; if (code2language($langcode) eq '') { push(@errors,$item); } } else { push(@errors,$item); } } } if (grep(/^\Q$item\E$/,@errors)) { $newvalues{$item} = $domdefaults{$item}; } elsif ($domdefaults{$item} ne $newvalues{$item}) { $changes{$item} = 1; } } my %defaults_hash = ( defaults => { auth_def => $newvalues{'auth_def'}, auth_arg_def => $newvalues{'auth_arg_def'}, lang_def => $newvalues{'lang_def'}, } ); my $title = &defaults_titles(); my $putresult = &Apache::lonnet::put_dom('configuration',\%defaults_hash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; my $version = $r->dir_config('lonVersion'); my $mailmsgtext = "Changes made to domain settings in a LON-CAPA installation - domain: $dom (running version: $version) - dns_domain.tab needs to be updated with the following changes, to support legacy 2.4, 2.5 and 2.6 versions of LON-CAPA.\n\n"; foreach my $item (sort(keys(%changes))) { my $value = $env{'form.'.$item}; if ($value eq '') { $value = &mt('none'); } elsif ($item eq 'auth_def') { my %authnames = &authtype_names(); my %shortauth = ( internal => 'int', krb4 => 'krb4', krb5 => 'krb5', localauth => 'loc', ); $value = $authnames{$shortauth{$value}}; } $resulttext .= '
    • '.&mt('[_1] set to "[_2]"',$title->{$item},$value).'
    • '; $mailmsgtext .= "$title->{$item} set to $value\n"; } $resulttext .= '
    '; $mailmsgtext .= "\n"; my $cachetime = 24*60*60; &Apache::lonnet::do_cache_new('domdefaults',$dom, $defaults_hash{'defaults'},$cachetime); my $sysmail = $r->dir_config('lonSysEMail'); &Apache::lonmsg::sendemail($sysmail,"LON-CAPA Domain Settings Change - $dom",$mailmsgtext); } else { $resulttext = &mt('No changes made to default authentication/language settings'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } if (@errors > 0) { $resulttext .= '
    '.&mt('The following were left unchanged because the values entered were invalid:'); foreach my $item (@errors) { $resulttext .= ' "'.$title->{$item}.'",'; } $resulttext =~ s/,$//; } return $resulttext; } sub modify_scantron { my ($r,$dom,$confname,%domconfig) = @_; my ($resulttext,%confhash,%changes,$errors); my $custom = 'custom.tab'; my $default = 'default.tab'; my $servadm = $r->dir_config('lonAdmEMail'); my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm); if ($env{'form.scantronformat.filename'} ne '') { my $error; if ($configuserok eq 'ok') { if ($switchserver) { $error = &mt("Upload of scantron format file is not permitted to this server: [_1]",$switchserver); } else { if ($author_ok eq 'ok') { my ($result,$scantronurl) = &publishlogo($r,'upload','scantronformat',$dom, $confname,'scantron','','',$custom); if ($result eq 'ok') { $confhash{'scantron'}{'scantronformat'} = $scantronurl; $changes{'scantronformat'} = 1; } else { $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$custom,$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].",$custom,$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].",$custom,$confname,$dom,$configuserok); } if ($error) { &Apache::lonnet::logthis($error); $errors .= '
  • '.$error.'
  • '; } } if (ref($domconfig{'scantron'}) eq 'HASH') { if ($domconfig{'scantron'}{'scantronformat'} ne '') { if ($env{'form.scantronformat_del'}) { $confhash{'scantron'}{'scantronformat'} = ''; $changes{'scantronformat'} = 1; } } } if (keys(%confhash) > 0) { my $putresult = &Apache::lonnet::put_dom('configuration',\%confhash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { if (ref($confhash{'scantron'}) eq 'HASH') { $resulttext = &mt('Changes made:').'
      '; if ($confhash{'scantron'}{'scantronformat'} eq '') { $resulttext .= '
    • '.&mt('[_1] scantron format file removed; [_2] file will be used for courses in this domain.',$custom,$default).'
    • '; } else { $resulttext .= '
    • '.&mt('Custom scantron format file ([_1]) uploaded for use with courses in this domain.',$custom).'
    • '; } $resulttext .= '
    '; } else { $resulttext = &mt('Changes made to scantron format file.'); } $resulttext .= ''; &Apache::loncommon::devalidate_domconfig_cache($dom); } else { $resulttext = &mt('No changes made to scantron format file'); } } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } } else { $resulttext = &mt('No changes made to scantron format file'); } if ($errors) { $resulttext .= &mt('The following errors occurred: ').'
      '. $errors.'
    '; } return $resulttext; } sub modify_coursecategories { my ($dom,%domconfig) = @_; my ($resulttext,%deletions,%reorderings,%needreordering,%adds,$errors); my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory'); if (($domconfig{'coursecategories'}{'instcode::0'} ne '') && ($env{'form.instcode'} == 0)) { push (@deletecategory,'instcode::0'); } my (@predelcats,@predeltrails,%predelallitems); if (ref($domconfig{'coursecategories'}) eq 'HASH') { if (@deletecategory > 0) { #FIXME Need to remove category from all courses using a deleted category &extract_categories($domconfig{'coursecategories'},\@predelcats,\@predeltrails,\%predelallitems); foreach my $item (@deletecategory) { if ($domconfig{'coursecategories'}{$item} ne '') { delete($domconfig{'coursecategories'}{$item}); $deletions{$item} = 1; &recurse_cat_deletes($item,$domconfig{'coursecategories'}, \%deletions); } } } foreach my $item (keys(%{$domconfig{'coursecategories'}})) { my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item); if ($domconfig{'coursecategories'}{$item} ne $env{'form.'.$item}) { $reorderings{$item} = 1; $domconfig{'coursecategories'}{$item} = $env{'form.'.$item}; } if ($env{'form.addcategory_name_'.$item} ne '') { my $newcat = $env{'form.addcategory_name_'.$item}; my $newdepth = $depth+1; my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth; $domconfig{'coursecategories'}{$newitem} = $env{'form.addcategory_pos_'.$item}; $adds{$newitem} = 1; } if ($env{'form.subcat_'.$item} ne '') { my $newcat = $env{'form.subcat_'.$item}; my $newdepth = $depth+1; my $newitem = &escape($newcat).':'.&escape($cat).':'.$newdepth; $domconfig{'coursecategories'}{$newitem} = 0; $adds{$newitem} = 1; } } } if ($env{'form.instcode'} eq '1') { if (ref($domconfig{'coursecategories'}) eq 'HASH') { my $newitem = 'instcode::0'; if ($domconfig{'coursecategories'}{$newitem} eq '') { $domconfig{'coursecategories'}{$newitem} = $env{'form.instcode_pos'}; $adds{$newitem} = 1; } } else { my $newitem = 'instcode::0'; $domconfig{'coursecategories'}{$newitem} = $env{'form.instcode_pos'}; $adds{$newitem} = 1; } } if ($env{'form.addcategory_name'} ne '') { my $newitem = &escape($env{'form.addcategory_name'}).'::0'; $domconfig{'coursecategories'}{$newitem} = $env{'form.addcategory_pos'}; $adds{$newitem} = 1; } if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) { my %sort_by_deltrail; if (keys(%deletions) > 0) { foreach my $key (keys(%deletions)) { if ($predelallitems{$key} ne '') { $sort_by_deltrail{$predelallitems{$key}} = $predeltrails[$predelallitems{$key}]; } } } my (@chkcats,@chktrails,%chkallitems); &extract_categories($domconfig{'coursecategories'},\@chkcats,\@chktrails,\%chkallitems); if (ref($chkcats[0]) eq 'ARRAY') { my $depth = 0; my $chg = 0; for (my $i=0; $i<@{$chkcats[0]}; $i++) { my $name = $chkcats[0][$i]; my $item; if ($name eq '') { $chg ++; } else { $item = &escape($name).'::0'; if ($chg) { $domconfig{'coursecategories'}{$item} -= $chg; } $depth ++; &recurse_check(\@chkcats,$domconfig{'coursecategories'},$depth,$name); $depth --; } } } my $putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom); my (@cats,@trails,%allitems); &extract_categories($domconfig{'coursecategories'},\@cats,\@trails,\%allitems); if ($putresult eq 'ok') { $resulttext = &mt('Changes made:').'
      '; if (keys(%deletions) > 0) { $resulttext .= '
    • '.&mt('Deleted categories:').'
        '; foreach my $predeltrail (sort {$a <=> $b } (keys(%sort_by_deltrail))) { $resulttext .= '
      • '.$predeltrails[$predeltrail].'
      • '; } $resulttext .= '
    • '; } if (keys(%reorderings) > 0) { my %sort_by_trail; $resulttext .= '
    • '.&mt('Reordered categories:').'
        '; foreach my $key (keys(%reorderings)) { if ($allitems{$key} ne '') { $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}]; } } foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) { $resulttext .= '
      • '.$trails[$trail].'
      • '; } $resulttext .= '
    • '; } if (keys(%adds) > 0) { my %sort_by_trail; $resulttext .= '
    • '.&mt('Added categories:').'
        '; foreach my $key (keys(%adds)) { if ($allitems{$key} ne '') { $sort_by_trail{$allitems{$key}} = $trails[$allitems{$key}]; } } foreach my $trail (sort {$a <=> $b } (keys(%sort_by_trail))) { $resulttext .= '
      • '.$trails[$trail].'
      • '; } $resulttext .= '
    • '; } $resulttext .= '
    '; } else { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } } else { $resulttext = &mt('No changes made to course categories'); } return $resulttext; } sub recurse_check { my ($chkcats,$categories,$depth,$name) = @_; if (ref($chkcats->[$depth]{$name}) eq 'ARRAY') { my $chg = 0; for (my $j=0; $j<@{$chkcats->[$depth]{$name}}; $j++) { my $category = $chkcats->[$depth]{$name}[$j]; my $item; if ($category eq '') { $chg ++; } else { my $deeper = $depth + 1; $item = &escape($category).':'.&escape($name).':'.$depth; if ($chg) { $categories->{$item} -= $chg; } &recurse_check($chkcats,$categories,$deeper,$category); $deeper --; } } } return; } sub recurse_cat_deletes { my ($item,$coursecategories,$deletions) = @_; my ($deleted,$container,$depth) = map { &unescape($_); } split(/:/,$item); my $subdepth = $depth + 1; if (ref($coursecategories) eq 'HASH') { foreach my $subitem (keys(%{$coursecategories})) { my ($child,$parent,$itemdepth) = map { &unescape($_); } split(/:/,$subitem); if (($parent eq $deleted) && ($itemdepth == $subdepth)) { delete($coursecategories->{$subitem}); $deletions->{$subitem} = 1; &recurse_cat_deletes($subitem,$coursecategories,$deletions); } } } return; } sub gather_categories { my ($categories,$cats,$idx,$jsarray) = @_; my %counters; my $num = 0; foreach my $item (keys(%{$categories})) { my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item); if ($container eq '' && $depth == 0) { $cats->[$depth][$categories->{$item}] = $cat; } else { $cats->[$depth]{$container}[$categories->{$item}] = $cat; } my ($escitem,$tail) = split(/:/,$item,2); if ($counters{$tail} eq '') { $counters{$tail} = $num; $num ++; } if (ref($idx) eq 'HASH') { $idx->{$item} = $counters{$tail}; } if (ref($jsarray) eq 'ARRAY') { push(@{$jsarray->[$counters{$tail}]},$item); } } return; } sub extract_categories { my ($categories,$cats,$trails,$allitems,$idx,$jsarray) = @_; if (ref($categories) eq 'HASH') { &gather_categories($categories,$cats,$idx,$jsarray); if (ref($cats->[0]) eq 'ARRAY') { for (my $i=0; $i<@{$cats->[0]}; $i++) { my $name = $cats->[0][$i]; my $item = &escape($name).'::0'; my $trailstr; if ($name eq 'instcode') { $trailstr = &mt('Official courses (with institutional codes)'); } else { $trailstr = $name; } if ($allitems->{$item} eq '') { push(@{$trails},$trailstr); $allitems->{$item} = scalar(@{$trails})-1; } my @parents = ($name); if (ref($cats->[1]{$name}) eq 'ARRAY') { for (my $j=0; $j<@{$cats->[1]{$name}}; $j++) { my $category = $cats->[1]{$name}[$j]; &recurse_categories($cats,2,$category,$trails,$allitems,\@parents); } } } } } return; } sub recurse_categories { my ($cats,$depth,$category,$trails,$allitems,$parents) = @_; my $shallower = $depth - 1; if (ref($cats->[$depth]{$category}) eq 'ARRAY') { for (my $k=0; $k<@{$cats->[$depth]{$category}}; $k++) { my $name = $cats->[$depth]{$category}[$k]; my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower; my $trailstr = join(' -> ',(@{$parents},$category)); if ($allitems->{$item} eq '') { push(@{$trails},$trailstr); $allitems->{$item} = scalar(@{$trails})-1; } my $deeper = $depth+1; push(@{$parents},$category); &recurse_categories($cats,$deeper,$name,$trails,$allitems,$parents); pop(@{$parents}); } } else { my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower; my $trailstr = join(' -> ',(@{$parents},$category)); if ($allitems->{$item} eq '') { push(@{$trails},$trailstr); $allitems->{$item} = scalar(@{$trails})-1; } } return; } 1;