version 1.246, 2004/02/12 18:00:33
|
version 1.326, 2005/04/15 22:03:23
|
Line 30
|
Line 30
|
package Apache::lonnavmaps; |
package Apache::lonnavmaps; |
|
|
use strict; |
use strict; |
|
use GDBM_File; |
use Apache::Constants qw(:common :http); |
use Apache::Constants qw(:common :http); |
use Apache::loncommon(); |
use Apache::loncommon(); |
use Apache::lonmenu(); |
use Apache::lonmenu(); |
|
use Apache::lonenc(); |
use Apache::lonlocal; |
use Apache::lonlocal; |
|
use Apache::lonnet; |
use POSIX qw (floor strftime); |
use POSIX qw (floor strftime); |
use Data::Dumper; # for debugging, not always used |
use Data::Dumper; # for debugging, not always |
|
use Time::HiRes qw( gettimeofday tv_interval ); |
|
|
# symbolic constants |
# symbolic constants |
sub SYMB { return 1; } |
sub SYMB { return 1; } |
Line 83 my %colormap =
|
Line 87 my %colormap =
|
# is not yet done and due in less then 24 hours |
# is not yet done and due in less then 24 hours |
my $hurryUpColor = "#FF0000"; |
my $hurryUpColor = "#FF0000"; |
|
|
|
sub launch_win { |
|
my ($mode,$script,$toplinkitems)=@_; |
|
my $result; |
|
if ($script ne 'no') { |
|
$result.='<script type="text/javascript">'; |
|
} |
|
$result.='function launch_navmapwin() { |
|
newWindow=open(\'/adm/navmaps?launchExternal\',\'loncapanav\',\'width=400,height=600,scrollbars=1\'); |
|
}'; |
|
if ($mode eq 'now') { |
|
$result.="\nlaunch_navmapwin();\n"; |
|
} |
|
if ($script ne 'no') { |
|
$result.='</script>'; |
|
} |
|
if ($mode eq 'link') { |
|
&add_linkitem($toplinkitems,'launchnav','launch_navmapwin()', |
|
"Launch navigation window"); |
|
} |
|
return $result; |
|
} |
|
|
|
sub close { |
|
if ($env{'environment.remotenavmap'} ne 'on') { return ''; } |
|
return(<<ENDCLOSE); |
|
<script type="text/javascript"> |
|
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.'; |
|
</script> |
|
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); |
|
<form name="navform"></form> |
|
<script type="text/javascript"> |
|
this.document.navform.action='/adm/navmaps#curloc'; |
|
this.document.navform.target='loncapanav'; |
|
this.document.navform.submit(); |
|
</script> |
|
ENDUPDATE |
|
} |
|
|
sub handler { |
sub handler { |
my $r = shift; |
my $r = shift; |
real_handler($r); |
real_handler($r); |
Line 90 sub handler {
|
Line 144 sub handler {
|
|
|
sub real_handler { |
sub real_handler { |
my $r = shift; |
my $r = shift; |
|
#my $t0=[&gettimeofday()]; |
# Handle header-only request |
# Handle header-only request |
if ($r->header_only) { |
if ($r->header_only) { |
if ($ENV{'browser.mathml'}) { |
if ($env{'browser.mathml'}) { |
&Apache::loncommon::content_type($r,'text/xml'); |
&Apache::loncommon::content_type($r,'text/xml'); |
} else { |
} else { |
&Apache::loncommon::content_type($r,'text/html'); |
&Apache::loncommon::content_type($r,'text/html'); |
Line 103 sub real_handler {
|
Line 157 sub real_handler {
|
} |
} |
|
|
# Send header, don't cache this page |
# Send header, don't cache this page |
if ($ENV{'browser.mathml'}) { |
if ($env{'browser.mathml'}) { |
&Apache::loncommon::content_type($r,'text/xml'); |
&Apache::loncommon::content_type($r,'text/xml'); |
} else { |
} else { |
&Apache::loncommon::content_type($r,'text/html'); |
&Apache::loncommon::content_type($r,'text/html'); |
Line 111 sub real_handler {
|
Line 165 sub real_handler {
|
&Apache::loncommon::no_cache($r); |
&Apache::loncommon::no_cache($r); |
$r->send_http_header; |
$r->send_http_header; |
|
|
|
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=(<<MENU) |
|
swmenu=$menu |
|
swmenu.clearTimeout(swmenu.menucltim); |
|
$navstatus |
|
MENU |
|
} else { |
|
my $nothing = &Apache::lonhtmlcommon::javascript_nothing(); |
|
my $mainwindow='window.open('.$nothing.',"loncapaclient","",false);'; |
|
$menu=(<<MENU) |
|
swmenu=$mainwindow |
|
$navstatus |
|
MENU |
|
} |
|
my $html=&Apache::lonxml::xmlbegin(); |
|
$r->print(<<"ENDSUBM"); |
|
$html |
|
<head> |
|
<script type="text/javascript"> |
|
function submitthis() { |
|
$menu |
|
self.close(); |
|
} |
|
|
|
</script> |
|
</head> |
|
<body bgcolor="#FFFFFF" onLoad="submitthis()"></body> |
|
</html> |
|
ENDSUBM |
|
return; |
|
} |
|
if ($ENV{QUERY_STRING} eq 'launchExternal') { |
|
&Apache::lonnet::put('environment',{'remotenavmap' => 'on'}); |
|
&Apache::lonnet::appenv('environment.remotenavmap' => 'on'); |
|
} |
|
|
# Create the nav map |
# Create the nav map |
my $navmap = Apache::lonnavmaps::navmap->new(); |
my $navmap = Apache::lonnavmaps::navmap->new(); |
|
|
if (!defined($navmap)) { |
if (!defined($navmap)) { |
my $requrl = $r->uri; |
my $requrl = $r->uri; |
$ENV{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; |
$env{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; |
return HTTP_NOT_ACCEPTABLE; |
return HTTP_NOT_ACCEPTABLE; |
} |
} |
|
my $html=&Apache::lonxml::xmlbegin(); |
$r->print("<html><head>\n"); |
$r->print("$html<head>\n"); |
$r->print("<title>".&mt('Navigate Course Contents')."</title>"); |
$r->print("<title>".&mt('Navigate Course Contents')."</title>"); |
# ------------------------------------------------------------ Get query string |
# ------------------------------------------------------------ Get query string |
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register']); |
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']); |
|
|
# ----------------------------------------------------- Force menu registration |
# ----------------------------------------------------- Force menu registration |
my $addentries=''; |
my $addentries=''; |
if ($ENV{'form.register'}) { |
my $more_unload; |
$addentries=' onLoad="'.&Apache::lonmenu::loadevents(). |
my $body_only=''; |
'" onUnload="'.&Apache::lonmenu::unloadevents().'"'; |
if ($env{'environment.remotenavmap'} eq 'on') { |
$r->print(&Apache::lonmenu::registerurl(1)); |
$r->print('<script type="text/javascript"> |
|
function collapse() { |
|
this.document.location="/adm/navmaps?collapseExternal"; |
|
} |
|
</script>'); |
|
# FIXME need to be smarter to only catch window close events |
|
# $more_unload="collapse()" |
|
$body_only=1; |
|
} |
|
if ($env{'form.register'}) { |
|
$addentries=' onLoad="'.&Apache::lonmenu::loadevents(). |
|
'" onUnload="'.&Apache::lonmenu::unloadevents().';'. |
|
$more_unload.'"'; |
|
$r->print(&Apache::lonmenu::registerurl(1)); |
|
} else { |
|
$addentries=' onUnload="'.$more_unload.'"'; |
} |
} |
|
|
# Header |
# Header |
$r->print('</head>'. |
$r->print('</head>'. |
&Apache::loncommon::bodytag('Navigate Course Contents','', |
&Apache::loncommon::bodytag('Navigate Course Contents','', |
$addentries,'','',$ENV{'form.register'})); |
$addentries,$body_only,'', |
|
$env{'form.register'})); |
$r->print('<script>window.focus();</script>'); |
$r->print('<script>window.focus();</script>'); |
|
|
$r->rflush(); |
$r->rflush(); |
|
|
# Check that it's defined |
# Check that it's defined |
if (!($navmap->courseMapDefined())) { |
if (!($navmap->courseMapDefined())) { |
|
$r->print(&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT')); |
$r->print('<font size="+2" color="red">Coursemap undefined.</font>' . |
$r->print('<font size="+2" color="red">Coursemap undefined.</font>' . |
'</body></html>'); |
'</body></html>'); |
return OK; |
return OK; |
Line 166 sub real_handler {
|
Line 280 sub real_handler {
|
if ($sequenceCount == 1) { |
if ($sequenceCount == 1) { |
# The automatic iterator creation in the render call |
# The automatic iterator creation in the render call |
# will pick this up. We know the condition because |
# will pick this up. We know the condition because |
# the defined($ENV{'form.filter'}) also ensures this |
# the defined($env{'form.filter'}) also ensures this |
# is a fresh call. |
# is a fresh call. |
$ENV{'form.filter'} = "$sequenceId"; |
$env{'form.filter'} = "$sequenceId"; |
} |
} |
} |
} |
|
|
|
if ($ENV{QUERY_STRING} eq 'launchExternal') { |
|
$r->print(' |
|
<form name="returnwin" action="/adm/flip?postdata=return%3a" |
|
method="post" target="loncapaclient"> |
|
</form>'); |
|
$r->print(' |
|
<script type="text/javascript"> |
|
this.document.returnwin.submit(); |
|
</script>'); |
|
} |
|
|
|
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"); |
|
} |
|
|
my $jumpToFirstHomework = 0; |
my $jumpToFirstHomework = 0; |
# Check to see if the student is jumping to next open, do-able problem |
# Check to see if the student is jumping to next open, do-able problem |
if ($ENV{QUERY_STRING} eq 'jumpToFirstHomework') { |
if ($ENV{QUERY_STRING} =~ /^jumpToFirstHomework/) { |
$jumpToFirstHomework = 1; |
$jumpToFirstHomework = 1; |
# Find the next homework problem that they can do. |
# Find the next homework problem that they can do. |
my $iterator = $navmap->getIterator(undef, undef, undef, 1); |
my $iterator = $navmap->getIterator(undef, undef, undef, 1); |
Line 194 sub real_handler {
|
Line 327 sub real_handler {
|
pop @$stack; # last resource in the stack is the problem |
pop @$stack; # last resource in the stack is the problem |
# itself, which we don't need in the map stack |
# itself, which we don't need in the map stack |
my @mapPcs = map {$_->map_pc()} @$stack; |
my @mapPcs = map {$_->map_pc()} @$stack; |
$ENV{'form.filter'} = join(',', @mapPcs); |
$env{'form.filter'} = join(',', @mapPcs); |
|
|
# Mark as both "here" and "jump" |
# Mark as both "here" and "jump" |
$ENV{'form.postsymb'} = $curRes->symb(); |
$env{'form.postsymb'} = $curRes->symb(); |
} |
} |
} |
} |
} |
} |
Line 207 sub real_handler {
|
Line 340 sub real_handler {
|
$r->print("<font size='+2'>All homework assignments have been completed.</font><br /><br />"); |
$r->print("<font size='+2'>All homework assignments have been completed.</font><br /><br />"); |
} |
} |
} else { |
} else { |
$r->print("<a href='navmaps?jumpToFirstHomework'>" . |
&add_linkitem(\%toplinkitems,'firsthomework', |
&mt("Go To My First Homework Problem")."</a> "); |
'location.href="navmaps?jumpToFirstHomework"', |
|
"Show Me My First Homework Problem"); |
} |
} |
|
|
my $suppressEmptySequences = 0; |
my $suppressEmptySequences = 0; |
Line 217 sub real_handler {
|
Line 351 sub real_handler {
|
|
|
# Display only due homework. |
# Display only due homework. |
my $showOnlyHomework = 0; |
my $showOnlyHomework = 0; |
if ($ENV{QUERY_STRING} eq 'showOnlyHomework') { |
if ($env{'form.showOnlyHomework'} eq "1") { |
$showOnlyHomework = 1; |
$showOnlyHomework = 1; |
$suppressEmptySequences = 1; |
$suppressEmptySequences = 1; |
$filterFunc = sub { my $res = shift; |
$filterFunc = sub { my $res = shift; |
return $res->completable() || $res->is_map(); |
return $res->completable() || $res->is_map(); |
}; |
}; |
|
&add_linkitem(\%toplinkitems,'everything', |
|
'location.href="navmaps?sort='.$env{'form.sort'}.'"', |
|
"Show Everything"); |
$r->print("<p><font size='+2'>".&mt("Uncompleted Homework")."</font></p>"); |
$r->print("<p><font size='+2'>".&mt("Uncompleted Homework")."</font></p>"); |
$ENV{'form.filter'} = ''; |
$env{'form.filter'} = ''; |
$ENV{'form.condition'} = 1; |
$env{'form.condition'} = 1; |
$resource_no_folder_link = 1; |
$resource_no_folder_link = 1; |
} else { |
} else { |
$r->print("<a href='navmaps?showOnlyHomework'>" . |
&add_linkitem(\%toplinkitems,'uncompleted', |
&mt("Show Only Uncompleted Homework")."</a> "); |
'location.href="navmaps?sort='.$env{'form.sort'}. |
} |
'&showOnlyHomework=1"', |
|
"Show Only Uncompleted Homework"); |
|
} |
|
|
|
my %selected=($env{'form.sort'} => 'selected=on'); |
|
my $sort_html=("<form> |
|
<nobr> |
|
<input type=\"hidden\" name=\"showOnlyHomework\" value=\"".$env{'form.showOnlyHomework'}."\" /> |
|
<input type=\"submit\" value=\"".&mt('Sort by:')."\" /> |
|
<select name=\"sort\"> |
|
<option value=\"default\" $selected{'default'}>".&mt('Default')."</option> |
|
<option value=\"title\" $selected{'title'} >".&mt('Title')."</option> |
|
<option value=\"duedate\" $selected{'duedate'}>".&mt('Duedate')."</option> |
|
<option value=\"discussion\" $selected{'discussion'}>".&mt('Has New Discussion')."</option> |
|
</select> |
|
</nobr> |
|
</form>"); |
# renderer call |
# renderer call |
my $renderArgs = { 'cols' => [0,1,2,3], |
my $renderArgs = { 'cols' => [0,1,2,3], |
|
'sort' => $env{'form.sort'}, |
'url' => '/adm/navmaps', |
'url' => '/adm/navmaps', |
'navmap' => $navmap, |
'navmap' => $navmap, |
'suppressNavmap' => 1, |
'suppressNavmap' => 1, |
'suppressEmptySequences' => $suppressEmptySequences, |
'suppressEmptySequences' => $suppressEmptySequences, |
'filterFunc' => $filterFunc, |
'filterFunc' => $filterFunc, |
'resource_no_folder_link' => $resource_no_folder_link, |
'resource_no_folder_link' => $resource_no_folder_link, |
'r' => $r}; |
'sort_html'=> $sort_html, |
|
'r' => $r, |
|
'caller' => 'navmapsdisplay', |
|
'linkitems' => \%toplinkitems}; |
my $render = render($renderArgs); |
my $render = render($renderArgs); |
$navmap->untieHashes(); |
|
|
|
# If no resources were printed, print a reassuring message so the |
# If no resources were printed, print a reassuring message so the |
# user knows there was no error. |
# user knows there was no error. |
Line 253 sub real_handler {
|
Line 408 sub real_handler {
|
$r->print("<p><font size='+1'>This course is empty.</font></p>"); |
$r->print("<p><font size='+1'>This course is empty.</font></p>"); |
} |
} |
} |
} |
|
#my $td=&tv_interval($t0); |
|
#$r->print("<br />$td"); |
|
|
$r->print("</body></html>"); |
$r->print("</body></html>"); |
$r->rflush(); |
$r->rflush(); |
Line 283 sub removeFromFilter {
|
Line 440 sub removeFromFilter {
|
|
|
# Convenience function: Given a stack returned from getStack on the iterator, |
# Convenience function: Given a stack returned from getStack on the iterator, |
# return the correct src() value. |
# return the correct src() value. |
# Later, this should add an anchor when we start putting anchors in pages. |
|
sub getLinkForResource { |
sub getLinkForResource { |
my $stack = shift; |
my $stack = shift; |
my $res; |
my $res; |
|
|
# Check to see if there are any pages in the stack |
# Check to see if there are any pages in the stack |
foreach $res (@$stack) { |
foreach $res (@$stack) { |
if (defined($res) && $res->is_page()) { |
if (defined($res)) { |
return $res->src(); |
my $anchor; |
|
if ($res->is_page()) { |
|
foreach (@$stack) { if (defined($_)) { $anchor = $_; } } |
|
$anchor=&Apache::lonnet::escape($anchor->shown_symb()); |
|
return ($res->link(),$res->shown_symb(),$anchor); |
|
} |
|
# in case folder was skipped over as "only sequence" |
|
my ($map,$id,$src)=&Apache::lonnet::decode_symb($res->symb()); |
|
if ($map=~/\.page$/) { |
|
my $url=&Apache::lonnet::clutter($map); |
|
$anchor=&Apache::lonnet::escape($src->shown_symb()); |
|
return ($url,$res->shown_symb(),$anchor); |
|
} |
} |
} |
} |
} |
|
|
Line 303 sub getLinkForResource {
|
Line 471 sub getLinkForResource {
|
if (defined($_)) { $res = $_; } |
if (defined($_)) { $res = $_; } |
} |
} |
|
|
return $res->src(); |
return ($res->link(),$res->shown_symb()); |
} |
} |
|
|
# Convenience function: This seperates the logic of how to create |
# Convenience function: This separates the logic of how to create |
# the problem text strings ("Due: DATE", "Open: DATE", "Not yet assigned", |
# the problem text strings ("Due: DATE", "Open: DATE", "Not yet assigned", |
# etc.) into a seperate function. It takes a resource object as the |
# etc.) into a separate function. It takes a resource object as the |
# first parameter, and the part number of the resource as the second. |
# first parameter, and the part number of the resource as the second. |
# It's basically a big switch statement on the status of the resource. |
# It's basically a big switch statement on the status of the resource. |
|
|
Line 373 sub getDescription {
|
Line 541 sub getDescription {
|
# Convenience function, so others can use it: Is the problem due in less then |
# Convenience function, so others can use it: Is the problem due in less then |
# 24 hours, and still can be done? |
# 24 hours, and still can be done? |
|
|
sub dueInLessThen24Hours { |
sub dueInLessThan24Hours { |
my $res = shift; |
my $res = shift; |
my $part = shift; |
my $part = shift; |
my $status = $res->status($part); |
my $status = $res->status($part); |
Line 397 sub lastTry {
|
Line 565 sub lastTry {
|
$res->duedate($part) > time(); |
$res->duedate($part) > time(); |
} |
} |
|
|
# This puts a human-readable name on the ENV variable. |
# This puts a human-readable name on the env variable. |
|
|
sub advancedUser { |
sub advancedUser { |
return $ENV{'request.role.adv'}; |
return $env{'request.role.adv'}; |
} |
} |
|
|
|
|
Line 504 sub timeToHumanString {
|
Line 672 sub timeToHumanString {
|
} |
} |
|
|
# Not this year, so show the year |
# Not this year, so show the year |
my $timeStr = strftime("on %A, %b %e %G at %I:%M %P", localtime($time)); |
my $timeStr = strftime("on %A, %b %e %Y at %I:%M %P", localtime($time)); |
$timeStr =~ s/12:00 am/00:00/; |
$timeStr =~ s/12:00 am/00:00/; |
$timeStr =~ s/12:00 pm/noon/; |
$timeStr =~ s/12:00 pm/noon/; |
return $timeStr; |
return $timeStr; |
Line 703 automatically.
|
Line 871 automatically.
|
|
|
=over 4 |
=over 4 |
|
|
=item * B<iterator>: default: constructs one from %ENV |
=item * B<iterator>: default: constructs one from %env |
|
|
A reference to a fresh ::iterator to use from the navmaps. The |
A reference to a fresh ::iterator to use from the navmaps. The |
rendering will reflect the options passed to the iterator, so you can |
rendering will reflect the options passed to the iterator, so you can |
use that to just render a certain part of the course, if you like. If |
use that to just render a certain part of the course, if you like. If |
one is not passed, the renderer will attempt to construct one from |
one is not passed, the renderer will attempt to construct one from |
ENV{'form.filter'} and ENV{'form.condition'} information, plus the |
env{'form.filter'} and env{'form.condition'} information, plus the |
'iterator_map' parameter if any. |
'iterator_map' parameter if any. |
|
|
=item * B<iterator_map>: default: not used |
=item * B<iterator_map>: default: not used |
Line 719 instruct the renderer to render only a p
|
Line 887 instruct the renderer to render only a p
|
the source of the map you want to process, like |
the source of the map you want to process, like |
'/res/103/jerf/navmap.course.sequence'. |
'/res/103/jerf/navmap.course.sequence'. |
|
|
=item * B<navmap>: default: constructs one from %ENV |
=item * B<navmap>: default: constructs one from %env |
|
|
A reference to a navmap, used only if an iterator is not passed in. If |
A reference to a navmap, used only if an iterator is not passed in. If |
this is necessary to make an iterator but it is not passed in, a new |
this is necessary to make an iterator but it is not passed in, a new |
one will be constructed based on ENV info. This is useful to do basic |
one will be constructed based on env info. This is useful to do basic |
error checking before passing it off to render. |
error checking before passing it off to render. |
|
|
=item * B<r>: default: must be passed in |
=item * B<r>: default: must be passed in |
Line 749 then only one line will be displayed for
|
Line 917 then only one line will be displayed for
|
all parts will always be displayed. If showParts is 0, this is |
all parts will always be displayed. If showParts is 0, this is |
ignored. |
ignored. |
|
|
=item * B<jumpCount>: default: determined from %ENV |
=item * B<jumpCount>: default: determined from %env |
|
|
A string identifying the URL to place the anchor 'curloc' at. |
A string identifying the URL to place the anchor 'curloc' at. |
It is the responsibility of the renderer user to |
It is the responsibility of the renderer user to |
ensure that the #curloc is in the URL. By default, determined through |
ensure that the #curloc is in the URL. By default, determined through |
the use of the ENV{} 'jump' information, and should normally "just |
the use of the env{} 'jump' information, and should normally "just |
work" correctly. |
work" correctly. |
|
|
=item * B<here>: default: empty string |
=item * B<here>: default: empty string |
Line 782 are allowing the user to open and close
|
Line 950 are allowing the user to open and close
|
|
|
Describes the currently-open row number to cause the browser to jump |
Describes the currently-open row number to cause the browser to jump |
to, because the user just opened that folder. By default, pulled from |
to, because the user just opened that folder. By default, pulled from |
the Jump information in the ENV{'form.*'}. |
the Jump information in the env{'form.*'}. |
|
|
=item * B<printKey>: default: false |
=item * B<printKey>: default: false |
|
|
Line 851 sub render_resource {
|
Line 1019 sub render_resource {
|
my $nonLinkedText = ''; # stuff after resource title not in link |
my $nonLinkedText = ''; # stuff after resource title not in link |
|
|
my $link = $params->{"resourceLink"}; |
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 $src = $resource->src(); |
my $it = $params->{"iterator"}; |
my $it = $params->{"iterator"}; |
my $filter = $it->{FILTER}; |
my $filter = $it->{FILTER}; |
|
|
my $title = $resource->compTitle(); |
my $title = $resource->compTitle(); |
if ($src =~ /^\/uploaded\//) { |
|
$nonLinkedText=$title; |
|
$title = ''; |
|
} |
|
my $partLabel = ""; |
my $partLabel = ""; |
my $newBranchText = ""; |
my $newBranchText = ""; |
|
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); |
# If this is a new branch, label it so |
# If this is a new branch, label it so |
if ($params->{'isNewBranch'}) { |
if ($params->{'isNewBranch'}) { |
$newBranchText = "<img src='/adm/lonIcons/branch.gif' border='0' />"; |
$newBranchText = "<img src='$location/branch.gif' border='0' />"; |
} |
} |
|
|
# links to open and close the folder |
# links to open and close the folder |
|
|
|
|
my $linkopen = "<a href='$link'>"; |
my $linkopen = "<a href='$link'>"; |
|
|
|
|
my $linkclose = "</a>"; |
my $linkclose = "</a>"; |
|
|
# Default icon: unknown page |
# Default icon: unknown page |
my $icon = "<img src='/adm/lonIcons/unknown.gif' alt='' border='0' />"; |
my $icon = "<img src='$location/unknown.gif' alt='' border='0' />"; |
|
|
if ($resource->is_problem()) { |
if ($resource->is_problem()) { |
if ($part eq '0' || $params->{'condensed'}) { |
if ($part eq '0' || $params->{'condensed'}) { |
$icon = '<img src="/adm/lonIcons/problem.gif" alt="" border="0" />'; |
$icon ='<img src="'.$location.'/problem.gif" alt="" border="0" />'; |
} else { |
} else { |
$icon = $params->{'indentString'}; |
$icon = $params->{'indentString'}; |
} |
} |
} else { |
} else { |
$icon = "<img src='".&Apache::loncommon::icon($resource->src). |
$icon = "<img src='".&Apache::loncommon::icon($resource->src)."' alt='' border='0' />"; |
"' alt='' border='0' />"; |
|
} |
} |
|
|
# Display the correct map icon to open or shut map |
# Display the correct map icon to open or shut map |
Line 898 sub render_resource {
|
Line 1075 sub render_resource {
|
|
|
if (!$params->{'resource_no_folder_link'}) { |
if (!$params->{'resource_no_folder_link'}) { |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif'; |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif'; |
$icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />"; |
$icon = "<img src='$location/$icon' alt='' border='0' />"; |
|
|
$linkopen = "<a href='" . $params->{'url'} . '?' . |
$linkopen = "<a href='" . $params->{'url'} . '?' . |
$params->{'queryString'} . '&filter='; |
$params->{'queryString'} . '&filter='; |
Line 911 sub render_resource {
|
Line 1088 sub render_resource {
|
'&jump=' . |
'&jump=' . |
&Apache::lonnet::escape($resource->symb()) . |
&Apache::lonnet::escape($resource->symb()) . |
"&folderManip=1'>"; |
"&folderManip=1'>"; |
|
|
} else { |
} else { |
# Don't allow users to manipulate folder |
# Don't allow users to manipulate folder |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . |
'.nomanip.gif'; |
'.nomanip.gif'; |
$icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />"; |
$icon = "<img src='$location/$icon' alt='' border='0' />"; |
|
|
$linkopen = ""; |
$linkopen = ""; |
$linkclose = ""; |
$linkclose = ""; |
Line 938 sub render_resource {
|
Line 1116 sub render_resource {
|
} |
} |
|
|
# Decide what to display |
# Decide what to display |
|
|
$result .= "$newBranchText$linkopen$icon$linkclose"; |
$result .= "$newBranchText$linkopen$icon$linkclose"; |
|
|
my $curMarkerBegin = ''; |
my $curMarkerBegin = ''; |
Line 953 sub render_resource {
|
Line 1132 sub render_resource {
|
|
|
if ($resource->is_problem() && $part ne '0' && |
if ($resource->is_problem() && $part ne '0' && |
!$params->{'condensed'}) { |
!$params->{'condensed'}) { |
my $displaypart=&Apache::lonnet::EXT('resource.'.$part.'.display', |
my $displaypart=$resource->part_display($part); |
$resource->symb()); |
|
unless ($displaypart) { $displaypart=$part; } |
|
$partLabel = " (Part: $displaypart)"; |
$partLabel = " (Part: $displaypart)"; |
$link.='#'.&Apache::lonnet::escape($part); |
if ($link!~/\#/) { $link.='#'.&Apache::lonnet::escape($part); } |
$title = ""; |
$title = ""; |
} |
} |
|
|
Line 965 sub render_resource {
|
Line 1142 sub render_resource {
|
$nonLinkedText .= ' (' . $resource->countParts() . ' parts)'; |
$nonLinkedText .= ' (' . $resource->countParts() . ' parts)'; |
} |
} |
|
|
if (!$params->{'resource_nolink'} && $src !~ /^\/uploaded\// && |
my $target; |
!$resource->is_sequence()) { |
if ($env{'environment.remotenavmap'} eq 'on') { |
$result .= " $curMarkerBegin<a href='$link'>$title$partLabel</a>$curMarkerEnd $nonLinkedText</td>"; |
$target=' target="loncapaclient" '; |
|
} |
|
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { |
|
$result .= " $curMarkerBegin<a $target href='$link'>$title$partLabel</a>$curMarkerEnd $nonLinkedText</td>"; |
} else { |
} else { |
$result .= " $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText</td>"; |
$result .= " $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText</td>"; |
} |
} |
Line 982 sub render_communication_status {
|
Line 1162 sub render_communication_status {
|
my $link = $params->{"resourceLink"}; |
my $link = $params->{"resourceLink"}; |
my $linkopen = "<a href='$link'>"; |
my $linkopen = "<a href='$link'>"; |
my $linkclose = "</a>"; |
my $linkclose = "</a>"; |
|
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); |
if ($resource->hasDiscussion()) { |
if ($resource->hasDiscussion()) { |
$discussionHTML = $linkopen . |
$discussionHTML = $linkopen . |
'<img border="0" src="/adm/lonMisc/chat.gif" />' . |
'<img border="0" src="'.$location.'/chat.gif" />' . |
$linkclose; |
$linkclose; |
} |
} |
|
|
Line 995 sub render_communication_status {
|
Line 1175 sub render_communication_status {
|
if ($_) { |
if ($_) { |
$feedbackHTML .= ' <a href="/adm/email?display=' |
$feedbackHTML .= ' <a href="/adm/email?display=' |
. &Apache::lonnet::escape($_) . '">' |
. &Apache::lonnet::escape($_) . '">' |
. '<img src="/adm/lonMisc/feedback.gif" ' |
. '<img src="'.$location.'/feedback.gif" ' |
. 'border="0" /></a>'; |
. 'border="0" /></a>'; |
} |
} |
} |
} |
Line 1003 sub render_communication_status {
|
Line 1183 sub render_communication_status {
|
|
|
if ($resource->getErrors()) { |
if ($resource->getErrors()) { |
my $errors = $resource->getErrors(); |
my $errors = $resource->getErrors(); |
|
my $errorcount = 0; |
foreach (split(/,/, $errors)) { |
foreach (split(/,/, $errors)) { |
|
last if ($errorcount>=10); # Only output 10 bombs maximum |
if ($_) { |
if ($_) { |
|
$errorcount++; |
$errorHTML .= ' <a href="/adm/email?display=' |
$errorHTML .= ' <a href="/adm/email?display=' |
. &Apache::lonnet::escape($_) . '">' |
. &Apache::lonnet::escape($_) . '">' |
. '<img src="/adm/lonMisc/bomb.gif" ' |
. '<img src="'.$location.'/bomb.gif" ' |
. 'border="0" /></a>'; |
. 'border="0" /></a>'; |
} |
} |
} |
} |
Line 1036 sub render_quick_status {
|
Line 1219 sub render_quick_status {
|
my $icon = $statusIconMap{$resource->simpleStatus($part)}; |
my $icon = $statusIconMap{$resource->simpleStatus($part)}; |
my $alt = $iconAltTags{$icon}; |
my $alt = $iconAltTags{$icon}; |
if ($icon) { |
if ($icon) { |
$result .= "<td width='30' valign='center' width='50' align='right'>$linkopen<img width='25' height='25' src='/adm/lonIcons/$icon' border='0' alt='$alt' />$linkclose</td>\n"; |
my $location= |
|
&Apache::loncommon::lonhttpdurl("/adm/lonIcons/$icon"); |
|
$result .= "<td width='30' valign='center' width='50' align='right'>$linkopen<img width='25' height='25' src='$location' border='0' alt='$alt' />$linkclose</td>\n"; |
} else { |
} else { |
$result .= "<td width='30'> </td>\n"; |
$result .= "<td width='30'> </td>\n"; |
} |
} |
Line 1056 sub render_long_status {
|
Line 1241 sub render_long_status {
|
if ($resource->is_problem()) { |
if ($resource->is_problem()) { |
$color = $colormap{$resource->status}; |
$color = $colormap{$resource->status}; |
|
|
if (dueInLessThen24Hours($resource, $part) || |
if (dueInLessThan24Hours($resource, $part) || |
lastTry($resource, $part)) { |
lastTry($resource, $part)) { |
$color = $hurryUpColor; |
$color = $hurryUpColor; |
} |
} |
Line 1108 my @statuses = ($resObj->CORRECT, $resOb
|
Line 1293 my @statuses = ($resObj->CORRECT, $resOb
|
use Data::Dumper; |
use Data::Dumper; |
sub render_parts_summary_status { |
sub render_parts_summary_status { |
my ($resource, $part, $params) = @_; |
my ($resource, $part, $params) = @_; |
if (!$resource->is_problem()) { return '<td></td>'; } |
if (!$resource->is_problem() && !$resource->contains_problem) { return '<td></td>'; } |
if ($params->{showParts}) { |
if ($params->{showParts}) { |
return '<td></td>'; |
return '<td></td>'; |
} |
} |
|
|
my $td = "<td align='right'>\n"; |
my $td = "<td align='right'>\n"; |
my $endtd = "</td>\n"; |
my $endtd = "</td>\n"; |
|
my @probs; |
|
|
# If there is a single part, just show the simple status |
if ($resource->contains_problem) { |
if ($resource->singlepart()) { |
@probs=$resource->retrieveResources($resource,sub { $_[0]->is_problem() },1,0); |
my $status = $resource->simpleStatus('0'); |
} else { |
return $td . "<font color='" . $statusColors{$status} . "'>" |
@probs=($resource); |
. $statusStrings{$status} . "</font>" . $endtd; |
} |
} |
my $return; |
|
my %overallstatus; |
# Now we can be sure the $part doesn't really matter. |
my $totalParts; |
my $statusCount = $resource->simpleStatusCount(); |
foreach my $resource (@probs) { |
my @counts; |
# If there is a single part, just show the simple status |
foreach my $status(@statuses) { |
if ($resource->singlepart()) { |
# decouple display order from the simpleStatusCount order |
my $status = $resource->simpleStatus(${$resource->parts}[0]); |
my $slot = Apache::lonnavmaps::resource::statusToSlot($status); |
$overallstatus{$status}++; |
if ($statusCount->[$slot]) { |
$totalParts++; |
push @counts, "<font color='" . $statusColors{$status} . |
next; |
"'>" . $statusCount->[$slot] . ' ' |
} |
|
# Now we can be sure the $part doesn't really matter. |
|
my $statusCount = $resource->simpleStatusCount(); |
|
my @counts; |
|
foreach my $status (@statuses) { |
|
# decouple display order from the simpleStatusCount order |
|
my $slot = Apache::lonnavmaps::resource::statusToSlot($status); |
|
if ($statusCount->[$slot]) { |
|
$overallstatus{$status}+=$statusCount->[$slot]; |
|
$totalParts+=$statusCount->[$slot]; |
|
} |
|
} |
|
} |
|
$return.= $td . $totalParts . ' parts: '; |
|
foreach my $status (@statuses) { |
|
if ($overallstatus{$status}) { |
|
$return.="<font color='" . $statusColors{$status} . |
|
"'>" . $overallstatus{$status} . ' ' |
. $statusStrings{$status} . "</font>"; |
. $statusStrings{$status} . "</font>"; |
} |
} |
} |
} |
|
$return.= $endtd; |
return $td . $resource->countParts() . ' parts: ' . join (', ', @counts) . $endtd; |
return $return; |
} |
} |
|
|
my @preparedColumns = (\&render_resource, \&render_communication_status, |
my @preparedColumns = (\&render_resource, \&render_communication_status, |
Line 1149 sub setDefault {
|
Line 1352 sub setDefault {
|
return $val; |
return $val; |
} |
} |
|
|
|
sub cmp_title { |
|
my ($atitle,$btitle) = (lc($_[0]->compTitle),lc($_[1]->compTitle)); |
|
$atitle=~s/^\s*//; |
|
$btitle=~s/^\s*//; |
|
return $atitle cmp $btitle; |
|
} |
|
|
sub render { |
sub render { |
my $args = shift; |
my $args = shift; |
&Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); |
&Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); |
my $result = ''; |
my $result = ''; |
|
|
# Configure the renderer. |
# Configure the renderer. |
my $cols = $args->{'cols'}; |
my $cols = $args->{'cols'}; |
if (!defined($cols)) { |
if (!defined($cols)) { |
Line 1171 sub render {
|
Line 1380 sub render {
|
my $jump = $args->{'jump'}; |
my $jump = $args->{'jump'}; |
my $here = $args->{'here'}; |
my $here = $args->{'here'}; |
my $suppressNavmap = setDefault($args->{'suppressNavmap'}, 0); |
my $suppressNavmap = setDefault($args->{'suppressNavmap'}, 0); |
|
my $closeAllPages = setDefault($args->{'closeAllPages'}, 0); |
my $currentJumpDelta = 2; # change this to change how many resources are displayed |
my $currentJumpDelta = 2; # change this to change how many resources are displayed |
# before the current resource when using #current |
# before the current resource when using #current |
|
|
Line 1180 sub render {
|
Line 1390 sub render {
|
# marker |
# marker |
my $filterHash = {}; |
my $filterHash = {}; |
# Figure out what we're not displaying |
# Figure out what we're not displaying |
foreach (split(/\,/, $ENV{"form.filter"})) { |
foreach (split(/\,/, $env{"form.filter"})) { |
if ($_) { |
if ($_) { |
$filterHash->{$_} = "1"; |
$filterHash->{$_} = "1"; |
} |
} |
Line 1200 sub render {
|
Line 1410 sub render {
|
} |
} |
|
|
my $condition = 0; |
my $condition = 0; |
if ($ENV{'form.condition'}) { |
if ($env{'form.condition'}) { |
$condition = 1; |
$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 |
# Step 1: Check to see if we have a navmap |
if (!defined($navmap)) { |
if (!defined($navmap)) { |
$navmap = Apache::lonnavmaps::navmap->new(); |
$navmap = Apache::lonnavmaps::navmap->new(); |
Line 1214 sub render {
|
Line 1424 sub render {
|
# Step two: Locate what kind of here marker is necessary |
# Step two: Locate what kind of here marker is necessary |
# Determine where the "here" marker is and where the screen jumps to. |
# Determine where the "here" marker is and where the screen jumps to. |
|
|
if ($ENV{'form.postsymb'}) { |
if ($env{'form.postsymb'}) { |
$here = $jump = $ENV{'form.postsymb'}; |
$here = $jump = &Apache::lonnet::symbclean($env{'form.postsymb'}); |
} elsif ($ENV{'form.postdata'}) { |
} elsif ($env{'form.postdata'}) { |
# couldn't find a symb, is there a URL? |
# couldn't find a symb, is there a URL? |
my $currenturl = $ENV{'form.postdata'}; |
my $currenturl = $env{'form.postdata'}; |
#$currenturl=~s/^http\:\/\///; |
#$currenturl=~s/^http\:\/\///; |
#$currenturl=~s/^[^\/]+//; |
#$currenturl=~s/^[^\/]+//; |
|
|
$here = $jump = &Apache::lonnet::symbread($currenturl); |
$here = $jump = &Apache::lonnet::symbread($currenturl); |
} |
} else { |
|
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 |
# Step three: Ensure the folders are open |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
Line 1233 sub render {
|
Line 1451 sub render {
|
# We only need to do this if we need to open the maps to show the |
# We only need to do this if we need to open the maps to show the |
# current position. This will change the counter so we can't count |
# current position. This will change the counter so we can't count |
# for the jump marker with this loop. |
# for the jump marker with this loop. |
while (($curRes = $mapIterator->next()) && !$found) { |
while ($here && ($curRes = $mapIterator->next()) && !$found) { |
if (ref($curRes) && $curRes->symb() eq $here) { |
if (ref($curRes) && $curRes->symb() eq $here) { |
my $mapStack = $mapIterator->getStack(); |
my $mapStack = $mapIterator->getStack(); |
|
|
Line 1250 sub render {
|
Line 1468 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" |
# 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 |
# from the querystring, and get the new "jump" marker |
$here = $ENV{'form.here'}; |
$here = $env{'form.here'}; |
$jump = $ENV{'form.jump'}; |
$jump = $env{'form.jump'}; |
} |
} |
|
|
my $it = $args->{'iterator'}; |
my $it = $args->{'iterator'}; |
if (!defined($it)) { |
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 |
# Step 1: Check to see if we have a navmap |
if (!defined($navmap)) { |
if (!defined($navmap)) { |
Line 1279 sub render {
|
Line 1497 sub render {
|
$args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition); |
$args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition); |
} |
} |
} |
} |
|
|
# (re-)Locate the jump point, if any |
# (re-)Locate the jump point, if any |
# Note this does not take filtering or hidden into account... need |
# Note this does not take filtering or hidden into account... need |
# to be fixed? |
# to be fixed? |
Line 1309 sub render {
|
Line 1527 sub render {
|
my $printKey = $args->{'printKey'}; |
my $printKey = $args->{'printKey'}; |
my $printCloseAll = $args->{'printCloseAll'}; |
my $printCloseAll = $args->{'printCloseAll'}; |
if (!defined($printCloseAll)) { $printCloseAll = 1; } |
if (!defined($printCloseAll)) { $printCloseAll = 1; } |
|
|
# Print key? |
# Print key? |
if ($printKey) { |
if ($printKey) { |
$result .= '<table border="0" cellpadding="2" cellspacing="0">'; |
$result .= '<table border="0" cellpadding="2" cellspacing="0">'; |
my $date=localtime; |
my $date=localtime; |
$result.='<tr><td align="right" valign="bottom">Key: </td>'; |
$result.='<tr><td align="right" valign="bottom">Key: </td>'; |
|
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); |
if ($navmap->{LAST_CHECK}) { |
if ($navmap->{LAST_CHECK}) { |
$result .= |
$result .= |
'<img src="/adm/lonMisc/chat.gif"> '.&mt('New discussion since').' '. |
'<img src="'.$location.'/chat.gif"> '.&mt('New discussion since').' '. |
strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})). |
strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})). |
'</td><td align="center" valign="bottom"> '. |
'</td><td align="center" valign="bottom"> '. |
'<img src="/adm/lonMisc/feedback.gif"> '.&mt('New message (click to open)').'<p>'. |
'<img src="'.$location.'/feedback.gif"> '.&mt('New message (click to open)').'<p>'. |
'</td>'; |
'</td>'; |
} else { |
} else { |
$result .= '<td align="center" valign="bottom"> '. |
$result .= '<td align="center" valign="bottom"> '. |
'<img src="/adm/lonMisc/chat.gif"> '.&mt('Discussions').'</td><td align="center" valign="bottom">'. |
'<img src="'.$location.'/chat.gif"> '.&mt('Discussions').'</td><td align="center" valign="bottom">'. |
' <img src="/adm/lonMisc/feedback.gif"> '.&mt('New message (click to open)'). |
' <img src="'.$location.'/feedback.gif"> '.&mt('New message (click to open)'). |
'</td>'; |
'</td>'; |
} |
} |
|
|
Line 1333 sub render {
|
Line 1552 sub render {
|
} |
} |
|
|
if ($printCloseAll && !$args->{'resource_no_folder_link'}) { |
if ($printCloseAll && !$args->{'resource_no_folder_link'}) { |
|
my ($link,$text); |
if ($condition) { |
if ($condition) { |
$result.="<a href=\"navmaps?condition=0&filter=&$queryString" . |
$link='"navmaps?condition=0&filter=&'.$queryString. |
"&here=" . Apache::lonnet::escape($here) . |
'&here='.&Apache::lonnet::escape($here).'"'; |
"\">".&mt('Close All Folders')."</a>"; |
$text='Close All Folders'; |
} else { |
} else { |
$result.="<a href=\"navmaps?condition=1&filter=&$queryString" . |
$link='"navmaps?condition=1&filter=&'.$queryString. |
"&here=" . Apache::lonnet::escape($here) . |
'&here='.&Apache::lonnet::escape($here).'"'; |
"\">".&mt('Open All Folders')."</a>"; |
$text='Open All Folders'; |
|
} |
|
if ($args->{'caller'} eq 'navmapsdisplay') { |
|
&add_linkitem($args->{'linkitems'},'changefolder', |
|
'location.href='.$link,$text); |
|
} else { |
|
$result.='<a href='.$link.'>'.&mt($text).'</a>'; |
|
} |
|
$result .= "\n"; |
|
} |
|
|
|
# Check for any unread discussions in all resources. |
|
if ($args->{'caller'} eq 'navmapsdisplay') { |
|
&add_linkitem($args->{'linkitems'},'clearbubbles', |
|
'document.clearbubbles.submit()', |
|
'Mark all posts read'); |
|
my $time=time; |
|
$result .= (<<END); |
|
<form name="clearbubbles" method="post" action="/adm/feedback"> |
|
<input type="hidden" name="navurl" value="$ENV{'QUERY_STRING'}" /> |
|
<input type="hidden" name="navtime" value="$time" /> |
|
END |
|
if ($args->{'sort'} eq 'discussion') { |
|
my $totdisc = 0; |
|
my $haveDisc = ''; |
|
my @allres=$navmap->retrieveResources(); |
|
foreach my $resource (@allres) { |
|
if ($resource->hasDiscussion()) { |
|
$haveDisc .= $resource->wrap_symb().':'; |
|
$totdisc ++; |
|
} |
|
} |
|
if ($totdisc > 0) { |
|
$haveDisc =~ s/:$//; |
|
$result .= (<<END); |
|
<input type="hidden" name="navmaps" value="$haveDisc" /> |
|
</form> |
|
END |
|
} |
|
} |
|
$result.='</form>'; |
|
} |
|
|
|
if ($args->{'caller'} eq 'navmapsdisplay') { |
|
$result .= '<table><tr><td>'. |
|
&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').'</td>'; |
|
if ($env{'environment.remotenavmap'} ne 'on') { |
|
$result .= '<td> </td>'; |
|
} else { |
|
$result .= '</tr><tr>'; |
} |
} |
$result .= "<br /><br />\n"; |
$result.=&show_linkitems($args->{'linkitems'}); |
} |
if ($args->{'sort_html'}) { |
|
if ($env{'environment.remotenavmap'} ne 'on') { |
|
$result.='<td> </td><td> </td><td> </td>'. |
|
'<td align="right">'.$args->{'sort_html'}.'</td></tr>'; |
|
} else { |
|
$result.='</tr><tr><td align="left"><br />'. |
|
$args->{'sort_html'}.'</td></tr>'; |
|
} |
|
} |
|
$result .= '</table>'; |
|
} elsif ($args->{'sort_html'}) { |
|
$result.=$args->{'sort_html'}; |
|
} |
|
|
|
$result .= "<br />\n"; |
if ($r) { |
if ($r) { |
$r->print($result); |
$r->print($result); |
$r->rflush(); |
$r->rflush(); |
Line 1366 sub render {
|
Line 1648 sub render {
|
$args->{'indentLevel'} = 0; |
$args->{'indentLevel'} = 0; |
$args->{'isNewBranch'} = 0; |
$args->{'isNewBranch'} = 0; |
$args->{'condensed'} = 0; |
$args->{'condensed'} = 0; |
$args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='/adm/lonIcons/whitespace1.gif' width='25' height='1' alt='' border='0' />"); |
my $location= |
|
&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace1.gif"); |
|
$args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='$location' width='25' height='1' alt='' border='0' />"); |
$args->{'displayedHereMarker'} = 0; |
$args->{'displayedHereMarker'} = 0; |
|
|
# If we're suppressing empty sequences, look for them here. Use DFS for speed, |
# If we're suppressing empty sequences, look for them here. Use DFS for speed, |
Line 1416 sub render {
|
Line 1700 sub render {
|
$args->{'here'} = $here; |
$args->{'here'} = $here; |
|
|
$args->{'indentLevel'} = -1; # first BEGIN_MAP takes this to 0 |
$args->{'indentLevel'} = -1; # first BEGIN_MAP takes this to 0 |
while ($curRes = $it->next()) { |
my @resources; |
|
my $code='';# sub { !(shift->is_map();) }; |
|
if ($args->{'sort'} eq 'title') { |
|
my $oldFilterFunc = $filterFunc; |
|
my $filterFunc= |
|
sub { |
|
my ($res)=@_; |
|
if ($res->is_map()) { return 0;} |
|
return &$oldFilterFunc($res); |
|
}; |
|
@resources=$navmap->retrieveResources(undef,$filterFunc); |
|
@resources= sort { &cmp_title($a,$b) } @resources; |
|
} elsif ($args->{'sort'} eq 'duedate') { |
|
my $oldFilterFunc = $filterFunc; |
|
my $filterFunc= |
|
sub { |
|
my ($res)=@_; |
|
if (!$res->is_problem()) { return 0;} |
|
return &$oldFilterFunc($res); |
|
}; |
|
@resources=$navmap->retrieveResources(undef,$filterFunc); |
|
@resources= sort { |
|
if ($a->duedate ne $b->duedate) { |
|
return $a->duedate cmp $b->duedate; |
|
} |
|
my $value=&cmp_title($a,$b); |
|
return $value; |
|
} @resources; |
|
} elsif ($args->{'sort'} eq 'discussion') { |
|
my $oldFilterFunc = $filterFunc; |
|
my $filterFunc= |
|
sub { |
|
my ($res)=@_; |
|
if (!$res->hasDiscussion() && |
|
!$res->getFeedback() && |
|
!$res->getErrors()) { return 0;} |
|
return &$oldFilterFunc($res); |
|
}; |
|
@resources=$navmap->retrieveResources(undef,$filterFunc); |
|
@resources= sort { &cmp_title($a,$b) } @resources; |
|
} else { |
|
#unknow sort mechanism or default |
|
undef($args->{'sort'}); |
|
} |
|
|
|
|
|
while (1) { |
|
if ($args->{'sort'}) { |
|
$curRes = shift(@resources); |
|
} else { |
|
$curRes = $it->next($closeAllPages); |
|
} |
|
if (!$curRes) { last; } |
|
|
# Maintain indentation level. |
# Maintain indentation level. |
if ($curRes == $it->BEGIN_MAP() || |
if ($curRes == $it->BEGIN_MAP() || |
$curRes == $it->BEGIN_BRANCH() ) { |
$curRes == $it->BEGIN_BRANCH() ) { |
Line 1519 sub render {
|
Line 1856 sub render {
|
# Add part 0 so we display it correctly. |
# Add part 0 so we display it correctly. |
unshift @parts, '0'; |
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 |
# Now, we've decided what parts to show. Loop through them and |
# show them. |
# show them. |
foreach my $part (@parts) { |
foreach my $part (@parts) { |
Line 1530 sub render {
|
Line 1886 sub render {
|
|
|
# Set up some data about the parts that the cols might want |
# Set up some data about the parts that the cols might want |
my $filter = $it->{FILTER}; |
my $filter = $it->{FILTER}; |
my $stack = $it->getStack(); |
|
my $src = getLinkForResource($stack); |
|
|
|
my $srcHasQuestion = $src =~ /\?/; |
|
$args->{"resourceLink"} = $src. |
|
($srcHasQuestion?'&':'?') . |
|
'symb=' . &Apache::lonnet::escape($curRes->symb()); |
|
|
|
# Now, display each column. |
# Now, display each column. |
foreach my $col (@$cols) { |
foreach my $col (@$cols) { |
my $colHTML = ''; |
my $colHTML = ''; |
Line 1587 sub render {
|
Line 1936 sub render {
|
# it's quite likely this might fix other browsers, too, and |
# it's quite likely this might fix other browsers, too, and |
# certainly won't hurt anything. |
# certainly won't hurt anything. |
if ($displayedJumpMarker) { |
if ($displayedJumpMarker) { |
$result .= "<script>setTimeout(\"location += '#curloc';\", 0)</script>\n"; |
$result .= " |
|
<script> |
|
if (location.href.indexOf('#curloc')==-1) { |
|
setTimeout(\"location += '#curloc';\", 0) |
|
} |
|
</script>"; |
} |
} |
|
|
$result .= "</table>"; |
$result .= "</table>"; |
Line 1598 sub render {
|
Line 1952 sub render {
|
$r->rflush(); |
$r->rflush(); |
} |
} |
|
|
if ($mustCloseNavMap) { $navmap->untieHashes(); } |
return $result; |
|
} |
|
|
|
sub add_linkitem { |
|
my ($linkitems,$name,$cmd,$text)=@_; |
|
$$linkitems{$name}{'cmd'}=$cmd; |
|
$$linkitems{$name}{'text'}=&mt($text); |
|
} |
|
|
|
sub show_linkitems { |
|
my ($linkitems)=@_; |
|
my @linkorder = ("blank","launchnav","closenav","firsthomework", |
|
"everything","uncompleted","changefolder","clearbubbles"); |
|
|
|
my $result .= (<<ENDBLOCK); |
|
<td align="left"> |
|
<script type="text/javascript"> |
|
function changeNavDisplay () { |
|
var navchoice = document.linkitems.toplink[document.linkitems.toplink.selectedIndex].value; |
|
ENDBLOCK |
|
foreach my $link (@linkorder) { |
|
$result.= "if (navchoice == '$link') {". |
|
$linkitems->{$link}{'cmd'}."}\n"; |
|
} |
|
$result.='} |
|
</script> |
|
<form name="linkitems" method="post"> |
|
<nobr><select name="toplink">'."\n"; |
|
foreach my $link (@linkorder) { |
|
if (defined($linkitems->{$link})) { |
|
if ($linkitems->{$link}{'text'} ne '') { |
|
$result .= ' <option value="'.$link.'">'. |
|
$linkitems->{$link}{'text'}."</option>\n"; |
|
} |
|
} |
|
} |
|
$result .= '</select> <input type="button" name="chgnav" |
|
value="Go" onClick="javascript:changeNavDisplay()" /> |
|
</nobr></form></td>'."\n"; |
|
|
return $result; |
return $result; |
} |
} |
|
|
Line 1660 successful, or B<undef> if not.
|
Line 2052 successful, or B<undef> if not.
|
|
|
=back |
=back |
|
|
When you are done with the $navmap object, you I<must> call |
|
$navmap->untieHashes(), or you'll prevent the current user from using that |
|
course until the web server is restarted. (!) |
|
|
|
=head2 Methods |
=head2 Methods |
|
|
=over 4 |
=over 4 |
Line 1676 See iterator documentation below.
|
Line 2064 See iterator documentation below.
|
|
|
use strict; |
use strict; |
use GDBM_File; |
use GDBM_File; |
|
use Apache::lonnet; |
|
|
sub new { |
sub new { |
# magic invocation to create a class instance |
# magic invocation to create a class instance |
Line 1695 sub new {
|
Line 2084 sub new {
|
|
|
my %navmaphash; |
my %navmaphash; |
my %parmhash; |
my %parmhash; |
my $courseFn = $ENV{"request.course.fn"}; |
my $courseFn = $env{"request.course.fn"}; |
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
&GDBM_READER(), 0640))) { |
&GDBM_READER(), 0640))) { |
return undef; |
return undef; |
Line 1721 sub generate_course_user_opt {
|
Line 2110 sub generate_course_user_opt {
|
my $self = shift; |
my $self = shift; |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
|
|
my $uname=$ENV{'user.name'}; |
my $uname=$env{'user.name'}; |
my $udom=$ENV{'user.domain'}; |
my $udom=$env{'user.domain'}; |
my $uhome=$ENV{'user.home'}; |
my $cid=$env{'request.course.id'}; |
my $cid=$ENV{'request.course.id'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $chome=$ENV{'course.'.$cid.'.home'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my ($cdom,$cnum)=split(/\_/,$cid); |
|
|
|
my $userprefix=$uname.'_'.$udom.'_'; |
|
|
|
my %courserdatas; my %useropt; my %courseopt; my %userrdatas; |
my $useropt; my $courseopt; |
unless ($uhome eq 'no_host') { |
|
# ------------------------------------------------- Get coursedata (if present) |
# ------------------------------------------------- Get coursedata (if present) |
unless ((time-$courserdatas{$cid.'.last_cache'})<240) { |
my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom); |
my $reply=&Apache::lonnet::reply('dump:'.$cdom.':'.$cnum. |
# Check for network failure |
':resourcedata',$chome); |
if (!ref($courseopt)) { |
# Check for network failure |
if ( $courseopt =~ /no.such.host/i || $courseopt =~ /con_lost/i) { |
if ( $reply =~ /no.such.host/i || $reply =~ /con_lost/i) { |
$self->{NETWORK_FAILURE} = 1; |
$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); |
|
} |
} |
|
undef($courseopt); |
|
} |
|
|
# --------------------------------------------------- Get userdata (if present) |
# --------------------------------------------------- Get userdata (if present) |
unless ((time-$userrdatas{$uname.'___'.$udom.'.last_cache'})<240) { |
|
my $reply=&Apache::lonnet::reply('dump:'.$udom.':'.$uname.':resourcedata',$uhome); |
my $useropt=&Apache::lonnet::get_userresdata($uname,$udom); |
if ($reply!~/^error\:/) { |
# Check for network failure |
$userrdatas{$uname.'___'.$udom}=$reply; |
if (!ref($useropt)) { |
$userrdatas{$uname.'___'.$udom.'.last_cache'}=time; |
if ( $useropt =~ /no.such.host/i || $useropt =~ /con_lost/i) { |
} |
$self->{NETWORK_FAILURE} = 1; |
# 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); |
|
} |
} |
$self->{COURSE_OPT} = \%courseopt; |
undef($useropt); |
$self->{USER_OPT} = \%useropt; |
|
} |
} |
|
|
|
$self->{COURSE_OPT} = $courseopt; |
|
$self->{USER_OPT} = $useropt; |
|
|
$self->{COURSE_USER_OPT_GENERATED} = 1; |
$self->{COURSE_USER_OPT_GENERATED} = 1; |
|
|
return; |
return; |
Line 1778 sub generate_course_user_opt {
|
Line 2149 sub generate_course_user_opt {
|
|
|
sub generate_email_discuss_status { |
sub generate_email_discuss_status { |
my $self = shift; |
my $self = shift; |
|
my $symb = shift; |
if ($self->{EMAIL_DISCUSS_GENERATED}) { return; } |
if ($self->{EMAIL_DISCUSS_GENERATED}) { return; } |
|
|
my $cid=$ENV{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
my ($cdom,$cnum)=split(/\_/,$cid); |
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'); |
my $logoutTime = $emailstatus{'logout'}; |
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) ? |
$self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? |
$courseLeaveTime : $logoutTime); |
$courseLeaveTime : $logoutTime); |
my %discussiontime = &Apache::lonnet::dump('discussiontimes', |
my %discussiontime = &Apache::lonnet::dump('discussiontimes', |
$cdom, $cnum); |
$cdom, $cnum); |
|
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{$_}; |
|
} |
|
|
my %feedback=(); |
my %feedback=(); |
my %error=(); |
my %error=(); |
my $keys = &Apache::lonnet::reply('keys:'. |
my @keys = &Apache::lonnet::getkeys('nohist_email',$env{'user.domain'}, |
$ENV{'user.domain'}.':'. |
$env{'user.name'}); |
$ENV{'user.name'}.':nohist_email', |
|
$ENV{'user.home'}); |
|
|
|
foreach my $msgid (split(/\&/, $keys)) { |
foreach my $msgid (@keys) { |
$msgid=&Apache::lonnet::unescape($msgid); |
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { |
my $plain=&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid)); |
my $plain= |
if ($plain=~/(Error|Feedback) \[([^\]]+)\]/) { |
&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid)); |
my ($what,$url)=($1,$2); |
if ($plain=~/(Error|Feedback) \[([^\]]+)\]/) { |
my %status= |
my ($what,$url)=($1,$2); |
&Apache::lonnet::get('email_status',[$msgid]); |
|
if ($status{$msgid}=~/^error\:/) { |
|
$status{$msgid}=''; |
|
} |
|
|
|
if (($status{$msgid} eq 'new') || |
|
(!$status{$msgid})) { |
|
if ($what eq 'Error') { |
if ($what eq 'Error') { |
$error{$url}.=','.$msgid; |
$error{$url}.=','.$msgid; |
} else { |
} else { |
Line 1819 sub generate_email_discuss_status {
|
Line 2192 sub generate_email_discuss_status {
|
} |
} |
} |
} |
|
|
|
#url's of resources that have feedbacks |
$self->{FEEDBACK} = \%feedback; |
$self->{FEEDBACK} = \%feedback; |
$self->{ERROR_MSG} = \%error; # what is this? JB |
#or errors |
|
$self->{ERROR_MSG} = \%error; |
$self->{DISCUSSION_TIME} = \%discussiontime; |
$self->{DISCUSSION_TIME} = \%discussiontime; |
$self->{EMAIL_STATUS} = \%emailstatus; |
$self->{EMAIL_STATUS} = \%emailstatus; |
|
$self->{LAST_READ} = \%lastreadtime; |
|
|
$self->{EMAIL_DISCUSS_GENERATED} = 1; |
$self->{EMAIL_DISCUSS_GENERATED} = 1; |
} |
} |
Line 1832 sub get_user_data {
|
Line 2208 sub get_user_data {
|
if ($self->{RETRIEVED_USER_DATA}) { return; } |
if ($self->{RETRIEVED_USER_DATA}) { return; } |
|
|
# Retrieve performance data on problems |
# Retrieve performance data on problems |
my %student_data = Apache::lonnet::currentdump($ENV{'request.course.id'}, |
my %student_data = Apache::lonnet::currentdump($env{'request.course.id'}, |
$ENV{'user.domain'}, |
$env{'user.domain'}, |
$ENV{'user.name'}); |
$env{'user.name'}); |
$self->{STUDENT_DATA} = \%student_data; |
$self->{STUDENT_DATA} = \%student_data; |
|
|
$self->{RETRIEVED_USER_DATA} = 1; |
$self->{RETRIEVED_USER_DATA} = 1; |
Line 1859 sub navhash {
|
Line 2235 sub navhash {
|
# Checks to see if coursemap is defined, matching test in old lonnavmaps |
# Checks to see if coursemap is defined, matching test in old lonnavmaps |
sub courseMapDefined { |
sub courseMapDefined { |
my $self = shift; |
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 $firstres = $self->navhash("map_start_$uri"); |
my $lastres = $self->navhash("map_finish_$uri"); |
my $lastres = $self->navhash("map_finish_$uri"); |
Line 1869 sub courseMapDefined {
|
Line 2245 sub courseMapDefined {
|
sub getIterator { |
sub getIterator { |
my $self = shift; |
my $self = shift; |
my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift, |
my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift, |
shift, undef, shift); |
shift, undef, shift, |
|
shift, shift); |
return $iterator; |
return $iterator; |
} |
} |
|
|
# unties the hash when done |
|
sub untieHashes { |
|
my $self = shift; |
|
untie %{$self->{NAV_HASH}}; |
|
untie %{$self->{PARM_HASH}}; |
|
} |
|
|
|
# Private method: Does the given resource (as a symb string) have |
# Private method: Does the given resource (as a symb string) have |
# current discussion? Returns 0 if chat/mail data not extracted. |
# current discussion? Returns 0 if chat/mail data not extracted. |
sub hasDiscussion { |
sub hasDiscussion { |
my $self = shift; |
my $self = shift; |
my $symb = shift; |
my $symb = shift; |
|
|
$self->generate_email_discuss_status(); |
$self->generate_email_discuss_status(); |
|
|
if (!defined($self->{DISCUSSION_TIME})) { return 0; } |
if (!defined($self->{DISCUSSION_TIME})) { return 0; } |
|
|
#return defined($self->{DISCUSSION_TIME}->{$symb}); |
#return defined($self->{DISCUSSION_TIME}->{$symb}); |
return $self->{DISCUSSION_TIME}->{$symb} > |
|
$self->{LAST_CHECK}; |
# 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 { |
|
# return $self->{DISCUSSION_TIME}->{$ressymb} > $self->{LAST_CHECK}; # v.1.1 behavior |
|
return $self->{DISCUSSION_TIME}->{$ressymb} > 0; # in 1.2 will display speech bubble icons for all items with posts until marked as read (even if read in v 1.1). |
|
} |
|
} |
|
|
|
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 |
# Private method: Does the given resource (as a symb string) have |
# current feedback? Returns the string in the feedback hash, which |
# current feedback? Returns the string in the feedback hash, which |
# will be false if it does not exist. |
# will be false if it does not exist. |
|
|
sub getFeedback { |
sub getFeedback { |
my $self = shift; |
my $self = shift; |
my $symb = shift; |
my $symb = shift; |
Line 1963 sub getById {
|
Line 2351 sub getById {
|
sub getBySymb { |
sub getBySymb { |
my $self = shift; |
my $self = shift; |
my $symb = shift; |
my $symb = shift; |
|
|
my ($mapUrl, $id, $filename) = &Apache::lonnet::decode_symb($symb); |
my ($mapUrl, $id, $filename) = &Apache::lonnet::decode_symb($symb); |
my $map = $self->getResourceByUrl($mapUrl); |
my $map = $self->getResourceByUrl($mapUrl); |
return $self->getById($map->map_pc() . '.' . $id); |
my $returnvalue = undef; |
|
if (ref($map)) { |
|
$returnvalue = $self->getById($map->map_pc() .'.'.$id); |
|
} |
|
return $returnvalue; |
} |
} |
|
|
sub getByMapPc { |
sub getByMapPc { |
Line 1988 resource in the navmap.
|
Line 2381 resource in the navmap.
|
sub firstResource { |
sub firstResource { |
my $self = shift; |
my $self = shift; |
my $firstResource = $self->navhash('map_start_' . |
my $firstResource = $self->navhash('map_start_' . |
&Apache::lonnet::clutter($ENV{'request.course.uri'})); |
&Apache::lonnet::clutter($env{'request.course.uri'})); |
return $self->getById($firstResource); |
return $self->getById($firstResource); |
} |
} |
|
|
Line 2004 in the navmap.
|
Line 2397 in the navmap.
|
sub finishResource { |
sub finishResource { |
my $self = shift; |
my $self = shift; |
my $firstResource = $self->navhash('map_finish_' . |
my $firstResource = $self->navhash('map_finish_' . |
&Apache::lonnet::clutter($ENV{'request.course.uri'})); |
&Apache::lonnet::clutter($env{'request.course.uri'})); |
return $self->getById($firstResource); |
return $self->getById($firstResource); |
} |
} |
|
|
Line 2031 sub parmval_real {
|
Line 2424 sub parmval_real {
|
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated |
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated |
$self->generate_course_user_opt(); |
$self->generate_course_user_opt(); |
|
|
my $cid=$ENV{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
my $csec=$ENV{'request.course.sec'}; |
my $csec=$env{'request.course.sec'}; |
my $uname=$ENV{'user.name'}; |
my $uname=$env{'user.name'}; |
my $udom=$ENV{'user.domain'}; |
my $udom=$env{'user.domain'}; |
|
|
unless ($symb) { return ''; } |
unless ($symb) { return ''; } |
my $result=''; |
my $result=''; |
Line 2048 sub parmval_real {
|
Line 2441 sub parmval_real {
|
|
|
my $symbparm=$symb.'.'.$what; |
my $symbparm=$symb.'.'.$what; |
my $mapparm=$mapname.'___(all).'.$what; |
my $mapparm=$mapname.'___(all).'.$what; |
my $usercourseprefix=$uname.'_'.$udom.'_'.$cid; |
my $usercourseprefix=$cid; |
|
|
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; |
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; |
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; |
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; |
Line 2078 sub parmval_real {
|
Line 2471 sub parmval_real {
|
|
|
if (defined($courseopt)) { |
if (defined($courseopt)) { |
if (defined($$courseopt{$courselevelr})) { return $$courseopt{$courselevelr}; } |
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 |
# ----------------------------------------------------- third, check map parms |
Line 2096 sub parmval_real {
|
Line 2487 sub parmval_real {
|
$default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat); |
$default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat); |
if (defined($default)) { return $default} |
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 ($space,@qualifier)=split(/\./,$rwhat); |
my $qualifier=join('.',@qualifier); |
my $qualifier=join('.',@qualifier); |
Line 2125 you're not sure if $res is already an ob
|
Line 2522 you're not sure if $res is already an ob
|
resource appears multiple times in the course, only the first instance |
resource appears multiple times in the course, only the first instance |
will be returned. As a result, this is probably useful only for maps. |
will be returned. As a result, this is probably useful only for maps. |
|
|
=item * B<retrieveResources>(map, filterFunc, recursive, bailout): |
=item * B<retrieveResources>(map, filterFunc, recursive, bailout, showall): |
|
|
The map is a specification of a map to retreive the resources from, |
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 |
either as a url or as an object. The filterFunc is a reference to a |
Line 2133 function that takes a resource object as
|
Line 2530 function that takes a resource object as
|
true if the resource should be included, or false if it should not |
true if the resource should be included, or false if it should not |
be. If recursive is true, the map will be recursively examined, |
be. If recursive is true, the map will be recursively examined, |
otherwise it will not be. If bailout is true, the function will return |
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, |
as soon as it finds a resource, if false it will finish. If showall is |
the map is the top-level map of the course, filterFunc is a function |
true it will not hide maps that contain nothing but one other map. By |
that always returns 1, recursive is true, bailout is false. The |
default, the map is the top-level map of the course, filterFunc is a |
resources will be returned in a list containing the resource objects |
function that always returns 1, recursive is true, bailout is false, |
for the corresponding resources, with B<no structure information> in |
showall is false. The resources will be returned in a list containing |
the list; regardless of branching, recursion, etc., it will be a flat |
the resource objects for the corresponding resources, with B<no |
list. |
structure information> 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, |
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 |
just a list of all resources. It is also suitable for finding out how |
Line 2148 want to know is if I<any> resources matc
|
Line 2546 want to know is if I<any> resources matc
|
parameter will allow you to avoid potentially expensive enumeration of |
parameter will allow you to avoid potentially expensive enumeration of |
all matching resources. |
all matching resources. |
|
|
=item * B<hasResources>(map, filterFunc, recursive): |
=item * B<hasResource>(map, filterFunc, recursive, showall): |
|
|
Convience method for |
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 |
which will tell whether the map has resources matching the description |
in the filter function. |
in the filter function. |
|
|
=cut |
=cut |
|
|
|
|
sub getResourceByUrl { |
sub getResourceByUrl { |
my $self = shift; |
my $self = shift; |
my $resUrl = shift; |
my $resUrl = shift; |
Line 2185 sub retrieveResources {
|
Line 2584 sub retrieveResources {
|
if (!defined($recursive)) { $recursive = 1; } |
if (!defined($recursive)) { $recursive = 1; } |
my $bailout = shift; |
my $bailout = shift; |
if (!defined($bailout)) { $bailout = 0; } |
if (!defined($bailout)) { $bailout = 0; } |
|
my $showall = shift; |
# Create the necessary iterator. |
# Create the necessary iterator. |
if (!ref($map)) { # assume it's a url of a map. |
if (!ref($map)) { # assume it's a url of a map. |
$map = $self->getResourceByUrl($map); |
$map = $self->getResourceByUrl($map); |
Line 2204 sub retrieveResources {
|
Line 2603 sub retrieveResources {
|
|
|
# Get an iterator. |
# Get an iterator. |
my $it = $self->getIterator($map->map_start(), $map->map_finish(), |
my $it = $self->getIterator($map->map_start(), $map->map_finish(), |
undef, $recursive); |
undef, $recursive, $showall); |
|
|
my @resources = (); |
my @resources = (); |
|
|
Line 2234 sub hasResource {
|
Line 2633 sub hasResource {
|
my $map = shift; |
my $map = shift; |
my $filterFunc = shift; |
my $filterFunc = shift; |
my $recursive = 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; |
1; |
|
|
package Apache::lonnavmaps::iterator; |
package Apache::lonnavmaps::iterator; |
|
use WeakRef; |
|
use Apache::lonnet; |
|
|
=pod |
=pod |
|
|
Line 2381 sub new {
|
Line 2783 sub new {
|
my $class = ref($proto) || $proto; |
my $class = ref($proto) || $proto; |
my $self = {}; |
my $self = {}; |
|
|
$self->{NAV_MAP} = shift; |
weaken($self->{NAV_MAP} = shift); |
return undef unless ($self->{NAV_MAP}); |
return undef unless ($self->{NAV_MAP}); |
|
|
# Handle the parameters |
# Handle the parameters |
Line 2494 sub new {
|
Line 2896 sub new {
|
} |
} |
|
|
# Check: Was this only one resource, a map? |
# Check: Was this only one resource, a map? |
if ($resourceCount == 1 && $resource->is_map() && !$self->{FORCE_TOP}) { |
if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { |
my $firstResource = $resource->map_start(); |
my $firstResource = $resource->map_start(); |
my $finishResource = $resource->map_finish(); |
my $finishResource = $resource->map_finish(); |
return |
return |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
$finishResource, $self->{FILTER}, |
$finishResource, $self->{FILTER}, |
$self->{ALREADY_SEEN}, |
$self->{ALREADY_SEEN}, |
$self->{CONDITION}, 0); |
$self->{CONDITION}, |
|
$self->{FORCE_TOP}); |
|
|
} |
} |
|
|
Line 2527 sub new {
|
Line 2930 sub new {
|
|
|
sub next { |
sub next { |
my $self = shift; |
my $self = shift; |
|
my $closeAllPages=shift; |
if ($self->{FINISHED}) { |
if ($self->{FINISHED}) { |
return END_ITERATOR(); |
return END_ITERATOR(); |
} |
} |
Line 2541 sub next {
|
Line 2944 sub next {
|
|
|
if ($self->{RECURSIVE_ITERATOR_FLAG}) { |
if ($self->{RECURSIVE_ITERATOR_FLAG}) { |
# grab the next from the recursive iterator |
# grab the next from the recursive iterator |
my $next = $self->{RECURSIVE_ITERATOR}->next(); |
my $next = $self->{RECURSIVE_ITERATOR}->next($closeAllPages); |
|
|
# is it a begin or end map? If so, update the depth |
# is it a begin or end map? If so, update the depth |
if ($next == BEGIN_MAP() ) { $self->{RECURSIVE_DEPTH}++; } |
if ($next == BEGIN_MAP() ) { $self->{RECURSIVE_DEPTH}++; } |
Line 2655 sub next {
|
Line 3058 sub next {
|
|
|
# That ends the main iterator logic. Now, do we want to recurse |
# That ends the main iterator logic. Now, do we want to recurse |
# down this map (if this resource is a map)? |
# down this map (if this resource is a map)? |
if ($self->{HERE}->is_map() && |
if ( ($self->{HERE}->is_sequence() || (!$closeAllPages && $self->{HERE}->is_page())) && |
(defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) { |
(defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) { |
$self->{RECURSIVE_ITERATOR_FLAG} = 1; |
$self->{RECURSIVE_ITERATOR_FLAG} = 1; |
my $firstResource = $self->{HERE}->map_start(); |
my $firstResource = $self->{HERE}->map_start(); |
Line 2664 sub next {
|
Line 3067 sub next {
|
$self->{RECURSIVE_ITERATOR} = |
$self->{RECURSIVE_ITERATOR} = |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
$finishResource, $self->{FILTER}, |
$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. |
# If this is a blank resource, don't actually return it. |
Line 2673 sub next {
|
Line 3078 sub next {
|
my $browsePriv = $self->{HERE}->browsePriv(); |
my $browsePriv = $self->{HERE}->browsePriv(); |
if (!$self->{HERE}->src() || |
if (!$self->{HERE}->src() || |
(!($browsePriv eq 'F') && !($browsePriv eq '2')) ) { |
(!($browsePriv eq 'F') && !($browsePriv eq '2')) ) { |
return $self->next(); |
return $self->next($closeAllPages); |
} |
} |
|
|
return $self->{HERE}; |
return $self->{HERE}; |
Line 2717 sub populateStack {
|
Line 3122 sub populateStack {
|
1; |
1; |
|
|
package Apache::lonnavmaps::DFSiterator; |
package Apache::lonnavmaps::DFSiterator; |
|
use WeakRef; |
|
use Apache::lonnet; |
|
|
# Not documented in the perldoc: This is a simple iterator that just walks |
# 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 |
# through the nav map and presents the resources in a depth-first search |
Line 2725 package Apache::lonnavmaps::DFSiterator;
|
Line 3132 package Apache::lonnavmaps::DFSiterator;
|
# useful for pre-processing of some kind, and is in fact used by the main |
# useful for pre-processing of some kind, and is in fact used by the main |
# iterator that way, but that's about it. |
# iterator that way, but that's about it. |
# One could imagine merging this into the init routine of the main iterator, |
# One could imagine merging this into the init routine of the main iterator, |
# but this might as well be left seperate, since it is possible some other |
# but this might as well be left separate, since it is possible some other |
# use might be found for it. - Jeremy |
# use might be found for it. - Jeremy |
|
|
# Unlike the main iterator, this DOES return all resources, even blank ones. |
# Unlike the main iterator, this DOES return all resources, even blank ones. |
Line 2745 sub new {
|
Line 3152 sub new {
|
my $class = ref($proto) || $proto; |
my $class = ref($proto) || $proto; |
my $self = {}; |
my $self = {}; |
|
|
$self->{NAV_MAP} = shift; |
weaken($self->{NAV_MAP} = shift); |
return undef unless ($self->{NAV_MAP}); |
return undef unless ($self->{NAV_MAP}); |
|
|
$self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); |
$self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); |
Line 2899 sub populateStack {
|
Line 3306 sub populateStack {
|
1; |
1; |
|
|
package Apache::lonnavmaps::resource; |
package Apache::lonnavmaps::resource; |
|
use WeakRef; |
use Apache::lonnet; |
use Apache::lonnet; |
|
|
=pod |
=pod |
Line 2981 sub new {
|
Line 3388 sub new {
|
my $class = ref($proto) || $proto; |
my $class = ref($proto) || $proto; |
my $self = {}; |
my $self = {}; |
|
|
$self->{NAV_MAP} = shift; |
weaken($self->{NAV_MAP} = shift); |
$self->{ID} = shift; |
$self->{ID} = shift; |
|
|
# Store this new resource in the parent nav map's cache. |
# Store this new resource in the parent nav map's cache. |
Line 3069 Returns the title of the resource.
|
Line 3476 Returns the title of the resource.
|
# These info functions can be used directly, as they don't return |
# These info functions can be used directly, as they don't return |
# resource information. |
# resource information. |
sub comesfrom { my $self=shift; return $self->navHash("comesfrom_", 1); } |
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 ext { my $self=shift; return $self->navHash("ext_", 1) eq 'true:'; } |
sub from { my $self=shift; return $self->navHash("from_", 1); } |
sub from { my $self=shift; return $self->navHash("from_", 1); } |
# considered private and undocumented |
# considered private and undocumented |
Line 3080 sub randompick {
|
Line 3488 sub randompick {
|
return $self->{NAV_MAP}->{PARM_HASH}->{$self->symb . |
return $self->{NAV_MAP}->{PARM_HASH}->{$self->symb . |
'.0.parameter_randompick'}; |
'.0.parameter_randompick'}; |
} |
} |
|
sub link { |
|
my $self=shift; |
|
if ($self->encrypted()) { return &Apache::lonenc::encrypted($self->src); } |
|
return $self->src; |
|
} |
sub src { |
sub src { |
my $self=shift; |
my $self=shift; |
return $self->navHash("src_", 1); |
return $self->navHash("src_", 1); |
} |
} |
|
sub shown_symb { |
|
my $self=shift; |
|
if ($self->encrypted()) {return &Apache::lonenc::encrypted($self->symb());} |
|
return $self->symb(); |
|
} |
sub symb { |
sub symb { |
my $self=shift; |
my $self=shift; |
(my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/; |
(my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/; |
Line 3092 sub symb {
|
Line 3510 sub symb {
|
. '___' . $second . '___' . $symbSrc; |
. '___' . $second . '___' . $symbSrc; |
return &Apache::lonnet::symbclean($symb); |
return &Apache::lonnet::symbclean($symb); |
} |
} |
|
sub wrap_symb { |
|
my $self = shift; |
|
return $self->{NAV_MAP}->wrap_symb($self->symb()); |
|
} |
sub title { |
sub title { |
my $self=shift; |
my $self=shift; |
if ($self->{ID} eq '0.0') { |
if ($self->{ID} eq '0.0') { |
# If this is the top-level map, return the title of the course |
# If this is the top-level map, return the title of the course |
# since this map can not be titled otherwise. |
# 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); } |
return $self->navHash("title_", 1); } |
# considered private and undocumented |
# considered private and undocumented |
sub to { my $self=shift; return $self->navHash("to_", 1); } |
sub to { my $self=shift; return $self->navHash("to_", 1); } |
|
sub condition { |
|
my $self=shift; |
|
my $undercond=$self->navHash("undercond_", 1); |
|
if (!defined($undercond)) { return 1; }; |
|
my $condid=$self->navHash("condid_$undercond"); |
|
if (!defined($condid)) { return 1; }; |
|
my $condition=&Apache::lonnet::directcondval($condid); |
|
return $condition; |
|
} |
|
|
sub compTitle { |
sub compTitle { |
my $self = shift; |
my $self = shift; |
my $title = $self->title(); |
my $title = $self->title(); |
Line 3142 Returns true if the resource is a sequen
|
Line 3574 Returns true if the resource is a sequen
|
|
|
=cut |
=cut |
|
|
|
sub hasResource { |
|
my $self = shift; |
|
return $self->{NAV_MAP}->hasResource(@_); |
|
} |
|
|
|
sub retrieveResources { |
|
my $self = shift; |
|
return $self->{NAV_MAP}->retrieveResources(@_); |
|
} |
|
|
sub is_html { |
sub is_html { |
my $self=shift; |
my $self=shift; |
Line 3158 sub is_page {
|
Line 3599 sub is_page {
|
sub is_problem { |
sub is_problem { |
my $self=shift; |
my $self=shift; |
my $src = $self->src(); |
my $src = $self->src(); |
return ($src =~ /problem$/); |
return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library)$/) |
|
} |
|
sub contains_problem { |
|
my $self=shift; |
|
if ($self->is_page()) { |
|
my $hasProblem=$self->hasResource($self,sub { $_[0]->is_problem() },1); |
|
return $hasProblem; |
|
} |
|
return 0; |
} |
} |
sub is_sequence { |
sub is_sequence { |
my $self=shift; |
my $self=shift; |
Line 3166 sub is_sequence {
|
Line 3615 sub is_sequence {
|
return $self->navHash("is_map_", 1) && |
return $self->navHash("is_map_", 1) && |
$self->navHash("map_type_" . $self->map_pc()) eq 'sequence'; |
$self->navHash("map_type_" . $self->map_pc()) eq 'sequence'; |
} |
} |
|
sub is_survey { |
|
my $self = shift(); |
|
my $part = shift(); |
|
if ($self->parmval('type',$part) eq 'survey') { |
|
return 1; |
|
} |
|
if ($self->src() =~ /\.(survey)$/) { |
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
sub is_empty_sequence { |
|
my $self=shift; |
|
my $src = $self->src(); |
|
return !$self->is_page() && $self->navHash("is_map_", 1) && !$self->navHash("map_type_" . $self->map_pc()); |
|
} |
|
|
# Private method: Shells out to the parmval in the nav map, handler parts. |
# Private method: Shells out to the parmval in the nav map, handler parts. |
sub parmval { |
sub parmval { |
Line 3342 sub awarded {
|
Line 3808 sub awarded {
|
} |
} |
sub duedate { |
sub duedate { |
(my $self, my $part) = @_; |
(my $self, my $part) = @_; |
|
my $interval=$self->parmval("interval", $part); |
|
if ($interval) { |
|
my $first_access=&Apache::lonnet::get_first_access('map',$self->symb); |
|
if ($first_access) { return ($first_access+$interval); } |
|
} |
return $self->parmval("duedate", $part); |
return $self->parmval("duedate", $part); |
} |
} |
sub maxtries { |
sub maxtries { |
Line 3382 sub weight {
|
Line 3853 sub weight {
|
my $self = shift; my $part = shift; |
my $self = shift; my $part = shift; |
if (!defined($part)) { $part = '0'; } |
if (!defined($part)) { $part = '0'; } |
return &Apache::lonnet::EXT('resource.'.$part.'.weight', |
return &Apache::lonnet::EXT('resource.'.$part.'.weight', |
$self->symb(), $ENV{'user.domain'}, |
$self->symb(), $env{'user.domain'}, |
$ENV{'user.name'}, |
$env{'user.name'}, |
$ENV{'request.course.sec'}); |
$env{'request.course.sec'}); |
|
} |
|
sub part_display { |
|
my $self= shift(); my $partID = shift(); |
|
if (! defined($partID)) { $partID = '0'; } |
|
my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display', |
|
$self->symb); |
|
if (! defined($display) || $display eq '') { |
|
$display = $partID; |
|
} |
|
return $display; |
} |
} |
|
|
# Multiple things need this |
# Multiple things need this |
Line 3475 Returns the number of parts of the probl
|
Line 3955 Returns the number of parts of the probl
|
for single part problems, returns 1. For multipart, it returns the |
for single part problems, returns 1. For multipart, it returns the |
number of parts in the problem, not including psuedo-part 0. |
number of parts in the problem, not including psuedo-part 0. |
|
|
|
=item * B<countResponses>(): |
|
|
|
Returns the total number of responses in the problem a student can answer. |
|
|
|
=item * B<responseTypes>(): |
|
|
|
Returns a hash whose keys are the response types. The values are the number |
|
of times each response type is used. This is for the I<entire> problem, not |
|
just a single part. |
|
|
=item * B<multipart>(): |
=item * B<multipart>(): |
|
|
Returns true if the problem is multipart, false otherwise. Use this instead |
Returns true if the problem is multipart, false otherwise. Use this instead |
Line 3521 sub countParts {
|
Line 4011 sub countParts {
|
return scalar(@{$parts}); # + $delta; |
return scalar(@{$parts}); # + $delta; |
} |
} |
|
|
|
sub countResponses { |
|
my $self = shift; |
|
my $count; |
|
foreach my $part (@{$self->parts()}) { |
|
$count+= scalar($self->responseIds($part)); |
|
} |
|
return $count; |
|
} |
|
|
|
sub responseTypes { |
|
my $self = shift; |
|
my %responses; |
|
foreach my $part ($self->parts()) { |
|
foreach my $responsetype ($self->responseType($part)) { |
|
$responses{$responsetype}++ if (defined($responsetype)); |
|
} |
|
} |
|
return %responses; |
|
} |
|
|
sub multipart { |
sub multipart { |
my $self = shift; |
my $self = shift; |
return $self->countParts() > 1; |
return $self->countParts() > 1; |
Line 3608 sub extractParts {
|
Line 4118 sub extractParts {
|
} |
} |
|
|
|
|
|
# These hashes probably do not need names that end with "Hash".... |
my %responseIdHash; |
my %responseIdHash; |
my %responseTypeHash; |
my %responseTypeHash; |
|
|
Line 3642 sub extractParts {
|
Line 4153 sub extractParts {
|
} |
} |
} |
} |
} |
} |
|
my $resorder = &Apache::lonnet::metadata($self->src(),'responseorder'); |
|
# |
|
# Reorder the arrays in the %responseIdHash and %responseTypeHash |
|
if ($resorder) { |
|
my @resorder=split(/,/,$resorder); |
|
foreach my $part (keys(%responseIdHash)) { |
|
my $i=0; |
|
my %resids = map { ($_,$i++) } @{ $responseIdHash{$part} }; |
|
my @neworder; |
|
foreach my $possibleid (@resorder) { |
|
if (exists($resids{$possibleid})) { |
|
push(@neworder,$resids{$possibleid}); |
|
} |
|
} |
|
my @ids; |
|
my @type; |
|
foreach my $element (@neworder) { |
|
push (@ids,$responseIdHash{$part}->[$element]); |
|
push (@type,$responseTypeHash{$part}->[$element]); |
|
} |
|
$responseIdHash{$part}=\@ids; |
|
$responseTypeHash{$part}=\@type; |
|
} |
|
} |
$self->{RESPONSE_IDS} = \%responseIdHash; |
$self->{RESPONSE_IDS} = \%responseIdHash; |
$self->{RESPONSE_TYPES} = \%responseTypeHash; |
$self->{RESPONSE_TYPES} = \%responseTypeHash; |
} |
} |
Line 3833 sub getCompletionStatus {
|
Line 4368 sub getCompletionStatus {
|
|
|
my $status = $self->queryRestoreHash('solved', shift); |
my $status = $self->queryRestoreHash('solved', shift); |
|
|
# Left as seperate if statements in case we ever do more with this |
# 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_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_attempted') {return $self->INCORRECT; } |
if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; } |
if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; } |
Line 3985 sub status {
|
Line 4521 sub status {
|
|
|
if ($dateStatus == PAST_DUE_ANSWER_LATER || |
if ($dateStatus == PAST_DUE_ANSWER_LATER || |
$dateStatus == PAST_DUE_NO_ANSWER ) { |
$dateStatus == PAST_DUE_NO_ANSWER ) { |
return $dateStatus; |
return $suppressFeedback ? ANSWER_SUBMITTED : $dateStatus; |
} |
} |
|
|
if ($dateStatus == ANSWER_OPEN) { |
if ($dateStatus == ANSWER_OPEN) { |
Line 4171 sub getNext {
|
Line 4707 sub getNext {
|
my $to = $self->to(); |
my $to = $self->to(); |
foreach my $branch ( split(/,/, $to) ) { |
foreach my $branch ( split(/,/, $to) ) { |
my $choice = $self->{NAV_MAP}->getById($branch); |
my $choice = $self->{NAV_MAP}->getById($branch); |
|
if (!$choice->condition()) { next; } |
my $next = $choice->goesto(); |
my $next = $choice->goesto(); |
$next = $self->{NAV_MAP}->getById($next); |
$next = $self->{NAV_MAP}->getById($next); |
|
|
Line 4199 sub browsePriv {
|
Line 4736 sub browsePriv {
|
return $self->{BROWSE_PRIV}; |
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 |
=pod |