--- loncom/homework/lonhomework.pm 2011/09/09 16:56:35 1.328
+++ loncom/homework/lonhomework.pm 2024/11/21 07:26:01 1.384
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Homework handler
#
-# $Id: lonhomework.pm,v 1.328 2011/09/09 16:56:35 bisitz Exp $
+# $Id: lonhomework.pm,v 1.384 2024/11/21 07:26:01 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -49,15 +49,23 @@ use Apache::matchresponse();
use Apache::chemresponse();
use Apache::functionplotresponse();
use Apache::drawimage();
+use Apache::loncapamath();
+use Apache::loncourseuser();
+use Apache::grades();
use Apache::Constants qw(:common);
use Apache::loncommon();
+use Apache::lonparmset();
+use Apache::lonnavmaps();
use Apache::lonlocal;
+use LONCAPA qw(:DEFAULT :match);
+use LONCAPA::ltiutils();
use Time::HiRes qw( gettimeofday tv_interval );
use HTML::Entities();
use File::Copy();
# FIXME - improve commenting
+my $registered_cleanup;
BEGIN {
&Apache::lonxml::register_insert();
@@ -155,15 +163,25 @@ sub get_target {
return ('web','answer');
} elsif (($env{'form.problemmode'} eq 'saveedit') ||
($env{'form.problemmode'} eq 'undo')) {
- return ('modified','no_output_web','edit');
+ my %editors = &Apache::loncommon::permitted_editors();
+ if ($editors{'edit'}) {
+ return ('modified','no_output_web','edit');
+ } else {
+ return ('web');
+ }
} elsif ($env{'form.problemmode'} eq 'edit') {
- return ('no_output_web','edit');
+ my %editors = &Apache::loncommon::permitted_editors();
+ if ($editors{'edit'}) {
+ return ('no_output_web','edit');
+ } else {
+ return ('web');
+ }
} else {
return ('web');
}
}
#
-# End of Construction Space
+# End of Authoring Space
#
}
#
@@ -188,7 +206,7 @@ sub proctor_checked_in {
if ($type eq 'Task') {
my $version=$Apache::lonhomework::history{'resource.0.version'};
$key ="resource.$version.0.checkedin";
- } elsif ($type eq 'problem') {
+ } elsif (($type eq 'problem') || ($type eq 'tool')) {
$key ='resource.0.checkedin';
}
# backward compatability, used to be username@domain,
@@ -203,24 +221,57 @@ sub proctor_checked_in {
return 1;
}
}
-
return 0;
}
sub check_slot_access {
- my ($id,$type)=@_;
+ my ($id,$type,$symb,$partlist)=@_;
# does it pass normal muster
- my ($status,$datemsg)=&check_access($id);
-
- my $useslots = &Apache::lonnet::EXT("resource.0.useslots");
+ my ($status,$datemsg)=&check_access($id,$symb);
+
+ my $useslots = &Apache::lonnet::EXT("resource.0.useslots",$symb);
if ($useslots ne 'resource' && $useslots ne 'map'
&& $useslots ne 'map_map') {
return ($status,$datemsg);
}
- if ($status eq 'SHOW_ANSWER' ||
- $status eq 'CLOSED' ||
+ my $checkin = 'resource.0.checkedin';
+ my $version;
+ if ($type eq 'Task') {
+ $version=$Apache::lonhomework::history{'resource.version'};
+ $checkin = "resource.$version.0.checkedin";
+ }
+ my $checkedin = $Apache::lonhomework::history{$checkin};
+ my ($returned_slot,$slot_name,$checkinslot,$ipused,$blockip,$now,$ip,
+ $consumed_uniq);
+ $now = time;
+ $ip=$ENV{'REMOTE_ADDR'} || $env{'request.host'};
+
+ if ($checkedin) {
+ $checkinslot = $Apache::lonhomework::history{"$checkin.slot"};
+ my %slot=&Apache::lonnet::get_slot($checkinslot);
+ $consumed_uniq = $slot{'uniqueperiod'};
+ if ($slot{'iptied'}) {
+ $ipused = $Apache::lonhomework::history{"$checkin.ip"};
+ unless (($ip ne '') &&
+ (($ipused eq $ip) || ($ENV{'REMOTE_ADDR'} eq '127.0.0.1'))) {
+ $blockip = $slot{'iptied'};
+ $slot_name = $checkinslot;
+ $returned_slot = \%slot;
+ }
+ }
+ }
+
+ if ($status eq 'SHOW_ANSWER') {
+ if ($blockip eq 'answer') {
+ return ('NEED_DIFFERENT_IP','',$slot_name,$returned_slot,$ipused);
+ } else {
+ return ($status,$datemsg);
+ }
+ }
+
+ if ($status eq 'CLOSED' ||
$status eq 'INVALID_ACCESS' ||
$status eq 'UNAVAILABLE') {
return ($status,$datemsg);
@@ -228,38 +279,83 @@ sub check_slot_access {
if ($env{'request.state'} eq "construct") {
return ($status,$datemsg);
}
-
+
if ($type eq 'Task') {
- my $version=$Apache::lonhomework::history{'resource.version'};
- if ($Apache::lonhomework::history{"resource.$version.0.checkedin"} &&
+ if ($checkedin &&
$Apache::lonhomework::history{"resource.$version.0.status"} eq 'pass') {
- return ('SHOW_ANSWER');
- }
+ if ($blockip eq 'answer') {
+ return ('NEED_DIFFERENT_IP','',$slot_name,$returned_slot,$ipused);
+ } else {
+ return ('SHOW_ANSWER');
+ }
+ }
+ } elsif (($type eq 'problem') &&
+ ($Apache::lonhomework::browse eq 'F') &&
+ ($ENV{'REMOTE_ADDR'} eq '127.0.0.1') &&
+ ($env{'form.grade_courseid'} eq $env{'request.course.id'}) &&
+ (&Apache::lonnet::allowed('mgr',$env{'request.course.id'}))) {
+ return ($status,$datemsg);
}
- my $availablestudent = &Apache::lonnet::EXT("resource.0.availablestudent");
- my $available = &Apache::lonnet::EXT("resource.0.available");
+ my $availablestudent = &Apache::lonnet::EXT("resource.0.availablestudent",$symb);
+ my $available = &Apache::lonnet::EXT("resource.0.available",$symb);
my @slots= (split(':',$availablestudent),split(':',$available));
# if (!@slots) {
# return ($status,$datemsg);
# }
+ undef($returned_slot);
+ undef($slot_name);
my $slotstatus='NOT_IN_A_SLOT';
- my ($returned_slot,$slot_name);
+ my $num_usable_slots = 0;
+ if (!$symb) {
+ ($symb) = &Apache::lonnet::whichuser();
+ }
foreach my $slot (@slots) {
$slot =~ s/(^\s*|\s*$)//g;
&Apache::lonxml::debug("getting $slot");
my %slot=&Apache::lonnet::get_slot($slot);
&Apache::lonhomework::showhash(%slot);
- if ($slot{'starttime'} < time &&
- $slot{'endtime'} > time &&
+ next if ($slot{'endtime'} < $now);
+ $num_usable_slots ++;
+ if ($slot{'starttime'} < $now &&
+ $slot{'endtime'} > $now &&
&Apache::loncommon::check_ip_acc($slot{'ip'})) {
- &Apache::lonxml::debug("$slot is good");
- $slotstatus='NEEDS_CHECKIN';
- $returned_slot=\%slot;
- $slot_name=$slot;
- last;
- }
+ if ($slot{'iptied'}) {
+ if ($env{'request.course.id'}) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if ($slot eq $checkinslot) {
+ if ($ip eq $ipused) {
+ &Apache::lonxml::debug("$slot is good");
+ $slotstatus ='NEEDS_CHECKIN';
+ } else {
+ $slotstatus = 'NEED_DIFFERENT_IP';
+ $slot_name = $slot;
+ $returned_slot = \%slot;
+ last;
+ }
+ } elsif ($ip) {
+ my $uniqkey = "$slot\0$symb\0$ip";
+ my %used_ip = &Apache::lonnet::get('slot_uniqueips',[$uniqkey],$cdom,$cnum);
+ if ($used_ip{$uniqkey}) {
+ $slotstatus = 'NEED_DIFFERENT_IP';
+ } else {
+ &Apache::lonxml::debug("$slot is good");
+ $slotstatus ='NEEDS_CHECKIN';
+ }
+ }
+ }
+ } else {
+ &Apache::lonxml::debug("$slot is good");
+ $slotstatus='NEEDS_CHECKIN';
+ }
+ if ($slotstatus eq 'NEEDS_CHECKIN') {
+ $returned_slot=\%slot;
+ $slot_name=$slot;
+ last;
+ }
+ }
}
if ($slotstatus eq 'NEEDS_CHECKIN' &&
&proctor_checked_in($slot_name,$returned_slot,$type)) {
@@ -267,7 +363,7 @@ sub check_slot_access {
$slotstatus=$status;
}
- my ($is_correct,$got_grade,$checkedin);
+ my ($is_correct,$got_grade);
if ($type eq 'Task') {
my $version=$Apache::lonhomework::history{'resource.0.version'};
$got_grade =
@@ -276,13 +372,49 @@ sub check_slot_access {
$is_correct =
($Apache::lonhomework::history{"resource.$version.0.status"} eq 'pass'
|| $Apache::lonhomework::history{"resource.0.solved"} =~ /^correct_/ );
- $checkedin =
- $Apache::lonhomework::history{"resource.$version.0.checkedin"};
- } elsif ($type eq 'problem') {
- $got_grade = 1;
- $checkedin = $Apache::lonhomework::history{"resource.0.checkedin"};
- $is_correct =
- ($Apache::lonhomework::history{"resource.0.solved"} =~/^correct_/);
+ } elsif (($type eq 'problem') || ($type eq 'tool')) {
+ if ((ref($partlist) eq 'ARRAY') && (@{$partlist} > 0)) {
+ my ($numcorrect,$numgraded) = (0,0);
+ foreach my $part (@{$partlist}) {
+ my $currtries = $Apache::lonhomework::history{"resource.$part.tries"};
+ my $maxtries = &Apache::lonnet::EXT("resource.$part.maxtries",$symb);
+ my $probstatus = &Apache::structuretags::get_problem_status($part);
+ my $earlyout;
+ unless (($probstatus eq 'no') ||
+ ($probstatus eq 'no_feedback_ever')) {
+ if ($Apache::lonhomework::history{"resource.$part.solved"} =~/^correct_/) {
+ $numcorrect ++;
+ } else {
+ $earlyout = 1;
+ }
+ }
+ if ($currtries == $maxtries) {
+ $earlyout = 1;
+ } else {
+ $numgraded ++;
+ }
+ last if ($earlyout);
+ }
+ my $numparts = scalar(@{$partlist});
+ if ($numparts == $numcorrect) {
+ $is_correct = 1;
+ }
+ if ($numparts == $numgraded) {
+ $got_grade = 1;
+ }
+ } else {
+ my $currtries = $Apache::lonhomework::history{"resource.0.tries"};
+ my $maxtries = &Apache::lonnet::EXT("resource.0.maxtries",$symb);
+ my $probstatus = &Apache::structuretags::get_problem_status('0');
+ unless (($probstatus eq 'no') ||
+ ($probstatus eq 'no_feedback_ever')) {
+ $is_correct =
+ ($Apache::lonhomework::history{"resource.0.solved"} =~/^correct_/);
+ }
+ unless (($currtries == $maxtries) || ($is_correct)) {
+ $got_grade = 1;
+ }
+ }
}
&Apache::lonxml::debug(" slot is $slotstatus checkedin ($checkedin) got_grade ($got_grade) is_correct ($is_correct)");
@@ -299,43 +431,127 @@ sub check_slot_access {
# However, the problem is not closed, and potentially, another slot might be
# used to gain access to it to work on it, until the due date is reached, and the
# problem then becomes CLOSED. Therefore return the slotstatus -
- # (which will be NOT_IN_SLOT).
- if (!defined($slot_name)
- && $checkedin
- && $type eq 'problem') {
- return ($slotstatus);
+ # (which will be one of: NOT_IN_A_SLOT, RESERVABLE, RESERVABLE_LATER, or NOTRESERVABLE).
+
+ if (!defined($slot_name) && (($type eq 'problem') || ($type eq 'tool'))) {
+ if ($slotstatus eq 'NOT_IN_A_SLOT') {
+ if (!$num_usable_slots) {
+ ($slotstatus,$datemsg) = &check_reservable_slot($slotstatus,$symb,$now,$checkedin,
+ $consumed_uniq);
+ }
+ }
+ return ($slotstatus,$datemsg);
}
if ($slotstatus eq 'NOT_IN_A_SLOT'
&& $checkedin ) {
if ($got_grade) {
- return ('SHOW_ANSWER');
+ if ($blockip eq 'answer') {
+ return ('NEED_DIFFERENT_IP','',$slot_name,$returned_slot,$ipused);
+ } else {
+ return ('SHOW_ANSWER');
+ }
} else {
return ('WAITING_FOR_GRADE');
}
}
- if ( $is_correct) {
- if ($type eq 'problem') {
+ if (($is_correct) && ($blockip ne 'answer')) {
+ if (($type eq 'problem') || ($type eq 'tool')) {
return ($status);
}
return ('SHOW_ANSWER');
}
if ( $status eq 'CANNOT_ANSWER' &&
- ($slotstatus ne 'NEEDS_CHECKIN' && $slotstatus ne 'NOT_IN_A_SLOT')) {
+ ($slotstatus ne 'NEEDS_CHECKIN' && $slotstatus ne 'NOT_IN_A_SLOT' &&
+ $slotstatus ne 'NEED_DIFFERENT_IP') ) {
return ($status,$datemsg);
}
+ return ($slotstatus,$datemsg,$slot_name,$returned_slot,$ipused);
+}
- return ($slotstatus,$datemsg,$slot_name,$returned_slot);
+sub check_reservable_slot {
+ my ($slotstatus,$symb,$now,$checkedin,$consumed_uniq) = @_;
+ my $datemsg;
+ if ($slotstatus eq 'NOT_IN_A_SLOT') {
+ if ($env{'request.course.id'}) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ unless ($symb) {
+ ($symb)=&Apache::lonnet::whichuser();
+ }
+ $slotstatus = 'NOTRESERVABLE';
+ my ($reservable_now_order,$reservable_now,$reservable_future_order,
+ $reservable_future) =
+ &Apache::loncommon::get_future_slots($cnum,$cdom,$now,$symb);
+ if ((ref($reservable_now_order) eq 'ARRAY') && (ref($reservable_now) eq 'HASH')) {
+ if (@{$reservable_now_order} > 0) {
+ if ((!$checkedin) || (ref($consumed_uniq) ne 'ARRAY')) {
+ $slotstatus = 'RESERVABLE';
+ $datemsg = $reservable_now->{$reservable_now_order->[-1]}{'endreserve'};
+ } else {
+ my ($uniqstart,$uniqend,$useslot);
+ if (ref($consumed_uniq) eq 'ARRAY') {
+ ($uniqstart,$uniqend)=@{$consumed_uniq};
+ }
+ foreach my $slot (reverse(@{$reservable_now_order})) {
+ if ($reservable_now->{$slot}{'uniqueperiod'} =~ /^(\d+)\,(\d+)$/) {
+ my ($new_uniq_start,$new_uniq_end) = ($1,$2);
+ next if (!
+ ($uniqstart < $new_uniq_start && $uniqend < $new_uniq_start) ||
+ ($uniqstart > $new_uniq_end && $uniqend > $new_uniq_end ));
+ }
+ $useslot = $slot;
+ last;
+ }
+ if ($useslot) {
+ $slotstatus = 'RESERVABLE';
+ $datemsg = $reservable_now->{$useslot}{'endreserve'};
+ }
+ }
+ }
+ }
+ unless ($slotstatus eq 'RESERVABLE') {
+ if ((ref($reservable_future_order) eq 'ARRAY') && (ref($reservable_future) eq 'HASH')) {
+ if (@{$reservable_future_order} > 0) {
+ if ((!$checkedin) || (ref($consumed_uniq) ne 'ARRAY')) {
+ $slotstatus = 'RESERVABLE_LATER';
+ $datemsg = $reservable_future->{$reservable_future_order->[0]}{'startreserve'};
+ } else {
+ my ($uniqstart,$uniqend,$useslot);
+ if (ref($consumed_uniq) eq 'ARRAY') {
+ ($uniqstart,$uniqend)=@{$consumed_uniq};
+ }
+ foreach my $slot (@{$reservable_future_order}) {
+ if ($reservable_future->{$slot}{'uniqueperiod'} =~ /^(\d+),(\d+)$/) {
+ my ($new_uniq_start,$new_uniq_end) = ($1,$2);
+ next if (!
+ ($uniqstart < $new_uniq_start && $uniqend < $new_uniq_start) ||
+ ($uniqstart > $new_uniq_end && $uniqend > $new_uniq_end ));
+ }
+ $useslot = $slot;
+ last;
+ }
+ if ($useslot) {
+ $slotstatus = 'RESERVABLE_LATER';
+ $datemsg = $reservable_future->{$useslot}{'startreserve'};
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return ($slotstatus,$datemsg);
}
# JB, 9/24/2002: Any changes in this function may require a change
# in lonnavmaps::resource::getDateStatus.
sub check_access {
- my ($id) = @_;
+ my ($id,$symb) = @_;
my $date ='';
my $status;
my $datemsg = '';
@@ -365,11 +581,13 @@ sub check_access {
&Apache::lonxml::debug("checking for part :$id:");
&Apache::lonxml::debug("time:".time);
- my ($symb)=&Apache::lonnet::whichuser();
+ unless ($symb) {
+ ($symb)=&Apache::lonnet::whichuser();
+ }
&Apache::lonxml::debug("symb:".$symb);
#if ($env{'request.state'} ne "construct" && $symb ne '') {
if ($env{'request.state'} ne "construct") {
- my $idacc = &Apache::lonnet::EXT("resource.$id.acc");
+ my $idacc = &Apache::lonnet::EXT("resource.$id.acc",$symb);
my $allowed=&Apache::loncommon::check_ip_acc($idacc);
if (!$allowed && ($Apache::lonhomework::browse ne 'F')) {
$status='INVALID_ACCESS';
@@ -385,12 +603,12 @@ sub check_access {
foreach my $temp ("opendate","duedate","answerdate") {
$lastdate = $date;
if ($temp eq 'duedate') {
- $date = &due_date($id);
+ $date = &due_date($id,$symb);
} else {
- $date = &Apache::lonnet::EXT("resource.$id.$temp");
+ $date = &Apache::lonnet::EXT("resource.$id.$temp",$symb);
}
- my $thistype = &Apache::lonnet::EXT("resource.$id.$temp.type");
+ my $thistype = &Apache::lonnet::EXT("resource.$id.$temp.type",$symb);
if ($thistype =~ /^(con_lost|no_such_host)/ ||
$date =~ /^(con_lost|no_such_host)/) {
$status='UNAVAILABLE';
@@ -399,10 +617,10 @@ sub check_access {
}
if ($thistype eq 'date_interval') {
if ($temp eq 'opendate') {
- $date=&Apache::lonnet::EXT("resource.$id.duedate")-$date;
+ $date=&Apache::lonnet::EXT("resource.$id.duedate",$symb)-$date;
}
if ($temp eq 'answerdate') {
- $date=&Apache::lonnet::EXT("resource.$id.duedate")+$date;
+ $date=&Apache::lonnet::EXT("resource.$id.duedate",$symb)+$date;
}
}
&Apache::lonxml::debug("found :$date: for :$temp:");
@@ -422,33 +640,33 @@ sub check_access {
$datemsg=$date;
} elsif ($type eq 'opendate') {
$status='CLOSED';
- $datemsg = &mt("will open on")." $date";
+ $datemsg = &mt('will open on [_1]',$date);
} elsif ($type eq 'duedate') {
$status='CAN_ANSWER';
- $datemsg = &mt("is due at")." $date";
+ $datemsg = &mt('is due at [_1]',$date);
} elsif ($type eq 'answerdate') {
$status='CLOSED';
- $datemsg = &mt("was due on")." $lastdate".&mt(", and answers will be available on")." $date";
+ $datemsg = &mt('was due on [_1], and answers will be available on [_2]',
+ $lastdate,$date);
}
}
if ($status eq 'CAN_ANSWER' ||
(($Apache::lonhomework::browse eq 'F') && ($status eq 'CLOSED'))) {
#check #tries, and if correct.
my $tries = $Apache::lonhomework::history{"resource.$id.tries"};
- my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries");
+ my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries",$symb);
if ( $tries eq '' ) { $tries = '0'; }
if ( $maxtries eq '' &&
$env{'request.state'} ne 'construct') { $maxtries = '2'; }
- $Apache::lonhomework::results{'resource.'.$id.'.maxtries'}=$maxtries;
if ($maxtries && $tries >= $maxtries) { $status = 'CANNOT_ANSWER'; }
# if (correct and show prob status) or excused then CANNOT_ANSWER
- if(($Apache::lonhomework::history{"resource.$id.solved"}=~/^correct/
- &&
- &show_problem_status()
- &&
- $Apache::lonhomework::history{"resource.$id.awarded"}==1)
- ||
- $Apache::lonhomework::history{"resource.$id.solved"}=~/^excused/) {
+ if ( ($Apache::lonhomework::history{"resource.$id.solved"}=~/^correct/)
+ && (&show_problem_status()) ) {
+ if (($Apache::lonhomework::history{"resource.$id.awarded"} >= 1) ||
+ (&Apache::lonnet::EXT("resource.$id.retrypartial",$symb) !~/^1|on|yes$/i)) {
+ $status = 'CANNOT_ANSWER';
+ }
+ } elsif ($Apache::lonhomework::history{"resource.$id.solved"}=~/^excused/) {
$status = 'CANNOT_ANSWER';
}
if ($status eq 'CANNOT_ANSWER'
@@ -457,17 +675,18 @@ sub check_access {
}
}
if ($status eq 'CAN_ANSWER' || $status eq 'CANNOT_ANSWER') {
- my @interval=&Apache::lonnet::EXT("resource.$id.interval");
+ my @interval=&Apache::lonnet::EXT("resource.$id.interval",$symb);
&Apache::lonxml::debug("looking for interval @interval");
- if ($interval[0]) {
- my $first_access=&Apache::lonnet::get_first_access($interval[1]);
+ if ($interval[0]=~ /^\d+/) {
+ my $first_access=&Apache::lonnet::get_first_access($interval[1],$symb);
&Apache::lonxml::debug("looking for accesstime $first_access");
if (!$first_access) {
$status='NOT_YET_VIEWED';
- my $due_date = &due_date($id);
+ my $due_date = &due_date($id,$symb);
my $seconds_left = $due_date - time;
- if ($seconds_left > $interval[0] || $due_date eq '') {
- $seconds_left = $interval[0];
+ my ($timelimit) = ($interval[0] =~ /^(\d+)/);
+ if ($seconds_left > $timelimit || $due_date eq '') {
+ $seconds_left = $timelimit;
}
$datemsg=&seconds_to_human_length($seconds_left);
}
@@ -479,7 +698,6 @@ sub check_access {
# return ('UNCHECKEDOUT','needs to be checked out');
#}
-
&Apache::lonxml::debug("sending back :$status:$datemsg:");
if (($Apache::lonhomework::browse eq 'F') && ($status eq 'CLOSED')) {
&Apache::lonxml::debug("should be allowed to browse a resource when closed");
@@ -503,7 +721,8 @@ sub due_date {
my $first_access=&Apache::lonnet::get_first_access($interval[1],$symb);
&Apache::lonxml::debug("looking for first_access $first_access ($interval[1])");
if (defined($first_access)) {
- my $interval = $first_access+$interval[0];
+ my ($timelimit) = ($interval[0] =~ /^(\d+)/);
+ my $interval = $first_access+$timelimit;
$date = (!$due_date || $interval < $due_date) ? $interval
: $due_date;
} else {
@@ -512,7 +731,7 @@ sub due_date {
} else {
$date = $due_date;
}
- return $date
+ return $date;
}
sub seconds_to_human_length {
@@ -561,7 +780,7 @@ sub showarray {
sub showhashsubset {
my ($hash,$keyre) = @_;
my $resultkey;
- foreach $resultkey (sort keys %$hash) {
+ foreach $resultkey (sort(keys(%$hash))) {
if ($resultkey !~ /$keyre/) { next; }
if (ref($$hash{$resultkey}) eq 'ARRAY' ) {
&Apache::lonxml::debug("$resultkey ---- ".
@@ -579,12 +798,18 @@ sub showhashsubset {
sub setuppermissions {
$Apache::lonhomework::browse= &Apache::lonnet::allowed('bre',$env{'request.filename'});
+ unless ($Apache::lonhomework::browse eq 'F') {
+ $Apache::lonhomework::browse=&Apache::lonnet::allowed('bro',$env{'request.filename'});
+ }
my $viewgrades = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
if (! $viewgrades &&
exists($env{'request.course.sec'}) &&
$env{'request.course.sec'} !~ /^\s*$/) {
$viewgrades = &Apache::lonnet::allowed('vgr',$env{'request.course.id'}.
'/'.$env{'request.course.sec'});
+ if ($viewgrades) {
+ $Apache::lonhomework::viewgradessec = $env{'request.course.sec'};
+ }
}
$Apache::lonhomework::viewgrades = $viewgrades;
@@ -602,6 +827,9 @@ sub setuppermissions {
$modifygrades =
&Apache::lonnet::allowed('mgr',$env{'request.course.id'}.
'/'.$env{'request.course.sec'});
+ if ($modifygrades) {
+ $Apache::lonhomework::modifygradessec = $env{'request.course.sec'};
+ }
}
$Apache::lonhomework::modifygrades = $modifygrades;
@@ -620,7 +848,9 @@ sub setuppermissions {
sub unset_permissions {
undef($Apache::lonhomework::queuegrade);
undef($Apache::lonhomework::modifygrades);
+ undef($Apache::lonhomework::modifygradessec);
undef($Apache::lonhomework::viewgrades);
+ undef($Apache::lonhomework::viewgradessec);
undef($Apache::lonhomework::browse);
}
@@ -638,7 +868,7 @@ sub setupheader {
}
sub handle_save_or_undo {
- my ($request,$problem,$result) = @_;
+ my ($request,$problem,$result,$getobjref) = @_;
my $file = &Apache::lonnet::filelocation("",$request->uri);
my $filebak =$file.".bak";
@@ -681,6 +911,30 @@ sub handle_save_or_undo {
my $fh=Apache::File->new(">$file");
if (defined($fh)) {
print $fh $$result;
+ if (ref($getobjref) eq 'SCALAR') {
+ if ($file =~ m{([^/]+)\.(html?)$}) {
+ my $fname = $1;
+ my $ext = $2;
+ my $path = $file;
+ $path =~ s/\Q$fname\E\.\Q$ext\E$//;
+ my (%allfiles,%codebase);
+ &Apache::lonnet::extract_embedded_items($file,\%allfiles,
+ \%codebase,$result);
+ if (keys(%allfiles) > 0) {
+ my $url = $request->uri;
+ my $state = <
".&mt("Completed upload of the file. This file contained references to other files.")."
". + "".&mt("Please select the locations from which the referenced files are to be uploaded.")."
". + &Apache::loncommon::ask_for_embedded_content($url,$state,\%allfiles,\%codebase, + {'error_on_invalid_names' => 1, + 'ignore_remote_references' => 1,}); + } + } + } } else { &Apache::lonxml::info(''. &mt("Unable to write to [_1]", @@ -695,11 +949,20 @@ sub handle_save_or_undo { sub analyze_header { my ($request) = @_; - my $js = &Apache::structuretags::setmode_javascript(); + my $js = &Apache::lonxml::setmode_javascript(); # Breadcrumbs - my $brcrum = [{'href' => &Apache::loncommon::authorspace(), - 'text' => 'Construction Space'}, + my $text = 'Authoring Space'; + my $href = &Apache::loncommon::authorspace($request->uri); + if ($env{'request.course.id'}) { + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + if ($href eq "/priv/$cdom/$cnum/") { + $text = 'Course Authoring Space'; + } + } + my $brcrum = [{'href' => $href, + 'text' => $text}, {'href' => '', 'text' => 'Problem Testing'}, {'href' => '', @@ -711,24 +974,32 @@ sub analyze_header { {'bread_crumbs' => $brcrum,}) .&Apache::loncommon::head_subbox( &Apache::loncommon::CSTR_pageheader()); + my %lt = &Apache::lonlocal::texthash( + edit => 'Edit', + editxml => 'EditXML', + ); $result .= - &Apache::lonxml::message_location().' - '; &Apache::lonxml::add_messages(\$result); $request->print($result); $request->rflush(); @@ -750,13 +1021,9 @@ sub analyze { my $rndseed=$env{'form.rndseed'}; &analyze_header($request); my %prog_state= - &Apache::lonhtmlcommon::Create_PrgWin($request,&mt('Analyze Progress'), - &mt('Getting Problem Variants'), - $env{'form.numtoanalyze'}, - 'inline',undef); + &Apache::lonhtmlcommon::Create_PrgWin($request,$env{'form.numtoanalyze'}); for(my $i=1;$i<$env{'form.numtoanalyze'}+1;$i++) { - &Apache::lonhtmlcommon::Increment_PrgWin($request,\%prog_state, - &mt('last problem')); + &Apache::lonhtmlcommon::Increment_PrgWin($request,\%prog_state,'last problem'); if (&Apache::loncommon::connection_aborted($request)) { return; } my $thisseed=$i+$rndseed; my $subresult=&Apache::lonnet::ssi($request->uri, @@ -765,7 +1032,7 @@ sub analyze { (my $garbage,$subresult)=split(/_HASH_REF__/,$subresult,2); my %analyze=&Apache::lonnet::str2hash($subresult); my @parts; - if (defined(@{ $analyze{'parts'} })) { + if (ref($analyze{'parts'}) eq 'ARRAY') { @parts=@{ $analyze{'parts'} }; } foreach my $part (@parts) { @@ -798,15 +1065,15 @@ sub analyze { } } } - &Apache::lonhtmlcommon::Update_PrgWin($request,\%prog_state, - &mt('Analyzing Results')); + &Apache::lonhtmlcommon::Update_PrgWin($request,\%prog_state,&mt('Analyzing Results')); $request->print('