--- loncom/interface/spreadsheet/Spreadsheet.pm 2003/06/18 17:35:14 1.14 +++ loncom/interface/spreadsheet/Spreadsheet.pm 2003/09/12 18:59:48 1.25 @@ -1,5 +1,5 @@ # -# $Id: Spreadsheet.pm,v 1.14 2003/06/18 17:35:14 matthew Exp $ +# $Id: Spreadsheet.pm,v 1.25 2003/09/12 18:59:48 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -48,6 +48,8 @@ Spreadsheet package Apache::Spreadsheet; use strict; +#use warnings FATAL=>'all'; +#no warnings 'uninitialized'; use Apache::Constants qw(:common :http); use Apache::lonnet; use Safe; @@ -90,7 +92,7 @@ sub new { type => $stype, symb => $usymb, errorlog => '', - maxrow => '', + maxrow => 0, cid => $ENV{'request.course.id'}, cnum => $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, cdom => $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, @@ -229,6 +231,16 @@ sub initialize { # the descendents of the spreadsheet class. } +sub clear_package { + # This method is here to remind you that it will be overridden by + # the descendents of the spreadsheet class. +} + +sub cleanup { + my $self = shift(); + $self->clear_package(); +} + sub initialize_spreadsheet_package { &load_spreadsheet_expirationdates(); &clear_spreadsheet_definition_cache(); @@ -248,18 +260,28 @@ sub load_spreadsheet_expirationdates { sub check_expiration_time { my $self = shift; my ($time)=@_; - my ($key1,$key2,$key3,$key4); + return 0 if (! defined($time)); + my ($key1,$key2,$key3,$key4,$key5); + # Description of keys + # + # key1: all sheets of this type have expired + # key2: all sheets of this type for this student + # key3: all sheets of this type in this map for this student + # key4: this assessment sheet for this student + # key5: this assessment sheet for all students $key1 = '::'.$self->{'type'}.':'; $key2 = $self->{'name'}.':'.$self->{'domain'}.':'.$self->{'type'}.':'; $key3 = $key2.$self->{'container'} if (defined($self->{'container'})); - $key4 = $key2.$self->{'usymb'} if (defined($self->{'usymb'})); - foreach my $key ($key1,$key2,$key3,$key4) { + $key4 = $key2.$self->{'symb'} if (defined($self->{'symb'})); + $key5 = $key1.$self->{'symb'} if (defined($self->{'symb'})); + my $returnvalue = 1; # default to okay + foreach my $key ($key1,$key2,$key3,$key4,$key5) { next if (! defined($key)); - if (exists($expiredates{$key}) &&$expiredates{$key} > $time) { - return 0; + if (exists($expiredates{$key}) && $expiredates{$key} > $time) { + $returnvalue = 0; # need to recompute } } - return 1; + return $returnvalue; } ###################################################### @@ -277,18 +299,23 @@ Returns the safe space required by a Spr =cut ###################################################### +{ + + my $safeeval; + sub initialize_safe_space { - my $self = shift; - my $safeeval = new Safe(shift); - my $safehole = new Safe::Hole; - $safeeval->permit("entereval"); - $safeeval->permit(":base_math"); - $safeeval->permit("sort"); - $safeeval->deny(":base_io"); - $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); - $safehole->wrap(\&mask,$safeeval,'&mask'); - $safeeval->share('$@'); - my $code=<<'ENDDEFS'; + my $self = shift; + if (! defined($safeeval)) { + $safeeval = new Safe(shift); + my $safehole = new Safe::Hole; + $safeeval->permit("entereval"); + $safeeval->permit(":base_math"); + $safeeval->permit("sort"); + $safeeval->deny(":base_io"); + $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); + $safehole->wrap(\&mask,$safeeval,'&mask'); + $safeeval->share('$@'); + my $code=<<'ENDDEFS'; # ---------------------------------------------------- Inside of the safe space # # f: formulas @@ -655,7 +682,8 @@ sub calc { # ------------------------------------------- End of "Inside of the safe space" ENDDEFS - $safeeval->reval($code); + $safeeval->reval($code); + } $self->{'safe'} = $safeeval; $self->{'root'} = $self->{'safe'}->root(); # @@ -669,6 +697,9 @@ ENDDEFS $self->{'safe'}->reval($initstring); return $self; } + +} + ###################################################### =pod @@ -785,8 +816,8 @@ sub expandnamed { my @vars=split(/\W+/,$formula); my %values=(); foreach my $varname ( @vars ) { - if ($varname=~/\D/) { - $formula=~s/$varname/'$c{\''.$varname.'\'}'/ge; + if ($varname=~/^(parameter|stores|timestamp)/) { + $formula=~s/$varname/'$c{\''.$varname.'\'}'/ge; $varname=~s/$var/\([\\w:\\- ]\+\)/g; foreach (keys(%{$self->{'constants'}})) { if ($_=~/$varname/) { @@ -1135,6 +1166,7 @@ sub display { } elsif ($outputmode eq 'csv') { $self->outsheet_csv($r); } + $self->cleanup(); return; } @@ -1143,13 +1175,15 @@ sub display { ############################################ sub html_export_row { my $self = shift(); + my ($color) = @_; + $color = '#CCCCFF' if (! defined($color)); my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}); my $row_html; my @rowdata = $self->get_row(0); foreach my $cell (@rowdata) { if ($cell->{'name'} =~ /^[A-Z]/) { - $row_html .= ''. - &html_editable_cell($cell,'#CCCCFF',$allowed).''; + $row_html .= ''. + &html_editable_cell($cell,$color,$allowed).''; } else { $row_html .= ''. &html_editable_cell($cell,'#DDCCFF',$allowed).''; @@ -1161,14 +1195,14 @@ sub html_export_row { sub html_template_row { my $self = shift(); my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}); - my ($num_uneditable) = @_; + my ($num_uneditable,$importcolor) = @_; my $row_html; my @rowdata = $self->get_template_row(); my $count = 0; for (my $i = 0; $i<=$#rowdata; $i++) { my $cell = $rowdata[$i]; if ($i < $num_uneditable) { - $row_html .= ''. + $row_html .= ''. &html_uneditable_cell($cell,'#FFDDDD',$allowed).''; } else { $row_html .= ''. @@ -1200,13 +1234,17 @@ sub html_editable_cell { $value = &HTML::Entities::encode($value) if ($value !~/ /); } return $value if (! $allowed); - # Make the formula safe for outputting - $formula =~ s/\'/\"/g; + # # The formula will be parsed by the browser twice before being - # displayed to the user for editing. - $formula = &HTML::Entities::encode(&HTML::Entities::encode($formula)); - # Escape newlines so they make it into the edit window - $formula =~ s/\n/\\n/gs; + # displayed to the user for editing. + # + # The encoding string "^A-blah" is placed in []'s inside a regexp, so + # we specify the characters we want left alone by putting a '^' in front. + $formula = &HTML::Entities::encode($formula,'^A-z0-9 !#$%-;=?~'); + # HTML::Entities::encode does not catch everything - we need '\' encoded + $formula =~ s/\\/&\#092/g; + # Escape it again - this time the only encodable character is '&' + $formula =~ s/\&/\&/g; # Glue everything together $result .= "".$value.""; @@ -1222,14 +1260,19 @@ sub html_uneditable_cell { sub html_row { my $self = shift(); - my ($num_uneditable,$row) = @_; + my ($num_uneditable,$row,$exportcolor,$importcolor) = @_; my $allowed = &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}); my @rowdata = $self->get_row($row); my $num_cols_output = 0; my $row_html; + my $color = $importcolor; + if ($row == 0) { + $color = $exportcolor; + } + $color = '#FFDDDD' if (! defined($color)); foreach my $cell (@rowdata) { if ($num_cols_output++ < $num_uneditable) { - $row_html .= ''; + $row_html .= ''; $row_html .= &html_uneditable_cell($cell,'#FFDDDD'); } else { $row_html .= ''; @@ -1317,6 +1360,7 @@ sub create_excel_spreadsheet { sub outsheet_excel { my $self = shift; my ($r) = @_; + my $connection = $r->connection(); $r->print("

Preparing Excel Spreadsheet

"); # # Create excel worksheet @@ -1340,7 +1384,7 @@ sub outsheet_excel { $self->excel_output_row($worksheet,0,$rows_output++,'Summary'); $rows_output++; # skip a line # - $self->excel_rows($worksheet,$cols_output,$rows_output); + $self->excel_rows($connection,$worksheet,$cols_output,$rows_output); # # # Close the excel file @@ -1358,6 +1402,7 @@ sub outsheet_excel { sub outsheet_csv { my $self = shift; my ($r) = @_; + my $connection = $r->connection(); my $csvdata = ''; my @Values; # @@ -1381,7 +1426,7 @@ sub outsheet_csv { } # # Output the body of the spreadsheet - $self->csv_rows($file); + $self->csv_rows($connection,$file); # # Close the csv file close($file); @@ -1531,9 +1576,6 @@ sub load { } else { $self->filename($newfilename); } - } elsif ($filename =~ /^default\.$self->{'type'}/) { - # if there is an Original_$stype, load it instead - $formulas = $self->load_system_default_sheet(); } else { # Load the spreadsheet definition file from the save file my %tmphash = &Apache::lonnet::dump($filename,$cdom,$cnum); @@ -1558,7 +1600,7 @@ sub load { sub set_row_sources { my $self = shift; while (my ($cell,$value) = each(%{$self->{'formulas'}})) { - next if ($cell !~ /^A(\d+)/ && $1 > 0); + next if ($cell !~ /^A(\d+)/ || $1 < 1); my $row = $1; $self->{'row_source'}->{$row} = $value; } @@ -1620,7 +1662,12 @@ sub save { return $reply if ($reply ne 'ok'); } if ($self->is_default()) { - &Apache::lonnet::expirespread('','',$self->{'type'},''); + if ($self->{'type'} eq 'studentcalc') { + &Apache::lonnet::expirespread('','','studentcalc',''); + } elsif ($self->{'type'} eq 'assesscalc') { + &Apache::lonnet::expirespread('','','assesscalc',''); + &Apache::lonnet::expirespread('','','studentcalc',''); + } } return $reply; } @@ -1632,7 +1679,7 @@ sub save { sub save_tmp { my $self = shift; my $filename=$ENV{'user.name'}.'_'. - $ENV{'user.domain'}.'_spreadsheet_'.$self->{'usymb'}.'_'. + $ENV{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'. $self->{'filename'}; $filename=~s/\W/\_/g; $filename=$Apache::lonnet::tmpdir.$filename.'.tmp'; @@ -1652,7 +1699,7 @@ sub save_tmp { sub load_tmp { my $self = shift; my $filename=$ENV{'user.name'}.'_'. - $ENV{'user.domain'}.'_spreadsheet_'.$self->{'usymb'}.'_'. + $ENV{'user.domain'}.'_spreadsheet_'.$self->{'symb'}.'_'. $self->{'filename'}; $filename=~s/\W/\_/g; $filename=$Apache::lonnet::tmpdir.$filename.'.tmp';