File Coverage

blib/lib/HTML/Chunks/Super.pm
Criterion Covered Total %
statement 12 81 14.8
branch 0 36 0.0
condition 0 24 0.0
subroutine 4 9 44.4
pod 1 5 20.0
total 17 155 10.9


line stmt bran cond sub pod time code
1             package HTML::Chunks::Super;
2              
3 1     1   2196 use Safe;
  1         46100  
  1         53  
4 1     1   938 use IO::Scalar;
  1         15062  
  1         46  
5 1     1   8 use strict;
  1         1  
  1         29  
6 1     1   4 use base qw(HTML::Chunks);
  1         2  
  1         997  
7              
8             our $VERSION = "1.01";
9              
10             sub new
11             {
12 0     0 1   my $class = shift;
13 0           my $self = $class->SUPER::new(@_);
14              
15 0           return $self;
16             }
17              
18             # override basic chunk output to support conditionals
19             sub outputBasicChunk
20             {
21 0     0 0   my $self = shift;
22 0           my $chunk = shift;
23 0 0         my $chunkRef = ref $chunk ? $chunk : \$chunk;
24              
25 0           my $tree = $self->buildTree($chunkRef);
26 0           $self->outputNode($tree, @_);
27             }
28              
29             # parse a chunk into a decision tree. it might be possible to gain some
30             # efficiencies by doing this parsing when chunks are loaded, but it would
31             # be tricky to avoid confusing our parent class.
32             sub buildTree
33             {
34 0     0 0   my $self = shift;
35 0           my ($chunk) = @_;
36              
37 0 0         my $chunkRef = ref $chunk ? $chunk : \$chunk;
38 0           my $tree = [];
39 0           my @stack;
40 0           my $pos = 0;
41              
42 0           while ($$chunkRef =~ /\G(.*?)/gs)
43             {
44 0           my $beginDepth = @stack;
45 0 0         my $node = $beginDepth ? $stack[-1]->{current} : $tree;
46              
47 0 0 0       if (defined $1 && length $1)
48             {
49 0           push @{$node}, $1;
  0            
50             }
51              
52 0           my $cmd = uc($2);
53              
54 0 0 0       if ($cmd eq 'ELSE' || $cmd eq 'ELSIF')
55             {
56 0 0         my $branch = @stack ? $stack[-1] : undef;
57              
58 0 0 0       if ($branch && $branch->{current} == $branch->{true})
59             {
60 0           $node = $branch->{current} = $branch->{false} = [];
61             }
62             }
63              
64 0 0 0       if ($cmd eq 'ENDIF' || $cmd eq 'ELSIF')
65             {
66 0           my $branch = pop @stack;
67 0 0         delete $branch->{current} if $branch;
68             }
69              
70 0 0 0       if ($cmd eq 'IF' || ($cmd eq 'ELSIF' && $beginDepth))
      0        
71             {
72 0           my $branch = {
73             test => $3,
74             true => []
75             };
76              
77 0           push @{$node}, $branch;
  0            
78 0           push @stack, $branch;
79 0           $branch->{current} = $branch->{true};
80             }
81              
82 0           $pos = pos $$chunkRef;
83             }
84              
85 0           my $tail = substr $$chunkRef, $pos;
86 0 0 0       push @{$tree}, $tail if (defined $tail && length $tail);
  0            
87              
88 0           return $tree;
89             }
90              
91             sub outputNode
92             {
93 0     0 0   my $self = shift;
94 0           my $node = shift;
95              
96 0 0         if (defined $node)
97             {
98 0 0         die "what is this? => ", $node, "\n" unless (ref $node eq 'ARRAY');
99              
100 0           foreach my $thing (@{$node})
  0            
101             {
102 0 0         if (ref $thing eq 'HASH')
103             {
104 0 0 0       if (exists $thing->{test} && $self->testsTrue($thing->{test}, @_))
105             {
106 0 0         $self->outputNode($thing->{true}, @_) if (exists $thing->{true});
107             }
108             else
109             {
110 0 0         $self->outputNode($thing->{false}, @_) if (exists $thing->{false});
111             }
112             }
113             else
114             {
115             # call the normal HTML::Chunk output routine when we're down to a
116             # basic unadulterated chunk
117 0           $self->SUPER::outputBasicChunk(\$thing, @_);
118             }
119             }
120             }
121             }
122              
123             sub testsTrue
124             {
125 0     0 0   my $self = shift;
126 0           my $test = shift;
127 0           our %values;
128 0           local %values;
129              
130             # Translate any data tokens into scalars containing the actual data values
131              
132 0           $test =~ s/\#\#([\w\.]+)\#\#/
133 0           my $name = $1;
134 0           my $f = new IO::Scalar \$values{$name};
135 0           my $oldfh = select $f;
136 0           $self->outputData($name, @_);
137 0           select $oldfh;
138 0           close $f;
139              
140 0           "\$values{'$name'}";
141             /gex;
142              
143             # select STDERR, otherwise a 'print' in the test will blow up apache
144 0           my $oldfh = select STDERR;
145              
146             # now safely evaluate the test
147 0           my $safe = new Safe;
148 0           $safe->share('%values');
149 0           my $status = $safe->reval($test);
150              
151             # put filehandle things back
152 0           select $oldfh;
153              
154 0 0         warn $@ if $@;
155              
156 0           return $status;
157             }
158              
159             1;
160              
161             __END__