version 1.1, 2011/09/07 10:58:36
|
version 1.2, 2011/09/13 10:27:52
|
Line 38 use Error qw(:try);
|
Line 38 use Error qw(:try);
|
use HTML::TokeParser; |
use HTML::TokeParser; |
|
|
|
|
use Apache::LONCAPA; |
use LONCAPA; |
use Apache::lonnet; |
use Apache::lonnet; |
|
|
#------------- File scoped variables: |
#------------- File scoped variables: |
Line 56 my %randompickseed;
|
Line 56 my %randompickseed;
|
my %randomorder; |
my %randomorder; |
my %encurl; |
my %encurl; |
my %hiddenurl; |
my %hiddenurl; |
|
my %parmhash; |
my @cond; # Array of conditions. |
my @cond; # Array of conditions. |
|
my $retfrid; |
# |
# |
# Other stuff we make global (sigh) so that it does not need |
# Other stuff we make global (sigh) so that it does not need |
# to be passed around all the time: |
# to be passed around all the time: |
Line 128 sub simplify {
|
Line 129 sub simplify {
|
sub merge_conditions { |
sub merge_conditions { |
my $hash = shift; |
my $hash = shift; |
|
|
for (my $i = 0; i < scalar(@cond); i++) { |
for (my $i = 0; $i < scalar(@cond); $i++) { |
$hash->{'condition' . '.' . $i} = $cond[$i]; |
$hash->{'condition' . '.' . $i} = $cond[$i]; |
} |
} |
} |
} |
Line 181 sub count_mapalias {
|
Line 182 sub count_mapalias {
|
# result string.' |
# result string.' |
# |
# |
# Parameters: |
# Parameters: |
# none |
# hash - Reference to the hash we are trying t build up. |
# Implicit inputs |
# Implicit inputs |
# %mapalias - a hash that is indexed by map aliases and contains for each key |
# %mapalias - a hash that is indexed by map aliases and contains for each key |
# an array of the resource id's the alias 'points to'. |
# an array of the resource id's the alias 'points to'. |
Line 191 sub count_mapalias {
|
Line 192 sub count_mapalias {
|
# |
# |
# |
# |
sub get_mapalias_errors { |
sub get_mapalias_errors { |
|
my $hash = shift; |
my $error_text; |
my $error_text; |
foreach my $mapalias (sort(keys(%mapalias_cache))) { |
foreach my $mapalias (sort(keys(%mapalias_cache))) { |
next if (scalar(@{ $mapalias_cache{$mapalias} } ) == 1); |
next if (scalar(@{ $mapalias_cache{$mapalias} } ) == 1); |
Line 199 sub get_mapalias_errors {
|
Line 201 sub get_mapalias_errors {
|
join('</li><li>', |
join('</li><li>', |
map { |
map { |
my $id = $_; |
my $id = $_; |
if (exists($hash{'src_'.$id})) { |
if (exists($hash->{'src_'.$id})) { |
$count++; |
$count++; |
} |
} |
my ($mapid) = split(/\./,$id); |
my ($mapid) = split(/\./,$id); |
&mt('Resource "[_1]" <br /> in Map "[_2]"', |
&mt('Resource "[_1]" <br /> in Map "[_2]"', |
$hash{'title_'.$id}, |
$hash->{'title_'.$id}, |
$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); |
$error_text .= '<div class="LC_error">'. |
$error_text .= '<div class="LC_error">'. |
Line 229 sub clear_mapalias_count {
|
Line 231 sub clear_mapalias_count {
|
# |
# |
|
|
# |
# |
|
# Put a version into a src element of a hash or url: |
|
# |
|
# Parameters: |
|
# uri - URI into which the version must be added. |
|
# hash - Reference to the hash being built up. |
|
# short- Short coursename. |
|
# |
|
|
|
sub putinversion { |
|
my ($uri, $hash, $short) = @_; |
|
my $key=$short.'_'.&Apache::lonnet::clutter($uri); |
|
if ($hash->{'version_'.$uri}) { |
|
my $version=$hash->{'version_'.$uri}; |
|
if ($version eq 'mostrecent') { return $uri; } |
|
if ($version eq &Apache::lonnet::getversion( |
|
&Apache::lonnet::filelocation('',$uri))) |
|
{ return $uri; } |
|
$uri=~s/\.(\w+)$/\.$version\.$1/; |
|
} |
|
&Apache::lonnet::do_cache_new('courseresversion',$key,&Apache::lonnet::declutter($uri),600); |
|
return $uri; |
|
} |
|
|
|
|
|
# |
# Create hash entries for each version of the course. |
# Create hash entries for each version of the course. |
# Parameters: |
# Parameters: |
# $cenv - Reference to a course environment from lonnet::coursedescription. |
# $cenv - Reference to a course environment from lonnet::coursedescription. |
Line 291 sub vesiontrack {
|
Line 318 sub vesiontrack {
|
unless ($hash->{'version_'.$uri}) { |
unless ($hash->{'version_'.$uri}) { |
$hash->{'version_'.$uri}=$version; |
$hash->{'version_'.$uri}=$version; |
} elsif ($version!=$hash->{'version_'.$uri}) { |
} elsif ($version!=$hash->{'version_'.$uri}) { |
throw Error::Simple(&versionerror($uri,$hash{'version_'.$uri},$version)); |
throw Error::Simple(&versionerror($uri, $hash->{'version_'.$uri}, $version)); |
} |
} |
} |
} |
return $uri; |
return $uri; |
Line 410 sub hiddenurls {
|
Line 437 sub hiddenurls {
|
# |
# |
|
|
sub accinit { |
sub accinit { |
my ($uri,$short,$fn)=@_; |
my ($uri, $short, $fn, $hash)=@_; |
my %acchash=(); |
my %acchash=(); |
my %captured=(); |
my %captured=(); |
my $condcounter=0; |
my $condcounter=0; |
Line 542 sub accinit {
|
Line 569 sub accinit {
|
# new value indicating how far the map has been traversed (the sofar). |
# new value indicating how far the map has been traversed (the sofar). |
# |
# |
sub traceroute { |
sub traceroute { |
my ($sofar,$rid,$beenhere,$encflag,$hdnflag)=@_; |
my ($sofar, $rid, $beenhere, $encflag, $hdnflag, $hash)=@_; |
my $newsofar=$sofar=simplify($sofar); |
my $newsofar=$sofar=simplify($sofar); |
|
|
unless ($beenhere=~/\&\Q$rid\E\&/) { |
unless ($beenhere=~/\&\Q$rid\E\&/) { |
Line 608 sub traceroute {
|
Line 635 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}); |
my $errtext.=&mt('<br />Undefined condition ID: [_1]',$hash->{'undercond_'.$id}); |
throw Error::Simple($errtext); |
throw Error::Simple($errtext); |
} |
} |
} |
} |
Line 1128 sub read_map {
|
Line 1155 sub read_map {
|
# Check for duplication: A map may only be included once. |
# Check for duplication: A map may only be included once. |
|
|
if($hash->{'map_pc_' . $uri}) { |
if($hash->{'map_pc_' . $uri}) { |
throw Error::Simple('Duplicate map: ' $uri); |
throw Error::Simple('Duplicate map: ', $uri); |
} |
} |
# count the map number and save it locally so that we don't lose it |
# count the map number and save it locally so that we don't lose it |
# when we recurse. |
# when we recurse. |
Line 1151 sub read_map {
|
Line 1178 sub read_map {
|
my $parent_no = $1; # Parent's map number. |
my $parent_no = $1; # Parent's map number. |
if (defined($hash->{'map_hierarchy_' . $parent_no})) { |
if (defined($hash->{'map_hierarchy_' . $parent_no})) { |
$hash->{'map_hierarchy_' . $lmap_no} = |
$hash->{'map_hierarchy_' . $lmap_no} = |
$hash->{'map_hierarchy_' . $parent_no} . ',' $parent_no; |
$hash->{'map_hierarchy_' . $parent_no} . ',' . $parent_no; |
} else { |
} else { |
# Only 1 level deep ..nothing to append to: |
# Only 1 level deep ..nothing to append to: |
|
|
Line 1165 sub read_map {
|
Line 1192 sub read_map {
|
|
|
my $filename = &Apache::lonnet::filelocation('', &append_version($uri, $hash)); |
my $filename = &Apache::lonnet::filelocation('', &append_version($uri, $hash)); |
my $ispage = ($filename =~/\.page$/); |
my $ispage = ($filename =~/\.page$/); |
unless ($ispage || ($filname =~ /\.sequence$/)) { |
unless ($ispage || ($filename =~ /\.sequence$/)) { |
throw Error::Simple(&mt("<br />Invalid map: <tt>[_1]</tt>", $filename)); |
throw Error::Simple(&mt("<br />Invalid map: <tt>[_1]</tt>", $filename)); |
} |
} |
|
|
$filename =~ /\.(\w+)$/; |
$filename =~ /\.(\w+)$/; |
|
|
$hash->{'map_type_'.$lpc}=$1; |
$hash->{'map_type_'.$lmap_no}=$1; |
|
|
# Repcopy the file and get its contents...report errors if we can't |
# Repcopy the file and get its contents...report errors if we can't |
|
|
Line 1192 sub read_map {
|
Line 1219 sub read_map {
|
# tags.. this is because there is no body to a <param> tag. |
# tags.. this is because there is no body to a <param> tag. |
# |
# |
|
|
my $parser = HTML::TokeParser->new($\contents); |
my $parser = HTML::TokeParser->new(\$contents); |
$parser->attr_encoded(1); # Don't interpret entities in attributes (leave &xyz; alone). |
$parser->attr_encoded(1); # Don't interpret entities in attributes (leave &xyz; alone). |
|
|
while (my $token = $parser->get_token()) { |
while (my $token = $parser->get_token()) { |
Line 1207 sub read_map {
|
Line 1234 sub read_map {
|
# resources, they are also not processed if random order is turned on. |
# resources, they are also not processed if random order is turned on. |
# |
# |
|
|
$parser = HTML::TokeParser->new($\contents); # no way to reset the existing parser |
$parser = HTML::TokeParser->new(\$contents); # no way to reset the existing parser |
$parser->attr_encoded(1); |
$parser->attr_encoded(1); |
|
|
my $linkpc=0; |
my $linkpc=0; |
Line 1220 sub read_map {
|
Line 1247 sub read_map {
|
# Resource |
# Resource |
|
|
if ($token->[1] eq 'resource') { |
if ($token->[1] eq 'resource') { |
my $resource_id = &parse_resource($token,$lpc,$ispage,$uri, $hash); |
my $resource_id = &parse_resource($token,$lmap_no,$ispage,$uri, $hash); |
if (defined $resource_id) { |
if (defined $resource_id) { |
push(@map_ids, $resource_id); |
push(@map_ids, $resource_id); |
} |
} |
Line 1228 sub read_map {
|
Line 1255 sub read_map {
|
# Link |
# Link |
|
|
} elsif ($token->[1] eq 'link' && !$randomize) { |
} elsif ($token->[1] eq 'link' && !$randomize) { |
&make_link(++$linkpc,$lpc,$token->[2]->{'to'}, |
&make_link(++$linkpc,$lmap_no,$token->[2]->{'to'}, |
$token->[2]->{'from'}, |
$token->[2]->{'from'}, |
$token->[2]->{'condition'}, $hash); # note ..condition may be undefined. |
$token->[2]->{'condition'}, $hash); # note ..condition may be undefined. |
|
|
# condition |
# condition |
|
|
} elsif ($token->[1] eq 'condition' && !$randomize) { |
} elsif ($token->[1] eq 'condition' && !$randomize) { |
&parse_condition($token,$lpc, $hash); |
&parse_condition($token,$lmap_no, $hash); |
} |
} |
} |
} |
|
|
Line 1279 sub read_map {
|
Line 1306 sub read_map {
|
|
|
|
|
my $from = shift(@map_ids); |
my $from = shift(@map_ids); |
my $from_rid = $lpc.'.'.$from; |
my $from_rid = $lmap_no.'.'.$from; |
$hash->{'map_start_'.$uri} = $from_rid; |
$hash->{'map_start_'.$uri} = $from_rid; |
$hash->{'type_'.$from_rid}='start'; |
$hash->{'type_'.$from_rid}='start'; |
|
|
Line 1288 sub read_map {
|
Line 1315 sub read_map {
|
# if randomorder was set. This means that for an instructor to choose |
# if randomorder was set. This means that for an instructor to choose |
|
|
while (my $to = shift(@map_ids)) { |
while (my $to = shift(@map_ids)) { |
&make_link(++$linkpc,$lpc,$to,$from); |
&make_link(++$linkpc,$lmap_no,$to,$from); |
my $to_rid = $lpc.'.'.$to; |
my $to_rid = $lmap_no.'.'.$to; |
$hash->{'type_'.$to_rid}='normal'; |
$hash->{'type_'.$to_rid}='normal'; |
$from = $to; |
$from = $to; |
$from_rid = $to_rid; |
$from_rid = $to_rid; |
Line 1308 sub read_map {
|
Line 1335 sub read_map {
|
while (my $token = $parser->get_token) { |
while (my $token = $parser->get_token) { |
next if ($token->[0] ne 'S'); |
next if ($token->[0] ne 'S'); |
if ($token->[1] eq 'param') { |
if ($token->[1] eq 'param') { |
&parse_mapalias_param($token,$lpc, $hash); |
&parse_mapalias_param($token,$lmap_no, $hash); |
} |
} |
} |
} |
|
|
Line 1342 sub loadmap {
|
Line 1369 sub loadmap {
|
%randompickseed = (); |
%randompickseed = (); |
%encurl = (); |
%encurl = (); |
%hiddenurl = (); |
%hiddenurl = (); |
|
%parmhash = (); |
@cond = (); |
@cond = (); |
|
$retfrid = ''; |
|
|
|
|
# |
# |
|
|
$username = $uname; |
$username = $uname; |
Line 1357 sub loadmap {
|
Line 1387 sub loadmap {
|
# Get the information we need about the course. |
# Get the information we need about the course. |
# Return without filling in anything if we can't get any info: |
# Return without filling in anything if we can't get any info: |
|
|
my %cenv = &Apache::lonnet::coursedesription($short_name, |
my %cenv = &Apache::lonnet::coursedescription($short_name, |
{'freshen_cache' => 1, |
{'freshen_cache' => 1, |
'user' => $uname}); |
'user' => $uname}); |
unless ($cenv{'url'}) { |
unless ($cenv{'url'}) { |
Line 1374 sub loadmap {
|
Line 1404 sub loadmap {
|
|
|
# Figure out the map filename's URI, and set up some starting points for the map. |
# Figure out the map filename's URI, and set up some starting points for the map. |
|
|
$course_uri = $cenv->{'url'}; |
my $course_uri = $cenv{'url'}; |
$map_uri = &Apache::lonnet::clutter($course_uri); |
my $map_uri = &Apache::lonnet::clutter($course_uri); |
|
|
$target_hash->{'src_0.0'} = &versiontrack($map_uri, $target_hash); |
$target_hash->{'src_0.0'} = &versiontrack($map_uri, $target_hash); |
$target_hash->{'title_0.0'} = &Apache::lonnet::metadata($course_uri, 'title'); |
$target_hash->{'title_0.0'} = &Apache::lonnet::metadata($course_uri, 'title'); |
$target_hash->{'ids_'.$file_map_uri} = '0.0'; |
$target_hash->{'ids_'.$map_uri} = '0.0'; |
$target_hash->{'is_map_0.0'} = 1; |
$target_hash->{'is_map_0.0'} = 1; |
&read_map($course_uri, '0.0', &hash); |
&read_map($course_uri, '0.0', &hash); |
|
|
# |
# |
|
|
if (defined($hash->{'map_start_'.$uri})) { |
if (defined($target_hash->{'map_start_'.$map_uri})) { |
|
|
&traceroute('0',$hash->{'map_start_'.$course_uri},'&', $hash); |
&traceroute('0',$target_hash->{'map_start_'.$course_uri},'&', $target_hash); |
&accinit($course_uri, $short_name, $fn, $hash); |
&accinit($course_uri, $short_name, $filepath, $target_hash); |
&hiddenurls($hash); |
&hiddenurls($target_hash); |
|
} |
|
my $errors = &get_mapalias_errors($target_hash); |
|
if ($errors ne "") { |
|
throw Error::Simple("Map alias errors: ", $errors); |
|
} |
|
|
|
# Put the versions in to src: |
|
|
|
foreach my $key (keys(%$target_hash)) { |
|
if ($key =~ /^src_/) { |
|
$target_hash->{$key} = |
|
&putinversion($target_hash->{$key}, $target_hash, $short_name); |
|
} elsif ($key =~ /^(map_(?:start|finish|pc)_)(.*)/) { |
|
my ($type, $url) = ($1,$2); |
|
my $value = $target_hash->{$key}; |
|
$target_hash->{$type.&putinversion($url, $target_hash, $short_name)}=$value; |
|
} |
} |
} |
|
|
# Merge in the child hashes in case the caller wants that information as well. |
# Merge in the child hashes in case the caller wants that information as well. |
|
|
|
|
&merge_hash($hash, 'randompick', \%randompick); |
&merge_hash($target_hash, 'randompick', \%randompick); |
&merge_hash($hash, 'randompickseed', \%randompick); |
&merge_hash($target_hash, 'randompickseed', \%randompick); |
&merge_hash($hash, 'randomorder', \%randomorder); |
&merge_hash($target_hash, 'randomorder', \%randomorder); |
&merge_hash($hash, 'encurl', \%encurl); |
&merge_hash($target_hash, 'encurl', \%encurl); |
&merge_hash($hash, 'hiddenurl', \%hiddenurl); |
&merge_hash($target_hash, 'hiddenurl', \%hiddenurl); |
&merge_conditions($hash); |
&merge_hash($target_hash, 'param', \%parmhash); |
|
&merge_conditions($target_hash); |
} |
} |
otherwise { |
otherwise { |
my $e = shift; |
my $e = shift; |