--- loncom/interface/spreadsheet/lonspreadsheet.pm 2003/06/19 16:04:06 1.13 +++ loncom/interface/spreadsheet/lonspreadsheet.pm 2011/10/09 00:28:03 1.55.6.1 @@ -1,5 +1,5 @@ # -# $Id: lonspreadsheet.pm,v 1.13 2003/06/19 16:04:06 matthew Exp $ +# $Id: lonspreadsheet.pm,v 1.55.6.1 2011/10/09 00:28:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -54,12 +54,16 @@ built-in functions. package Apache::lonspreadsheet; use strict; +use warnings FATAL=>'all'; +no warnings 'uninitialized'; use Apache::classcalc(); use Apache::studentcalc(); use Apache::assesscalc(); use Apache::Constants qw(:common :http); use Apache::lonnet; use Apache::lonhtmlcommon; +use Apache::lonlocal; +use Apache::loncoursedata(); use HTML::Entities(); ## @@ -68,22 +72,22 @@ use HTML::Entities(); sub textfield { my ($title,$name,$value)=@_; - return "\n

$title:
". - ''; + return "\n

$title:
". + ''; } sub hiddenfield { my ($name,$value)=@_; - return ''."\n"; + return ''."\n"; } sub selectbox { my ($title,$name,$value,%options)=@_; - my $selout="\n

$title:
".''; foreach (sort keys(%options)) { $selout.=''; } return $selout.''; } @@ -96,33 +100,36 @@ sub file_dialogs { my $message = ''; ## ## Deal with saving the spreadsheet - if ((exists($ENV{'form.save'}) || exists($ENV{'form.makedefault'})) && - exists($ENV{'form.savefilename'})) { - $spreadsheet->filename($ENV{'form.savefilename'}); + $spreadsheet->check_formulas_loaded(); + if ((exists($env{'form.save'}) || exists($env{'form.makedefault'})) && + exists($env{'form.savefilename'})) { + $spreadsheet->filename($env{'form.savefilename'}); my $save_status = $spreadsheet->save(); if ($save_status ne 'ok') { - $message .= "An error occurred while saving the spreadsheet". - "There error is:".$save_status; - return $result; + $message .= ''. + &mt('An error occurred while saving the spreadsheet. The error is: [_1].', + $save_status).''; } else { - $message .= "Spreadsheet saved as ".$ENV{'form.savefilename'}; + $message .= ''.&mt('Spreadsheet saved as: [_1] .', + ''.$spreadsheet->filename().''). + ''; } - } elsif (exists($ENV{'form.newformula'}) && - exists($ENV{'form.cell'}) && - $ENV{'form.cell'} ne '' ) { + } elsif (exists($env{'form.newformula'}) && + exists($env{'form.cell'}) && + $env{'form.cell'} ne '' ) { ## ## Make any requested modifications to the spreadsheet - $spreadsheet->modify_cell($ENV{'form.cell'}, - $ENV{'form.newformula'}); + $spreadsheet->modify_cell($env{'form.cell'}, + $env{'form.newformula'}); $spreadsheet->save_tmp(); # output that we are dealing with a temporary file $result .=&hiddenfield('workcopy',$sheettype); - if ($ENV{'form.newformula'} !~ /^\s*$/) { + if ($env{'form.newformula'} !~ /^\s*$/) { $message .=''. - ''. - '
Cell '.$ENV{'form.cell'}.' = 
'.$ENV{'form.newformula'}."
\n"; + '

'.&mt('Cell').' '.$env{'form.cell'}.' = 
'. + '
'.$env{'form.newformula'}."
\n"; } else { - $message .= 'Deleted contents of cell '.$ENV{'form.cell'}.'.'; + $message .= &mt('Deleted contents of cell').' '.$env{'form.cell'}.'.'; } } ## @@ -136,38 +143,44 @@ sub file_dialogs { if ($spreadsheet->is_default()) { $filename = 'Default'; } - my $save_dialog = ''. - ' '. + my $save_dialog = ''. + ' '. ''. - ''; + ''; my $makedefault_dialog = ''; + 'value="'.&mt('Save as & Make This Sheet the Default').'"/>'; # my $link = 'Select Spreadsheet File"; + "('sheet','loadfilename','spreadsheet')\">".&mt('Select Spreadsheet File').""; + my $load=&mt('Load:'); my $load_dialog = < - - + + - $link + $link   \n \n\n"; # + my $headline = &mt('File Dialogs'); $result .=< + $headline + --> @@ -180,6 +193,9 @@ END
+ END return ($result,$message); } @@ -194,13 +210,13 @@ sub handler { if ($loaderror) { return $loaderror; } # Check the course homeserver $loaderror= &Apache::lonnet::overloaderror($r, - $ENV{'course.'.$ENV{'request.course.id'}.'.home'}); + $env{'course.'.$env{'request.course.id'}.'.home'}); # if ($loaderror) { return $loaderror; } # # HTML Header # if ($r->header_only) { - $r->content_type('text/html'); + &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; return OK; } @@ -208,98 +224,159 @@ sub handler { # Roles Checking # # Needs to be in a course - if (! $ENV{'request.course.fn'}) { + if (! $env{'request.course.fn'}) { # Not in a course, or not allowed to modify parms - $ENV{'user.error.msg'}= + $env{'user.error.msg'}= $r->uri.":opa:0:0:Cannot modify spreadsheet"; return HTTP_NOT_ACCEPTABLE; } + my ($sheettype) = ($r->uri=~/\/(\w+)$/); + my $courseid = $env{'request.course.id'}; + + ## + ## Check permissions + my $allowed_to_edit = &Apache::lonnet::allowed('mgr', + $env{'request.course.id'}); + # Only those instructors/tas/whatevers with complete access + # (not section restricted) are able to modify spreadsheets. + my $allowed_to_view = &Apache::lonnet::allowed('vgr', + $env{'request.course.id'}); + if (! $allowed_to_view) { + $allowed_to_view = &Apache::lonnet::allowed('vgr', + $env{'request.course.id'}.'/'.$env{'request.course.sec'}); + # Those who are restricted by section are allowed to view. + # The routines in lonstatistics which decide which students' + # will be shown take care of the restriction by section. + } + + # + # Do not allow users without vgr or mgr priv to continue unless + # grading type is set to spreadsheet. + # + + if ((!$allowed_to_view) && (!$allowed_to_edit)) { + if ($env{'course.'.$courseid.'.grading'} eq 'spreadsheet') { + if ($sheettype ne 'studentcalc') { + $r->internal_redirect('/adm/studentcalc'); + return OK; + } + } else { + $r->internal_redirect('/adm/quickgrades'); + return OK; + } + } # # Get query string for limited number of parameters # &Apache::loncommon::get_unprocessed_cgi - ($ENV{'QUERY_STRING'},['sname','sdomain','usymb','filename']); + ($ENV{'QUERY_STRING'},['sname','sdomain','usymb','filename','recalc', + 'output_format','not_first_run']); # # Deal with restricted student permissions # - if ($ENV{'request.role'} =~ /^st\./) { - delete $ENV{'form.cell'} if (exists($ENV{'form.cell'})); - delete $ENV{'form.newformula'} if (exists($ENV{'form.newformula'})); + if ($env{'request.role'} =~ /^st\./) { + delete $env{'form.cell'} if (exists($env{'form.cell'})); + delete $env{'form.newformula'} if (exists($env{'form.newformula'})); } # # Determine basic information about the spreadsheet - my ($sheettype) = ($r->uri=~/\/(\w+)$/); # my $symb = undef; - $symb = $ENV{'form.usymb'} if (exists($ENV{'form.usymb'})); - my $name = $ENV{'user.name'}; - my $domain = $ENV{'user.domain'}; - if (exists($ENV{'form.sname'})) { - $name = $ENV{'form.sname'}; - $domain = $ENV{'form.sdomain'}; + $symb = $env{'form.usymb'} if (exists($env{'form.usymb'})); + my $name = $env{'user.name'}; + my $domain = $env{'user.domain'}; + my $warning; + if (exists($env{'form.sname'}) && $env{'form.sname'} ne '') { + if (($env{'form.sname'} ne $env{'user.name'}) || + ($env{'form.sdomain'} ne $env{'user.domain'})) { + if (($allowed_to_view) || ($allowed_to_edit)) { + if (&Apache::lonnet::homeserver($env{'form.sname'},$env{'form.sdomain'}) ne 'no_host') { + $name = $env{'form.sname'}; + $domain = $env{'form.sdomain'}; + } else { + $warning = &mt('Requested user: "[_1]" does not exist; your own sheet is displayed instead.',$env{'form.sname'}.':'.$env{'form.sdomain'}); + } + } else { + $warning = &mt('Your current role is not permitted to display this sheet for the requested user: "[_1]"; your own sheet is displayed instead.',$env{'form.sname'}.':'.$env{'form.sdomain'}); + } + } } - # - # Open page, try to prevent browser cache. - # - $r->content_type('text/html'); - $r->header_out('Cache-control','no-cache'); - $r->header_out('Pragma','no-cache'); - $r->send_http_header; - ## - ## Check permissions - my $allowed_to_edit = &Apache::lonnet::allowed('mgr', - $ENV{'request.course.id'}); - # Only those instructors/tas/whatevers with complete access - # (not section restricted) are able to modify spreadsheets. - my $allowed_to_view = &Apache::lonnet::allowed('vgr', - $ENV{'request.course.id'}); - if (! $allowed_to_view) { - $allowed_to_view = &Apache::lonnet::allowed('vgr', - $ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'}); - # Those who are restricted by section are allowed to view. - # The routines in lonstatistics which decide which students' - # will be shown take care of the restriction by section. + $env{'form.sname'} = $name; + $env{'form.sdomain'} = $domain; + my $section = &Apache::lonnet::getsection($domain,$name, + $env{'request.course.id'}); + my @groups; + if (($env{'user.name'} eq $name) && ($env{'user.domain'} eq $domain)) { + @groups = &Apache::lonnet::sort_course_groups($env{'request.course.id'}, + split(':',$env{'request.course.groups'})); + } else { + @groups = &Apache::lonnet::get_users_groups($domain,$name, + $env{'request.course.id'}); } + # # Only those able to view others grades will be allowed to continue # if they are not requesting their own. if ($sheettype eq 'classcalc') { - if (! $allowed_to_view) { - $r->print('

Access Permission Denied

'. - ''); + if (!$allowed_to_view) { + $r->internal_redirect('/adm/studentcalc'); return OK; - } + } } - if ((($name ne $ENV{'user.name'} ) || - ($domain ne $ENV{'user.domain'})) && $sheettype ne 'classcalc') { + if ((($name ne $env{'user.name'} ) || + ($domain ne $env{'user.domain'})) && $sheettype ne 'classcalc') { # Check that the student is in their section? - if (exists($ENV{'request.course.sec'}) && - $ENV{'request.course.sec'} ne '' ) { - my $stu_sec = &Apache::lonnet::usection($domain,$name, - $ENV{'request.course.id'}); - if ($stu_sec ne $ENV{'request.course.sec'}) { - $r->print - ('

The student requested is not in your section.

'. - ''); - return OK; + if (exists($env{'request.course.sec'}) && + $env{'request.course.sec'} ne '' ) { + my $stu_sec = &Apache::lonnet::getsection($domain,$name, + $env{'request.course.id'}); + if ($stu_sec ne $env{'request.course.sec'}) { + $env{'user.error.msg'}= + $r->uri.":vgr:0:0:Requested student not in your section."; + return HTTP_NOT_ACCEPTABLE; } } } # + # Open page, try to prevent browser cache. + # + &Apache::loncommon::content_type($r,'text/html'); + &Apache::loncommon::no_cache($r); + $r->send_http_header; + + # # Header.... # - $r->print('LON-CAPA Spreadsheet'); my $nothing = &Apache::lonhtmlcommon::javascript_nothing(); ## ## Spit out the javascript required for editing ## + my $js; if ($allowed_to_edit) { + my %lt=( + 'ce' => 'Cell', + 'ac' => 'Accept', + 'dc' => 'Discard Changes' + ); my $extra_javascript = &Apache::loncommon::browser_and_searcher_javascript(); - $r->print(< - + + my $cell_extra_js = &Apache::loncommon::resize_textarea_js(); + my $cell_edit_start = + &Apache::loncommon::start_page('Cell Edit Window',$cell_extra_js, + {'only_body' => 1, + 'js_ready' => 1, + 'add_entries' => { + 'onresize' => "resize_textarea('LC_newformula','LC_aftertextarea')", + 'onload' => "resize_textarea('LC_newformula','LC_aftertextarea')", + }}); + my $cell_edit_end = + &Apache::loncommon::end_page({'js_ready' => 1,}); + + $js = < +// ENDSCRIPT } - $r->print(''.&Apache::loncommon::bodytag('Grades Spreadsheet'). - '
'); - $r->print(&hiddenfield('sname' ,$ENV{'form.sname'}). - &hiddenfield('sdomain',$ENV{'form.sdomain'}). - &hiddenfield('usymb' ,$ENV{'form.usymb'})); + &Apache::lonhtmlcommon::clear_breadcrumbs(); + &Apache::lonhtmlcommon::add_breadcrumb + ({href => $r->uri, + title => 'Spreadsheet', + text => 'Spreadsheet', + faq => 134, + bug => 'Spreadsheet'}); + my $settingslink = &Apache::lonhtmlcommon::coursepreflink(&mt('Grade display settings'), + 'grading'); + &Apache::lonhtmlcommon::add_breadcrumb_tool('advtools',$settingslink); + $r->print(&Apache::loncommon::start_page('Grades Spreadsheet',$js). + &Apache::lonhtmlcommon::breadcrumbs('Spreadsheet', + 'Spreadsheet_About')); + # + # Open the form + # + if ($warning) { + $r->print('

'.$warning.'

'); + } + $r->print(''); + $r->print(&hiddenfield('sname' ,$env{'form.sname'}). + &hiddenfield('sdomain',$env{'form.sdomain'}). + &hiddenfield('usymb' ,$env{'form.usymb'})); $r->rflush(); ## ## Determine the filename to use my $filename = undef; if ($allowed_to_edit) { - $filename = $ENV{'form.filename'} if (exists($ENV{'form.filename'})); + $filename = $env{'form.filename'} if (exists($env{'form.filename'})); # - if (exists($ENV{'form.load'}) && exists($ENV{'form.loadfilename'})) { - $filename = $ENV{'form.loadfilename'}; - $ENV{'form.workcopy'} = 'no'; + if (exists($env{'form.load'}) && exists($env{'form.loadfilename'})) { + $filename = $env{'form.loadfilename'}; + $env{'form.workcopy'} = 'no'; + } + } + ## + ## Take care of "backdoor" spreadsheet expiration / recalc stuff + if ($allowed_to_edit && exists($env{'form.recalc'})) { + if (exists($env{'form.recalc'})) { + &Apache::loncoursedata::delete_caches($env{'requres.course.id'}); + } + if ($env{'form.recalc'} eq 'ilovewastingtime') { + &Apache::lonnet::logthis('spreadsheet expired: entire course'); + # expire ALL spreadsheets + &Apache::lonnet::expirespread('','','studentcalc'); + &Apache::lonnet::expirespread('','','assesscalc'); + $r->print('

'. + &mt('Expired spreadsheet caches for all students'). + '

'); + } elsif ($env{'form.recalc'} =~ /^symb:/) { + # expire for all students on this symb + my ($symb) = ($env{'form.recalc'} =~ /^symb:(.*)$/); + &Apache::lonnet::logthis('spreadsheet expired: symb = '.$symb); + &Apache::lonnet::expirespread('','','assesscalc',$symb); + &Apache::lonnet::expirespread('','','studentcalc'); + $r->print('

'. + &mt('Expired spreadsheet caches for all students for symb [_1]', + $symb). + '

'); + } elsif ($env{'form.recalc'} =~ /^student:/) { + # expire all assessment spreadsheets for this user + my ($sname,$sdom) = ($env{'form.recalc'}=~/^student:(.*):(.*)$/); + &Apache::lonnet::logthis('spreadsheet expired: student = '. + $sname.'@'.$sdom); + if (defined($sname) && defined($sdom)) { + &Apache::lonnet::expirespread($sname,$sdom,'assesscalc'); + &Apache::lonnet::expirespread($sname,$sdom,'studentcalc'); + $r->print('

'. + &mt('Expired spreadsheet caches for student [_1]', + $sname.'@'.$sdom). + '

'); + } } } ## @@ -360,13 +497,16 @@ ENDSCRIPT &Apache::Spreadsheet::initialize_spreadsheet_package(); my $spreadsheet = undef; if ($sheettype eq 'classcalc') { - $spreadsheet = Apache::classcalc->new($name,$domain,$filename,undef); + $spreadsheet = Apache::classcalc->new($name,$domain,$filename,undef, + $section,\@groups); } elsif ($sheettype eq 'studentcalc') { - $spreadsheet = Apache::studentcalc->new($name,$domain,$filename,undef); + $spreadsheet = Apache::studentcalc->new($name,$domain,$filename,undef, + $section,\@groups); } elsif ($sheettype eq 'assesscalc' && defined($symb) && $allowed_to_edit) { - $spreadsheet = Apache::assesscalc->new($name,$domain,$filename,$symb); + $spreadsheet = Apache::assesscalc->new($name,$domain,$filename,$symb, + $section,\@groups); } else { return HTTP_NOT_ACCEPTABLE; } @@ -381,23 +521,25 @@ ENDSCRIPT ## Editing/loading/saving if ($allowed_to_edit) { my ($html,$action_message) = &file_dialogs($spreadsheet); - if ($ENV{'form.makedefault'}) { + if ($env{'form.makedefault'}) { $spreadsheet->make_default(); if ($action_message) { $action_message .= '
'; } - $action_message .= 'Made this spreadsheet the default'; + $action_message .= &mt('Made this spreadsheet the default'); if ($sheettype eq 'classcalc') { - $action_message .= ' for the course'; + $action_message .= ' '.&mt('for the course'); } elsif ($sheettype eq 'studentcalc') { - $action_message .= ' for all students'; + $action_message .= ' '.&mt('for all students'); } elsif ($sheettype eq 'assesscalc') { - $action_message .= ' for all assessments'; + $action_message .= ' '.&mt('for all assessments'); } $action_message .= '.'; } - $r->print(''. - '
'.$spreadsheet->html_header().''.$html."
\n"); + $r->print(''. + '
'. + $spreadsheet->html_header(). + ''.$html."
\n"); if ($action_message ne '') { $r->print(< @@ -415,9 +557,23 @@ END } $r->rflush(); # - if ($sheettype eq 'classcalc') { - $r->print('
'); + $r->print(""); + $r->print(''); + if ($allowed_to_view) { + $r->print(''); } + if ($allowed_to_edit) { + $r->print(''); + } + $r->print('
'. + ''. + &Apache::loncommon::help_open_topic("Spreadsheet_About", + 'Spreadsheet Help'). + ''. + &Apache::loncommon::help_open_topic("Spreadsheet_Editing", + 'Editing Help'). + '
'); # # Keep track of the filename $r->print(&hiddenfield('filename',$filename)); @@ -425,14 +581,16 @@ END # Keep track of the number of times we have been called, sort of. $r->print(&hiddenfield('not_first_run','whatever')); # - if (exists($ENV{'form.not_first_run'}) || $sheettype ne 'classcalc') { + if (exists($env{'form.not_first_run'}) || $sheettype ne 'classcalc') { $r->print($spreadsheet->get_html_title()); if ($allowed_to_view || $allowed_to_edit) { $r->print($spreadsheet->parent_link()); } + $r->rflush(); $spreadsheet->display($r); } - $r->print(''); + $r->print(''.&Apache::loncommon::end_page()); + $spreadsheet->clear_package(); return OK; }