--- loncom/interface/loncommon.pm 2004/11/23 07:29:24 1.234
+++ loncom/interface/loncommon.pm 2006/07/19 11:30:36 1.434
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.234 2004/11/23 07:29:24 raeburn Exp $
+# $Id: loncommon.pm,v 1.434 2006/07/19 11:30:36 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -55,13 +55,16 @@ redundancy from other modules and increa
package Apache::loncommon;
use strict;
-use Apache::lonnet();
+use Apache::lonnet;
use GDBM_File;
use POSIX qw(strftime mktime);
-use Apache::Constants qw(:common :http :methods);
use Apache::lonmenu();
use Apache::lonlocal;
use HTML::Entities;
+use Apache::lonhtmlcommon();
+use Apache::loncoursedata();
+use Apache::lontexconvert();
+use LONCAPA;
my $readit;
@@ -74,7 +77,7 @@ my %language;
my %supported_language;
my %cprtag;
my %scprtag;
-my %fe; my %fd;
+my %fe; my %fd; my %fm;
my %category_extensions;
# ---------------------------------------------- Designs
@@ -105,10 +108,10 @@ BEGIN {
my $langtabfile = $Apache::lonnet::perlvar{'lonTabDir'}.
'/language.tab';
if ( open(my $fh,"<$langtabfile") ) {
- while (<$fh>) {
- next if /^\#/;
- chomp;
- my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$_));
+ while (my $line = <$fh>) {
+ next if ($line=~/^\#/);
+ chomp($line);
+ my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$line));
$language{$key}=$val.' - '.$enc;
if ($sup) {
$supported_language{$key}=$sup;
@@ -122,24 +125,24 @@ BEGIN {
my $copyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
'/copyright.tab';
if ( open (my $fh,"<$copyrightfile") ) {
- while (<$fh>) {
- next if /^\#/;
- chomp;
- my ($key,$val)=(split(/\s+/,$_,2));
+ while (my $line = <$fh>) {
+ next if ($line=~/^\#/);
+ chomp($line);
+ my ($key,$val)=(split(/\s+/,$line,2));
$cprtag{$key}=$val;
}
close($fh);
}
}
-# ------------------------------------------------------------------ source copyrights
+# ----------------------------------------------------------- source copyrights
{
my $sourcecopyrightfile = $Apache::lonnet::perlvar{'lonIncludes'}.
'/source_copyright.tab';
if ( open (my $fh,"<$sourcecopyrightfile") ) {
- while (<$fh>) {
- next if /^\#/;
- chomp;
- my ($key,$val)=(split(/\s+/,$_,2));
+ while (my $line = <$fh>) {
+ next if ($line =~ /^\#/);
+ chomp($line);
+ my ($key,$val)=(split(/\s+/,$line,2));
$scprtag{$key}=$val;
}
close($fh);
@@ -152,19 +155,20 @@ BEGIN {
my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
opendir(DIR,$designdir);
while ($filename=readdir(DIR)) {
+ if ($filename!~/\.tab$/) { next; }
my ($domain)=($filename=~/^(\w+)\./);
- {
- my $designfile = $designdir.'/'.$filename;
- if ( open (my $fh,"<$designfile") ) {
- while (<$fh>) {
- next if /^\#/;
- chomp;
- my ($key,$val)=(split(/\=/,$_));
- if ($val) { $designhash{$domain.'.'.$key}=$val; }
- }
- close($fh);
- }
- }
+ {
+ my $designfile = $designdir.'/'.$filename;
+ if ( open (my $fh,"<$designfile") ) {
+ while (my $line = <$fh>) {
+ next if ($line =~ /^\#/);
+ chomp($line);
+ my ($key,$val)=(split(/\=/,$line));
+ if ($val) { $designhash{$domain.'.'.$key}=$val; }
+ }
+ close($fh);
+ }
+ }
}
closedir(DIR);
@@ -175,10 +179,10 @@ BEGIN {
my $categoryfile = $Apache::lonnet::perlvar{'lonTabDir'}.
'/filecategories.tab';
if ( open (my $fh,"<$categoryfile") ) {
- while (<$fh>) {
- next if /^\#/;
- chomp;
- my ($extension,$category)=(split(/\s+/,$_,2));
+ while (my $line = <$fh>) {
+ next if ($line =~ /^\#/);
+ chomp($line);
+ my ($extension,$category)=(split(/\s+/,$line,2));
push @{$category_extensions{lc($category)}},$extension;
}
close($fh);
@@ -190,13 +194,14 @@ BEGIN {
my $typesfile = $Apache::lonnet::perlvar{'lonTabDir'}.
'/filetypes.tab';
if ( open (my $fh,"<$typesfile") ) {
- while (<$fh>) {
- next if (/^\#/);
- chomp;
- my ($ending,$emb,$descr)=split(/\s+/,$_,3);
+ while (my $line = <$fh>) {
+ next if ($line =~ /^\#/);
+ chomp($line);
+ my ($ending,$emb,$mime,$descr)=split(/\s+/,$line,4);
if ($descr ne '') {
$fe{$ending}=lc($emb);
$fd{$ending}=$descr;
+ if ($mime ne 'unk') { $fm{$ending}=$mime; }
}
}
close($fh);
@@ -311,8 +316,8 @@ END
}
sub lastresurl {
- if ($ENV{'environment.lastresurl'}) {
- return $ENV{'environment.lastresurl'}
+ if ($env{'environment.lastresurl'}) {
+ return $env{'environment.lastresurl'}
} else {
return '/res';
}
@@ -329,9 +334,12 @@ sub storeresurl {
sub studentbrowser_javascript {
unless (
- (($ENV{'request.course.id'}) &&
- (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})))
- || ($ENV{'request.role'}=~/^(au|dc|su)/)
+ (($env{'request.course.id'}) &&
+ (&Apache::lonnet::allowed('srm',$env{'request.course.id'})
+ || &Apache::lonnet::allowed('srm',$env{'request.course.id'}.
+ '/'.$env{'request.course.sec'})
+ ))
+ || ($env{'request.role'}=~/^(au|dc|su)/)
) { return ''; }
return (<<'ENDSTDBRW');
+ENDOUTPUT
+ return $output;
+}
+
+# now just updates the help link and generates a blue icon
sub help_open_menu {
- my ($color,$topic,$component_help,$function,$faq,$bug,$stayOnPage,$width,$height,$text) = @_;
+ my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text)
+ = @_;
+
+ $stayOnPage = 0 if (not defined $stayOnPage);
+ if ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' ) {
+ $stayOnPage=1;
+ }
+ my $output;
+ if ($component_help) {
+ if (!$text) {
+ $output=&help_open_topic($component_help,undef,$stayOnPage,
+ $width,$height);
+ } else {
+ my $help_text;
+ $help_text=&unescape($topic);
+ $output='
'.
+ &help_open_topic($component_help,$help_text,$stayOnPage,
+ $width,$height).'
';
+ }
+ }
+ my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage);
+ return $output.$banner_link;
+}
+
+sub top_nav_help {
+ my ($text) = @_;
+
+ my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height);
+
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- if ($ENV{'browser.interface'} eq 'textual' ||
- $ENV{'environment.remote'} eq 'off' ) {
+ if ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
}
$width = 620 if (not defined $width);
$height = 600 if (not defined $height);
my $link='';
my $title = &mt('Get help');
- my $origurl = $ENV{'REQUEST_URI'};
- $origurl=~s|^/~|/priv/|;
- my $timestamp = time;
- foreach (\$color,\$function,\$topic,\$component_help,\$faq,\$bug,\$origurl) {
- $$_ = &Apache::lonnet::escape($$_);
- }
-
- if (!$stayOnPage) {
- $link = "javascript:helpMenu('open')";
+ if ($stayOnPage) {
+ $link = "javascript:helpMenu('display')";
} else {
- $link = "javascript:helpMenu('display')";
+ $link = "javascript:helpMenu('open')";
}
- my $banner_link = "/adm/helpmenu?page=banner&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp&stayonpage=$stayOnPage";
- my $details_link = "/adm/helpmenu?page=body&color=$color&function=$function&topic=$topic&component_help=$component_help&faq=$faq&bug=$bug&origurl=$origurl&stamp=$timestamp";
+ my $helptopic=&general_help();
+ my $banner_link = &update_help_link($topic,$component_help,$faq,$bug,$stayOnPage);
+ my $details_link = '/adm/help/'.$helptopic.'.hlp';
my $template;
- if ($text ne "") {
- $template .=
- "".
- "$text ";
- }
+ my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
my $helpicon=&lonhttpdurl("/adm/lonIcons/helpgateway.gif");
+ my $start_page =
+ &Apache::loncommon::start_page('Help Menu', undef,
+ {'frameset' => 1,
+ 'js_ready' => 1,
+ 'add_entries' => {
+ 'border' => '0',
+ 'rows' => "105,*",},});
+ my $end_page =
+ &Apache::loncommon::end_page({'frameset' => 1,
+ 'js_ready' => 1,});
+
$template .= <<"ENDTEMPLATE";
-
+$banner_link
+ $text
ENDTEMPLATE
- if ($component_help) {
- if (!$text) {
- $template=&help_open_topic($component_help,undef,$stayOnPage,
- $width,$height).' '.$template;
- } else {
- my $help_text;
- $help_text=&Apache::lonnet::unescape($topic);
- $template=''.
- &help_open_topic($component_help,$help_text,$stayOnPage,
- $width,$height).' '.$template.
- '
';
- }
- }
- if ($text ne '') { $template.='
' };
return $template;
}
sub help_open_bug {
my ($topic, $text, $stayOnPage, $width, $height) = @_;
- unless ($ENV{'user.adv'}) { return ''; }
+ unless ($env{'user.adv'}) { return ''; }
unless ($Apache::lonnet::perlvar{'BugzillaHost'}) { return ''; }
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- if ($ENV{'browser.interface'} eq 'textual' ||
- $ENV{'environment.remote'} eq 'off' ) {
+ if ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
}
$width = 600 if (not defined $width);
@@ -743,8 +853,8 @@ sub help_open_bug {
$topic=~s/\W+/\+/g;
my $link='';
my $template='';
- my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
- &Apache::lonnet::escape($ENV{'REQUEST_URI'}).'&component='.$topic;
+ my $url=$Apache::lonnet::perlvar{'BugzillaHost'}.'enter_bug.cgi?product=LON-CAPA&bug_file_loc='.
+ &escape($ENV{'REQUEST_URI'}).'&component='.$topic;
if (!$stayOnPage)
{
$link = "javascript:void(open('$url', 'Bugzilla', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
@@ -774,12 +884,12 @@ ENDTEMPLATE
sub help_open_faq {
my ($topic, $text, $stayOnPage, $width, $height) = @_;
- unless ($ENV{'user.adv'}) { return ''; }
+ unless ($env{'user.adv'}) { return ''; }
unless ($Apache::lonnet::perlvar{'FAQHost'}) { return ''; }
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- if ($ENV{'browser.interface'} eq 'textual' ||
- $ENV{'environment.remote'} eq 'off' ) {
+ if ($env{'browser.interface'} eq 'textual' ||
+ $env{'environment.remote'} eq 'off' ) {
$stayOnPage=1;
}
$width = 350 if (not defined $width);
@@ -822,6 +932,98 @@ ENDTEMPLATE
=pod
+=item * change_content_javascript():
+
+This and the next function allow you to create small sections of an
+otherwise static HTML page that you can update on the fly with
+Javascript, even in Netscape 4.
+
+The Javascript fragment returned by this function (no EscriptE tag)
+must be written to the HTML page once. It will prove the Javascript
+function "change(name, content)". Calling the change function with the
+name of the section
+you want to update, matching the name passed to C, and
+the new content you want to put in there, will put the content into
+that area.
+
+B: Netscape 4 only reserves enough space for the changable area
+to contain room for the original contents. You need to "make space"
+for whatever changes you wish to make, and be B to check your
+code in Netscape 4. This feature in Netscape 4 is B powerful;
+it's adequate for updating a one-line status display, but little more.
+This script will set the space to 100% width, so you only need to
+worry about height in Netscape 4.
+
+Modern browsers are much less limiting, and if you can commit to the
+user not using Netscape 4, this feature may be used freely with
+pretty much any HTML.
+
+=cut
+
+sub change_content_javascript {
+ # If we're on Netscape 4, we need to use Layer-based code
+ if ($env{'browser.type'} eq 'netscape' &&
+ $env{'browser.version'} =~ /^4\./) {
+ return (<. $name is
+the name you will use to reference the area later; do not repeat the
+same name on a given HTML page more then once. $origContent is what
+the area will originally contain, which can be left blank.
+
+=cut
+
+sub changable_area {
+ my ($name, $origContent) = @_;
+
+ if ($env{'browser.type'} eq 'netscape' &&
+ $env{'browser.version'} =~ /^4\./) {
+ # If this is netscape 4, we need to use the Layer tag
+ return "$origContent ";
+ } else {
+ return "$origContent ";
+ }
+}
+
+=pod
+
+=back
+
+=head1 Excel and CSV file utility routines
+
+=over 4
+
+=cut
+
+###############################################################
+###############################################################
+
+=pod
+
=item * csv_translate($text)
Translate $text to allow it to be output as a 'comma separated values'
@@ -838,7 +1040,6 @@ sub csv_translate {
return $text;
}
-
###############################################################
###############################################################
@@ -862,6 +1063,10 @@ Currently supported formats:
=item h3
+=item h4
+
+=item i
+
=item date
=back
@@ -884,6 +1089,8 @@ sub define_excel_formats {
$format->{'h1'} = $workbook->add_format(bold=>1, size=>18);
$format->{'h2'} = $workbook->add_format(bold=>1, size=>16);
$format->{'h3'} = $workbook->add_format(bold=>1, size=>14);
+ $format->{'h4'} = $workbook->add_format(bold=>1, size=>12);
+ $format->{'i'} = $workbook->add_format(italic=>1);
$format->{'date'} = $workbook->add_format(num_format=>
'mm/dd/yyyy hh:mm:ss');
return $format;
@@ -894,84 +1101,83 @@ sub define_excel_formats {
=pod
-=item * change_content_javascript():
-
-This and the next function allow you to create small sections of an
-otherwise static HTML page that you can update on the fly with
-Javascript, even in Netscape 4.
+=item * create_workbook
-The Javascript fragment returned by this function (no EscriptE tag)
-must be written to the HTML page once. It will prove the Javascript
-function "change(name, content)". Calling the change function with the
-name of the section
-you want to update, matching the name passed to C, and
-the new content you want to put in there, will put the content into
-that area.
+Create an Excel worksheet. If it fails, output message on the
+request object and return undefs.
-B: Netscape 4 only reserves enough space for the changable area
-to contain room for the original contents. You need to "make space"
-for whatever changes you wish to make, and be B to check your
-code in Netscape 4. This feature in Netscape 4 is B powerful;
-it's adequate for updating a one-line status display, but little more.
-This script will set the space to 100% width, so you only need to
-worry about height in Netscape 4.
+Inputs: Apache request object
-Modern browsers are much less limiting, and if you can commit to the
-user not using Netscape 4, this feature may be used freely with
-pretty much any HTML.
+Returns (undef) on failure,
+ Excel worksheet object, scalar with filename, and formats
+ from &Apache::loncommon::define_excel_formats on success
=cut
-sub change_content_javascript {
- # If we're on Netscape 4, we need to use Layer-based code
- if ($ENV{'browser.type'} eq 'netscape' &&
- $ENV{'browser.version'} =~ /^4\./) {
- return (<new('/home/httpd'.$filename);
+ if (! defined($workbook)) {
+ $r->log_error("Error creating excel spreadsheet $filename: $!");
+ $r->print(''.&mt("Unable to create new Excel file. ".
+ "This error has been logged. ".
+ "Please alert your LON-CAPA administrator").
+ '
');
+ return (undef);
}
+ #
+ $workbook->set_tempdir('/home/httpd/perl/tmp');
+ #
+ my $format = &Apache::loncommon::define_excel_formats($workbook);
+ return ($workbook,$filename,$format);
}
+###############################################################
+###############################################################
+
=pod
-=item * changable_area($name, $origContent):
+=item * create_text_file
-This provides a "changable area" that can be modified on the fly via
-the Javascript code provided in C. $name is
-the name you will use to reference the area later; do not repeat the
-same name on a given HTML page more then once. $origContent is what
-the area will originally contain, which can be left blank.
+Create a file to write to and eventually make available to the usre.
+If file creation fails, outputs an error message on the request object and
+return undefs.
-=cut
+Inputs: Apache request object, and file suffix
-sub changable_area {
- my ($name, $origContent) = @_;
+Returns (undef) on failure,
+ Filehandle and filename on success.
- if ($ENV{'browser.type'} eq 'netscape' &&
- $ENV{'browser.version'} =~ /^4\./) {
- # If this is netscape 4, we need to use the Layer tag
- return "$origContent ";
- } else {
- return "$origContent ";
+=cut
+
+###############################################################
+###############################################################
+sub create_text_file {
+ my ($r,$suffix) = @_;
+ if (! defined($suffix)) { $suffix = 'txt'; };
+ my $fh;
+ my $filename = '/prtspool/'.
+ $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
+ time.'_'.rand(1000000000).'.'.$suffix;
+ $fh = Apache::File->new('>/home/httpd'.$filename);
+ if (! defined($fh)) {
+ $r->log_error("Couldn't open $filename for output $!");
+ $r->print("Problems occured in creating the output file. ".
+ "This error has been logged. ".
+ "Please alert your LON-CAPA administrator.");
}
+ return ($fh,$filename)
}
-=pod
+
+=pod
=back
@@ -999,8 +1205,8 @@ sub get_domains {
# The code below was stolen from "The Perl Cookbook", p 102, 1st ed.
my @domains;
my %seen;
- foreach (sort values(%Apache::lonnet::hostdom)) {
- push (@domains,$_) unless $seen{$_}++;
+ foreach my $dom (sort(values(%Apache::lonnet::hostdom))) {
+ push(@domains,$dom) unless $seen{$dom}++;
}
return @domains;
}
@@ -1014,27 +1220,49 @@ sub domain_select {
} &get_domains;
if ($multiple) {
$domains{''}=&mt('Any domain');
- return &multiple_select_form($name,$value,4,%domains);
+ return &multiple_select_form($name,$value,4,\%domains);
} else {
return &select_form($name,$value,%domains);
}
}
+#-------------------------------------------
+
+=pod
+
+=item * multiple_select_form($name,$value,$size,$hash,$order)
+
+Returns a string containing a element int multiple mode
+
+
+Args:
+ $name - name of the element
+ $value - sclara or array ref of values that should already be selected
+ $size - number of rows long the select element is
+ $hash - the elements should be 'option' => 'shown text'
+ (shown text should already have been &mt())
+ $order - (optional) array ref of the order to show the elments in
+
+=cut
+
+#-------------------------------------------
sub multiple_select_form {
- my ($name,$value,$size,%hash)=@_;
+ my ($name,$value,$size,$hash,$order)=@_;
my %selected = map { $_ => 1 } ref($value)?@{$value}:($value);
my $output='';
if (! defined($size)) {
$size = 4;
- if (scalar(keys(%hash))<4) {
- $size = scalar(keys(%hash));
+ if (scalar(keys(%$hash))<4) {
+ $size = scalar(keys(%$hash));
}
}
$output.="\n";
- foreach (sort(keys(%hash))) {
- $output.=''.$hash{$_}." \n";
+ my @order = ref($order) ? @$order
+ : sort(keys(%$hash));
+ foreach my $key (@order) {
+ $output.='&').'" ';
+ $output.='selected="selected" ' if ($selected{$key});
+ $output.='>'.$hash->{$key}." \n";
}
$output.=" \n";
return $output;
@@ -1062,10 +1290,11 @@ sub select_form {
} else {
@keys=sort(keys(%hash));
}
- foreach (@keys) {
- $selectform.="".&mt($hash{$_})." \n";
+ foreach my $key (@keys) {
+ $selectform.=
+ '&').'" '.
+ ($key eq $def ? 'selected="selected" ' : '').
+ ">".&mt($hash{$key})." \n";
}
$selectform.=" ";
return $selectform;
@@ -1101,7 +1330,7 @@ sub select_level_form {
my $selectform = "\n";
for (my $i=0; $i<=18; $i++) {
$selectform.="".&gradeleveldescription($i)." \n";
}
$selectform.=" ";
@@ -1129,10 +1358,10 @@ sub select_dom_form {
my @domains = get_domains();
if ($includeempty) { @domains=('',@domains); }
my $selectdomain = "\n";
- foreach (@domains) {
- $selectdomain.="$_ \n";
+ foreach my $dom (@domains) {
+ $selectdomain.="$dom \n";
}
$selectdomain.=" ";
return $selectdomain;
@@ -1154,9 +1383,9 @@ given $domain.
sub get_library_servers {
my $domain = shift;
my %library_servers;
- foreach (keys(%Apache::lonnet::libserv)) {
- if ($Apache::lonnet::hostdom{$_} eq $domain) {
- $library_servers{$_} = $Apache::lonnet::hostname{$_};
+ foreach my $hostid (keys(%Apache::lonnet::libserv)) {
+ if ($Apache::lonnet::hostdom{$hostid} eq $domain) {
+ $library_servers{$hostid} = $Apache::lonnet::hostname{$hostid};
}
}
return %library_servers;
@@ -1178,9 +1407,10 @@ sub home_server_option_list {
my $domain = shift;
my %servers = &get_library_servers($domain);
my $result = '';
- foreach (sort keys(%servers)) {
+ foreach my $hostid (sort(keys(%servers))) {
$result.=
- ''.$_.' '.$servers{$_}." \n";
+ ''.
+ $hostid.' '.$servers{$hostid}." \n";
}
return $result;
}
@@ -1230,9 +1460,11 @@ Outputs:
###############################################################
###############################################################
sub decode_user_agent {
+ my ($r)=@_;
my @browsertype=split(/\&/,$Apache::lonnet::perlvar{"lonBrowsDet"});
my %mathcap=split(/\&/,$$Apache::lonnet::perlvar{"lonMathML"});
my $httpbrowser=$ENV{"HTTP_USER_AGENT"};
+ if (!$httpbrowser && $r) { $httpbrowser=$r->header_in('User-Agent'); }
my $clientbrowser='unknown';
my $clientversion='0';
my $clientmathml='';
@@ -1428,10 +1660,11 @@ sub authform_nochange{
kerb_def_dom => 'MSU.EDU',
@_,
);
- my $result = &mt('[_1] Do not change login data',
+ my $result = ''.&mt('[_1] Do not change login data',
' ');
+ "javascript:changed_radio('nochange',$in{'formname'});".'" />').
+ ' ';
return $result;
}
@@ -1463,14 +1696,15 @@ sub authform_kerberos{
my $jscall = "javascript:changed_radio('krb',$in{'formname'});";
my $result .= &mt
('[_1] Kerberos authenticated with domain [_2] '.
- '[_3] Version 4 [_4] Version 5',
- ' ',
- ' ',
- ' ',
- ' ');
+ ' ',
+ ' ',
+ ' ');
return $result;
}
@@ -1495,9 +1729,9 @@ sub authform_internal{
my $jscall = "javascript:changed_radio('int',$args{'formname'});";
my $result.=&mt
('[_1] Internally authenticated (with initial password [_2])',
- ' ',
- ' ');
return $result;
}
@@ -1522,9 +1756,9 @@ sub authform_local{
my $jscall = "javascript:changed_radio('loc',$in{'formname'});";
my $result.=&mt('[_1] Local Authentication with argument [_2]',
- ' ',
- ' ');
return $result;
}
@@ -1538,9 +1772,9 @@ sub authform_filesystem{
my $jscall = "javascript:changed_radio('fsys',$in{'formname'});";
my $result.= &mt
('[_1] Filesystem Authenticated (with initial password [_2])',
- ' ',
- ' ');
return $result;
}
@@ -1666,8 +1900,8 @@ sub initialize_keywords {
}
untie %thesaurus_db;
# Remove special values from %Keywords.
- foreach ('total.count','average.count') {
- delete($Keywords{$_}) if (exists($Keywords{$_}));
+ foreach my $value ('total.count','average.count') {
+ delete($Keywords{$value}) if (exists($Keywords{$value}));
}
return 1;
}
@@ -1722,12 +1956,20 @@ sub get_related_words {
return ();
}
my @Words=();
+ my $count=0;
if (exists($thesaurus_db{$keyword})) {
- $_ = $thesaurus_db{$keyword};
- (undef,@Words) = split/:/; # The first element is the number of times
- # the word appears. We do not need it now.
- for (my $i=0;$i<=$#Words;$i++) {
- ($Words[$i],undef)= split/\,/,$Words[$i];
+ # The first element is the number of times
+ # the word appears. We do not need it now.
+ my (undef,@RelatedWords) = (split(/:/,$thesaurus_db{$keyword}));
+ my (undef,$mostfrequentcount)=split(/\,/,$RelatedWords[0]);
+ my $threshold=$mostfrequentcount/10;
+ foreach my $possibleword (@RelatedWords) {
+ my ($word,$wordcount)=split(/\,/,$possibleword);
+ if ($wordcount>$threshold) {
+ push(@Words,$word);
+ $count++;
+ if ($count>10) { last; }
+ }
}
}
untie %thesaurus_db;
@@ -1756,12 +1998,11 @@ if $first is set to 'lastname' then it r
=cut
+
###############################################################
sub plainname {
my ($uname,$udom,$first)=@_;
- my %names=&Apache::lonnet::get('environment',
- ['firstname','middlename','lastname','generation'],
- $udom,$uname);
+ my %names=&getnames($uname,$udom);
my $name=&Apache::lonnet::format_name($names{'firstname'},
$names{'middlename'},
$names{'lastname'},
@@ -1769,7 +2010,7 @@ sub plainname {
$name=~s/^\s+//;
$name=~s/\s+$//;
$name=~s/\s+/ /g;
- if ($name !~ /\S/) { $name=$uname.'@'.$udom; }
+ if ($name !~ /\S/) { $name=$uname.':'.$udom; }
return $name;
}
@@ -1792,19 +2033,7 @@ if the user does not
sub nickname {
my ($uname,$udom)=@_;
- my %names;
- if ($uname eq $ENV{'user.name'} &&
- $udom eq $ENV{'user.domain'}) {
- %names=('nickname' => $ENV{'environment.nickname'} ,
- 'firstname' => $ENV{'environment.firstname'} ,
- 'middlename' => $ENV{'environment.middlename'},
- 'lastname' => $ENV{'environment.lastname'} ,
- 'generation' => $ENV{'environment.generation'});
- } else {
- %names=&Apache::lonnet::get('environment',
- ['nickname','firstname','middlename',
- 'lastname','generation'],$udom,$uname);
- }
+ my %names=&getnames($uname,$udom);
my $name=$names{'nickname'};
if ($name) {
$name='"'.$name.'"';
@@ -1817,6 +2046,23 @@ sub nickname {
return $name;
}
+sub getnames {
+ my ($uname,$udom)=@_;
+ if ($udom eq 'public' && $uname eq 'public') {
+ return ('lastname' => &mt('Public'));
+ }
+ my $id=$uname.':'.$udom;
+ my ($names,$cached)=&Apache::lonnet::is_cached_new('namescache',$id);
+ if ($cached) {
+ return %{$names};
+ } else {
+ my %loadnames=&Apache::lonnet::get('environment',
+ ['firstname','middlename','lastname','generation','nickname'],
+ $udom,$uname);
+ &Apache::lonnet::do_cache_new('namescache',$id,\%loadnames);
+ return %loadnames;
+ }
+}
# ------------------------------------------------------------------ Screenname
@@ -1830,8 +2076,8 @@ Gets a users screenname and returns it a
sub screenname {
my ($uname,$udom)=@_;
- if ($uname eq $ENV{'user.name'} &&
- $udom eq $ENV{'user.domain'}) {return $ENV{'environment.screenname'};}
+ if ($uname eq $env{'user.name'} &&
+ $udom eq $env{'user.domain'}) {return $env{'environment.screenname'};}
my %names=&Apache::lonnet::get('environment',['screenname'],$udom,$uname);
return $names{'screenname'};
}
@@ -1840,10 +2086,11 @@ sub screenname {
# ------------------------------------------------------------- Message Wrapper
sub messagewrapper {
- my ($link,$username,$domain)=@_;
+ my ($link,$username,$domain,$subject,$text)=@_;
return
''.$link.' ';
}
# --------------------------------------------------------------- Notes Wrapper
@@ -1873,24 +2120,23 @@ sub syllabuswrapper {
}
sub track_student_link {
- my ($linktext,$sname,$sdom,$target) = @_;
- my $link ="/adm/trackstudent";
+ my ($linktext,$sname,$sdom,$target,$start) = @_;
+ my $link ="/adm/trackstudent?";
my $title = 'View recent activity';
if (defined($sname) && $sname !~ /^\s*$/ &&
defined($sdom) && $sdom !~ /^\s*$/) {
- $link .= "?selected_student=$sname:$sdom";
+ $link .= "selected_student=$sname:$sdom";
$title .= ' of this student';
- }
+ }
if (defined($target) && $target !~ /^\s*$/) {
$target = qq{target="$target"};
} else {
$target = '';
}
+ if ($start) { $link.='&start='.$start; }
return qq{$linktext };
}
-
-
=pod
=back
@@ -2004,7 +2250,8 @@ category
=cut
sub filecategorytypes {
- return @{$category_extensions{lc($_[0])}};
+ my ($cat) = @_;
+ return @{$category_extensions{lc($cat)}};
}
=pod
@@ -2019,6 +2266,10 @@ sub fileembstyle {
return $fe{lc(shift(@_))};
}
+sub filemimetype {
+ return $fm{lc(shift(@_))};
+}
+
sub filecategoryselect {
my ($name,$value)=@_;
@@ -2075,13 +2326,13 @@ sub fileextensions {
sub display_languages {
my %languages=();
- foreach (&preferred_languages()) {
- $languages{$_}=1;
+ foreach my $lang (&preferred_languages()) {
+ $languages{$lang}=1;
}
&get_unprocessed_cgi($ENV{'QUERY_STRING'},['displaylanguage']);
- if ($ENV{'form.displaylanguage'}) {
- foreach (split(/\s*(\,|\;|\:)\s*/,$ENV{'form.displaylanguage'})) {
- $languages{$_}=1;
+ if ($env{'form.displaylanguage'}) {
+ foreach my $lang (split(/\s*(\,|\;|\:)\s*/,$env{'form.displaylanguage'})) {
+ $languages{$lang}=1;
}
}
return %languages;
@@ -2089,24 +2340,24 @@ sub display_languages {
sub preferred_languages {
my @languages=();
- if ($ENV{'course.'.$ENV{'request.course.id'}.'.languages'}) {
+ if ($env{'course.'.$env{'request.course.id'}.'.languages'}) {
@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,
- $ENV{'course.'.$ENV{'request.course.id'}.'.languages'}));
+ $env{'course.'.$env{'request.course.id'}.'.languages'}));
}
- if ($ENV{'environment.languages'}) {
- @languages=split(/\s*(\,|\;|\:)\s*/,$ENV{'environment.languages'});
+ if ($env{'environment.languages'}) {
+ @languages=split(/\s*(\,|\;|\:)\s*/,$env{'environment.languages'});
}
my $browser=(split(/\;/,$ENV{'HTTP_ACCEPT_LANGUAGE'}))[0];
if ($browser) {
@languages=(@languages,split(/\s*(\,|\;|\:)\s*/,$browser));
}
- if ($Apache::lonnet::domain_lang_def{$ENV{'user.domain'}}) {
+ if ($Apache::lonnet::domain_lang_def{$env{'user.domain'}}) {
@languages=(@languages,
- $Apache::lonnet::domain_lang_def{$ENV{'user.domain'}});
+ $Apache::lonnet::domain_lang_def{$env{'user.domain'}});
}
- if ($Apache::lonnet::domain_lang_def{$ENV{'request.role.domain'}}) {
+ if ($Apache::lonnet::domain_lang_def{$env{'request.role.domain'}}) {
@languages=(@languages,
- $Apache::lonnet::domain_lang_def{$ENV{'request.role.domain'}});
+ $Apache::lonnet::domain_lang_def{$env{'request.role.domain'}});
}
if ($Apache::lonnet::domain_lang_def{
$Apache::lonnet::perlvar{'lonDefDomain'}}) {
@@ -2116,11 +2367,11 @@ sub preferred_languages {
}
# turn "en-ca" into "en-ca,en"
my @genlanguages;
- foreach (@languages) {
- unless ($_=~/\w/) { next; }
- push (@genlanguages,$_);
- if ($_=~/(\-|\_)/) {
- push (@genlanguages,(split(/(\-|\_)/,$_))[0]);
+ foreach my $lang (@languages) {
+ unless ($lang=~/\w/) { next; }
+ push (@genlanguages,$lang);
+ if ($lang=~/(\-|\_)/) {
+ push(@genlanguages,(split(/(\-|\_)/,$lang))[0]);
}
}
return @genlanguages;
@@ -2176,14 +2427,14 @@ sub get_previous_attempt {
my %lasthash=();
my $version;
for ($version=1;$version<=$returnhash{'version'};$version++) {
- foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {
- $lasthash{$_}=$returnhash{$version.':'.$_};
+ foreach my $key (sort(split(/\:/,$returnhash{$version.':keys'}))) {
+ $lasthash{$key}=$returnhash{$version.':'.$key};
}
}
$prevattempts='';
$prevattempts.='History ';
- foreach (sort(keys %lasthash)) {
- my ($ign,@parts) = split(/\./,$_);
+ foreach my $key (sort(keys(%lasthash))) {
+ my ($ign,@parts) = split(/\./,$key);
if ($#parts > 0) {
my $data=$parts[-1];
pop(@parts);
@@ -2199,27 +2450,27 @@ sub get_previous_attempt {
if ($getattempt eq '') {
for ($version=1;$version<=$returnhash{'version'};$version++) {
$prevattempts.='Transaction '.$version.' ';
- foreach (sort(keys %lasthash)) {
+ foreach my $key (sort(keys(%lasthash))) {
my $value;
- if ($_ =~ /timestamp/) {
- $value=scalar(localtime($returnhash{$version.':'.$_}));
+ if ($key =~ /timestamp/) {
+ $value=scalar(localtime($returnhash{$version.':'.$key}));
} else {
- $value=$returnhash{$version.':'.$_};
+ $value=$returnhash{$version.':'.$key};
}
- $prevattempts.=''.&Apache::lonnet::unescape($value).' ';
+ $prevattempts.=''.&unescape($value).' ';
}
}
}
$prevattempts.='Current ';
- foreach (sort(keys %lasthash)) {
+ foreach my $key (sort(keys(%lasthash))) {
my $value;
- if ($_ =~ /timestamp/) {
- $value=scalar(localtime($lasthash{$_}));
+ if ($key =~ /timestamp/) {
+ $value=scalar(localtime($lasthash{$key}));
} else {
- $value=$lasthash{$_};
+ $value=$lasthash{$key};
}
- $value=&Apache::lonnet::unescape($value);
- if ($_ =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
+ $value=&unescape($value);
+ if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
$prevattempts.=''.$value.' ';
}
$prevattempts.='
';
@@ -2251,14 +2502,14 @@ sub relative_to_absolute {
}
}
$thisdir=~s-/[^/]*$--;
- foreach (@rlinks) {
- unless (($_=~/^http:\/\//i) ||
- ($_=~/^\//) ||
- ($_=~/^javascript:/i) ||
- ($_=~/^mailto:/i) ||
- ($_=~/^\#/)) {
- my $newlocation=&Apache::lonnet::hreflocation($thisdir,$_);
- $output=~s/(\"|\'|\=\s*)$_(\"|\'|\s|\>)/$1$newlocation$2/;
+ foreach my $link (@rlinks) {
+ unless (($link=~/^http:\/\//i) ||
+ ($link=~/^\//) ||
+ ($link=~/^javascript:/i) ||
+ ($link=~/^mailto:/i) ||
+ ($link=~/^\#/)) {
+ my $newlocation=&Apache::lonnet::hreflocation($thisdir,$link);
+ $output=~s/(\"|\'|\=\s*)\Q$link\E(\"|\'|\s|\>)/$1$newlocation$2/;
}
}
# -------------------------------------------------- Deal with Applet codebases
@@ -2285,7 +2536,7 @@ sub get_student_view {
if (defined($moreenv)) {
%form=(%form,%{$moreenv});
}
- if ($target eq 'tex') {$form{'grade_target'} = 'tex';}
+ if (defined($target)) { $form{'grade_target'} = $target; }
$feedurl=&Apache::lonnet::clutter($feedurl);
my $userview=&Apache::lonnet::ssi_body($feedurl,%form);
$userview=~s/\]*\>//gi;
@@ -2325,7 +2576,7 @@ sub get_student_answers {
=item * &submlink()
-Inputs: $text $uname $udom $symb
+Inputs: $text $uname $udom $symb $target
Returns: A link to grades.pm such as to see the SUBM view of a student
@@ -2333,15 +2584,64 @@ Returns: A link to grades.pm such as to
###############################################
sub submlink {
- my ($text,$uname,$udom,$symb)=@_;
+ my ($text,$uname,$udom,$symb,$target)=@_;
+ if (!($uname && $udom)) {
+ (my $cursymb, my $courseid,$udom,$uname)=
+ &Apache::lonxml::whichuser($symb);
+ if (!$symb) { $symb=$cursymb; }
+ }
+ if (!$symb) { $symb=&Apache::lonnet::symbread(); }
+ $symb=&escape($symb);
+ if ($target) { $target="target=\"$target\""; }
+ return ''.$text.' ';
+}
+##############################################
+
+=pod
+
+=item * &pgrdlink()
+
+Inputs: $text $uname $udom $symb $target
+
+Returns: A link to grades.pm such as to see the PGRD view of a student
+
+=cut
+
+###############################################
+sub pgrdlink {
+ my $link=&submlink(@_);
+ $link=~s/(&command=submission)/$1&showgrading=yes/;
+ return $link;
+}
+##############################################
+
+=pod
+
+=item * &pprmlink()
+
+Inputs: $text $uname $udom $symb $target
+
+Returns: A link to parmset.pm such as to see the PPRM view of a
+student and a specific resource
+
+=cut
+
+###############################################
+sub pprmlink {
+ my ($text,$uname,$udom,$symb,$target)=@_;
if (!($uname && $udom)) {
(my $cursymb, my $courseid,$udom,$uname)=
&Apache::lonxml::whichuser($symb);
if (!$symb) { $symb=$cursymb; }
}
- if (!$symb) { $symb=&symbread(); }
- return ''.$text.' ';
+ if (!$symb) { $symb=&Apache::lonnet::symbread(); }
+ $symb=&escape($symb);
+ if ($target) { $target="target=\"$target\""; }
+ return ''.$text.' ';
}
##############################################
@@ -2367,6 +2667,11 @@ sub timehash {
'dlsav' => $ltime[8] );
}
+sub utc_string {
+ my ($date)=@_;
+ return strftime("%Y%m%dT%H%M%SZ",gmtime($date));
+}
+
sub maketime {
my %th=@_;
return POSIX::mktime(
@@ -2377,11 +2682,17 @@ sub maketime {
#########################################
sub findallcourses {
- my %courses=();
+ my ($roles) = @_;
+ my %roles;
+ if (ref($roles)) { %roles = map { $_ => 1 } @{$roles}; }
+ my %courses;
my $now=time;
- foreach (keys %ENV) {
- if ($_=~/^user\.role\.\w+\.\/(\w+)\/(\w+)/) {
- my ($starttime,$endtime)=$ENV{$_};
+ foreach my $key (keys(%env)) {
+ if ( $key=~m{^user\.role\.(\w+)\./(\w+)/(\w+)} ) {
+ my ($role,$domain,$id) = ($1,$2,$3);
+ next if ($role eq 'ca' || $role eq 'aa');
+ next if (%roles && !exists($roles{$role}));
+ my ($starttime,$endtime)=split(/\./,$env{$key});
my $active=1;
if ($starttime) {
if ($now<$starttime) { $active=0; }
@@ -2389,10 +2700,10 @@ sub findallcourses {
if ($endtime) {
if ($now>$endtime) { $active=0; }
}
- if ($active) { $courses{$1.'_'.$2}=1; }
+ if ($active) { $courses{$domain.'_'.$id}=1; }
}
}
- return keys %courses;
+ return keys(%courses);
}
###############################################
@@ -2418,9 +2729,9 @@ sub determinedomain {
if (! $domain) {
# Determine domain if we have not been given one
$domain = $Apache::lonnet::perlvar{'lonDefDomain'};
- if ($ENV{'user.domain'}) { $domain=$ENV{'user.domain'}; }
- if ($ENV{'request.role.domain'}) {
- $domain=$ENV{'request.role.domain'};
+ if ($env{'user.domain'}) { $domain=$env{'user.domain'}; }
+ if ($env{'request.role.domain'}) {
+ $domain=$env{'request.role.domain'};
}
}
return $domain;
@@ -2462,10 +2773,11 @@ Returns: value of designparamter $which
=cut
+
##############################################
sub designparm {
my ($which,$domain)=@_;
- if ($ENV{'browser.blackwhite'} eq 'on') {
+ if ($env{'browser.blackwhite'} eq 'on') {
if ($which=~/\.(font|alink|vlink|link)$/) {
return '#000000';
}
@@ -2476,11 +2788,11 @@ sub designparm {
return '#CCCCCC';
}
}
- if ($ENV{'environment.color.'.$which}) {
- return $ENV{'environment.color.'.$which};
+ if (exists($env{'environment.color.'.$which})) {
+ return $env{'environment.color.'.$which};
}
$domain=&determinedomain($domain);
- if ($designhash{$domain.'.'.$which}) {
+ if (exists($designhash{$domain.'.'.$which})) {
return $designhash{$domain.'.'.$which};
} else {
return $designhash{'default.'.$which};
@@ -2519,6 +2831,20 @@ Inputs:
=item * $forcereg, if page should register as content page (relevant for
text interface only)
+=item * $customtitle, alternate text to use instead of $title
+ in the title box that appears, this text
+ is not auto translated like the $title is
+
+=item * $notopbar, if true, keep the 'what is this' info but remove the
+ navigational links
+
+=item * $bgcolor, used to override the bgcolor on a webpage to a specific value
+
+=item * $notitle, if true keep the nav controls, but remove the title bar
+
+=item * $no_inline_link, if true and in remote mode, don't show the
+ 'Switch To Inline Menu' link
+
=back
Returns: A uniform header for LON-CAPA web pages.
@@ -2529,138 +2855,1207 @@ other decorations will be returned.
=cut
sub bodytag {
- my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,$customtitle)=@_;
+ my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,$customtitle,
+ $notopbar,$bgcolor,$notitle,$no_inline_link)=@_;
+
$title=&mt($title);
+
$function = &get_users_function() if (!$function);
- my $img=&designparm($function.'.img',$domain);
- my $pgbg=&designparm($function.'.pgbg',$domain);
- my $tabbg=&designparm($function.'.tabbg',$domain);
- my $font=&designparm($function.'.font',$domain);
- my $link=&designparm($function.'.link',$domain);
- my $alink=&designparm($function.'.alink',$domain);
- my $vlink=&designparm($function.'.vlink',$domain);
- my $sidebg=&designparm($function.'.sidebg',$domain);
-# Accessibility font enhance
- unless ($addentries) { $addentries=''; }
- my $addstyle='';
- if ($ENV{'browser.fontenhance'} eq 'on') {
- $addstyle=' font-size: x-large;';
- }
+ my $img = &designparm($function.'.img',$domain);
+ my $font = &designparm($function.'.font',$domain);
+ my $pgbg = $bgcolor || &designparm($function.'.pgbg',$domain);
+
+ my %design = ( 'style' => 'margin-top: 0px',
+ 'bgcolor' => $pgbg,
+ 'text' => $font,
+ 'alink' => &designparm($function.'.alink',$domain),
+ 'vlink' => &designparm($function.'.vlink',$domain),
+ 'link' => &designparm($function.'.link',$domain),);
+ @$addentries{keys(%design)} = @design{keys(%design)};
+
# role and realm
- my ($role,$realm)
- =&Apache::lonnet::plaintext((split(/\./,$ENV{'request.role'}))[0]);
+ my ($role,$realm) = split(/\./,$env{'request.role'},2);
+ if ($role eq 'ca') {
+ my ($rdom,$rname) = ($realm =~ m-^/(\w+)/(\w+)$-);
+ $realm = &plainname($rname,$rdom).':'.$rdom;
+ }
# realm
- if ($ENV{'request.course.id'}) {
- $realm=
- $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
+ if ($env{'request.course.id'}) {
+ if ($env{'request.role'} !~ /^cr/) {
+ $role = &Apache::lonnet::plaintext($role,&course_type());
+ }
+ $realm = $env{'course.'.$env{'request.course.id'}.'.description'};
+ } else {
+ $role = &Apache::lonnet::plaintext($role);
}
- unless ($realm) { $realm=' '; }
+
+ if (!$realm) { $realm=' '; }
# Set messages
my $messages=&domainlogo($domain);
# Port for miniserver
my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
+
+ my $extra_body_attr = &make_attr_string($forcereg,$addentries);
+
# construct main body tag
- my $bodytag = <
-h1, h2, h3, th { font-family: Arial, Helvetica, sans-serif }
-a:focus { color: red; background: yellow }
-
-
-END
- my $upperleft=' ';
- if ($bodyonly) {
+ my $bodytag = "".
+ &Apache::lontexconvert::init_math_support();
+
+ if ($bodyonly
+ || ($env{'request.state'} eq 'construct'
+ && $env{'environment.remote'} ne 'off' )) {
return $bodytag;
- } elsif ($ENV{'browser.interface'} eq 'textual') {
+ } elsif ($env{'browser.interface'} eq 'textual') {
# Accessibility
- return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
- $forcereg).
- 'LON-CAPA: '.$title.' ';
- } elsif ($ENV{'environment.remote'} eq 'off') {
-# No Remote
- my $roleinfo=(<
-
- $ENV{'environment.firstname'}
- $ENV{'environment.middlename'}
- $ENV{'environment.lastname'}
- $ENV{'environment.generation'}
-
-
-$role
-
-$realm
+ $bodytag.=&Apache::lonmenu::menubuttons($forcereg,$forcereg);
+ if (!$notitle) {
+ $bodytag.='LON-CAPA: '.$title.' ';
+ }
+ return $bodytag;
+ }
+
+ my $name = &plainname($env{'user.name'},$env{'user.domain'});
+ if ($env{'user.name'} eq 'public' && $env{'user.domain'} eq 'public') {
+ undef($role);
+ } else {
+ $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
+ }
+
+ my $roleinfo=(<
+
+ $name
+
+
+
+$role
+
+
+$realm
+
ENDROLE
- my $titleinfo = ''.$title.' ';
- if ($customtitle) {
- $titleinfo = $customtitle;
- }
- if ($ENV{'request.state'} eq 'construct') {
+
+ my $titleinfo = ''.$title.' ';
+ if ($customtitle) {
+ $titleinfo = $customtitle;
+ }
+ #
+ # Extra info if you are the DC
+ my $dc_info = '';
+ if ($env{'user.adv'} && exists($env{'user.role.dc./'.
+ $env{'course.'.$env{'request.course.id'}.
+ '.domain'}.'/'})) {
+ my $cid = $env{'request.course.id'};
+ $dc_info.= $cid.' '.$env{'course.'.$cid.'.internal.coursecode'};
+ $dc_info =~ s/\s+$//;
+ $dc_info = '('.$dc_info.')';
+ }
+
+ if ($env{'environment.remote'} eq 'off') {
+ # No Remote
+ if ($env{'request.state'} eq 'construct') {
+ $forcereg=1;
+ }
+
+ if (!$customtitle && $env{'request.state'} eq 'construct') {
+ # this is for resources; directories have customtitle, and crumbs
+ # and select recent are created in lonpubdir.pm
my ($uname,$thisdisfn)=
- ($ENV{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);
+ ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);
my $formaction='/priv/'.$uname.'/'.$thisdisfn;
$formaction=~s/\/+/\//g;
- $titleinfo = ''
.&Apache::lonmenu::constspaceform();
+ }
- &Apache::lonhtmlcommon::store_recent('construct',$formaction,$formaction);
- if ($thisdisfn!~m|/$|) { $forcereg=1; }
+ my $titletable;
+ if (!$notitle) {
+ $titletable =
+ ''.
+ " $titleinfo $dc_info ".$roleinfo.
+ '
';
}
-
- return $bodytag.&Apache::lonmenu::menubuttons($forcereg,'web',
- $forcereg).
- ''.$titleinfo.' '.$roleinfo.'
';
+ if ($notopbar) {
+ $bodytag .= $titletable;
+ } else {
+ if ($env{'request.state'} eq 'construct') {
+ $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg,
+ $titletable);
+ } else {
+ $bodytag .= &Apache::lonmenu::menubuttons($forcereg,$forcereg).
+ $titletable;
+ }
+ }
+ return $bodytag;
}
#
# Top frame rendering, Remote is up
#
- my $titleinfo = ' '.$title.' ';
- if ($customtitle) {
- $titleinfo = $customtitle;
+
+ my $upperleft=' ';
+
+ # Explicit link to get inline menu
+ my $menu= ($no_inline_link?''
+ :''.&mt('Switch to Inline Menu Mode').' ');
+ #
+ if ($notitle) {
+ return $bodytag;
}
return(<
-
-$upperleft
-$messages
+
+$upperleft
+ $messages
-
-
-$titleinfo
-
-
- $ENV{'environment.firstname'}
- $ENV{'environment.middlename'}
- $ENV{'environment.lastname'}
- $ENV{'environment.generation'}
-
-
+ $titleinfo $dc_info $menu
+$roleinfo
-
-$role
-
-
-$realm
-
+
ENDBODY
}
+sub make_attr_string {
+ my ($register,$attr_ref) = @_;
+
+ if ($attr_ref && !ref($attr_ref)) {
+ die("addentries Must be a hash ref ".
+ join(':',caller(1))." ".
+ join(':',caller(0))." ");
+ }
+
+ if ($register) {
+ my ($on_load,$on_unload);
+ foreach my $key (keys(%{$attr_ref})) {
+ if (lc($key) eq 'onload') {
+ $on_load.=$attr_ref->{$key}.';';
+ delete($attr_ref->{$key});
+
+ } elsif (lc($key) eq 'onunload') {
+ $on_unload.=$attr_ref->{$key}.';';
+ delete($attr_ref->{$key});
+ }
+ }
+ $attr_ref->{'onload'} =
+ &Apache::lonmenu::loadevents(). $on_load;
+ $attr_ref->{'onunload'}=
+ &Apache::lonmenu::unloadevents().$on_unload;
+ }
+
+# Accessibility font enhance
+ if ($env{'browser.fontenhance'} eq 'on') {
+ my $style;
+ foreach my $key (keys(%{$attr_ref})) {
+ if (lc($key) eq 'style') {
+ $style.=$attr_ref->{$key}.';';
+ delete($attr_ref->{$key});
+ }
+ }
+ $attr_ref->{'style'}=$style.'; font-size: x-large;';
+ }
+
+ if ($env{'browser.blackwhite'} eq 'on') {
+ delete($attr_ref->{'font'});
+ delete($attr_ref->{'link'});
+ delete($attr_ref->{'alink'});
+ delete($attr_ref->{'vlink'});
+ delete($attr_ref->{'bgcolor'});
+ delete($attr_ref->{'background'});
+ }
+
+ my $attr_string;
+ foreach my $attr (keys(%$attr_ref)) {
+ $attr_string .= " $attr=\"".$attr_ref->{$attr}.'" ';
+ }
+ return $attr_string;
+}
+
+
+###############################################
###############################################
=pod
-=item get_users_function
+=back
+
+=head1 HTML Helpers
+
+=over 4
+
+=item * &endbodytag()
+
+Returns a uniform footer for LON-CAPA web pages.
+
+Inputs: none
+
+=back
+
+=cut
+
+sub endbodytag {
+ my $endbodytag='';
+ $endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
+ if ( exists( $env{'internal.head.redirect'} ) ) {
+ $endbodytag=
+ "".
+ &mt('Continue').' '.
+ $endbodytag;
+ }
+ return $endbodytag;
+}
+
+=pod
+
+=over 4
+
+=item * &standard_css()
+
+Returns a style sheet
+
+Inputs: (all optional)
+ domain -> force to color decorate a page for a specific
+ domain
+ function -> force usage of a specific rolish color scheme
+ bgcolor -> override the default page bgcolor
+
+=back
+
+=cut
+
+sub standard_css {
+ my ($function,$domain,$bgcolor) = @_;
+ $function = &get_users_function() if (!$function);
+ my $img = &designparm($function.'.img', $domain);
+ my $tabbg = &designparm($function.'.tabbg', $domain);
+ my $font = &designparm($function.'.font', $domain);
+ my $sidebg = &designparm($function.'.sidebg',$domain);
+ my $pgbg_or_bgcolor =
+ $bgcolor ||
+ &designparm($function.'.pgbg', $domain);
+ my $pgbg = &designparm($function.'.pgbg', $domain);
+ my $alink = &designparm($function.'.alink', $domain);
+ my $vlink = &designparm($function.'.vlink', $domain);
+ my $link = &designparm($function.'.link', $domain);
+
+ my $sans = 'Arial,Helvetica,sans-serif';
+ my $mono = 'monospace';
+ my $data_table_head = $tabbg;
+ my $data_table_light = '#EEEEEE';
+ my $data_table_dark = '#DDD';
+ my $data_table_darker = '#CCC';
+ my $data_table_highlight = '#FFFF00';
+ my $mail_new = '#FFBB77';
+ my $mail_new_hover = '#DD9955';
+ my $mail_read = '#BBBB77';
+ my $mail_read_hover = '#999944';
+ my $mail_replied = '#AAAA88';
+ my $mail_replied_hover = '#888855';
+ my $mail_other = '#99BBBB';
+ my $mail_other_hover = '#669999';
+ my $table_header = '#DDDDDD';
+
+ my $border = ($env{'browser.type'} eq 'explorer') ? '0px 2px 0px 2px'
+ : '0px 3px 0px 4px';
+ return <
+ $args - optional arguments
+ force_register - if is true call registerurl so the remote is
+ informed
+ redirect -> array ref of
+ 1- seconds before redirect occurs
+ 2- url to redirect to
+ 3- whether the side effect should occur
+ (side effect of setting
+ $env{'internal.head.redirect'} to the url
+ redirected too)
+ domain -> force to color decorate a page for a specific
+ domain
+ function -> force usage of a specific rolish color scheme
+ bgcolor -> override the default page bgcolor
+
+=back
+
+=cut
+
+sub headtag {
+ my ($title,$head_extra,$args) = @_;
+
+ my $function = $args->{'function'} || &get_users_function();
+ my $domain = $args->{'domain'} || &determinedomain();
+ my $bgcolor = $args->{'bgcolor'} || &designparm($function.'.pgbg',$domain);
+ my $url = join(':',$env{'user.name'},$env{'user.domain'},
+ #time(),
+ $env{'environment.color.timestamp'},
+ $function,$domain,$bgcolor);
+
+ $url = '/adm/css/'.&escape($url).'.css';
+
+ my $result =
+ ''.
+ &font_settings().
+ &Apache::lonhtmlcommon::htmlareaheaders();
+
+ if ($args->{'force_register'}) {
+ $result .= &Apache::lonmenu::registerurl(1);
+ }
+
+ if (ref($args->{'redirect'})) {
+ my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}};
+ $url = &Apache::lonenc::check_encrypt($url);
+ if (!$inhibit_continue) {
+ $env{'internal.head.redirect'} = $url;
+ }
+ $result.=<
+
+ADDMETA
+ }
+ if (!defined($title)) {
+ $title = 'The LearningOnline Network with CAPA';
+ }
+
+ $result .= ' LON-CAPA '.&mt($title).' '
+ .' '
+ .$head_extra;
+ return $result;
+}
+
+=pod
+
+=over 4
+
+=item * &font_settings()
+
+Returns neccessary to set the proper encoding
+
+Inputs: none
+
+=back
+
+=cut
+
+sub font_settings {
+ my $headerstring='';
+ if (($env{'browser.os'} eq 'mac') && (!$env{'browser.mathml'})) {
+ $headerstring.=
+ ' ';
+ } elsif (!$env{'browser.mathml'} && $env{'browser.unicode'}) {
+ $headerstring.=
+ ' ';
+ }
+ return $headerstring;
+}
+
+=pod
+
+=over 4
+
+=item * &xml_begin()
+
+Returns the needed doctype and
+
+Inputs: none
+
+=back
+
+=cut
+
+sub xml_begin {
+ my $output='';
+
+ &Apache::lonhtmlcommon::init_htmlareafields();
+
+ if ($env{'browser.mathml'}) {
+ $output=''
+ #.''."\n"
+# .'] >'
+ .''
+ .'';
+ } else {
+ $output='';
+ }
+ return $output;
+}
+
+=pod
+
+=over 4
+
+=item * &endheadtag()
+
+Returns a uniform for LON-CAPA web pages.
+
+Inputs: none
+
+=back
+
+=cut
+
+sub endheadtag {
+ return '';
+}
+
+=pod
+
+=over 4
+
+=item * &head()
+
+Returns a uniform complete .. section for LON-CAPA web pages.
+
+Inputs: $title - optional title for the page
+ $head_extra - optional extra HTML to put inside the
+
+=back
+
+=cut
+
+sub head {
+ my ($title,$head_extra,$args) = @_;
+ return &headtag($title,$head_extra,$args).&endheadtag();
+}
+
+=pod
+
+=over 4
+
+=item * &start_page()
+
+Returns a complete .. section for LON-CAPA web pages.
+
+Inputs: $title - optional title for the page
+ $head_extra - optional extra HTML to incude inside the
+ $args - additional optional args supported are:
+ only_body -> is true will set &bodytag() onlybodytag
+ arg on
+ no_nav_bar -> is true will set &bodytag() notopbar arg on
+ add_entries -> additional attributes to add to the
+ domain -> force to color decorate a page for a
+ specific domain
+ function -> force usage of a specific rolish color
+ scheme
+ redirect -> see &headtag()
+ bgcolor -> override the default page bg color
+ js_ready -> return a string ready for being used in
+ a javascript writeln
+ html_encode -> return a string ready for being used in
+ a html attribute
+ force_register -> if is true will turn on the &bodytag()
+ $forcereg arg
+ body_title -> alternate text to use instead of $title
+ in the title box that appears, this text
+ is not auto translated like the $title is
+ frameset -> if true will start with a
+ rather than
+ no_title -> if true the title bar won't be shown
+ skip_phases -> hash ref of
+ head -> skip the generation
+ body -> skip all generation
+
+ no_inline_link -> if true and in remote mode, don't show the
+ 'Switch To Inline Menu' link
+
+=back
+
+=cut
+
+sub start_page {
+ my ($title,$head_extra,$args) = @_;
+ #&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
+ my %head_args;
+ foreach my $arg ('redirect','force_register','domain','function',
+ 'bgcolor') {
+ if (defined($args->{$arg})) {
+ $head_args{$arg} = $args->{$arg};
+ }
+ }
+
+ $env{'internal.start_page'}++;
+ my $result;
+ if (! exists($args->{'skip_phases'}{'head'}) ) {
+ $result.=
+ &xml_begin().
+ &headtag($title,$head_extra,\%head_args).&endheadtag();
+ }
+
+ if (! exists($args->{'skip_phases'}{'body'}) ) {
+ if ($args->{'frameset'}) {
+ my $attr_string = &make_attr_string($args->{'force_register'},
+ $args->{'add_entries'});
+ $result .= "\n\n";
+ } else {
+ $result .=
+ &bodytag($title,
+ $args->{'function'}, $args->{'add_entries'},
+ $args->{'only_body'}, $args->{'domain'},
+ $args->{'force_register'}, $args->{'body_title'},
+ $args->{'no_nav_bar'}, $args->{'bgcolor'},
+ $args->{'no_title'}, $args->{'no_inline_link'});
+ }
+ }
+
+ if ($args->{'js_ready'}) {
+ $result = &js_ready($result);
+ }
+ if ($args->{'html_encode'}) {
+ $result = &html_encode($result);
+ }
+ return $result;
+}
+
+
+=pod
+
+=over 4
+
+=item * &head()
+
+Returns a complete section for LON-CAPA web pages.
+
+Inputs: $args - additional optional args supported are:
+ js_ready -> return a string ready for being used in
+ a javascript writeln
+ html_encode -> return a string ready for being used in
+ a html attribute
+ frameset -> if true will start with a
+ rather than
+
+=cut
+
+sub end_page {
+ my ($args) = @_;
+ $env{'internal.end_page'}++;
+ my $result;
+ if ($args->{'discussion'}) {
+ my ($target,$parser);
+ if (ref($args->{'discussion'})) {
+ ($target,$parser) =($args->{'discussion'}{'target'},
+ $args->{'discussion'}{'parser'});
+ }
+ $result .= &Apache::lonxml::xmlend($target,$parser);
+ }
+
+ if ($args->{'frameset'}) {
+ $result .= ' ';
+ } else {
+ $result .= &endbodytag();
+ }
+ $result .= "\n";
+
+ if ($args->{'js_ready'}) {
+ $result = &js_ready($result);
+ }
+
+ if ($args->{'html_encode'}) {
+ $result = &html_encode($result);
+ }
+
+ return $result;
+}
+
+sub html_encode {
+ my ($result) = @_;
+
+ $result = &HTML::Entities::encode($result,'<>&"');
+
+ return $result;
+}
+sub js_ready {
+ my ($result) = @_;
+
+ $result =~ s/[\n\r]/ /xmsg;
+ $result =~ s/\\/\\\\/xmsg;
+ $result =~ s/'/\\'/xmsg;
+ $result =~ s{}{<\\/}xmsg;
+
+ return $result;
+}
+
+sub validate_page {
+ if ( exists($env{'internal.start_page'})
+ && $env{'internal.start_page'} > 1) {
+ &Apache::lonnet::logthis('start_page called multiple times '.
+ $env{'internal.start_page'}.' '.
+ $ENV{'request.filename'});
+ }
+ if ( exists($env{'internal.end_page'})
+ && $env{'internal.end_page'} > 1) {
+ &Apache::lonnet::logthis('end_page called multiple times '.
+ $env{'internal.end_page'}.' '.
+ $env{'request.filename'});
+ }
+ if ( exists($env{'internal.start_page'})
+ && ! exists($env{'internal.end_page'})) {
+ &Apache::lonnet::logthis('start_page called without end_page '.
+ $env{'request.filename'});
+ }
+ if ( ! exists($env{'internal.start_page'})
+ && exists($env{'internal.end_page'})) {
+ &Apache::lonnet::logthis('end_page called without start_page'.
+ $env{'request.filename'});
+ }
+}
+
+sub simple_error_page {
+ my ($r,$title,$msg) = @_;
+ my $page =
+ &Apache::loncommon::start_page($title).
+ &mt($msg).
+ &Apache::loncommon::end_page();
+ if (ref($r)) {
+ $r->print($page);
+ return;
+ }
+ return $page;
+}
+
+{
+ my $row_count;
+ sub start_data_table {
+ my ($add_class) = @_;
+ my $css_class = (join(' ','LC_data_table',$add_class));
+ undef($row_count);
+ return ''."\n";
+ }
+
+ sub end_data_table {
+ undef($row_count);
+ return '
'."\n";;
+ }
+
+ sub start_data_table_row {
+ my ($add_class) = @_;
+ $row_count++;
+ my $css_class = ($row_count % 2)?'':'LC_even_row';
+ $css_class = (join(' ',$css_class,$add_class));
+ return ''."\n";;
+ }
+
+ sub end_data_table_row {
+ return ' '."\n";;
+ }
+
+ sub start_data_table_empty_row {
+ $row_count++;
+ return ''."\n";;
+ }
+
+ sub end_data_table_empty_row {
+ return ' '."\n";;
+ }
+
+ sub start_data_table_header_row {
+ return ''."\n";;
+ }
+}
+
+###############################################
+
+=pod
+
+=item * &get_users_function()
Used by &bodytag to determine the current users primary role.
Returns either 'student','coordinator','admin', or 'author'.
@@ -2670,13 +4065,13 @@ Returns either 'student','coordinator','
###############################################
sub get_users_function {
my $function = 'student';
- if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {
+ if ($env{'request.role'}=~/^(cc|in|ta|ep)/) {
$function='coordinator';
}
- if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {
+ if ($env{'request.role'}=~/^(su|dc|ad|li)/) {
$function='admin';
}
- if (($ENV{'request.role'}=~/^(au|ca)/) ||
+ if (($env{'request.role'}=~/^(au|ca)/) ||
($ENV{'REQUEST_URI'}=~/^(\/priv|\~)/)) {
$function='author';
}
@@ -2687,169 +4082,401 @@ sub get_users_function {
=pod
-=item get_sections
+=item * &check_user_status
+
+Determines current status of supplied role for a
+specific user. Roles can be active, previous or future.
+
+Inputs:
+user's domain, user's username, course's domain,
+course's number, optional section ID.
+
+Outputs:
+role status: active, previous or future.
+
+=cut
+
+sub check_user_status {
+ my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
+ my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
+ my @uroles = keys %userinfo;
+ my $srchstr;
+ my $active_chk = 'none';
+ my $now = time;
+ if (@uroles > 0) {
+ if (($role eq 'cc') || ($sec eq '') || (!defined($sec))) {
+ $srchstr = '/'.$cdom.'/'.$crs.'_'.$role;
+ } else {
+ $srchstr = '/'.$cdom.'/'.$crs.'/'.$sec.'_'.$role;
+ }
+ if (grep/^\Q$srchstr\E$/,@uroles) {
+ my $role_end = 0;
+ my $role_start = 0;
+ $active_chk = 'active';
+ if ($userinfo{$srchstr} =~ m/^\Q$role\E_(\d+)/) {
+ $role_end = $1;
+ if ($userinfo{$srchstr} =~ m/^\Q$role\E_\Q$role_end\E_(\d+)$/) {
+ $role_start = $1;
+ }
+ }
+ if ($role_start > 0) {
+ if ($now < $role_start) {
+ $active_chk = 'future';
+ }
+ }
+ if ($role_end > 0) {
+ if ($now > $role_end) {
+ $active_chk = 'previous';
+ }
+ }
+ }
+ }
+ return $active_chk;
+}
+
+###############################################
+
+=pod
+
+=item * &get_sections()
Determines all the sections for a course including
sections with students and sections containing other roles.
-Incoming parameters: domain, course number, reference to
-section hash (keys to be section/group IDs), reference to
-array containing roles for which sections should be gathered
-(optional). If the fourth argument is undefined, sections
-are gathered for any role.
+Incoming parameters:
+
+1. domain
+2. course number
+3. reference to array containing roles for which sections should
+be gathered (optional).
+4. reference to array containing status types for which sections
+should be gathered (optional).
+
+If the third argument is undefined, sections are gathered for any role.
+If the fourth argument is undefined, sections are gathered for any status.
+Permissible values are 'active' or 'future' or 'previous'.
-Returns number of sections.
+Returns section hash (keys are section IDs, values are
+number of users in each section), subject to the
+optional roles filter, optional status filter
=cut
###############################################
sub get_sections {
- my ($cdom,$cnum,$sectioncount,$possible_roles) = @_;
- my $cid = $cdom.'_'.$cnum;
- my $numsections = 0;
- if ($cdom && $cnum) {
- if (!defined($possible_roles) || (grep/^st$/,@$possible_roles)) {
- my ($classlist) = &Apache::loncoursedata::get_classlist($cid,$cdom,$cnum);
- my $sec_index = &Apache::loncoursedata::CL_SECTION();
- my $status_index = &Apache::loncoursedata::CL_STATUS();
- while (my ($student,$data) = each %$classlist) {
- my ($section,$status) = ($data->[$sec_index],
- $data->[$status_index]);
- unless ($section eq '' || $section =~ /^\s*$/) {
- if (!defined($$sectioncount{$section})) {
- $$sectioncount{$section} = 1;
- $numsections ++;
- } else {
- $$sectioncount{$section} ++;
+ my ($cdom,$cnum,$possible_roles,$possible_status) = @_;
+ if (!defined($cdom) || !defined($cnum)) {
+ my $cid = $env{'request.course.id'};
+
+ return if (!defined($cid));
+
+ $cdom = $env{'course.'.$cid.'.domain'};
+ $cnum = $env{'course.'.$cid.'.num'};
+ }
+
+ my %sectioncount;
+ my $now = time;
+
+ if (!defined($possible_roles) || (grep(/^st$/,@$possible_roles))) {
+ my ($classlist) = &Apache::loncoursedata::get_classlist($cdom,$cnum);
+ my $sec_index = &Apache::loncoursedata::CL_SECTION();
+ my $status_index = &Apache::loncoursedata::CL_STATUS();
+ my $start_index = &Apache::loncoursedata::CL_START();
+ my $end_index = &Apache::loncoursedata::CL_END();
+ my $status;
+ while (my ($student,$data) = each(%$classlist)) {
+ my ($section,$stu_status,$start,$end) = ($data->[$sec_index],
+ $data->[$status_index],
+ $data->[$start_index],
+ $data->[$end_index]);
+ if ($stu_status eq 'Active') {
+ $status = 'active';
+ } elsif ($end < $now) {
+ $status = 'previous';
+ } elsif ($start > $now) {
+ $status = 'future';
+ }
+ if ($section ne '-1' && $section !~ /^\s*$/) {
+ if ((!defined($possible_status)) || (($status ne '') &&
+ (grep/^\Q$status\E$/,@{$possible_status}))) {
+ $sectioncount{$section}++;
+ }
+ }
+ }
+ }
+ my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
+ foreach my $user (sort(keys(%courseroles))) {
+ if ($user !~ /^(\w{2})/) { next; }
+ my ($role) = ($user =~ /^(\w{2})/);
+ if ($possible_roles && !(grep(/^$role$/,@$possible_roles))) { next; }
+ my ($section,$status);
+ if ($role eq 'cr' &&
+ $user =~ m-^$role/[^/]*/[^/]*/[^/]*:[^:]*:[^:]*:(\w+)-) {
+ $section=$1;
+ }
+ if ($user =~ /^$role:[^:]*:[^:]*:(\w+)/) { $section=$1; }
+ if (!defined($section) || $section eq '-1') { next; }
+ my ($end,$start) = ($courseroles{$user} =~ /^([^:]*):([^:]*)$/);
+ if ($end == -1 && $start == -1) {
+ next; #deleted role
+ }
+ if (!defined($possible_status)) {
+ $sectioncount{$section}++;
+ } else {
+ if ((!$end || $end >= $now) && (!$start || $start <= $now)) {
+ $status = 'active';
+ } elsif ($end < $now) {
+ $status = 'future';
+ } elsif ($start > $now) {
+ $status = 'previous';
+ }
+ if (($status ne '') && (grep/^\Q$status\E$/,@{$possible_status})) {
+ $sectioncount{$section}++;
+ }
+ }
+ }
+ return %sectioncount;
+}
+
+###############################################
+
+=pod
+
+=item * &get_course_users()
+
+Retrieves usernames:domains for users in the specified course
+with specific role(s), and access status.
+
+Incoming parameters:
+1. course domain
+2. course number
+3. access status: users must have - either active,
+previous, future, or all.
+4. reference to array of permissible roles
+5. reference to array of section restrictions (optional)
+6. reference to results object (hash of hashes).
+7. reference to optional userdata hash
+Keys of top level hash are roles.
+Keys of inner hashes are username:domain, with
+values set to access type.
+Optional userdata hash returns an array with arguments in the
+same order as loncoursedata::get_classlist() for student data.
+
+Entries for end, start, section and status are blank because
+of the possibility of multiple values for non-student roles.
+
+=cut
+
+###############################################
+
+sub get_course_users {
+ my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata) = @_;
+ my %idx = ();
+ my %seclists;
+
+ $idx{udom} = &Apache::loncoursedata::CL_SDOM();
+ $idx{uname} = &Apache::loncoursedata::CL_SNAME();
+ $idx{end} = &Apache::loncoursedata::CL_END();
+ $idx{start} = &Apache::loncoursedata::CL_START();
+ $idx{id} = &Apache::loncoursedata::CL_ID();
+ $idx{section} = &Apache::loncoursedata::CL_SECTION();
+ $idx{fullname} = &Apache::loncoursedata::CL_FULLNAME();
+ $idx{status} = &Apache::loncoursedata::CL_STATUS();
+
+ if (grep(/^st$/,@{$roles})) {
+ my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist($cdom,$cnum);
+ my $now = time;
+ foreach my $student (keys(%{$classlist})) {
+ my $match = 0;
+ my $secmatch = 0;
+ my $section = $$classlist{$student}[$idx{section}];
+ if ($section eq '') {
+ $section = 'none';
+ }
+ if ((ref($sections) eq 'ARRAY') && (@{$sections} > 0)) {
+ if (grep(/^all$/,@{$sections})) {
+ $secmatch = 1;
+ } elsif ($$classlist{$student}[$idx{section}] eq '') {
+ if (grep(/^none$/,@{$sections})) {
+ $secmatch = 1;
+ }
+ } else {
+ if (grep(/^\Q$section\E$/,@{$sections})) {
+ $secmatch = 1;
}
+ }
+ if (!$secmatch) {
+ next;
}
}
+ push(@{$seclists{$student}},$section);
+ if (defined($$types{'active'})) {
+ if ($$classlist{$student}[$idx{status}] eq 'Active') {
+ push(@{$$users{st}{$student}},'active');
+ $match = 1;
+ }
+ }
+ if (defined($$types{'previous'})) {
+ if ($$classlist{$student}[$idx{end}] <= $now) {
+ push(@{$$users{st}{$student}},'previous');
+ $match = 1;
+ }
+ }
+ if (defined($$types{'future'})) {
+ if (($$classlist{$student}[$idx{start}] > $now) && ($$classlist{$student}[$idx{end}] > $now) || ($$classlist{$student}[$idx{end}] == 0) || ($$classlist{$student}[$idx{end}] eq '')) {
+ push(@{$$users{st}{$student}},'future');
+ $match = 1;
+ }
+ }
+ if ($match && ref($userdata) eq 'HASH') {
+ $$userdata{$student} = $$classlist{$student};
+ }
}
- my %courseroles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
- foreach my $user (sort keys %courseroles) {
- if ($user =~ /^(\w{2})/) {
- my $role = $1;
- if (!defined($possible_roles) || (grep/^$role$/,@$possible_roles)) {
- if ($role eq 'cr') {
- if ($user =~ m-^$role/[^/]*/[^/]*/[^/]*:[^:]*:[^:]*:(\w+)-) {
- if (!defined($$sectioncount{$1})) {
- $$sectioncount{$1} = 1;
- $numsections ++;
- } else {
- $$sectioncount{$1} ++;
+ }
+ if ((@{$roles} > 1) || ((@{$roles} == 1) && ($$roles[0] ne "st"))) {
+ my @coursepersonnel = &Apache::lonnet::getkeys('nohist_userroles',$cdom,$cnum);
+ foreach my $person (@coursepersonnel) {
+ my $match = 0;
+ my $secmatch = 0;
+ my ($role,$user,$usec) = ($person =~ /^([^:]*):([^:]+:[^:]+):([^:]*)/);
+ $user =~ s/:$//;
+ if (($role) && (grep(/^\Q$role\E$/,@{$roles}))) {
+ my ($uname,$udom) = split(/:/,$user);
+ if ((ref($sections) eq 'ARRAY') && (@{$sections} > 0)) {
+ if (grep(/^all$/,@{$sections})) {
+ $secmatch = 1;
+ } elsif ($usec eq '') {
+ if (grep(/^none$/,@{$sections})) {
+ $secmatch = 1;
+ }
+ } else {
+ if (grep(/^\Q$usec\E$/,@{$sections})) {
+ $secmatch = 1;
+ }
+ }
+ if (!$secmatch) {
+ next;
+ }
+ }
+ if ($usec eq '') {
+ $usec = 'none';
+ }
+ if ($uname ne '' && $udom ne '') {
+ my $status = &check_user_status($udom,$uname,$cdom,$cnum,$role,
+ $usec);
+ foreach my $type (keys(%{$types})) {
+ if ($status eq $type) {
+ if (!grep(/^\Q$type\E$/,@{$$users{$role}{$user}})) {
+ push(@{$$users{$role}{$user}},$type);
}
+ $match = 1;
}
}
- if ($user =~ /^$role:[^:]*:[^:]*:(\w+)/) {
- if (!defined($$sectioncount{$1})) {
- $$sectioncount{$1} = 1;
- $numsections ++;
- } else {
- $$sectioncount{$1} ++;
+ if (($match) && (ref($userdata) eq 'HASH')) {
+ if (!exists($$userdata{$uname.':'.$udom})) {
+ &get_user_info($udom,$uname,\%idx,$userdata);
+ }
+ if (!grep(/^\Q$usec\E$/,@{$seclists{$uname.':'.$udom}})) {
+ push(@{$seclists{$uname.':'.$udom}},$usec);
}
}
}
}
}
+ if (grep(/^ow$/,@{$roles})) {
+ if ((defined($cdom)) && (defined($cnum))) {
+ my %csettings = &Apache::lonnet::get('environment',['internal.courseowner'],$cdom,$cnum);
+ if ( defined($csettings{'internal.courseowner'}) ) {
+ my $owner = $csettings{'internal.courseowner'};
+ @{$$users{'ow'}{$owner.':'.$cdom}} = 'any';
+ if (defined($userdata) &&
+ !exists($$userdata{$owner.':'.$cdom})) {
+ &get_user_info($cdom,$owner,\%idx,$userdata);
+ if (!grep(/^none$/,@{$seclists{$owner.':'.$cdom}})) {
+ push(@{$seclists{$owner.':'.$cdom}},'none');
+ }
+ }
+ }
+ }
+ }
+ foreach my $user (keys(%seclists)) {
+ @{$seclists{$user}} = (sort {$a <=> $b} @{$seclists{$user}});
+ $$userdata{$user}[$idx{section}] = join(',',@{$seclists{$user}});
+ }
}
- return $numsections;
+ return;
}
+sub get_user_info {
+ my ($udom,$uname,$idx,$userdata) = @_;
+ $$userdata{$uname.':'.$udom}[$$idx{fullname}] =
+ &plainname($uname,$udom,'lastname');
+ $$userdata{$uname.':'.$udom}[$$idx{uname}] = $uname;
+ $$userdata{$uname.':'.$udom}[$$idx{udom}] = $udom;
+ return;
+}
-sub get_posted_cgi {
- my $r=shift;
-
- my $buffer;
-
- $r->read($buffer,$r->header_in('Content-length'),0);
- unless ($buffer=~/^(\-+\w+)\s+Content\-Disposition\:\s*form\-data/si) {
- my @pairs=split(/&/,$buffer);
- my $pair;
- foreach $pair (@pairs) {
- my ($name,$value) = split(/=/,$pair);
- $value =~ tr/+/ /;
- $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
- $name =~ tr/+/ /;
- $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
- &add_to_env("form.$name",$value);
- }
- } else {
- my $contentsep=$1;
- my @lines = split (/\n/,$buffer);
- my $name='';
- my $value='';
- my $fname='';
- my $fmime='';
- my $i;
- for ($i=0;$i<=$#lines;$i++) {
- if ($lines[$i]=~/^$contentsep/) {
- if ($name) {
- chomp($value);
- if ($fname) {
- $ENV{"form.$name.filename"}=$fname;
- $ENV{"form.$name.mimetype"}=$fmime;
- } else {
- $value=~s/\s+$//s;
- }
- &add_to_env("form.$name",$value);
- }
- if ($i<$#lines) {
- $i++;
- $lines[$i]=~
- /Content\-Disposition\:\s*form\-data\;\s*name\=\"([^\"]+)\"/i;
- $name=$1;
- $value='';
- if ($lines[$i]=~/filename\=\"([^\"]+)\"/i) {
- $fname=$1;
- if
- ($lines[$i+1]=~/Content\-Type\:\s*([\w\-\/]+)/i) {
- $fmime=$1;
- $i++;
- } else {
- $fmime='';
- }
- } else {
- $fname='';
- $fmime='';
- }
- $i++;
- }
- } else {
- $value.=$lines[$i]."\n";
- }
+sub get_secgrprole_info {
+ my ($cdom,$cnum,$needroles,$type) = @_;
+ my %sections_count = &get_sections($cdom,$cnum);
+ my @sections = (sort {$a <=> $b} keys(%sections_count));
+ my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
+ my @groups = sort(keys(%curr_groups));
+ my $allroles = [];
+ my $rolehash;
+ my $accesshash = {
+ active => 'Currently has access',
+ future => 'Will have future access',
+ previous => 'Previously had access',
+ };
+ if ($needroles) {
+ $rolehash = {'all' => 'all'};
+ my %user_roles = &Apache::lonnet::dump('nohist_userroles',$cdom,$cnum);
+ if (&Apache::lonnet::error(%user_roles)) {
+ undef(%user_roles);
}
+ foreach my $item (keys(%user_roles)) {
+ my ($role)=split(/\:/,$item,2);
+ if ($role eq 'cr') { next; }
+ if ($role =~ /^cr/) {
+ $$rolehash{$role} = (split('/',$role))[3];
+ } else {
+ $$rolehash{$role} = &Apache::lonnet::plaintext($role,$type);
+ }
+ }
+ foreach my $key (sort(keys(%{$rolehash}))) {
+ push(@{$allroles},$key);
+ }
+ push (@{$allroles},'st');
+ $$rolehash{'st'} = &Apache::lonnet::plaintext('st',$type);
}
- $ENV{'request.method'}=$ENV{'REQUEST_METHOD'};
- $r->method_number(M_GET);
- $r->method('GET');
- $r->headers_in->unset('Content-length');
+ return (\@sections,\@groups,$allroles,$rolehash,$accesshash);
}
=pod
=item * get_unprocessed_cgi($query,$possible_names)
-Modify the %ENV hash to contain unprocessed CGI form parameters held in
+Modify the %env hash to contain unprocessed CGI form parameters held in
$query. The parameters listed in $possible_names (an array reference),
-will be set in $ENV{'form.name'} if they do not already exist.
+will be set in $env{'form.name'} if they do not already exist.
Typically called with $ENV{'QUERY_STRING'} as the first parameter.
$possible_names is an ref to an array of form element names. As an example:
get_unprocessed_cgi($ENV{'QUERY_STRING'},['uname','udom']);
-will result in $ENV{'form.uname'} and $ENV{'form.udom'} being set.
+will result in $env{'form.uname'} and $env{'form.udom'} being set.
=cut
sub get_unprocessed_cgi {
my ($query,$possible_names)= @_;
# $Apache::lonxml::debug=1;
- foreach (split(/&/,$query)) {
- my ($name, $value) = split(/=/,$_);
- $name = &Apache::lonnet::unescape($name);
+ foreach my $pair (split(/&/,$query)) {
+ my ($name, $value) = split(/=/,$pair);
+ $name = &unescape($name);
if (!defined($possible_names) || (grep {$_ eq $name} @$possible_names)) {
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
- &Apache::lonxml::debug("Seting :$name: to :$value:");
- unless (defined($ENV{'form.'.$name})) { &add_to_env('form.'.$name,$value) };
+ unless (defined($env{'form.'.$name})) { &add_to_env('form.'.$name,$value) };
}
}
}
@@ -2863,7 +4490,7 @@ returns cache-controlling header code
=cut
sub cacheheader {
- unless ($ENV{'request.method'} eq 'GET') { return ''; }
+ unless ($env{'request.method'} eq 'GET') { return ''; }
my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime);
my $output .='
@@ -2882,7 +4509,7 @@ specifies header code to not have cache
sub no_cache {
my ($r) = @_;
if ($ENV{'REQUEST_METHOD'} ne 'GET' &&
- $ENV{'request.method'} ne 'GET') { return ''; }
+ $env{'request.method'} ne 'GET') { return ''; }
my $date=strftime("%a, %d %b %Y %H:%M:%S GMT",gmtime(time));
$r->no_cache(1);
$r->header_out("Expires" => $date);
@@ -2891,6 +4518,11 @@ sub no_cache {
sub content_type {
my ($r,$type,$charset) = @_;
+ if ($r) {
+ # Note that printout.pl calls this with undef for $r.
+ &no_cache($r);
+ }
+ if ($env{'browser.mathml'} && $type eq 'text/html') { $type='text/xml'; }
unless ($charset) {
$charset=&Apache::lonlocal::current_encoding;
}
@@ -2906,7 +4538,7 @@ sub content_type {
=item * add_to_env($name,$value)
-adds $name to the %ENV hash with value
+adds $name to the %env hash with value
$value, if $name already exists, the entry is converted to an array
reference and $value is added to the array.
@@ -2914,18 +4546,18 @@ reference and $value is added to the arr
sub add_to_env {
my ($name,$value)=@_;
- if (defined($ENV{$name})) {
- if (ref($ENV{$name})) {
+ if (defined($env{$name})) {
+ if (ref($env{$name})) {
#already have multiple values
- push(@{ $ENV{$name} },$value);
+ push(@{ $env{$name} },$value);
} else {
#first time seeing multiple values, convert hash entry to an arrayref
- my $first=$ENV{$name};
- undef($ENV{$name});
- push(@{ $ENV{$name} },$first,$value);
+ my $first=$env{$name};
+ undef($env{$name});
+ push(@{ $env{$name} },$first,$value);
}
} else {
- $ENV{$name}=$value;
+ $env{$name}=$value;
}
}
@@ -2933,7 +4565,7 @@ sub add_to_env {
=item * get_env_multiple($name)
-gets $name from the %ENV hash, it seemlessly handles the cases where multiple
+gets $name from the %env hash, it seemlessly handles the cases where multiple
values may be defined and end up as an array ref.
returns an array of values
@@ -2943,12 +4575,12 @@ returns an array of values
sub get_env_multiple {
my ($name) = @_;
my @values;
- if (defined($ENV{$name})) {
+ if (defined($env{$name})) {
# exists is it an array
- if (ref($ENV{$name})) {
- @values=@{ $ENV{$name} };
+ if (ref($env{$name})) {
+ @values=@{ $env{$name} };
} else {
- $values[0]=$ENV{$name};
+ $values[0]=$env{$name};
}
}
return(@values);
@@ -2966,25 +4598,25 @@ sub get_env_multiple {
=item * upfile_store($r)
Store uploaded file, $r should be the HTTP Request object,
-needs $ENV{'form.upfile'}
+needs $env{'form.upfile'}
returns $datatoken to be put into hidden field
=cut
sub upfile_store {
my $r=shift;
- $ENV{'form.upfile'}=~s/\r/\n/gs;
- $ENV{'form.upfile'}=~s/\f/\n/gs;
- $ENV{'form.upfile'}=~s/\n+/\n/gs;
- $ENV{'form.upfile'}=~s/\n+$//gs;
+ $env{'form.upfile'}=~s/\r/\n/gs;
+ $env{'form.upfile'}=~s/\f/\n/gs;
+ $env{'form.upfile'}=~s/\n+/\n/gs;
+ $env{'form.upfile'}=~s/\n+$//gs;
- my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
- '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;
+ my $datatoken=$env{'user.name'}.'_'.$env{'user.domain'}.
+ '_enroll_'.$env{'request.course.id'}.'_'.time.'_'.$$;
{
my $datafile = $r->dir_config('lonDaemons').
'/tmp/'.$datatoken.'.tmp';
if ( open(my $fh,">$datafile") ) {
- print $fh $ENV{'form.upfile'};
+ print $fh $env{'form.upfile'};
close($fh);
}
}
@@ -2996,8 +4628,8 @@ sub upfile_store {
=item * load_tmp_file($r)
Load uploaded file from tmp, $r should be the HTTP Request object,
-needs $ENV{'form.datatoken'},
-sets $ENV{'form.upfile'} to the contents of the file
+needs $env{'form.datatoken'},
+sets $env{'form.upfile'} to the contents of the file
=cut
@@ -3006,13 +4638,13 @@ sub load_tmp_file {
my @studentdata=();
{
my $studentfile = $r->dir_config('lonDaemons').
- '/tmp/'.$ENV{'form.datatoken'}.'.tmp';
+ '/tmp/'.$env{'form.datatoken'}.'.tmp';
if ( open(my $fh,"<$studentfile") ) {
@studentdata=<$fh>;
close($fh);
}
}
- $ENV{'form.upfile'}=join('',@studentdata);
+ $env{'form.upfile'}=join('',@studentdata);
}
=pod
@@ -3021,14 +4653,19 @@ sub load_tmp_file {
Separate uploaded file into records
returns array of records,
-needs $ENV{'form.upfile'} and $ENV{'form.upfiletype'}
+needs $env{'form.upfile'} and $env{'form.upfiletype'}
=cut
sub upfile_record_sep {
- if ($ENV{'form.upfiletype'} eq 'xml') {
+ if ($env{'form.upfiletype'} eq 'xml') {
} else {
- return split(/\n/,$ENV{'form.upfile'});
+ my @records;
+ foreach my $line (split(/\n/,$env{'form.upfile'})) {
+ if ($line=~/^\s*$/) { next; }
+ push(@records,$line);
+ }
+ return @records;
}
}
@@ -3036,30 +4673,33 @@ sub upfile_record_sep {
=item * record_sep($record)
-Separate a record into fields $record should be an item from the upfile_record_sep(), needs $ENV{'form.upfiletype'}
+Separate a record into fields $record should be an item from the upfile_record_sep(), needs $env{'form.upfiletype'}
=cut
+sub takeleft {
+ my $index=shift;
+ return substr('0000'.$index,-4,4);
+}
+
sub record_sep {
my $record=shift;
my %components=();
- if ($ENV{'form.upfiletype'} eq 'xml') {
- } elsif ($ENV{'form.upfiletype'} eq 'space') {
+ if ($env{'form.upfiletype'} eq 'xml') {
+ } elsif ($env{'form.upfiletype'} eq 'space') {
my $i=0;
- foreach (split(/\s+/,$record)) {
- my $field=$_;
+ foreach my $field (split(/\s+/,$record)) {
$field=~s/^(\"|\')//;
$field=~s/(\"|\')$//;
- $components{$i}=$field;
+ $components{&takeleft($i)}=$field;
$i++;
}
- } elsif ($ENV{'form.upfiletype'} eq 'tab') {
+ } elsif ($env{'form.upfiletype'} eq 'tab') {
my $i=0;
- foreach (split(/\t/,$record)) {
- my $field=$_;
+ foreach my $field (split(/\t/,$record)) {
$field=~s/^(\"|\')//;
$field=~s/(\"|\')$//;
- $components{$i}=$field;
+ $components{&takeleft($i)}=$field;
$i++;
}
} else {
@@ -3077,7 +4717,7 @@ sub record_sep {
$field=~s/^\s*$delimiter//;
$field=~s/$delimiter\s*$//;
}
- $components{$i}=$field;
+ $components{&takeleft($i)}=$field;
$i++;
}
}
@@ -3114,6 +4754,22 @@ sub upfile_select_html {
return $Str;
}
+sub get_samples {
+ my ($records,$toget) = @_;
+ my @samples=({});
+ my $got=0;
+ foreach my $rec (@$records) {
+ my %temp = &record_sep($rec);
+ if (! grep(/\S/, values(%temp))) { next; }
+ if (%temp) {
+ $samples[$got]=\%temp;
+ $got++;
+ if ($got == $toget) { last; }
+ }
+ }
+ return \@samples;
+}
+
######################################################
######################################################
@@ -3131,20 +4787,17 @@ Apache Request ref, $records is an array
######################################################
sub csv_print_samples {
my ($r,$records) = @_;
- my (%sone,%stwo,%sthree);
- %sone=&record_sep($$records[0]);
- if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
- if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
- #
+ my $samples = &get_samples($records,3);
+
$r->print(&mt('Samples').'');
- foreach (sort({$a <=> $b} keys(%sone))) {
- $r->print(''.&mt('Column [_1]',($_+1)).' '); }
+ foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
+ $r->print(''.&mt('Column [_1]',($sample+1)).' '); }
$r->print(' ');
- foreach my $hash (\%sone,\%stwo,\%sthree) {
+ foreach my $hash (@$samples) {
$r->print('');
- foreach (sort({$a <=> $b} keys(%sone))) {
+ foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
$r->print('');
- if (defined($$hash{$_})) { $r->print($$hash{$_}); }
+ if (defined($$hash{$sample})) { $r->print($$hash{$sample}); }
$r->print(' ');
}
$r->print(' ');
@@ -3171,23 +4824,23 @@ $d is an array of 2 element arrays (inte
######################################################
sub csv_print_select_table {
my ($r,$records,$d) = @_;
- my $i=0;my %sone;
- %sone=&record_sep($$records[0]);
+ my $i=0;
+ my $samples = &get_samples($records,1);
$r->print(&mt('Associate columns with student attributes.')."\n".
''.
''.&mt('Attribute').' '.
''.&mt('Column').' '."\n");
- foreach (@$d) {
- my ($value,$display,$defaultcol)=@{ $_ };
+ foreach my $array_ref (@$d) {
+ my ($value,$display,$defaultcol)=@{ $array_ref };
$r->print(''.$display.' ');
$r->print('');
$r->print(' ');
- foreach (sort({$a <=> $b} keys(%sone))) {
- $r->print('Column '.($_+1).' ');
+ foreach my $sample (sort({$a <=> $b} keys(%{ $samples->[0] }))) {
+ $r->print('Column '.($sample+1).' ');
}
$r->print(' '."\n");
$i++;
@@ -3215,28 +4868,27 @@ $d is an array of 2 element arrays (inte
######################################################
sub csv_samples_select_table {
my ($r,$records,$d) = @_;
- my %sone; my %stwo; my %sthree;
my $i=0;
#
+ my $samples = &get_samples($records,3);
$r->print(''.
&mt('Field').' '.&mt('Samples').' ');
- %sone=&record_sep($$records[0]);
- if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
- if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
- #
- foreach (sort keys %sone) {
+
+ foreach my $key (sort(keys(%{ $samples->[0] }))) {
$r->print('');
- foreach (@$d) {
- my ($value,$display,$defaultcol)=@{ $_ };
+ foreach my $option (@$d) {
+ my ($value,$display,$defaultcol)=@{ $option };
$r->print(''.
+ ($i eq $defaultcol ? ' selected="selected" ':'').'>'.
$display.' ');
}
$r->print(' ');
- if (defined($sone{$_})) { $r->print($sone{$_}."\n"); }
- if (defined($stwo{$_})) { $r->print($stwo{$_}."\n"); }
- if (defined($sthree{$_})) { $r->print($sthree{$_}."\n"); }
+ foreach my $line (0..2) {
+ if (defined($samples->[$line]{$key})) {
+ $r->print($samples->[$line]{$key}." \n");
+ }
+ }
$r->print(' ');
$i++;
}
@@ -3325,7 +4977,7 @@ the routine &Apache::lonnet::transfer_pr
my $uniq=0;
sub get_cgi_id {
$uniq=($uniq+1)%100000;
- return (time.'_'.$uniq);
+ return (time.'_'.$$.'_'.$uniq);
}
############################################################
@@ -3361,6 +5013,9 @@ they are plotted. If undefined, default
=item @Values: An array of array references. Each array reference holds data
to be plotted in a stacked bar chart.
+=item If the final element of @Values is a hash reference the key/value
+pairs will be added to the graph definition.
+
=back
Returns:
@@ -3446,9 +5101,9 @@ sub DrawBarGraph {
$Title = '' if (! defined($Title));
$xlabel = '' if (! defined($xlabel));
$ylabel = '' if (! defined($ylabel));
- $ValuesHash{$id.'.title'} = &Apache::lonnet::escape($Title);
- $ValuesHash{$id.'.xlabel'} = &Apache::lonnet::escape($xlabel);
- $ValuesHash{$id.'.ylabel'} = &Apache::lonnet::escape($ylabel);
+ $ValuesHash{$id.'.title'} = &escape($Title);
+ $ValuesHash{$id.'.xlabel'} = &escape($xlabel);
+ $ValuesHash{$id.'.ylabel'} = &escape($ylabel);
$ValuesHash{$id.'.y_max_value'} = $Max;
$ValuesHash{$id.'.NumBars'} = $NumBars;
$ValuesHash{$id.'.NumSets'} = $NumSets;
@@ -3528,9 +5183,9 @@ sub DrawXYGraph {
$ylabel = '' if (! defined($ylabel));
my %ValuesHash =
(
- $id.'.title' => &Apache::lonnet::escape($Title),
- $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
- $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+ $id.'.title' => &escape($Title),
+ $id.'.xlabel' => &escape($xlabel),
+ $id.'.ylabel' => &escape($ylabel),
$id.'.y_max_value'=> $Max,
$id.'.labels' => join(',',@$Xlabels),
$id.'.PlotType' => 'XY',
@@ -3625,9 +5280,9 @@ sub DrawXYYGraph {
$ylabel = '' if (! defined($ylabel));
my %ValuesHash =
(
- $id.'.title' => &Apache::lonnet::escape($Title),
- $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
- $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+ $id.'.title' => &escape($Title),
+ $id.'.xlabel' => &escape($xlabel),
+ $id.'.ylabel' => &escape($ylabel),
$id.'.labels' => join(',',@$Xlabels),
$id.'.PlotType' => 'XY',
$id.'.NumSets' => 2,
@@ -3699,7 +5354,7 @@ Inputs:
sub chartlink {
my ($linktext, $sname, $sdomain) = @_;
my $link = ''.$linktext.' ';
}
@@ -3729,6 +5384,7 @@ a hash ref describing the data to be sto
'chartoutputmode' => 'scalar',
'chartoutputdata' => 'scalar',
'Section' => 'array',
+ 'Group' => 'array',
'StudentData' => 'array',
'Maps' => 'array');
@@ -3741,34 +5397,35 @@ Returns: both routines return nothing
sub store_course_settings {
# save to the environment
# appenv the same items, just to be safe
- my $courseid = $ENV{'request.course.id'};
- my $coursedom = $ENV{'course.'.$courseid.'.domain'};
+ my $courseid = $env{'request.course.id'};
+ my $udom = $env{'user.domain'};
+ my $uname = $env{'user.name'};
my ($prefix,$Settings) = @_;
my %SaveHash;
my %AppHash;
while (my ($setting,$type) = each(%$Settings)) {
- my $basename = 'internal.'.$prefix.'.'.$setting;
- my $envname = 'course.'.$courseid.'.'.$basename;
- if (exists($ENV{'form.'.$setting})) {
+ my $basename = join('.','internal',$courseid,$prefix,$setting);
+ my $envname = 'environment.'.$basename;
+ if (exists($env{'form.'.$setting})) {
# Save this value away
if ($type eq 'scalar' &&
- (! exists($ENV{$envname}) ||
- $ENV{$envname} ne $ENV{'form.'.$setting})) {
- $SaveHash{$basename} = $ENV{'form.'.$setting};
- $AppHash{$envname} = $ENV{'form.'.$setting};
+ (! exists($env{$envname}) ||
+ $env{$envname} ne $env{'form.'.$setting})) {
+ $SaveHash{$basename} = $env{'form.'.$setting};
+ $AppHash{$envname} = $env{'form.'.$setting};
} elsif ($type eq 'array') {
my $stored_form;
- if (ref($ENV{'form.'.$setting})) {
+ if (ref($env{'form.'.$setting})) {
$stored_form = join(',',
map {
- &Apache::lonnet::escape($_);
- } sort(@{$ENV{'form.'.$setting}}));
+ &escape($_);
+ } sort(@{$env{'form.'.$setting}}));
} else {
$stored_form =
- &Apache::lonnet::escape($ENV{'form.'.$setting});
+ &escape($env{'form.'.$setting});
}
# Determine if the array contents are the same.
- if ($stored_form ne $ENV{$envname}) {
+ if ($stored_form ne $env{$envname}) {
$SaveHash{$basename} = $stored_form;
$AppHash{$envname} = $stored_form;
}
@@ -3776,8 +5433,7 @@ sub store_course_settings {
}
}
my $put_result = &Apache::lonnet::put('environment',\%SaveHash,
- $coursedom,
- $ENV{'course.'.$courseid.'.num'});
+ $udom,$uname);
if ($put_result !~ /^(ok|delayed)/) {
&Apache::lonnet::logthis('unable to save form parameters, '.
'got error:'.$put_result);
@@ -3788,20 +5444,20 @@ sub store_course_settings {
}
sub restore_course_settings {
- my $courseid = $ENV{'request.course.id'};
+ my $courseid = $env{'request.course.id'};
my ($prefix,$Settings) = @_;
while (my ($setting,$type) = each(%$Settings)) {
- next if (exists($ENV{'form.'.$setting}));
- my $envname = 'course.'.$courseid.'.internal.'.$prefix.
+ next if (exists($env{'form.'.$setting}));
+ my $envname = 'environment.internal.'.$courseid.'.'.$prefix.
'.'.$setting;
- if (exists($ENV{$envname})) {
+ if (exists($env{$envname})) {
if ($type eq 'scalar') {
- $ENV{'form.'.$setting} = $ENV{$envname};
+ $env{'form.'.$setting} = $env{$envname};
} elsif ($type eq 'array') {
- $ENV{'form.'.$setting} = [
+ $env{'form.'.$setting} = [
map {
- &Apache::lonnet::unescape($_);
- } split(',',$ENV{$envname})
+ &unescape($_);
+ } split(',',$env{$envname})
];
}
}
@@ -3811,15 +5467,26 @@ sub restore_course_settings {
############################################################
############################################################
-sub propath {
- my ($udom,$uname)=@_;
- $udom=~s/\W//g;
- $uname=~s/\W//g;
- my $subdir=$uname.'__';
- $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
- my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname";
- return $proname;
-}
+sub course_type {
+ my ($cid) = @_;
+ if (!defined($cid)) {
+ $cid = $env{'request.course.id'};
+ }
+ if (defined($env{'course.'.$cid.'.type'})) {
+ return $env{'course.'.$cid.'.type'};
+ } else {
+ return 'Course';
+ }
+}
+
+sub group_term {
+ my $crstype = &course_type();
+ my %names = (
+ 'Course' => 'group',
+ 'Group' => 'team',
+ );
+ return $names{$crstype};
+}
sub icon {
my ($file)=@_;
@@ -3834,7 +5501,7 @@ sub icon {
$curfext.".gif";
}
}
- return $iconname;
+ return &lonhttpdurl($iconname);
}
sub lonhttpdurl {
@@ -3872,8 +5539,8 @@ sub escape_double {
# Escapes the last element of a full URL.
sub escape_url {
my ($url) = @_;
- my @urlslices = split(/\//, $url);
- my $lastitem = &Apache::lonnet::escape(pop(@urlslices));
+ my @urlslices = split(/\//, $url,-1);
+ my $lastitem = &escape(pop(@urlslices));
return join('/',@urlslices).'/'.$lastitem;
}
=pod