--- loncom/interface/lonnavmaps.pm 2011/10/07 15:10:12 1.444.2.6 +++ loncom/interface/lonnavmaps.pm 2011/12/18 17:15:03 1.472 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.444.2.6 2011/10/07 15:10:12 raeburn Exp $ +# $Id: lonnavmaps.pm,v 1.472 2011/12/18 17:15:03 raeburn Exp $ # # Copyright Michigan State University Board of Trustees @@ -225,7 +225,7 @@ automatically. =over 4 -=item * B: default: constructs one from %env +=item * B 'Correct', 'navmap.wrong.gif' => 'Incorrect', - 'navmap.open.gif' => 'Open', + 'navmap.open.gif' => 'Is Open', 'navmap.partial.gif' => 'Partially Correct', 'navmap.ellipsis.gif' => 'Attempted', ); @@ -527,8 +533,8 @@ my %colormap = $resObj->INCORRECT => '', $resObj->OPEN => '', $resObj->NOTHING_SET => '', - $resObj->CREDIT_ATTEMPTED => '', $resObj->ATTEMPTED => '', + $resObj->CREDIT_ATTEMPTED => '', $resObj->ANSWER_SUBMITTED => '', $resObj->PARTIALLY_CORRECT => '#006600' ); @@ -539,35 +545,6 @@ my $hurryUpColor = "#FF0000"; my $future_slots_checked = 0; my $future_slots = 0; -sub close { - if ($env{'environment.remotenavmap'} ne 'on') { return ''; } - return(< -window.status='Accessing Nav Control'; -menu=window.open("/adm/rat/empty.html","loncapanav", - "height=600,width=400,scrollbars=1"); -window.status='Closing Nav Control'; -menu.close(); -window.status='Done.'; - -ENDCLOSE -} - -sub update { - if ($env{'environment.remotenavmap'} ne 'on') { return ''; } - if (!$env{'request.course.id'}) { return ''; } - if ($ENV{'REQUEST_URI'}=~m|^/adm/navmaps|) { return ''; } - return(< - -ENDUPDATE -} - - sub addToFilter { my $hashIn = shift; my $addition = shift; @@ -638,10 +615,10 @@ sub getDescription { return &mt("Having technical difficulties; please check status later"); } if ($status == $res->NOTHING_SET) { - return &mt("Not currently assigned."); + return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part); } if ($status == $res->OPEN_LATER) { - return &mt("Open ") .timeToHumanString($open,'start'); + return &mt("Open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start'),$res->symb(),'opendate',$part)); } if ($res->simpleStatus($part) == $res->OPEN) { unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) { @@ -675,27 +652,27 @@ sub getDescription { if ($status == $res->OPEN) { if ($due) { if ($res->is_practice()) { - return &mt("Closes ")." " .timeToHumanString($due,'start'); + return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part)); } else { - return &mt("Due")." " .timeToHumanString($due,'end'); + return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)); } } else { - return &mt("Open, no due date"); + return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part); } } if ($status == $res->PAST_DUE_ANSWER_LATER) { - return &mt("Answer open")." " .timeToHumanString($answer,'start'); + return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part)); } if ($status == $res->PAST_DUE_NO_ANSWER) { if ($res->is_practice()) { - return &mt("Closed")." " . timeToHumanString($due,'start'); + return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part)); } else { - return &mt("Was due")." " . timeToHumanString($due,'end'); + return &mt("Was due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'answerdate,duedate',$part)); } } if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) && $res->handgrade($part) ne 'yes') { - return &mt("Answer available"); + return &Apache::lonhtmlcommon::direct_parm_link(&mt("Answer available"),$res->symb(),'answerdate,duedate',$part); } if ($status == $res->EXCUSED) { return &mt("Excused by instructor"); @@ -723,10 +700,10 @@ sub getDescription { } } if ($due) { - return &mt("Due")." " . timeToHumanString($due,'end') . + return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)) . " $triesString"; } else { - return &mt("No due date")." $triesString"; + return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString"; } } if ($status == $res->ANSWER_SUBMITTED) { @@ -832,7 +809,7 @@ sub timeToHumanString { } # Is it less than 24 hours away? If so, - # display hours + minutes, (and + seconds, if format specified it) + # display hours + minutes, (and + seconds, if format specified it) if ( $delta < $hour * 24) { my $hours = floor($delta / $hour); my $minutes = floor(($delta % $hour) / $minute); @@ -870,7 +847,7 @@ sub timeToHumanString { # If there's a caller supplied format, use it, unless it only displays # H:M:S or H:M. - if (($format ne '') && ($format ne '%T') && ($format ne '%R')) { + if (($format ne '') && ($format ne '%T') && ($format ne '%R')) { my $timeStr = $dt->strftime($format); return $timeStr.' ('.$dt->time_zone_short_name().')'; } @@ -1006,10 +983,10 @@ sub render_resource { } if ($resource->randomout()) { - $nonLinkedText .= ' ('.&mt('hidden').') '; + $nonLinkedText .= ' ('.&mt('hidden').') '; } if (!$resource->condval()) { - $nonLinkedText .= ' ('.&mt('conditionally hidden').') '; + $nonLinkedText .= ' ('.&mt('conditionally hidden').') '; } if (($resource->is_practice()) && ($resource->is_raw_problem())) { $nonLinkedText .=' '.&mt('not graded').''; @@ -1036,8 +1013,8 @@ sub render_resource { # Is this the current resource? if (!$params->{'displayedHereMarker'} && $resource->symb() eq $params->{'here'} ) { - $curMarkerBegin = ''; - $curMarkerEnd = ''; + $curMarkerBegin = ''; + $curMarkerEnd = ''; $params->{'displayedHereMarker'} = 1; } @@ -1053,12 +1030,8 @@ sub render_resource { $nonLinkedText .= ' ('.&mt('[_1] parts', $resource->countParts()).')'; } - my $target; - if ($env{'environment.remotenavmap'} eq 'on') { - $target=' target="loncapaclient" '; - } if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { - $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$nonLinkedText"; + $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$nonLinkedText"; } else { $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$nonLinkedText"; } @@ -1071,11 +1044,7 @@ sub render_communication_status { my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = ""; my $link = $params->{"resourceLink"}; - my $target; - if ($env{'environment.remotenavmap'} eq 'on') { - $target=' target="loncapaclient" '; - } - my $linkopen = ""; + my $linkopen = ""; my $linkclose = ""; my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); if ($resource->hasDiscussion()) { @@ -1088,7 +1057,7 @@ sub render_communication_status { my $feedback = $resource->getFeedback(); foreach my $msgid (split(/\,/, $feedback)) { if ($msgid) { - $feedbackHTML .= ' ' . ''.&mt('New E-mail').''; } @@ -1102,7 +1071,7 @@ sub render_communication_status { last if ($errorcount>=10); # Only output 10 bombs maximum if ($msgid) { $errorcount++; - $errorHTML .= ' ' . ''.&mt('New Error').''; } @@ -1122,11 +1091,7 @@ sub render_quick_status { $params->{'multipart'} && $part eq "0"; my $link = $params->{"resourceLink"}; - my $target; - if ($env{'environment.remotenavmap'} eq 'on') { - $target=' target="loncapaclient" '; - } - my $linkopen = ""; + my $linkopen = ""; my $linkclose = ""; $result .= ''; @@ -1170,6 +1135,14 @@ sub render_long_status { $result .= getDescription($resource, $part); if ($color) {$result .= ""; } } + if ($resource->is_map()) { + if (&Apache::lonnet::allowed('mdc')) { + if ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/) { + $result.=" ". + "".&mt("Edit Content").' '; + } + } + } if ($resource->is_map() && &advancedUser() && $resource->randompick()) { $result .= &mt('(randomly select [_1])', $resource->randompick()); } @@ -1424,6 +1397,7 @@ sub render { } } + # (re-)Locate the jump point, if any # Note this does not take filtering or hidden into account... need # to be fixed? @@ -1492,9 +1466,9 @@ sub render { } if ($args->{'caller'} eq 'navmapsdisplay') { &add_linkitem($args->{'linkitems'},'changefolder', - "location.href='$link'",$text); + "location.href='$link'",$text); } else { - $result.= ''.&mt($text).''; + $result.= ''.&mt($text).''; } $result .= "\n"; } @@ -1536,19 +1510,13 @@ END if ($args->{'caller'} eq 'navmapsdisplay') { $result .= ''. - ''. - &show_linkitems_toolbar($args->{'linkitems'}); + &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').''; + $result .= ''; + $result.=''; + $result.=&show_linkitems_toolbar($args->{'linkitems'}); if ($args->{'sort_html'}) { - if ($env{'environment.remotenavmap'} ne 'on') { - $result .= ''. - ''; - } else { - $result .= ''; - } - } else { - $result .= ''; + $result.=''. + ''; } $result .= '
'. - &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').' '.&mt('Tools:').' '.&mt('Tools:').'   '.$args->{'sort_html'}.'

'. - $args->{'sort_html'}.'
   '.$args->{'sort_html'}.'
'; } elsif ($args->{'sort_html'}) { @@ -1682,6 +1650,7 @@ END $curRes = shift(@resources); } else { $curRes = $it->next($closeAllPages); + } if (!$curRes) { last; } @@ -1888,9 +1857,9 @@ sub add_linkitem { sub show_linkitems_toolbar { my ($linkitems,$condition)=@_; - my @linkorder = ("launchnav","closenav","firsthomework", - "everything","uncompleted","changefolder","clearbubbles"); - my $result .=''."\n". + my @linkorder = ('firsthomework','everything','uncompleted', + 'changefolder','clearbubbles'); + my $result .=''."\n". ''."\n". '
    '; foreach my $link (@linkorder) { @@ -2008,6 +1977,12 @@ sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; + bless($self); # So we can call change_user if neceesary + + $self->{USERNAME} = shift || $env{'user.name'}; + $self->{DOMAIN} = shift || $env{'user.domain'}; + + # Resource cache stores navmap resources as we reference them. We generate # them on-demand so we don't pay for creating resources unless we use them. @@ -2017,38 +1992,103 @@ sub new { # failed $self->{NETWORK_FAILURE} = 0; - # tie the nav hash + # We can only tie the nav hash as done below if the username/domain + # match the env one. Otherwise change_user does everything we need...since we can't + # assume there are course hashes for the specific requested user@domamin: + # - my %navmaphash; - my %parmhash; - my $courseFn = $env{"request.course.fn"}; - if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", - &GDBM_READER(), 0640))) { - return undef; - } - - if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db", - &GDBM_READER(), 0640))) - { - untie %{$self->{PARM_HASH}}; - return undef; + if ( ($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'})) { + + # tie the nav hash + + my %navmaphash; + my %parmhash; + my $courseFn = $env{"request.course.fn"}; + if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", + &GDBM_READER(), 0640))) { + return undef; + } + + if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db", + &GDBM_READER(), 0640))) + { + untie %{$self->{PARM_HASH}}; + return undef; + } + + $self->{NAV_HASH} = \%navmaphash; + $self->{PARM_HASH} = \%parmhash; + $self->{PARM_CACHE} = {}; + } else { + $self->change_user($self->{USERNAME}, $self->{DOMAIN}); } - $self->{NAV_HASH} = \%navmaphash; - $self->{PARM_HASH} = \%parmhash; - $self->{PARM_CACHE} = {}; + my $d = Data::Dumper->new([$self]); - bless($self); - return $self; } +# +# In some instances it is useful to be able to dynamically change the +# username/domain associated with a navmap (e.g. to navigate for someone +# else besides the current user...if sufficiently privileged. +# Parameters: +# user - New user. +# domain- Domain the user belongs to. +# Implicit inputs: +# +sub change_user { + my $self = shift; + $self->{USERNAME} = shift; + $self->{DOMAIN} = shift; + + # If the hashes are already tied make sure to break that bond: + + untie %{$self->{NAV_HASH}}; + untie %{$self->{PARM_HASH}}; + + # The assumption is that we have to + # use lonmap here to re-read the hash and from it reconstruct + # new big and parameter hashes. An implicit assumption at this time + # is that the course file is probably not created locally yet + # an that we will therefore just read without tying. + + my ($cdom, $cnum) = split(/\_/, $env{'request.course.id'}); + + my %big_hash; + &Apache::lonmap::loadmap($cnum, $cdom, $self->{USERNAME}, $self->{DOMAIN}, \%big_hash); + $self->{NAV_HASH} = \%big_hash; + + + + # Now clear the parm cache and reconstruct the parm hash fromt he big_hash + # param.xxxx keys. + + $self->{PARM_CACHE} = {}; + + my %parm_hash = {}; + foreach my $key (keys %big_hash) { + if ($key =~ /^param\./) { + my $param_key = $key; + $param_key =~ s/^param\.//; + $parm_hash{$param_key} = $big_hash{$key}; + } + } + + $self->{PARM_HASH} = \%parm_hash; + + + + +} + sub generate_course_user_opt { my $self = shift; if ($self->{COURSE_USER_OPT_GENERATED}) { return; } - my $uname=$env{'user.name'}; - my $udom=$env{'user.domain'}; + my $uname=$self->{USERNAME}; + my $udom=$self->{DOMAIN}; + my $cid=$env{'request.course.id'}; my $cdom=$env{'course.'.$cid.'.domain'}; my $cnum=$env{'course.'.$cid.'.num'}; @@ -2091,7 +2131,7 @@ sub generate_email_discuss_status { my $cdom=$env{'course.'.$cid.'.domain'}; my $cnum=$env{'course.'.$cid.'.num'}; - my %emailstatus = &Apache::lonnet::dump('email_status'); + my %emailstatus = &Apache::lonnet::dump('email_status',$self->{DOMAIN},$self->{USERNAME}); my $logoutTime = $emailstatus{'logout'}; my $courseLeaveTime = $emailstatus{'logout_'.$env{'request.course.id'}}; $self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? @@ -2099,7 +2139,7 @@ sub generate_email_discuss_status { my %discussiontime = &Apache::lonnet::dump('discussiontimes', $cdom, $cnum); my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss', - $env{'user.domain'},$env{'user.name'},'lastread'); + $self->{DOMAIN},$self->{USERNAME},'lastread'); my %lastreadtime = (); foreach my $key (keys %lastread) { my $shortkey = $key; @@ -2109,8 +2149,8 @@ sub generate_email_discuss_status { my %feedback=(); my %error=(); - my @keys = &Apache::lonnet::getkeys('nohist_email',$env{'user.domain'}, - $env{'user.name'}); + my @keys = &Apache::lonnet::getkeys('nohist_email',$self->{DOMAIN}, + $self->{USERNAME}); foreach my $msgid (@keys) { if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { @@ -2158,8 +2198,8 @@ sub get_user_data { # Retrieve performance data on problems my %student_data = Apache::lonnet::currentdump($env{'request.course.id'}, - $env{'user.domain'}, - $env{'user.name'}); + $self->{DOMAIN}, + $self->{USERNAME}); $self->{STUDENT_DATA} = \%student_data; $self->{RETRIEVED_USER_DATA} = 1; @@ -2473,7 +2513,7 @@ sub parmval { my $self = shift; my ($what,$symb,$recurse)=@_; my $hashkey = $what."|||".$symb; - + my $cache = $self->{PARM_CACHE}; if (defined($self->{PARM_CACHE}->{$hashkey})) { if (ref($self->{PARM_CACHE}->{$hashkey}) eq 'ARRAY') { if (defined($self->{PARM_CACHE}->{$hashkey}->[0])) { @@ -2510,8 +2550,8 @@ sub parmval_real { @cgrps = sort(@cgrps); $cgroup = $cgrps[0]; } - my $uname=$env{'user.name'}; - my $udom=$env{'user.domain'}; + my $uname=$self->{USERNAME}; + my $udom=$self->{DOMAIN}; unless ($symb) { return ['']; } my $result=''; @@ -2658,7 +2698,7 @@ in the filter function. Retrieves version infomation for a url. Returns the version (a number, or the string "mostrecent") for resources which have version information in the big hash. - + =cut @@ -2913,6 +2953,9 @@ sub new { weaken($self->{NAV_MAP} = shift); return undef unless ($self->{NAV_MAP}); + $self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; + $self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; + # Handle the parameters $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); @@ -3026,12 +3069,15 @@ sub new { if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { my $firstResource = $resource->map_start(); my $finishResource = $resource->map_finish(); - return - Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, - $finishResource, $self->{FILTER}, - $self->{ALREADY_SEEN}, - $self->{CONDITION}, - $self->{FORCE_TOP}); + my $result; + my $rdump = Data::Dumper->new([$result]); + $result = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, + $finishResource, $self->{FILTER}, + $self->{ALREADY_SEEN}, + $self->{CONDITION}, + $self->{FORCE_TOP}); + return $result; + } @@ -3051,6 +3097,7 @@ sub new { $self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; bless ($self); + my $selfDump = Data::Dumper->new([$self]); return $self; } @@ -3066,6 +3113,8 @@ sub next { # do so. if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { $self->{HAVE_RETURNED_0} = 1; + my $nextTopLevel = $self->{NAV_MAP}->getById('0.0'); + return $self->{NAV_MAP}->getById('0.0'); } if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) { @@ -3085,13 +3134,13 @@ sub next { if ($self->{RECURSIVE_DEPTH} == 0) { $self->{RECURSIVE_ITERATOR_FLAG} = 0; } - return $next; } if (defined($self->{FORCE_NEXT})) { my $tmp = $self->{FORCE_NEXT}; $self->{FORCE_NEXT} = undef; + return $tmp; } @@ -3161,6 +3210,8 @@ sub next { # So we need to look at all the resources we can get to from here, # categorize them if we haven't seen them, remember if we have a new my $nextUnfiltered = $here->getNext(); + + my $maxDepthAdded = -1; for (@$nextUnfiltered) { @@ -3194,7 +3245,6 @@ sub next { $self->{RECURSIVE_ITERATOR_FLAG} = 1; my $firstResource = $self->{HERE}->map_start(); my $finishResource = $self->{HERE}->map_finish(); - $self->{RECURSIVE_ITERATOR} = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, $finishResource, $self->{FILTER}, @@ -3212,6 +3262,8 @@ sub next { return $self->next($closeAllPages); } + my $hereResource = $self->{HERE}; + return $self->{HERE}; } @@ -3286,6 +3338,9 @@ sub new { weaken($self->{NAV_MAP} = shift); return undef unless ($self->{NAV_MAP}); + $self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; + $self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; + $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); @@ -3375,6 +3430,7 @@ sub next { my $nextUnfiltered; if ($self->{DIRECTION} == FORWARD()) { $nextUnfiltered = $self->{HERE}->getNext(); + } else { $nextUnfiltered = $self->{HERE}->getPrevious(); } @@ -3522,6 +3578,9 @@ sub new { weaken($self->{NAV_MAP} = shift); $self->{ID} = shift; + $self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; + $self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; + # Store this new resource in the parent nav map's cache. $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self; $self->{RESOURCE_ERROR} = 0; @@ -3544,7 +3603,7 @@ sub navHash { my $param = shift; my $id = shift; my $arg = $param . ($id?$self->{ID}:""); - if (defined($arg)) { + if (ref($self) && ref($self->{NAV_MAP}) && defined($arg)) { return $self->{NAV_MAP}->navhash($arg); } return; @@ -3785,7 +3844,7 @@ sub is_practice { sub is_problem { my $self=shift; my $src = $self->src(); - if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) { + if ($src =~ /$LONCAPA::assess_re/) { return !($self->is_practice()); } return 0; @@ -3808,9 +3867,7 @@ my %incomplete_hash = sub is_incomplete { my $self = shift; if ($self->is_problem()) { - &Apache::lonnet::logthis('is problem'); foreach my $part (@{$self->parts()}) { - &Apache::lonnet::logthis("$part status ".$self->status($part)); if (exists($incomplete_hash{$self->status($part)})) { return 1; } @@ -3822,7 +3879,7 @@ sub is_incomplete { sub is_raw_problem { my $self=shift; my $src = $self->src(); - if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) { + if ($src =~ /$LONCAPA::assess_re/) { return 1; } return 0; @@ -3966,7 +4023,6 @@ sub map_hierarchy { return $self->navHash("map_hierarchy_$pc", 0); } - ##### # Property queries ##### @@ -3996,7 +4052,17 @@ their code.) =over 4 -=item * B: +=item * B + +returns true if the current date is such that the +specified resource part is printable. + +=item * B + +Returns true if all parts in the resource are printable making the +entire resource printable. + +=item * B Get the Client IP/Name Access Control information. @@ -4049,6 +4115,55 @@ Get the weight for the problem. =cut +sub printable { + + my ($self, $part) = @_; + + # Get the print open/close dates for the resource. + + my $start = $self->parmval("prinstartdate", $part); + my $end = $self->parmval("printenddate", $part); + + # The following cases apply: + # - No dates set: Printable. + # - Start date set but no end date: Printable if now >= start date. + # - End date set but no start date: Printable if now <= end date. + # - both defined: printable if start <= now <= end + # + my $now = time(); + + my $startok = 1; + my $endok = 1; + + if ((defined $start) && ($start ne '')) { + $startok = $start <= $now; + } + if ((defined $end) && ($end != '')) { + $endok = $end >= $now; + } + return $startok && $endok; +} + +sub resprintable { + my $self = shift; + + # get parts...or realize there are no parts. + + my $partsref = $self->parts(); + my @parts = @$partsref; + + if ((!defined(@parts)) || (scalar(@parts) == 0)) { + return $self->printable(0); + } else { + foreach my $part (@parts) { + if (!$self->printable($part)) { + return 0; + } + } + return 1; + } +} + sub acc { (my $self, my $part) = @_; my $acc = $self->parmval("acc", $part); @@ -4101,6 +4216,11 @@ sub checkedin { } } # this should work exactly like the copy in lonhomework.pm +# Why is there a copy in lonhomework? Why not centralized? +# +# TODO: Centralize duedate. +# + sub duedate { (my $self, my $part) = @_; my $date; @@ -4180,8 +4300,8 @@ sub weight { my $self = shift; my $part = shift; if (!defined($part)) { $part = '0'; } my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', - $self->symb(), $env{'user.domain'}, - $env{'user.name'}, + $self->symb(), $self->{DOMAIN}, + $self->{USERNAME}, $env{'request.course.sec'}); return $weight; } @@ -4209,7 +4329,7 @@ sub getReturnHash { my $self = shift; if (!defined($self->{RETURN_HASH})) { - my %tmpHash = &Apache::lonnet::restore($self->symb()); + my %tmpHash = &Apache::lonnet::restore($self->symb(),undef,$self->{DOMAIN},$self->{USERNAME}); $self->{RETURN_HASH} = \%tmpHash; } } @@ -4998,6 +5118,7 @@ sub check_for_slot { my $ip = $slots{$slot_name}->{'ip'}; if ($self->simpleStatus() == OPEN) { my $startreserve = $slots{$slot_name}->{'startreserve'}; + my $endreserve = $slots{$slot_name}->{'endreserve'}; my @proctors; if ($slots{$slot_name}->{'proctor'} ne '') { @proctors = split(',',$slots{$slot_name}->{'proctor'}); @@ -5023,7 +5144,9 @@ sub check_for_slot { } } else { if ($start > $now) { - return (RESERVABLE,$startreserve,$slot_name); + if (!$endreserve || $endreserve > $now) { + return (RESERVABLE,$startreserve,$slot_name); + } } } } @@ -5198,9 +5321,9 @@ sub completable { # "If any of the parts are open, or have tries left (implies open), # and it is not "attempted" (manually graded problem), it is # not "complete" - if ($self->getCompletionStatus($part) == ATTEMPTED() || + if ($self->getCompletionStatus($part) == ATTEMPTED() || $self->getCompletionStatus($part) == CREDIT_ATTEMPTED() || - $status == ANSWER_SUBMITTED() ) { + $status == ANSWER_SUBMITTED() ) { # did this part already, as well as we can next; }