--- loncom/interface/lonnavmaps.pm 2011/09/22 12:48:40 1.464 +++ loncom/interface/lonnavmaps.pm 2011/11/29 11:58:53 1.470 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.464 2011/09/22 12:48:40 raeburn Exp $ +# $Id: lonnavmaps.pm,v 1.470 2011/11/29 11:58:53 foxr Exp $ # # Copyright Michigan State University Board of Trustees @@ -225,7 +225,7 @@ automatically. =over 4 -=item * B: default: constructs one from %env +=item * Bsymb(),'opendate'),$part); } if ($status == $res->OPEN_LATER) { - return &mt("Open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start')),$res->symb(),'opendate',$part); + 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'})) { @@ -646,22 +652,22 @@ sub getDescription { if ($status == $res->OPEN) { if ($due) { if ($res->is_practice()) { - return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start')),$res->symb(),'duedate',$part); + return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part)); } else { - return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end')),$res->symb(),'duedate',$part); + return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)); } } else { 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 [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start')),$res->symb(),'answerdate',$part); + 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 [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start')),$res->symb(),'answerdate,duedate',$part); + return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part)); } else { - return &mt("Was due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end')),$res->symb(),'answerdate,duedate',$part); + 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) @@ -694,7 +700,7 @@ sub getDescription { } } if ($due) { - return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end')),$res->symb(),'duedate',$part) . + return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)) . " $triesString"; } else { return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString"; @@ -1129,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()); } @@ -1383,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? @@ -1635,6 +1650,7 @@ END $curRes = shift(@resources); } else { $curRes = $it->next($closeAllPages); + } if (!$curRes) { last; } @@ -1961,10 +1977,13 @@ 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. $self->{RESOURCE_CACHE} = {}; @@ -1973,32 +1992,96 @@ 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; } @@ -2986,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; + } @@ -3011,6 +3097,7 @@ sub new { $self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; bless ($self); + my $selfDump = Data::Dumper->new([$self]); return $self; } @@ -3026,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}) { @@ -3045,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; } @@ -3121,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) { @@ -3154,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}, @@ -3172,6 +3262,8 @@ sub next { return $self->next($closeAllPages); } + my $hereResource = $self->{HERE}; + return $self->{HERE}; } @@ -3338,6 +3430,7 @@ sub next { my $nextUnfiltered; if ($self->{DIRECTION} == FORWARD()) { $nextUnfiltered = $self->{HERE}->getNext(); + } else { $nextUnfiltered = $self->{HERE}->getPrevious(); } @@ -3751,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; @@ -3786,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;