--- loncom/lonmap.pm 2011/11/29 11:50:53 1.6 +++ loncom/lonmap.pm 2014/12/11 01:50:27 1.15 @@ -2,7 +2,7 @@ # # Read maps into a 'big hash'. # -# $Id: lonmap.pm,v 1.6 2011/11/29 11:50:53 foxr Exp $ +# $Id: lonmap.pm,v 1.15 2014/12/11 01:50:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -157,7 +157,7 @@ sub merge_hash { $key .= '.'; # If we are prefixing, prefix then . } - foreach my $childkey (keys (%$child)) { + foreach my $childkey (keys(%$child)) { $parent->{$key . $childkey} = $child->{$childkey}; } } @@ -213,9 +213,10 @@ sub get_mapalias_errors { $count++; } my ($mapid) = split(/\./,$id); - &mt('Resource "[_1]"
in Map "[_2]"', - $hash->{'title_'.$id}, - $hash->{'title_'.$hash->{'ids_'.$hash->{'map_id_'.$mapid}}}); + &mt('Resource [_1][_2]in Map [_3]', + '"'.$hash->{'title_'.$id}.'"', + '
', + '"'.$hash->{'title_'.$hash->{'ids_'.$hash->{'map_id_'.$mapid}}}.'"'); } (@{ $mapalias_cache{$mapalias} })); next if ($count < 2); $error_text .= '
'. @@ -278,7 +279,7 @@ sub process_versions { $cenv->{'domain'}, $cenv->{'num'}); - foreach my $ver (keys (%versions)) { + foreach my $ver (keys(%versions)) { if ($ver =~/^error\:/) { # lonc/lond transaction failed. throw Error::Simple('lonc/lond returned error: ' . $ver); } @@ -295,7 +296,6 @@ sub process_versions { # sub versionerror { my ($uri, $used, $unused) = @_; - my ($uri,$usedversion,$unusedversion)=@_; return '
'. &mt('Version discrepancy: resource [_1] included in both version [_2] and version [_3]. Using version [_2].', $uri,$used,$unused).'
'; @@ -410,7 +410,7 @@ sub hiddenurls { my $courseid = $hash->{'context.courseid'}; my $randomoutentry=''; - foreach my $rid (keys %randompick) { + foreach my $rid (keys(%randompick)) { my $rndpick=$randompick{$rid}; my $mpc=$hash->{'map_pc_'.$hash->{'src_'.$rid}}; # ------------------------------------------- put existing resources into array @@ -450,7 +450,7 @@ sub hiddenurls { } } # ------------------------------ take care of explicitly hidden urls or folders - foreach my $rid (keys %hiddenurl) { + foreach my $rid (keys(%hiddenurl)) { $hash->{'randomout_'.$rid}='1'; my ($mapid,$resid)=split(/\./,$rid); $randomoutentry.='&'. @@ -616,9 +616,18 @@ sub traceroute { my $symb=&Apache::lonnet::encode_symb($hash->{'map_id_'.$mapid},$resid, $hash->{'src_'.$rid}); my $hidden=&Apache::lonnet::EXT('resource.0.hiddenresource',$symb); + my $ignorehidden; if ($hdnflag || lc($hidden) eq 'yes') { - $hiddenurl{$rid}=1; + if (defined($hash->{'is_map_'.$rid})) { + if (($hash->{'context.nohideurl'}) && ($hash->{'context.nohideurl'} eq $hash->{'src_'.$rid})) { + $ignorehidden = 1; # Hidden parameter explicitly deleted + # if printing/grading bubblesheet exam + } + } + unless ($ignorehidden) { + $hiddenurl{$rid}=1; + } } if (!$hdnflag && lc($hidden) eq 'no') { delete($hiddenurl{$rid}); @@ -648,12 +657,16 @@ sub traceroute { if (defined($hash->{'is_map_'.$rid})) { if (defined($hash->{'map_start_'.$hash->{'src_'.$rid}})) { + my $maphidden; + unless ($ignorehidden) { + $maphidden = $hdnflag || $hiddenurl{$rid}; + } $sofar=$newsofar= &traceroute($sofar, $hash->{'map_start_'.$hash->{'src_'.$rid}}, $beenhere, $encflag || $encurl{$rid}, - $hdnflag || $hiddenurl{$rid}, $hash); + $maphidden, $hash); } } @@ -673,7 +686,7 @@ sub traceroute { $further=simplify('('.'_'.$rid.')&('. $hash->{'condid_'.$hash->{'undercond_'.$id}}.')'); } else { - my $errtext.=&mt('
Undefined condition ID: [_1]',$hash->{'undercond_'.$id}); + my $errtext.='
'.&mt('Undefined condition ID: [_1]',$hash->{'undercond_'.$id}); throw Error::Simple($errtext); } } @@ -783,7 +796,6 @@ sub parse_param { $hiddenurl{$referid}=1; } } - } @@ -801,6 +813,7 @@ sub parse_param { # $lpc - Map nesting level (?) # $ispage - True if this resource is encapsulated in a .page (assembled resourcde). # $uri - URI of the enclosing resource. +# $code - CODE for which resource is being parsed (CODEd assignments). # $hash - Reference to the hash we are building. # # Returns: @@ -823,7 +836,7 @@ sub parse_param { # sub parse_resource { - my ($token,$lpc,$ispage,$uri, $hash) = @_; + my ($token,$lpc,$ispage,$uri,$code,$hash) = @_; # I refuse to countenance code like this that has # such a dirty side effect (and forcing this sub to be called within a loop). @@ -970,7 +983,15 @@ sub parse_resource { if (($turi=~/\.sequence$/) || ($turi=~/\.page$/)) { $hash->{'is_map_'.$rid}='1'; # String in lonuserstate. - &read_map($turi,$rid, $hash); + if ($hiddenurl{$rid}) { + if (($hash->{'context.nohideurl'}) && + ($hash->{'context.nohideurl'} eq $hash->{'src_'.$rid})) { + delete($hiddenurl{$rid}); # Hidden parameter explicitly deleted + # if printing/grading bubblesheet exam + } + } + + &read_map($turi,$rid,$code,$hash); } return $token->[2]->{'id'}; } @@ -1178,7 +1199,8 @@ sub parse_mapalias_param { # $parent_rid - map number qualified id of the parent of the map being read. # For the top level course map this is 0.0. For the first nested # map 1.n where n is the id of the resource within the -# top level map and so on. +# top level map and so on. +# $code - CODE for which map is being read (CODEd assignments). # $hash - Reference to a hash that will become the big hash for the course # This hash is modified as per the map description. # Side-effects: @@ -1188,7 +1210,7 @@ sub parse_mapalias_param { # # sub read_map { - my ($uri, $parent_rid, $hash) = @_; + my ($uri, $parent_rid, $code, $hash) = @_; # Check for duplication: A map may only be included once. @@ -1235,7 +1257,7 @@ sub read_map { my $ispage = ($filename =~/\.page$/); unless ($ispage || ($filename =~ /\.sequence$/)) { &Apache::lonnet::logthis("invalid: $filename : $uri"); - throw Error::Simple(&mt("
Invalid map: [_1]", $filename)); + throw Error::Simple('
'.&mt('Invalid map: [_1]',''.$filename.'')); } $filename =~ /\.(\w+)$/; @@ -1246,8 +1268,8 @@ sub read_map { my $contents = &Apache::lonnet::getfile($filename); if($contents eq -1) { - throw Error::Simple(&mt('
Map not loaded: The file [_1] does not exist.', - $filename)); + throw Error::Simple('
'.&mt('Map not loaded: The file [_1] does not exist.', + ''.$filename.'')); } # Now that we succesfully retrieved the file we can make our parsing passes over it: # parsing is done in passes: @@ -1289,7 +1311,7 @@ sub read_map { # Resource if ($token->[1] eq 'resource') { - my $resource_id = &parse_resource($token,$lmap_no,$ispage,$uri, $hash); + my $resource_id = &parse_resource($token,$lmap_no,$ispage,$uri,$code,$hash); if (defined $resource_id) { push(@map_ids, $resource_id); } @@ -1313,7 +1335,7 @@ sub read_map { # if ($randomize) { - if (!&has_advanced_role($username, $userdomain) ) { + if (!&has_advanced_role($username, $userdomain) || $code) { my $seed; # In the advanced role, the map's random seed @@ -1397,6 +1419,8 @@ sub read_map { # $cdom - Domain in which the course is evaluated. # $uname - Name of the user for whom the course is being read # $udom - Name of the domain of the user for whom the course is being read. +# $code - CODE for which course is being read (CODEd assignments) +# $nohideurl - URL for an exam folder for which hidden state is to be ignored. # $target_hash- Reference to the target hash into which all of this is read. # Note tht some of the hash entries we need to build require knowledge of the # course URI.. these are expected to be filled in by the caller. @@ -1405,11 +1429,11 @@ sub read_map { # # sub loadmap { - my ($cnum, $cdom, $uname, $udom, $target_hash) = @_; + my ($cnum, $cdom, $uname, $udom, $code, $nohideurl, $target_hash) = @_; - # Clear the auxillary hashes and the cond array. + # Clear the auxiliary hashes and the cond array. %randompick = (); @@ -1423,7 +1447,7 @@ sub loadmap { $userdomain = ''; %mapalias_cache = (); %cenv = (); - + $map_number = 0; # @@ -1443,7 +1467,7 @@ sub loadmap { {'freshen_cache' => 1, 'user' => $uname}); - unless ($cenv{'url'}) { + unless ($cenv{'url'}) { &Apache::lonnet::logthis("lonmap::loadmap failed: $cnum/$cdom - did not get url"); return; } @@ -1475,11 +1499,12 @@ sub loadmap { $target_hash->{'context.username'} = $username; $target_hash->{'context.userdom'} = $userdomain; $target_hash->{'context.courseid'} = $course_id; + + # When grading or printing a bubblesheet exam ignore + # "hidden" parameter set in the map containing the exam folder. + $target_hash->{'context.nohideurl'} = $nohideurl; - - &read_map($course_uri, '0.0', $target_hash); - - # + &read_map($course_uri, '0.0', $code, $target_hash); if (defined($target_hash->{'map_start_'.$map_uri})) { @@ -1529,7 +1554,7 @@ sub loadmap { &merge_hash($target_hash, 'randompick', \%randompick); - &merge_hash($target_hash, 'randompickseed', \%randompick); + &merge_hash($target_hash, 'randompickseed', \%randompickseed); &merge_hash($target_hash, 'randomorder', \%randomorder); &merge_hash($target_hash, 'encurl', \%encurl); &merge_hash($target_hash, 'hiddenurl', \%hiddenurl); @@ -1559,28 +1584,39 @@ Apache::lonmap - Construct a hash that r =head1 SYNOPSIS -&Apache::lonmap::loadmap($filepath, \%target_hash); +&Apache::lonmap::loadmap($cnum, $cdom, $uname, $udom, $code, $nohideurl, \%target_hash); =head1 INTRODUCTION This module reads a course filename into a hash reference. It's up to the caller -to to things like decide the has should be tied to some external file and handle the locking -if this file should be shared amongst several Apache children. +to do things like decide that the hash should be tied to some external file and handle the +the locking if this file should be shared amongst several Apache children. =head1 SUBROUTINES =over -=item loadmap($filepath, $targethash) +=item loadmap($cnum, $cdom, $uname, $udom, $code, $nohideurl, $targethash) -Reads the map file into a target hash. +Reads the top-level map file into a target hash. This is done by first parsing the +map file into local hashes and then unrolling those hashes into the big hash. =over -=item $filepath - The path to the map file to read. +=item $cnum - number of course being read. + +=item $cdom - domain in which the course is evaluated. + +=item $uname - name of the user for whom the course is being read. + +=item $udom - name of the domain of the user for whom the course is being read. + +=item $code - CODE for which course is being read (CODEd assignments). + +=item $nohideurl - URL for an exam folder for which hidden state is to be ignored. -=item $targethash - A reference to hash into which the course is read. +=item $targethash - A reference to hash into which the course is read =back