--- loncom/auth/lonroles.pm 2009/06/29 12:43:45 1.228 +++ loncom/auth/lonroles.pm 2016/08/08 13:39:26 1.269.2.25 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # User Roles Screen # -# $Id: lonroles.pm,v 1.228 2009/06/29 12:43:45 bisitz Exp $ +# $Id: lonroles.pm,v 1.269.2.25 2016/08/08 13:39:26 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -57,8 +57,7 @@ course they should act on, etc. Both in handler determines via C's C<&allowed> function that a certain action is not allowed, C is used as error handler. This allows the user to select another role which may have permission to do -what they were trying to do. C can also be accessed via the -B button in the Remote Control. +what they were trying to do. =begin latex @@ -129,7 +128,7 @@ package Apache::lonroles; use strict; use Apache::lonnet; use Apache::lonuserstate(); -use Apache::Constants qw(:common); +use Apache::Constants qw(:common REDIRECT); use Apache::File(); use Apache::lonmenu; use Apache::loncommon; @@ -138,25 +137,21 @@ use Apache::lonannounce; use Apache::lonlocal; use Apache::lonpageflip(); use Apache::lonnavdisplay(); +use Apache::loncoursequeueadmin; +use Apache::longroup; +use Apache::lonrss; use GDBM_File; use LONCAPA qw(:DEFAULT :match); use HTML::Entities; sub redirect_user { - my ($r,$title,$url,$msg,$launch_nav) = @_; + my ($r,$title,$url,$msg) = @_; $msg = $title if (! defined($msg)); &Apache::loncommon::content_type($r,'text/html'); &Apache::loncommon::no_cache($r); $r->send_http_header; my $swinfo=&Apache::lonmenu::rawconfig(); - my $navwindow; - if ($launch_nav eq 'on') { - $navwindow.=&Apache::lonnavdisplay::launch_win('now',undef,undef, - ($url =~ m-^/adm/whatsnew-)); - } else { - $navwindow.=&Apache::lonnavmaps::close(); - } # Breadcrumbs my $brcrum = [{'href' => $url, @@ -176,7 +171,6 @@ $start_page $swinfo // ]]> -$navwindow

$msg

$end_page ENDREDIR @@ -214,16 +208,60 @@ sub handler { my $r = shift; + # Check for critical messages and redirect if present. + my ($redirect,$url) = &Apache::loncommon::critical_redirect(300); + if ($redirect) { + &Apache::loncommon::content_type($r,'text/html'); + $r->header_out(Location => $url); + return REDIRECT; + } + my $now=time; my $then=$env{'user.login.time'}; my $refresh=$env{'user.refresh.time'}; + my $update=$env{'user.update.time'}; if (!$refresh) { $refresh = $then; } + if (!$update) { + $update = $then; + } + + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); + +# -------------------------------------------------- Check if setting hot list + my $hotlist; + if ($env{'form.action'} eq 'verify_and_change_rolespref') { + $hotlist = &Apache::lonpreferences::verify_and_change_rolespref($r); + } + +# -------------------------------------------------------- Check for new roles + my $updateresult; + if ($env{'form.state'} eq 'doupdate') { + my $show_course=&Apache::loncommon::show_course(); + my $checkingtxt; + if ($show_course) { + $checkingtxt = &mt('Checking for new courses ...'); + } else { + $checkingtxt = &mt('Checking for new roles ...'); + } + $updateresult = $checkingtxt; + $updateresult .= &update_session_roles(); + &Apache::lonnet::appenv({'user.update.time' => $now}); + $update = $now; + &Apache::loncoursequeueadmin::reqauthor_check(); + } + +# -------------------------------------------------- Check for author requests + my $reqauthor; + if ($env{'form.state'} eq 'requestauthor') { + $reqauthor = &Apache::loncoursequeueadmin::process_reqauthor(\$update); + } + my $envkey; my %dcroles = (); - my $numdc = &check_fordc(\%dcroles,$then); - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); + my $numdc = &check_fordc(\%dcroles,$update,$then); + my $loncaparev = $r->dir_config('lonVersion'); # ================================================================== Roles Init if ($env{'form.selectrole'}) { @@ -237,30 +275,43 @@ sub handler { if ($env{'request.course.id'}) { # Check if user is CC trying to select a course role if ($env{'form.switchrole'}) { - if (!defined($env{'user.role.'.$env{'form.switchrole'}})) { - &adhoc_course_role($then); + my $switch_is_active; + if (defined($env{'user.role.'.$env{'form.switchrole'}})) { + my ($start,$end) = split(/\./,$env{'user.role.'.$env{'form.switchrole'}}); + if (!$end || $end > $now) { + if (!$start || $start < $update) { + $switch_is_active = 1; + } + } + } + unless ($switch_is_active) { + &adhoc_course_role($refresh,$update,$then); } } my %temp=('logout_'.$env{'request.course.id'} => time); &Apache::lonnet::put('email_status',\%temp); &Apache::lonnet::delenv('user.state.'.$env{'request.course.id'}); } - &Apache::lonnet::appenv({"request.course.id" => '', - "request.course.fn" => '', - "request.course.uri" => '', - "request.course.sec" => '', - "request.role" => 'cm', - "request.role.adv" => $env{'user.adv'}, - "request.role.domain" => $env{'user.domain'}}); + &Apache::lonnet::appenv({"request.course.id" => '', + "request.course.fn" => '', + "request.course.uri" => '', + "request.course.sec" => '', + "request.course.tied" => '', + "request.course.timechecked" => '', + "request.role" => 'cm', + "request.role.adv" => $env{'user.adv'}, + "request.role.domain" => $env{'user.domain'}}); # Check if user is a DC trying to enter a course or author space and needs privs to be created if ($numdc > 0) { - foreach my $envkey (keys %env) { -# Is this an ad-hoc CC-role? - if (my ($domain,$coursenum) = - ($envkey =~ m-^form\.cc\./($match_domain)/($match_courseid)$-)) { + foreach my $envkey (keys(%env)) { +# Is this an ad-hoc Coordinator role? + if (my ($ccrole,$domain,$coursenum) = + ($envkey =~ m-^form\.(cc|co)\./($match_domain)/($match_courseid)$-)) { if ($dcroles{$domain}) { - &Apache::lonnet::check_adhoc_privs($domain,$coursenum, - $then,$now,'cc'); + if (&Apache::lonnet::check_adhoc_privs($domain,$coursenum, + $update,$refresh,$now,$ccrole)) { + &Apache::lonnet::appenv({"environment.internal.$domain.$coursenum.$ccrole.adhoc" => time}); + } } last; } @@ -273,8 +324,9 @@ sub handler { my ($server_status,$home) = &check_author_homeserver($user,$domain); if ($server_status eq 'switchserver') { my $trolecode = 'au./'.$domain.'/'; - my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode; + my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode; $r->internal_redirect($switchserver); + return OK; } last; } @@ -284,8 +336,9 @@ sub handler { my ($server_status,$home) = &check_author_homeserver($user,$domain); if ($server_status eq 'switchserver') { my $trolecode = 'ca./'.$domain.'/'.$user; - my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode; + my $switchserver = '/adm/switchserver?otherserver='.$home.'&role='.$trolecode; $r->internal_redirect($switchserver); + return OK; } last; } @@ -300,13 +353,14 @@ sub handler { if ($dcroles{$domain}) { my ($server_status,$home) = &check_author_homeserver($user,$domain); if (($server_status eq 'ok') || ($server_status eq 'switchserver')) { - &Apache::lonnet::check_adhoc_privs($domain,$user,$then, - $now,'ca'); + &Apache::lonnet::check_adhoc_privs($domain,$user,$update, + $refresh,$now,'ca'); if ($server_status eq 'switchserver') { my $trolecode = 'ca./'.$domain.'/'.$user; my $switchserver = '/adm/switchserver?' - .'otherserver='.$home.'&role='.$trolecode; + .'otherserver='.$home.'&role='.$trolecode; $r->internal_redirect($switchserver); + return OK; } } else { delete($env{$envkey}); @@ -319,15 +373,34 @@ sub handler { } } - foreach $envkey (keys %env) { + foreach $envkey (keys(%env)) { next if ($envkey!~/^user\.role\./); my ($where,$trolecode,$role,$tstatus,$tend,$tstart); - &Apache::lonnet::role_status($envkey,$then,$refresh,$now,\$role,\$where, + &Apache::lonnet::role_status($envkey,$update,$refresh,$now,\$role,\$where, \$trolecode,\$tstatus,\$tstart,\$tend); if ($env{'form.'.$trolecode}) { if ($tstatus eq 'is') { $where=~s/^\///; my ($cdom,$cnum,$csec)=split(/\//,$where); + if (($cnum) && ($role ne 'ca') && ($role ne 'aa')) { + my $home = $env{'course.'.$cdom.'_'.$cnum.'.home'}; + my @ids = &Apache::lonnet::current_machine_ids(); + unless ($loncaparev eq '' && $home && grep(/^\Q$home\E$/,@ids)) { + my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired'); + if ($curr_reqd_hash{'internal.releaserequired'} ne '') { + my ($switchserver,$switchwarning) = + &Apache::loncommon::check_release_required($loncaparev,$cdom.'_'.$cnum,$trolecode, + $curr_reqd_hash{'internal.releaserequired'}); + if ($switchwarning ne '' || $switchserver ne '') { + &Apache::loncommon::content_type($r,'text/html'); + &Apache::loncommon::no_cache($r); + $r->send_http_header; + $r->print(&Apache::loncommon::check_release_result($switchwarning,$switchserver)); + return OK; + } + } + } + } # check for course groups my %coursegroups = &Apache::lonnet::get_active_groups( $env{'user.domain'},$env{'user.name'},$cdom, $cnum); @@ -445,16 +518,39 @@ ENDENTERKEY if (($cnum) && ($role ne 'ca') && ($role ne 'aa')) { my $msg; - my ($furl,$ferr)= - &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + my ($furl,$ferr)= + &Apache::lonuserstate::readmap($cdom.'/'.$cnum); + unless ($ferr) { + unless (($env{'form.switchrole'}) || + ($env{"environment.internal.$cdom.$cnum.$role.adhoc"})) { + &Apache::lonnet::put('nohist_crslastlogin', + {$env{'user.name'}.':'.$env{'user.domain'}. + ':'.$csec.':'.$role => $now},$cdom,$cnum); + } + my ($feeds,$syllabus_time); + &Apache::lonrss::advertisefeeds($cnum,$cdom,undef,\$feeds); + &Apache::lonnet::appenv({'request.course.feeds' => $feeds}); + &Apache::lonnet::get_numsuppfiles($cnum,$cdom,1); + unless ($env{'course.'.$cdom.'_'.$cnum.'.updatedsyllabus'}) { + unless (($env{'course.'.$cdom.'_'.$cnum.'.externalsyllabus'}) || + ($env{'course.'.$cdom.'_'.$cnum.'.uploadedsyllabus'})) { + my %syllabus=&Apache::lonnet::dump('syllabus',$cdom,$cnum); + $syllabus_time = $syllabus{'uploaded.lastmodified'}; + if ($syllabus_time) { + &Apache::lonnet::appenv({'request.course.syllabustime' => $syllabus_time}); + } + } + } + } if (($env{'form.orgurl'}) && - ($env{'form.orgurl'}!~/^\/adm\/flip/)) { + ($env{'form.orgurl'}!~/^\/adm\/flip/) && + ($env{'form.orgurl'} ne '/adm/roles')) { my $dest=$env{'form.orgurl'}; if ($env{'form.symb'}) { if ($dest =~ /\?/) { $dest .= '&'; } else { - $dest .= '?' + $dest .= '?'; } $dest .= 'symb='.$env{'form.symb'}; } @@ -463,6 +559,13 @@ ENDENTERKEY if (($ferr) && ($tadv)) { &error_page($r,$ferr,$dest); } else { + if ($dest =~ m{^/adm/coursedocs\?folderpath}) { + if ($env{'request.course.id'} eq $cdom.'_'.$cnum) { + my $chome = &Apache::lonnet::homeserver($cnum,$cdom); + &Apache::loncommon::update_content_constraints($cdom,$cnum,$chome, + $cdom.'_'.$cnum); + } + } $r->internal_redirect($dest); } return OK; @@ -486,26 +589,61 @@ ENDENTERKEY } else { # Check to see if the user is a CC entering a course # for the first time - my (undef, undef, $role, $courseid) = split(/\./, $envkey); - if (substr($courseid, 0, 1) eq '/') { - $courseid = substr($courseid, 1); - } - $courseid =~ s/\//_/; - if ($role eq 'cc' && $env{'course.' . $courseid . - '.course.helper.not.run'}) { + if ((($role eq 'cc') || ($role eq 'co')) + && ($env{'course.'.$cdom.'_'.$cnum.'.course.helper.not.run'})) { $furl = "/adm/helper/course.initialization.helper"; # Send the user to the course they selected } elsif ($env{'request.course.id'}) { - if ($env{'form.destinationurl'}) { - my $dest = $env{'form.destinationurl'}; - if ($env{'form.destsymb'} ne '') { - my $esc_symb = &HTML::Entities::encode($env{'form.destsymb'},'"<>&'); - $dest .= '?symb='.$esc_symb; + my ($dest,$destsymb,$checkenc); + $dest = $env{'form.destinationurl'}; + $destsymb = $env{'form.destsymb'}; + if ($dest ne '') { + if ($env{'form.switchrole'}) { + if ($destsymb ne '') { + if ($destsymb !~ m{^/enc/}) { + unless ($env{'request.role.adv'}) { + $checkenc = 1; + } + } + } + if ($dest =~ m{^/enc/}) { + if ($env{'request.role.adv'}) { + $dest = &Apache::lonenc::unencrypted($dest); + if ($destsymb eq '') { + ($destsymb) = ($dest =~ /(?:\?|\&)symb=([^\&]*)/); + $destsymb = &unescape($destsymb); + } + } + } else { + if ($destsymb eq '') { + ($destsymb) = ($dest =~ /(?:\?|\&)symb=([^\&]+)/); + $destsymb = &unescape($destsymb); + } + unless ($env{'request.role.adv'}) { + $checkenc = 1; + } + } + if (($checkenc) && ($destsymb ne '')) { + my ($encstate,$unencsymb,$res); + $unencsymb = &Apache::lonnet::symbclean($destsymb); + (undef,undef,$res) = &Apache::lonnet::decode_symb($unencsymb); + &Apache::lonnet::symbverify($unencsymb,$res,\$encstate); + if ($encstate) { + if (($dest ne '') && ($dest !~ m{^/enc/})) { + $dest=&Apache::lonenc::encrypted($dest); + } + } + } } - &redirect_user($r,&mt('Entering [_1]', - $env{'course.'.$courseid.'.description'}), - $dest,$msg, - $env{'environment.remotenavmap'}); + unless (($dest =~ m{^/enc/}) || ($dest =~ /(\?|\&)symb=.+___\d+___.+/)) { + if (($destsymb ne '') && ($destsymb !~ m{^/enc/})) { + my $esc_symb = &escape($destsymb); + $dest .= '?symb='.$esc_symb; + } + } + &redirect_user($r, &mt('Entering [_1]', + $env{'course.'.$cdom.'_'.$cnum.'.description'}), + $dest, $msg); return OK; } if (&Apache::lonnet::allowed('whn', @@ -514,28 +652,40 @@ ENDENTERKEY $env{'request.course.id'}.'/' .$env{'request.course.sec'}) ) { - my $startpage = &courseloadpage($courseid); + my $startpage = &courseloadpage($env{'request.course.id'}); unless ($startpage eq 'firstres') { $msg = &mt('Entering [_1] ...', - $env{'course.'.$courseid.'.description'}); - &redirect_user($r,&mt('New in course'), - '/adm/whatsnew?refpage=start',$msg, - $env{'environment.remotenavmap'}); + $env{'course.'.$env{'request.course.id'}.'.description'}); + &redirect_user($r, &mt('New in course'), + '/adm/whatsnew?refpage=start', $msg); return OK; } } } -# Are we allowed to look at the first resource? - if ($furl !~ m|^/adm/|) { -# Guess not ... - $furl=&Apache::lonpageflip::first_accessible_resource(); - } + # Are we allowed to look at the first resource? + my $access; + if ($furl =~ m{^(/adm/wrapper|)/ext/}) { + # If it's an external resource, + # strip off the symb argument and possible query + my ($exturl,$symb) = ($furl =~ m{^(.+)(?:\?|\&)symb=(.+)$}); + # Unencode $symb + $symb = &unescape($symb); + # Then check for permission + $access = &Apache::lonnet::allowed('bre',$exturl,$symb); + # For other resources just check for permission + } else { + $access = &Apache::lonnet::allowed('bre',$furl); + } + if (!$access) { + $furl = &Apache::lonpageflip::first_accessible_resource(); + } elsif ($access eq 'B') { + $furl = '/adm/navmaps?showOnlyHomework=1'; + } $msg = &mt('Entering [_1] ...', - $env{'course.'.$courseid.'.description'}); - &redirect_user($r,&mt('Entering [_1]', - $env{'course.'.$courseid.'.description'}), - $furl,$msg, - $env{'environment.remotenavmap'}); + $env{'course.'.$cdom.'_'.$cnum.'.description'}); + &redirect_user($r, &mt('Entering [_1]', + $env{'course.'.$cdom.'_'.$cnum.'.description'}), + $furl, $msg); } return OK; } @@ -545,13 +695,12 @@ ENDENTERKEY if ($role =~ /^(au|ca|aa)$/) { my $redirect_url = '/priv/'; if ($role eq 'au') { - $redirect_url.=$env{'user.name'}; + $redirect_url.=$env{'user.domain'}.'/'.$env{'user.name'}; } else { - $where =~ /\/(.*)$/; - $redirect_url .= $1; + $redirect_url .= $where; } $redirect_url .= '/'; - &redirect_user($r,&mt('Entering Construction Space'), + &redirect_user($r,&mt('Entering Authoring Space'), $redirect_url); return OK; } @@ -583,22 +732,33 @@ ENDENTERKEY my $crumbtext = 'User Roles'; my $pagetitle = 'My Roles'; my $recent = &mt('Recent Roles'); + my $standby = &mt('Role selected. Please stand by.'); my $show_course=&Apache::loncommon::show_course(); if ($show_course) { $crumbtext = 'Courses'; $pagetitle = 'My Courses'; $recent = &mt('Recent Courses'); + $standby = &mt('Course selected. Please stand by.'); } my $brcrum =[{href=>"/adm/roles",text=>$crumbtext}]; + + my %roles_in_env; + my $showcount = &roles_from_env(\%roles_in_env,$update); + my $swinfo=&Apache::lonmenu::rawconfig(); my $start_page=&Apache::loncommon::start_page($pagetitle,undef,{bread_crumbs=>$brcrum}); - my $standby=&mt('Role selected. Please stand by.'); - $standby=~s/\n/\\n/g; - my $noscript=''.&mt('Use of LON-CAPA requires Javascript to be enabled in your web browser.').'
'.&mt('As this is not the case, most functionality in the system will be unavailable.').'

'; + my %domdefs=&Apache::lonnet::get_domain_defaults($env{'user.domain'}); + my $cattype = 'std'; + if ($domdefs{'catauth'}) { + $cattype = $domdefs{'catauth'}; + } + my $funcs = &get_roles_functions($showcount,$cattype); + &js_escape(\$standby); + my $noscript='
'.&mt('Use of LON-CAPA requires Javascript to be enabled in your web browser.').'
'.&mt('As this is not the case, most functionality in the system will be unavailable.').'

'; $r->print(< +$funcs @@ -618,8 +778,22 @@ function enterrole (thisform,rolecode,bu thisform.submit(); } else { alert('$standby'); - } + } +} + +function rolesView (caller) { + if ((caller == 'showall') || (caller == 'noshowall')) { + document.rolechoice.display.value = caller; + } else { + if ((caller == 'doupdate') || (caller == 'requestauthor') || + (caller == 'queued')) { + document.rolechoice.state.value = caller; + } + } + document.rolechoice.selectrole.value=''; + document.rolechoice.submit(); } + // ]]> ENDHEADER @@ -671,59 +845,81 @@ ENDHEADER if ($reinit) { $r->print( '

'. - &mt('As your session file for the course has expired, you will need to re-select the course.').'

'); + &mt('As your session file for the course or community has expired, you will need to re-select it.').''); } else { $r->print( '

'. - &mt('You need to choose another user role or enter a specific course for this function').'

'); + &mt('You need to choose another user role or enter a specific course or community for this function.'). + ''); } } } -# -------------------------------------------------------- Choice or no choice? if ($nochoose) { $r->print("

".&mt('Sorry ...')."

\n". &mt('This action is currently not authorized.').''. &Apache::loncommon::end_page()); return OK; } else { + if ($updateresult || $reqauthor || $hotlist) { + my $showresult = '
'; + if ($updateresult) { + $showresult .= &Apache::lonhtmlcommon::confirm_success($updateresult); + } + if ($reqauthor) { + $showresult .= &Apache::lonhtmlcommon::confirm_success($reqauthor); + } + if ($hotlist) { + $showresult .= $hotlist; + } + $showresult .= '
'; + $r->print($showresult); + } elsif ($env{'form.state'} eq 'queued') { + $r->print(&get_queued()); + } if (($ENV{'REDIRECT_QUERY_STRING'}) && ($fn)) { $fn.='?'.$ENV{'REDIRECT_QUERY_STRING'}; } + my $display = ($env{'form.display'} =~ /^(showall)$/); $r->print('
'); $r->print(''); $r->print(''); $r->print(''); + $r->print(''); + $r->print(''); } + $r->rflush(); my (%roletext,%sortrole,%roleclass,%futureroles,%timezones); my ($countactive,$countfuture,$inrole,$possiblerole) = - &gather_roles($then,$refresh,$now,$reinit,$nochoose,\%roletext,\%sortrole,\%roleclass, - \%futureroles,\%timezones); - + &gather_roles($update,$refresh,$now,$reinit,$nochoose,\%roles_in_env,\%roletext, + \%sortrole,\%roleclass,\%futureroles,\%timezones,$loncaparev); $refresh = $now; &Apache::lonnet::appenv({'user.refresh.time' => $refresh}); - if ($env{'user.adv'}) { - $r->print( - '

'); - } else { + if ((($cattype eq 'std') || ($cattype eq 'domonly')) && (!$env{'user.adv'})) { if ($countactive > 0) { - &queued_selfenrollment($r); my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); - $r->print('

'.&mt('[_1]Visit the [_2]Course Catalog[_3] to view all [_4] LON-CAPA courses.','','','',$domdesc).'
'.&mt('If a course is [_1]not[_2] in your list of current courses below, you may be able to enroll if self-enrollment is permitted.','','').'

'); + $r->print( + '

' + .&mt('[_1]Visit the [_2]Course/Community Catalog[_3][_4]' + .' to view all [_5] LON-CAPA courses and communities.' + ,'' + ,'' + ,'' + ,'' + ,'"'.$domdesc.'"') + .'
' + .&mt('If a course or community is [_1]not[_2] in your list of current courses and communities below,' + .' you may be able to enroll if self-enrollment is permitted.' + ,'','') + .'

' + ); } } # No active roles if ($countactive==0) { - if ($inrole) { - $r->print('

'.&mt('Currently no additional roles or courses').'

'); - } else { - $r->print('

'.&mt('Currently no active roles or courses').'

'); - } - &findcourse_advice($r); + &requestcourse_advice($r,$cattype,$inrole); $r->print('
'); if ($countfuture) { $r->print(&mt('The following [quant,_1,role,roles] will become active in the future:',$countfuture)); @@ -754,31 +950,59 @@ ENDHEADER return OK; } # ----------------------------------------------------------------------- Table + + if ($numdc > 0) { + $r->print(&coursepick_jscript()); + $r->print(&Apache::loncommon::coursebrowser_javascript(). + &Apache::loncommon::authorbrowser_javascript()); + } + unless ((!&Apache::loncommon::show_course()) || ($nochoose) || ($countactive==1)) { $r->print("

".&mt('Select a Course to Enter')."

\n"); } + if ($env{'form.destinationurl'}) { + $r->print(''); + if ($env{'form.destsymb'} ne '') { + $r->print(''); + } + } + my $doheaders = &roletable_headers($r,\%roleclass,\%sortrole,$nochoose); if ($env{'environment.recentroles'}) { my %recent_roles = &Apache::lonhtmlcommon::get_recent('roles',$env{'environment.recentrolesn'}); my $output=''; - foreach (sort(keys(%recent_roles))) { - if (ref($roletext{'user.role.'.$_}) eq 'ARRAY') { + foreach my $role (sort(keys(%recent_roles))) { + if (ref($roletext{'user.role.'.$role}) eq 'ARRAY') { $output.= &Apache::loncommon::start_data_table_row(). - $roletext{'user.role.'.$_}->[0]. - &Apache::loncommon::end_data_table_row(). - &Apache::loncommon::continue_data_table_row(). - $roletext{'user.role.'.$_}->[1]. + $roletext{'user.role.'.$role}->[0]. &Apache::loncommon::end_data_table_row(); - if ($_ =~ m-dc\./($match_domain)/- + if ($roletext{'user.role.'.$role}->[1] ne '') { + $output .= &Apache::loncommon::continue_data_table_row(). + $roletext{'user.role.'.$role}->[1]. + &Apache::loncommon::end_data_table_row(); + } + if ($role =~ m{dc\./($match_domain)/} && $dcroles{$1}) { $output .= &adhoc_roles_row($1,'recent'); } } elsif ($numdc > 0) { - unless ($_ =~/^error\:/) { - $output.=&display_cc_role('user.role.'.$_); + unless ($role =~/^error\:/) { + my ($roletext,$role_text_end) = &display_cc_role('user.role.'.$role); + if ($roletext) { + $output.= &Apache::loncommon::start_data_table_row(). + $roletext. + &Apache::loncommon::end_data_table_row(); + if ($role_text_end) { + $output .= &Apache::loncommon::continue_data_table_row(). + $role_text_end. + &Apache::loncommon::end_data_table_row(); + } + } } - } + } } if ($output) { $r->print(&Apache::loncommon::start_data_table_empty_row() @@ -791,12 +1015,6 @@ ENDHEADER $doheaders ++; } } - - if ($numdc > 0) { - $r->print(&coursepick_jscript()); - $r->print(&Apache::loncommon::coursebrowser_javascript(). - &Apache::loncommon::authorbrowser_javascript()); - } &print_rolerows($r,$doheaders,\%roleclass,\%sortrole,\%dcroles,\%roletext); if ($countactive > 1) { my $tremark=''; @@ -832,45 +1050,60 @@ ENDHEADER $r->print('

'.&mt('Current Privileges').'

'); $r->print(&privileges_info()); } - $r->print(&Apache::lonnet::getannounce()); + my $announcements = &Apache::lonnet::getannounce(); + $r->print( + '
'. + '

'.&mt('Announcements').'

'. + $announcements + ) unless (!$announcements); if ($advanced) { my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); - $r->print('

' - .&mt('This is LON-CAPA [_1]',$r->dir_config('lonVersion')) - .'
' - .''.&mt('Logout').'  ' - .'' - .&mt('Course Catalog') - .'

'); + $r->print('

' + .&mt('This LON-CAPA server is version [_1]',$r->dir_config('lonVersion')) + .'

'); } $r->print(&Apache::loncommon::end_page()); return OK; } +sub roles_from_env { + my ($roleshash,$update) = @_; + my $count = 0; + if (ref($roleshash) eq 'HASH') { + foreach my $envkey (keys(%env)) { + if ($envkey =~ m{^user\.role\.(\w+)[./]}) { + next if ($1 eq 'gr'); + $roleshash->{$envkey} = $env{$envkey}; + my ($start,$end) = split(/\./,$env{$envkey}); + unless ($end && $end<$update) { + $count ++; + } + } + } + } + return $count; +} + sub gather_roles { - my ($then,$refresh,$now,$reinit,$nochoose,$roletext,$sortrole,$roleclass,$futureroles,$timezones) = @_; + my ($update,$refresh,$now,$reinit,$nochoose,$roles_in_env,$roletext,$sortrole,$roleclass,$futureroles, + $timezones,$loncaparev) = @_; my ($countactive,$countfuture,$inrole,$possiblerole) = (0,0,0,''); my $advanced = $env{'user.adv'}; my $tryagain = $env{'form.tryagain'}; - foreach my $envkey (sort(keys(%env))) { - my $button = 1; - my $switchserver=''; - my ($role_text,$role_text_end,$sortkey); - if ($envkey=~/^user\.role\./) { - my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend); - &Apache::lonnet::role_status($envkey,$then,$refresh,$now,\$role,\$where, + my @ids = &Apache::lonnet::current_machine_ids(); + if (ref($roles_in_env) eq 'HASH') { + foreach my $envkey (sort(keys(%{$roles_in_env}))) { + my $button = 1; + my $switchserver=''; + my $switchwarning; + my ($role_text,$role_text_end,$sortkey,$role,$where,$trolecode,$tstart, + $tend,$tremark,$tstatus,$tpstart,$tpend); + &Apache::lonnet::role_status($envkey,$update,$refresh,$now,\$role,\$where, \$trolecode,\$tstatus,\$tstart,\$tend); next if (!defined($role) || $role eq '' || $role =~ /^gr/); - my $timezone = &role_timezone($where,$timezones); $tremark=''; $tpstart=' '; $tpend=' '; - if ($tstart) { - $tpstart=&Apache::lonlocal::locallocaltime($tstart,$timezone); - } - if ($tend) { - $tpend=&Apache::lonlocal::locallocaltime($tend,$timezone); - } if ($env{'request.role'} eq $trolecode) { $tstatus='selected'; } @@ -878,7 +1111,14 @@ sub gather_roles { if (($tstatus eq 'is') || ($tstatus eq 'selected') || ($tstatus eq 'future') - || ($env{'form.showall'})) { + || ($env{'form.display'} eq 'showall')) { + my $timezone = &role_timezone($where,$timezones); + if ($tstart) { + $tpstart=&Apache::lonlocal::locallocaltime($tstart,$timezone); + } + if ($tend) { + $tpend=&Apache::lonlocal::locallocaltime($tend,$timezone); + } if ($tstatus eq 'is') { $tbg='LC_roles_is'; $possiblerole=$trolecode; @@ -904,7 +1144,7 @@ sub gather_roles { if ($role =~ /^cr\//) { my ($rdummy,$rdomain,$rauthor,$rrole)=split(/\//,$role); if ($tremark) { $tremark.='
'; } - $tremark.=&mt('Defined by [_1] at [_2].',$rauthor,$rdomain); + $tremark.=&mt('Custom role defined by [_1].',$rauthor.':'.$rdomain); } $trole=Apache::lonnet::plaintext($role); my $ttype; @@ -915,15 +1155,14 @@ sub gather_roles { if (($role eq 'ca') || ($role eq 'aa')) { my $home = &Apache::lonnet::homeserver($trest,$tdom); my $allowed=0; - my @ids=&Apache::lonnet::current_machine_ids(); foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } if (!$allowed) { $button=0; - $switchserver='otherserver='.$home.'&role='.$trolecode; + $switchserver='otherserver='.$home.'&role='.$trolecode; } #next if ($home eq 'no_host'); $home = &Apache::lonnet::hostname($home); - $ttype='Construction Space'; + $ttype='Authoring Space'; $twhere=&mt('User').': '.$trest.'
'.&mt('Domain'). ': '.$tdom.'
'. ' '.&mt('Server').': '.$home; @@ -935,15 +1174,14 @@ sub gather_roles { my $home = &Apache::lonnet::homeserver ($env{'user.name'},$env{'user.domain'}); my $allowed=0; - my @ids=&Apache::lonnet::current_machine_ids(); foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } } if (!$allowed) { $button=0; - $switchserver='otherserver='.$home.'&role='.$trolecode; + $switchserver='otherserver='.$home.'&role='.$trolecode; } #next if ($home eq 'no_host'); $home = &Apache::lonnet::hostname($home); - $ttype='Construction Space'; + $ttype='Authoring Space'; $twhere=&mt('Domain').': '.$tdom.'
'.&mt('Server'). ': '.$home; $env{'course.'.$tdom.'_'.$trest.'.description'}='ca'; @@ -952,26 +1190,49 @@ sub gather_roles { } elsif ($trest) { my $tcourseid=$tdom.'_'.$trest; $ttype = &Apache::loncommon::course_type($tcourseid); - $trole = &Apache::lonnet::plaintext($role,$ttype); + $trole = &Apache::lonnet::plaintext($role,$ttype,$tcourseid); if ($env{'course.'.$tcourseid.'.description'}) { + my $home=$env{'course.'.$tcourseid.'.home'}; $twhere=$env{'course.'.$tcourseid.'.description'}; $sortkey=$role."\0".$tdom."\0".$twhere."\0".$envkey; + $twhere = &HTML::Entities::encode($twhere,'"<>&'); unless ($twhere eq &mt('Currently not available')) { $twhere.=' '. &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom). ''; + unless ($home && grep(/^\Q$home\E$/,@ids) && $loncaparev eq '') { + my $required = $env{'course.'.$tcourseid.'.internal.releaserequired'}; + if ($required ne '') { + ($switchserver,$switchwarning) = + &Apache::loncommon::check_release_required($loncaparev,$tcourseid,$trolecode,$required); + if ($switchserver || $switchwarning) { + $button = 0; + } + } + } } } else { my %newhash=&Apache::lonnet::coursedescription($tcourseid); if (%newhash) { $sortkey=$role."\0".$tdom."\0".$newhash{'description'}. "\0".$envkey; - $twhere=$newhash{'description'}. - ' '. - &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom). - ''; + $twhere=&HTML::Entities::encode($newhash{'description'},'"<>&'). + ' '. + &Apache::loncommon::syllabuswrapper(&mt('Syllabus'),$trest,$tdom). + ''; $ttype = $newhash{'type'}; - $trole = &Apache::lonnet::plaintext($role,$ttype); + $trole = &Apache::lonnet::plaintext($role,$ttype,$tcourseid); + my $home = $newhash{'home'}; + unless ($home && grep(/^\Q$home\E$/,@ids) && $loncaparev eq '') { + my $required = $newhash{'internal.releaserequired'}; + if ($required ne '') { + ($switchserver,$switchwarning) = + &Apache::loncommon::check_release_required($loncaparev,$tcourseid,$trolecode,$required); + if ($switchserver || $switchwarning) { + $button = 0; + } + } + } } else { $twhere=&mt('Currently not available'); $env{'course.'.$tcourseid.'.description'}=$twhere; @@ -995,7 +1256,7 @@ sub gather_roles { ($role_text,$role_text_end) = &build_roletext($trolecode,$tdom,$trest,$tstatus,$tryagain, $advanced,$tremark,$tbg,$trole,$twhere,$tpstart, - $tpend,$nochoose,$button,$switchserver,$reinit); + $tpend,$nochoose,$button,$switchserver,$reinit,$switchwarning); $roletext->{$envkey}=[$role_text,$role_text_end]; if (!$sortkey) {$sortkey=$twhere."\0".$envkey;} $sortrole->{$sortkey}=$envkey; @@ -1015,9 +1276,15 @@ sub role_timezone { my $cnum = $2; if ($cdom && $cnum) { if (!exists($timezones->{$cdom.'_'.$cnum})) { - my %timehash = - &Apache::lonnet::get('environment',['timezone'],$cdom,$cnum); - if ($timehash{'timezone'} eq '') { + my $tz; + if ($env{'course.'.$cdom.'_'.$cnum.'.description'}) { + $tz = $env{'course.'.$cdom.'_'.$cnum.'.timezone'}; + } else { + my %timehash = + &Apache::lonnet::get('environment',['timezone'],$cdom,$cnum); + $tz = $timehash{'timezone'}; + } + if ($tz eq '') { if (!exists($timezones->{$cdom})) { my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom); @@ -1030,7 +1297,7 @@ sub role_timezone { $timezones->{$cdom.'_'.$cnum} = $timezones->{$cdom}; } else { $timezones->{$cdom.'_'.$cnum} = - &Apache::lonlocal::gettimezone($timehash{'timezone'}); + &Apache::lonlocal::gettimezone($tz); } } $timezone = $timezones->{$cdom.'_'.$cnum}; @@ -1087,7 +1354,7 @@ sub roletable_headers { } sub roletypes { - my @types = ('Domain','Construction Space','Course','Unavailable','System'); + my @types = ('Domain','Authoring Space','Course','Community','Unavailable','System'); return @types; } @@ -1103,10 +1370,12 @@ sub print_rolerows { if (ref($roletext->{$sortrole->{$which}}) eq 'ARRAY') { $output.= &Apache::loncommon::start_data_table_row(). $roletext->{$sortrole->{$which}}->[0]. - &Apache::loncommon::end_data_table_row(). - &Apache::loncommon::continue_data_table_row(). - $roletext->{$sortrole->{$which}}->[1]. &Apache::loncommon::end_data_table_row(); + if ($roletext->{$sortrole->{$which}}->[1] ne '') { + $output .= &Apache::loncommon::continue_data_table_row(). + $roletext->{$sortrole->{$which}}->[1]. + &Apache::loncommon::end_data_table_row(); + } } if ($sortrole->{$which} =~ m-dc\./($match_domain)/-) { if (ref($dcroles) eq 'HASH') { @@ -1134,7 +1403,7 @@ sub print_rolerows { } sub findcourse_advice { - my ($r) = @_; + my ($r,$cattype) = @_; my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); if (&Apache::lonnet::auto_run(undef,$env{'user.domain'})) { @@ -1149,51 +1418,78 @@ sub findcourse_advice { } else { $r->print(&mt('If you were expecting to see an active role listed for a particular course, that course may not have been created yet.').'
'); } - $r->print('

'.&mt('The [_1]Course Catalog[_2] provides information about all [_3] classes for which LON-CAPA courses have been created.','','',$domdesc).'
'); - $r->print(&mt('You can search the course catalog for courses which permit self-enrollment, if you would like to enroll in a course.').'

'); - &queued_selfenrollment($r); + if (($cattype eq 'std') || ($cattype eq 'domonly')) { + $r->print('

'.&mt('Self-Enrollment').'

'. + '

'.&mt('The [_1]Course/Community Catalog[_2] provides information about all [_3] classes for which LON-CAPA courses have been created, as well as any communities in the domain.','','',$domdesc).'
'); + $r->print(&mt('You can search for courses and communities which permit self-enrollment, if you would like to enroll in one.').'

'. + &Apache::loncoursequeueadmin::queued_selfenrollment()); + } return; } -sub queued_selfenrollment { - my ($r) = @_; - my %selfenrollrequests = &Apache::lonnet::dump('selfenrollrequests'); - my %reqs_by_date; - foreach my $item (keys(%selfenrollrequests)) { - if (ref($selfenrollrequests{$item}) eq 'HASH') { - if ($selfenrollrequests{$item}{'status'} eq 'request') { - if ($selfenrollrequests{$item}{'timestamp'}) { - push(@{$reqs_by_date{$selfenrollrequests{$item}{'timestamp'}}},$item); - } - } - } - } - if (keys(%reqs_by_date)) { - my $rolename = &Apache::lonnet::plaintext('st'); - $r->print(''.&mt('Enrollment requests pending Course Coordinator approval').'
'. - &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(). - ''.&mt('Date requested').''.&mt('Course title').''. - ''.&mt('User role').''.&mt('Section').''. - &Apache::loncommon::end_data_table_header_row()); - my @sorted = sort { $a <=> $b } (keys(%reqs_by_date)); - foreach my $item (@sorted) { - if (ref($reqs_by_date{$item}) eq 'ARRAY') { - foreach my $crs (@{$reqs_by_date{$item}}) { - my %courseinfo = &Apache::lonnet::coursedescription($crs); - my $usec = $selfenrollrequests{$crs}{'section'}; - if ($usec eq '') { - $usec = &mt('No section'); - } - $r->print(&Apache::loncommon::start_data_table_row(). - ''.&Apache::lonlocal::locallocaltime($item).''. - ''.$courseinfo{'description'}.''. - ''.$rolename.''.$usec.''. - &Apache::loncommon::end_data_table_row()); +sub requestcourse_advice { + my ($r,$cattype,$inrole) = @_; + my $domdesc = &Apache::lonnet::domain($env{'user.domain'},'description'); + my $esc_dom = &HTML::Entities::encode($env{'user.domain'},'"<>&'); + my (%can_request,%request_doms,$output); + &Apache::lonnet::check_can_request($env{'user.domain'},\%can_request,\%request_doms); + if (keys(%request_doms) > 0) { + my ($types,$typename) = &Apache::loncommon::course_types(); + if ((ref($types) eq 'ARRAY') && (ref($typename) eq 'HASH')) { + my (@reqdoms,@reqtypes); + foreach my $type (sort(keys(%request_doms))) { + push(@reqtypes,$type); + if (ref($request_doms{$type}) eq 'ARRAY') { + my $domstr = join(', ',map { &Apache::lonnet::domain($_) } sort(@{$request_doms{$type}})); + $output .= + '
  • ' + .&mt('[_1]'.$typename->{$type}.'[_2] in domain: [_3]', + '', + '', + ''.$domstr.'') + .'
  • '; + foreach my $dom (@{$request_doms{$type}}) { + unless (grep(/^\Q$dom\E/,@reqdoms)) { + push(@reqdoms,$dom); + } + } } } + my @showtypes; + foreach my $type (@{$types}) { + if (grep(/^\Q$type\E$/,@reqtypes)) { + push(@showtypes,$type); + } + } + my $requrl = '/adm/requestcourse'; + if (@reqdoms == 1) { + $requrl .= '?showdom='.$reqdoms[0]; + } + if (@showtypes > 0) { + $requrl.=(($requrl=~/\?/)?'&':'?').'crstype='.$showtypes[0]; + } + if (@reqdoms == 1 || @showtypes > 0) { + $requrl .= '&state=crstype&action=new'; + } + if ($output) { + $r->print('

    '.&mt('Request creation of a course or community').'

    '. + '

    '. + &mt('You have rights to request the creation of courses and/or communities in the following domain(s):'). + '

      '. + $output. + '
    '. + &mt('Use the [_1]request form[_2] to submit a request for creation of a new course or community.', + '',''). + '

    '); + } + } + } elsif (!$env{'user.adv'}) { + if ($inrole) { + $r->print('

    '.&mt('Currently no additional roles, courses or communities').'

    '); + } else { + $r->print('

    '.&mt('Currently no active roles, courses or communities').'

    '); } - $r->print(&Apache::loncommon::end_data_table()); + &findcourse_advice($r,$cattype); } return; } @@ -1213,7 +1509,7 @@ sub privileges_info { my (undef,$tdom,$trest,$tsec)=split(m{/},$where); if ($trest) { if ($env{'course.'.$tdom.'_'.$trest.'.description'} eq 'ca') { - $ttype='Construction Space'; + $ttype='Authoring Space'; $twhere='User: '.$trest.', Domain: '.$tdom; } else { $ttype= &Apache::loncommon::course_type($tdom.'_'.$trest); @@ -1254,7 +1550,7 @@ sub privileges_info { } sub build_roletext { - my ($trolecode,$tdom,$trest,$tstatus,$tryagain,$advanced,$tremark,$tbg,$trole,$twhere,$tpstart,$tpend,$nochoose,$button,$switchserver,$reinit) = @_; + my ($trolecode,$tdom,$trest,$tstatus,$tryagain,$advanced,$tremark,$tbg,$trole,$twhere,$tpstart,$tpend,$nochoose,$button,$switchserver,$reinit,$switchwarning) = @_; my ($roletext,$roletext_end); my $is_dc=($trolecode =~ m/^dc\./); my $rowspan=($is_dc) ? '' @@ -1272,6 +1568,13 @@ sub build_roletext { } else { $roletext.=(' '); } + if ($switchwarning) { + if ($tremark eq '') { + $tremark = $switchwarning; + } else { + $tremark .= '
    '.$switchwarning; + } + } } elsif ($tstatus eq 'is') { $roletext.=''. ''. ''. ''. @@ -1460,10 +1766,11 @@ sub courselink { } sub coursepick_jscript { - my %lt = &Apache::lonlocal::texthash( - plsu => "Please use the 'Select Course' link to open a separate pick course window where you may select the course you wish to enter.", - youc => 'You can only use this screen to select courses in the current domain.', + my %js_lt = &Apache::lonlocal::texthash( + plsu => "Please use the 'Select Course/Community' link to open a separate pick course window where you may select the course or community you wish to enter.", + youc => 'You can only use this screen to select courses and communities in the current domain.', ); + &js_escape(\%js_lt); my $verify_script = <<"END";