: default: false
@@ -1009,6 +1047,15 @@ sub render_resource {
my $nonLinkedText = ''; # stuff after resource title not in link
my $link = $params->{"resourceLink"};
+
+ # The URL part is not escaped at this point, but the symb is...
+ # The stuff to the left of the ? must have ' replaced by \' since
+ # it will be quoted with ' in the href.
+
+ my ($left,$right) = split(/\?/, $link);
+ $left =~ s/'/\\'/g;
+ $link = $left.'?'.$right;
+
my $src = $resource->src();
my $it = $params->{"iterator"};
my $filter = $it->{FILTER};
@@ -1020,24 +1067,28 @@ sub render_resource {
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons");
# If this is a new branch, label it so
if ($params->{'isNewBranch'}) {
- $newBranchText = "
";
+ $newBranchText = "
";
}
# links to open and close the folder
+
+
my $linkopen = "";
+
+
my $linkclose = "";
# Default icon: unknown page
- my $icon = "
";
+ my $icon = "
";
if ($resource->is_problem()) {
if ($part eq '0' || $params->{'condensed'}) {
- $icon ='
';
+ $icon ='
';
} else {
$icon = $params->{'indentString'};
}
} else {
- $icon = "
";
+ $icon = "
";
}
# Display the correct map icon to open or shut map
@@ -1052,7 +1103,8 @@ sub render_resource {
if (!$params->{'resource_no_folder_link'}) {
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';
- $icon = "
";
+ $icon = "
";
$linkopen = "{'queryString'} . '&filter=';
@@ -1065,11 +1117,13 @@ sub render_resource {
'&jump=' .
&Apache::lonnet::escape($resource->symb()) .
"&folderManip=1'>";
+
} else {
# Don't allow users to manipulate folder
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') .
'.nomanip.gif';
- $icon = "
";
+ $icon = "
";
$linkopen = "";
$linkclose = "";
@@ -1079,6 +1133,9 @@ sub render_resource {
if ($resource->randomout()) {
$nonLinkedText .= ' (hidden) ';
}
+ if (!$resource->condval()) {
+ $nonLinkedText .= ' (conditionally hidden) ';
+ }
# We're done preparing and finally ready to start the rendering
my $result = "";
@@ -1092,6 +1149,7 @@ sub render_resource {
}
# Decide what to display
+
$result .= "$newBranchText$linkopen$icon$linkclose";
my $curMarkerBegin = '';
@@ -1100,7 +1158,7 @@ sub render_resource {
# Is this the current resource?
if (!$params->{'displayedHereMarker'} &&
$resource->symb() eq $params->{'here'} ) {
- $curMarkerBegin = '> ';
+ $curMarkerBegin = '>';
$curMarkerEnd = '<';
$params->{'displayedHereMarker'} = 1;
}
@@ -1109,7 +1167,7 @@ sub render_resource {
!$params->{'condensed'}) {
my $displaypart=$resource->part_display($part);
$partLabel = " (Part: $displaypart)";
- $link.='#'.&Apache::lonnet::escape($part);
+ if ($link!~/\#/) { $link.='#'.&Apache::lonnet::escape($part); }
$title = "";
}
@@ -1118,7 +1176,7 @@ sub render_resource {
}
my $target;
- if ($ENV{'environment.remotenavmap'} eq 'on') {
+ if ($env{'environment.remotenavmap'} eq 'on') {
$target=' target="loncapaclient" ';
}
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {
@@ -1135,7 +1193,11 @@ sub render_communication_status {
my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = "";
my $link = $params->{"resourceLink"};
- my $linkopen = "";
+ my $target;
+ if ($env{'environment.remotenavmap'} eq 'on') {
+ $target=' target="loncapaclient" ';
+ }
+ my $linkopen = "";
my $linkclose = "";
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
if ($resource->hasDiscussion()) {
@@ -1148,7 +1210,7 @@ sub render_communication_status {
my $feedback = $resource->getFeedback();
foreach (split(/\,/, $feedback)) {
if ($_) {
- $feedbackHTML .= ' '
. ' ';
@@ -1163,7 +1225,7 @@ sub render_communication_status {
last if ($errorcount>=10); # Only output 10 bombs maximum
if ($_) {
$errorcount++;
- $errorHTML .= ' '
. ' ';
@@ -1185,7 +1247,11 @@ sub render_quick_status {
$params->{'multipart'} && $part eq "0";
my $link = $params->{"resourceLink"};
- my $linkopen = "";
+ my $target;
+ if ($env{'environment.remotenavmap'} eq 'on') {
+ $target=' target="loncapaclient" ';
+ }
+ my $linkopen = "";
my $linkclose = "";
if ($resource->is_problem() &&
@@ -1344,7 +1410,6 @@ sub render {
# no columns, no nav maps.
return '';
}
- my $mustCloseNavMap = 0;
my $navmap;
if (defined($args->{'navmap'})) {
$navmap = $args->{'navmap'};
@@ -1365,7 +1430,7 @@ sub render {
# marker
my $filterHash = {};
# Figure out what we're not displaying
- foreach (split(/\,/, $ENV{"form.filter"})) {
+ foreach (split(/\,/, $env{"form.filter"})) {
if ($_) {
$filterHash->{$_} = "1";
}
@@ -1385,30 +1450,43 @@ sub render {
}
my $condition = 0;
- if ($ENV{'form.condition'}) {
+ if ($env{'form.condition'}) {
$condition = 1;
}
- if (!$ENV{'form.folderManip'} && !defined($args->{'iterator'})) {
+ if (!$env{'form.folderManip'} && !defined($args->{'iterator'})) {
# Step 1: Check to see if we have a navmap
if (!defined($navmap)) {
$navmap = Apache::lonnavmaps::navmap->new();
- $mustCloseNavMap = 1;
- }
+ if (!defined($navmap)) {
+ # no londer in course
+ return 'No course selected
+ Select a course ';
+ }
+ }
# Step two: Locate what kind of here marker is necessary
# Determine where the "here" marker is and where the screen jumps to.
- if ($ENV{'form.postsymb'}) {
- $here = $jump = $ENV{'form.postsymb'};
- } elsif ($ENV{'form.postdata'}) {
+ if ($env{'form.postsymb'} ne '') {
+ $here = $jump = &Apache::lonnet::symbclean($env{'form.postsymb'});
+ } elsif ($env{'form.postdata'} ne '') {
# couldn't find a symb, is there a URL?
- my $currenturl = $ENV{'form.postdata'};
+ my $currenturl = $env{'form.postdata'};
#$currenturl=~s/^http\:\/\///;
#$currenturl=~s/^[^\/]+//;
$here = $jump = &Apache::lonnet::symbread($currenturl);
- }
+ }
+ if ($here eq '') {
+ my $last;
+ if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
+ &GDBM_READER(),0640)) {
+ $last=$hash{'last_known'};
+ untie(%hash);
+ }
+ if ($last) { $here = $jump = $last; }
+ }
# Step three: Ensure the folders are open
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1);
@@ -1435,21 +1513,20 @@ sub render {
}
}
- if ( !defined($args->{'iterator'}) && $ENV{'form.folderManip'} ) { # we came from a user's manipulation of the nav page
+ if ( !defined($args->{'iterator'}) && $env{'form.folderManip'} ) { # we came from a user's manipulation of the nav page
# If this is a click on a folder or something, we want to preserve the "here"
# from the querystring, and get the new "jump" marker
- $here = $ENV{'form.here'};
- $jump = $ENV{'form.jump'};
+ $here = $env{'form.here'};
+ $jump = $env{'form.jump'};
}
my $it = $args->{'iterator'};
if (!defined($it)) {
- # Construct a default iterator based on $ENV{'form.'} information
+ # Construct a default iterator based on $env{'form.'} information
# Step 1: Check to see if we have a navmap
if (!defined($navmap)) {
$navmap = Apache::lonnavmaps::navmap->new();
- $mustCloseNavMap = 1;
}
# See if we're being passed a specific map
@@ -1555,13 +1632,7 @@ END
my @allres=$navmap->retrieveResources();
foreach my $resource (@allres) {
if ($resource->hasDiscussion()) {
- my $ressymb;
- if ($resource->symb() =~ m-(___adm/\w+/\w+)/(\d+)/bulletinboard$-) {
- $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
- } else {
- $ressymb = $resource->symb();
- }
- $haveDisc .= $ressymb.':';
+ $haveDisc .= $resource->wrap_symb().':';
$totdisc ++;
}
}
@@ -1579,14 +1650,14 @@ END
if ($args->{'caller'} eq 'navmapsdisplay') {
$result .= ''.
&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').' | ';
- if ($ENV{'environment.remotenavmap'} ne 'on') {
+ if ($env{'environment.remotenavmap'} ne 'on') {
$result .= ' | ';
} else {
$result .= ' ';
}
$result.=&show_linkitems($args->{'linkitems'});
if ($args->{'sort_html'}) {
- if ($ENV{'environment.remotenavmap'} ne 'on') {
+ if ($env{'environment.remotenavmap'} ne 'on') {
$result.=' | | | '.
''.$args->{'sort_html'}.' | ';
} else {
@@ -1623,7 +1694,7 @@ END
$args->{'condensed'} = 0;
my $location=
&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace1.gif");
- $args->{'indentString'} = setDefault($args->{'indentString'}, " ");
+ $args->{'indentString'} = setDefault($args->{'indentString'}, " ");
$args->{'displayedHereMarker'} = 0;
# If we're suppressing empty sequences, look for them here. Use DFS for speed,
@@ -1776,10 +1847,6 @@ END
$args->{'multipart'} = $curRes->multipart();
if ($condenseParts) { # do the condensation
- if (!$curRes->opendate("0")) {
- @parts = ();
- $args->{'condensed'} = 1;
- }
if (!$args->{'condensed'}) {
# Decide whether to condense based on similarity
my $status = $curRes->status($parts[0]);
@@ -1829,7 +1896,26 @@ END
# Add part 0 so we display it correctly.
unshift @parts, '0';
}
-
+
+ {
+ my ($src,$symb,$anchor,$stack);
+ if ($args->{'sort'}) {
+ my $it = $navmap->getIterator(undef, undef, undef, 1);
+ while ( my $res=$it->next()) {
+ if (ref($res) &&
+ $res->symb() eq $curRes->symb()) { last; }
+ }
+ $stack=$it->getStack();
+ } else {
+ $stack=$it->getStack();
+ }
+ ($src,$symb,$anchor)=getLinkForResource($stack);
+ if (defined($anchor)) { $anchor='#'.$anchor; }
+ my $srcHasQuestion = $src =~ /\?/;
+ $args->{"resourceLink"} = $src.
+ ($srcHasQuestion?'&':'?') .
+ 'symb=' . &Apache::lonnet::escape($symb).$anchor;
+ }
# Now, we've decided what parts to show. Loop through them and
# show them.
foreach my $part (@parts) {
@@ -1840,22 +1926,6 @@ END
# Set up some data about the parts that the cols might want
my $filter = $it->{FILTER};
- my $src;
- if ($args->{'sort'}) {
- $src = $curRes->src(); # FIXME this is wrong for .pages
- } else {
- my $stack = $it->getStack();
- $src=getLinkForResource($stack);
- }
- my $anchor='';
- if ($src=~s/(\#.*)$//) {
- $anchor=$1;
- }
- my $srcHasQuestion = $src =~ /\?/;
- $args->{"resourceLink"} = $src.
- ($srcHasQuestion?'&':'?') .
- 'symb=' . &Apache::lonnet::escape($curRes->symb()).
- $anchor;
# Now, display each column.
foreach my $col (@$cols) {
@@ -1933,8 +2003,8 @@ sub add_linkitem {
sub show_linkitems {
my ($linkitems)=@_;
- my @linkorder = ("launchnav","closenav","firsthomework","everything",
- "uncompleted","changefolder","clearbubbles");
+ my @linkorder = ("blank","launchnav","closenav","firsthomework",
+ "everything","uncompleted","changefolder","clearbubbles");
my $result .= (<
@@ -2034,6 +2104,7 @@ See iterator documentation below.
use strict;
use GDBM_File;
+use Apache::lonnet;
sub new {
# magic invocation to create a class instance
@@ -2053,7 +2124,7 @@ sub new {
my %navmaphash;
my %parmhash;
- my $courseFn = $ENV{"request.course.fn"};
+ my $courseFn = $env{"request.course.fn"};
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db",
&GDBM_READER(), 0640))) {
return undef;
@@ -2079,56 +2150,36 @@ 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 $uhome=$ENV{'user.home'};
- my $cid=$ENV{'request.course.id'};
- my $chome=$ENV{'course.'.$cid.'.home'};
- my ($cdom,$cnum)=split(/\_/,$cid);
-
- my $userprefix=$uname.'_'.$udom.'_';
+ my $uname=$env{'user.name'};
+ my $udom=$env{'user.domain'};
+ my $cid=$env{'request.course.id'};
+ my $cdom=$env{'course.'.$cid.'.domain'};
+ my $cnum=$env{'course.'.$cid.'.num'};
- my %courserdatas; my %useropt; my %courseopt; my %userrdatas;
- unless ($uhome eq 'no_host') {
# ------------------------------------------------- Get coursedata (if present)
- unless ((time-$courserdatas{$cid.'.last_cache'})<240) {
- my $reply=&Apache::lonnet::reply('dump:'.$cdom.':'.$cnum.
- ':resourcedata',$chome);
- # Check for network failure
- if ( $reply =~ /no.such.host/i || $reply =~ /con_lost/i) {
- $self->{NETWORK_FAILURE} = 1;
- } elsif ($reply!~/^error\:/) {
- $courserdatas{$cid}=$reply;
- $courserdatas{$cid.'.last_cache'}=time;
- }
- }
- foreach (split(/\&/,$courserdatas{$cid})) {
- my ($name,$value)=split(/\=/,$_);
- $courseopt{$userprefix.&Apache::lonnet::unescape($name)}=
- &Apache::lonnet::unescape($value);
+ my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
+ # Check for network failure
+ if (!ref($courseopt)) {
+ if ( $courseopt =~ /no.such.host/i || $courseopt =~ /con_lost/i) {
+ $self->{NETWORK_FAILURE} = 1;
}
+ undef($courseopt);
+ }
+
# --------------------------------------------------- Get userdata (if present)
- unless ((time-$userrdatas{$uname.'___'.$udom.'.last_cache'})<240) {
- my $reply=&Apache::lonnet::reply('dump:'.$udom.':'.$uname.':resourcedata',$uhome);
- if ($reply!~/^error\:/) {
- $userrdatas{$uname.'___'.$udom}=$reply;
- $userrdatas{$uname.'___'.$udom.'.last_cache'}=time;
- }
- # check to see if network failed
- elsif ( $reply=~/no.such.host/i || $reply=~/con.*lost/i )
- {
- $self->{NETWORK_FAILURE} = 1;
- }
- }
- foreach (split(/\&/,$userrdatas{$uname.'___'.$udom})) {
- my ($name,$value)=split(/\=/,$_);
- $useropt{$userprefix.&Apache::lonnet::unescape($name)}=
- &Apache::lonnet::unescape($value);
+
+ my $useropt=&Apache::lonnet::get_userresdata($uname,$udom);
+ # Check for network failure
+ if (!ref($useropt)) {
+ if ( $useropt =~ /no.such.host/i || $useropt =~ /con_lost/i) {
+ $self->{NETWORK_FAILURE} = 1;
}
- $self->{COURSE_OPT} = \%courseopt;
- $self->{USER_OPT} = \%useropt;
+ undef($useropt);
}
+ $self->{COURSE_OPT} = $courseopt;
+ $self->{USER_OPT} = $useropt;
+
$self->{COURSE_USER_OPT_GENERATED} = 1;
return;
@@ -2139,18 +2190,19 @@ sub generate_email_discuss_status {
my $symb = shift;
if ($self->{EMAIL_DISCUSS_GENERATED}) { return; }
- my $cid=$ENV{'request.course.id'};
- my ($cdom,$cnum)=split(/\_/,$cid);
+ my $cid=$env{'request.course.id'};
+ my $cdom=$env{'course.'.$cid.'.domain'};
+ my $cnum=$env{'course.'.$cid.'.num'};
my %emailstatus = &Apache::lonnet::dump('email_status');
my $logoutTime = $emailstatus{'logout'};
- my $courseLeaveTime = $emailstatus{'logout_'.$ENV{'request.course.id'}};
+ my $courseLeaveTime = $emailstatus{'logout_'.$env{'request.course.id'}};
$self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ?
$courseLeaveTime : $logoutTime);
my %discussiontime = &Apache::lonnet::dump('discussiontimes',
$cdom, $cnum);
my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss',
- $ENV{'user.domain'},$ENV{'user.name'},'lastread');
+ $env{'user.domain'},$env{'user.name'},'lastread');
my %lastreadtime = ();
foreach (keys %lastread) {
my $key = $_;
@@ -2160,13 +2212,10 @@ sub generate_email_discuss_status {
my %feedback=();
my %error=();
- my $keys = &Apache::lonnet::reply('keys:'.
- $ENV{'user.domain'}.':'.
- $ENV{'user.name'}.':nohist_email',
- $ENV{'user.home'});
+ my @keys = &Apache::lonnet::getkeys('nohist_email',$env{'user.domain'},
+ $env{'user.name'});
- foreach my $msgid (split(/\&/, $keys)) {
- $msgid=&Apache::lonnet::unescape($msgid);
+ foreach my $msgid (@keys) {
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) {
my $plain=
&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid));
@@ -2197,9 +2246,9 @@ sub get_user_data {
if ($self->{RETRIEVED_USER_DATA}) { return; }
# Retrieve performance data on problems
- my %student_data = Apache::lonnet::currentdump($ENV{'request.course.id'},
- $ENV{'user.domain'},
- $ENV{'user.name'});
+ my %student_data = Apache::lonnet::currentdump($env{'request.course.id'},
+ $env{'user.domain'},
+ $env{'user.name'});
$self->{STUDENT_DATA} = \%student_data;
$self->{RETRIEVED_USER_DATA} = 1;
@@ -2224,7 +2273,7 @@ sub navhash {
# Checks to see if coursemap is defined, matching test in old lonnavmaps
sub courseMapDefined {
my $self = shift;
- my $uri = &Apache::lonnet::clutter($ENV{'request.course.uri'});
+ my $uri = &Apache::lonnet::clutter($env{'request.course.uri'});
my $firstres = $self->navhash("map_start_$uri");
my $lastres = $self->navhash("map_finish_$uri");
@@ -2234,7 +2283,8 @@ sub courseMapDefined {
sub getIterator {
my $self = shift;
my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift,
- shift, undef, shift);
+ shift, undef, shift,
+ shift, shift);
return $iterator;
}
@@ -2243,21 +2293,14 @@ sub getIterator {
sub hasDiscussion {
my $self = shift;
my $symb = shift;
-
$self->generate_email_discuss_status();
if (!defined($self->{DISCUSSION_TIME})) { return 0; }
#return defined($self->{DISCUSSION_TIME}->{$symb});
-# backward compatibility (bulletin boards used to be 'wrapped')
- my $ressymb = $symb;
- if ($ressymb =~ m|adm/(\w+)/(\w+)/(\d+)/bulletinboard$|) {
- unless ($ressymb =~ m|adm/wrapper/adm|) {
- $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
- }
- }
-
+ # backward compatibility (bulletin boards used to be 'wrapped')
+ my $ressymb = $self->wrap_symb($symb);
if ( defined ( $self->{LAST_READ}->{$ressymb} ) ) {
return $self->{DISCUSSION_TIME}->{$ressymb} > $self->{LAST_READ}->{$ressymb};
} else {
@@ -2266,9 +2309,21 @@ sub hasDiscussion {
}
}
+sub wrap_symb {
+ my $self = shift;
+ my $symb = shift;
+ if ($symb =~ m-___(adm/\w+/\w+/)(\d+)(/bulletinboard)$-) {
+ unless ($symb =~ m|adm/wrapper/adm|) {
+ $symb = 'bulletin___'.$2.'___adm/wrapper/'.$1.$2.$3;
+ }
+ }
+ return $symb;
+}
+
# Private method: Does the given resource (as a symb string) have
# current feedback? Returns the string in the feedback hash, which
# will be false if it does not exist.
+
sub getFeedback {
my $self = shift;
my $symb = shift;
@@ -2364,7 +2419,7 @@ resource in the navmap.
sub firstResource {
my $self = shift;
my $firstResource = $self->navhash('map_start_' .
- &Apache::lonnet::clutter($ENV{'request.course.uri'}));
+ &Apache::lonnet::clutter($env{'request.course.uri'}));
return $self->getById($firstResource);
}
@@ -2380,7 +2435,7 @@ in the navmap.
sub finishResource {
my $self = shift;
my $firstResource = $self->navhash('map_finish_' .
- &Apache::lonnet::clutter($ENV{'request.course.uri'}));
+ &Apache::lonnet::clutter($env{'request.course.uri'}));
return $self->getById($firstResource);
}
@@ -2407,10 +2462,10 @@ sub parmval_real {
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated
$self->generate_course_user_opt();
- my $cid=$ENV{'request.course.id'};
- my $csec=$ENV{'request.course.sec'};
- my $uname=$ENV{'user.name'};
- my $udom=$ENV{'user.domain'};
+ my $cid=$env{'request.course.id'};
+ my $csec=$env{'request.course.sec'};
+ my $uname=$env{'user.name'};
+ my $udom=$env{'user.domain'};
unless ($symb) { return ''; }
my $result='';
@@ -2424,7 +2479,7 @@ sub parmval_real {
my $symbparm=$symb.'.'.$what;
my $mapparm=$mapname.'___(all).'.$what;
- my $usercourseprefix=$uname.'_'.$udom.'_'.$cid;
+ my $usercourseprefix=$cid;
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what;
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm;
@@ -2454,8 +2509,6 @@ sub parmval_real {
if (defined($courseopt)) {
if (defined($$courseopt{$courselevelr})) { return $$courseopt{$courselevelr}; }
- if (defined($$courseopt{$courselevelm})) { return $$courseopt{$courselevelm}; }
- if (defined($$courseopt{$courselevel})) { return $$courseopt{$courselevel}; }
}
# ----------------------------------------------------- third, check map parms
@@ -2472,7 +2525,13 @@ sub parmval_real {
$default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat);
if (defined($default)) { return $default}
-# --------------------------------------------------- fifth , cascade up parts
+# --------------------------------------------------- fifth, check more course
+ if (defined($courseopt)) {
+ if (defined($$courseopt{$courselevelm})) { return $$courseopt{$courselevelm}; }
+ if (defined($$courseopt{$courselevel})) { return $$courseopt{$courselevel}; }
+ }
+
+# --------------------------------------------------- sixth , cascade up parts
my ($space,@qualifier)=split(/\./,$rwhat);
my $qualifier=join('.',@qualifier);
@@ -2501,7 +2560,7 @@ you're not sure if $res is already an ob
resource appears multiple times in the course, only the first instance
will be returned. As a result, this is probably useful only for maps.
-=item * B(map, filterFunc, recursive, bailout):
+=item * B(map, filterFunc, recursive, bailout, showall):
The map is a specification of a map to retreive the resources from,
either as a url or as an object. The filterFunc is a reference to a
@@ -2509,13 +2568,14 @@ function that takes a resource object as
true if the resource should be included, or false if it should not
be. If recursive is true, the map will be recursively examined,
otherwise it will not be. If bailout is true, the function will return
-as soon as it finds a resource, if false it will finish. By default,
-the map is the top-level map of the course, filterFunc is a function
-that always returns 1, recursive is true, bailout is false. The
-resources will be returned in a list containing the resource objects
-for the corresponding resources, with B in
-the list; regardless of branching, recursion, etc., it will be a flat
-list.
+as soon as it finds a resource, if false it will finish. If showall is
+true it will not hide maps that contain nothing but one other map. By
+default, the map is the top-level map of the course, filterFunc is a
+function that always returns 1, recursive is true, bailout is false,
+showall is false. The resources will be returned in a list containing
+the resource objects for the corresponding resources, with B in the list; regardless of branching,
+recursion, etc., it will be a flat list.
Thus, this is suitable for cases where you don't want the structure,
just a list of all resources. It is also suitable for finding out how
@@ -2524,11 +2584,11 @@ want to know is if I resources matc
parameter will allow you to avoid potentially expensive enumeration of
all matching resources.
-=item * B(map, filterFunc, recursive):
+=item * B(map, filterFunc, recursive, showall):
Convience method for
- scalar(retrieveResources($map, $filterFunc, $recursive, 1)) > 0
+ scalar(retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0
which will tell whether the map has resources matching the description
in the filter function.
@@ -2562,7 +2622,7 @@ sub retrieveResources {
if (!defined($recursive)) { $recursive = 1; }
my $bailout = shift;
if (!defined($bailout)) { $bailout = 0; }
-
+ my $showall = shift;
# Create the necessary iterator.
if (!ref($map)) { # assume it's a url of a map.
$map = $self->getResourceByUrl($map);
@@ -2581,7 +2641,7 @@ sub retrieveResources {
# Get an iterator.
my $it = $self->getIterator($map->map_start(), $map->map_finish(),
- undef, $recursive);
+ undef, $recursive, $showall);
my @resources = ();
@@ -2611,14 +2671,17 @@ sub hasResource {
my $map = shift;
my $filterFunc = shift;
my $recursive = shift;
+ my $showall = shift;
- return scalar($self->retrieveResources($map, $filterFunc, $recursive, 1)) > 0;
+ return scalar($self->retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0;
}
1;
package Apache::lonnavmaps::iterator;
use WeakRef;
+use Apache::lonnet;
+
=pod
=back
@@ -2878,7 +2941,8 @@ sub new {
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
$finishResource, $self->{FILTER},
$self->{ALREADY_SEEN},
- $self->{CONDITION}, 0);
+ $self->{CONDITION},
+ $self->{FORCE_TOP});
}
@@ -3041,7 +3105,9 @@ sub next {
$self->{RECURSIVE_ITERATOR} =
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
$finishResource, $self->{FILTER},
- $self->{ALREADY_SEEN}, $self->{CONDITION});
+ $self->{ALREADY_SEEN},
+ $self->{CONDITION},
+ $self->{FORCE_TOP});
}
# If this is a blank resource, don't actually return it.
@@ -3095,6 +3161,8 @@ sub populateStack {
package Apache::lonnavmaps::DFSiterator;
use WeakRef;
+use Apache::lonnet;
+
# Not documented in the perldoc: This is a simple iterator that just walks
# through the nav map and presents the resources in a depth-first search
# fashion, ignorant of conditionals, randomized resources, etc. It presents
@@ -3446,6 +3514,7 @@ Returns the title of the resource.
# These info functions can be used directly, as they don't return
# resource information.
sub comesfrom { my $self=shift; return $self->navHash("comesfrom_", 1); }
+sub encrypted { my $self=shift; return $self->navHash("encrypted_", 1); }
sub ext { my $self=shift; return $self->navHash("ext_", 1) eq 'true:'; }
sub from { my $self=shift; return $self->navHash("from_", 1); }
# considered private and undocumented
@@ -3457,10 +3526,29 @@ sub randompick {
return $self->{NAV_MAP}->{PARM_HASH}->{$self->symb .
'.0.parameter_randompick'};
}
+sub link {
+ my $self=shift;
+ if ($self->encrypted()) { return &Apache::lonenc::encrypted($self->src); }
+ return $self->src;
+}
sub src {
my $self=shift;
return $self->navHash("src_", 1);
}
+sub shown_symb {
+ my $self=shift;
+ if ($self->encrypted()) {return &Apache::lonenc::encrypted($self->symb());}
+ return $self->symb();
+}
+sub id {
+ my $self=shift;
+ return $self->{ID};
+}
+sub enclosing_map_src {
+ my $self=shift;
+ (my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/;
+ return $self->navHash('map_id_'.$first);
+}
sub symb {
my $self=shift;
(my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/;
@@ -3469,12 +3557,16 @@ sub symb {
. '___' . $second . '___' . $symbSrc;
return &Apache::lonnet::symbclean($symb);
}
+sub wrap_symb {
+ my $self = shift;
+ return $self->{NAV_MAP}->wrap_symb($self->symb());
+}
sub title {
my $self=shift;
if ($self->{ID} eq '0.0') {
# If this is the top-level map, return the title of the course
# since this map can not be titled otherwise.
- return $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
+ return $env{'course.'.$env{'request.course.id'}.'.description'};
}
return $self->navHash("title_", 1); }
# considered private and undocumented
@@ -3488,7 +3580,19 @@ sub condition {
my $condition=&Apache::lonnet::directcondval($condid);
return $condition;
}
-
+sub condval {
+ my $self=shift;
+ my $uri=&Apache::lonnet::deversion(&Apache::lonnet::declutter($self->src()));
+ my ($pathname,$filename)=($uri=~m|(.*)/([^/]*)|);
+ $pathname=~s/^adm\/wrapper\///;
+
+ my $match=($env{'acc.res.'.$env{'request.course.id'}.'.'.$pathname}=~
+ /\&\Q$filename\E\:([\d\|]+)\&/);
+ if ($match) {
+ return &Apache::lonnet::condval($1);
+ }
+ return 0;
+}
sub compTitle {
my $self = shift;
my $title = $self->title();
@@ -3554,7 +3658,7 @@ sub is_page {
sub is_problem {
my $self=shift;
my $src = $self->src();
- return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library)$/)
+ return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/)
}
sub contains_problem {
my $self=shift;
@@ -3770,6 +3874,10 @@ sub duedate {
}
return $self->parmval("duedate", $part);
}
+sub handgrade {
+ (my $self, my $part) = @_;
+ return $self->parmval("handgrade", $part);
+}
sub maxtries {
(my $self, my $part) = @_;
return $self->parmval("maxtries", $part);
@@ -3808,9 +3916,9 @@ sub weight {
my $self = shift; my $part = shift;
if (!defined($part)) { $part = '0'; }
return &Apache::lonnet::EXT('resource.'.$part.'.weight',
- $self->symb(), $ENV{'user.domain'},
- $ENV{'user.name'},
- $ENV{'request.course.sec'});
+ $self->symb(), $env{'user.domain'},
+ $env{'user.name'},
+ $env{'request.course.sec'});
}
sub part_display {
my $self= shift(); my $partID = shift();
@@ -4054,7 +4162,7 @@ sub extractParts {
return;
}
foreach (split(/\,/,$metadata)) {
- if ($_ =~ /^part_(.*)$/) {
+ if ($_ =~ /^(?:part|Task)_(.*)$/) {
my $part = $1;
# This floods the logs if it blows up
if (defined($parts{$part})) {
@@ -4319,14 +4427,17 @@ sub ATTEMPTED { return 16; }
sub getCompletionStatus {
my $self = shift;
+ my $part = shift;
return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE});
- my $status = $self->queryRestoreHash('solved', shift);
+ my $status = $self->queryRestoreHash('solved', $part);
# Left as separate if statements in case we ever do more with this
if ($status eq 'correct_by_student') {return $self->CORRECT;}
if ($status eq 'correct_by_scantron') {return $self->CORRECT;}
- if ($status eq 'correct_by_override') {return $self->CORRECT_BY_OVERRIDE; }
+ if ($status eq 'correct_by_override') {
+ return $self->CORRECT_BY_OVERRIDE;
+ }
if ($status eq 'incorrect_attempted') {return $self->INCORRECT; }
if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; }
if ($status eq 'excused') {return $self->EXCUSED; }
@@ -4430,6 +4541,7 @@ An answer has been submitted, but the st
sub TRIES_LEFT { return 20; }
sub ANSWER_SUBMITTED { return 21; }
+sub PARTIALLY_CORRECT{ return 22; }
sub status {
my $self = shift;
@@ -4448,14 +4560,29 @@ sub status {
my $suppressFeedback = $self->problemstatus($part) eq 'no';
# If there's an answer date and we're past it, don't
# suppress the feedback; student should know
- if ($self->answerdate($part) && $self->answerdate($part) < time()) {
+ if ($self->duedate($part) && $self->duedate($part) < time() &&
+ $self->answerdate($part) && $self->answerdate($part) < time()) {
$suppressFeedback = 0;
}
# There are a few whole rows we can dispose of:
if ($completionStatus == CORRECT ||
$completionStatus == CORRECT_BY_OVERRIDE ) {
- return $suppressFeedback? ANSWER_SUBMITTED : CORRECT;
+ if ( $suppressFeedback ) { return ANSWER_SUBMITTED }
+ my $awarded=$self->awarded($part);
+ if ($awarded < 1 && $awarded > 0) {
+ return PARTIALLY_CORRECT;
+ } elsif ($awarded<1) {
+ return INCORRECT;
+ }
+ return CORRECT;
+ }
+
+ # If it's WRONG... and not open
+ if ( ($completionStatus == INCORRECT ||
+ $completionStatus == INCORRECT_BY_OVERRIDE)
+ && (!$self->opendate($part) || $self->opendate($part) > time()) ) {
+ return INCORRECT;
}
if ($completionStatus == ATTEMPTED) {
@@ -4542,6 +4669,7 @@ my %compositeToSimple =
NETWORK_FAILURE() => ERROR,
NOTHING_SET() => CLOSED,
CORRECT() => CORRECT,
+ PARTIALLY_CORRECT() => PARTIALLY_CORRECT,
EXCUSED() => CORRECT,
PAST_DUE_NO_ANSWER() => INCORRECT,
PAST_DUE_ANSWER_LATER() => INCORRECT,
@@ -4662,7 +4790,7 @@ sub getNext {
my $to = $self->to();
foreach my $branch ( split(/,/, $to) ) {
my $choice = $self->{NAV_MAP}->getById($branch);
- if (!$choice->condition()) { next; }
+ #if (!$choice->condition()) { next; }
my $next = $choice->goesto();
$next = $self->{NAV_MAP}->getById($next);
@@ -4691,7 +4819,8 @@ sub browsePriv {
return $self->{BROWSE_PRIV};
}
- $self->{BROWSE_PRIV} = &Apache::lonnet::allowed('bre', $self->src());
+ $self->{BROWSE_PRIV} = &Apache::lonnet::allowed('bre',$self->src(),
+ $self->symb());
}
=pod
|