version 1.142, 2011/10/20 17:14:19
|
version 1.150, 2016/01/26 14:30:40
|
Line 42 use Safe::Hole;
|
Line 42 use Safe::Hole;
|
use Opcode; |
use Opcode; |
use Apache::lonenc; |
use Apache::lonenc; |
use Fcntl qw(:flock); |
use Fcntl qw(:flock); |
use LONCAPA; |
use LONCAPA qw(:DEFAULT :match); |
use File::Basename; |
use File::Basename; |
|
|
|
|
Line 59 my $retfurl; # first URL
|
Line 59 my $retfurl; # first URL
|
my %randompick; # randomly picked resources |
my %randompick; # randomly picked resources |
my %randompickseed; # optional seed for randomly picking resources |
my %randompickseed; # optional seed for randomly picking resources |
my %randomorder; # maps to order contents randomly |
my %randomorder; # maps to order contents randomly |
|
my %randomizationcode; # code used to grade folder for bubblesheet exam |
my %encurl; # URLs in this folder are supposed to be encrypted |
my %encurl; # URLs in this folder are supposed to be encrypted |
my %hiddenurl; # this URL (or complete folder) is supposed to be hidden |
my %hiddenurl; # this URL (or complete folder) is supposed to be hidden |
|
|
Line 140 sub processversionfile {
|
Line 141 sub processversionfile {
|
# Parameters: |
# Parameters: |
# uri - URI of the map file. |
# uri - URI of the map file. |
# parent_rid - Resource id in the map of the parent resource (0.0 for the top level map) |
# parent_rid - Resource id in the map of the parent resource (0.0 for the top level map) |
# |
# courseid - Course id for the course for which the map is being loaded |
# |
# |
sub loadmap { |
sub loadmap { |
my ($uri,$parent_rid)=@_; |
my ($uri,$parent_rid,$courseid)=@_; |
|
|
# Is the map already included? |
# Is the map already included? |
|
|
Line 183 sub loadmap {
|
Line 184 sub loadmap {
|
# We can only nest sequences or pages. Anything else is an illegal nest. |
# We can only nest sequences or pages. Anything else is an illegal nest. |
|
|
unless (($fn=~/\.sequence$/) || $ispage) { |
unless (($fn=~/\.sequence$/) || $ispage) { |
$errtext.=&mt("<br />Invalid map: <tt>[_1]</tt>",$fn); |
$errtext.='<br />'.&mt('Invalid map: [_1]',"<tt>$fn</tt>"); |
return; |
return; |
} |
} |
|
|
Line 192 sub loadmap {
|
Line 193 sub loadmap {
|
my $instr=&Apache::lonnet::getfile($fn); |
my $instr=&Apache::lonnet::getfile($fn); |
|
|
if ($instr eq -1) { |
if ($instr eq -1) { |
$errtext.=&mt('<br />Map not loaded: The file <tt>[_1]</tt> does not exist.',$fn); |
$errtext.= '<br />' |
|
.&mt('Map not loaded: The file [_1] does not exist.', |
|
"<tt>$fn</tt>"); |
return; |
return; |
} |
} |
|
|
Line 236 sub loadmap {
|
Line 239 sub loadmap {
|
# This is handled in the next chunk of code. |
# This is handled in the next chunk of code. |
|
|
my @map_ids; |
my @map_ids; |
|
my $codechecked; |
while (my $token = $parser->get_token) { |
while (my $token = $parser->get_token) { |
next if ($token->[0] ne 'S'); |
next if ($token->[0] ne 'S'); |
|
|
# Resource |
# Resource |
|
|
if ($token->[1] eq 'resource') { |
if ($token->[1] eq 'resource') { |
my $resource_id = &parse_resource($token,$lpc,$ispage,$uri); |
my $resource_id = &parse_resource($token,$lpc,$ispage,$uri,$courseid); |
if (defined $resource_id) { |
if (defined $resource_id) { |
push(@map_ids, $resource_id); |
push(@map_ids, $resource_id); |
|
unless ($codechecked) { |
|
my $startsymb = |
|
&Apache::lonnet::encode_symb($hash{'map_id_'.$lpc},$resource_id, |
|
$hash{'src_'."$lpc.$resource_id"}); |
|
my $code = |
|
&Apache::lonnet::EXT('resource.0.examcode',$startsymb,undef,undef, |
|
undef,undef,$courseid); |
|
if ($code) { |
|
$randomizationcode{$parent_rid} = $code; |
|
} |
|
$codechecked = 1; |
|
} |
} |
} |
|
|
# Link |
# Link |
Line 260 sub loadmap {
|
Line 276 sub loadmap {
|
&parse_condition($token,$lpc); |
&parse_condition($token,$lpc); |
} |
} |
} |
} |
|
undef($codechecked); |
|
|
|
|
# Handle randomization and random selection |
# Handle randomization and random selection |
|
|
if ($randomize) { |
if ($randomize) { |
if (!$env{'request.role.adv'}) { |
my $advanced; |
|
if ($env{'request.course.id'}) { |
|
$advanced = (&Apache::lonnet::allowed('adv') eq 'F'); |
|
} else { |
|
$env{'request.course.id'} = $courseid; |
|
$advanced = (&Apache::lonnet::allowed('adv') eq 'F'); |
|
$env{'request.course.id'} = ''; |
|
} |
|
unless ($advanced) { |
|
# Order of resources is not randomized if user has and advanced role in the course. |
my $seed; |
my $seed; |
|
|
# In the advanced role, the map's random seed |
# If the map's random seed parameter has been specified |
# parameter is used as the basis for computing the |
# it is used as the basis for computing the seed ... |
# seed ... if it has been specified: |
|
|
|
if (defined($randompickseed{$parent_rid})) { |
if (defined($randompickseed{$parent_rid})) { |
$seed = $randompickseed{$parent_rid}; |
$seed = $randompickseed{$parent_rid}; |
Line 289 sub loadmap {
|
Line 314 sub loadmap {
|
# TODO: Here for sure we need to pass along the username/domain |
# TODO: Here for sure we need to pass along the username/domain |
# so that we can impersonate users in lonprintout e.g. |
# so that we can impersonate users in lonprintout e.g. |
|
|
|
my $setcode; |
|
if (defined($randomizationcode{$parent_rid})) { |
|
if ($env{'form.CODE'} eq '') { |
|
$env{'form.CODE'} = $randomizationcode{$parent_rid}; |
|
$setcode = 1; |
|
} |
|
} |
|
|
my $rndseed=&Apache::lonnet::rndseed($seed); |
my $rndseed=&Apache::lonnet::rndseed($seed); |
&Apache::lonnet::setup_random_from_rndseed($rndseed); |
&Apache::lonnet::setup_random_from_rndseed($rndseed); |
|
|
|
if ($setcode) { |
|
undef($env{'form.CODE'}); |
|
undef($setcode); |
|
} |
|
|
# Take the set of map ids we have decoded and permute them to a |
# Take the set of map ids we have decoded and permute them to a |
# random order based on the seed set above. All of this is |
# random order based on the seed set above. All of this is |
# processing the randomorder parameter if it is set, not |
# processing the randomorder parameter if it is set, not |
# randompick. |
# randompick. |
|
|
@map_ids=&Math::Random::random_permutation(@map_ids); |
@map_ids=&Math::Random::random_permutation(@map_ids); |
} |
} |
|
|
|
|
Line 352 sub loadmap {
|
Line 390 sub loadmap {
|
# $lpc - Map nesting level (?) |
# $lpc - Map nesting level (?) |
# $ispage - True if this resource is encapsulated in a .page (assembled resourcde). |
# $ispage - True if this resource is encapsulated in a .page (assembled resourcde). |
# $uri - URI of the enclosing resource. |
# $uri - URI of the enclosing resource. |
|
# $courseid - Course id of the course containing the resource being parsed. |
# Returns: |
# Returns: |
# Value of the id attribute of the tag. |
# Value of the id attribute of the tag. |
# |
# |
Line 372 sub loadmap {
|
Line 411 sub loadmap {
|
|
|
|
|
sub parse_resource { |
sub parse_resource { |
my ($token,$lpc,$ispage,$uri) = @_; |
my ($token,$lpc,$ispage,$uri,$courseid) = @_; |
|
|
# I refuse to countenance code like this that has |
# I refuse to countenance code like this that has |
# such a dirty side effect (and forcing this sub to be called within a loop). |
# such a dirty side effect (and forcing this sub to be called within a loop). |
Line 436 sub parse_resource {
|
Line 475 sub parse_resource {
|
} elsif ($turi!~/\.(sequence|page)$/) { |
} elsif ($turi!~/\.(sequence|page)$/) { |
$turi='/adm/coursedocs/showdoc'.$turi; |
$turi='/adm/coursedocs/showdoc'.$turi; |
} |
} |
|
} elsif ($turi=~ m{^/adm/$match_domain/$match_courseid/\d+/exttools?$}) { |
|
$turi='/adm/wrapper'.$turi; |
} elsif ($turi=~/\S/) { # normal non-empty internal resource |
} elsif ($turi=~/\S/) { # normal non-empty internal resource |
my $mapdir=$uri; |
my $mapdir=$uri; |
$mapdir=~s/[^\/]+$//; |
$mapdir=~s/[^\/]+$//; |
Line 511 sub parse_resource {
|
Line 552 sub parse_resource {
|
if (($turi=~/\.sequence$/) || |
if (($turi=~/\.sequence$/) || |
($turi=~/\.page$/)) { |
($turi=~/\.page$/)) { |
$hash{'is_map_'.$rid}=1; |
$hash{'is_map_'.$rid}=1; |
&loadmap($turi,$rid); |
&loadmap($turi,$rid,$courseid); |
} |
} |
return $token->[2]->{'id'}; |
return $token->[2]->{'id'}; |
} |
} |
Line 909 sub traceroute {
|
Line 950 sub traceroute {
|
$further=simplify('('.'_'.$rid.')&('. |
$further=simplify('('.'_'.$rid.')&('. |
$hash{'condid_'.$hash{'undercond_'.$id}}.')'); |
$hash{'condid_'.$hash{'undercond_'.$id}}.')'); |
} else { |
} else { |
$errtext.=&mt('<br />Undefined condition ID: [_1]',$hash{'undercond_'.$id}); |
$errtext.= '<br />'. |
|
&mt('Undefined condition ID: [_1]', |
|
$hash{'undercond_'.$id}); |
} |
} |
} |
} |
# Recurse to resoruces that have to's to us. |
# Recurse to resoruces that have to's to us. |
Line 1031 sub accinit {
|
Line 1074 sub accinit {
|
|
|
sub hiddenurls { |
sub hiddenurls { |
my $randomoutentry=''; |
my $randomoutentry=''; |
foreach my $rid (keys %randompick) { |
foreach my $rid (keys(%randompick)) { |
my $rndpick=$randompick{$rid}; |
my $rndpick=$randompick{$rid}; |
my $mpc=$hash{'map_pc_'.$hash{'src_'.$rid}}; |
my $mpc=$hash{'map_pc_'.$hash{'src_'.$rid}}; |
# ------------------------------------------- put existing resources into array |
# ------------------------------------------- put existing resources into array |
Line 1052 sub hiddenurls {
|
Line 1095 sub hiddenurls {
|
# -------------------------------- randomly eliminate the ones that should stay |
# -------------------------------- randomly eliminate the ones that should stay |
my (undef,$id)=split(/\./,$rid); |
my (undef,$id)=split(/\./,$rid); |
if ($randompickseed{$rid}) { $id=$randompickseed{$rid}; } |
if ($randompickseed{$rid}) { $id=$randompickseed{$rid}; } |
|
my $setcode; |
|
if (defined($randomizationcode{$rid})) { |
|
if ($env{'form.CODE'} eq '') { |
|
$env{'form.CODE'} = $randomizationcode{$rid}; |
|
$setcode = 1; |
|
} |
|
} |
my $rndseed=&Apache::lonnet::rndseed($id); # use id instead of symb |
my $rndseed=&Apache::lonnet::rndseed($id); # use id instead of symb |
|
if ($setcode) { |
|
undef($env{'form.CODE'}); |
|
undef($setcode); |
|
} |
&Apache::lonnet::setup_random_from_rndseed($rndseed); |
&Apache::lonnet::setup_random_from_rndseed($rndseed); |
my @whichids=&Math::Random::random_permuted_index($#currentrids+1); |
my @whichids=&Math::Random::random_permuted_index($#currentrids+1); |
for (my $i=1;$i<=$rndpick;$i++) { $currentrids[$whichids[$i]]=''; } |
for (my $i=1;$i<=$rndpick;$i++) { $currentrids[$whichids[$i]]=''; } |
Line 1071 sub hiddenurls {
|
Line 1125 sub hiddenurls {
|
} |
} |
} |
} |
# ------------------------------ take care of explicitly hidden urls or folders |
# ------------------------------ take care of explicitly hidden urls or folders |
foreach my $rid (keys %hiddenurl) { |
foreach my $rid (keys(%hiddenurl)) { |
$hash{'randomout_'.$rid}=1; |
$hash{'randomout_'.$rid}=1; |
my ($mapid,$resid)=split(/\./,$rid); |
my ($mapid,$resid)=split(/\./,$rid); |
$randomoutentry.='&'. |
$randomoutentry.='&'. |
Line 1108 sub readmap {
|
Line 1162 sub readmap {
|
# |
# |
# Most likely a permissions problem on the lockfile or its directory. |
# Most likely a permissions problem on the lockfile or its directory. |
# |
# |
$errtext.='<br />'.&mt('Map not loaded - Lock file could not be opened when reading map:').' <tt>'.$fn.'</tt>.'; |
|
$retfurl = ''; |
$retfurl = ''; |
return ($retfurl,$errtext); |
return ($retfurl,'<br />'.&mt('Map not loaded - Lock file could not be opened when reading map:').' <tt>'.$fn.'</tt>.'); |
} |
} |
my $lock=0; |
my $lock=0; |
my $gotstate=0; |
my $gotstate=0; |
Line 1126 sub readmap {
|
Line 1179 sub readmap {
|
undef %hiddenurl; |
undef %hiddenurl; |
undef %encurl; |
undef %encurl; |
$retfrid=''; |
$retfrid=''; |
|
$errtext=''; |
my ($untiedhash,$untiedparmhash,$tiedhash,$tiedparmhash); # More state flags. |
my ($untiedhash,$untiedparmhash,$tiedhash,$tiedparmhash); # More state flags. |
|
|
# if we got the lock, regenerate course regnerate empty files and tie them. |
# if we got the lock, regenerate course regnerate empty files and tie them. |
Line 1220 sub readmap {
|
Line 1274 sub readmap {
|
# |
# |
&Apache::lonnet::appenv({"request.course.id" => $short, |
&Apache::lonnet::appenv({"request.course.id" => $short, |
"request.course.fn" => $fn, |
"request.course.fn" => $fn, |
"request.course.uri" => $uri}); |
"request.course.uri" => $uri, |
|
"request.course.tied" => time}); |
|
|
$untiedhash = untie(%hash); |
$untiedhash = untie(%hash); |
$untiedparmhash = untie(%parmhash); |
$untiedparmhash = untie(%parmhash); |
$gotstate = 1; |
$gotstate = 1; |
Line 1265 sub readmap {
|
Line 1321 sub readmap {
|
undef %randompick; |
undef %randompick; |
undef %hiddenurl; |
undef %hiddenurl; |
undef %encurl; |
undef %encurl; |
|
$errtext=''; |
$retfrid=''; |
$retfrid=''; |
# |
# |
# Once more through the routine of tying and loading and so on. |
# Once more through the routine of tying and loading and so on. |
Line 1367 sub build_tmp_hashes {
|
Line 1424 sub build_tmp_hashes {
|
# sub-maps. |
# sub-maps. |
|
|
|
|
&loadmap($uri,'0.0'); |
&loadmap($uri,'0.0',$short); |
|
|
# The code below only executes if there is a starting point for the map> |
# The code below only executes if there is a starting point for the map> |
# Q/BUG??? If there is no start resource for the map should that be an error? |
# Q/BUG??? If there is no start resource for the map should that be an error? |
Line 1376 sub build_tmp_hashes {
|
Line 1433 sub build_tmp_hashes {
|
if (defined($hash{'map_start_'.$uri})) { |
if (defined($hash{'map_start_'.$uri})) { |
&Apache::lonnet::appenv({"request.course.id" => $short, |
&Apache::lonnet::appenv({"request.course.id" => $short, |
"request.course.fn" => $fn, |
"request.course.fn" => $fn, |
"request.course.uri" => $uri}); |
"request.course.uri" => $uri, |
|
"request.course.tied" => time}); |
$env{'request.course.id'}=$short; |
$env{'request.course.id'}=$short; |
&traceroute('0',$hash{'map_start_'.$uri},'&'); |
&traceroute('0',$hash{'map_start_'.$uri},'&'); |
&accinit($uri,$short,$fn); |
&accinit($uri,$short,$fn); |
Line 1427 sub unlink_tmpfiles {
|
Line 1485 sub unlink_tmpfiles {
|
my ($fn) = @_; |
my ($fn) = @_; |
my $file_dir = dirname($fn); |
my $file_dir = dirname($fn); |
|
|
if ($fn eq LONCAPA::tempdir()) { |
if ("$file_dir/" eq LONCAPA::tempdir()) { |
my @files = qw (.db _symb.db .state _parms.db); |
my @files = qw (.db _symb.db .state _parms.db); |
foreach my $file (@files) { |
foreach my $file (@files) { |
if (-e $fn.$file) { |
if (-e $fn.$file) { |
Line 1504 sub evalstate {
|
Line 1562 sub evalstate {
|
$count++; |
$count++; |
} |
} |
my ($mapid) = split(/\./,$id); |
my ($mapid) = split(/\./,$id); |
&mt('Resource "[_1]" <br /> in Map "[_2]"', |
&mt('Resource [_1][_2]in Map [_3]', |
$hash{'title_'.$id}, |
$hash{'title_'.$id},'<br />', |
$hash{'title_'.$hash{'ids_'.$hash{'map_id_'.$mapid}}}); |
$hash{'title_'.$hash{'ids_'.$hash{'map_id_'.$mapid}}}); |
} (@{ $mapalias_cache{$mapalias} })); |
} (@{ $mapalias_cache{$mapalias} })); |
next if ($count < 2); |
next if ($count < 2); |