header_only) {
- if ($env{'browser.mathml'}) {
- &Apache::loncommon::content_type($r,'text/xml');
- } else {
- &Apache::loncommon::content_type($r,'text/html');
- }
- $r->send_http_header;
- return OK;
- }
-
- # Send header, don't cache this page
- if ($env{'browser.mathml'}) {
- &Apache::loncommon::content_type($r,'text/xml');
- } else {
- &Apache::loncommon::content_type($r,'text/html');
- }
- &Apache::loncommon::no_cache($r);
-
- my %toplinkitems=();
- &add_linkitem(\%toplinkitems,'blank','',"Select Action");
- if ($ENV{QUERY_STRING} eq 'collapseExternal') {
- &Apache::lonnet::put('environment',{'remotenavmap' => 'off'});
- &Apache::lonnet::appenv('environment.remotenavmap' => 'off');
- my $menu=&Apache::lonmenu::reopenmenu();
- my $navstatus=&Apache::lonmenu::get_nav_status();
- if ($menu) {
- $menu=(<');
- $r->print('
- ');
- }
-
- if ($env{'environment.remotenavmap'} ne 'on') {
- $r->print(&launch_win('link','yes',\%toplinkitems));
- }
- if ($env{'environment.remotenavmap'} eq 'on') {
- &add_linkitem(\%toplinkitems,'closenav','collapse()',
- "Close navigation window");
- }
-
-
- # Check to see if the student is jumping to next open, do-able problem
- if ($ENV{QUERY_STRING} =~ /^jumpToFirstHomework/) {
- # Find the next homework problem that they can do.
- my $iterator = $navmap->getIterator(undef, undef, undef, 1);
- my $curRes;
- my $foundDoableProblem = 0;
- my $minimumduedate;
-
- while ($curRes = $iterator->next()) {
- if (ref($curRes) && $curRes->is_problem()) {
- my $status = $curRes->status();
- if ($curRes->completable()) {
- my $thisduedate=$curRes->duedate();
- unless ($foundDoableProblem) {
- $minimumduedate=$thisduedate;
- }
-
- $foundDoableProblem = 1;
-
- if ($thisduedate<=$minimumduedate) {
- # Pop open all previous maps
- my $stack = $iterator->getStack();
- pop @$stack; # last resource in the stack is the problem
- # itself, which we don't need in the map stack
- my @mapPcs = map {$_->map_pc()} @$stack;
- $env{'form.filter'} = join(',', @mapPcs);
-
- # Mark as both "here" and "jump"
- $env{'form.postsymb'} = $curRes->symb();
- $minimumduedate=$thisduedate;
- }
- }
- }
- }
-
- # If we found no problems, print a note to that effect.
- if (!$foundDoableProblem) {
- $r->print("All homework assignments have been completed.
");
- }
- } else {
- &add_linkitem(\%toplinkitems,'firsthomework',
- 'location.href="navmaps?jumpToFirstHomework"',
- "Show my first due problem");
- }
-
- my $suppressEmptySequences = 0;
- my $filterFunc = undef;
- my $resource_no_folder_link = 0;
-
- # Display only due homework.
- my $showOnlyHomework = 0;
- if ($env{'form.showOnlyHomework'} eq "1") {
- $showOnlyHomework = 1;
- $suppressEmptySequences = 1;
- $filterFunc = sub { my $res = shift;
- return $res->completable() || $res->is_map();
- };
- &add_linkitem(\%toplinkitems,'everything',
- 'location.href="navmaps?sort='.$env{'form.sort'}.'"',
- "Show everything");
- $r->print("".&mt("Uncompleted Problems")."
");
- $env{'form.filter'} = '';
- $env{'form.condition'} = 1;
- $resource_no_folder_link = 1;
- } else {
- &add_linkitem(\%toplinkitems,'uncompleted',
- 'location.href="navmaps?sort='.$env{'form.sort'}.
- '&showOnlyHomework=1"',
- "Show only uncompleted problems");
- }
-
- my %selected=($env{'form.sort'} => 'selected=on');
- my $sort_html=("");
- # renderer call
- my $renderArgs = { 'cols' => [0,1,2,3],
- 'sort' => $env{'form.sort'},
- 'url' => '/adm/navmaps',
- 'navmap' => $navmap,
- 'suppressNavmap' => 1,
- 'suppressEmptySequences' => $suppressEmptySequences,
- 'filterFunc' => $filterFunc,
- 'resource_no_folder_link' => $resource_no_folder_link,
- 'sort_html'=> $sort_html,
- 'r' => $r,
- 'caller' => 'navmapsdisplay',
- 'linkitems' => \%toplinkitems};
- my $render = render($renderArgs);
-
- # If no resources were printed, print a reassuring message so the
- # user knows there was no error.
- if ($renderArgs->{'counter'} == 0) {
- if ($showOnlyHomework) {
- $r->print("".&mt("All homework is currently completed").".
");
- } else { # both jumpToFirstHomework and normal use the same: course must be empty
- $r->print("This course is empty.
");
- }
- }
- #my $td=&tv_interval($t0);
- #$r->print("
$td");
-
- $r->print(&Apache::loncommon::end_page());
- $r->rflush();
-
- return OK;
-}
-
# Convenience functions: Returns a string that adds or subtracts
# the second argument from the first hash, appropriate for the
# query string that determines which folders to recurse on
@@ -470,7 +149,7 @@ sub getLinkForResource {
if (defined($res)) {
my $anchor;
if ($res->is_page()) {
- foreach (@$stack) { if (defined($_)) { $anchor = $_; } }
+ foreach my $item (@$stack) { if (defined($item)) { $anchor = $item; } }
$anchor=&escape($anchor->shown_symb());
return ($res->link(),$res->shown_symb(),$anchor);
}
@@ -488,8 +167,8 @@ sub getLinkForResource {
# (when we first recurse on a map, it puts an undefined resource
# on the bottom because $self->{HERE} isn't defined yet, and we
# want the src for the map anyhow)
- foreach (@$stack) {
- if (defined($_)) { $res = $_; }
+ foreach my $item (@$stack) {
+ if (defined($item)) { $res = $item; }
}
return ($res->link(),$res->shown_symb());
@@ -1093,7 +772,13 @@ sub render_resource {
if ($resource->is_problem()) {
if ($part eq '0' || $params->{'condensed'}) {
- $icon ='';
+ $icon = '';
} else {
$icon = $params->{'indentString'};
}
@@ -1118,16 +803,16 @@ sub render_resource {
($nowOpen ? &mt('Open Folder') : &mt('Close Folder')).' '.$title."\" border='0' />";
$linkopen = "{'url'} . '?' .
- $params->{'queryString'} . '&filter=';
+ $params->{'queryString'} . '&filter=';
$linkopen .= ($nowOpen xor $it->{CONDITION}) ?
addToFilter($filter, $mapId) :
removeFromFilter($filter, $mapId);
- $linkopen .= "&condition=" . $it->{CONDITION} . '&hereType='
- . $params->{'hereType'} . '&here=' .
+ $linkopen .= "&condition=" . $it->{CONDITION} . '&hereType='
+ . $params->{'hereType'} . '&here=' .
&escape($params->{'here'}) .
- '&jump=' .
+ '&jump=' .
&escape($resource->symb()) .
- "&folderManip=1\">";
+ "&folderManip=1\">";
} else {
# Don't allow users to manipulate folder
@@ -1149,7 +834,7 @@ sub render_resource {
}
# We're done preparing and finally ready to start the rendering
- my $result = "";
+ my $result = " | ";
my $indentLevel = $params->{'indentLevel'};
if ($newBranchText) { $indentLevel--; }
@@ -1213,17 +898,17 @@ sub render_communication_status {
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
if ($resource->hasDiscussion()) {
$discussionHTML = $linkopen .
- '' .
+ '' .
$linkclose;
}
if ($resource->getFeedback()) {
my $feedback = $resource->getFeedback();
- foreach (split(/\,/, $feedback)) {
- if ($_) {
+ foreach my $msgid (split(/\,/, $feedback)) {
+ if ($msgid) {
$feedbackHTML .= ' '
- . ''
+ . '';
}
}
@@ -1232,13 +917,13 @@ sub render_communication_status {
if ($resource->getErrors()) {
my $errors = $resource->getErrors();
my $errorcount = 0;
- foreach (split(/,/, $errors)) {
+ foreach my $msgid (split(/,/, $errors)) {
last if ($errorcount>=10); # Only output 10 bombs maximum
- if ($_) {
+ if ($msgid) {
$errorcount++;
$errorHTML .= ' '
- . ''
+ . '';
}
}
@@ -1248,7 +933,7 @@ sub render_communication_status {
$discussionHTML = $feedbackHTML = $errorHTML = '';
}
- return " | $discussionHTML$feedbackHTML$errorHTML | ";
+ return "$discussionHTML$feedbackHTML$errorHTML | ";
}
sub render_quick_status {
@@ -1273,7 +958,7 @@ sub render_quick_status {
if ($icon) {
my $location=
&Apache::loncommon::lonhttpdurl("/adm/lonIcons/$icon");
- $result .= "$linkopen$linkclose | \n";
+ $result .= "$linkopen$linkclose | \n";
} else {
$result .= " | \n";
}
@@ -1285,7 +970,7 @@ sub render_quick_status {
}
sub render_long_status {
my ($resource, $part, $params) = @_;
- my $result = "\n";
+ my $result = " | \n";
my $firstDisplayed = !$params->{'condensed'} &&
$params->{'multipart'} && $part eq "0";
@@ -1441,9 +1126,9 @@ sub render {
# marker
my $filterHash = {};
# Figure out what we're not displaying
- foreach (split(/\,/, $env{"form.filter"})) {
- if ($_) {
- $filterHash->{$_} = "1";
+ foreach my $item (split(/\,/, $env{"form.filter"})) {
+ if ($item) {
+ $filterHash->{$item} = "1";
}
}
@@ -1471,7 +1156,7 @@ sub render {
$navmap = Apache::lonnavmaps::navmap->new();
if (!defined($navmap)) {
# no londer in course
- return ''.&mt('No course selected').'
+ return ''.&mt('No course selected').'
'.&mt('Select a course').' ';
}
}
@@ -1609,11 +1294,11 @@ sub render {
if ($printCloseAll && !$args->{'resource_no_folder_link'}) {
my ($link,$text);
if ($condition) {
- $link='"navmaps?condition=0&filter=&'.$queryString.
+ $link='"navmaps?condition=0&filter=&'.$queryString.
'&here='.&escape($here).'"';
$text='Close all folders';
} else {
- $link='"navmaps?condition=1&filter=&'.$queryString.
+ $link='"navmaps?condition=1&filter=&'.$queryString.
'&here='.&escape($here).'"';
$text='Open all folders';
}
@@ -1660,7 +1345,7 @@ END
if ($args->{'caller'} eq 'navmapsdisplay') {
$result .= ''.
- &Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').' | ';
+ &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').'';
if ($env{'environment.remotenavmap'} ne 'on') {
$result .= ' | ';
} else {
@@ -2216,10 +1901,10 @@ sub generate_email_discuss_status {
my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss',
$env{'user.domain'},$env{'user.name'},'lastread');
my %lastreadtime = ();
- foreach (keys %lastread) {
- my $key = $_;
- $key =~ s/_lastread$//;
- $lastreadtime{$key} = $lastread{$_};
+ foreach my $key (keys %lastread) {
+ my $shortkey = $key;
+ $shortkey =~ s/_lastread$//;
+ $lastreadtime{$shortkey} = $lastread{$key};
}
my %feedback=();
@@ -2229,22 +1914,36 @@ sub generate_email_discuss_status {
foreach my $msgid (@keys) {
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) {
- my $plain=
- &LONCAPA::unescape(&LONCAPA::unescape($msgid));
- if ($plain=~/ \[([^\]]+)\]\:/) {
- my $url=$1;
- if ($plain=~/\:Error \[/) {
- $error{$url}.=','.$msgid;
- } else {
- $feedback{$url}.=','.$msgid;
- }
- }
+ my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid,
+ $symb,$error) = &Apache::lonmsg::unpackmsgid($msgid);
+ &Apache::lonenc::check_decrypt(\$symb);
+ if (($fromcid ne '') && ($fromcid ne $cid)) {
+ next;
+ }
+ if (defined($symb)) {
+ if (defined($error) && $error == 1) {
+ $error{$symb}.=','.$msgid;
+ } else {
+ $feedback{$symb}.=','.$msgid;
+ }
+ } else {
+ my $plain=
+ &LONCAPA::unescape(&LONCAPA::unescape($msgid));
+ if ($plain=~/ \[([^\]]+)\]\:/) {
+ my $url=$1;
+ if ($plain=~/\:Error \[/) {
+ $error{$url}.=','.$msgid;
+ } else {
+ $feedback{$url}.=','.$msgid;
+ }
+ }
+ }
}
}
- #url's of resources that have feedbacks
+ #symbs of resources that have feedbacks (will be urls pre-2.3)
$self->{FEEDBACK} = \%feedback;
- #or errors
+ #or errors (will be urls pre 2.3)
$self->{ERROR_MSG} = \%error;
$self->{DISCUSSION_TIME} = \%discussiontime;
$self->{EMAIL_STATUS} = \%emailstatus;
@@ -2349,9 +2048,10 @@ sub last_post_time {
return $self->{DISCUSSION_TIME}->{$ressymb};
}
-sub unread_discussion {
+sub discussion_info {
my $self = shift;
my $symb = shift;
+ my $filter = shift;
$self->get_discussion_data();
@@ -2363,12 +2063,10 @@ sub unread_discussion {
my $prevread = $self->{LAST_READ}{$ressymb};
- my $unreadcount = 0;
+ my $count = 0;
my $hiddenflag = 0;
my $deletedflag = 0;
- my ($hidden,$deleted);
-
- my %subjects;
+ my ($hidden,$deleted,%info);
for (my $id=$version; $id>0; $id--) {
my $vkeys=$self->{DISCUSSION_DATA}{$id.':keys:'.$discsymb};
@@ -2384,18 +2082,24 @@ sub unread_discussion {
$deletedflag = 1;
}
} else {
- if (($hidden !~/\.$id\./) && ($deleted !~/\.$id\./)
- && $prevread < $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':timestamp'}) {
- $unreadcount++;
- $subjects{$unreadcount}=
- $id.': '.$self->{DISCUSSION_DATA}{$id.':'.$discsymb.':subject'};
- }
+ if (($hidden !~/\.$id\./) && ($deleted !~/\.$id\./)) {
+ if ($filter eq 'unread') {
+ if ($prevread >= $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':timestamp'}) {
+ next;
+ }
+ }
+ $count++;
+ $info{$count}{'subject'} =
+ $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':subject'};
+ $info{$count}{'id'} = $id;
+ $info{$count}{'timestamp'} = $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':timestamp'};
+ }
}
}
if (wantarray) {
- return ($unreadcount,\%subjects);
+ return ($count,%info);
}
- return $unreadcount
+ return $count;
}
sub wrap_symb {
@@ -2426,23 +2130,48 @@ sub unwrap_symb {
sub getFeedback {
my $self = shift;
my $symb = shift;
+ my $source = shift;
$self->generate_email_discuss_status();
if (!defined($self->{FEEDBACK})) { return ""; }
- return $self->{FEEDBACK}->{$symb};
+ my $feedback;
+ if ($self->{FEEDBACK}->{$symb}) {
+ $feedback = $self->{FEEDBACK}->{$symb};
+ if ($self->{FEEDBACK}->{$source}) {
+ $feedback .= ','.$self->{FEEDBACK}->{$source};
+ }
+ } else {
+ if ($self->{FEEDBACK}->{$source}) {
+ $feedback = $self->{FEEDBACK}->{$source};
+ }
+ }
+ return $feedback;
}
# Private method: Get the errors for that resource (by source).
sub getErrors {
my $self = shift;
+ my $symb = shift;
my $src = shift;
$self->generate_email_discuss_status();
if (!defined($self->{ERROR_MSG})) { return ""; }
- return $self->{ERROR_MSG}->{$src};
+
+ my $errors;
+ if ($self->{ERROR_MSG}->{$symb}) {
+ $errors = $self->{ERROR_MSG}->{$symb};
+ if ($self->{ERROR_MSG}->{$src}) {
+ $errors .= ','.$self->{ERROR_MSG}->{$src};
+ }
+ } else {
+ if ($self->{ERROR_MSG}->{$src}) {
+ $errors = $self->{ERROR_MSG}->{$src};
+ }
+ }
+ return $errors;
}
=pod
@@ -3432,9 +3161,9 @@ sub next {
# filter the next possibilities to remove things we've
# already seen.
- foreach (@$nextUnfiltered) {
- if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) {
- push @$next, $_;
+ foreach my $item (@$nextUnfiltered) {
+ if (!defined($self->{ALREADY_SEEN}->{$item->{ID}})) {
+ push @$next, $item;
}
}
@@ -4037,7 +3766,7 @@ sub duedate {
my $date;
my $interval=$self->parmval("interval", $part);
my $due_date=$self->parmval("duedate", $part);
- if (defined($interval)) {
+ if ($interval =~ /\d+/) {
my $first_access=&Apache::lonnet::get_first_access('map',$self->symb);
if (defined($first_access)) {
$interval = $first_access+$interval;
@@ -4150,13 +3879,15 @@ data was not extracted when the nav map
Returns a false value if there hasn't been discussion otherwise returns
unix timestamp of last time a discussion posting (or edit) was made.
-=item * B:
+=item * B:
-returns in scalar context the count of the number of unread discussion
-postings
+optional argument is a filter (currently can be 'unread');
+returns in scalar context the count of the number of discussion postings.
returns in list context both the count of postings and a hash ref
-containing the subjects of all unread postings
+containing information about the postings (subject, id, timestamp) in a hash.
+
+Default is to return counts for all postings. However if called with a second argument set to 'unread', will return information about only unread postings.
=item * B:
@@ -4165,8 +3896,8 @@ for the resource, or the null string if
email data was not extracted when the nav map was constructed. Usually
used like this:
- for (split(/\,/, $res->getFeedback())) {
- my $link = &escape($_);
+ for my $url (split(/\,/, $res->getFeedback())) {
+ my $link = &escape($url);
...
and use the link as appropriate.
@@ -4183,23 +3914,25 @@ sub last_post_time {
return $self->{NAV_MAP}->last_post_time($self->symb());
}
-sub unread_discussion {
- my $self = shift;
- return $self->{NAV_MAP}->unread_discussion($self->symb());
+sub discussion_info {
+ my ($self,$filter) = @_;
+ return $self->{NAV_MAP}->discussion_info($self->symb(),$filter);
}
sub getFeedback {
my $self = shift;
my $source = $self->src();
+ my $symb = $self->symb();
if ($source =~ /^\/res\//) { $source = substr $source, 5; }
- return $self->{NAV_MAP}->getFeedback($source);
+ return $self->{NAV_MAP}->getFeedback($symb,$source);
}
sub getErrors {
my $self = shift;
my $source = $self->src();
+ my $symb = $self->symb();
if ($source =~ /^\/res\//) { $source = substr $source, 5; }
- return $self->{NAV_MAP}->getErrors($source);
+ return $self->{NAV_MAP}->getErrors($symb,$source);
}
=pod
@@ -4360,8 +4093,8 @@ sub extractParts {
$self->{PART_TYPE} = {};
return;
}
- foreach (split(/\,/,$metadata)) {
- if ($_ =~ /^(?:part|Task)_(.*)$/) {
+ foreach my $entry (split(/\,/,$metadata)) {
+ if ($entry =~ /^(?:part|Task)_(.*)$/) {
my $part = $1;
# This floods the logs if it blows up
if (defined($parts{$part})) {
@@ -4386,8 +4119,8 @@ sub extractParts {
# Init the responseIdHash
- foreach (@{$self->{PARTS}}) {
- $responseIdHash{$_} = [];
+ foreach my $part (@{$self->{PARTS}}) {
+ $responseIdHash{$part} = [];
}
# Now, the unfortunate thing about this is that parts, part name, and
@@ -4467,13 +4200,13 @@ the completion information.
Idiomatic usage of these two methods would probably look something
like
- foreach ($resource->parts()) {
- my $dateStatus = $resource->getDateStatus($_);
- my $completionStatus = $resource->getCompletionStatus($_);
+ foreach my $part ($resource->parts()) {
+ my $dateStatus = $resource->getDateStatus($part);
+ my $completionStatus = $resource->getCompletionStatus($part);
or
- my $status = $resource->status($_);
+ my $status = $resource->status($part);
... use it here ...
}
|