--- loncom/interface/loncommon.pm 2021/12/17 19:59:39 1.1075.2.159
+++ loncom/interface/loncommon.pm 2024/10/07 21:20:09 1.1075.2.172
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1075.2.159 2021/12/17 19:59:39 raeburn Exp $
+# $Id: loncommon.pm,v 1.1075.2.172 2024/10/07 21:20:09 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -61,7 +61,6 @@ use POSIX qw(strftime mktime);
use Apache::lonmenu();
use Apache::lonenc();
use Apache::lonlocal;
-use Apache::lonnet();
use HTML::Entities;
use Apache::lonhtmlcommon();
use Apache::loncoursedata();
@@ -3670,6 +3669,30 @@ sub syllabuswrapper {
# -----------------------------------------------------------------------------
+sub aboutme_on {
+ my ($uname,$udom)=@_;
+ unless ($uname) { $uname=$env{'user.name'}; }
+ unless ($udom) { $udom=$env{'user.domain'}; }
+ return if ($udom eq 'public' && $uname eq 'public');
+ my $hashkey=$uname.':'.$udom;
+ my ($aboutme,$cached)=&Apache::lonnet::is_cached_new('aboutme',$hashkey);
+ if ($cached) {
+ return $aboutme;
+ }
+ $aboutme = &Apache::lonnet::usertools_access($uname,$udom,'aboutme');
+ &Apache::lonnet::do_cache_new('aboutme',$hashkey,$aboutme,3600);
+ return $aboutme;
+}
+
+sub devalidate_aboutme_cache {
+ my ($uname,$udom)=@_;
+ if (!$udom) { $udom =$env{'user.domain'}; }
+ if (!$uname) { $uname=$env{'user.name'}; }
+ return if ($udom eq 'public' && $uname eq 'public');
+ my $id=$uname.':'.$udom;
+ &Apache::lonnet::devalidate_cache_new('aboutme',$id);
+}
+
sub track_student_link {
my ($linktext,$sname,$sdom,$target,$start,$only_body) = @_;
my $link ="/adm/trackstudent?";
@@ -4753,6 +4776,17 @@ sub blockcheck {
}
}
}
+ } elsif (($activity eq 'com') || ($activity eq 'port') || ($activity eq 'blogs') ||
+ ($activity eq 'about') || ($activity eq 'wishlist') || ($activity eq 'passwd')) {
+ my $checkrole;
+ if ($env{'request.role.domain'} eq '') {
+ $checkrole = "cm./$env{'user.domain'}/";
+ } else {
+ $checkrole = "cm./$env{'request.role.domain'}/";
+ }
+ if (($checkrole) && (&Apache::lonnet::allowed('evb',undef,undef,$checkrole))) {
+ $has_evb = 1;
+ }
}
unless ($has_evb || $check_ipaccess) {
my @machinedoms = &Apache::lonnet::current_machine_domains();
@@ -4798,6 +4832,9 @@ sub blockcheck {
}
}
}
+ if (($activity eq 'wishlist') || ($activity eq 'annotate')) {
+ return ();
+ }
}
if (defined($udom) && defined($uname)) {
# If uname and udom are for a course, check for blocks in the course.
@@ -4814,7 +4851,10 @@ sub blockcheck {
my $startblock = 0;
my $endblock = 0;
my $triggerblock = '';
- my %live_courses = &findallcourses(undef,$uname,$udom);
+ my %live_courses;
+ unless (($activity eq 'wishlist') || ($activity eq 'annotate')) {
+ %live_courses = &findallcourses(undef,$uname,$udom);
+ }
# If uname is for a user, and activity is course-specific, i.e.,
# boards, chat or groups, check for blocking in current course only.
@@ -5157,6 +5197,10 @@ END_MYBLOCK
$text = &mt('Search Blocked');
} elsif ($activity eq 'about') {
$text = &mt('Access to User Information Pages Blocked');
+ } elsif ($activity eq 'wishlist') {
+ $text = &mt('Access to Stored Links Blocked');
+ } elsif ($activity eq 'annotate') {
+ $text = &mt('Access to Annotations Blocked');
}
$output .= <<"END_BLOCK";
@@ -5424,8 +5468,12 @@ sub domainlogo {
&Apache::lonnet::repcopy($local_name);
}
$imgsrc = &lonhttpdurl($imgsrc);
- }
- return '
';
+ }
+ my $alttext = $domain;
+ if ($designhash{$domain.'.login.alttext_domlogo'} ne '') {
+ $alttext = $designhash{$domain.'.login.alttext_domlogo'};
+ }
+ return '
';
} elsif (defined(&Apache::lonnet::domain($domain,'description'))) {
return &Apache::lonnet::domain($domain,'description');
} else {
@@ -5772,54 +5820,76 @@ sub bodytag {
unless (ref($args->{'bread_crumbs'}) eq 'ARRAY') {
$funclist = $forbodytag;
}
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
} else {
# if ($env{'request.state'} eq 'construct') {
# $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
# }
- $bodytag .= Apache::lonhtmlcommon::scripttag(
- Apache::lonmenu::utilityfunctions($httphost), 'start');
+ my $need_endlcint;
+ unless ($args->{'switchserver'}) {
+ $bodytag .= Apache::lonhtmlcommon::scripttag(
+ Apache::lonmenu::utilityfunctions($httphost), 'start');
+ $need_endlcint = 1;
+ }
- my ($left,$right) = Apache::lonmenu::primary_menu($args->{'links_disabled'});
+ if (($env{'environment.remote'} eq 'on') && ($env{'request.state'} eq 'construct')) {
+ unless ($env{'form.inhibitmenu'}) {
+ $bodytag .= &inline_for_remote($public,$role,$realm,$dc_info,$no_inline_link);
+ }
+ } else {
+ my ($left,$right) = Apache::lonmenu::primary_menu($args->{'links_disabled'});
- if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
- if ($dc_info) {
- $dc_info = qq|
$dc_info|;
+ if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
+ if ($dc_info) {
+ $dc_info = qq|
$dc_info|;
+ }
+ $bodytag .= qq|
$left $role
+ $realm $dc_info
|;
+ if ($need_endlcint) {
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ }
+ return $bodytag;
}
- $bodytag .= qq|
$left $role
- $realm $dc_info
|;
- return $bodytag;
- }
- unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
- $bodytag .= qq|
$left $role
|;
- }
+ unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
+ $bodytag .= qq|
$left $role
|;
+ }
- $bodytag .= $right;
+ $bodytag .= $right;
- if ($dc_info) {
- $dc_info = &dc_courseid_toggle($dc_info);
+ if ($dc_info) {
+ $dc_info = &dc_courseid_toggle($dc_info);
+ }
+ $bodytag .= qq|
$realm $dc_info
|;
}
- $bodytag .= qq|
$realm $dc_info
|;
#if directed to not display the secondary menu, don't.
if ($args->{'no_secondary_menu'}) {
+ if ($need_endlcint) {
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ }
return $bodytag;
}
#don't show menus for public users
if (!$public){
- $bodytag .= Apache::lonmenu::secondary_menu($httphost,$args->{'links_disabled'});
+ unless (($env{'environment.remote'} eq 'on') &&
+ ($env{'request.state'} eq 'construct')) {
+ $bodytag .= Apache::lonmenu::secondary_menu($httphost,$args->{'links_disabled'});
+ }
$bodytag .= Apache::lonmenu::serverform();
- $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ if ($need_endlcint) {
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ }
if ($env{'request.state'} eq 'construct') {
$bodytag .= &Apache::lonmenu::innerregister($forcereg,
$args->{'bread_crumbs'},'','',$hostname);
} elsif ($forcereg) {
$bodytag .= &Apache::lonmenu::innerregister($forcereg,undef,
$args->{'group'},
- $args->{'hide_buttons',
- $hostname});
+ $args->{'hide_buttons'},
+ $hostname);
} else {
my $forbodytag;
&Apache::lonmenu::prepare_functions($env{'request.noversionuri'},
@@ -5831,11 +5901,13 @@ sub bodytag {
$bodytag .= $forbodytag;
}
}
- }else{
- # this is to seperate menu from content when there's no secondary
+ } else {
+ # this is to separate menu from content when there's no secondary
# menu. Especially needed for public accessible ressources.
$bodytag .= '
';
- $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ if ($need_endlcint) {
+ $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
+ }
}
return $bodytag;
@@ -5845,12 +5917,6 @@ sub bodytag {
# Top frame rendering, Remote is up
#
- my $imgsrc = $img;
- if ($img =~ /^\/adm/) {
- $imgsrc = &lonhttpdurl($img);
- }
- my $upperleft='
';
-
my $help=($no_inline_link?''
:&Apache::loncommon::top_nav_help('Help'));
@@ -5869,26 +5935,37 @@ sub bodytag {
}
unless ($env{'form.inhibitmenu'}) {
- $bodytag .= qq|
$name $role
-
$realm $dc_info
|;
- }
- if ($env{'request.state'} eq 'construct') {
- if (!$public){
- if ($env{'request.state'} eq 'construct') {
- $funclist = &Apache::lonhtmlcommon::scripttag(
- &Apache::lonmenu::utilityfunctions($httphost), 'start').
- &Apache::lonhtmlcommon::scripttag('','end').
- &Apache::lonmenu::innerregister($forcereg,
- $args->{'bread_crumbs'});
- }
- }
+ $bodytag .= &inline_for_remote($public,$role,$realm,$dc_info,$no_inline_link);
}
return $bodytag."\n".$funclist;
}
+sub inline_for_remote {
+ my ($public,$role,$realm,$dc_info,$no_inline_link) = @_;
+ my $help=($no_inline_link?''
+ :&Apache::loncommon::top_nav_help('Help'));
+
+ # Explicit link to get inline menu
+ my $menu= ($no_inline_link?''
+ :'
'.&mt('Switch to Inline Menu Mode').'');
+
+ if ($dc_info) {
+ $dc_info = qq|
($dc_info)|;
+ }
+
+ my $name = &plainname($env{'user.name'},$env{'user.domain'});
+ unless ($public) {
+ $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},
+ undef,'LC_menubuttons_link');
+ }
+
+ return qq|
$name $role
+
$realm $dc_info
|;
+}
+
sub dc_courseid_toggle {
my ($dc_info) = @_;
return '
'.
@@ -5968,6 +6045,9 @@ sub endbodytag {
$endbodytag;
}
}
+ if ((ref($args) eq 'HASH') && ($args->{'dashjs'})) {
+ $endbodytag = &Apache::lonhtmlcommon::dash_to_minus_js().$endbodytag;
+ }
return $endbodytag;
}
@@ -8022,6 +8102,7 @@ Inputs: $title - optional title for the
(side effect of setting
$env{'internal.head.redirect'} to the url
redirected too)
+ 4- whether encrypt check should be skipped
domain -> force to color decorate a page for a specific
domain
function -> force usage of a specific rolish color scheme
@@ -8055,7 +8136,7 @@ sub headtag {
$inhibitprint = &print_suppression();
}
- if (!$args->{'frameset'}) {
+ if (!$args->{'frameset'} && !$args->{'switchserver'}) {
$result .= &Apache::lonhtmlcommon::htmlareaheaders();
}
if ($args->{'force_register'}) {
@@ -8063,7 +8144,8 @@ sub headtag {
}
if (!$args->{'no_nav_bar'}
&& !$args->{'only_body'}
- && !$args->{'frameset'}) {
+ && !$args->{'frameset'}
+ && !$args->{'switchserver'}) {
$result .= &help_menu_js($httphost);
$result.=&modal_window();
$result.=&togglebox_script();
@@ -8084,8 +8166,10 @@ sub headtag {
}
}
if (ref($args->{'redirect'})) {
- my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}};
- $url = &Apache::lonenc::check_encrypt($url);
+ my ($time,$url,$inhibit_continue,$skip_enc_check) = @{$args->{'redirect'}};
+ if (!$skip_enc_check) {
+ $url = &Apache::lonenc::check_encrypt($url);
+ }
if (!$inhibit_continue) {
$env{'internal.head.redirect'} = $url;
}
@@ -8229,8 +8313,12 @@ OFFLOAD
$title = 'The LearningOnline Network with CAPA';
}
if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
- $result .= ' LON-CAPA '.$title.''
- .'';
+ } else {
+ $result .= ' LON-CAPA '.$title.'';
+ }
+ $result .= "\n".'{'frameset'}) {
$result .= ' /';
}
@@ -13125,7 +13213,9 @@ sub process_extracted_files {
my $url = '/uploaded/'.$docudom.'/'.$docuname.'/'.
$docstype.'/'.$mapinner{$outer}.'/'.$newidx.'/'.
$title;
- if (($outer !~ /\D/) && ($mapinner{$outer} !~ /\D/) && ($newidx !~ /\D/)) {
+ if (($outer !~ /\D/) &&
+ (($mapinner{$outer} eq 'default') || ($mapinner{$outer} !~ /\D/)) &&
+ ($newidx !~ /\D/)) {
if (!-e "$prefix$dir/$docstype/$mapinner{$outer}") {
mkdir("$prefix$dir/$docstype/$mapinner{$outer}",0755);
}
@@ -14886,7 +14976,7 @@ sub recurse_categories {
for (my $k=0; $k<@{$cats->[$depth]{$category}}; $k++) {
my $name = $cats->[$depth]{$category}[$k];
my $item = &escape($category).':'.&escape($parents->[-1]).':'.$shallower;
- my $trailstr = join(' -> ',(@{$parents},$category));
+ my $trailstr = join(' » ',(@{$parents},$category));
if ($allitems->{$item} eq '') {
push(@{$trails},$trailstr);
$allitems->{$item} = scalar(@{$trails})-1;
@@ -15164,7 +15254,8 @@ sub commit_studentrole {
}
$oldsecurl = $uurl;
$expire_role_result =
- &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',$now,'','',$context);
+ &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',$now,
+ '','','',$context);
if ($env{'request.course.sec'} ne '') {
if ($expire_role_result eq 'refused') {
my @roles = ('st');
@@ -15527,6 +15618,7 @@ sub construct_course {
$cenv{'internal.defaultcredits'} = $args->{'defaultcredits'};
}
my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.
+ my @oklcsecs = (); # Used to accumulate LON-CAPA sections for validated institutional sections.
if ($args->{'crssections'}) {
$cenv{'internal.sectionnums'} = '';
if ($args->{'crssections'} =~ m/,/) {
@@ -15540,7 +15632,11 @@ sub construct_course {
my $class = $args->{'crscode'}.$sec;
my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});
$cenv{'internal.sectionnums'} .= $item.',';
- unless ($addcheck eq 'ok') {
+ if ($addcheck eq 'ok') {
+ unless (grep(/^\Q$gp\E$/,@oklcsecs)) {
+ push(@oklcsecs,$gp);
+ }
+ } else {
push(@badclasses,$class);
}
}
@@ -15568,7 +15664,11 @@ sub construct_course {
my ($xl,$gp) = split/:/,$item;
my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});
$cenv{'internal.crosslistings'} .= $item.',';
- unless ($addcheck eq 'ok') {
+ if ($addcheck eq 'ok') {
+ unless (grep(/^\Q$gp\E$/,@oklcsecs)) {
+ push(@oklcsecs,$gp);
+ }
+ } else {
push(@badclasses,$xl);
}
}
@@ -15631,6 +15731,36 @@ sub construct_course {
if ($args->{'no_end_date'}) {
$args->{'endaccess'} = 0;
}
+# If an official course with institutional sections is created by cloning
+# an existing course, section-specific hiding of course totals in student's
+# view of grades as copied from cloned course, will be checked for valid
+# sections.
+ if (($can_clone && $cloneid) &&
+ ($cenv{'internal.coursecode'} ne '') &&
+ ($cenv{'grading'} eq 'standard') &&
+ ($cenv{'hidetotals'} ne '') &&
+ ($cenv{'hidetotals'} ne 'all')) {
+ my @hidesecs;
+ my $deletehidetotals;
+ if (@oklcsecs) {
+ foreach my $sec (split(/,/,$cenv{'hidetotals'})) {
+ if (grep(/^\Q$sec$/,@oklcsecs)) {
+ push(@hidesecs,$sec);
+ }
+ }
+ if (@hidesecs) {
+ $cenv{'hidetotals'} = join(',',@hidesecs);
+ } else {
+ $deletehidetotals = 1;
+ }
+ } else {
+ $deletehidetotals = 1;
+ }
+ if ($deletehidetotals) {
+ delete($cenv{'hidetotals'});
+ &Apache::lonnet::del('environment',['hidetotals'],$$crsudom,$$crsunum);
+ }
+ }
$cenv{'internal.autostart'}=$args->{'enrollstart'};
$cenv{'internal.autoend'}=$args->{'enrollend'};
$cenv{'default_enrollment_start_date'}=$args->{'startaccess'};
@@ -17056,9 +17186,12 @@ sub recurse_supplemental {
if ($fatal) {
$errors ++;
} else {
- if ($#LONCAPA::map::resources > 0) {
- foreach my $res (@LONCAPA::map::resources) {
- my ($title,$src,$ext,$type,$status)=split(/\:/,$res);
+ my @order = @LONCAPA::map::order;
+ if (@order > 0) {
+ my @resources = @LONCAPA::map::resources;
+ my @resparms = @LONCAPA::map::resparms;
+ foreach my $idx (@order) {
+ my ($title,$src,$ext,$type,$status)=split(/\:/,$resources[$idx]);
if (($src ne '') && ($status eq 'res')) {
if ($src =~ m{^\Q/uploaded/$cdom/$cnum/\E(supplemental_\d+\.sequence)$}) {
($numfiles,$errors) = &recurse_supplemental($cnum,$cdom,$1,$numfiles,$errors);
@@ -17265,7 +17398,7 @@ sub create_captcha {
$output = ''."\n".
''.
&mt('Type in the letters/numbers shown below').' '.
- ''.
+ ''.
'
'.
'';
last;