--- loncom/interface/domainprefs.pm 2013/02/02 02:48:47 1.190 +++ loncom/interface/domainprefs.pm 2014/03/29 20:35:21 1.231 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set domain-wide configuration settings # -# $Id: domainprefs.pm,v 1.190 2013/02/02 02:48:47 raeburn Exp $ +# $Id: domainprefs.pm,v 1.231 2014/03/29 20:35:21 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -86,7 +86,7 @@ $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 (quotas, +number of rows displayed on the page, and $action is the context (quotas, requestcourses or requestauthor). The print_quotas routine was orginally created to display/store information @@ -94,7 +94,8 @@ about default quota sizes for portfolio 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. +used by course owners to request creation of a course, and to display/store +default quota sizes for Authoring Spaces. Outputs: 1 @@ -102,8 +103,8 @@ $datatable - HTML containing form eleme 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: +(official, unofficial, community, and textbook). 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: @@ -212,13 +213,13 @@ sub handler { 'contacts','defaults','scantron','coursecategories', 'serverstatuses','requestcourses','helpsettings', 'coursedefaults','usersessions','loadbalancing', - 'requestauthor'],$dom); + 'requestauthor','selfenrollment'],$dom); my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll', 'autoupdate','autocreate','directorysrch','contacts', - 'usercreation','usermodification','scantron', + 'usercreation','selfcreation','usermodification','scantron', 'requestcourses','requestauthor','coursecategories', 'serverstatuses','helpsettings', - 'coursedefaults','usersessions'); + 'coursedefaults','selfenrollment','usersessions'); my %existing; if (ref($domconfig{'loadbalancing'}) eq 'HASH') { %existing = %{$domconfig{'loadbalancing'}}; @@ -238,6 +239,8 @@ sub handler { col2 => '',}, {col1 => 'Administrator Settings', col2 => '',}], + print => \&print_rolecolors, + modify => \&modify_rolecolors, }, 'login' => { text => 'Log-in page options', @@ -246,25 +249,33 @@ sub handler { col2 => '',}, {col1 => 'Log-in Help', col2 => 'Value'}], + print => \&print_login, + modify => \&modify_login, }, 'defaults' => { text => 'Default authentication/language/timezone/portal', help => 'Domain_Configuration_LangTZAuth', header => [{col1 => 'Setting', col2 => 'Value'}], + print => \&print_defaults, + modify => \&modify_defaults, }, 'quotas' => - { text => 'Blogs, personal web pages, webDAV, portfolios', + { text => 'Blogs, personal web pages, webDAV/quotas, portfolios', help => 'Domain_Configuration_Quotas', header => [{col1 => 'User affiliation', col2 => 'Available tools', - col3 => 'Portfolio quota',}], + col3 => 'Quotas, MB; (Authoring requires role)',}], + print => \&print_quotas, + modify => \&modify_quotas, }, 'autoenroll' => { text => 'Auto-enrollment settings', help => 'Domain_Configuration_Auto_Enrollment', header => [{col1 => 'Configuration setting', col2 => 'Value(s)'}], + print => \&print_autoenroll, + modify => \&modify_autoenroll, }, 'autoupdate' => { text => 'Auto-update settings', @@ -274,27 +285,34 @@ sub handler { {col1 => 'Setting', col2 => 'Affiliation'}, {col1 => 'User population', - col2 => 'Updateable user data'}], + col2 => 'Updatable user data'}], + print => \&print_autoupdate, + modify => \&modify_autoupdate, }, 'autocreate' => { text => 'Auto-course creation settings', help => 'Domain_Configuration_Auto_Creation', header => [{col1 => 'Configuration Setting', col2 => 'Value',}], + print => \&print_autocreate, + modify => \&modify_autocreate, }, 'directorysrch' => { text => 'Institutional directory searches', help => 'Domain_Configuration_InstDirectory_Search', header => [{col1 => 'Setting', col2 => 'Value',}], + print => \&print_directorysrch, + modify => \&modify_directorysrch, }, 'contacts' => { text => 'Contact Information', help => 'Domain_Configuration_Contact_Info', header => [{col1 => 'Setting', col2 => 'Value',}], + print => \&print_contacts, + modify => \&modify_contacts, }, - 'usercreation' => { text => 'User creation', help => 'Domain_Configuration_User_Creation', @@ -304,16 +322,30 @@ sub handler { col2 => 'Usernames which may be created',}, {col1 => 'Context', col2 => 'Assignable authentication types'}], + print => \&print_usercreation, + modify => \&modify_usercreation, + }, + 'selfcreation' => + { text => 'Users self-creating accounts', + help => 'Domain_Configuration_Self_Creation', + header => [{col1 => 'Self-creation with institutional username', + col2 => 'Enabled?'}, + {col1 => 'Institutional user type (login/SSO self-creation)', + col2 => 'Information user can enter'}, + {col1 => 'Self-creation with e-mail as username', + col2 => 'Settings'}], + print => \&print_selfcreation, + modify => \&modify_selfcreation, }, 'usermodification' => { text => 'User modification', help => 'Domain_Configuration_User_Modification', header => [{col1 => 'Target user has role', - col2 => 'User information updateable in author context'}, + col2 => 'User information updatable 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)'}], + col2 => 'User information updatable in course context'}], + print => \&print_usermodification, + modify => \&modify_usermodification, }, 'scantron' => { text => 'Bubblesheet format file', @@ -321,6 +353,8 @@ sub handler { header => [ {col1 => 'Item', col2 => '', }], + print => \&print_scantron, + modify => \&modify_scantron, }, 'requestcourses' => {text => 'Request creation of courses', @@ -328,15 +362,21 @@ sub handler { header => [{col1 => 'User affiliation', col2 => 'Availability/Processing of requests',}, {col1 => 'Setting', - col2 => 'Value'}], + col2 => 'Value'}, + {col1 => 'Available textbooks', + col2 => ''}], + print => \&print_quotas, + modify => \&modify_quotas, }, 'requestauthor' => - {text => 'Request authoring space', + {text => 'Request Authoring Space', help => 'Domain_Configuration_Request_Author', header => [{col1 => 'User affiliation', col2 => 'Availability/Processing of requests',}, {col1 => 'Setting', col2 => 'Value'}], + print => \&print_quotas, + modify => \&modify_quotas, }, 'coursecategories' => { text => 'Cataloging of courses/communities', @@ -346,6 +386,8 @@ sub handler { {col1 => 'Categories', col2 => '', }], + print => \&print_coursecategories, + modify => \&modify_coursecategories, }, 'serverstatuses' => {text => 'Access to server status pages', @@ -354,12 +396,16 @@ sub handler { col2 => 'Other named users', col3 => 'Specific IPs', }], + print => \&print_serverstatuses, + modify => \&modify_serverstatuses, }, 'helpsettings' => {text => 'Help page settings', help => 'Domain_Configuration_Help_Settings', header => [{col1 => 'Help Settings (logged-in users)', col2 => 'Value'}], + print => \&print_helpsettings, + modify => \&modify_helpsettings, }, 'coursedefaults' => {text => 'Course/Community defaults', @@ -368,12 +414,28 @@ sub handler { col2 => 'Value',}, {col1 => 'Defaults which can be overridden for each course by a DC', col2 => 'Value',},], + print => \&print_coursedefaults, + modify => \&modify_coursedefaults, + }, + 'selfenrollment' => + {text => 'Self-enrollment in Course/Community', + help => 'Domain_Configuration_Selfenrollment', + header => [{col1 => 'Configuration Rights', + col2 => 'Configured by Course Personnel or Domain Coordinator?'}, + {col1 => 'Defaults', + col2 => 'Value'}, + {col1 => 'Self-enrollment validation (optional)', + col2 => 'Value'},], + print => \&print_selfenrollment, + modify => \&modify_selfenrollment, }, 'privacy' => {text => 'User Privacy', help => 'Domain_Configuration_User_Privacy', header => [{col1 => 'Setting', col2 => 'Value',}], + print => \&print_privacy, + modify => \&modify_privacy, }, 'usersessions' => {text => 'User session hosting/offloading', @@ -384,6 +446,8 @@ sub handler { col2 => 'Rules'}, {col1 => "Hosting domain's own users elsewhere", col2 => 'Rules'}], + print => \&print_usersessions, + modify => \&modify_usersessions, }, 'loadbalancing' => {text => 'Dedicated Load Balancer(s)', @@ -393,6 +457,8 @@ sub handler { col3 => 'User affiliation', col4 => 'Overrides'}, ], + print => \&print_loadbalancing, + modify => \&modify_loadbalancing, }, ); if (keys(%servers) > 1) { @@ -404,6 +470,8 @@ sub handler { col2 => ''}, {col1 => 'Log-in Help', col2 => 'Value'}], + print => \&print_login, + modify => \&modify_login, }; } @@ -415,9 +483,15 @@ sub handler { my $confname = $dom.'-domainconfig'; if ($phase eq 'process') { - &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,\@roles); + my $result = &Apache::lonconfigsettings::make_changes($r,$dom,$phase,$context,\@prefs_order, + \%prefs,\%domconfig,$confname,\@roles); + if ((ref($result) eq 'HASH') && (keys(%{$result}))) { + $r->rflush(); + &devalidate_remote_domconfs($dom,$result); + } } elsif ($phase eq 'display') { - my $js = &recaptcha_js(); + my $js = &recaptcha_js(). + &credits_js(); if ((keys(%servers) > 1) || (keys(%existing) > 0)) { my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); @@ -427,6 +501,16 @@ sub handler { &common_domprefs_js(). &Apache::loncommon::javascript_array_indexof(); } + if (grep(/^requestcourses$/,@actions)) { + my $javascript_validations; + my $coursebrowserjs=&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}); + $js .= < +$javascript_validations + +$coursebrowserjs +END + } &Apache::lonconfigsettings::display_settings($r,$dom,$phase,$context,\@prefs_order,\%prefs,\%domconfig,$confname,$js); } else { # check if domconfig user exists for the domain. @@ -436,7 +520,7 @@ sub handler { unless ($configuserok eq 'ok') { &Apache::lonconfigsettings::print_header($r,$phase,$context); $r->print(&mt('The domain configuration user "[_1]" has yet to be created.', - $confname). + $confname). '
' ); if ($switchserver) { @@ -496,21 +580,21 @@ sub handler { } sub process_changes { - my ($r,$dom,$confname,$action,$roles,$values) = @_; + my ($r,$dom,$confname,$action,$roles,$values,$lastactref) = @_; my %domconfig; if (ref($values) eq 'HASH') { %domconfig = %{$values}; } my $output; if ($action eq 'login') { - $output = &modify_login($r,$dom,$confname,%domconfig); + $output = &modify_login($r,$dom,$confname,$lastactref,%domconfig); } elsif ($action eq 'rolecolors') { $output = &modify_rolecolors($r,$dom,$confname,$roles, - %domconfig); + $lastactref,%domconfig); } elsif ($action eq 'quotas') { - $output = &modify_quotas($dom,$action,%domconfig); + $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); } elsif ($action eq 'autoenroll') { - $output = &modify_autoenroll($dom,%domconfig); + $output = &modify_autoenroll($dom,$lastactref,%domconfig); } elsif ($action eq 'autoupdate') { $output = &modify_autoupdate($dom,%domconfig); } elsif ($action eq 'autocreate') { @@ -519,28 +603,32 @@ sub process_changes { $output = &modify_directorysrch($dom,%domconfig); } elsif ($action eq 'usercreation') { $output = &modify_usercreation($dom,%domconfig); + } elsif ($action eq 'selfcreation') { + $output = &modify_selfcreation($dom,%domconfig); } elsif ($action eq 'usermodification') { $output = &modify_usermodification($dom,%domconfig); } elsif ($action eq 'contacts') { - $output = &modify_contacts($dom,%domconfig); + $output = &modify_contacts($dom,$lastactref,%domconfig); } elsif ($action eq 'defaults') { - $output = &modify_defaults($dom,$r); + $output = &modify_defaults($dom,$lastactref,%domconfig); } elsif ($action eq 'scantron') { - $output = &modify_scantron($r,$dom,$confname,%domconfig); + $output = &modify_scantron($r,$dom,$confname,$lastactref,%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); + $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); } elsif ($action eq 'requestauthor') { - $output = &modify_quotas($dom,$action,%domconfig); + $output = &modify_quotas($r,$dom,$action,$lastactref,%domconfig); } elsif ($action eq 'helpsettings') { $output = &modify_helpsettings($r,$dom,$confname,%domconfig); } elsif ($action eq 'coursedefaults') { - $output = &modify_coursedefaults($dom,%domconfig); + $output = &modify_coursedefaults($dom,$lastactref,%domconfig); + } elsif ($action eq 'selfenrollment') { + $output = &modify_selfenrollment($dom,$lastactref,%domconfig) } elsif ($action eq 'usersessions') { - $output = &modify_usersessions($dom,%domconfig); + $output = &modify_usersessions($dom,$lastactref,%domconfig); } elsif ($action eq 'loadbalancing') { $output = &modify_loadbalancing($dom,%domconfig); } @@ -569,7 +657,7 @@ sub print_config_box { if ($numheaders > 1) { my $colspan = ''; my $rightcolspan = ''; - if (($action eq 'rolecolors') || ($action eq 'coursecategories') || + if (($action eq 'rolecolors') || ($action eq 'coursecategories') || (($action eq 'login') && ($numheaders < 3))) { $colspan = ' colspan="2"'; } @@ -585,14 +673,12 @@ sub print_config_box { '.&mt($item->{'header'}->[0]->{'col2'}).' '; $rowtotal ++; - if ($action eq 'autoupdate') { - $output .= &print_autoupdate('top',$dom,$settings,\$rowtotal); - } elsif ($action eq 'usercreation') { - $output .= &print_usercreation('top',$dom,$settings,\$rowtotal); - } elsif ($action eq 'usermodification') { - $output .= &print_usermodification('top',$dom,$settings,\$rowtotal); + if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') || + ($action eq 'usermodification') || ($action eq 'coursedefaults') || + ($action eq 'selfenrollment') || ($action eq 'usersessions')) { + $output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'coursecategories') { - $output .= &print_coursecategories('top',$dom,$item,$settings,\$rowtotal); + $output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal); } elsif ($action eq 'login') { if ($numheaders == 3) { $colspan = ' colspan="2"'; @@ -600,16 +686,10 @@ sub print_config_box { } else { $output .= &print_login('page',$dom,$confname,$phase,$settings,\$rowtotal); } - } elsif ($action eq 'requestcourses') { - $output .= &print_quotas($dom,$settings,\$rowtotal,$action); - } elsif ($action eq 'requestauthor') { + } elsif (($action eq 'requestcourses') || ($action eq 'requestauthor')) { $output .= &print_quotas($dom,$settings,\$rowtotal,$action); - } elsif ($action eq 'usersessions') { - $output .= &print_usersessions('top',$dom,$settings,\$rowtotal); } elsif ($action eq 'rolecolors') { $output .= &print_rolecolors($phase,'student',$dom,$confname,$settings,\$rowtotal); - } elsif ($action eq 'coursedefaults') { - $output .= &print_coursedefaults('top',$dom,$settings,\$rowtotal); } $output .= ' @@ -619,13 +699,14 @@ sub print_config_box { - '; - $output .= ' + '; $rowtotal ++; - if ($action eq 'autoupdate') { - $output .= &print_autoupdate('middle',$dom,$settings,\$rowtotal).' + if (($action eq 'autoupdate') || ($action eq 'usercreation') || + ($action eq 'selfcreation') || ($action eq 'selfenrollment') || + ($action eq 'usersessions')) { + $output .= $item->{'print'}->('middle',$dom,$settings,\$rowtotal).'
'.&mt($item->{'header'}->[1]->{'col1'}).''.&mt($item->{'header'}->[1]->{'col1'}).' '.&mt($item->{'header'}->[1]->{'col2'}).'
@@ -634,35 +715,12 @@ sub print_config_box { - '. - &print_autoupdate('bottom',$dom,$settings,\$rowtotal); - $rowtotal ++; - } elsif ($action eq 'usercreation') { - $output .= &print_usercreation('middle',$dom,$settings,\$rowtotal).' -
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'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); + + '."\n". + $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); $rowtotal ++; + } elsif (($action eq 'usermodification') || ($action eq 'coursedefaults')) { + $output .= $item->{'print'}->('bottom',$dom,$settings,\$rowtotal); } elsif ($action eq 'coursecategories') { $output .= &print_coursecategories('bottom',$dom,$item,$settings,\$rowtotal); } elsif ($action eq 'login') { @@ -676,18 +734,15 @@ sub print_config_box {
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
'.&mt($item->{'header'}->[2]->{'col2'}).'
- '. + '. &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal); $rowtotal ++; } else { $output .= &print_login('help',$dom,$confname,$phase,$settings,\$rowtotal); } } elsif ($action eq 'requestcourses') { - $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); - } elsif ($action eq 'requestauthor') { - $output .= &print_requestmail($dom,$action,$settings,\$rowtotal); - } elsif ($action eq 'usersessions') { - $output .= &print_usersessions('middle',$dom,$settings,\$rowtotal).' + $output .= &print_requestmail($dom,$action,$settings,\$rowtotal). + &print_studentcode($settings,\$rowtotal).'
'.&mt($item->{'header'}->[2]->{'col1'}).''.&mt($item->{'header'}->[2]->{'col2'}).'
'.&mt($item->{'header'}->[2]->{'col2'}).'
@@ -696,11 +751,10 @@ sub print_config_box { - '. - &print_usersessions('bottom',$dom,$settings,\$rowtotal); - $rowtotal ++; - } elsif ($action eq 'coursedefaults') { - $output .= &print_coursedefaults('bottom',$dom,$settings,\$rowtotal); + '. + &print_textbookcourses($dom,$settings,\$rowtotal); + } elsif ($action eq 'requestauthor') { + $output .= &print_requestmail($dom,$action,$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'}).'
'.&mt($item->{'header'}->[2]->{'col2'}).'
@@ -779,24 +833,14 @@ sub print_config_box { $rowtotal ++; if ($action eq 'quotas') { $output .= &print_quotas($dom,$settings,\$rowtotal,$action); - } elsif ($action eq 'autoenroll') { - $output .= &print_autoenroll($dom,$settings,\$rowtotal); - } elsif ($action eq 'autocreate') { - $output .= &print_autocreate($dom,$settings,\$rowtotal); - } elsif ($action eq 'directorysrch') { - $output .= &print_directorysrch($dom,$settings,\$rowtotal); - } elsif ($action eq 'contacts') { - $output .= &print_contacts($dom,$settings,\$rowtotal); - } elsif ($action eq 'defaults') { - $output .= &print_defaults($dom,\$rowtotal); + } elsif (($action eq 'autoenroll') || ($action eq 'autocreate') || ($action eq 'directorysrch') || + ($action eq 'contacts') || ($action eq 'defaults') || ($action eq 'serverstatuses') || + ($action eq 'loadbalancing')) { + $output .= $item->{'print'}->($dom,$settings,\$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($dom,$confname,$settings,\$rowtotal); - } elsif ($action eq 'loadbalancing') { - $output .= &print_loadbalancing($dom,$settings,\$rowtotal); } } $output .= ' @@ -1140,17 +1184,7 @@ sub print_rolecolors { my %designhash = &Apache::loncommon::get_domainconf($dom); my %defaultdesign = %Apache::loncommon::defaultdesign; my (%is_custom,%designs); - my %defaults = ( - img => $defaultdesign{$role.'.img'}, - font => $defaultdesign{$role.'.font'}, - fontmenu => $defaultdesign{$role.'.fontmenu'}, - ); - foreach my $item (@bgs) { - $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; - } - foreach my $item (@links) { - $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item}; - } + my %defaults = &role_defaults($role,\@bgs,\@links,\@images); if (ref($settings) eq 'HASH') { if (ref($settings->{$role}) eq 'HASH') { if ($settings->{$role}->{'img'} ne '') { @@ -1211,6 +1245,44 @@ sub print_rolecolors { return $datatable; } +sub role_defaults { + my ($role,$bgs,$links,$images,$logintext) = @_; + my %defaults; + unless ((ref($bgs) eq 'ARRAY') && (ref($links) eq 'ARRAY') && (ref($images) eq 'ARRAY')) { + return %defaults; + } + my %defaultdesign = %Apache::loncommon::defaultdesign; + if ($role eq 'login') { + %defaults = ( + font => $defaultdesign{$role.'.font'}, + ); + if (ref($logintext) eq 'ARRAY') { + foreach my $item (@{$logintext}) { + $defaults{'logintext'}{$item} = $defaultdesign{$role.'.'.$item}; + } + } + foreach my $item (@{$images}) { + $defaults{'showlogo'}{$item} = 1; + } + } else { + %defaults = ( + img => $defaultdesign{$role.'.img'}, + font => $defaultdesign{$role.'.font'}, + fontmenu => $defaultdesign{$role.'.fontmenu'}, + ); + } + foreach my $item (@{$bgs}) { + $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item}; + } + foreach my $item (@{$links}) { + $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item}; + } + foreach my $item (@{$images}) { + $defaults{$item} = $defaultdesign{$role.'.'.$item}; + } + return %defaults; +} + sub display_color_options { my ($dom,$confname,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs, $images,$bgs,$links,$alt_text,$rowtotal,$logintext) = @_; @@ -1227,7 +1299,7 @@ sub display_color_options { $datatable .= ''. ' '. + ' value="'.$current_color.'" /> '. ' '; unless ($role eq 'login') { $datatable .= ''. @@ -1237,7 +1309,7 @@ sub display_color_options { } else { $datatable .= ' '; } - $current_color = $designs->{'fontmenu'} ? + $current_color = $designs->{'fontmenu'} ? $designs->{'fontmenu'} : $defaults->{'fontmenu'}; $datatable .= ''. '
'. - &mt('Upload:'); + $datatable .= ' '. + &mt('Upload:').'
'; } } else { - $datatable .= '
'. - &mt('Upload:'); + $datatable .= ' '. + &mt('Upload:').'
'; } if ($switchserver) { $datatable .= &mt('Upload to library server: [_1]',$switchserver); @@ -1372,7 +1444,7 @@ sub display_color_options { ''; foreach my $item (@{$bgs}) { - $datatable .= '
'; + $datatable .= ''.$choices->{$item}; my $color = $designs->{'bgs'}{$item} ? $designs->{'bgs'}{$item} : $defaults->{'bgs'}{$item}; if ($designs->{'bgs'}{$item}) { $datatable .= ' '; @@ -1400,8 +1472,7 @@ sub display_color_options { ''; foreach my $item (@{$links}) { my $color = $designs->{'link'}{$item} ? $designs->{'link'}{$item} : $defaults->{'links'}{$item}; - $datatable .= ''; + '" size="5" />'.(' ' x 2). + ''.&mt('Authoring').': '. + ''; } $datatable .= ''; } @@ -1675,12 +1742,16 @@ sub print_quotas { } unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { $defaultquota = '20'; + $authorquota = '500'; if (ref($settings) eq 'HASH') { if (ref($settings->{'defaultquota'}) eq 'HASH') { $defaultquota = $settings->{'defaultquota'}->{'default'}; } elsif (defined($settings->{'default'})) { $defaultquota = $settings->{'default'}; } + if (ref($settings->{'authorquota'}) eq 'HASH') { + $authorquota = $settings->{'authorquota'}->{'default'}; + } } } $typecount ++; @@ -1791,15 +1862,19 @@ sub print_quotas { } $datatable .= ''; unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { - $datatable .= ''; + $defaultquota.'" size="5" />'.(' ' x2). + ''.&mt('Authoring').': '. + ''; } $datatable .= ''; $typecount ++; $css_class = $typecount%2?' class="LC_odd_row"':''; $datatable .= ''. - ''. @@ -1926,87 +2001,251 @@ sub print_quotas { sub print_requestmail { my ($dom,$action,$settings,$rowtotal) = @_; - my ($now,$datatable,%dompersonnel,@domcoord,@currapproval,$rows); + my ($now,$datatable,%currapp); $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); + map {$currapp{$_}=1;} split(/,/,$settings->{'notify'}{'approval'}); } } } - @domcoord = sort(@domcoord); - my $numinrow = 4; - my $numdc = @domcoord; - my $css_class = 'class="LC_odd_row"'; + my $numinrow = 2; + my $css_class; + $css_class = ($$rowtotal%2? ' class="LC_odd_row"':''); my $text; if ($action eq 'requestcourses') { $text = &mt('Receive notification of course requests requiring approval'); + } elsif ($action eq 'requestauthor') { + $text = &mt('Receive notification of Authoring Space requests requiring approval'); } else { - $text = &mt('Receive notification of authoring space requests requiring approval') + $text = &mt('Receive notification of queued requests for self-created user accounts requiring approval'); } - $datatable = ''. + $datatable = ''. ' '. ' '; - $$rowtotal += $rows; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'addbook_pos'".');"'; + $datatable .= ''."\n". + ''."\n". + ''."\n"; + $itemcount ++; return $datatable; } +sub textbookcourses_javascript { + my ($textbooks) = @_; + return unless(ref($textbooks) eq 'HASH'); + my $num = scalar(keys(%{$textbooks})); + my @jsarray; + foreach my $item (sort {$a <=> $b } (keys(%{$textbooks}))) { + push(@jsarray,$textbooks->{$item}); + } + my $jstext = ' var textbooks = Array('."'".join("','",@jsarray)."'".');'."\n"; + return <<"ENDSCRIPT"; + + +ENDSCRIPT +} + sub print_autoenroll { my ($dom,$settings,$rowtotal) = @_; my $autorun = &Apache::lonnet::auto_run(undef,$dom), @@ -2155,8 +2394,7 @@ sub print_autoupdate { sub print_autocreate { my ($dom,$settings,$rowtotal) = @_; - my (%createon,%createoff); - my $curr_dc; + my (%createon,%createoff,%currhash); my @types = ('xml','req'); if (ref($settings) eq 'HASH') { foreach my $item (@types) { @@ -2169,7 +2407,9 @@ sub print_autocreate { } } } - $curr_dc = $settings->{'xmldc'}; + if ($settings->{'xmldc'} ne '') { + $currhash{$settings->{'xmldc'}} = 1; + } } else { foreach my $item (@types) { $createoff{$item} = ' checked="checked" '; @@ -2177,6 +2417,7 @@ sub print_autocreate { } } $$rowtotal += 2; + my $numinrow = 2; my $datatable=''. ''. ''; - $$rowtotal ++ ; } else { $datatable .= $dctable.''; } + $$rowtotal += $rows; return $datatable; } @@ -2322,7 +2564,7 @@ sub print_contacts { my @contacts = ('adminemail','supportemail'); my (%checked,%to,%otheremails,%bccemails); my @mailings = ('errormail','packagesmail','lonstatusmail','helpdeskmail', - 'requestsmail','updatesmail'); + 'requestsmail','updatesmail','idconflictsmail'); foreach my $type (@mailings) { $otheremails{$type} = ''; } @@ -2359,21 +2601,21 @@ sub print_contacts { $checked{'lonstatusmail'}{'adminemail'} = ' checked="checked" '; $checked{'requestsmail'}{'adminemail'} = ' checked="checked" '; $checked{'updatesmail'}{'adminemail'} = ' checked="checked" '; + $checked{'idconflictsmail'}{'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 .= ''. ''; + $rownum ++; } foreach my $type (@mailings) { - $rownum ++; $css_class = $rownum%2?' class="LC_odd_row"':''; $datatable .= ''. ''."\n"; + $rownum ++; } + my %choices; + $choices{'reporterrors'} = &mt('E-mail error reports to [_1]', + &Apache::loncommon::modal_link('http://loncapa.org/core.html', + &mt('LON-CAPA core group - MSU'),600,500)); + $choices{'reportupdates'} = &mt('E-mail record of completed LON-CAPA updates to [_1]', + &Apache::loncommon::modal_link('http://loncapa.org/core.html', + &mt('LON-CAPA core group - MSU'),600,500)); + my @toggles = ('reporterrors','reportupdates'); + my %defaultchecked = ('reporterrors' => 'on', + 'reportupdates' => 'on'); + (my $reports,$rownum) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, + \%choices,$rownum); + $datatable .= $reports; $$rowtotal += $rownum; return $datatable; } @@ -2418,7 +2674,8 @@ sub print_helpsettings { } sub radiobutton_prefs { - my ($settings,$toggles,$defaultchecked,$choices,$itemcount) = @_; + my ($settings,$toggles,$defaultchecked,$choices,$itemcount,$onclick, + $additional) = @_; return unless ((ref($toggles) eq 'ARRAY') && (ref($defaultchecked) eq 'HASH') && (ref($choices) eq 'HASH')); @@ -2444,17 +2701,22 @@ sub radiobutton_prefs { } } } + if ($onclick) { + $onclick = ' onclick="'.$onclick.'"'; + } foreach my $item (@{$toggles}) { $css_class = $itemcount%2?' class="LC_odd_row"':''; $datatable .= - ''. ''. + $checkedoff{$item}.' value="0"'.$onclick.' />'.&mt('No').''. + ''.$additional. + ''. ''; $itemcount ++; } @@ -2463,45 +2725,351 @@ sub radiobutton_prefs { sub print_coursedefaults { my ($position,$dom,$settings,$rowtotal) = @_; - my ($css_class,$datatable); + my ($css_class,$datatable,%checkedon,%checkedoff,%defaultchecked,@toggles); my $itemcount = 1; + my %choices = &Apache::lonlocal::texthash ( + canuse_pdfforms => 'Course/Community users can create/upload PDF forms', + uploadquota => 'Default quota for files uploaded directly to course/community using Course Editor (MB)', + anonsurvey_threshold => 'Responder count needed before showing submissions for anonymous surveys', + coursecredits => 'Credits can be specified for courses', + ); + my %staticdefaults = ( + anonsurvey_threshold => 10, + uploadquota => 500, + ); if ($position eq 'top') { - my (%checkedon,%checkedoff,%choices,%defaultchecked,@toggles); - %choices = - &Apache::lonlocal::texthash ( - canuse_pdfforms => 'Course/Community users can create/upload PDF forms', - ); %defaultchecked = ('canuse_pdfforms' => 'off'); - @toggles = ('canuse_pdfforms',); + @toggles = ('canuse_pdfforms'); ($datatable,$itemcount) = &radiobutton_prefs($settings,\@toggles,\%defaultchecked, \%choices,$itemcount); - $$rowtotal += $itemcount; } else { $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; + my ($currdefresponder,$def_official_credits,$def_unofficial_credits,$def_textbook_credits, + %curruploadquota); + my $currusecredits = 0; + my @types = ('official','unofficial','community','textbook'); if (ref($settings) eq 'HASH') { $currdefresponder = $settings->{'anonsurvey_threshold'}; + if (ref($settings->{'uploadquota'}) eq 'HASH') { + foreach my $type (keys(%{$settings->{'uploadquota'}})) { + $curruploadquota{$type} = $settings->{'uploadquota'}{$type}; + } + } + if (ref($settings->{'coursecredits'}) eq 'HASH') { + $def_official_credits = $settings->{'coursecredits'}->{'official'}; + $def_unofficial_credits = $settings->{'coursecredits'}->{'unofficial'}; + $def_textbook_credits = $settings->{'coursecredits'}->{'textbook'}; + if (($def_official_credits ne '') || ($def_unofficial_credits ne '') || + ($def_textbook_credits ne '')) { + $currusecredits = 1; + } + } } if (!$currdefresponder) { - $currdefresponder = 10; + $currdefresponder = $staticdefaults{'anonsurvey_threshold'}; } elsif ($currdefresponder < 1) { $currdefresponder = 1; } + foreach my $type (@types) { + if ($curruploadquota{$type} eq '') { + $curruploadquota{$type} = $staticdefaults{'uploadquota'}; + } + } $datatable .= - ''. ''; + ''."\n"; + $itemcount ++; + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + ''."\n"; + $itemcount ++; + my $onclick = 'toggleCredits(this.form);'; + my $display = 'none'; + if ($currusecredits) { + $display = 'block'; + } + my $additional = '
'. + ''. + &mt('Default credits for official courses [_1]', + ''). + '
'. + ''. + &mt('Default credits for unofficial courses [_1]', + ''). + '
'. + ''. + &mt('Default credits for textbook courses [_1]', + ''). + '
'."\n"; + %defaultchecked = ('coursecredits' => 'off'); + @toggles = ('coursecredits'); + my $current = { + 'coursecredits' => $currusecredits, + }; + (my $table,$itemcount) = + &radiobutton_prefs($current,\@toggles,\%defaultchecked, + \%choices,$itemcount,$onclick,$additional); + $datatable .= $table; + $itemcount ++; } + $$rowtotal += $itemcount; + return $datatable; +} + +sub print_selfenrollment { + my ($position,$dom,$settings,$rowtotal) = @_; + my ($css_class,$datatable); + my $itemcount = 1; + my @types = ('official','unofficial','community','textbook'); + if (($position eq 'top') || ($position eq 'middle')) { + my ($rowsref,$titlesref) = &get_selfenroll_titles(); + my %descs = &selfenroll_default_descs(); + my @rows; + my $key; + if ($position eq 'top') { + $key = 'admin'; + if (ref($rowsref) eq 'ARRAY') { + @rows = @{$rowsref}; + } + } elsif ($position eq 'middle') { + $key = 'default'; + @rows = ('types','registered','approval','limit'); + } + foreach my $row (@rows) { + if (defined($titlesref->{$row})) { + $itemcount ++; + $css_class = $itemcount%2?' class="LC_odd_row"':''; + $datatable .= ''. + ''. + ''; + } + } elsif ($position eq 'bottom') { + my ($itemsref,$namesref,$fieldsref) = &selfenroll_validation_types(); + my %currvalidation; + if (ref($settings) eq 'HASH') { + if (ref($settings->{'validation'}) eq 'HASH') { + %currvalidation = %{$settings->{'validation'}}; + } + } + foreach my $item (@{$itemsref}) { + $css_class = $itemcount%2 ? ' class="LC_odd_row"' : ''; + $datatable .= ''. + ''."\n"; + $itemcount ++; + } + } + $$rowtotal += $itemcount; return $datatable; } +sub get_selfenroll_titles { + my @row = ('types','registered','enroll_dates','access_dates','section', + 'approval','limit'); + my %lt = &Apache::lonlocal::texthash ( + types => 'Users allowed to self-enroll', + registered => 'Registration status (official courses)' , + enroll_dates => 'Dates self-enrollment available', + access_dates => 'Access dates for self-enrolling users', + section => 'Self-enrolling users section', + approval => 'Processing of requests', + limit => 'Enrollment limit', + ); + return (\@row,\%lt); +} + +sub selfenroll_default_descs { + my %desc = ( + types => { + dom => &mt('Course domain'), + all => &mt('Any domain'), + '' => &mt('None'), + }, + limit => { + none => &mt('No limit'), + allstudents => &mt('Limit by total students'), + selfenrolled => &mt('Limit by total self-enrolled'), + }, + approval => { + '0' => &mt('Processed automatically'), + '1' => &mt('Queued for approval'), + '2' => &mt('Queued, pending validation'), + }, + registered => { + 0 => 'No registration required', + 1 => 'Registered students only', + }, + ); + return %desc; +} + +sub selfenroll_validation_types { + my @items = ('url','fields','button','markup'); + my %names = &Apache::lonlocal::texthash ( + url => 'Web address of validation server/script', + fields => 'Form fields to send to validator', + button => 'Text for validation button', + markup => 'Validation description (HTML)', + ); + my @fields = ('username','domain','uniquecode','course','token'); + return (\@items,\%names,\@fields); +} + sub print_usersessions { my ($position,$dom,$settings,$rowtotal) = @_; my ($css_class,$datatable,%checked,%choices); @@ -2928,7 +3496,7 @@ sub print_loadbalancing { } my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); - my $rownum = 6; + my $rownum = 8; if (ref($types) eq 'ARRAY') { $rownum += scalar(@{$types}); } @@ -2959,7 +3527,7 @@ sub print_loadbalancing { ''; @@ -3098,7 +3666,7 @@ sub loadbalancing_rules { $css_class,$balnum,$islast) = @_; my $output; my $num = 0; - my ($alltypes,$othertypes,$titles) = + my ($alltypes,$othertypes,$titles) = &loadbalancing_titles($dom,$intdom,$usertypes,$types); if ((ref($alltypes) eq 'ARRAY') && (ref($titles) eq 'HASH')) { foreach my $type (@{$alltypes}) { @@ -3107,7 +3675,7 @@ sub loadbalancing_rules { if (ref($currrules) eq 'HASH') { $current = $currrules->{$type}; } - if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { + if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) { if ($dom ne &Apache::lonnet::host_domain($lonhost)) { $current = ''; } @@ -3128,8 +3696,10 @@ sub loadbalancing_titles { '_LC_author' => &mt('Users from [_1] with author role',$dom), '_LC_internetdom' => &mt('Users not from [_1], but from [_2]',$dom,$intdom), '_LC_external' => &mt('Users not from [_1]',$intdom), + '_LC_ipchangesso' => &mt('SSO users from [_1], with IP mismatch',$dom), + '_LC_ipchange' => &mt('Non-SSO users with IP mismatch'), ); - my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external'); + my @alltypes = ('_LC_adv','_LC_author','_LC_internetdom','_LC_external','_LC_ipchangesso','_LC_ipchange'); if (ref($types) eq 'ARRAY') { unshift(@alltypes,@{$types},'default'); } @@ -3154,23 +3724,28 @@ sub loadbalancing_titles { sub loadbalance_rule_row { my ($type,$title,$current,$servers,$currbalancer,$lonhost,$dom, $targets_div_style,$homedom_div_style,$css_class,$balnum,$num,$islast) = @_; - my @rulenames = ('default','homeserver'); + my @rulenames; my %ruletitles = &offloadtype_text(); - if ($type eq '_LC_external') { - push(@rulenames,'externalbalancer'); + if (($type eq '_LC_ipchangesso') || ($type eq '_LC_ipchange')) { + @rulenames = ('balancer','offloadedto'); } else { - push(@rulenames,'specific'); + @rulenames = ('default','homeserver'); + if ($type eq '_LC_external') { + push(@rulenames,'externalbalancer'); + } else { + push(@rulenames,'specific'); + } + push(@rulenames,'none'); } - push(@rulenames,'none'); my $style = $targets_div_style; - if (($type eq '_LC_external') || ($type eq '_LC_internetdom')) { + if (($type eq '_LC_external') || ($type eq '_LC_internetdom') || ($type eq '_LC_ipchange')) { $style = $homedom_div_style; } my $space; if ($islast && $num == 1) { $space = '
 
'; } - my $output = + my $output = ''."\n". ''; $$rowtotal ++; $rowcount ++; } } elsif ($position eq 'middle') { - my @creators = ('author','course','requestcrs','selfcreate'); + my @creators = ('author','course','requestcrs'); 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'}})) { @@ -3375,10 +3935,8 @@ sub print_usercreation { my $rownum = 0; foreach my $item (@creators) { $rownum ++; - if ($item ne 'selfcreate') { - if ($checked{$item} eq '') { - $checked{$item} = 'any'; - } + if ($checked{$item} eq '') { + $checked{$item} = 'any'; } my $css_class; if ($rownum%2) { @@ -3389,30 +3947,18 @@ sub print_usercreation { $datatable .= ''. ''. + &print_requestmail($dom,'selfcreation',$createsettings,$rowtotal); + $$rowtotal ++; + my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info(); + $numinrow = 1; + 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('cancreate','emailusername_'.$status,$settings, + $numinrow,$$rowtotal,$usertypes,$infofields,$infotitles); + $$rowtotal ++; + } + } + 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,$$rowtotal); + $$rowtotal ++; + } + } + $datatable .= &captcha_choice('cancreate',$createsettings,$$rowtotal); + } + return $datatable; +} + sub captcha_choice { my ($context,$settings,$itemcount) = @_; my ($keyentry,$currpub,$currpriv,%checked,$rowname,$pubtext,$privtext); my %lt = &captcha_phrases(); $keyentry = 'hidden'; if ($context eq 'cancreate') { - $rowname = &mt('CAPTCHA validation (e-mail as username)'); + $rowname = &mt('CAPTCHA validation'); } elsif ($context eq 'login') { $rowname = &mt('"Contact helpdesk" CAPTCHA validation'); } @@ -3531,9 +4182,9 @@ sub captcha_choice { # # Note: If reCAPTCHA is to be used for LON-CAPA servers in a domain, a domain coordinator should visit: # https://www.google.com/recaptcha and generate a Public and Private key. For domains with multiple -# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) +# servers a single key pair will be used for all servers, so the internet domain (e.g., yourcollege.edu) # specified for use with the key should be broad enough to accommodate all servers in the LON-CAPA domain. -# +# $output .= ''."\n". ''; $rownum ++; @@ -3884,8 +4537,8 @@ sub print_scantronformat { $datatable .= ''. + $link. + ''. ''; } else { $datatable .= $parent - .' 
'."\n"; - + $datatable .= ''.$choices->{$item}."\n"; if ($designs->{'links'}{$item}) { $datatable.=' '; } @@ -1459,17 +1530,13 @@ sub login_header_options { } sub login_text_colors { - my ($img,$role,$logintext,$phase,$choices,$designs) = @_; + my ($img,$role,$logintext,$phase,$choices,$designs,$defaults) = @_; my $color_menu = ''; foreach my $item (@{$logintext}) { - my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'logintext'}{$item}); - $color_menu .= ''. - ''; + $color_menu .= ''; } $color_menu .= '
'.$link; - if ($designs->{'logintext'}{$item}) { - $color_menu .= '    '; - } - $color_menu .= '
 '.$choices->{$item}; + my $color = $designs->{'logintext'}{$item} ? $designs->{'logintext'}{$item} : $defaults->{'logintext'}{$item}; + $color_menu .= '

'; return $color_menu; @@ -1501,20 +1568,12 @@ sub image_changes { $role.'_del_'.$img.'" value="1" />'.&mt('Delete?'). ' '.&mt('Replace:').'
'; } else { - $output .= '
'.$logincolors.&mt('Upload:').'
'; + $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,$rowtotal,$action) = @_; my $context; @@ -1523,34 +1582,37 @@ sub print_quotas { } else { $context = $action; } - my ($datatable,$defaultquota,@usertools,@options,%validations); + my ($datatable,$defaultquota,$authorquota,@usertools,@options,%validations); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); my $typecount = 0; my ($css_class,%titles); if ($context eq 'requestcourses') { - @usertools = ('official','unofficial','community'); + @usertools = ('official','unofficial','community','textbook'); @options =('norequest','approval','validate','autolimit'); %validations = &Apache::lonnet::auto_courserequest_checks($dom); %titles = &courserequest_titles(); } elsif ($context eq 'requestauthor') { @usertools = ('author'); @options = ('norequest','approval','automatic'); - %titles = &authorrequest_titles(); + %titles = &authorrequest_titles(); } else { @usertools = ('aboutme','blog','webdav','portfolio'); %titles = &tool_titles(); } if (ref($types) eq 'ARRAY') { foreach my $type (@{$types}) { - my $currdefquota; + my ($currdefquota,$currauthorquota); unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { if (ref($settings) eq 'HASH') { if (ref($settings->{defaultquota}) eq 'HASH') { - $currdefquota = $settings->{defaultquota}->{$type}; + $currdefquota = $settings->{defaultquota}->{$type}; } else { $currdefquota = $settings->{$type}; } + if (ref($settings->{authorquota}) eq 'HASH') { + $currauthorquota = $settings->{authorquota}->{$type}; + } } } if (defined($usertypes->{$type})) { @@ -1664,10 +1726,15 @@ sub print_quotas { unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { $datatable .= - '
'. + ''. + ''.&mt('Portfolio').': '. ' Mb
'. + $datatable .= ''. + ''.&mt('Portfolio').': '. ' Mb
'.&mt('LON-CAPA Advanced Users').' '; + ''.&mt('LON-CAPA Advanced Users').'
'; if ($context eq 'requestcourses') { $datatable .= &mt('(overrides affiliation, if set)'). '
'.$text.''; - 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 ($numdc,$table,$rows) = &active_dc_picker($dom,$numinrow,'checkbox', + $action.'notifyapproval',%currapp); + if ($numdc > 0) { + $datatable .= $table; + } else { + $datatable .= &mt('There are no active Domain Coordinators'); + } + $datatable .=''; + $$rowtotal += $rows; + return $datatable; +} + +sub print_studentcode { + my ($settings,$rowtotal) = @_; + my $rownum = 0; + my ($output,%current); + my @crstypes = ('official','unofficial','community','textbook'); + if (ref($settings->{'uniquecode'}) eq 'HASH') { + foreach my $type (@crstypes) { + $current{$type} = $settings->{'uniquecode'}{$type}; + } + } + $output .= ''. + ''. + ''; + $$rowtotal ++; + return $output; +} + +sub print_textbookcourses { + my ($dom,$settings,$rowtotal) = @_; + my $rownum = 0; + my $css_class; + my $itemcount = 1; + my $maxnum = 0; + my $bookshash; + if (ref($settings) eq 'HASH') { + $bookshash = $settings->{'textbooks'}; + } + my %ordered; + if (ref($bookshash) eq 'HASH') { + foreach my $item (keys(%{$bookshash})) { + if (ref($bookshash->{$item}) eq 'HASH') { + my $num = $bookshash->{$item}{'order'}; + $ordered{$num} = $item; } - my $check = ' '; - if (grep(/^\Q$domcoord[$i]\E$/,@currapproval)) { - $check = ' checked="checked" '; + } + } + my $confname = $dom.'-domainconfig'; + my $switchserver = &check_switchserver($dom,$confname); + my $maxnum = scalar(keys(%ordered)); + my $datatable = &textbookcourses_javascript(\%ordered); + if (keys(%ordered)) { + my @items = sort { $a <=> $b } keys(%ordered); + for (my $i=0; $i<@items; $i++) { + $css_class = $itemcount%2?' class="LC_odd_row"':''; + my $key = $ordered{$items[$i]}; + my %coursehash=&Apache::lonnet::coursedescription($key); + my $coursetitle = $coursehash{'description'}; + my ($subject,$title,$author,$image,$imgsrc,$cdom,$cnum); + if (ref($bookshash->{$key}) eq 'HASH') { + $subject = $bookshash->{$key}->{'subject'}; + $title = $bookshash->{$key}->{'title'}; + $author = $bookshash->{$key}->{'author'}; + $image = $bookshash->{$key}->{'image'}; + if ($image ne '') { + my ($path,$imagefile) = ($image =~ m{^(.+)/([^/]+)$}); + my $imagethumb = "$path/tn-".$imagefile; + $imgsrc = ''.&mt('Textbook image').''; + } + } + my $chgstr = ' onchange="javascript:reorderBooks(this.form,'."'$key'".');"'; + $datatable .= ''. + ''; + $datatable .= ' '. + ''.&mt('LON-CAPA course:').' '. + $coursetitle.''."\n"; + $itemcount ++; } - $datatable .= '
'.&mt('Generate unique six character code as course identifier?').''; + foreach my $type (@crstypes) { + my $check = ' '; + if ($current{$type}) { + $check = ' checked="checked" '; + } + $output .= ''.(' 'x2).' '; + } + $output .= '
' + .''.(' 'x2). + ''. + ''.&mt('Subject:').' '. + (' 'x2). + ''.&mt('Title:').' '. + (' 'x2). + ''.&mt('Author(s):').' '. + (' 'x2). + ''.&mt('Thumbnail:'); + if ($image) { + $datatable .= ''. + $imgsrc. + ' '. + ' '.&mt('Replace:').' '; } - 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 .= ''; - } else { - $datatable .= ''; - } + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); } else { - $datatable .= ''; + $datatable .= ''; } - $datatable .= '
'; - } else { - $datatable .= &mt('There are no active Domain Coordinators'); - $rows ++; } - $datatable .='
'."\n". + ''."\n". + ' '."\n". + ''.&mt('Add').''. + ''.&mt('Subject:').' '."\n". + (' 'x2). + ''.&mt('Title:').' '."\n". + (' 'x2). + ''.&mt('Author(s):').' '."\n". + (' 'x2). + ''.&mt('Image:').' '; + if ($switchserver) { + $datatable .= &mt('Upload to library server: [_1]',$switchserver); + } else { + $datatable .= ''; + } + $datatable .= ''."\n". + ''.&mt('LON-CAPA course:').' '. + &Apache::loncommon::select_dom_form($env{'request.role.domain'},'addbook_cdom'). + ''. + &Apache::loncommon::selectcourse_link + ('display','addbook_cnum','addbook_cdom',undef,undef,undef,'Course'); + '
'.&mt('Create pending official courses from XML files').' '. ''; - my ($numdc,$dctable) = &active_dc_picker($dom,$curr_dc); + my ($numdc,$dctable,$rows) = &active_dc_picker($dom,$numinrow,'radio', + 'autocreate_xmldc',%currhash); if ($numdc > 1) { $datatable .= '
'. &mt('Course creation processed as: (choose Dom. Coord.)'). ''.$dctable.'
'.$titles->{$item}. ''. '
'. @@ -2396,7 +2638,21 @@ sub print_contacts { 'value="'.$bccemails{$type}.'" />'; } $datatable .= '
'.$choices->{$item}. + ''. + ''.$choices->{$item}. ''. ' '. - '
'.$choices{'anonsurvey_threshold'}. + ''. + $choices{'anonsurvey_threshold'}. ''. ''. - '
'. + $choices{'uploadquota'}. + ''. + ''; + foreach my $type (@types) { + $datatable .= ''; + } + $datatable .= '
'.&mt($type).'
'. + '
'.$titlesref->{$row}.''. + ''; + my (%current,%currentcap); + if (ref($settings) eq 'HASH') { + if (ref($settings->{$key}) eq 'HASH') { + foreach my $type (@types) { + if (ref($settings->{$key}->{$type}) eq 'HASH') { + $current{$type} = $settings->{$key}->{$type}->{$row}; + } + if (($row eq 'limit') && ($key eq 'default')) { + if (ref($settings->{$key}->{$type}) eq 'HASH') { + $currentcap{$type} = $settings->{$key}->{$type}->{'cap'}; + } + } + } + } + } + my %roles = ( + '0' => &Apache::lonnet::plaintext('dc'), + ); + + foreach my $type (@types) { + unless (($row eq 'registered') && ($key eq 'default')) { + $datatable .= ''; + } + } + unless (($row eq 'registered') && ($key eq 'default')) { + $datatable .= ''; + } + foreach my $type (@types) { + if ($type eq 'community') { + $roles{'1'} = &mt('Community personnel'); + } else { + $roles{'1'} = &mt('Course personnel'); + } + $datatable .= ''; + } + $datatable .= ''; + } + $datatable .= '
'.&mt($type).'
'; + if ($position eq 'top') { + my %checked; + if ($current{$type} eq '0') { + $checked{'0'} = ' checked="checked"'; + } else { + $checked{'1'} = ' checked="checked"'; + } + foreach my $role ('1','0') { + $datatable .= ' '; + } + } else { + if ($row eq 'types') { + my %checked; + if ($current{$type} =~ /^(all|dom)$/) { + $checked{$1} = ' checked="checked"'; + } else { + $checked{''} = ' checked="checked"'; + } + foreach my $val ('','dom','all') { + $datatable .= ' '; + } + } elsif ($row eq 'registered') { + my %checked; + if ($current{$type} eq '1') { + $checked{'1'} = ' checked="checked"'; + } else { + $checked{'0'} = ' checked="checked"'; + } + foreach my $val ('0','1') { + $datatable .= ' '; + } + } elsif ($row eq 'approval') { + my %checked; + if ($current{$type} =~ /^([12])$/) { + $checked{$1} = ' checked="checked"'; + } else { + $checked{'0'} = ' checked="checked"'; + } + for my $val (0..2) { + $datatable .= ' '; + } + } elsif ($row eq 'limit') { + my %checked; + if ($current{$type} =~ /^(allstudents|selfenrolled)$/) { + $checked{$1} = ' checked="checked"'; + } else { + $checked{'none'} = ' checked="checked"'; + } + my $cap; + if ($currentcap{$type} =~ /^\d+$/) { + $cap = $currentcap{$type}; + } + foreach my $val ('none','allstudents','selfenrolled') { + $datatable .= ' '; + } + $datatable .= '
'. + ''.&mt('Maximum allowed: '). + ''. + ''; + } + } + $datatable .= '
'. + $namesref->{$item}. + ''; + if (($item eq 'url') || ($item eq 'button')) { + $datatable .= ''. + ''; + } elsif ($item eq 'fields') { + my @currfields; + if (ref($currvalidation{$item}) eq 'ARRAY') { + @currfields = @{$currvalidation{$item}}; + } + foreach my $field (@{$fieldsref}) { + my $check = ''; + if (grep(/^\Q$field\E$/,@currfields)) { + $check = ' checked="checked"'; + } + $datatable .= ' '; + } + } elsif ($item eq 'markup') { + $datatable .= ''; + } + $datatable .= '
'. '

'; if ($lonhost eq '') { - $datatable .= ''; + $datatable .= ''; if (keys(%currbalancer) > 0) { $datatable .= &mt('Add balancer:'); } else { @@ -2975,7 +3543,7 @@ sub print_loadbalancing { next if ($currbalancer{$server}); $datatable .= ''."\n"; } - $datatable .= + $datatable .= ''."\n". ' '."\n"; } else { @@ -3014,7 +3582,7 @@ sub print_loadbalancing { if (exists($currbalancer{$spares[$i]})) { $disabled = ' disabled="disabled"'; } - $targettable .= + $targettable .= '

'.$space. '
'.$title.'
'.$space. @@ -3190,7 +3765,7 @@ sub loadbalance_rule_row { unless ($checked) { $default = ' selected="selected"'; } - $extra = + $extra = ': 
'.&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')); - } + my @options = ('any'); + if (ref($rules) eq 'HASH') { + if (keys(%{$rules}) > 0) { + push(@options,('official','unofficial')); } - push(@options,'none'); } + 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" '; - } + if ($checked{$item} eq $option) { + $check = ' checked="checked" '; } $datatable .= ''.&mt('E-mail address as username'). + ''. + ''; + foreach my $option ('email','emailapproval','off') { + my $checked; + if ($option eq 'email') { + if ($radiohash{'cancreate_email'}) { + $checked = 'checked="checked"'; + } + } elsif ($option eq 'emailapproval') { + if ($radiohash{'cancreate_emailapproval'}) { + $checked = 'checked="checked"'; + } + } else { + if ((!$radiohash{'cancreate_email'}) && (!$radiohash{'cancreate_emailapproval'})) { + $checked = 'checked="checked"'; + } + } + $datatable .= ' '; + } + $$rowtotal ++; + $datatable .= '
'."\n". ''.$pubtext.' '."\n". @@ -3608,18 +4259,26 @@ sub usercreation_types { 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 selfcreation_types { + my %lt = &Apache::lonlocal::texthash ( + selfcreate => 'User creates own account', + any => 'Any', + official => 'Institutional only ', + unofficial => 'Non-institutional only', + email => 'E-mail address', + login => 'Institutional Login', + sso => 'SSO', + ); +} + sub authtype_names { my %lt = &Apache::lonlocal::texthash( int => 'Internal', @@ -3652,7 +4311,7 @@ sub print_usermodification { $$rowtotal ++; $rowcount ++; } - } elsif ($position eq 'middle') { + } elsif ($position eq 'bottom') { $context = 'course'; $rowcount = 0; foreach my $role ('st','ep','ta','in','cr') { @@ -3661,29 +4320,23 @@ sub print_usermodification { $$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 ($dom,$settings,$rowtotal) = @_; my @items = ('auth_def','auth_arg_def','lang_def','timezone_def', 'datelocale_def','portal_def'); - my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my %defaults; + if (ref($settings) eq 'HASH') { + %defaults = %{$settings}; + } else { + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); + foreach my $item (@items) { + $defaults{$item} = $domdefaults{$item}; + } + } my $titles = &defaults_titles($dom); my $rownum = 0; my ($datatable,$css_class); @@ -3707,7 +4360,7 @@ sub print_defaults { my %authnames = &authtype_names(); foreach my $auth (@authtypes) { my $checked = ' '; - if ($domdefaults{$item} eq $auth) { + if ($defaults{$item} eq $auth) { $checked = ' checked="checked" '; } $datatable .= '
'.&mt('Default in use:').'
'. ''; if ($scantronurl) { - $datatable .= ''. - &mt('Default bubblesheet format file').''; + $datatable .= &Apache::loncommon::modal_link($scantronurl,&mt('Default bubblesheet format file'),600,500, + undef,undef,undef,undef,'background-color:#ffffff'); } else { $datatable = &mt('File unavailable for display'); } @@ -3910,11 +4563,12 @@ sub print_scantronformat { } $datatable .= '
'.$errorstr.' '; } elsif ($scantronurl) { + my $link = &Apache::loncommon::modal_link($scantronurl,&mt('Custom bubblesheet format file'),600,500, + undef,undef,undef,undef,'background-color:#ffffff'); $datatable .= ''. - ''. - &mt('Custom bubblesheet format file').' '. &mt('Replace:').'
'; } @@ -4068,7 +4722,7 @@ sub print_coursecategories { } $datatable .= ''; } - $datatable .= '
'; + $datatable .= ''; if ($parent eq 'instcode' || $parent eq 'communities') { $datatable .= '' .$default_names{$parent}.''; @@ -4098,7 +4752,8 @@ sub print_coursecategories { $datatable .= ''; + $text .= '
'; my ($idxnum,$parent_name,$parent_item); my $higher = $depth - 1; if ($higher == 0) { @@ -4444,9 +5100,22 @@ sub build_category_rows { } sub modifiable_userdata_row { - my ($context,$role,$settings,$numinrow,$rowcount,$usertypes) = @_; - my $rolename; - if ($context eq 'selfcreate') { + my ($context,$item,$settings,$numinrow,$rowcount,$usertypes,$fieldsref,$titlesref) = @_; + my ($role,$rolename,$statustype); + $role = $item; + if ($context eq 'cancreate') { + if ($item =~ /^emailusername_(.+)$/) { + $statustype = $1; + $role = 'emailusername'; + if (ref($usertypes) eq 'HASH') { + if ($usertypes->{$statustype}) { + $rolename = &mt('Data provided by [_1]',$usertypes->{$statustype}); + } else { + $rolename = &mt('Data provided by user'); + } + } + } + } elsif ($context eq 'selfcreate') { if (ref($usertypes) eq 'HASH') { $rolename = $usertypes->{$role}; } else { @@ -4459,9 +5128,18 @@ sub modifiable_userdata_row { $rolename = &Apache::lonnet::plaintext($role); } } - my @fields = ('lastname','firstname','middlename','generation', - 'permanentemail','id'); - my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); + my (@fields,%fieldtitles); + if (ref($fieldsref) eq 'ARRAY') { + @fields = @{$fieldsref}; + } else { + @fields = ('lastname','firstname','middlename','generation', + 'permanentemail','id'); + } + if ((ref($titlesref) eq 'HASH')) { + %fieldtitles = %{$titlesref}; + } else { + %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); + } my $output; my $css_class = $rowcount%2?' class="LC_odd_row"':''; $output = ''. @@ -4472,14 +5150,33 @@ sub modifiable_userdata_row { 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" '; + my $hashref = $settings->{$context}->{$role}; + if ($role eq 'emailusername') { + if ($statustype) { + if (ref($settings->{$context}->{$role}->{$statustype}) eq 'HASH') { + $hashref = $settings->{$context}->{$role}->{$statustype}; + if (ref($hashref) eq 'HASH') { + foreach my $field (@fields) { + if ($hashref->{$field}) { + $checks{$field} = $hashref->{$field}; + } + } + } + } + } + } else { + if (ref($hashref) eq 'HASH') { + foreach my $field (@fields) { + if ($hashref->{$field}) { + $checks{$field} = ' checked="checked" '; + } + } } } } } } + for (my $i=0; $i<@fields; $i++) { my $rem = $i%($numinrow); if ($rem == 0) { @@ -4489,20 +5186,40 @@ sub modifiable_userdata_row { $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" '; + unless ($role eq 'emailusername') { + if (exists($checks{$fields[$i]})) { + $check = $checks{$fields[$i]} + } else { + if ($role eq 'st') { + if (ref($settings) ne 'HASH') { + $check = ' checked="checked" '; + } } } } $output .= ''; + ''; + if ($role eq 'emailusername') { + unless ($checks{$fields[$i]} =~ /^(required|optional)$/) { + $checks{$fields[$i]} = 'omit'; + } + foreach my $option ('required','optional','omit') { + my $checked=''; + if ($checks{$fields[$i]} eq $option) { + $checked='checked="checked" '; + } + $output .= ''.(' ' x2); + } + $output .= ''.$fieldtitles{$fields[$i]}.''; + } else { + $output .= ''; + } + $output .= ''; $rem = @fields%($numinrow); } my $colsleft = $numinrow - $rem; @@ -4517,7 +5234,7 @@ sub modifiable_userdata_row { } sub insttypes_row { - my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context) = @_; + my ($settings,$types,$usertypes,$dom,$numinrow,$othertitle,$context,$rownum) = @_; my %lt = &Apache::lonlocal::texthash ( cansearch => 'Users allowed to search', statustocreate => 'Institutional affiliation(s) able to create own account (login/SSO)', @@ -4531,9 +5248,13 @@ sub insttypes_row { if ($context eq 'statustocreate') { $class = 'LC_right_item'; } - my $output = ''. - '
'. - '
'.$lt{$context}.$showdom. - ''; + my $css_class = ' class="LC_odd_row"'; + if ($rownum ne '') { + $css_class = ($rownum%2? ' class="LC_odd_row"':''); + } + my $output = ''. + '
'.$lt{$context}.$showdom. + ''; my $rem; if (ref($types) eq 'ARRAY') { for (my $i=0; $i<@{$types}; $i++) { @@ -4662,7 +5383,7 @@ sub usertype_update_row { } sub modify_login { - my ($r,$dom,$confname,%domconfig) = @_; + my ($r,$dom,$confname,$lastactref,%domconfig) = @_; my ($resulttext,$errors,$colchgtext,%changes,%colchanges,%newfile,%newurl, %curr_loginvia,%loginhash,@currlangs,@newlangs,$addedfile,%title,@offon); %title = ( coursecatalog => 'Display course catalog', @@ -4842,7 +5563,7 @@ sub modify_login { } else { my $puberror = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$newfile{$lang},$result); $errors .= '
  • '.$puberror.'
  • '; - if ((grep(/^\Q$lang\E$/,@currlangs)) && + if ((grep(/^\Q$lang\E$/,@currlangs)) && (!grep(/^\Q$lang\E$/,@delurls))) { $loginhash{'login'}{'helpurl'}{$lang} = $domconfig{'login'}{'helpurl'}{$lang}; @@ -4900,6 +5621,9 @@ sub modify_login { } if (keys(%changes) > 0 || $colchgtext) { &Apache::loncommon::devalidate_domconfig_cache($dom); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domainconfig'} = 1; + } $resulttext = &mt('Changes made:').'
      '; foreach my $item (sort(keys(%changes))) { if ($item eq 'loginvia') { @@ -4959,7 +5683,7 @@ sub modify_login { } } elsif ($item eq 'captcha') { if (ref($loginhash{'login'}) eq 'HASH') { - my $chgtxt; + my $chgtxt; if ($loginhash{'login'}{$item} eq 'notused') { $chgtxt .= &mt('No CAPTCHA validation in use for helpdesk form.'); } else { @@ -5020,7 +5744,7 @@ sub color_font_choices { links => "Link colors", images => "Images", font => "Font color", - fontmenu => "Font Menu", + fontmenu => "Font menu", pgbg => "Page", tabbg => "Header", sidebg => "Border", @@ -5032,7 +5756,7 @@ sub color_font_choices { } sub modify_rolecolors { - my ($r,$dom,$confname,$roles,%domconfig) = @_; + my ($r,$dom,$confname,$roles,$lastactref,%domconfig) = @_; my ($resulttext,%rolehash); $rolehash{'rolecolors'} = {}; if (ref($domconfig{'rolecolors'}) ne 'HASH') { @@ -5047,6 +5771,9 @@ sub modify_rolecolors { if ($putresult eq 'ok') { if (keys(%changes) > 0) { &Apache::loncommon::devalidate_domconfig_cache($dom); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domainconfig'} = 1; + } $resulttext = &display_colorchgs($dom,\%changes,$roles, $rolehash{'rolecolors'}); } else { @@ -5072,24 +5799,45 @@ sub modify_colors { my @images; my $servadm = $r->dir_config('lonAdmEMail'); my $errors; + my %defaults; 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','login'); @bgs = ('pgbg','mainbg','sidebg'); } else { @images = ('img'); - @bgs = ('pgbg','tabbg','sidebg'); + @bgs = ('pgbg','tabbg','sidebg'); + } + my %defaults = &role_defaults($role,\@bgs,\@links,\@images,\@logintext); + unless ($env{'form.'.$role.'_font'} eq $defaults{'font'}) { + $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'}; + } + if ($role eq 'login') { + foreach my $item (@logintext) { + unless ($env{'form.'.$role.'_'.$item} eq $defaults{'logintext'}{$item}) { + $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; + } + } + } else { + unless($env{'form.'.$role.'_fontmenu'} eq $defaults{'fontmenu'}) { + $confhash->{$role}{'fontmenu'} = $env{'form.'.$role.'_fontmenu'}; + } } - $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'}; - foreach my $item (@bgs,@links,@logintext) { - $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; + foreach my $item (@bgs) { + unless ($env{'form.'.$role.'_'.$item} eq $defaults{'bgs'}{$item} ) { + $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; + } + } + foreach my $item (@links) { + unless ($env{'form.'.$role.'_'.$item} eq $defaults{'links'}{$item}) { + $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item}; + } } my ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm); @@ -5437,7 +6185,7 @@ sub publishlogo { # See if there is anything left unless ($fname) { return ('error: no uploaded file'); } $fname="$subdir/$fname"; - my $docroot=$r->dir_config('lonDocRoot'); + my $docroot=$r->dir_config('lonDocRoot'); my $filepath="$docroot/priv"; my $relpath = "$dom/$confname"; my ($fnamepath,$file,$fetchthumb); @@ -5457,19 +6205,19 @@ sub publishlogo { if ($file=~/\.(\w+)$/ && (&Apache::loncommon::fileembstyle($1) eq 'hdn')) { $output = - &mt('Invalid file extension ([_1]) - reserved for LONCAPA use.',$1); + &mt('Invalid file extension ([_1]) - reserved for internal use.',$1); } elsif ($file=~/\.(\w+)$/ && !defined(&Apache::loncommon::fileembstyle($1))) { $output = &mt('Unrecognized file extension ([_1]) - rename the file with a proper extension and re-upload.',$1); } elsif ($file=~/\.(\d+)\.(\w+)$/) { - $output = &mt('File name not allowed - rename the file to remove the number immediately before the file extension([_1]) and re-upload.',$2); + $output = &mt('Filename 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'); + $output = &mt('Filename is a directory name - rename the file and re-upload'); } else { my $source = $filepath.'/'.$file; my $logfile; if (!open($logfile,">>$source".'.log')) { - return (&mt('No write permission to Construction Space')); + return (&mt('No write permission to Authoring Space')); } print $logfile "\n================= Publish ".localtime()." ================\n". @@ -5706,21 +6454,25 @@ sub check_switchserver { } sub modify_quotas { - my ($dom,$action,%domconfig) = @_; + my ($r,$dom,$action,$lastactref,%domconfig) = @_; my ($context,@usertools,@options,%validations,%titles,%confhash,%toolshash, - %limithash,$toolregexp,%conditions,$resulttext,%changes); + %limithash,$toolregexp,%conditions,$resulttext,%changes,$confname,$configuserok, + $author_ok,$switchserver,$errors); if ($action eq 'quotas') { $context = 'tools'; } else { $context = $action; } if ($context eq 'requestcourses') { - @usertools = ('official','unofficial','community'); + @usertools = ('official','unofficial','community','textbook'); @options =('norequest','approval','validate','autolimit'); %validations = &Apache::lonnet::auto_courserequest_checks($dom); %titles = &courserequest_titles(); $toolregexp = join('|',@usertools); %conditions = &courserequest_conditions(); + $confname = $dom.'-domainconfig'; + my $servadm = $r->dir_config('lonAdmEMail'); + ($configuserok,$author_ok,$switchserver) = &config_check($dom,$confname,$servadm); } elsif ($context eq 'requestauthor') { @usertools = ('author'); %titles = &authorrequest_titles(); @@ -5728,7 +6480,7 @@ sub modify_quotas { @usertools = ('aboutme','blog','webdav','portfolio'); %titles = &tool_titles(); } - my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); foreach my $key (keys(%env)) { if ($context eq 'requestcourses') { @@ -5748,16 +6500,47 @@ sub modify_quotas { } else { if ($key =~ /^form\.quota_(.+)$/) { $confhash{'defaultquota'}{$1} = $env{$key}; - } - if ($key =~ /^form\.\Q$context\E_(.+)$/) { + } elsif ($key =~ /^form\.authorquota_(.+)$/) { + $confhash{'authorquota'}{$1} = $env{$key}; + } elsif ($key =~ /^form\.\Q$context\E_(.+)$/) { @{$toolshash{$1}} = &Apache::loncommon::get_env_multiple($key); } } } if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { - my @approvalnotify = &Apache::loncommon::get_env_multiple('form.reqapprovalnotify'); + my @approvalnotify = &Apache::loncommon::get_env_multiple('form.'.$context.'notifyapproval'); @approvalnotify = sort(@approvalnotify); $confhash{'notify'}{'approval'} = join(',',@approvalnotify); + my @crstypes = ('official','unofficial','community','textbook'); + my @hasuniquecode = &Apache::loncommon::get_env_multiple('form.uniquecode'); + foreach my $type (@hasuniquecode) { + if (grep(/^\Q$type\E$/,@crstypes)) { + $confhash{'uniquecode'}{$type} = 1; + } + } + my ($newbook,@allpos); + if ($context eq 'requestcourses') { + if ($env{'form.addbook'}) { + if (($env{'form.addbook_cnum'} =~ /^$match_courseid$/) && + ($env{'form.addbook_cdom'} =~ /^$match_domain$/)) { + if (&Apache::lonnet::homeserver($env{'form.addbook_cnum'}, + $env{'form.addbook_cdom'}) eq 'no_host') { + $errors .= '
    • '.&mt('Invalid LON-CAPA course for textbook'). + '
    • '; + } else { + $newbook = $env{'form.addbook_cdom'}.'_'.$env{'form.addbook_cnum'}; + my $position = $env{'form.addbook_pos'}; + $position =~ s/\D+//g; + if ($position ne '') { + $allpos[$position] = $newbook; + } + } + } else { + $errors .= '
    • '.&mt('Invalid LON-CAPA course for textbook'). + '
    • '; + } + } + } if (ref($domconfig{$action}) eq 'HASH') { if (ref($domconfig{$action}{'notify'}) eq 'HASH') { if ($domconfig{$action}{'notify'}{'approval'} ne $confhash{'notify'}{'approval'}) { @@ -5768,13 +6551,135 @@ sub modify_quotas { $changes{'notify'}{'approval'} = 1; } } + if (ref($domconfig{$action}{'uniquecode'}) eq 'HASH') { + if (ref($confhash{'uniquecode'}) eq 'HASH') { + foreach my $crstype (keys(%{$domconfig{$action}{'uniquecode'}})) { + unless ($confhash{'uniquecode'}{$crstype}) { + $changes{'uniquecode'} = 1; + } + } + unless ($changes{'uniquecode'}) { + foreach my $crstype (keys(%{$confhash{'uniquecode'}})) { + unless ($domconfig{$action}{'uniquecode'}{$crstype}) { + $changes{'uniquecode'} = 1; + } + } + } + } else { + $changes{'uniquecode'} = 1; + } + } elsif (ref($confhash{'uniquecode'}) eq 'HASH') { + $changes{'uniquecode'} = 1; + } + if ($context eq 'requestcourses') { + if (ref($domconfig{$action}{'textbooks'}) eq 'HASH') { + my %deletions; + my @todelete = &Apache::loncommon::get_env_multiple('form.book_del'); + if (@todelete) { + map { $deletions{$_} = 1; } @todelete; + } + my %imgdeletions; + my @todeleteimages = &Apache::loncommon::get_env_multiple('form.book_image_del'); + if (@todeleteimages) { + map { $imgdeletions{$_} = 1; } @todeleteimages; + } + my $maxnum = $env{'form.book_maxnum'}; + for (my $i=0; $i<=$maxnum; $i++) { + my $key = $env{'form.book_id_'.$i}; + if (ref($domconfig{$action}{'textbooks'}{$key}) eq 'HASH') { + if ($deletions{$key}) { + if ($domconfig{$action}{'textbooks'}{$key}{'image'}) { + #FIXME need to obsolete item in RES space + } + next; + } else { + my $newpos = $env{'form.'.$key}; + $newpos =~ s/\D+//g; + foreach my $item ('subject','title','author') { + $confhash{'textbooks'}{$key}{$item} = $env{'form.book_'.$item.'_'.$i}; + if ($domconfig{$action}{'textbooks'}{$key}{$item} ne $confhash{'textbooks'}{$key}{$item}) { + $changes{'textbooks'}{$key} = 1; + } + } + $allpos[$newpos] = $key; + } + if ($imgdeletions{$key}) { + $changes{'textbooks'}{$key} = 1; + #FIXME need to obsolete item in RES space + } elsif ($env{'form.book_image_'.$i.'.filename'}) { + my ($cdom,$cnum) = split(/_/,$key); + my ($imgurl,$error) = &process_textbook_image($r,$dom,$confname,'book_image_'.$i, + $cdom,$cnum,$configuserok, + $switchserver,$author_ok); + if ($imgurl) { + $confhash{'textbooks'}{$key}{'image'} = $imgurl; + $changes{'textbooks'}{$key} = 1; + } + if ($error) { + &Apache::lonnet::logthis($error); + $errors .= '
    • '.$error.'
    • '; + } + } elsif ($domconfig{$action}{'textbooks'}{$key}{'image'}) { + $confhash{'textbooks'}{$key}{'image'} = + $domconfig{$action}{'textbooks'}{$key}{'image'}; + } + } + } + } + } } else { if ($confhash{'notify'}{'approval'}) { $changes{'notify'}{'approval'} = 1; } + if (ref($confhash{'uniquecode'} eq 'HASH')) { + $changes{'uniquecode'} = 1; + } + } + if ($context eq 'requestcourses') { + if ($newbook) { + $changes{'textbooks'}{$newbook} = 1; + foreach my $item ('subject','title','author') { + $env{'form.addbook_'.$item} =~ s/(`)/'/g; + if ($env{'form.addbook_'.$item}) { + $confhash{'textbooks'}{$newbook}{$item} = $env{'form.addbook_'.$item}; + } + } + if ($env{'form.addbook_image.filename'} ne '') { + my ($cdom,$cnum) = split(/_/,$newbook); + my ($imageurl,$error) = + &process_textbook_image($r,$dom,$confname,'addbook_image',$cdom,$cnum,$configuserok, + $switchserver,$author_ok); + if ($imageurl) { + $confhash{'textbooks'}{$newbook}{'image'} = $imageurl; + } + if ($error) { + &Apache::lonnet::logthis($error); + $errors .= '
    • '.$error.'
    • '; + } + } + } + if (@allpos > 0) { + my $idx = 0; + foreach my $item (@allpos) { + if ($item ne '') { + $confhash{'textbooks'}{$item}{'order'} = $idx; + if (ref($domconfig{$action}) eq 'HASH') { + if (ref($domconfig{$action}{'textbooks'}) eq 'HASH') { + if (ref($domconfig{$action}{'textbooks'}{$item}) eq 'HASH') { + if ($domconfig{$action}{'textbooks'}{$item}{'order'} ne $idx) { + $changes{'textbooks'}{$item} = 1; + } + } + } + } + $idx ++; + } + } + } } } else { $confhash{'defaultquota'}{'default'} = $env{'form.defaultquota'}; + $confhash{'authorquota'}{'default'} = $env{'form.authorquota'}; } foreach my $item (@usertools) { foreach my $type (@{$types},'default','_LC_adv') { @@ -5862,6 +6767,17 @@ sub modify_quotas { } } } + if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') { + foreach my $key (keys(%{$domconfig{'quotas'}{'authorquota'}})) { + if (exists($confhash{'authorquota'}{$key})) { + if ($confhash{'authorquota'}{$key} ne $domconfig{'quotas'}{'authorquota'}{$key}) { + $changes{'authorquota'}{$key} = 1; + } + } else { + $confhash{'authorquota'}{$key} = $domconfig{'quotas'}{'authorquota'}{$key}; + } + } + } } if (ref($confhash{'defaultquota'}) eq 'HASH') { foreach my $key (keys(%{$confhash{'defaultquota'}})) { @@ -5880,13 +6796,30 @@ sub modify_quotas { } } } + if (ref($confhash{'authorquota'}) eq 'HASH') { + foreach my $key (keys(%{$confhash{'authorquota'}})) { + if (ref($domconfig{'quotas'}) eq 'HASH') { + if (ref($domconfig{'quotas'}{'authorquota'}) eq 'HASH') { + if (!exists($domconfig{'quotas'}{'authorquota'}{$key})) { + $changes{'authorquota'}{$key} = 1; + } + } else { + $changes{'authorquota'}{$key} = 1; + } + } else { + $changes{'authorquota'}{$key} = 1; + } + } + } } if ($context eq 'requestauthor') { $domdefaults{'requestauthor'} = \%confhash; } else { foreach my $key (keys(%confhash)) { - $domdefaults{$key} = $confhash{$key}; + unless (($context eq 'requestcourses') && ($key eq 'textbooks')) { + $domdefaults{$key} = $confhash{$key}; + } } } @@ -5899,9 +6832,11 @@ sub modify_quotas { if (keys(%changes) > 0) { my $cachetime = 24*60*60; &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); - + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domdefaults'} = 1; + } $resulttext = &mt('Changes made:').'
        '; - unless (($context eq 'requestcourses') || + unless (($context eq 'requestcourses') || ($context eq 'requestauthor')) { if (ref($changes{'defaultquota'}) eq 'HASH') { $resulttext .= '
      • '.&mt('Portfolio default quotas').'
          '; @@ -5911,7 +6846,20 @@ sub modify_quotas { if ($type eq 'default') { $typetitle = $othertitle; } - $resulttext .= '
        • '.&mt('[_1] set to [_2] Mb',$typetitle,$confhash{'defaultquota'}{$type}).'
        • '; + $resulttext .= '
        • '.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'defaultquota'}{$type}).'
        • '; + } + } + $resulttext .= '
      • '; + } + if (ref($changes{'authorquota'}) eq 'HASH') { + $resulttext .= '
      • '.&mt('Authoring Space default quotas').'
          '; + foreach my $type (@{$types},'default') { + if (defined($changes{'authorquota'}{$type})) { + my $typetitle = $usertypes->{$type}; + if ($type eq 'default') { + $typetitle = $othertitle; + } + $resulttext .= '
        • '.&mt('[_1] set to [_2] MB',$typetitle,$confhash{'authorquota'}{$type}).'
        • '; } } $resulttext .= '
      • '; @@ -5922,7 +6870,7 @@ sub modify_quotas { my (%haschgs,%inconf); if ($context eq 'requestauthor') { %haschgs = %changes; - %inconf = %confhash; + %inconf = %confhash; } else { if (ref($changes{$item}) eq 'HASH') { %haschgs = %{$changes{$item}}; @@ -5936,7 +6884,7 @@ sub modify_quotas { &Apache::lonnet::usertools_access($env{'user.name'}, $env{'user.domain'}, $item,'reload',$context); - if (($context eq 'requestcourses') || + if (($context eq 'requestcourses') || ($context eq 'requestauthor')) { if ($env{'environment.canrequest.'.$item} ne $newacc) { $newenv{'environment.canrequest.'.$item} = $newacc; @@ -6008,6 +6956,42 @@ sub modify_quotas { } } } + if ($action eq 'requestcourses') { + my @offon = ('off','on'); + if ($changes{'uniquecode'}) { + if (ref($confhash{'uniquecode'}) eq 'HASH') { + my $codestr = join(' ',map{ &mt($_); } sort(keys(%{$confhash{'uniquecode'}}))); + $resulttext .= '
      • '. + &mt('Generation of six character code as course identifier for distribution to students set to on for: [_1].',''.$codestr.''). + '
      • '; + } else { + $resulttext .= '
      • '.&mt('Generation of six character code as course identifier for distribution to students set to off.'). + '
      • '; + } + } + if (ref($changes{'textbooks'}) eq 'HASH') { + $resulttext .= '
      • '.&mt('Available textbooks updated').'
          '; + foreach my $key (sort(keys(%{$changes{'textbooks'}}))) { + my %coursehash = &Apache::lonnet::coursedescription($key); + my $coursetitle = $coursehash{'description'}; + my $position = $confhash{'textbooks'}{$key}{'order'} + 1; + $resulttext .= '
        • '; + foreach my $item ('subject','title','author') { + my $name = $item.':'; + $name =~ s/^(\w)/\U$1/; + $resulttext .= &mt($name).' '.$confhash{'textbooks'}{$key}{$item}.'
          '; + } + $resulttext .= ' '.&mt('Order: [_1]',$position).'
          '; + if ($confhash{'textbooks'}{$key}{'image'}) { + $resulttext .= ' '.&mt('Image: [_1]', + 'Textbook cover').'
          '; + } + $resulttext .= ' '.&mt('LON-CAPA Course: [_1]',$coursetitle).'
        • '; + } + $resulttext .= '
      • '; + } + } $resulttext .= '
      '; if (keys(%newenv)) { &Apache::lonnet::appenv(\%newenv); @@ -6025,11 +7009,42 @@ sub modify_quotas { $resulttext = ''. &mt('An error occurred: [_1]',$putresult).''; } + if ($errors) { + $resulttext .= '

      '.&mt('The following errors occurred when modifying Textbook settings.'). + '

        '.$errors.'

      '; + } return $resulttext; } +sub process_textbook_image { + my ($r,$dom,$confname,$caller,$cdom,$cnum,$configuserok,$switchserver,$author_ok) = @_; + my $filename = $env{'form.'.$caller.'.filename'}; + my ($error,$url); + my ($width,$height) = (50,50); + if ($configuserok eq 'ok') { + if ($switchserver) { + $error = &mt('Upload of textbook image is not permitted to this server: [_1]', + $switchserver); + } elsif ($author_ok eq 'ok') { + my ($result,$imageurl) = + &publishlogo($r,'upload',$caller,$dom,$confname, + "textbooks/$dom/$cnum/cover",$width,$height); + if ($result eq 'ok') { + $url = $imageurl; + } else { + $error = &mt("Upload of [_1] failed because an error occurred publishing the file in RES space. Error was: [_2].",$filename,$result); + } + } else { + $error = &mt("Upload of [_1] failed because an author role could not be assigned to a Domain Configuration user ([_2]) in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$author_ok); + } + } else { + $error = &mt("Upload of [_1] failed because a Domain Configuration user ([_2]) could not be created in domain: [_3]. Error was: [_4].",$filename,$confname,$dom,$configuserok); + } + return ($url,$error); +} + sub modify_autoenroll { - my ($dom,%domconfig) = @_; + my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,%changes); my %currautoenroll; if (ref($domconfig{'autoenroll'}) eq 'HASH') { @@ -6097,6 +7112,9 @@ sub modify_autoenroll { if ($changes{'coowners'}) { $resulttext .= '
    • '.&mt("$title{'coowners'} set to $offon[$env{'form.autoassign_coowners'}]").'
    • '; &Apache::loncommon::devalidate_domconfig_cache($dom); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domainconfig'} = 1; + } } $resulttext .= '
    '; } else { @@ -6502,7 +7520,7 @@ sub modify_directorysrch { } else { $chgtext =~ s/\; $//; } - $resulttext .= + $resulttext .= '
  • '. &mt("Users from domain '[_1]' permitted to search the institutional directory set to: [_2]", ''.$dom.'',$chgtext). @@ -6548,7 +7566,7 @@ sub modify_directorysrch { } sub modify_contacts { - my ($dom,%domconfig) = @_; + my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,%currsetting,%newsetting,%changes,%contacts_hash); if (ref($domconfig{'contacts'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'contacts'}})) { @@ -6558,7 +7576,8 @@ sub modify_contacts { my (%others,%to,%bcc); my @contacts = ('supportemail','adminemail'); my @mailings = ('errormail','packagesmail','helpdeskmail','lonstatusmail', - 'requestsmail','updatesmail'); + 'requestsmail','updatesmail','idconflictsmail'); + my @toggles = ('reporterrors','reportupdates'); foreach my $type (@mailings) { @{$newsetting{$type}} = &Apache::loncommon::get_env_multiple('form.'.$type); @@ -6580,6 +7599,11 @@ sub modify_contacts { $to{$item} = $env{'form.'.$item}; $contacts_hash{'contacts'}{$item} = $to{$item}; } + foreach my $item (@toggles) { + if ($env{'form.'.$item} =~ /^(0|1)$/) { + $contacts_hash{'contacts'}{$item} = $env{'form.'.$item}; + } + } if (keys(%currsetting) > 0) { foreach my $item (@contacts) { if ($to{$item} ne $currsetting{$item}) { @@ -6618,7 +7642,7 @@ sub modify_contacts { 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})) { @@ -6635,10 +7659,22 @@ sub modify_contacts { } } } + foreach my $item (@toggles) { + if (($env{'form.'.$item} == 1) && ($currsetting{$item} == 0)) { + $changes{$item} = 1; + } elsif ((!$env{'form.'.$item}) && + (($currsetting{$item} eq '') || ($currsetting{$item} == 1))) { + $changes{$item} = 1; + } + } my $putresult = &Apache::lonnet::put_dom('configuration',\%contacts_hash, $dom); if ($putresult eq 'ok') { if (keys(%changes) > 0) { + &Apache::loncommon::devalidate_domconfig_cache($dom); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domainconfig'} = 1; + } my ($titles,$short_titles) = &contact_titles(); $resulttext = &mt('Changes made:').'
      '; foreach my $item (@contacts) { @@ -6669,6 +7705,23 @@ sub modify_contacts { $resulttext .= ''; } } + my @offon = ('off','on'); + if ($changes{'reporterrors'}) { + $resulttext .= '
    • '. + &mt('E-mail error reports to [_1] set to "'. + $offon[$env{'form.reporterrors'}].'".', + &Apache::loncommon::modal_link('http://loncapa.org/core.html', + &mt('LON-CAPA core group - MSU'),600,500)). + '
    • '; + } + if ($changes{'reportupdates'}) { + $resulttext .= '
    • '. + &mt('E-mail record of completed LON-CAPA updates to [_1] set to "'. + $offon[$env{'form.reportupdates'}].'".', + &Apache::loncommon::modal_link('http://loncapa.org/core.html', + &mt('LON-CAPA core group - MSU'),600,500)). + '
    • '; + } $resulttext .= '
    '; } else { $resulttext = &mt('No changes made to contact information'); @@ -6682,106 +7735,38 @@ sub modify_contacts { sub modify_usercreation { my ($dom,%domconfig) = @_; - my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate); + my ($resulttext,%curr_usercreation,%changes,%authallowed,%cancreate,%save_usercreate); 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.'); + if ($key eq 'cancreate') { + if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') { + foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) { + if (($item eq 'selfcreate') || ($item eq 'statustocreate') || + ($item eq 'captcha') || ($item eq 'recaptchakeys')) { + $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item}; + } else { + $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item}; + } } } + } elsif ($key eq 'email_rule') { + $save_usercreate{$key} = $domconfig{'usercreation'}{$key}; + } else { + $curr_usercreation{$key} = $domconfig{'usercreation'}{$key}; } - } 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'); + my @username_rule = &Apache::loncommon::get_env_multiple('form.username_rule'); + my @id_rule = &Apache::loncommon::get_env_multiple('form.id_rule'); + my @contexts = ('author','course','requestcrs'); + foreach my $item(@contexts) { + $cancreate{$item} = $env{'form.can_createuser_'.$item}; } - &process_captcha('cancreate',\%changes,\%cancreate,\%curr_usercreation); 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); - } + if ($curr_usercreation{'cancreate'}{$item} ne $cancreate{$item}) { + push(@{$changes{'cancreate'}},$item); } } } elsif (ref($curr_usercreation{'cancreate'}) eq 'ARRAY') { @@ -6832,21 +7817,6 @@ sub modify_usercreation { 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; @@ -6877,39 +7847,435 @@ sub modify_usercreation { } } + $save_usercreate{'cancreate'}{'course'} = $cancreate{'course'}; + $save_usercreate{'cancreate'}{'author'} = $cancreate{'author'}; + $save_usercreate{'cancreate'}{'requestcrs'} = $cancreate{'requestcrs'}; + $save_usercreate{'id_rule'} = \@id_rule; + $save_usercreate{'username_rule'} = \@username_rule, + $save_usercreate{'authtypes'} = \%authhash; + my %usercreation_hash = ( - usercreation => { - cancreate => \%cancreate, - username_rule => \@username_rule, - id_rule => \@id_rule, - email_rule => \@email_rule, - authtypes => \%authhash, - } - ); + usercreation => \%save_usercreate, + ); my $putresult = &Apache::lonnet::put_dom('configuration',\%usercreation_hash, $dom); + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + $resulttext = &mt('Changes made:').'
      '; + if (ref($changes{'cancreate'}) eq 'ARRAY') { + my %lt = &usercreation_types(); + foreach my $type (@{$changes{'cancreate'}}) { + my $chgtext = $lt{$type}.', '; + if ($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.').'
    • '; + } + } + my %authname = &authtype_names(); + my %context_title = &context_names(); + if (ref($changes{'authtypes'}) eq 'ARRAY') { + my $chgtext = '
        '; + foreach my $type (@{$changes{'authtypes'}}) { + my @allowed; + $chgtext .= '
      • '.$context_title{$type}.' - '.&mt('assignable authentication types: '); + foreach my $auth (@authtypes) { + if ($authhash{$type}{$auth}) { + push(@allowed,$authname{$auth}); + } + } + if (@allowed > 0) { + $chgtext .= join(', ',@allowed).'
      • '; + } else { + $chgtext .= &mt('none').''; + } + } + $chgtext .= '
      '; + $resulttext .= '
    • '.&mt('Authentication types available for assignment to new users').'
      '.$chgtext; + $resulttext .= '
    • '; + } + $resulttext .= '
    '; + } else { + $resulttext = &mt('No changes made to user creation settings'); + } + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + if ($warningmsg ne '') { + $resulttext .= '
    '.$warningmsg.'
    '; + } + return $resulttext; +} + +sub modify_selfcreation { + my ($dom,%domconfig) = @_; + my ($resulttext,$warningmsg,%curr_usercreation,%curr_usermodify,%changes,%cancreate); + my (%save_usercreate,%save_usermodify); + my ($othertitle,$usertypes,$types) = &Apache::loncommon::sorted_inst_types($dom); + if (ref($types) eq 'ARRAY') { + $usertypes->{'default'} = $othertitle; + push(@{$types},'default'); + } +# +# Retrieve current domain configuration for self-creation of usernames from $domconfig{'usercreation'}. +# + if (ref($domconfig{'usercreation'}) eq 'HASH') { + foreach my $key (keys(%{$domconfig{'usercreation'}})) { + if ($key eq 'cancreate') { + if (ref($domconfig{'usercreation'}{$key}) eq 'HASH') { + foreach my $item (keys(%{$domconfig{'usercreation'}{$key}})) { + if (($item eq 'selfcreate') || ($item eq 'statustocreate') || + ($item eq 'captcha') || ($item eq 'recaptchakeys') || + ($item eq 'emailusername') || ($item eq 'notify')) { + $curr_usercreation{$key}{$item} = $domconfig{'usercreation'}{$key}{$item}; + } else { + $save_usercreate{$key}{$item} = $domconfig{'usercreation'}{$key}{$item}; + } + } + } + } elsif ($key eq 'email_rule') { + $curr_usercreation{$key} = $domconfig{'usercreation'}{$key}; + } else { + $save_usercreate{$key} = $domconfig{'usercreation'}{$key}; + } + } + } +# +# Retrieve current domain configuration for self-creation of usernames from $domconfig{'usermodification'}. +# + if (ref($domconfig{'usermodification'}) eq 'HASH') { + foreach my $key (keys(%{$domconfig{'usermodification'}})) { + if ($key eq 'selfcreate') { + $curr_usermodify{$key} = $domconfig{'usermodification'}{$key}; + } else { + $save_usermodify{$key} = $domconfig{'usermodification'}{$key}; + } + } + } + + my @contexts = ('selfcreate'); + @{$cancreate{'selfcreate'}} = (); + %{$cancreate{'emailusername'}} = (); + @{$cancreate{'statustocreate'}} = (); 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', + email => 'users who provide a valid e-mail address for use as username (automatic creation)', + emailapproval => 'users who provide a valid e-mail address for use as username (queued for Domain Coordinator review)', ); +# +# Populate $cancreate{'selfcreate'} array reference with types of user, for which self-creation of user accounts +# is permitted. +# + foreach my $item ('login','sso','email') { + if ($item eq 'email') { + if ($env{'form.cancreate_email'} eq 'email') { + push(@{$cancreate{'selfcreate'}},'email'); + } elsif ($env{'form.cancreate_email'} eq 'emailapproval') { + push(@{$cancreate{'selfcreate'}},'emailapproval'); + } + } else { + if ($env{'form.cancreate_'.$item}) { + push(@{$cancreate{'selfcreate'}},$item); + } + } + } + my (@email_rule,%userinfo,%savecaptcha); + my ($infofields,$infotitles) = &Apache::loncommon::emailusername_info(); +# +# Populate $cancreate{'emailusername'}{$type} hash ref with information fields (if new user will provide data +# value set to one), if self-creation with e-mail address permitted, where $type is user type: faculty, staff, student etc. +# + if (($env{'form.cancreate_email'} eq 'email') || ($env{'form.cancreate_email'} eq 'emailapproval')) { + push(@contexts,'emailusername'); + if (ref($types) eq 'ARRAY') { + foreach my $type (@{$types}) { + if (ref($infofields) eq 'ARRAY') { + foreach my $field (@{$infofields}) { + if ($env{'form.canmodify_emailusername_'.$type.'_'.$field} =~ /^(required|optional)$/) { + $cancreate{'emailusername'}{$type}{$field} = $1; + } + } + } + } + } +# +# Populate $cancreate{'notify'} hash ref with names of Domain Coordinators who are to be notified of +# queued requests for self-creation of account using e-mail address as username +# + + my @approvalnotify = &Apache::loncommon::get_env_multiple('form.selfcreationnotifyapproval'); + @approvalnotify = sort(@approvalnotify); + $cancreate{'notify'}{'approval'} = join(',',@approvalnotify); + if (ref($curr_usercreation{'cancreate'}) eq 'HASH') { + if (ref($curr_usercreation{'cancreate'}{'notify'}) eq 'HASH') { + if ($curr_usercreation{'cancreate'}{'notify'}{'approval'} ne $cancreate{'notify'}{'approval'}) { + push(@{$changes{'cancreate'}},'notify'); + } + } else { + if ($cancreate{'notify'}{'approval'}) { + push(@{$changes{'cancreate'}},'notify'); + } + } + } elsif ($cancreate{'notify'}{'approval'}) { + push(@{$changes{'cancreate'}},'notify'); + } + +# +# Retrieve rules (if any) governing types of e-mail address which may be used as a username +# + @email_rule = &Apache::loncommon::get_env_multiple('form.email_rule'); + &process_captcha('cancreate',\%changes,\%savecaptcha,$curr_usercreation{'cancreate'}); + if (ref($curr_usercreation{'email_rule'}) eq 'ARRAY') { + if (@{$curr_usercreation{'email_rule'}} > 0) { + foreach my $type (@{$curr_usercreation{'email_rule'}}) { + if (!grep(/^\Q$type\E$/,@email_rule)) { + push(@{$changes{'email_rule'}},$type); + } + } + } + if (@email_rule > 0) { + foreach my $type (@email_rule) { + if (!grep(/^\Q$type\E$/,@{$curr_usercreation{'email_rule'}})) { + push(@{$changes{'email_rule'}},$type); + } + } + } + } elsif (@email_rule > 0) { + push(@{$changes{'email_rule'}},@email_rule); + } + } +# +# Check if domain default is set appropriately, if selef-creation of accounts is to be available for +# institutional log-in. +# + if (grep(/^login$/,@{$cancreate{'selfcreate'}})) { + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); + if (!((($domdefaults{'auth_def'} =~/^krb/) && ($domdefaults{'auth_arg_def'} ne '')) || + ($domdefaults{'auth_def'} eq 'localauth'))) { + $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.'); + } + } + my @fields = ('lastname','firstname','middlename','generation', + 'permanentemail','id'); + my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); +# +# Where usernames may created for institutional log-in and/or institutional single sign on: +# (a) populate $cancreate{'statustocreate'} array reference with institutional status types who +# may self-create accounts +# (b) populate $save_usermodify{'selfcreate'} hash reference with status types, and information fields +# which the user may supply, if institutional data is unavailable. +# + if (($env{'form.cancreate_login'}) || ($env{'form.cancreate_sso'})) { + if (ref($types) eq 'ARRAY') { + if (@{$types} > 1) { + @{$cancreate{'statustocreate'}} = &Apache::loncommon::get_env_multiple('form.statustocreate'); + push(@contexts,'statustocreate'); + } else { + undef($cancreate{'statustocreate'}); + } + foreach my $type (@{$types}) { + my @modifiable = &Apache::loncommon::get_env_multiple('form.canmodify_'.$type); + foreach my $field (@fields) { + if (grep(/^\Q$field\E$/,@modifiable)) { + $save_usermodify{'selfcreate'}{$type}{$field} = 1; + } else { + $save_usermodify{'selfcreate'}{$type}{$field} = 0; + } + } + } + if (ref($curr_usermodify{'selfcreate'}) eq 'HASH') { + foreach my $type (@{$types}) { + if (ref($curr_usermodify{'selfcreate'}{$type}) eq 'HASH') { + foreach my $field (@fields) { + if ($save_usermodify{'selfcreate'}{$type}{$field} ne + $curr_usermodify{'selfcreate'}{$type}{$field}) { + push(@{$changes{'selfcreate'}},$type); + last; + } + } + } + } + } else { + foreach my $type (@{$types}) { + push(@{$changes{'selfcreate'}},$type); + } + } + } + } + foreach my $item (@contexts) { + 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); + } + } + } + } + if (ref($cancreate{$item}) eq 'ARRAY') { + foreach my $type (@{$cancreate{$item}}) { + if (!grep(/^$type$/,@{$curr_usercreation{'cancreate'}{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + } elsif (ref($curr_usercreation{'cancreate'}{$item}) eq 'HASH') { + if (ref($cancreate{$item}) eq 'HASH') { + foreach my $curr (keys(%{$curr_usercreation{'cancreate'}{$item}})) { + if (ref($curr_usercreation{'cancreate'}{$item}{$curr}) eq 'HASH') { + foreach my $field (keys(%{$curr_usercreation{'cancreate'}{$item}{$curr}})) { + unless ($curr_usercreation{'cancreate'}{$item}{$curr}{$field} eq $cancreate{$item}{$curr}{$field}) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } else { + if (!$cancreate{$item}{$curr}) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + foreach my $field (keys(%{$cancreate{$item}})) { + if (ref($cancreate{$item}{$field}) eq 'HASH') { + foreach my $inner (keys(%{$cancreate{$item}{$field}})) { + if (ref($curr_usercreation{'cancreate'}{$item}{$field}) eq 'HASH') { + unless ($curr_usercreation{'cancreate'}{$item}{$field}{$inner} eq $cancreate{$item}{$field}{$inner}) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } else { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } else { + if (!$curr_usercreation{'cancreate'}{$item}{$field}) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } + } + } elsif ($curr_usercreation{'cancreate'}{$item}) { + if (ref($cancreate{$item}) eq 'ARRAY') { + if (!grep(/^\Q$curr_usercreation{'cancreate'}{$item}\E$/,@{$cancreate{$item}})) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } elsif (ref($cancreate{$item}) eq 'HASH') { + if (!$cancreate{$item}{$curr_usercreation{'cancreate'}{$item}}) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + } + } + } elsif ($item eq 'emailusername') { + if (ref($cancreate{$item}) eq 'HASH') { + foreach my $type (keys(%{$cancreate{$item}})) { + if (ref($cancreate{$item}{$type}) eq 'HASH') { + foreach my $field (keys(%{$cancreate{$item}{$type}})) { + if ($cancreate{$item}{$type}{$field}) { + if (!grep(/^$item$/,@{$changes{'cancreate'}})) { + push(@{$changes{'cancreate'}},$item); + } + last; + } + } + } + } + } + } + } +# +# Populate %save_usercreate hash with updates to self-creation configuration. +# + $save_usercreate{'cancreate'}{'captcha'} = $savecaptcha{'captcha'}; + $save_usercreate{'cancreate'}{'recaptchakeys'} = $savecaptcha{'recaptchakeys'}; + $save_usercreate{'cancreate'}{'selfcreate'} = $cancreate{'selfcreate'}; + if (ref($cancreate{'notify'}) eq 'HASH') { + $save_usercreate{'cancreate'}{'notify'} = $cancreate{'notify'}; + } + if (ref($cancreate{'statustocreate'}) eq 'ARRAY') { + $save_usercreate{'cancreate'}{'statustocreate'} = $cancreate{'statustocreate'}; + } + $save_usercreate{'cancreate'}{'emailusername'} = $cancreate{'emailusername'}; + $save_usercreate{'emailrule'} = \@email_rule; + + my %userconfig_hash = ( + usercreation => \%save_usercreate, + usermodification => \%save_usermodify, + ); + my $putresult = &Apache::lonnet::put_dom('configuration',\%userconfig_hash, + $dom); +# +# Accumulate details of changes to domain cofiguration for self-creation of usernames in $resulttext +# if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; if (ref($changes{'cancreate'}) eq 'ARRAY') { - my %lt = &usercreation_types(); + my %lt = &selfcreation_types(); foreach my $type (@{$changes{'cancreate'}}) { my $chgtext; - unless (($type eq 'statustocreate') || ($type eq 'captcha') || ($type eq 'recaptchakeys')) { - $chgtext = $lt{$type}.', '; - } if ($type eq 'selfcreate') { if (@{$cancreate{$type}} == 0) { - $chgtext .= &mt('creation of a new user account is not permitted.'); + $chgtext .= &mt('Self creation of a new user account is not permitted.'); } else { - $chgtext .= &mt('creation of a new account is permitted for:').'
        '; + $chgtext .= &mt('Self-creation of a new account is permitted for:'). + '
          '; foreach my $case (@{$cancreate{$type}}) { $chgtext .= '
        • '.$selfcreatetypes{$case}.'
        • '; } @@ -6918,7 +8284,10 @@ sub modify_usercreation { 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.").''; + $chgtext .= '
          '. + ''. + &mt("However, no institutional affiliations (including 'other') are currently permitted to create accounts."). + ''; } } } @@ -6929,11 +8298,13 @@ sub modify_usercreation { (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.").''; - } + $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):'); @@ -6950,7 +8321,9 @@ sub modify_usercreation { } $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.').''; + $chgtext .= '
        '. + &mt('However, users authenticated by institutional login/single sign on are not currently permitted to create accounts.'). + ''; } } } else { @@ -6962,21 +8335,21 @@ sub modify_usercreation { } } } elsif ($type eq 'captcha') { - if ($cancreate{$type} eq 'notused') { + if ($savecaptcha{$type} eq 'notused') { $chgtext .= &mt('No CAPTCHA validation in use for self-creation screen.'); } else { my %captchas = &captcha_phrases(); - if ($captchas{$cancreate{$type}}) { - $chgtext .= &mt("Validation for self-creation screen set to $captchas{$cancreate{$type}}."); + if ($captchas{$savecaptcha{$type}}) { + $chgtext .= &mt("Validation for self-creation screen set to $captchas{$savecaptcha{$type}}."); } else { - $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); + $chgtext .= &mt('Validation for self-creation screen set to unknown type.'); } } } elsif ($type eq 'recaptchakeys') { my ($privkey,$pubkey); - if (ref($cancreate{$type}) eq 'HASH') { - $pubkey = $cancreate{$type}{'public'}; - $privkey = $cancreate{$type}{'private'}; + if (ref($savecaptcha{$type}) eq 'HASH') { + $pubkey = $savecaptcha{$type}{'public'}; + $privkey = $savecaptcha{$type}{'private'}; } $chgtext .= &mt('ReCAPTCHA keys changes').'
          '; if (!$pubkey) { @@ -6990,51 +8363,41 @@ sub modify_usercreation { $chgtext .= '
        • '.&mt('Private key set to [_1]',$pubkey).'
        • '; } $chgtext .= '
        '; - } 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.'); + } elsif ($type eq 'emailusername') { + if (ref($cancreate{'emailusername'}) eq 'HASH') { + if (ref($types) eq 'ARRAY') { + foreach my $type (@{$types}) { + if (ref($cancreate{'emailusername'}{$type}) eq 'HASH') { + if (keys(%{$cancreate{'emailusername'}{$type}}) > 0) { + $chgtext .= &mt('When self-creating account with e-mail as username, the following information will be provided by [_1]:',$usertypes->{$type}). + '
          '; + foreach my $field (@{$infofields}) { + if ($cancreate{'emailusername'}{$type}{$field}) { + $chgtext .= '
        • '.$infotitles->{$field}.'
        • '; + } + } + } + $chgtext .= '
        '; + } else { + $chgtext .= &mt('When self creating account with e-mail as username, no information besides e-mail address will be provided by [_1].',$usertypes->{$type}).'
        '; + } + } + } + } + } elsif ($type eq 'notify') { + $chgtext = &mt('No Domain Coordinators will receive notification of username requests requiring approval.'); + if (ref($changes{'cancreate'}) eq 'ARRAY') { + if ((grep(/^notify$/,@{$changes{'cancreate'}})) && (ref($cancreate{'notify'}) eq 'HASH')) { + if ($cancreate{'notify'}{'approval'}) { + $chgtext = &mt('Notification of username requests requiring approval will be sent to: ').$cancreate{'notify'}{'approval'}; + } + } } } - $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'}.'
        • '; + if ($chgtext) { + $resulttext .= '
        • '.$chgtext.'
        • '; } } - $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) = @@ -7047,37 +8410,48 @@ sub modify_usercreation { } $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.'
    • '; + $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.').'
    • '; + $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 (ref($changes{'selfcreate'}) eq 'ARRAY') { + $resulttext .= '
      • '.&mt('When self-creating institutional account:').'
          '; + my %fieldtitles = &Apache::loncommon::personal_data_fieldtitles(); + foreach my $type (@{$changes{'selfcreate'}}) { + my $typename = $type; + if (ref($usertypes) eq 'HASH') { + if ($usertypes->{$type} ne '') { + $typename = $usertypes->{$type}; } } - if (@allowed > 0) { - $chgtext .= join(', ',@allowed).''; + my @modifiable; + $resulttext .= '
        • '. + &mt('Self-creation of account by users with status: [_1]', + ''.$typename.''). + ' - '.&mt('modifiable fields (if institutional data blank): '); + foreach my $field (@fields) { + if ($save_usermodify{'selfcreate'}{$type}{$field}) { + push(@modifiable,''.$fieldtitles{$field}.''); + } + } + if (@modifiable > 0) { + $resulttext .= join(', ',@modifiable); } else { - $chgtext .= &mt('none').'
        • '; + $resulttext .= &mt('none'); } + $resulttext .= ''; } - $chgtext .= '
        '; - $resulttext .= '
      • '.&mt('Authentication types available for assignment to new users').'
        '.$chgtext; - $resulttext .= '
      • '; + $resulttext .= '
      '; } $resulttext .= '
    '; } else { - $resulttext = &mt('No changes made to user creation settings'); + $resulttext = &mt('No changes made to self-creation settings'); } } else { $resulttext = ''. @@ -7097,7 +8471,7 @@ sub process_captcha { $newsettings->{'captcha'} = 'original'; } if ($current->{'captcha'} ne $newsettings->{'captcha'}) { - if ($container eq 'cancreate') { + if ($container eq 'cancreate') { if (ref($changes->{'cancreate'}) eq 'ARRAY') { push(@{$changes->{'cancreate'}},'captcha'); } elsif (!defined($changes->{'cancreate'})) { @@ -7136,7 +8510,7 @@ sub process_captcha { $changes->{'cancreate'} = ['recaptchakeys']; } } else { - $changes->{'recaptchakeys'} = 1; + $changes->{'recaptchakeys'} = 1; } } return; @@ -7144,17 +8518,20 @@ sub process_captcha { sub modify_usermodification { my ($dom,%domconfig) = @_; - my ($resulttext,%curr_usermodification,%changes); + my ($resulttext,%curr_usermodification,%changes,%modifyhash); if (ref($domconfig{'usermodification'}) eq 'HASH') { foreach my $key (keys(%{$domconfig{'usermodification'}})) { - $curr_usermodification{$key} = $domconfig{'usermodification'}{$key}; + if ($key eq 'selfcreate') { + $modifyhash{$key} = $domconfig{'usermodification'}{$key}; + } else { + $curr_usermodification{$key} = $domconfig{'usermodification'}{$key}; + } } } - my @contexts = ('author','course','selfcreate'); + my @contexts = ('author','course'); my %context_title = ( author => 'In author context', course => 'In course context', - selfcreate => 'When self creating account', ); my @fields = ('lastname','firstname','middlename','generation', 'permanentemail','id'); @@ -7162,14 +8539,7 @@ sub modify_usermodification { 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); @@ -7215,26 +8585,13 @@ sub modify_usermodification { 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}; - } - } + if ($role eq 'cr') { + $rolename = &mt('Custom'); } else { - if ($role eq 'cr') { - $rolename = &mt('Custom'); - } else { - $rolename = &Apache::lonnet::plaintext($role); - } + $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: '); - } + $resulttext .= '
  • '.&mt('Target user with [_1] role',$rolename).' - '.&mt('modifiable fields: '); foreach my $field (@fields) { if ($modifyhash{$context}{$role}{$field}) { push(@modifiable,$fieldtitles{$field}); @@ -7263,9 +8620,9 @@ sub modify_usermodification { } sub modify_defaults { - my ($dom,$r) = @_; + my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,$mailmsgtxt,%newvalues,%changes,@errors); - my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); my @items = ('auth_def','auth_arg_def','lang_def','timezone_def','datelocale_def','portal_def'); my @authtypes = ('internal','krb4','krb5','localauth'); foreach my $item (@items) { @@ -7325,7 +8682,7 @@ sub modify_defaults { if ($putresult eq 'ok') { if (keys(%changes) > 0) { $resulttext = &mt('Changes made:').'
      '; - my $version = $r->dir_config('lonVersion'); + my $version = &Apache::lonnet::get_server_loncaparev($dom); 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}; @@ -7348,9 +8705,21 @@ sub modify_defaults { $mailmsgtext .= "\n"; my $cachetime = 24*60*60; &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domdefaults'} = 1; + } 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); + my $notify = 1; + if (ref($domconfig{'contacts'}) eq 'HASH') { + if ($domconfig{'contacts'}{'reportupdates'} == 0) { + $notify = 0; + } + } + if ($notify) { + &Apache::lonmsg::sendemail('installrecord@loncapa.org', + "LON-CAPA Domain Settings Change - $dom", + $mailmsgtext); + } } } else { $resulttext = &mt('No changes made to default authentication/language/timezone settings'); @@ -7370,7 +8739,7 @@ sub modify_defaults { } sub modify_scantron { - my ($r,$dom,$confname,%domconfig) = @_; + my ($r,$dom,$confname,$lastactref,%domconfig) = @_; my ($resulttext,%confhash,%changes,$errors); my $custom = 'custom.tab'; my $default = 'default.tab'; @@ -7431,6 +8800,9 @@ sub modify_scantron { } $resulttext .= '
    '; &Apache::loncommon::devalidate_domconfig_cache($dom); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domainconfig'} = 1; + } } else { $resulttext = &mt('No changes made to bubblesheet format file'); } @@ -7821,7 +9193,7 @@ sub modify_helpsettings { $changes{$item} = 1; } } - if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) { + if (($env{'form.'.$item} eq '0') || ($env{'form.'.$item} eq '1')) { $helphash{'helpsettings'}{$item} = $env{'form.'.$item}; } } @@ -7854,11 +9226,17 @@ sub modify_helpsettings { } sub modify_coursedefaults { - my ($dom,%domconfig) = @_; + my ($dom,$lastactref,%domconfig) = @_; my ($resulttext,$errors,%changes,%defaultshash); my %defaultchecked = ('canuse_pdfforms' => 'off'); - my @offon = ('off','on'); my @toggles = ('canuse_pdfforms'); + my @numbers = ('anonsurvey_threshold','uploadquota_official','uploadquota_unofficial', + 'uploadquota_community','uploadquota_textbook'); + my @types = ('official','unofficial','community','textbook'); + my %staticdefaults = ( + anonsurvey_threshold => 10, + uploadquota => 500, + ); $defaultshash{'coursedefaults'} = {}; @@ -7874,7 +9252,7 @@ sub modify_coursedefaults { if (($domconfig{'coursedefaults'}{$item} eq '') && ($env{'form.'.$item} eq '0')) { $changes{$item} = 1; - } elsif ($domconfig{'coursdefaults'}{$item} ne $env{'form.'.$item}) { + } elsif ($domconfig{'coursedefaults'}{$item} ne $env{'form.'.$item}) { $changes{$item} = 1; } } elsif ($defaultchecked{$item} eq 'off') { @@ -7887,28 +9265,92 @@ sub modify_coursedefaults { } $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; + foreach my $item (@numbers) { + my ($currdef,$newdef); + $newdef = $env{'form.'.$item}; + if ($item eq 'anonsurvey_threshold') { + $currdef = $domconfig{'coursedefaults'}{$item}; + $newdef =~ s/\D//g; + if ($newdef eq '' || $newdef < 1) { + $newdef = 1; + } + $defaultshash{'coursedefaults'}{$item} = $newdef; + } else { + my ($type) = ($item =~ /^\Quploadquota_\E(\w+)$/); + if (ref($domconfig{'coursedefaults'}{'uploadquota'}) eq 'HASH') { + $currdef = $domconfig{'coursedefaults'}{'uploadquota'}{$type}; + } + $newdef =~ s/[^\w.\-]//g; + $defaultshash{'coursedefaults'}{'uploadquota'}{$type} = $newdef; + } + if ($currdef ne $newdef) { + my $staticdef; + if ($item eq 'anonsurvey_threshold') { + unless (($currdef eq '') && ($newdef == $staticdefaults{$item})) { + $changes{$item} = 1; + } + } else { + unless (($currdef eq '') && ($newdef == $staticdefaults{'uploadquota'})) { + $changes{'uploadquota'} = 1; + } + } + } + } + + my $officialcreds = $env{'form.official_credits'}; + $officialcreds =~ s/[^\d.]+//g; + my $unofficialcreds = $env{'form.unofficial_credits'}; + $unofficialcreds =~ s/[^\d.]+//g; + my $textbookcreds = $env{'form.textbook_credits'}; + $textbookcreds =~ s/[^\d.]+//g; + if (ref($domconfig{'coursedefaults'}{'coursecredits'} ne 'HASH') && + ($env{'form.coursecredits'} eq '1')) { + $changes{'coursecredits'} = 1; + } else { + if (($domconfig{'coursedefaults'}{'coursecredits'}{'official'} ne $officialcreds) || + ($domconfig{'coursedefaults'}{'coursecredits'}{'unofficial'} ne $unofficialcreds) || + ($domconfig{'coursedefaults'}{'coursecredits'}{'textbook'} ne $textbookcreds)) { + $changes{'coursecredits'} = 1; } } + $defaultshash{'coursedefaults'}{'coursecredits'} = { + official => $officialcreds, + unofficial => $unofficialcreds, + textbook => $textbookcreds, + } } 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 %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); + if (($changes{'canuse_pdfforms'}) || ($changes{'coursecredits'}) || + ($changes{'uploadquota'})) { + if ($changes{'canuse_pdfforms'}) { + $domdefaults{'canuse_pdfforms'}=$defaultshash{'coursedefaults'}{'canuse_pdfforms'}; + } + if ($changes{'coursecredits'}) { + if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') { + $domdefaults{'officialcredits'} = + $defaultshash{'coursedefaults'}{'coursecredits'}{'official'}; + $domdefaults{'unofficialcredits'} = + $defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}; + $domdefaults{'textbookcredits'} = + $domdefaults{'coursedefaults'}{'coursecredits'}{'textbook'}; + } + } + if ($changes{'uploadquota'}) { + if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') { + foreach my $type (@types) { + $domdefaults{$type.'quota'}=$defaultshash{'coursedefaults'}{'uploadquota'}{$type}; + } + } + } my $cachetime = 24*60*60; &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domdefaults'} = 1; + } } $resulttext = &mt('Changes made:').'
      '; foreach my $item (sort(keys(%changes))) { @@ -7919,7 +9361,37 @@ sub modify_coursedefaults { $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 .= '
    • '.&mt('Responder count required for display of anonymous survey submissions set to [_1].',$defaultshash{'coursedefaults'}{'anonsurvey_threshold'}).'
    • '; + } elsif ($item eq 'uploadquota') { + if (ref($defaultshash{'coursedefaults'}{'uploadquota'}) eq 'HASH') { + $resulttext .= '
    • '.&mt('Default quota for content uploaded to a course/community via Course Editor set as follows:').'
        '. + '
      • '.&mt('Official courses: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'official'}.'').'
      • '. + '
      • '.&mt('Unofficial courses: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'unofficial'}.'').'
      • '. + '
      • '.&mt('Textbook courses: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'textbook'}.'').'
      • '. + + '
      • '.&mt('Communities: [_1] MB',''.$defaultshash{'coursedefaults'}{'uploadquota'}{'community'}.'').'
      • '. + '
      '. + '
    • '; + } else { + $resulttext .= '
    • '.&mt('Default quota for content uploaded via Course Editor remains default: [_1] MB',$staticdefaults{'uploadquota'}).'
    • '; + } + } elsif ($item eq 'coursecredits') { + if (ref($defaultshash{'coursedefaults'}{'coursecredits'}) eq 'HASH') { + if (($domdefaults{'officialcredits'} eq '') && + ($domdefaults{'unofficialcredits'} eq '') && + ($domdefaults{'textbookcredits'} eq '')) { + $resulttext .= '
    • '.&mt('Student credits not in use for courses in this domain').'
    • '; + } else { + $resulttext .= '
    • '.&mt('Student credits can be set per course by a Domain Coordinator, with the following defaults applying:').'
        '. + '
      • '.&mt('Official courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'official'}).'
      • '. + '
      • '.&mt('Unofficial courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'unofficial'}).'
      • '. + '
      • '.&mt('Textbook courses: [_1]',$defaultshash{'coursedefaults'}{'coursecredits'}{'textbook'}).'
      • '. + '
      '. + '
    • '; + } + } else { + $resulttext .= '
    • '.&mt('Student credits not in use for courses in this domain').'
    • '; + } } } $resulttext .= '
    '; @@ -7933,8 +9405,212 @@ sub modify_coursedefaults { return $resulttext; } +sub modify_selfenrollment { + my ($dom,$lastactref,%domconfig) = @_; + my ($resulttext,$errors,%changes,%selfenrollhash,%ordered); + my @types = ('official','unofficial','community','textbook'); + my %titles = &tool_titles(); + my %descs = &selfenroll_default_descs(); + ($ordered{'admin'},my $titlesref) = &get_selfenroll_titles(); + $ordered{'default'} = ['types','registered','approval','limit']; + + my (%roles,%shown,%toplevel); + $roles{'0'} = &Apache::lonnet::plaintext('dc'); + + if (ref($domconfig{'selfenrollment'}) ne 'HASH') { + if ($domconfig{'selfenrollment'} eq '') { + $domconfig{'selfenrollment'} = {}; + } + } + %toplevel = ( + admin => 'Configuration Rights', + default => 'Default settings', + validation => 'Validation of self-enrollment requests', + ); + my ($itemsref,$namesref,$fieldsref) = &selfenroll_validation_types(); + + if (ref($ordered{'admin'}) eq 'ARRAY') { + foreach my $item (@{$ordered{'admin'}}) { + foreach my $type (@types) { + if ($env{'form.selfenrolladmin_'.$item.'_'.$type}) { + $selfenrollhash{'admin'}{$type}{$item} = 1; + } else { + $selfenrollhash{'admin'}{$type}{$item} = 0; + } + if (ref($domconfig{'selfenrollment'}{'admin'}) eq 'HASH') { + if (ref($domconfig{'selfenrollment'}{'admin'}{$type}) eq 'HASH') { + if ($selfenrollhash{'admin'}{$type}{$item} ne + $domconfig{'selfenrollment'}{'admin'}{$type}{$item}) { + push(@{$changes{'admin'}{$type}},$item); + } + } else { + if (!$selfenrollhash{'admin'}{$type}{$item}) { + push(@{$changes{'admin'}{$type}},$item); + } + } + } elsif (!$selfenrollhash{'admin'}{$type}{$item}) { + push(@{$changes{'admin'}{$type}},$item); + } + } + } + } + + foreach my $item (@{$ordered{'default'}}) { + foreach my $type (@types) { + my $value = $env{'form.selfenrolldefault_'.$item.'_'.$type}; + if ($item eq 'types') { + unless (($value eq 'all') || ($value eq 'dom')) { + $value = ''; + } + } elsif ($item eq 'registered') { + unless ($value eq '1') { + $value = 0; + } + } elsif ($item eq 'approval') { + unless ($value =~ /^[012]$/) { + $value = 0; + } + } else { + unless (($value eq 'allstudents') || ($value eq 'selfenrolled')) { + $value = 'none'; + } + } + $selfenrollhash{'default'}{$type}{$item} = $value; + if (ref($domconfig{'selfenrollment'}{'default'}) eq 'HASH') { + if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') { + if ($selfenrollhash{'default'}{$type}{$item} ne + $domconfig{'selfenrollment'}{'default'}{$type}{$item}) { + push(@{$changes{'default'}{$type}},$item); + } + } else { + push(@{$changes{'default'}{$type}},$item); + } + } else { + push(@{$changes{'default'}{$type}},$item); + } + if ($item eq 'limit') { + if (($value eq 'allstudents') || ($value eq 'selfenrolled')) { + $env{'form.selfenrolldefault_cap_'.$type} =~ s/\D//g; + if ($env{'form.selfenrolldefault_cap_'.$type} ne '') { + $selfenrollhash{'default'}{$type}{'cap'} = $env{'form.selfenrolldefault_cap_'.$type}; + } + } else { + $selfenrollhash{'default'}{$type}{'cap'} = ''; + } + if (ref($domconfig{'selfenrollment'}{'default'}{$type}) eq 'HASH') { + if ($selfenrollhash{'default'}{$type}{'cap'} ne + $domconfig{'selfenrollment'}{'admin'}{$type}{'cap'}) { + push(@{$changes{'default'}{$type}},'cap'); + } + } elsif ($selfenrollhash{'default'}{$type}{'cap'} ne '') { + push(@{$changes{'default'}{$type}},'cap'); + } + } + } + } + + foreach my $item (@{$itemsref}) { + if ($item eq 'fields') { + my @changed; + @{$selfenrollhash{'validation'}{$item}} = &Apache::loncommon::get_env_multiple('form.selfenroll_validation_'.$item); + if (@{$selfenrollhash{'validation'}{$item}} > 0) { + @{$selfenrollhash{'validation'}{$item}} = sort(@{$selfenrollhash{'validation'}{$item}}); + } + if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') { + if (ref($domconfig{'selfenrollment'}{'validation'}{$item}) eq 'ARRAY') { + @changed = &Apache::loncommon::compare_arrays($selfenrollhash{'validation'}{$item}, + $domconfig{'selfenrollment'}{'validation'}{$item}); + } else { + @changed = @{$selfenrollhash{'validation'}{$item}}; + } + } else { + @changed = @{$selfenrollhash{'validation'}{$item}}; + } + if (@changed) { + if ($selfenrollhash{'validation'}{$item}) { + $changes{'validation'}{$item} = join(', ',@{$selfenrollhash{'validation'}{$item}}); + } else { + $changes{'validation'}{$item} = &mt('None'); + } + } + } else { + $selfenrollhash{'validation'}{$item} = $env{'form.selfenroll_validation_'.$item}; + if ($item eq 'markup') { + if ($env{'form.selfenroll_validation_'.$item}) { + $env{'form.selfenroll_validation_'.$item} =~ s/[\n\r\f]+/\s/gs; + } + } + if (ref($domconfig{'selfenrollment'}{'validation'}) eq 'HASH') { + if ($domconfig{'selfenrollment'}{'validation'}{$item} ne $selfenrollhash{'validation'}{$item}) { + $changes{'validation'}{$item} = $selfenrollhash{'validation'}{$item}; + } + } + } + } + + my $putresult = &Apache::lonnet::put_dom('configuration',{'selfenrollment' => \%selfenrollhash}, + $dom); + if ($putresult eq 'ok') { + if (keys(%changes) > 0) { + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); + $resulttext = &mt('Changes made:').'
      '; + foreach my $key ('admin','default','validation') { + if (ref($changes{$key}) eq 'HASH') { + $resulttext .= '
    • '.$toplevel{$key}.'
        '; + if ($key eq 'validation') { + foreach my $item (@{$itemsref}) { + if (exists($changes{$key}{$item})) { + if ($item eq 'markup') { + $resulttext .= '
      • '.&mt('[_1] set to: [_2]',$namesref->{$item}, + '
        '.$changes{$key}{$item}.'
        ').'
      • '; + } else { + $resulttext .= '
      • '.&mt('[_1] set to: [_2]',$namesref->{$item}, + ''.$changes{$key}{$item}.'').'
      • '; + } + } + } + } else { + foreach my $type (@types) { + if ($type eq 'community') { + $roles{'1'} = &mt('Community personnel'); + } else { + $roles{'1'} = &mt('Course personnel'); + } + if (ref($changes{$key}{$type}) eq 'ARRAY') { + $resulttext .= '
      • '.$titles{$type}.'
          '; + foreach my $item (@{$ordered{$key}}) { + if (grep(/^\Q$item\E$/,@{$changes{$key}{$type}})) { + $resulttext .= '
        • '; + if ($key eq 'admin') { + $resulttext .= &mt('[_1] -- management by: [_2]',$titlesref->{$item}, + ''.$roles{$selfenrollhash{'admin'}{$type}{$item}}.''); + } else { + $resulttext .= &mt('[_1] set to: [_2]',$titlesref->{$item}, + ''.$descs{$item}{$selfenrollhash{'default'}{$type}{$item}}.''); + } + $resulttext .= '
        • '; + } + } + $resulttext .= '
      • '; + } + } + $resulttext .= '
    • '; + } + } + } + $resulttext .= '
    '; + } else { + $resulttext = &mt('No changes made to self-enrollment settings'); + } + } else { + $resulttext = ''. + &mt('An error occurred: [_1]',$putresult).''; + } + return $resulttext; +} + sub modify_usersessions { - my ($dom,%domconfig) = @_; + my ($dom,$lastactref,%domconfig) = @_; my @hostingtypes = ('version','excludedomain','includedomain'); my @offloadtypes = ('primary','default'); my %types = ( @@ -7951,7 +9627,7 @@ sub modify_usersessions { foreach my $prefix (@prefixes) { $defaultshash{'usersessions'}{$prefix} = {}; } - my %domdefaults = &Apache::lonnet::get_domain_defaults($dom); + my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1); my $resulttext; my %iphost = &Apache::lonnet::get_iphost(); foreach my $prefix (@prefixes) { @@ -8127,6 +9803,9 @@ sub modify_usersessions { } my $cachetime = 24*60*60; &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime); + if (ref($lastactref) eq 'HASH') { + $lastactref->{'domdefaults'} = 1; + } if (keys(%changes) > 0) { my %lt = &usersession_titles(); $resulttext = &mt('Changes made:').'
      '; @@ -8138,7 +9817,8 @@ sub modify_usersessions { foreach my $lonhost (sort(keys(%{$changes{$prefix}}))) { $resulttext .= '
    • '.$lonhost.' '; my $lonhostdom = &Apache::lonnet::host_domain($lonhost); - &Apache::lonnet::remote_devalidate_cache($lonhost,'spares',$lonhostdom); + my $cachekey = &escape('spares').':'.&escape($lonhostdom); + &Apache::lonnet::remote_devalidate_cache($lonhost,[$cachekey]); if (ref($changes{$prefix}{$lonhost}) eq 'HASH') { foreach my $type (@{$types{$prefix}}) { if ($changes{$prefix}{$lonhost}{$type}) { @@ -8228,7 +9908,7 @@ sub modify_loadbalancing { if ($balancer eq '') { next; } - if (!exists($servers{$balancer})) { + if (!exists($servers{$balancer})) { if (exists($currbalancer{$balancer})) { push(@{$changes{'delete'}},$balancer); } @@ -8279,14 +9959,14 @@ sub modify_loadbalancing { } } else { if (ref($defaultshash{'loadbalancing'}{$balancer}) eq 'HASH') { - foreach my $sparetype (@sparestypes) { + foreach my $sparetype (@sparestypes) { if (ref($defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}) eq 'ARRAY') { if (@{$defaultshash{'loadbalancing'}{$balancer}{'targets'}{$sparetype}} > 0) { $changes{'curr'}{$balancer}{'targets'} = 1; } } } - } + } } my $ishomedom; if (&Apache::lonnet::host_domain($balancer) eq $dom) { @@ -8295,7 +9975,7 @@ sub modify_loadbalancing { if (ref($alltypes) eq 'ARRAY') { foreach my $type (@{$alltypes}) { my $rule; - unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && + unless ((($type eq '_LC_external') || ($type eq '_LC_internetdom')) && (!$ishomedom)) { $rule = $env{'form.loadbalancing_rules_'.$i.'_'.$type}; } @@ -8320,17 +10000,17 @@ sub modify_loadbalancing { } my $putresult = &Apache::lonnet::put_dom('configuration', \%defaultshash,$dom); - if ($putresult eq 'ok') { if (keys(%changes) > 0) { if (ref($changes{'delete'}) eq 'ARRAY') { foreach my $balancer (sort(@{$changes{'delete'}})) { $resulttext .= '
    • '.&mt('Load Balancing discontinued for: [_1]',$balancer).'
    • '; - &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); + my $cachekey = &escape('loadbalancing').':'.&escape($dom); + &Apache::lonnet::remote_devalidate_cache($balancer,[$cachekey]); } } if (ref($changes{'add'}) eq 'ARRAY') { - foreach my $balancer (sort(@{$changes{'add'}})) { + foreach my $balancer (sort(@{$changes{'add'}})) { $resulttext .= '
    • '.&mt('Load Balancing enabled for: [_1]',$balancer); } } @@ -8371,17 +10051,19 @@ sub modify_loadbalancing { my $balancetext; if ($rule eq '') { $balancetext = $ruletitles{'default'}; - } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer')) { + } elsif (($rule eq 'homeserver') || ($rule eq 'externalbalancer') || + ($rule eq 'balancer') || ($rule eq 'offloadedto')) { $balancetext = $ruletitles{$rule}; } else { $balancetext = &mt('offload to [_1]',$defaultshash{'loadbalancing'}{$balancer}{'rules'}{$type}); } - $resulttext .= '
    • '.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'
    • '; + $resulttext .= '
    • '.&mt('Load Balancer: [_1] -- balancing for [_2] set to - "[_3]"',$balancer,$titles->{$type},$balancetext).'
    • '; } } } } - &Apache::lonnet::remote_devalidate_cache($balancer,'loadbalancing',$dom); + my $cachekey = &escape('loadbalancing').':'.&escape($dom); + &Apache::lonnet::remote_devalidate_cache($balancer,[$cachekey]); } } if ($resulttext ne '') { @@ -8444,73 +10126,104 @@ sub recurse_cat_deletes { sub get_active_dcs { my ($dom) = @_; - my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc']); + my $now = time; + my %dompersonnel = &Apache::lonnet::get_domain_roles($dom,['dc'],$now,$now); my %domcoords; my $numdcs = 0; - my $now = time; foreach my $server (keys(%dompersonnel)) { foreach my $user (sort(keys(%{$dompersonnel{$server}}))) { my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); - my ($end,$start) = split(':',$dompersonnel{$server}{$user}); - if (($end eq '') || ($end == 0) || ($end > $now)) { - if ($start <= $now) { - $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user}; - } - } + $domcoords{$uname.':'.$udom} = $dompersonnel{$server}{$user}; } } return %domcoords; } sub active_dc_picker { - my ($dom,$curr_dc) = @_; + my ($dom,$numinrow,$inputtype,$name,%currhash) = @_; my %domcoords = &get_active_dcs($dom); - my @dcs = sort(keys(%domcoords)); - my $numdcs = scalar(@dcs); - my $datatable; - my $numinrow = 2; + my @domcoord = keys(%domcoords); + if (keys(%currhash)) { + foreach my $dc (keys(%currhash)) { + unless (exists($domcoords{$dc})) { + push(@domcoord,$dc); + } + } + } + @domcoord = sort(@domcoord); + my $numdcs = scalar(@domcoord); + my $rows = 0; + my $table; if ($numdcs > 1) { - $datatable = '
  • '; - for (my $i=0; $i<@dcs; $i++) { + $table = '
    '; + for (my $i=0; $i<@domcoord; $i++) { my $rem = $i%($numinrow); if ($rem == 0) { if ($i > 0) { - $datatable .= ''; + $table .= ''; } - $datatable .= ''; + $table .= ''; + $rows ++; } - my $check = ' '; - if ($curr_dc eq '') { - if (!$i) { - $check = ' checked="checked" '; + my $check = ''; + if ($inputtype eq 'radio') { + if (keys(%currhash) == 0) { + if (!$i) { + $check = ' checked="checked"'; + } + } elsif (exists($currhash{$domcoord[$i]})) { + $check = ' checked="checked"'; + } + } else { + if (exists($currhash{$domcoord[$i]})) { + $check = ' checked="checked"'; } - } elsif ($dcs[$i] eq $curr_dc) { - $check = ' checked="checked" '; } - if ($i == @dcs - 1) { + if ($i == @domcoord - 1) { my $colsleft = $numinrow - $rem; if ($colsleft > 1) { - $datatable .= ''; + my ($dcname,$dcdom) = split(':',$domcoord[$i]); + my $user = &Apache::loncommon::plainname($dcname,$dcdom); + $table .= ''; + } + $table .= '
    '; + $table .= ''; } else { - $datatable .= ''; + $table .= ''; } } else { - $datatable .= ''; + $table .= ''; } - my ($dcname,$dcdom) = split(':',$dcs[$i]); - $datatable .= '
    '; + } elsif ($numdcs == 1) { + my ($dcname,$dcdom) = split(':',$domcoord[0]); + my $user = &Apache::loncommon::plainname($dcname,$dcdom); + if ($inputtype eq 'radio') { + $table .= ''.$user; + if ($user ne $dcname.':'.$dcdom) { + $table .= ' ('.$dcname.':'.$dcdom.')'; + } + } else { + my $check; + if (exists($currhash{$domcoord[0]})) { + $check = ' checked="checked"'; + } + $table .= ''; + $rows ++; } - $datatable .= '
    '; - } elsif (@dcs) { - $datatable .= ''; } - return ($numdcs,$datatable); + return ($numdcs,$table,$rows); } sub usersession_titles { @@ -8582,7 +10295,7 @@ sub lonbalance_targets_js { } &get_loadbalancers_config($servers,\%existing,\%currbalancer, \%currtargets,\%currrules); - my $balancers = join("','",sort(keys(%currbalancer))); + my $balancers = join("','",sort(keys(%currbalancer))); return <<"END"; + +END + +} + sub captcha_phrases { return &Apache::lonlocal::texthash ( priv => 'Private key', @@ -9049,4 +10794,28 @@ sub captcha_phrases { ); } +sub devalidate_remote_domconfs { + my ($dom,$cachekeys) = @_; + return unless (ref($cachekeys) eq 'HASH'); + my %servers = &Apache::lonnet::internet_dom_servers($dom); + my %thismachine; + map { $thismachine{$_} = 1; } &Apache::lonnet::current_machine_ids(); + my @posscached = ('domainconfig','domdefaults'); + if (keys(%servers) > 1) { + foreach my $server (keys(%servers)) { + next if ($thismachine{$server}); + my @cached; + foreach my $name (@posscached) { + if ($cachekeys->{$name}) { + push(@cached,&escape($name).':'.&escape($dom)); + } + } + if (@cached) { + &Apache::lonnet::remote_devalidate_cache($server,\@cached); + } + } + } + return; +} + 1;