--- loncom/interface/domainprefs.pm 2007/07/28 21:23:53 1.24 +++ loncom/interface/domainprefs.pm 2010/12/05 21:56:38 1.123.2.3 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.24 2007/07/28 21:23:53 raeburn Exp $ +# $Id: domainprefs.pm,v 1.123.2.3 2010/12/05 21:56:38 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -28,6 +28,131 @@ ############################################################### ############################################################## +=pod + +=head1 NAME + +Apache::domainprefs.pm + +=head1 SYNOPSIS + +Handles configuration of a LON-CAPA domain. + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + + +=head1 OVERVIEW + +Each institution using LON-CAPA will typically have a single domain designated +for use by individuals affliated with the institution. Accordingly, each domain +may define a default set of logos and a color scheme which can be used to "brand" +the LON-CAPA instance. In addition, an institution will typically have a language +and timezone which are used for the majority of courses. + +LON-CAPA provides a mechanism to display and modify these defaults, as well as a +host of other domain-wide settings which determine the types of functionality +available to users and courses in the domain. + +There is also a mechanism to configure cataloging of courses in the domain, and +controls on the operation of automated processes which govern such things as +roster updates, user directory updates and processing of course requests. + +The domain coordination manual which is built dynamically on install/update of +LON-CAPA from the relevant help items provides more information about domain +configuration. + +Most of the domain settings are stored in the configuration.db GDBM file which is +housed on the primary library server for the domain in /home/httpd/lonUsers/$dom, +where $dom is the domain. The configuration.db stores settings in a number of +frozen hashes of hashes. In a few cases, domain information must be uploaded to +the domain as files (e.g., image files for logos etc., or plain text files for +bubblesheet formats). In this case the domainprefs.pm must be running in a user +session hosted on the primary library server in the domain, as these files are +stored in author space belonging to a special $dom-domainconfig user. + +domainprefs.pm in combination with lonconfigsettings.pm will retrieve and display +the current settings, and provides an interface to make modifications. + +=head1 SUBROUTINES + +=over + +=item print_quotas() + +Inputs: 4 + +$dom,$settings,$rowtotal,$action. + +$dom is the domain, $settings is a reference to a hash of current settings for +the current context, $rowtotal is a reference to the scalar used to record the +number of rows displayed on the page, and $action is the context (either quotas +or requestcourses). + +The print_quotas routine was orginally created to display/store information +about default quota sizes for portfolio spaces for the different types of +institutional affiliation in the domain (e.g., Faculty, Staff, Student etc.), +but is now also used to manage availability of user tools: +i.e., blogs, aboutme page, and portfolios, and the course request tool, +used by course owners to request creation of a course. + +Outputs: 1 + +$datatable - HTML containing form elements which allow settings to be changed. + +In the case of course requests, radio buttons are displayed for each institutional +affiliate type (and also default, and _LC_adv) for each of the course types +(official, unofficial and community). In each case the radio buttons allow the +selection of one of four values: + +0, approval, validate, autolimit=N (where N is blank, or a positive integer). +which have the following effects: + +0 + +=over + +- course requests are not allowed for this course types/affiliation + +=back + +approval + +=over + +- course requests must be approved by a Doman Coordinator in the +course's domain + +=back + +validate + +=over + +- an institutional validation (e.g., check requestor is instructor +of record) needs to be passed before the course will be created. The required +validation is in localenroll.pm on the primary library server for the course +domain. + +=back + +autolimit + +=over + +- course requests will be processed autoatically up to a limit of +N requests for the course type for the particular requestor. +If N is undefined, there is no limit to the number of course requests +which a course owner may submit and have processed automatically. + +=back + +=item modify_quotas() + +=back + +=cut + package Apache::domainprefs; use strict; @@ -36,9 +161,15 @@ use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon(); use Apache::lonlocal; -use LONCAPA(); +use Apache::lonmsg(); +use Apache::lonconfigsettings; +use LONCAPA qw(:DEFAULT :match); use LONCAPA::Enrollment; +use LONCAPA::lonauthcgi(); use File::Copy; +use Locale::Language; +use DateTime::TimeZone; +use DateTime::Locale; sub handler { my $r=shift; @@ -48,6 +179,7 @@ sub handler { return OK; } + my $context = 'domain'; my $dom = $env{'request.role.domain'}; my $domdesc = &Apache::lonnet::domain($dom,'description'); if (&Apache::lonnet::allowed('mau',$dom)) { @@ -60,92 +192,182 @@ sub handler { } &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['phase']); - my $phase = "display"; + ['phase','actions']); + 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'],$dom); - my @prefs = ( - { text => 'Default color schemes', - help => 'Default_Color_Schemes', - action => 'rolecolors', - header => [{col1 => 'Student Settings', - col2 => '',}, - {col1 => 'Coordinator Settings', - col2 => '',}, - {col1 => 'Author Settings', - col2 => '',}, - {col1 => 'Administrator Settings', - col2 => '',}], - }, - { text => 'Log-in page options', - help => 'Domain_Log-in_Page', - action => 'login', - header => [{col1 => 'Item', - col2 => '',}], - }, - { text => 'Default quotas for user portfolios', - help => 'Default_User_Quota', - action => 'quotas', - header => [{col1 => 'User type', - col2 => 'Default quota'}], - }, - { text => 'Auto-enrollment settings', - help => 'Domain_Auto_Enrollment', - action => 'autoenroll', - header => [{col1 => 'Configuration setting', - col2 => 'Value(s)'}], - }, - { text => 'Auto-update settings', - help => 'Domain_Auto_Update', - action => 'autoupdate', - header => [{col1 => 'Setting', - col2 => 'Value',}, - {col1 => 'User Population', - col2 => 'Updataeable user data'}], - }, - { text => 'Institutional directory searches', - help => 'Domain_Directory_Search', - action => 'directorysrch', - header => [{col1 => 'Setting', - col2 => 'Value',}], - }, + 'quotas','autoenroll','autoupdate','directorysrch', + 'usercreation','usermodification','contacts','defaults', + 'scantron','coursecategories','serverstatuses', + 'requestcourses','helpsettings','coursedefaults'],$dom); + my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', + 'autoupdate','directorysrch','contacts', + 'usercreation','usermodification','scantron', + 'requestcourses','coursecategories','serverstatuses','helpsettings', + 'coursedefaults'); + my %prefs = ( + 'rolecolors' => + { text => 'Default color schemes', + help => 'Domain_Configuration_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_Configuration_Login_Page', + header => [{col1 => 'Item', + col2 => '',}], + }, + + 'defaults' => + { text => 'Default authentication/language/timezone', + help => 'Domain_Configuration_LangTZAuth', + header => [{col1 => 'Setting', + col2 => 'Value'}], + }, + 'quotas' => + { text => 'User blogs, personal information pages and portfolios', + help => 'Domain_Configuration_Quotas', + header => [{col1 => 'User affiliation', + col2 => 'Available tools', + col3 => 'Portfolio quota',}], + }, + 'autoenroll' => + { text => 'Auto-enrollment settings', + help => 'Domain_Configuration_Auto_Enrollment', + header => [{col1 => 'Configuration setting', + col2 => 'Value(s)'}], + }, + 'autoupdate' => + { text => 'Auto-update settings', + help => 'Domain_Configuration_Auto_Updates', + header => [{col1 => 'Setting', + col2 => 'Value',}, + {col1 => 'User population', + col2 => 'Updataeable user data'}], + }, + 'directorysrch' => + { text => 'Institutional directory searches', + help => 'Domain_Configuration_InstDirectory_Search', + header => [{col1 => 'Setting', + col2 => 'Value',}], + }, + 'contacts' => + { text => 'Contact Information', + help => 'Domain_Configuration_Contact_Info', + header => [{col1 => 'Setting', + col2 => 'Value',}], + }, + + 'usercreation' => + { text => 'User creation', + help => 'Domain_Configuration_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_Configuration_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'}, + {col1 => "Status of user", + col2 => 'Information settable when self-creating account (if directory data blank)'}], + }, + 'scantron' => + { text => 'Bubblesheet format file', + help => 'Domain_Configuration_Scantron_Format', + header => [ {col1 => 'Item', + col2 => '', + }], + }, + 'requestcourses' => + {text => 'Request creation of courses', + help => 'Domain_Configuration_Request_Courses', + header => [{col1 => 'User affiliation', + col2 => 'Availability/Processing of requests',}, + {col1 => 'Setting', + col2 => 'Value'}], + }, + 'coursecategories' => + { text => 'Cataloging of courses/communities', + help => 'Domain_Configuration_Cataloging_Courses', + header => [{col1 => 'Category settings', + col2 => '',}, + {col1 => 'Categories', + col2 => '', + }], + }, + 'serverstatuses' => + {text => 'Access to server status pages', + help => 'Domain_Configuration_Server_Status', + header => [{col1 => 'Status Page', + col2 => 'Other named users', + col3 => 'Specific IPs', + }], + }, + 'helpsettings' => + {text => 'Help page settings', + help => 'Domain_Configuration_Help_Settings', + header => [{col1 => 'Authenticated Help Settings', + col2 => ''}, + {col1 => 'Unauthenticated Help Settings', + col2 => ''}], + }, + 'coursedefaults' => + {text => 'Course/Community defaults', + help => 'Domain_Configuration_Course_Defaults', + header => [{col1 => 'Defaults which can be overridden for each course by a DC', + col2 => 'Value',}], + }, + 'privacy' => + {text => 'User Privacy', + help => 'Domain_Configuration_User_Privacy', + header => [{col1 => 'Setting', + col2 => 'Value',}], + }, ); + my %servers = &dom_servers($dom); + if (keys(%servers) > 1) { + $prefs{'login'} = { text => 'Log-in page options', + help => 'Domain_Configuration_Login_Page', + header => [{col1 => 'Log-in Service', + col2 => 'Server Setting',}, + {col1 => 'Log-in Page Items', + 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,'display')", - text=>"Domain Configuration"}); + ({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,'$phase')", - text=>"Updated"}); - &print_header($r,$phase); - foreach my $item (@prefs) { - $r->print('

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

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

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

'); - } else { - if ($phase eq '') { - $phase = 'display'; - } - my %helphash; - my $numprefs = @prefs; - &print_header($r,$phase); + &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles); + } elsif ($phase eq 'display') { + &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname); + } else { if (keys(%domconfig) == 0) { my $primarylibserv = &Apache::lonnet::domain($dom,'primary'); - my $perlvarref = &LONCAPA::Configuration::read_conf('loncapa.conf'); - my $hostid = $perlvarref->{'lonHostID'}; - if ($hostid ne $primarylibserv) { + 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'); + my @loginimages = ('img','logo','domlogo','login'); my $custom_img_count = 0; foreach my $img (@loginimages) { if ($designhash{$dom.'.login.'.$img} ne '') { @@ -158,31 +380,32 @@ sub handler { } } if ($custom_img_count > 0) { + &Apache::lonconfigsettings::print_header($r,$phase,$context); 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, you will be able to update settings from this screen when logged in to any server in the LON-CAPA network (with a DC role selected in the domain), although you will still need to switch to the domain's primary library server to upload new images or logos.").'

'.$switch_server.' '.&mt('to primary library server for domain: [_1]',$dom)); + $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)); + } + $r->print(&Apache::loncommon::end_page()); return OK; } } } - $r->print(' - -
'); - foreach my $item (@prefs) { - if ($item->{'action'} eq 'login') { - $r->print(' '); - } - &print_config_box($r,$dom,$confname,$phase,$item->{'action'}, - $item,$domconfig{$item->{'action'}}); - } - $r->print(' -
'); - &print_footer($r,$phase,'process','Save changes'); + &Apache::lonconfigsettings::display_choices($r,$phase,$context,\@prefs_order,\%prefs); } return OK; } sub process_changes { - my ($r,$dom,$confname,$action,$roles,%domconfig) = @_; + my ($r,$dom,$confname,$action,$roles,$values) = @_; + my %domconfig; + if (ref($values) eq 'HASH') { + %domconfig = %{$values}; + } my $output; if ($action eq 'login') { $output = &modify_login($r,$dom,$confname,%domconfig); @@ -190,44 +413,89 @@ sub process_changes { $output = &modify_rolecolors($r,$dom,$confname,$roles, %domconfig); } elsif ($action eq 'quotas') { - $output = &modify_quotas($dom,%domconfig); + $output = &modify_quotas($dom,$action,%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); + } elsif ($action eq 'serverstatuses') { + $output = &modify_serverstatuses($dom,%domconfig); + } elsif ($action eq 'requestcourses') { + $output = &modify_quotas($dom,$action,%domconfig); + } elsif ($action eq 'helpsettings') { + $output = &modify_helpsettings($r,$dom,$confname,%domconfig); + } elsif ($action eq 'coursedefaults') { + $output = &modify_coursedefaults($dom,%domconfig); } return $output; } sub print_config_box { my ($r,$dom,$confname,$phase,$action,$item,$settings) = @_; - $r->print(' - + 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 -# -# '); - if (($action eq 'autoupdate') || ($action eq 'rolecolors')) { - my $colspan = ($action eq 'rolecolors')?' colspan="2"':''; - $r->print(' + '."\n". + ''; + $rowtotal ++; + my $numheaders = 1; + if (ref($item->{'header'}) eq 'ARRAY') { + $numheaders = scalar(@{$item->{'header'}}); + } + if ($numheaders > 1) { + my $colspan = ''; + if (($action eq 'rolecolors') || ($action eq 'coursecategories') || ($action eq 'helpsettings')) { + $colspan = ' colspan="2"'; + } + $output .= ' @@ -235,13 +503,50 @@ sub print_config_box { + + + + + + @@ -249,10 +554,12 @@ sub print_config_box { @@ -260,95 +567,144 @@ sub print_config_box {
'.&mt($item->{text}).' 
'.&mt($item->{text}).' '. -# &Apache::loncommon::help_open_topic($item->{'help'}).'
'. + &mt($item->{text}).' '. + &Apache::loncommon::help_open_topic($item->{'help'}).'
- - - '); + + + '; + $rowtotal ++; if ($action eq 'autoupdate') { - $r->print(&print_autoupdate('top',$dom,$settings)); - } else { - $r->print(&print_rolecolors($phase,'student',$dom,$confname,$settings)); + $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); + } elsif ($action eq 'coursecategories') { + $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal); + } elsif ($action eq 'login') { + $output .= &print_login('top',$dom,$confname,$phase,$settings,\$rowtotal); + $colspan = ' colspan="2"'; + } elsif ($action eq 'requestcourses') { + $output .= &print_quotas($dom,$settings,\$rowtotal,$action); + } elsif ($action eq 'helpsettings') { + $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'rolecolors') { + $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal); } - $r->print(' + $output .= '
'.$item->{'header'}->[0]->{'col1'}.''.$item->{'header'}->[0]->{'col2'}.'
'.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col2'}).'
- - - '); + '; + $output .= ' + + '; + $rowtotal ++; if ($action eq 'autoupdate') { - $r->print(&print_autoupdate('bottom',$dom,$settings)); - } else { - $r->print(&print_rolecolors($phase,'coordinator',$dom,$confname,$settings).' + $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'}.'
'.&mt($item->{'header'}->[1]->{'col1'}).''.&mt($item->{'header'}->[1]->{'col2'}).'
+
+ + + + '. + &print_usercreation('bottom',$dom,$settings,\$rowtotal); + $rowtotal ++; + } elsif ($action eq 'usermodification') { + $output .= &print_usermodification('middle',$dom,$settings,\$rowtotal).' +
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
+
+ + + + '. + + &print_usermodification('bottom',$dom,$settings,\$rowtotal); + $rowtotal ++; + } elsif ($action eq 'coursecategories') { + $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); + } elsif ($action eq 'login') { + $output .= &print_login('bottom',$dom,$confname,$phase,$settings,\$rowtotal); + } elsif ($action eq 'requestcourses') { + $output .= &print_courserequestmail($dom,$settings,\$rowtotal); + } elsif ($action eq 'helpsettings') { + $output .= &print_helpsettings('bottom',$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'rolecolors') { + $output .= &print_rolecolors($phase,'coordinator',$dom,$confname,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
- - + + '. - &print_rolecolors($phase,'author',$dom,$confname,$settings).' + &print_rolecolors($phase,'author',$dom,$confname,$settings,\$rowtotal).'
'.$item->{'header'}->[2]->{'col1'}.''.$item->{'header'}->[2]->{'col2'}.''. + &mt($item->{'header'}->[2]->{'col1'}).''. + &mt($item->{'header'}->[2]->{'col2'}).'
- - + + '. - &print_rolecolors($phase,'admin',$dom,$confname,$settings)); + &print_rolecolors($phase,'admin',$dom,$confname,$settings,\$rowtotal); + $rowtotal += 2; } } else { - $r->print(' + $output .= ' -
'.$item->{'header'}->[3]->{'col1'}.''.$item->{'header'}->[3]->{'col2'}.''.&mt($item->{'header'}->[3]->{'col1'}).''.&mt($item->{'header'}->[3]->{'col2'}).'
- '); + '; if (($action eq 'login') || ($action eq 'directorysrch')) { - $r->print(' - '); + $output .= ' + '; + } elsif ($action eq 'serverstatuses') { + $output .= ' + '; + } else { - $r->print(' - '); + $output .= ' + '; } - $r->print(' - - '); + if (defined($item->{'header'}->[0]->{'col3'})) { + $output .= ''; + if ($item->{'header'}->[0]->{'col3'}) { + $output .= ''; + } + $output .= ''; + $rowtotal ++; if ($action eq 'login') { - $r->print(&print_login($dom,$confname,$phase,$settings)); + $output .= &print_login('bottom',$dom,$confname,$phase,$settings, + \$rowtotal); } elsif ($action eq 'quotas') { - $r->print(&print_quotas($dom,$settings)); + $output .= &print_quotas($dom,$settings,\$rowtotal,$action); } elsif ($action eq 'autoenroll') { - $r->print(&print_autoenroll($dom,$settings)); + $output .= &print_autoenroll($dom,$settings,\$rowtotal); } elsif ($action eq 'directorysrch') { - $r->print(&print_directorysrch($dom,$settings)); - } + $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 'serverstatuses') { + $output .= &print_serverstatuses($dom,$settings,\$rowtotal); + } elsif ($action eq 'helpsettings') { + $output .= &print_helpsettings('top',$dom,$confname,$settings,\$rowtotal); + } elsif ($action eq 'coursedefaults') { + $output .= &print_coursedefaults($dom,$settings,\$rowtotal); + } } - $r->print(' + $output .= '
'.$item->{'header'}->[0]->{'col1'}.''.&mt($item->{'header'}->[0]->{'col1'}).''.&mt($item->{'header'}->[0]->{'col1'}). + '
('.&mt('Automatic access for Dom. Coords.').')
'.$item->{'header'}->[0]->{'col1'}.''.&mt($item->{'header'}->[0]->{'col1'}).''.$item->{'header'}->[0]->{'col2'}.'
'. + &mt($item->{'header'}->[0]->{'col2'}); + if ($action eq 'serverstatuses') { + $output .= '
('.&mt('user1:domain1,user2:domain2 etc.').')'; + } + } else { + $output .= '
'. + &mt($item->{'header'}->[0]->{'col2'}); + } + $output .= ''. + &mt($item->{'header'}->[0]->{'col3'}); + if ($action eq 'serverstatuses') { + $output .= '
('.&mt('IP1,IP2 etc.').')'; + } + $output .= '

'); - return; +

'; + return ($output,$rowtotal); } -sub print_header { - my ($r,$phase) = @_; - my $js = ' - -'; - $r->print(&Apache::loncommon::start_page('View/Modify Domain Settings', - $js)); - $r->print(&Apache::lonhtmlcommon::breadcrumbs('Domain Settings')); - $r->print(' -
- - - -
-'); - $r->print('
'); - return; -} +sub print_login { + my ($position,$dom,$confname,$phase,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + my %choices = &login_choices(); + my $itemcount = 1; -sub print_footer { - my ($r,$phase,$newphase,$button_text) = @_; - $button_text = &mt($button_text); - $r->print(''); - my $dest='"javascript:changePage(document.'.$phase.','."'$newphase'".')"'; - if ($phase eq 'process') { - $r->print(''.$button_text.''); - } else { - $r->print(''); + if ($position eq 'top') { + my %servers = &dom_servers($dom); + my $choice = $choices{'disallowlogin'}; + $css_class = ' class="LC_odd_row"'; + $datatable .= ''.$choices{'disallowlogin'}.''. + ''. + ''."\n"; + my %disallowed; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'loginvia'}) eq 'HASH') { + %disallowed = %{$settings->{'loginvia'}}; + } + } + foreach my $lonhost (sort(keys(%servers))) { + my $direct = 'selected="selected"'; + if ($disallowed{$lonhost} eq '') { + $direct = ''; + } + $datatable .= ''. + ''; + } + $datatable .= '
'.$choices{'hostid'}.''.$choices{'serverurl'}.'
'.$servers{$lonhost}.'
'; + return $datatable; } - $r->print(''); - $r->print('
'.&Apache::loncommon::end_page()); - return; -} -sub print_login { - my ($dom,$confname,$phase,$settings) = @_; - my %choices = &login_choices(); - my ($catalogon,$catalogoff,$adminmailon,$adminmailoff); - $catalogon = ' checked="checked" '; - $adminmailoff = ' checked="checked" '; - my @images = ('img','logo','domlogo'); + 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); @@ -359,27 +715,44 @@ sub print_login { ); foreach my $item (@images) { $defaults{$item} = $defaultdesign{'login.'.$item}; + $defaults{'showlogo'}{$item} = 1; } 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') { - if ($settings->{'coursecatalog'} eq '0') { - $catalogoff = $catalogon; - $catalogon = ' '; - } - if ($settings->{'adminmail'} eq '1') { - $adminmailon = $adminmailoff; - $adminmailoff = ' '; + 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 '') { + if (defined($settings->{$item})) { $designs{$item} = $settings->{$item}; $is_custom{$item} = 1; } + if (defined($settings->{'showlogo'}{$item})) { + $designs{'showlogo'}{$item} = $settings->{'showlogo'}{$item}; + } + } + 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'}; @@ -423,28 +796,23 @@ sub print_login { } my %alt_text = &Apache::lonlocal::texthash ( img => 'Log-in banner', logo => 'Institution Logo', - domlogo => 'Domain Logo'); + domlogo => 'Domain Logo', + login => 'Login box'); my $itemcount = 1; - my $css_class = $itemcount%2?' class="LC_odd_row"':''; - my $datatable = - ''.$choices{'coursecatalog'}. - ''. - ' '. - ''. - ''; - $itemcount ++; - $css_class = $itemcount%2?' class="LC_odd_row"':''; - $datatable .= ''. - ''.$choices{'adminmail'}.''. - ''. - ' '. - ''; - $itemcount ++; - $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text); + my ($css_class,$datatable); + foreach my $item (@toggles) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''.$choices{$item}. + ''. + ' '. + ''; + $itemcount ++; + } + $datatable .= &display_color_options($dom,$confname,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text,$rowtotal,\@logintext,$loginheader); $datatable .= ''; return $datatable; } @@ -452,26 +820,34 @@ sub print_login { sub login_choices { my %choices = &Apache::lonlocal::texthash ( - coursecatalog => 'Display Course Catalog link?', - adminmail => "Display Administrator's E-mail Address?", - img => "Header", - logo => "Main Logo", - domlogo => "Domain Logo", - 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", + coursecatalog => 'Display Course/Community Catalog link?', + adminmail => "Display Administrator's E-mail Address?", + disallowlogin => "Login page requests redirected", + hostid => "Server", + serverurl => "Redirect to log-in via:", + directlogin => "No redirect", + 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 => "Header", + mainbg => "Page", + sidebg => "Login box", + link => "Link", + alink => "Active link", + vlink => "Visited link", ); return %choices; } sub print_rolecolors { - my ($phase,$role,$dom,$confname,$settings) = @_; + my ($phase,$role,$dom,$confname,$settings,$rowtotal) = @_; my %choices = &color_font_choices(); my @bgs = ('pgbg','tabbg','sidebg'); my @links = ('link','alink','vlink'); @@ -483,6 +859,7 @@ sub print_rolecolors { my %defaults = ( img => $defaultdesign{$role.'.img'}, font => $defaultdesign{$role.'.font'}, + fontmenu => $defaultdesign{$role.'.fontmenu'}, ); foreach my $item (@bgs) { $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; @@ -500,6 +877,10 @@ sub print_rolecolors { $designs{'font'} = $settings->{$role}->{'font'}; $is_custom{'font'} = 1; } + if ($settings->{$role}->{'fontmenu'} ne '') { + $designs{'fontmenu'} = $settings->{$role}->{'fontmenu'}; + $is_custom{'fontmenu'} = 1; + } foreach my $item (@bgs) { if ($settings->{$role}->{$item} ne '') { $designs{'bgs'}{$item} = $settings->{$role}->{$item}; @@ -518,6 +899,10 @@ sub print_rolecolors { $designs{img} = $designhash{$dom.'.'.$role.'.img'}; $is_custom{'img'} = 1; } + if ($designhash{$dom.'.'.$role.'.fontmenu'} ne '') { + $designs{fontmenu} = $designhash{$dom.'.'.$role.'.fontmenu'}; + $is_custom{'fontmenu'} = 1; + } if ($designhash{$dom.'.'.$role.'.font'} ne '') { $designs{font} = $designhash{$dom.'.'.$role.'.font'}; $is_custom{'font'} = 1; @@ -537,19 +922,19 @@ sub print_rolecolors { } } my $itemcount = 1; - my $datatable = &display_color_options($dom,$confname,$phase,$role,$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text); + 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) = @_; + $images,$bgs,$links,$alt_text,$rowtotal,$logintext,$loginheader) = @_; my $css_class = $itemcount%2?' class="LC_odd_row"':''; - my $datatable = ''. + my $datatable = ''. ''.$choices->{'font'}.''; if (!$is_custom->{'font'}) { - $datatable .= ''.&mt('Default in use:').' '.$defaults->{'font'}.''; + $datatable .= ''.&mt('Default in use:').' '.$defaults->{'font'}.''; } else { $datatable .= ' '; } @@ -557,14 +942,45 @@ sub display_color_options { $datatable .= ''. ' '.$fontlink. + '    '. ''; + unless ($role eq 'login') { + $datatable .= ''. + ''.$choices->{'fontmenu'}.''; + if (!$is_custom->{'fontmenu'}) { + $datatable .= ''.&mt('Default in use:').' '.$defaults->{'fontmenu'}.''; + } else { + $datatable .= ' '; + } + $fontlink = &color_pick($phase,$role,'fontmenu',$choices->{'fontmenu'},$designs->{'fontmenu'}); + $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); + ''.$choices->{$img}; + my ($imgfile,$img_import,$login_hdr_pick,$logincolors); + if ($role eq 'login') { + 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); + } elsif ($img ne 'domlogo') { + $datatable.= &logo_display_options($img,$defaults,$designs); + } + } + $datatable .= ''; if ($designs->{$img} ne '') { $imgfile = $designs->{$img}; $img_import = ($imgfile =~ m{^/adm/}); @@ -611,25 +1027,32 @@ sub display_color_options { } } if ($showfile) { - $showfile = &Apache::loncommon::lonhttpdurl($showfile); - $fullsize = &Apache::loncommon::lonhttpdurl($imgfile); - $datatable.= ''; - if (!$is_custom->{$img}) { - $datatable .= &mt('Default in use:').'
'; + 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 ($img_import) { - $datatable.= ''; - } - $datatable.= ''.$alt_text->{$img}.
-                             ''; - if ($is_custom->{$img}) { - $datatable.=' '.&mt('Replace:').'
'; - } else { - $datatable.=''.&mt('Upload:').'
'; + 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:'); @@ -652,7 +1075,7 @@ sub display_color_options { my $bgs_def; foreach my $item (@{$bgs}) { if (!$is_custom->{$item}) { - $bgs_def .= ''.$choices->{$item}.'
'.$defaults->{'bgs'}{$item}.''; + $bgs_def .= ''.$choices->{$item}.'    
'.$defaults->{'bgs'}{$item}.''; } } if ($bgs_def) { @@ -666,10 +1089,10 @@ sub display_color_options { my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item}); $datatable .= ''.$link; if ($designs->{'bgs'}{$item}) { - $datatable .= ' '; + $datatable .= '    '; } $datatable .= '
'; + '" onblur = "javascript:colchg_span('."'css_".$role.'_'.$item."'".',this);" />'; } $datatable .= ''; $itemcount ++; @@ -679,7 +1102,7 @@ sub display_color_options { my $links_def; foreach my $item (@{$links}) { if (!$is_custom->{$item}) { - $links_def .= ''.$choices->{$item}.'
'.$defaults->{'links'}{$item}.''; + $links_def .= ''.$choices->{$item}.'
'.$defaults->{'links'}{$item}.''; } } if ($links_def) { @@ -690,93 +1113,538 @@ sub display_color_options { $datatable .= ''. ''; foreach my $item (@{$links}) { - $datatable .= ''; } + $$rowtotal += $itemcount; return $datatable; } -sub color_pick { - my ($phase,$role,$item,$desc,$curcol) = @_; - my $link = ''.$desc.''; - return $link; +sub logo_display_options { + my ($img,$defaults,$designs) = @_; + my $checkedon; + if (ref($defaults) eq 'HASH') { + if (ref($defaults->{'showlogo'}) eq 'HASH') { + if ($defaults->{'showlogo'}{$img}) { + $checkedon = 'checked="checked" '; + } + } + } + if (ref($designs) eq 'HASH') { + if (ref($designs->{'showlogo'}) eq 'HASH') { + if (defined($designs->{'showlogo'}{$img})) { + if ($designs->{'showlogo'}{$img} == 0) { + $checkedon = ''; + } elsif ($designs->{'showlogo'}{$img} == 1) { + $checkedon = 'checked="checked" '; + } + } + } + } + return '
'."\n"; } -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(); +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; +} - $pjump_def +sub login_text_colors { + my ($img,$role,$logintext,$phase,$choices,$designs) = @_; + my $color_menu = '
'; - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'links'}{$item}); + $datatable .= ''."\n". + &color_pick($phase,$role,$item,$choices->{$item}, + $designs->{'links'}{$item}); if ($designs->{'links'}{$item}) { - $datatable.=''. - $link.''; - } else { - $datatable .= $link; + $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; +} - 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;'); - } +sub image_changes { + my ($is_custom,$alt_text,$img_import,$showfile,$fullsize,$role,$img,$imgfile,$logincolors) = @_; + my $output; + if (!$is_custom) { + if ($img ne 'domlogo') { + $output .= &mt('Default image:').'
'; } else { - document.parmform.pres_value.value=''; - document.parmform.pres_marker.value=''; + $output .= &mt('Default in use:').'
'; } } -ENDCOL + 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 print_quotas { - my ($dom,$settings) = @_; - my $datatable; - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($dom,$settings,$rowtotal,$action) = @_; + my $context; + if ($action eq 'quotas') { + $context = 'tools'; + } else { + $context = $action; + } + my ($datatable,$defaultquota,@usertools,@options,%validations); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; - my $css_class; - if (@{$types} > 0) { + my ($css_class,%titles); + if ($context eq 'requestcourses') { + @usertools = ('official','unofficial','community'); + @options =('norequest','approval','validate','autolimit'); + %validations = &Apache::lonnet::auto_courserequest_checks($dom); + %titles = &courserequest_titles(); + } else { + @usertools = ('aboutme','blog','portfolio'); + %titles = &tool_titles(); + } + if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { + my $currdefquota; + unless ($context eq 'requestcourses') { + if (ref($settings) eq 'HASH') { + if (ref($settings->{defaultquota}) eq 'HASH') { + $currdefquota = $settings->{defaultquota}->{$type}; + } else { + $currdefquota = $settings->{$type}; + } + } + } if (defined($usertypes->{$type})) { $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; - $datatable .= ''. + $datatable .= ''. ''.$usertypes->{$type}.''. + ''; + if ($context eq 'requestcourses') { + $datatable .= ''; + } + my %cell; + foreach my $item (@usertools) { + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + $curroption = $settings->{$item}->{$type}; + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + } + } + } + if (!$curroption) { + $curroption = 'norequest'; + } + $datatable .= ''; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{$type}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $cell{$item} .= ' '; + if ($option eq 'autolimit') { + $cell{$item} .= ''; + } + $cell{$item} .= '  '; + if ($option eq 'autolimit') { + $cell{$item} .= $titles{'unlimited'} + } + } + } else { + my $checked = 'checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + if ($settings->{$item}->{$type} == 0) { + $checked = ''; + } elsif ($settings->{$item}->{$type} == 1) { + $checked = 'checked="checked" '; + } + } + } + $datatable .= '  '; + } + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'.$titles{$item}.'
'.$cell{$item}.'
'; + } + $datatable .= ''; + unless ($context eq 'requestcourses') { + $datatable .= ''. ' Mb'; + '" value="'.$currdefquota. + '" size="5" /> Mb'; + } + $datatable .= ''; } } } - my $defaultquota = '20'; - if (ref($settings) eq 'HASH') { - if (defined($settings->{'default'})) { - $defaultquota = $settings->{'default'}; + unless ($context eq 'requestcourses') { + $defaultquota = '20'; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'defaultquota'}) eq 'HASH') { + $defaultquota = $settings->{'defaultquota'}->{'default'}; + } elsif (defined($settings->{'default'})) { + $defaultquota = $settings->{'default'}; + } } } $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. - ''.&mt($othertitle).''. - ''. - ' Mb'; + ''.$othertitle.''. + ''; + if ($context eq 'requestcourses') { + $datatable .= ''; + } + my %defcell; + foreach my $item (@usertools) { + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + $curroption = $settings->{$item}->{'default'}; + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + } + } + } + if (!$curroption) { + $curroption = 'norequest'; + } + $datatable .= ''; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{'default'}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($option eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $defcell{$item} .= ''; + if ($option eq 'autolimit') { + $defcell{$item} .= ''; + } + $defcell{$item} .= '  '; + if ($option eq 'autolimit') { + $defcell{$item} .= $titles{'unlimited'} + } + } + } else { + my $checked = 'checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + if ($settings->{$item}->{'default'} == 0) { + $checked = ''; + } elsif ($settings->{$item}->{'default'} == 1) { + $checked = 'checked="checked" '; + } + } + } + $datatable .= '  '; + } + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'.$titles{$item}.'
'.$defcell{$item}.'
'; + } + $datatable .= ''; + unless ($context eq 'requestcourses') { + $datatable .= ''. + ' Mb'; + } + $datatable .= ''; + $typecount ++; + $css_class = $typecount%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''.&mt('LON-CAPA Advanced Users').' '; + if ($context eq 'requestcourses') { + $datatable .= &mt('(overrides affiliation, if set)'). + ''. + ''. + ''; + } else { + $datatable .= &mt('(overrides affiliation, if checked)'). + ''. + ''; + my $checked = ''; + if ($curroption eq '') { + $checked = ' checked="checked"'; + } + $advcell{$item} .= '  '; + foreach my $option (@options) { + my $val = $option; + if ($option eq 'norequest') { + $val = 0; + } + if ($option eq 'validate') { + my $canvalidate = 0; + if (ref($validations{$item}) eq 'HASH') { + if ($validations{$item}{'_LC_adv'}) { + $canvalidate = 1; + } + } + next if (!$canvalidate); + } + my $checked = ''; + if ($val eq $curroption) { + $checked = ' checked="checked"'; + } elsif ($option eq 'autolimit') { + if ($curroption =~ /^autolimit/) { + $checked = ' checked="checked"'; + } + } + $advcell{$item} .= ''; + if ($option eq 'autolimit') { + $advcell{$item} .= ''; + } + $advcell{$item} .= '  '; + if ($option eq 'autolimit') { + $advcell{$item} .= $titles{'unlimited'} + } + } + } else { + my $checked = 'checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + if ($settings->{$item}->{'_LC_adv'} == 0) { + $checked = ''; + } elsif ($settings->{$item}->{'_LC_adv'} == 1) { + $checked = 'checked="checked" '; + } + } + } + $datatable .= '  '; + } + } + if ($context eq 'requestcourses') { + $datatable .= ''; + foreach my $item (@usertools) { + $datatable .= ''; + } + $datatable .= '
'. + '
'; + } + my %advcell; + foreach my $item (@usertools) { + if ($context eq 'requestcourses') { + my ($curroption,$currlimit); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$item}) eq 'HASH') { + $curroption = $settings->{$item}->{'_LC_adv'}; + if ($curroption =~ /^autolimit=(\d*)$/) { + $currlimit = $1; + } + } + } + $datatable .= '
'.$titles{$item}.'
'.$advcell{$item}.'
'; + } + $datatable .= ''; + $$rowtotal += $typecount; + return $datatable; +} + +sub print_courserequestmail { + my ($dom,$settings,$rowtotal) = @_; + my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows); + $now = time; + $rows = 0; + %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now); + foreach my $server (keys(%dompersonnel)) { + foreach my $user (sort(keys(%{$dompersonnel{$server}}))) { + my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); + if (!grep(/^$uname:$udom$/,@domcoord)) { + push(@domcoord,$uname.':'.$udom); + } + } + } + if (ref($settings) eq 'HASH') { + if (ref($settings->{'notify'}) eq 'HASH') { + if ($settings->{'notify'}{'approval'} ne '') { + @currapproval = split(',',$settings->{'notify'}{'approval'}); + } + } + } + if (@currapproval) { + foreach my $dc (@currapproval) { + unless (grep(/^\Q$dc\E$/,@domcoord)) { + push(@domcoord,$dc); + } + } + } + @domcoord = sort(@domcoord); + my $numinrow = 4; + my $numdc = @domcoord; + my $css_class = 'class="LC_odd_row"'; + $datatable = ''. + ' '.&mt('Receive notification of course requests requiring approval.'). + ' '. + ' '; + if (@domcoord > 0) { + $datatable .= ''; + for (my $i=0; $i<$numdc; $i++) { + my $rem = $i%($numinrow); + if ($rem == 0) { + if ($i > 0) { + $datatable .= ''; + } + $datatable .= ''; + $rows ++; + } + my $check = ' '; + if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) { + $check = ' checked="checked" '; + } + my ($uname,$udom) = split(':',$domcoord[$i]); + my $fullname = &Apache::loncommon::plainname($uname,$udom); + if ($i == $numdc-1) { + my $colsleft = $numinrow-$rem; + if ($colsleft > 1) { + $datatable .= ''; + } + $datatable .= '
'; + } else { + $datatable .= ''; + } + } else { + $datatable .= ''; + } + $datatable .= '
'; + } else { + $datatable .= &mt('There are no active Domain Coordinators'); + $rows ++; + } + $datatable .=''; + $$rowtotal += $rows; return $datatable; } sub print_autoenroll { - my ($dom,$settings) = @_; + my ($dom,$settings,$rowtotal) = @_; my $autorun = &Apache::lonnet::auto_run(undef,$dom), my ($defdom,$runon,$runoff); if (ref($settings) eq 'HASH') { @@ -810,6 +1678,10 @@ sub print_autoenroll { } } 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?').''. ''. ''; + $$rowtotal += 2; } else { - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my @fields = ('lastname','firstname','middlename','gen', 'permanentemail','id'); - 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 %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); my $numrows = 0; - if (@{$types} > 0) { - $datatable = - &usertype_update_row($settings,$usertypes,\%fieldtitles, - \@fields,$types,\$numrows); + 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) = @_; + my ($dom,$settings,$rowtotal) = @_; my $srchon = ' '; my $srchoff = ' checked="checked" '; - my $exacton = ''; - my $containson = ' checked="checked" '; - my $specifyon = ''; + my ($exacton,$containson,$beginson); my $localon = ' '; my $localoff = ' checked="checked" '; if (ref($settings) eq 'HASH') { @@ -909,97 +1777,71 @@ sub print_directorysrch { $localon = $localoff; $localoff = ' '; } - if ($settings->{'searchtypes'} eq 'exact') { - $exacton = $containson; - $containson = ' '; - } - if ($settings->{'searchtypes'} eq 'specify') { - $specifyon = $containson; - $containson = ' '; + 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) = &sorted_inst_types($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $numinrow = 4; + my $cansrchrow = 0; my $datatable=''. - ''.&mt('Directory search available?').''. + ''.&mt('Directory search available?').''. ' '. ''. ''. - ''.&mt('Search latitude').''. - ' '. - ''. - ' '. - ''. - ''.&mt('Other domains can search').''. + ''.&mt('Other domains can search?').''. ' '. ''. - ''. - ''.&mt('Users allowed to search').' ('.$dom.')'. - ''; - for (my $i=0; $i<@{$types}; $i++) { - if (defined($usertypes->{$types->[$i]})) { - my $rem = $i%($numinrow); - if ($rem == 0) { - if ($i > 0) { - $datatable .= ''; - } - $datatable .= ''; - } - my $check = ' '; - if (ref($settings->{'cansearch'}) eq 'ARRAY') { - if (grep(/^\Q$types->[$i]\E$/,@{$settings->{'cansearch'}})) { - $check = ' checked="checked" '; - } - } - $datatable .= ''; + ''; + $$rowtotal += 2; + if (ref($usertypes) eq 'HASH') { + if (keys(%{$usertypes}) > 0) { + $datatable .= &insttypes_row($settings,$types,$usertypes,$dom, + $numinrow,$othertitle,'cansearch'); + $cansrchrow = 1; } } - - my $rem = @{$types}%($numinrow); - my $colsleft = $numinrow - $rem; - if ($colsleft > 1) { - $datatable .= ''; } else { - $datatable .= ''; } - my $defcheck = ' '; - if (ref($settings->{'cansearch'}) eq 'ARRAY') { - if (grep(/^default$/,@{$settings->{'cansearch'}})) { - $defcheck = ' checked="checked" '; - } - } - $datatable .= ''. - '
'. - '
'; + if ($cansrchrow) { + $$rowtotal ++; + $datatable .= '
'; + $datatable .= '
'; - - $datatable .= ''. - ''.&mt('Supported search methods'). - ''; + $datatable .= ''; + $$rowtotal ++; + if ($cansrchrow) { + $datatable .= ''; + } else { + $datatable .= ''; + } + $datatable .= ''. + ''; + $$rowtotal ++; return $datatable; } -sub sorted_inst_types { - my ($dom) = @_; - my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom); - my $othertitle = "All users"; - my @types; - if (ref($order) eq 'ARRAY') { - @types = @{$order}; +sub print_contacts { + my ($dom,$settings,$rowtotal) = @_; + my $datatable; + my @contacts = ('adminemail','supportemail'); + my (%checked,%to,%otheremails); + my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail', + 'requestsmail'); + foreach my $type (@mailings) { + $otheremails{$type} = ''; } - if (@types == 0) { + 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'}; + } + } elsif ($type eq 'lonstatusmail') { + $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; + } + } + } 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" '; + $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; + $checked{'requestsmail'}{'adminemail'} = ' checked="checked" '; + } + my ($titles,$short_titles) = &contact_titles(); + my $rownum = 0; + my $css_class; + foreach my $item (@contacts) { + $rownum ++; + $css_class = $rownum%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''; + } + foreach my $type (@mailings) { + $rownum ++; + $css_class = $rownum%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''. + ''."\n"; + } + $$rowtotal += $rownum; + return $datatable; +} + +sub print_helpsettings { + + my ($position,$dom,$confname,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + + my $switchserver = &check_switchserver($dom,$confname); + + my $itemcount = 1; + + if ($position eq 'top') { + + my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles); + + %choices = + &Apache::lonlocal::texthash ( + submitbugs => 'Display "Submit a bug" link?', + ); + + %defaultchecked = ('submitbugs' => 'on'); + + @toggles = ('submitbugs',); + + 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} = ' '; + } + } + + 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 (@toggles) { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= + ' + + + '. + ''; + $itemcount ++; + } + + } else { + + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + + $datatable .= ''; + + if (ref($settings) eq 'HASH') { + if ($settings->{'loginhelpurl'} ne '') { + my($directory, $filename) = $settings->{'loginhelpurl'} =~ m/(.*\/)(.*)$/; + $datatable .= ''; + $datatable .= '' + } else { + $datatable .= ''; + $datatable .= ''; + } + } else { + $datatable .= ''; + $datatable .= ''; + } + + $datatable .= ''; + + } + + return $datatable; + +} + + +sub radiobutton_prefs { + my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_; + return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') && + (ref($choices) eq 'HASH')); + + my (%checkedon,%checkedoff,$datatable,$css_class); + + 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} = ' '; + } + } + 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 (@{$toggles}) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= + ''. + ''. + ''; + $itemcount ++; + } + return ($datatable,$itemcount); +} + +sub print_coursedefaults { + my ($dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + my $itemcount = 1; + my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles); + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + my %choices = + &Apache::lonlocal::texthash ( + anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', + ); + my $currdefresponder; + if (ref($settings) eq 'HASH') { + $currdefresponder = $settings->{'anonsurvey_threshold'}; + } + if (!$currdefresponder) { + $currdefresponder = 10; + } elsif ($currdefresponder < 1) { + $currdefresponder = 1; + } + $datatable .= + ''. + ''; + $$rowtotal += $itemcount; + 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', + 'lonstatusmail' => 'E-mail from nightly status check (warnings/errors)', + 'requestsmail' => 'E-mail from course requests requiring approval', + ); + my %short_titles = &Apache::lonlocal::texthash ( + adminemail => 'Admin E-mail address', + supportemail => 'Support E-mail', + ); + return (\%titles,\%short_titles); +} + +sub tool_titles { + my %titles = &Apache::lonlocal::texthash ( + aboutme => 'Personal Information Page', + blog => 'Blog', + portfolio => 'Portfolio', + official => 'Official courses (with institutional codes)', + unofficial => 'Unofficial courses', + community => 'Communities', + ); + return %titles; +} + +sub courserequest_titles { + my %titles = &Apache::lonlocal::texthash ( + official => 'Official', + unofficial => 'Unofficial', + community => 'Communities', + norequest => 'Not allowed', + approval => 'Approval by Dom. Coord.', + validate => 'With validation', + autolimit => 'Numerical limit', + unlimited => '(blank for unlimited)', + ); + return %titles; +} + +sub courserequest_conditions { + my %conditions = &Apache::lonlocal::texthash ( + approval => '(Processing of request subject to approval by Domain Coordinator).', + validate => '(Processing of request subject to instittutional validation).', + ); + return %conditions; +} + + +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 .= ''; + $$rowtotal ++; + $rowcount ++; + } + } elsif ($position eq 'middle') { + my @creators = ('author','course','requestcrs','selfcreate'); + my ($rules,$ruleorder) = + &Apache::lonnet::inst_userrules($dom,'username'); + my %lt = &usercreation_types(); + my %checked; + my @selfcreate; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'cancreate'}) eq 'HASH') { + foreach my $item (@creators) { + $checked{$item} = $settings->{'cancreate'}{$item}; + } + if (ref($settings->{'cancreate'}{'selfcreate'}) eq 'ARRAY') { + @selfcreate = @{$settings->{'cancreate'}{'selfcreate'}}; + } elsif ($settings->{'cancreate'}{'selfcreate'} ne '') { + if ($settings->{'cancreate'}{'selfcreate'} eq 'any') { + @selfcreate = ('email','login','sso'); + } elsif ($settings->{'cancreate'}{'selfcreate'} ne 'none') { + @selfcreate = ($settings->{'cancreate'}{'selfcreate'}); + } + } + } 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 ($item ne 'selfcreate') { + if ($checked{$item} eq '') { + $checked{$item} = 'any'; + } + } + my $css_class; + if ($rownum%2) { + $css_class = ''; + } else { + $css_class = ' class="LC_odd_row" '; + } + $datatable .= ''. + ''; + } + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($dom); if (ref($usertypes) eq 'HASH') { - @types = sort(keys(%{$usertypes})); + if (keys(%{$usertypes}) > 0) { + my $createsettings; + if (ref($settings) eq 'HASH') { + $createsettings = $settings->{cancreate}; + } + $datatable .= &insttypes_row($createsettings,$types,$usertypes, + $dom,$numinrow,$othertitle, + 'statustocreate'); + $$rowtotal ++; + } + } + } 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 .= ''. + ''; + $rownum ++; } + $$rowtotal += $rownum; } - if (keys(%{$usertypes}) > 0) { - $othertitle = &mt('Other users'); + 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 = ''. + ''. + ''; + return $output; +} + +sub usercreation_types { + my %lt = &Apache::lonlocal::texthash ( + author => 'When adding a co-author', + course => 'When adding a user to a course', + requestcrs => 'When requesting a course', + selfcreate => 'User creates own account', + any => 'Any', + official => 'Institutional only ', + unofficial => 'Non-institutional only', + email => 'E-mail 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 ++; + } + } elsif ($position eq 'middle') { + $context = 'course'; + $rowcount = 0; + foreach my $role ('st','ep','ta','in','cr') { + $datatable .= &modifiable_userdata_row($context,$role,$settings, + $numinrow,$rowcount); + $$rowtotal ++; + $rowcount ++; + } + } elsif ($position eq 'bottom') { + $context = 'selfcreate'; + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + $usertypes->{'default'} = $othertitle; + if (ref($types) eq 'ARRAY') { + push(@{$types},'default'); + $usertypes->{'default'} = $othertitle; + foreach my $status (@{$types}) { + $datatable .= &modifiable_userdata_row($context,$status,$settings, + $numinrow,$rowcount,$usertypes); + $$rowtotal ++; + $rowcount ++; + } + } + } + return $datatable; +} + +sub print_defaults { + my ($dom,$rowtotal) = @_; + my @items = ('auth_def','auth_arg_def','lang_def','timezone_def', + 'datelocale_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 .= ''. + ''; + $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', + 'timezone_def' => 'Default timezone', + 'datelocale_def' => 'Default locale for dates', + ); + return (\%titles); +} + +sub print_scantronformat { + my ($r,$dom,$confname,$settings,$rowtotal) = @_; + my $itemcount = 1; + my ($datatable,$css_class,$scantronurl,$is_custom,%error,%scantronurls, + %confhash); + my $switchserver = &check_switchserver($dom,$confname); + my %lt = &Apache::lonlocal::texthash ( + default => 'Default bubblesheet format file error', + custom => 'Custom bubblesheet 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}`); + chomp($md5chk{$type}); + } + if ($md5chk{'default'} ne $md5chk{'custom'}) { + foreach my $type (keys(%legacyfile)) { + ($scantronurls{$type},my $error) = + &legacy_scantronformat($r,$dom,$confname, + $type,$legacyfile{$type}, + $scantronurls{$type}, + $scantronfiles{$type}); + if ($error ne '') { + $error{$type} = $error; + } + } + if (keys(%error) == 0) { + $is_custom = 1; + $confhash{'scantron'}{'scantronformat'} = + $scantronurls{'custom'}; + my $putresult = + &Apache::lonnet::put_dom('configuration', + \%confhash,$dom); + if ($putresult ne 'ok') { + $error{'custom'} = + ''. + &mt('An error occurred updating the domain configuration: [_1]',$putresult).''; + } + } + } else { + ($scantronurls{'default'},my $error) = + &legacy_scantronformat($r,$dom,$confname, + 'default',$legacyfile{'default'}, + $scantronurls{'default'}, + $scantronfiles{'default'}); + if ($error eq '') { + $confhash{'scantron'}{'scantronformat'} = ''; + my $putresult = + &Apache::lonnet::put_dom('configuration', + \%confhash,$dom); + if ($putresult ne 'ok') { + $error{'default'} = + ''. + &mt('An error occurred updating the domain configuration: [_1]',$putresult).''; + } + } else { + $error{'default'} = $error; + } + } + } + } + } else { + $error{'default'} = &mt("Unable to copy default bubblesheet 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 { + if ($is_custom) { + $scantronurl = $scantronurls{'custom'}; + } else { + $scantronurl = $scantronurls{'default'}; + } + } + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''; + if (!$is_custom) { + $datatable .= ''; + if (keys(%error) == 0) { + $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 ($position,$dom,$hdritem,$settings,$rowtotal) = @_; + my $datatable; + if ($position eq 'top') { + my $toggle_cats_crs = ' '; + my $toggle_cats_dom = ' checked="checked" '; + my $can_cat_crs = ' '; + my $can_cat_dom = ' checked="checked" '; + my $toggle_catscomm_comm = ' '; + my $toggle_catscomm_dom = ' checked="checked" '; + my $can_catcomm_comm = ' '; + my $can_catcomm_dom = ' checked="checked" '; + + if (ref($settings) eq 'HASH') { + if ($settings->{'togglecats'} eq 'crs') { + $toggle_cats_crs = $toggle_cats_dom; + $toggle_cats_dom = ' '; + } + if ($settings->{'categorize'} eq 'crs') { + $can_cat_crs = $can_cat_dom; + $can_cat_dom = ' '; + } + if ($settings->{'togglecatscomm'} eq 'comm') { + $toggle_catscomm_comm = $toggle_catscomm_dom; + $toggle_catscomm_dom = ' '; + } + if ($settings->{'categorizecomm'} eq 'comm') { + $can_catcomm_comm = $can_catcomm_dom; + $can_catcomm_dom = ' '; + } + } + my %title = &Apache::lonlocal::texthash ( + togglecats => 'Show/Hide a course in catalog', + togglecatscomm => 'Show/Hide a community in catalog', + categorize => 'Assign a category to a course', + categorizecomm => 'Assign a category to a community', + ); + my %level = &Apache::lonlocal::texthash ( + dom => 'Set in Domain', + crs => 'Set in Course', + comm => 'Set in Community', + ); + $datatable = ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''; + $$rowtotal += 4; + } else { + my $css_class; + my $itemcount = 1; + my $cathash; + if (ref($settings) eq 'HASH') { + $cathash = $settings->{'cats'}; + } + if (ref($cathash) eq 'HASH') { + my (@cats,@trails,%allitems,%idx,@jsarray); + &Apache::loncommon::extract_categories($cathash,\@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; + my %default_names = ( + instcode => &mt('Official courses'), + communities => &mt('Communities'), + ); + + if ((!grep(/^instcode$/,@{$cats[0]})) || + ($cathash->{'instcode::0'} eq '') || + (!grep(/^communities$/,@{$cats[0]})) || + ($cathash->{'communities::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 .= ''; + } else { + $datatable .= '
'.&mt('Supported search methods'). + ''; foreach my $title (@{$titleorder}) { if (defined($searchtitles->{$title})) { my $check = ' '; - if (ref($settings->{'searchby'}) eq 'ARRAY') { - if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) { - $check = ' checked="checked" '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'searchby'}) eq 'ARRAY') { + if (grep(/^\Q$title\E$/,@{$settings->{'searchby'}})) { + $check = ' checked="checked" '; + } } } $datatable .= '
'. @@ -1010,26 +1852,1509 @@ sub print_directorysrch { } } $datatable .= '
'.&mt('Search latitude').''. + ' '. + ' '. + '
'.$titles->{$item}. + ''. + '
'. + $titles->{$type}.': '. + ''; + foreach my $item (@contacts) { + $datatable .= ' '; + } + $datatable .= '
'.&mt('Others').':  '. + ''. + '
'.$choices{$item}.'  +   + '. + '
   '; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= &mt('Upload Custom Login Page Help File:'); + $datatable .=''; + } + $datatable .= '
'.$choices->{$item}. + ''. + ' '. + '
'.$choices{'anonsurvey_threshold'}. + ''. + ''. + '
'.&mt('No format rules have been defined for usernames or IDs in this domain.').'
'.$lt{$item}. + ''; + my @options; + if ($item eq 'selfcreate') { + push(@options,('email','login','sso')); + } else { + @options = ('any'); + if (ref($rules) eq 'HASH') { + if (keys(%{$rules}) > 0) { + push(@options,('official','unofficial')); + } + } + push(@options,'none'); + } + foreach my $option (@options) { + my $type = 'radio'; + my $check = ' '; + if ($item eq 'selfcreate') { + $type = 'checkbox'; + if (grep(/^\Q$option\E$/,@selfcreate)) { + $check = ' checked="checked" '; + } + } else { + if ($checked{$item} eq $option) { + $check = ' checked="checked" '; + } + } + $datatable .= '  '; + } + $datatable .= '
'.$title{$item}. + ''. + ''; + foreach my $auth (@authtypes) { + $datatable .= ' '; + } + $datatable .= '
'; + if ($type eq 'email') { + $output .= &mt("Formats disallowed for $text{$type}: "); + } else { + $output .= &mt("Format rules to check for $text{$type}: "); + } + $output .= ''; + 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 .= '
'. + ''. + '  
'.$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 .= '  '; + } + } elsif ($item eq 'timezone_def') { + my $includeempty = 1; + $datatable .= &Apache::loncommon::select_timezone($item,$domdefaults{$item},undef,$includeempty); + } elsif ($item eq 'datelocale_def') { + my $includeempty = 1; + $datatable .= &Apache::loncommon::select_datelocale($item,$domdefaults{$item},undef,$includeempty); + } else { + $datatable .= ''; + } + $datatable .= '
'.&mt('Default in use:').'
'. + ''; + if ($scantronurl) { + $datatable .= ''. + &mt('Default scantron format file').''; + } else { + $datatable = &mt('File unavailable for display'); + } + $datatable .= '
'; + if (!$switchserver) { + $datatable .= &mt('Upload:').'
'; + } + } else { + my $errorstr; + foreach my $key (sort(keys(%error))) { + $errorstr .= $lt{$key}.': '.$error{$key}.'
'; + } + $datatable .= '
'.$errorstr; + } + } 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 .= '
'.$title{'togglecats'}.' '. + '
'.$title{'categorize'}.''. + ' '. + '
'.$title{'togglecatscomm'}.' '. + '
'.$title{'categorizecomm'}.''. + ' '. + '
' + .''; + if ($parent eq 'instcode' || $parent eq 'communities') { + $datatable .= '' + .$default_names{$parent}.''; + if ($parent eq 'instcode') { + $datatable .= '
(' + .&mt('with institutional codes') + .')
'; + } + $datatable .= '' + .''; + if ($parent eq 'instcode') { + $datatable .= ' '; + } else { + $datatable .= '
' + .''; + } + $datatable .= ''; + if ($parent eq 'communities') { + $datatable .= '
'; + } + $datatable .= ''; + } 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('Add category:').' ' + .'' + .''."\n"; + $itemcount ++; + foreach my $default ('instcode','communities') { + if ((!grep(/^\Q$default\E$/,@{$cats[0]})) || ($cathash->{$default.'::0'} eq '')) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderCats(this.form,'."'','$default"."_pos','$lastidx'".');"'; + $datatable .= ''. + ''. + ''. + $default_names{$default}.''; + if ($default eq 'instcode') { + $datatable .= '
(' + .&mt('with institutional codes').')'; + } + $datatable .= '' + .' ' + .''; + } + } + } + } else { + $datatable .= &initialize_categories($itemcount); + } + } else { + $datatable .= ''.$hdritem->{'header'}->[0]->{'col2'}.'' + .&initialize_categories($itemcount); + } + $$rowtotal += $itemcount; + } + return $datatable; +} + +sub print_serverstatuses { + my ($dom,$settings,$rowtotal) = @_; + my $datatable; + my @pages = &serverstatus_pages(); + my (%namedaccess,%machineaccess); + foreach my $type (@pages) { + $namedaccess{$type} = ''; + $machineaccess{$type}= ''; + } + if (ref($settings) eq 'HASH') { + foreach my $type (@pages) { + if (exists($settings->{$type})) { + if (ref($settings->{$type}) eq 'HASH') { + foreach my $key (keys(%{$settings->{$type}})) { + if ($key eq 'namedusers') { + $namedaccess{$type} = $settings->{$type}->{$key}; + } elsif ($key eq 'machines') { + $machineaccess{$type} = $settings->{$type}->{$key}; + } + } + } + } + } + } + my $titles= &LONCAPA::lonauthcgi::serverstatus_titles(); + my $rownum = 0; + my $css_class; + foreach my $type (@pages) { + $rownum ++; + $css_class = $rownum%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''. + $titles->{$type}.''. + ''. + ''. + ''. + ''. + ''. + ''."\n"; + } + $$rowtotal += $rownum; + return $datatable; +} + +sub serverstatus_pages { + return ('userstatus','lonstatus','loncron','server-status','codeversions', + 'clusterstatus','metadata_keywords','metadata_harvest', + 'takeoffline','takeonline','showenv','toggledebug'); +} + +sub coursecategories_javascript { + my ($settings) = @_; + my ($output,$jstext,$cathash); + if (ref($settings) eq 'HASH') { + $cathash = $settings->{'cats'}; + } + if (ref($cathash) eq 'HASH') { + my (@cats,@jsarray,%idx); + &Apache::loncommon::gather_categories($cathash,\@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"; + } + my $instcode_reserved = &mt('The name: "instcode" is a reserved category'); + my $communities_reserved = &mt('The name: "communities" is a reserved category'); + my $choose_again = '\\n'.&mt('Please use a different name for the new top level category'); + $output = <<"ENDSCRIPT"; + + +ENDSCRIPT + return $output; +} + +sub initialize_categories { + my ($itemcount) = @_; + my ($datatable,$css_class,$chgstr); + my %default_names = ( + instcode => 'Official courses (with institutional codes)', + communities => 'Communities', + ); + my $select0 = ' selected="selected"'; + my $select1 = ''; + foreach my $default ('instcode','communities') { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $chgstr = ' onchange="javascript:reorderCats(this.form,'."'',$default"."_pos','0'".');"'; + if ($default eq 'communities') { + $select1 = $select0; + $select0 = ''; + } + $datatable .= '' + .' ' + .$default_names{$default} + .'' + .' '; + $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('Add subcategory:').' '; + } + $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,$usertypes) = @_; + my $rolename; + if ($context eq 'selfcreate') { + if (ref($usertypes) eq 'HASH') { + $rolename = $usertypes->{$role}; + } else { + $rolename = $role; + } + } else { + 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 insttypes_row { + my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context) = @_; + my %lt = &Apache::lonlocal::texthash ( + cansearch => 'Users allowed to search', + statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)', + ); + my $showdom; + if ($context eq 'cansearch') { + $showdom = ' ('.$dom.')'; + } + my $output = ''. + ''.$lt{$context}.$showdom. + ''; + 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) eq 'HASH') { + if (ref($settings->{$context}) eq 'ARRAY') { + if (grep(/^\Q$types->[$i]\E$/,@{$settings->{$context}})) { + $check = ' checked="checked" '; + } + } elsif ($context eq 'statustocreate') { + $check = ' checked="checked" '; + } + } + $output .= ''; + } + } + + $rem = @{$types}%($numinrow); + } + my $colsleft = $numinrow - $rem; + if ($colsleft > 1) { + $output .= ''. + '
'. + ''; + } else { + $output .= ''; } - return ($othertitle,$usertypes,\@types); + my $defcheck = ' '; + if (ref($settings) eq 'HASH') { + if (ref($settings->{$context}) eq 'ARRAY') { + if (grep(/^default$/,@{$settings->{$context}})) { + $defcheck = ' checked="checked" '; + } + } elsif ($context eq 'statustocreate') { + $defcheck = ' checked="checked" '; + } + } + $output .= '
'; + return $output; } sub sorted_searchtitles { @@ -1042,6 +3367,16 @@ sub sorted_searchtitles { 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; @@ -1061,10 +3396,12 @@ sub usertype_update_row { $datatable .= ''; } my $check = ' '; - 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 (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" '; + } } } } @@ -1094,40 +3431,111 @@ 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'); + 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 %curr_loginvia; + if (ref($domconfig{login}) eq 'HASH') { + if (ref($domconfig{login}{loginvia}) eq 'HASH') { + foreach my $lonhost (keys(%{$domconfig{login}{loginvia}})) { + $curr_loginvia{$lonhost} = $domconfig{login}{loginvia}{$lonhost}; + } + } + } my %loginhash; ($errors,%colchanges) = &modify_colors($r,$dom,$confname,['login'], \%domconfig,\%loginhash); - $loginhash{login}{coursecatalog} = $env{'form.coursecatalog'}; - $loginhash{login}{adminmail} = $env{'form.adminmail'}; + 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 %servers = &dom_servers($dom); + if (keys(%servers) > 1) { + foreach my $lonhost (keys(%servers)) { + next if ($env{'form.'.$lonhost.'_serverurl'} eq $lonhost); + if ($env{'form.'.$lonhost.'_serverurl'} eq $curr_loginvia{$lonhost}) { + $loginhash{login}{loginvia}{$lonhost} = $curr_loginvia{$lonhost}; next; + } + if ($curr_loginvia{$lonhost} ne '') { + $loginhash{login}{loginvia}{$lonhost} = $env{'form.'.$lonhost.'_serverurl'}; + $changes{'loginvia'}{$lonhost} = 1; + } else { + if (defined($servers{$env{'form.'.$lonhost.'_serverurl'}})) { + $loginhash{login}{loginvia}{$lonhost} = $env{'form.'.$lonhost.'_serverurl'}; + $changes{'loginvia'}{$lonhost} = 1; + } + } + } + } + my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash, $dom); if ($putresult eq 'ok') { - if (($domconfig{'login'}{'coursecatalog'} eq '0') && - ($env{'form.coursecatalog'} eq '1')) { - $changes{'coursecatalog'} = 1; - } elsif (($domconfig{'login'}{'coursecatalog'} eq '' || - $domconfig{'login'}{'coursecatalog'} eq '1') && - ($env{'form.coursecatalog'} eq '0')) { - $changes{'coursecatalog'} = 1; - } - if (($domconfig{'login'}{'adminmail'} eq '1') && - ($env{'form.adminmail'} eq '0')) { - $changes{'adminmail'} = 1; - } elsif (($domconfig{'login'}{'adminmail'} eq '' || - $domconfig{'login'}{'adminmail'} eq '0') && - ($env{'form.adminmail'} eq '1')) { - $changes{'adminmail'} = 1; + my @toggles = ('coursecatalog','adminmail','newuser'); + my %defaultchecked = ( + 'coursecatalog' => 'on', + 'adminmail' => 'off', + 'newuser' => 'off', + ); + if (ref($domconfig{'login'}) eq 'HASH') { + 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))) { - $resulttext .= '
  • '.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'
  • '; + if ($item eq 'loginheader') { + $resulttext .= '
  • '.&mt("$title{$item} set to $env{'form.loginheader'}").'
  • '; + } elsif ($item eq 'loginvia') { + if (ref($changes{$item}) eq 'HASH') { + $resulttext .= '
  • '.&mt('Log-in page availability:').'
      '; + foreach my $lonhost (sort(keys(%{$changes{$item}}))) { + if ($servers{$env{'form.'.$lonhost.'_serverurl'}} ne '') { + $resulttext .= '
    • '.&mt('Server: [_1] log-in page now redirects to [_2]',$lonhost,$servers{$env{'form.'.$lonhost.'_serverurl'}}).'
    • '; + } else { + $resulttext .= '
    • '.&mt('Server: [_1] now has standard log-in page.',$lonhost).'
    • '; + } + } + $resulttext .= '
  • '; + } + } else { + $resulttext .= '
  • '.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'
  • '; + } } $resulttext .= $colchgtext.'
'; } else { @@ -1150,7 +3558,9 @@ sub color_font_choices { img => "Header", bgs => "Background colors", links => "Link colors", + images => "Images", font => "Font color", + fontmenu => "Font Menu", pgbg => "Page", tabbg => "Header", sidebg => "Border", @@ -1165,12 +3575,18 @@ sub modify_rolecolors { my ($r,$dom,$confname,$roles,%domconfig) = @_; my ($resulttext,%rolehash); $rolehash{'rolecolors'} = {}; + if (ref($domconfig{'rolecolors'}) ne 'HASH') { + if ($domconfig{'rolecolors'} eq '') { + $domconfig{'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 { @@ -1190,38 +3606,45 @@ sub modify_rolecolors { sub modify_colors { my ($r,$dom,$confname,$roles,$domconfig,$confhash) = @_; my (%changes,%choices); - my @bgs = ('pgbg','mainbg','sidebg'); + my @bgs; 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(); + $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'}; } if ($role eq 'login') { - @images = ('img','logo','domlogo'); + @images = ('img','logo','domlogo','login'); + @bgs = ('pgbg','mainbg','sidebg'); } else { @images = ('img'); + @bgs = ('pgbg','tabbg','sidebg'); } $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'}; - foreach my $item (@bgs,@links) { + foreach my $item (@bgs,@links,@logintext) { $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; } - 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); - } - } + 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 (($role eq 'login') && (($img eq 'img') || ($img eq 'logo'))) { + if (defined($env{'form.login_showlogo_'.$img})) { + $confhash->{$role}{'showlogo'}{$img} = 1; + } else { + $confhash->{$role}{'showlogo'}{$img} = 0; + } + } if ( ! $env{'form.'.$role.'_'.$img.'.filename'} && !defined($domconfig->{$role}{$img}) && !$env{'form.'.$role.'_del_'.$img} @@ -1248,11 +3671,11 @@ sub modify_colors { $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 Configuation user ([_2]) in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$author_ok); + $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 Configuation user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$choices{$img},$confname,$dom,$configuserok); + $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); @@ -1296,7 +3719,19 @@ sub modify_colors { $changes{$role}{'images'}{$img} = 1; } } - } + if (($role eq 'login') && (($img eq 'logo') || ($img eq 'img'))) { + if (ref($domconfig->{'login'}{'showlogo'}) eq 'HASH') { + if ($confhash->{$role}{'showlogo'}{$img} ne + $domconfig->{$role}{'showlogo'}{$img}) { + $changes{$role}{'showlogo'}{$img} = 1; + } + } else { + if ($confhash->{$role}{'showlogo'}{$img} == 0) { + $changes{$role}{'showlogo'}{$img} = 1; + } + } + } + } if ($domconfig->{$role}{'font'} ne '') { if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) { $changes{$role}{'font'} = 1; @@ -1306,6 +3741,17 @@ sub modify_colors { $changes{$role}{'font'} = 1; } } + if ($role ne 'login') { + if ($domconfig->{$role}{'fontmenu'} ne '') { + if ($confhash->{$role}{'fontmenu'} ne $domconfig->{$role}{'fontmenu'}) { + $changes{$role}{'fontmenu'} = 1; + } + } else { + if ($confhash->{$role}{'fontmenu'}) { + $changes{$role}{'fontmenu'} = 1; + } + } + } foreach my $item (@bgs) { if ($domconfig->{$role}{$item} ne '') { if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) { @@ -1328,20 +3774,46 @@ sub modify_colors { } } } + 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, - $confhash,\%changes); + \@logintext,$confhash,\%changes); } } else { &default_change_checker($role,\@images,\@links,\@bgs, - $confhash,\%changes); + \@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,$confhash,$changes) = @_; + my ($role,$images,$links,$bgs,$logintext,$confhash,$changes) = @_; foreach my $item (@{$links}) { if ($confhash->{$role}{$item}) { $changes->{$role}{'links'}{$item} = 1; @@ -1352,21 +3824,30 @@ sub default_change_checker { $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 ($role eq 'login') { + if ($confhash->{$role}{'showlogo'}{$img} == 0) { + $changes->{$role}{'showlogo'}{$img} = 1; + } + } } if ($confhash->{$role}{'font'}) { $changes->{$role}{'font'} = 1; } -} +} sub display_colorchgs { my ($dom,$changes,$roles,$confhash) = @_; my (%choices,$resulttext); - &Apache::loncommon::devalidate_domconfig_cache($dom); if (!grep(/^login$/,@{$roles})) { $resulttext = &mt('Changes made:').'
'; } @@ -1389,7 +3870,13 @@ sub display_colorchgs { $resulttext .= '
  • '.&mt($choices{$key}).':
      '; } foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) { - if ($confhash->{$role}{$item} eq '') { + if (($role eq 'login') && ($key eq 'showlogo')) { + if ($confhash->{$role}{$key}{$item}) { + $resulttext .= '
    • '.&mt("$choices{$item} set to be displayed").'
    • '; + } else { + $resulttext .= '
    • '.&mt("$choices{$item} set to not be displayed").'
    • '; + } + } elsif ($confhash->{$role}{$item} eq '') { $resulttext .= '
    • '.&mt("$choices{$item} set to default").'
    • '; } else { my $newitem = $confhash->{$role}{$item}; @@ -1467,7 +3954,7 @@ sub check_authorstatus { my $end = 0; $author_ok = &Apache::lonnet::assignrole($dom,$confname,'/'.$dom.'/', - 'au',$end,$start); + 'au',$end,$start,'','','domconfig'); } else { $author_ok = 'ok'; } @@ -1475,7 +3962,7 @@ sub check_authorstatus { } sub publishlogo { - my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight) = @_; + my ($r,$action,$formname,$dom,$confname,$subdir,$thumbwidth,$thumbheight,$savefileas) = @_; my ($output,$fname,$logourl); if ($action eq 'upload') { $fname=$env{'form.'.$formname.'.filename'}; @@ -1483,6 +3970,9 @@ sub publishlogo { } 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'); } @@ -1510,7 +4000,7 @@ sub publishlogo { !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 a rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); + $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 { @@ -1692,49 +4182,272 @@ sub check_switchserver { } sub modify_quotas { - my ($dom,%domconfig) = @_; - my ($resulttext,%changes); - my ($usertypes,$order) = - &Apache::lonnet::retrieve_inst_usertypes($dom); - my %formhash; + my ($dom,$action,%domconfig) = @_; + my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash, + %limithash,$toolregexp,%conditions,$resulttext,%changes); + if ($action eq 'quotas') { + $context = 'tools'; + } else { + $context = $action; + } + if ($context eq 'requestcourses') { + @usertools = ('official','unofficial','community'); + @options =('norequest','approval','validate','autolimit'); + %validations = &Apache::lonnet::auto_courserequest_checks($dom); + %titles = &courserequest_titles(); + $toolregexp = join('|',@usertools); + %conditions = &courserequest_conditions(); + } else { + @usertools = ('aboutme','blog','portfolio'); + %titles = &tool_titles(); + } + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); foreach my $key (keys(%env)) { - if ($key =~ /^form\.quota_(.+)$/) { - $formhash{$1} = $env{$key}; + if ($context eq 'requestcourses') { + if ($key =~ /^form\.crsreq_($toolregexp)_(.+)$/) { + my $item = $1; + my $type = $2; + if ($type =~ /^limit_(.+)/) { + $limithash{$item}{$1} = $env{$key}; + } else { + $confhash{$item}{$type} = $env{$key}; + } + } + } else { + if ($key =~ /^form\.quota_(.+)$/) { + $confhash{'defaultquota'}{$1} = $env{$key}; + } + if ($key =~ /^form\.\Q$context\E_(.+)$/) { + @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($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; + if ($context eq 'requestcourses') { + my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify'); + @approvalnotify = sort(@approvalnotify); + $confhash{'notify'}{'approval'} = join(',',@approvalnotify); + if (ref($domconfig{$action}) eq 'HASH') { + if (ref($domconfig{$action}{'notify'}) eq 'HASH') { + if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) { + $changes{'notify'}{'approval'} = 1; + } + } else { + if ($domconfig{$action}{'notify'}{'approval'}) { + $changes{'notify'}{'approval'} = 1; + } + } + } else { + if ($domconfig{$action}{'notify'}{'approval'}) { + $changes{'notify'}{'approval'} = 1; + } + } + } else { + $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'}; + } + foreach my $item (@usertools) { + foreach my $type (@{$types},'default','_LC_adv') { + my $unset; + if ($context eq 'requestcourses') { + $unset = '0'; + if ($type eq '_LC_adv') { + $unset = ''; + } + if ($confhash{$item}{$type} eq 'autolimit') { + $confhash{$item}{$type} .= '='; + unless ($limithash{$item}{$type} =~ /\D/) { + $confhash{$item}{$type} .= $limithash{$item}{$type}; + } + } + } else { + if (grep(/^\Q$type\E$/,@{$toolshash{$item}})) { + $confhash{$item}{$type} = 1; + } else { + $confhash{$item}{$type} = 0; + } + } + if (ref($domconfig{$action}) eq 'HASH') { + if (ref($domconfig{$action}{$item}) eq 'HASH') { + if ($domconfig{$action}{$item}{$type} ne $confhash{$item}{$type}) { + $changes{$item}{$type} = 1; + } + } else { + if ($context eq 'requestcourses') { + if ($confhash{$item}{$type} ne $unset) { + $changes{$item}{$type} = 1; + } + } else { + if (!$confhash{$item}{$type}) { + $changes{$item}{$type} = 1; + } + } } } else { - $formhash{$key} = $domconfig{'quotas'}{$key}; + if ($context eq 'requestcourses') { + if ($confhash{$item}{$type} ne $unset) { + $changes{$item}{$type} = 1; + } + } else { + if (!$confhash{$item}{$type}) { + $changes{$item}{$type} = 1; + } + } } } } - foreach my $key (keys(%formhash)) { - if ($formhash{$key} ne '') { - if (!exists($domconfig{'quotas'}{$key})) { - $changes{$key} = 1; + unless ($context eq 'requestcourses') { + if (ref($domconfig{'quotas'}) eq 'HASH') { + if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') { + foreach my $key (keys(%{$domconfig{'quotas'}{'defaultquota'}})) { + if (exists($confhash{'defaultquota'}{$key})) { + if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{'defaultquota'}{$key}) { + $changes{'defaultquota'}{$key} = 1; + } + } else { + $confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{'defaultquota'}{$key}; + } + } + } else { + foreach my $key (keys(%{$domconfig{'quotas'}})) { + if (exists($confhash{'defaultquota'}{$key})) { + if ($confhash{'defaultquota'}{$key} ne $domconfig{'quotas'}{$key}) { + $changes{'defaultquota'}{$key} = 1; + } + } else { + $confhash{'defaultquota'}{$key} = $domconfig{'quotas'}{$key}; + } + } + } + } + if (ref($confhash{'defaultquota'}) eq 'HASH') { + foreach my $key (keys(%{$confhash{'defaultquota'}})) { + if (ref($domconfig{'quotas'}) eq 'HASH') { + if (ref($domconfig{'quotas'}{'defaultquota'}) eq 'HASH') { + if (!exists($domconfig{'quotas'}{'defaultquota'}{$key})) { + $changes{'defaultquota'}{$key} = 1; + } + } else { + if (!exists($domconfig{'quotas'}{$key})) { + $changes{'defaultquota'}{$key} = 1; + } + } + } else { + $changes{'defaultquota'}{$key} = 1; + } } } } + + foreach my $key (keys(%confhash)) { + $domdefaults{$key} = $confhash{$key}; + } + my %quotahash = ( - quotas => {%formhash}, + $action => { %confhash } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%quotahash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); + $resulttext = &mt('Changes made:').'
        '; - foreach my $item (sort(keys(%changes))) { - $resulttext .= '
      • '.&mt('[_1] set to [_2] Mb',$usertypes->{$item},$formhash{$item}).'
      • '; + unless ($context eq 'requestcourses') { + if (ref($changes{'defaultquota'}) eq 'HASH') { + $resulttext .= '
      • '.&mt('Portfolio default quotas').'
          '; + foreach my $type (@{$types},'default') { + if (defined($changes{'defaultquota'}{$type})) { + my $typetitle = $usertypes->{$type}; + if ($type eq 'default') { + $typetitle = $othertitle; + } + $resulttext .= '
        • '.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'defaultquota'}{$type}).'
        • '; + } + } + $resulttext .= '
      • '; + } + } + my %newenv; + foreach my $item (@usertools) { + if (ref($changes{$item}) eq 'HASH') { + my $newacc = + &Apache::lonnet::usertools_access($env{'user.name'}, + $env{'user.domain'}, + $item,'reload',$context); + if ($context eq 'requestcourses') { + if ($env{'environment.canrequest.'.$item} ne $newacc) { + $newenv{'environment.canrequest.'.$item} = $newacc; + } + } else { + if ($env{'environment.availabletools.'.$item} ne $newacc) { + $newenv{'environment.availabletools.'.$item} = $newacc; + } + } + $resulttext .= '
      • '.$titles{$item}.'
          '; + foreach my $type (@{$types},'default','_LC_adv') { + if ($changes{$item}{$type}) { + my $typetitle = $usertypes->{$type}; + if ($type eq 'default') { + $typetitle = $othertitle; + } elsif ($type eq '_LC_adv') { + $typetitle = 'LON-CAPA Advanced Users'; + } + if ($confhash{$item}{$type}) { + if ($context eq 'requestcourses') { + my $cond; + if ($confhash{$item}{$type} =~ /^autolimit=(\d*)$/) { + if ($1 eq '') { + $cond = &mt('(Automatic processing of any request).'); + } else { + $cond = &mt('(Automatic processing of requests up to limit of [quant,_1,request] per user).',$1); + } + } else { + $cond = $conditions{$confhash{$item}{$type}}; + } + $resulttext .= '
        • '.&mt('Set to be available to [_1].',$typetitle).' '.$cond.'
        • '; + } else { + $resulttext .= '
        • '.&mt('Set to be available to [_1]',$typetitle).'
        • '; + } + } else { + if ($type eq '_LC_adv') { + if ($confhash{$item}{$type} eq '0') { + $resulttext .= '
        • '.&mt('Set to be unavailable to [_1]',$typetitle).'
        • '; + } else { + $resulttext .= '
        • '.&mt('No override set for [_1]',$typetitle).'
        • '; + } + } else { + $resulttext .= '
        • '.&mt('Set to be unavailable to [_1]',$typetitle).'
        • '; + } + } + } + } + $resulttext .= '
      • '; + } + } + if ($action eq 'requestcourses') { + if (ref($changes{'notify'}) eq 'HASH') { + if ($changes{'notify'}{'approval'}) { + if (ref($confhash{'notify'}) eq 'HASH') { + if ($confhash{'notify'}{'approval'}) { + $resulttext .= '
      • '.&mt('Notification of requests requiring approval will be sent to: ').$confhash{'notify'}{'approval'}.'
      • '; + } else { + $resulttext .= '
      • '.&mt('No Domain Coordinators will receive notification of course requests requiring approval.').'
      • '; + } + } + } + } } $resulttext .= '
      '; + if (keys(%newenv)) { + &Apache::lonnet::appenv(\%newenv); + } } else { - $resulttext = &mt('No changes made to default quotas'); + if ($context eq 'requestcourses') { + $resulttext = &mt('No changes made to rights to request creation of courses.'); + } else { + $resulttext = &mt('No changes made to availability of personal information pages, blogs, portfolios or default quotas'); + } } } else { $resulttext = ''. @@ -1824,7 +4537,7 @@ sub modify_autoupdate { run => 'Auto-update:', classlists => 'Updates to user information in classlists?' ); - my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my %fieldtitles = &Apache::lonlocal::texthash ( id => 'Student/Employee ID', permanentemail => 'E-mail address', @@ -1835,7 +4548,7 @@ sub modify_autoupdate { ); my $othertitle = &mt('All users'); if (keys(%{$usertypes}) > 0) { - $othertitle = "Other users"; + $othertitle = &mt('Other users'); } foreach my $key (keys(%env)) { if ($key =~ /^form\.updateable_(.+)_([^_]+)$/) { @@ -1857,14 +4570,14 @@ sub modify_autoupdate { } } elsif ($key eq 'fields') { if (ref($currautoupdate{$key}) eq 'HASH') { - foreach my $item (keys(%{$currautoupdate{$key}})) { + 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}}) { + if (!grep(/^\Q$type\E$/,@{$fields{$item}})) { $change = 1; } } @@ -1872,18 +4585,20 @@ sub modify_autoupdate { if ($change) { push(@{$changes{$key}},$item); } - } + } } } } } - foreach my $key (keys(%fields)) { - if (ref($currautoupdate{'fields'}) eq 'HASH') { - if (!exists($currautoupdate{'fields'}{$key})) { - push(@{$changes{'fields'}},$key); + 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); } - } else { - push(@{$changes{'fields'}},$key); } } my $putresult = &Apache::lonnet::put_dom('configuration',\%updatehash, @@ -1905,9 +4620,9 @@ sub modify_autoupdate { $newvaluestr = &mt('none'); } if ($item eq 'default') { - $resulttext .= '
    • '.&mt("Updates for $othertitle set to: [_1]",$newvaluestr).'
    • '; + $resulttext .= '
    • '.&mt("Updates for '[_1]' set to: '[_2]'",$othertitle,$newvaluestr).'
    • '; } else { - $resulttext .= '
    • '.&mt("Updates for [_1] set to: [_2]",$usertypes->{$item},$newvaluestr).'
    • '; + $resulttext .= '
    • '.&mt("Updates for '[_1]' set to: '[_2]'",$usertypes->{$item},$newvaluestr).'
    • '; } } } else { @@ -1941,29 +4656,34 @@ sub modify_directorysrch { } } my %title = ( available => 'Directory search available', - cansearch => 'Users permitted to search', 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'); - if (ref($currdirsrch{'cansearch'}) eq 'ARRAY') { - foreach my $type (@{$currdirsrch{'cansearch'}}) { - if (!grep(/^\Q$type\E$/,@cansearch)) { - push(@{$changes{'cansearch'}},$type); + 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); + foreach my $type (@cansearch) { + if (!grep(/^\Q$type\E$/,@{$currdirsrch{'cansearch'}})) { + push(@{$changes{'cansearch'}},$type); + } } + } else { + push(@{$changes{'cansearch'}},@cansearch); } - } else { - push(@{$changes{'cansearch'}},@cansearch); } if (ref($currdirsrch{'searchby'}) eq 'ARRAY') { @@ -1980,13 +4700,39 @@ sub modify_directorysrch { } 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 => $env{'form.searchtypes'}, + searchtypes => \@searchtypes, } ); my $putresult = &Apache::lonnet::put_dom('configuration',\%dirsrch_hash, @@ -2010,15 +4756,6 @@ sub modify_directorysrch { $changes{'localonly'} = 1; } } - if (exists($currdirsrch{'searchtypes'})) { - if ($currdirsrch{'searchtypes'} ne $env{'form.searchtypes'}) { - $changes{'searchtypes'} = 1; - } - } else { - if ($env{'form.searchtypes'}) { - $changes{'searchtypes'} = 1; - } - } if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
        '; if ($changes{'available'}) { @@ -2029,19 +4766,22 @@ sub modify_directorysrch { } if (ref($changes{'cansearch'}) eq 'ARRAY') { - my ($othertitle,$usertypes,$types) = &sorted_inst_types($dom); my $chgtext; - foreach my $type (@cansearch) { - if (defined($usertypes->{$type})) { - $chgtext .= $usertypes->{$type}.'; '; + 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 (grep(/^default$/,@cansearch)) { - $chgtext .= $othertitle; - } else { - $chgtext =~ s/\; $//; - } - $resulttext .= '
      • '.&mt("$title{'cansearch'} ([_1]) set to: [_2]",$dom,$chgtext).'
      • '; } if (ref($changes{'searchby'}) eq 'ARRAY') { my ($searchtitles,$titleorder) = &sorted_searchtitles(); @@ -2056,13 +4796,18 @@ sub modify_directorysrch { $chgtext =~ s/\; $//; $resulttext .= '
      • '.&mt("$title{'searchby'} set to: [_1]",$chgtext).'
      • '; } - if ($changes{'searchtypes'}) { - my %srchtypes_desc = ( - exact => 'Exact match only', - contains => 'Contains is a match', - specify => 'Match type specifiable', - ); - $resulttext .= '
      • '.&mt("$title{'searchtypes'} set to: \"$srchtypes_desc{$env{'form.searchtypes'}}\"").'
      • '; + 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 { @@ -2070,10 +4815,1438 @@ sub modify_directorysrch { } } 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','lonstatusmail', + 'requestsmail'); + 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'; + $default{'lonstatusmail'} = 'adminemail'; + $default{'requestsmail'} = 'adminemail'; + 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','requestcrs','selfcreate'); + foreach my $item(@contexts) { + if ($item eq 'selfcreate') { + @{$cancreate{$item}} = &Apache::loncommon::get_env_multiple('form.can_createuser_'.$item); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || ($domdefaults{'auth_def'} eq 'localauth'))) { + if (ref($cancreate{$item}) eq 'ARRAY') { + if (grep(/^login$/,@{$cancreate{$item}})) { + $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.'); + } + } + } + } else { + $cancreate{$item} = $env{'form.can_createuser_'.$item}; + } + } + my ($othertitle,$usertypes,$types) = + &Apache::loncommon::sorted_inst_types($dom); + if (ref($types) eq 'ARRAY') { + if (@{$types} > 0) { + @{$cancreate{'statustocreate'}} = + &Apache::loncommon::get_env_multiple('form.statustocreate'); + } else { + @{$cancreate{'statustocreate'}} = (); + } + push(@contexts,'statustocreate'); + } + if (ref($curr_usercreation{'cancreate'}) eq 'HASH') { + foreach my $item (@contexts) { + if (($item eq 'selfcreate') || ($item eq 'statustocreate')) { + if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') { + foreach my $curr (@{$curr_usercreation{'cancreate'}{$item}}) { + if (ref($cancreate{$item}) eq 'ARRAY') { + if (!grep(/^$curr$/,@{$cancreate{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + } else { + if ($curr_usercreation{'cancreate'}{$item} eq '') { + if (@{$cancreate{$item}} > 0) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } else { + if ($curr_usercreation{'cancreate'}{$item} eq 'any') { + if (@{$cancreate{$item}} < 3) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif ($curr_usercreation{'cancreate'}{$item} eq 'none') { + if (@{$cancreate{$item}} > 0) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif (!grep(/^$curr_usercreation{'cancreate'}{$item}$/,@{$cancreate{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + foreach my $type (@{$cancreate{$item}}) { + if (ref($curr_usercreation{'cancreate'}{$item}) eq 'ARRAY') { + if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif (($curr_usercreation{'cancreate'}{$item} ne 'any') && + ($curr_usercreation{'cancreate'}{$item} ne 'none')) { + if ($curr_usercreation{'cancreate'}{$item} ne $type) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + } + } else { + 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); + + my %selfcreatetypes = ( + sso => 'users authenticated by institutional single sign on', + login => 'users authenticated by institutional log-in', + email => 'users who provide a valid e-mail address for use as the username', + ); + 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; + unless ($type eq 'statustocreate') { + $chgtext = $lt{$type}.', '; + } + if ($type eq 'selfcreate') { + if (@{$cancreate{$type}} == 0) { + $chgtext .= &mt('creation of a new user account is not permitted.'); + } else { + $chgtext .= &mt('creation of a new account is permitted for:').'
          '; + foreach my $case (@{$cancreate{$type}}) { + $chgtext .= '
        • '.$selfcreatetypes{$case}.'
        • '; + } + $chgtext .= '
        '; + if (ref($cancreate{$type}) eq 'ARRAY') { + if (grep(/^(login|sso)$/,@{$cancreate{$type}})) { + if (ref($cancreate{'statustocreate'}) eq 'ARRAY') { + if (@{$cancreate{'statustocreate'}} == 0) { + $chgtext .= '
        '.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").''; + } + } + } + } + } + } elsif ($type eq 'statustocreate') { + if ((ref($cancreate{'selfcreate'}) eq 'ARRAY') && + (ref($cancreate{'statustocreate'}) eq 'ARRAY')) { + if (@{$cancreate{'selfcreate'}} > 0) { + if (@{$cancreate{'statustocreate'}} == 0) { + + $chgtext .= &mt("Institutional affiliations permitted to create accounts set to 'None'."); + if (!grep(/^email$/,@{$cancreate{'selfcreate'}})) { + $chgtext .= '
        '.&mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts.").''; + } + } elsif (ref($usertypes) eq 'HASH') { + if (grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) { + $chgtext .= &mt('Creation of a new account for an institutional user is restricted to the following institutional affiliation(s):'); + } else { + $chgtext .= &mt('Institutional affiliations permitted to create accounts with institutional authentication were set as follows:'); + } + $chgtext .= '
          '; + foreach my $case (@{$cancreate{$type}}) { + if ($case eq 'default') { + $chgtext .= '
        • '.$othertitle.'
        • '; + } else { + $chgtext .= '
        • '.$usertypes->{$case}.'
        • '; + } + } + $chgtext .= '
        '; + if (!grep(/^(login|sso)$/,@{$cancreate{'selfcreate'}})) { + $chgtext .= '
        '.&mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.').''; + } + } + } else { + if (@{$cancreate{$type}} == 0) { + $chgtext .= &mt("Institutional affiliations permitted to create accounts were set to 'none'."); + } else { + $chgtext .= &mt('Although institutional affiliations permitted to create accounts were changed, self creation of accounts is not currently permitted for any authentication types.'); + } + } + } + } 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; } -1; +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','selfcreate'); + my %context_title = ( + author => 'In author context', + course => 'In course context', + selfcreate => 'When self creating account', + ); + my @fields = ('lastname','firstname','middlename','generation', + 'permanentemail','id'); + my %roles = ( + author => ['ca','aa'], + course => ['st','ep','ta','in','cr'], + ); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + if (ref($types) eq 'ARRAY') { + push(@{$types},'default'); + $usertypes->{'default'} = $othertitle; + } + $roles{'selfcreate'} = $types; + 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 ($context eq 'selfcreate') { + $rolename = $role; + if (ref($usertypes) eq 'HASH') { + if ($usertypes->{$role} ne '') { + $rolename = $usertypes->{$role}; + } + } + } else { + if ($role eq 'cr') { + $rolename = &mt('Custom'); + } else { + $rolename = &Apache::lonnet::plaintext($role); + } + } + my @modifiable; + if ($context eq 'selfcreate') { + $resulttext .= '
        • '.&mt('Self-creation of account by users with status: [_1] ',$rolename).' - '.&mt('modifiable fields (if institutional data blank): '); + } else { + $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','timezone_def','datelocale_def'); + my @authtypes = ('internal','krb4','krb5','localauth'); + my @doms = &Apache::lonnet::current_machine_domains(); + my @langs; + foreach my $dom (@doms) { + if ($dom =~ /^(\w+c)itest$/) { + push (@langs,$1.'t'); + } else { + push(@langs,$dom); + } + } + 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 ((!grep(/^\Q$langcode\E,@langs)) && + ($langcode ne 'x_chef')) { + if (code2language($langcode) eq '') { + push(@errors,$item); + } + } + } else { + push(@errors,$item); + } + } + } elsif ($item eq 'timezone_def') { + if ($newvalues{$item} ne '') { + if (!DateTime::TimeZone->is_valid_name($newvalues{$item})) { + push(@errors,$item); + } + } + } elsif ($item eq 'datelocale_def') { + if ($newvalues{$item} ne '') { + my @datelocale_ids = DateTime::Locale->ids(); + if (!grep(/^\Q$newvalues{$item}\E$/,@datelocale_ids)) { + push(@errors,$item); + } + } + } + if (grep(/^\Q$item\E$/,@errors)) { + $newvalues{$item} = $domdefaults{$item}; + } elsif ($domdefaults{$item} ne $newvalues{$item}) { + $changes{$item} = 1; + } + $domdefaults{$item} = $newvalues{$item}; + } + my %defaults_hash = ( + defaults => \%newvalues, + ); + 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,\%domdefaults,$cachetime); + if ($changes{'auth_def'} || $changes{'auth_arg_def'} || $changes{'lang_def'} || $changes{'datelocale_def'}) { + 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/timezone 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,%changes,$errors, + $cathash); + my @deletecategory = &Apache::loncommon::get_env_multiple('form.deletecategory'); + if (ref($domconfig{'coursecategories'}) eq 'HASH') { + $cathash = $domconfig{'coursecategories'}{'cats'}; + if ($domconfig{'coursecategories'}{'togglecats'} ne $env{'form.togglecats'}) { + $changes{'togglecats'} = 1; + $domconfig{'coursecategories'}{'togglecats'} = $env{'form.togglecats'}; + } + if ($domconfig{'coursecategories'}{'categorize'} ne $env{'form.categorize'}) { + $changes{'categorize'} = 1; + $domconfig{'coursecategories'}{'categorize'} = $env{'form.categorize'}; + } + if ($domconfig{'coursecategories'}{'togglecatscomm'} ne $env{'form.togglecatscomm'}) { + $changes{'togglecatscomm'} = 1; + $domconfig{'coursecategories'}{'togglecatscomm'} = $env{'form.togglecatscomm'}; + } + if ($domconfig{'coursecategories'}{'categorizecomm'} ne $env{'form.categorizecomm'}) { + $changes{'categorizecomm'} = 1; + $domconfig{'coursecategories'}{'categorizecomm'} = $env{'form.categorizecomm'}; + } + } else { + $changes{'togglecats'} = 1; + $changes{'categorize'} = 1; + $domconfig{'coursecategories'} = { + togglecats => $env{'form.togglecats'}, + categorize => $env{'form.categorize'}, + }; + $changes{'togglecatscomm'} = 1; + $changes{'categorizecomm'} = 1; + $domconfig{'coursecategories'} = { + togglecats => $env{'form.togglecatscomm'}, + categorize => $env{'form.categorizecomm'}, + }; + } + if (ref($cathash) eq 'HASH') { + if (($domconfig{'coursecategories'}{'cats'}{'instcode::0'} ne '') && ($env{'form.instcode'} == 0)) { + push (@deletecategory,'instcode::0'); + } + if (($domconfig{'coursecategories'}{'cats'}{'communities::0'} ne '') && ($env{'form.communities'} == 0)) { + push(@deletecategory,'communities::0'); + } + } + my (@predelcats,@predeltrails,%predelallitems,%sort_by_deltrail); + if (ref($cathash) eq 'HASH') { + if (@deletecategory > 0) { + #FIXME Need to remove category from all courses using a deleted category + &Apache::loncommon::extract_categories($cathash,\@predelcats,\@predeltrails,\%predelallitems); + foreach my $item (@deletecategory) { + if ($domconfig{'coursecategories'}{'cats'}{$item} ne '') { + delete($domconfig{'coursecategories'}{'cats'}{$item}); + $deletions{$item} = 1; + &recurse_cat_deletes($item,$cathash,\%deletions); + } + } + } + foreach my $item (keys(%{$cathash})) { + my ($cat,$container,$depth) = map { &unescape($_); } split(/:/,$item); + if ($cathash->{$item} ne $env{'form.'.$item}) { + $reorderings{$item} = 1; + $domconfig{'coursecategories'}{'cats'}{$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'}{'cats'}{$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'}{'cats'}{$newitem} = 0; + $adds{$newitem} = 1; + } + } + } + if ($env{'form.instcode'} eq '1') { + if (ref($cathash) eq 'HASH') { + my $newitem = 'instcode::0'; + if ($cathash->{$newitem} eq '') { + $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'}; + $adds{$newitem} = 1; + } + } else { + my $newitem = 'instcode::0'; + $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.instcode_pos'}; + $adds{$newitem} = 1; + } + } + if ($env{'form.communities'} eq '1') { + if (ref($cathash) eq 'HASH') { + my $newitem = 'communities::0'; + if ($cathash->{$newitem} eq '') { + $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'}; + $adds{$newitem} = 1; + } + } else { + my $newitem = 'communities::0'; + $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.communities_pos'}; + $adds{$newitem} = 1; + } + } + if ($env{'form.addcategory_name'} ne '') { + if (($env{'form.addcategory_name'} ne 'instcode') && + ($env{'form.addcategory_name'} ne 'communities')) { + my $newitem = &escape($env{'form.addcategory_name'}).'::0'; + $domconfig{'coursecategories'}{'cats'}{$newitem} = $env{'form.addcategory_pos'}; + $adds{$newitem} = 1; + } + } + my $putresult; + if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) { + 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); + &Apache::loncommon::extract_categories($domconfig{'coursecategories'}{'cats'},\@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'}{'cats'}{$item} -= $chg; + } + $depth ++; + &recurse_check(\@chkcats,$domconfig{'coursecategories'}{'cats'},$depth,$name); + $depth --; + } + } + } + } + if ((keys(%changes) > 0) || (keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) { + $putresult = &Apache::lonnet::put_dom('configuration',\%domconfig,$dom); + if ($putresult eq 'ok') { + my %title = ( + togglecats => 'Show/Hide a course in catalog', + categorize => 'Assign a category to a course', + togglecatscomm => 'Show/Hide a community in catalog', + categorizecomm => 'Assign a category to a community', + ); + my %level = ( + dom => 'set in Domain ("Modify Course/Community")', + crs => 'set in Course ("Course Configuration")', + comm => 'set in Community ("Community Configuration")', + ); + $resulttext = &mt('Changes made:').'
      '; + if ($changes{'togglecats'}) { + $resulttext .= '
    • '.&mt("$title{'togglecats'} $level{$env{'form.togglecats'}}").'
    • '; + } + if ($changes{'categorize'}) { + $resulttext .= '
    • '.&mt("$title{'categorize'} $level{$env{'form.categorize'}}").'
    • '; + } + if ($changes{'togglecatscomm'}) { + $resulttext .= '
    • '.&mt("$title{'togglecatscomm'} $level{$env{'form.togglecatscomm'}}").'
    • '; + } + if ($changes{'categorizecomm'}) { + $resulttext .= '
    • '.&mt("$title{'categorizecomm'} $level{$env{'form.categorizecomm'}}").'
    • '; + } + if ((keys(%deletions) > 0) || (keys(%reorderings) > 0) || (keys(%adds) > 0)) { + my $cathash; + if (ref($domconfig{'coursecategories'}) eq 'HASH') { + $cathash = $domconfig{'coursecategories'}{'cats'}; + } else { + $cathash = {}; + } + my (@cats,@trails,%allitems); + &Apache::loncommon::extract_categories($cathash,\@cats,\@trails,\%allitems); + 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 and community categories'); + } + return $resulttext; +} + +sub modify_serverstatuses { + my ($dom,%domconfig) = @_; + my ($resulttext,%changes,%currserverstatus,%newserverstatus); + if (ref($domconfig{'serverstatuses'}) eq 'HASH') { + %currserverstatus = %{$domconfig{'serverstatuses'}}; + } + my @pages = &serverstatus_pages(); + foreach my $type (@pages) { + $newserverstatus{$type}{'namedusers'} = ''; + $newserverstatus{$type}{'machines'} = ''; + if (defined($env{'form.'.$type.'_namedusers'})) { + my @users = split(/,/,$env{'form.'.$type.'_namedusers'}); + my @okusers; + foreach my $user (@users) { + my ($uname,$udom) = split(/:/,$user); + if (($udom =~ /^$match_domain$/) && + (&Apache::lonnet::domain($udom)) && + ($uname =~ /^$match_username$/)) { + if (!grep(/^\Q$user\E/,@okusers)) { + push(@okusers,$user); + } + } + } + if (@okusers > 0) { + @okusers = sort(@okusers); + $newserverstatus{$type}{'namedusers'} = join(',',@okusers); + } + } + if (defined($env{'form.'.$type.'_machines'})) { + my @machines = split(/,/,$env{'form.'.$type.'_machines'}); + my @okmachines; + foreach my $ip (@machines) { + my @parts = split(/\./,$ip); + next if (@parts < 4); + my $badip = 0; + for (my $i=0; $i<4; $i++) { + if (!(($parts[$i] >= 0) && ($parts[$i] <= 255))) { + $badip = 1; + last; + } + } + if (!$badip) { + push(@okmachines,$ip); + } + } + @okmachines = sort(@okmachines); + $newserverstatus{$type}{'machines'} = join(',',@okmachines); + } + } + my %serverstatushash = ( + serverstatuses => \%newserverstatus, + ); + my %changes; + foreach my $type (@pages) { + foreach my $setting ('namedusers','machines') { + my (@current,@new); + if (ref($currserverstatus{$type}) eq 'HASH') { + if ($currserverstatus{$type}{$setting} ne '') { + @current = split(/,/,$currserverstatus{$type}{$setting}); + } + } + if ($newserverstatus{$type}{$setting} ne '') { + @new = split(/,/,$newserverstatus{$type}{$setting}); + } + if (@current > 0) { + if (@new > 0) { + foreach my $item (@current) { + if (!grep(/^\Q$item\E$/,@new)) { + $changes{$type}{$setting} = 1; + last; + } + } + foreach my $item (@new) { + if (!grep(/^\Q$item\E$/,@current)) { + $changes{$type}{$setting} = 1; + last; + } + } + } else { + $changes{$type}{$setting} = 1; + } + } elsif (@new > 0) { + $changes{$type}{$setting} = 1; + } + } + } + if (keys(%changes) > 0) { + my $titles= &LONCAPA::lonauthcgi::serverstatus_titles(); + my $putresult = &Apache::lonnet::put_dom('configuration', + \%serverstatushash,$dom); + if ($putresult eq 'ok') { + $resulttext .= &mt('Changes made:').'
      '; + foreach my $type (@pages) { + if (ref($changes{$type}) eq 'HASH') { + $resulttext .= '
    • '.$titles->{$type}.'
        '; + if ($changes{$type}{'namedusers'}) { + if ($newserverstatus{$type}{'namedusers'} eq '') { + $resulttext .= '
      • '.&mt("Access terminated for all specific (named) users").'
      • '."\n"; + } else { + $resulttext .= '
      • '.&mt("Access available for the following specified users: ").$newserverstatus{$type}{'namedusers'}.'
      • '."\n"; + } + } + if ($changes{$type}{'machines'}) { + if ($newserverstatus{$type}{'machines'} eq '') { + $resulttext .= '
      • '.&mt("Access terminated for all specific IP addresses").'
      • '."\n"; + } else { + $resulttext .= '
      • '.&mt("Access available for the following specified IP addresses: ").$newserverstatus{$type}{'machines'}.'
      • '."\n"; + } + } + $resulttext .= '
    • '; + } + } + $resulttext .= '
    '; + } else { + $resulttext = ''. + &mt('An error occurred saving access settings for server status pages: [_1].',$putresult).''; + + } + } else { + $resulttext = &mt('No changes made to access to server status pages'); + } + return $resulttext; +} + +sub modify_helpsettings { + my ($r,$dom,$confname,%domconfig) = @_; + my ($resulttext,$errors,%changes,%helphash); + + my $customhelpfile = $env{'form.loginhelpurl.filename'}; + my $defaulthelpfile = 'defaulthelp.html'; + my $servadm = $r->dir_config('lonAdmEMail'); + my ($configuserok,$author_ok,$switchserver) = + &config_check($dom,$confname,$servadm); + + my %defaultchecked = ('submitbugs' => 'on'); + my @offon = ('off','on'); + my %title = ( submitbugs => 'Display link for users to submit a bug', + loginhelpurl => 'Unauthenticated login help page set to custom file'); + + my @toggles = ('submitbugs'); + + $helphash{'helpsettings'} = {}; + + if (ref($domconfig{'helpsettings'}) ne 'HASH') { + if ($domconfig{'helpsettings'} eq '') { + $domconfig{'helpsettings'} = {}; + } + } + + if (ref($domconfig{'helpsettings'}) eq 'HASH') { + + foreach my $item (@toggles) { + + if ($defaultchecked{$item} eq 'on') { + if (($domconfig{'helpsettings'}{$item} eq '') && + ($env{'form.'.$item} eq '0')) { + $changes{$item} = 1; + } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) { + $changes{$item} = 1; + } + } elsif ($defaultchecked{$item} eq 'off') { + if (($domconfig{'helpsettings'}{$item} eq '') && + ($env{'form.'.$item} eq '1')) { + $changes{$item} = 1; + } elsif ($domconfig{'helpsettings'}{$item} ne $env{'form.'.$item}) { + $changes{$item} = 1; + } + } + $helphash{'helpsettings'}{$item} = $env{'form.'.$item}; + } + + if ($customhelpfile ne '') { + my $error; + if ($configuserok eq 'ok') { + if ($switchserver) { + $error = &mt("Upload of custom help file is not permitted to this server: [_1]",$switchserver); + } else { + if ($author_ok eq 'ok') { + my ($result,$loginhelpurl) = + &publishlogo($r,'upload','loginhelpurl',$dom, + $confname,'help','','',$customhelpfile); + if ($result eq 'ok') { + $helphash{'helpsettings'}{'loginhelpurl'} = $loginhelpurl; + $changes{'loginhelpurl'} = 1; + } else { + $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$customhelpfile,$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].",$customhelpfile,$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].",$customhelpfile,$confname,$dom,$configuserok); + } + if ($error) { + &Apache::lonnet::logthis($error); + $errors .= '
  • '.$error.'
  • '; + } + } + + if ($domconfig{'helpsettings'}{'loginhelpurl'} ne '') { + if ($env{'form.loginhelpurl_del'}) { + $helphash{'helpsettings'}{'loginhelpurl'} = ''; + $changes{'loginhelpurl'} = 1; + } + } + } + + + my $putresult; + + if (keys(%changes) > 0) { + $putresult = &Apache::lonnet::put_dom('configuration',\%helphash,$dom); + } else { + $putresult = 'ok'; + } + + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + $resulttext = &mt('Changes made:').'
      '; + foreach my $item (sort(keys(%changes))) { + if ($item eq 'submitbugs') { + $resulttext .= '
    • '.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'
    • '; + } + if ($item eq 'loginhelpurl') { + if ($helphash{'helpsettings'}{'loginhelpurl'} eq '') { + $resulttext .= '
    • '.&mt('[_1] help file removed; [_2] file will be used for the unathorized help page in this domain.',$customhelpfile,$defaulthelpfile).'
    • '; + } else { + $resulttext .= '
    • '.&mt("$title{$item} [_1]",$customhelpfile).'
    • '; + } + } + } + $resulttext .= '
    '; + } else { + $resulttext = &mt('No changes made to help settings'); + } + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + if ($errors) { + $resulttext .= &mt('The following errors occurred: ').'
      '. + $errors.'
    '; + } + return $resulttext; +} + +sub modify_coursedefaults { + my ($dom,%domconfig) = @_; + my ($resulttext,$errors,%changes,%defaultshash); + my %defaultchecked = ('canuse_pdfforms' => 'off'); + my @offon = ('off','on'); + my @toggles = ('canuse_pdfforms'); + + $defaultshash{'coursedefaults'} = {}; + + if (ref($domconfig{'coursedefaults'}) ne 'HASH') { + if ($domconfig{'coursedefaults'} eq '') { + $domconfig{'coursedefaults'} = {}; + } + } + + if (ref($domconfig{'coursedefaults'}) eq 'HASH') { + foreach my $item (@toggles) { + if ($defaultchecked{$item} eq 'on') { + if (($domconfig{'coursedefaults'}{$item} eq '') && + ($env{'form.'.$item} eq '0')) { + $changes{$item} = 1; + } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) { + $changes{$item} = 1; + } + } elsif ($defaultchecked{$item} eq 'off') { + if (($domconfig{'coursedefaults'}{$item} eq '') && + ($env{'form.'.$item} eq '1')) { + $changes{$item} = 1; + } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) { + $changes{$item} = 1; + } + } + $defaultshash{'coursedefaults'}{$item} = $env{'form.'.$item}; + } + my $currdefresponder = $domconfig{'coursedefaults'}{'anonsurvey_threshold'}; + my $newdefresponder = $env{'form.anonsurvey_threshold'}; + $newdefresponder =~ s/\D//g; + if ($newdefresponder eq '' || $newdefresponder < 1) { + $newdefresponder = 1; + } + $defaultshash{'coursedefaults'}{'anonsurvey_threshold'} = $newdefresponder; + if ($currdefresponder ne $newdefresponder) { + unless ($currdefresponder eq '' && $newdefresponder == 10) { + $changes{'anonsurvey_threshold'} = 1; + } + } + } + my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash, + $dom); + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + if ($changes{'canuse_pdfforms'}) { + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'}; + my $cachetime = 24*60*60; + &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); + } + $resulttext = &mt('Changes made:').'
      '; + foreach my $item (sort(keys(%changes))) { + if ($item eq 'canuse_pdfforms') { + if ($env{'form.'.$item} eq '1') { + $resulttext .= '
    • '.&mt("Course/Community users can create/upload PDF forms set to 'on'").'
    • '; + } else { + $resulttext .= '
    • '.&mt('Course/Community users can create/upload PDF forms set to "off"').'
    • '; + } + } elsif ($item eq 'anonsurvey_threshold') { + $resulttext .= '
    • '.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'
    • '; + } + + } + $resulttext .= '
    '; + } else { + $resulttext = &mt('No changes made to course defaults'); + } + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + 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 dom_servers { + my ($dom) = @_; + my (%uniqservers,%servers); + my $primaryserver = &Apache::lonnet::hostname(&Apache::lonnet::domain($dom,'primary')); + my @machinedoms = &Apache::lonnet::machine_domains($primaryserver); + foreach my $mdom (@machinedoms) { + my %currservers = %servers; + my %server = &Apache::lonnet::get_servers($mdom); + %servers = (%currservers,%server); + } + my %by_hostname; + foreach my $id (keys(%servers)) { + push(@{$by_hostname{$servers{$id}}},$id); + } + foreach my $hostname (sort(keys(%by_hostname))) { + if (@{$by_hostname{$hostname}} > 1) { + my $match = 0; + foreach my $id (@{$by_hostname{$hostname}}) { + if (&Apache::lonnet::host_domain($id) eq $dom) { + $uniqservers{$id} = $hostname; + $match = 1; + } + } + unless ($match) { + $uniqservers{$by_hostname{$hostname}[0]} = $hostname; + } + } else { + $uniqservers{$by_hostname{$hostname}[0]} = $hostname; + } + } + return %uniqservers; +} + +1; 500 Internal Server Error

    Internal Server Error

    The server encountered an internal error or misconfiguration and was unable to complete your request.

    Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

    More information about this error may be available in the server error log.