Added more tests for conditionals. Need to fix linking in POD. - Intermediate commit!
[p5sagit/Excel-Template.git] / lib / Excel / Template / Container / Conditional.pm
1 package Excel::Template::Container::Conditional;
2
3 #GGG Convert <conditional> to be a special case of <switch>?
4
5 use strict;
6
7 BEGIN {
8     use vars qw(@ISA);
9     @ISA = qw(Excel::Template::Container);
10
11     use Excel::Template::Container;
12 }
13
14 my %isOp = (
15     '='  => '==',
16     (map { $_ => $_ } ( '>', '<', '==', '!=', '>=', '<=' )),
17     (map { $_ => $_ } ( 'gt', 'lt', 'eq', 'ne', 'ge', 'le' )),
18 );
19
20 sub _conditional_passes
21 {
22     my $self = shift;
23     my ($context) = @_;
24
25     my $name = $context->get($self, 'NAME');
26     return 0 unless $name =~ /\S/;
27
28     my $val = $context->param($name);
29     $val = @{$val} while ref $val eq 'ARRAY';
30     $val = ${$val} while ref $val eq 'SCALAR';
31
32     my $value = $context->get($self, 'VALUE');
33     if (defined $value)
34     {
35         my $op = $context->get($self, 'OP');
36         $op = defined $op && exists $isOp{$op}
37             ? $isOp{$op}
38             : '==';
39
40         my $res;
41         for ($op)
42         {
43             /^>$/  && do { $res = ($val > $value);  last };
44             /^<$/  && do { $res = ($val < $value);  last };
45             /^==$/ && do { $res = ($val == $value); last };
46             /^!=$/ && do { $res = ($val != $value); last };
47             /^>=$/ && do { $res = ($val >= $value); last };
48             /^<=$/ && do { $res = ($val <= $value); last };
49             /^gt$/ && do { $res = ($val gt $value); last };
50             /^lt$/ && do { $res = ($val lt $value); last };
51             /^eq$/ && do { $res = ($val eq $value); last };
52             /^ne$/ && do { $res = ($val ne $value); last };
53             /^ge$/ && do { $res = ($val ge $value); last };
54             /^le$/ && do { $res = ($val le $value); last };
55
56             die "Unknown operator '$op' in conditional resolve", $/;
57         }
58
59         return $res && 1;
60     }
61
62     my $istrue = $val && 1;
63
64     my $is = uc $context->get($self, 'IS') || 'TRUE';
65     if ($is eq 'TRUE')
66     {
67         return 0 unless $istrue;
68     }
69     else
70     {
71         warn "Conditional 'is' value was [$is], defaulting to 'FALSE'" . $/
72             if $is ne 'FALSE' && $^W;
73
74         return 0 if $istrue;
75     }
76
77     return 1;
78 }
79
80 sub render
81 {
82     my $self = shift;
83     my ($context) = @_;
84
85     return 1 unless $self->_conditional_passes($context);
86
87     return $self->iterate_over_children($context);
88 }
89
90 #sub max_of
91 #{
92 #    my $self = shift;
93 #    my ($context, $attr) = @_;
94 #
95 #    return 0 unless $self->_conditional_passes($context);
96 #
97 #    return $self->SUPER::max_of($context, $attr);
98 #}
99 #
100 #sub total_of
101 #{
102 #    my $self = shift;
103 #    my ($context, $attr) = @_;
104 #
105 #    return 0 unless $self->_conditional_passes($context);
106 #
107 #    return $self->SUPER::total_of($context, $attr);
108 #}
109
110 1;
111 __END__
112
113 =head1 NAME
114
115 Excel::Template::Container::Conditional - Excel::Template::Container::Conditional
116
117 =head1 PURPOSE
118
119 To provide conditional execution of children nodes
120
121 =head1 NODE NAME
122
123 IF
124
125 =head1 INHERITANCE
126
127 L<CONTAINER|Excel::Template::Container>
128
129 =head1 ATTRIBUTES
130
131 =over 4
132
133 =item * NAME
134
135 This is the name of the parameter to test. It is resolved like any other parameter name. (q.v. L<VAR|Excel::Template::Element::Var> for more info.)
136
137 =item * VALUE
138
139 If VALUE is set, then a comparison operation is done. The value of NAME is compared to VALUE using the value of OP.
140
141 =item * OP
142
143 If VALUE is set, then this is checked. If it isn't present, then '==' (numeric equality) is assumed. OP must be one of Perl the numeric comparison operators or the string comparison operators. All 6 of each kind is supported.
144
145 B<Note>: If you want to use < or <=, you must instead use &lt; or &lt;=. This is to make sure it will parse with L<XML::Parser>. You should not need to use &gt; or &gt;= instead of > and >=, respectively.
146
147 =item * IS
148
149 If VALUE is not set, then IS is checked. IS is allowed to be either "TRUE" or "FALSE". The boolean value of NAME is checked against IS.
150
151 =back
152
153 =head1 CHILDREN
154
155 None
156
157 =head1 EFFECTS
158
159 None
160
161 =head1 DEPENDENCIES
162
163 None
164
165 =head1 USAGE
166
167   <if name="__ODD__" is="false">
168     ... Children here
169   </if>
170
171 In the above example, the children will be executed if the value of __ODD__ (which is set by the L<LOOP|Excel::Template::Container::Loop> node) is false. So, for all even iterations.
172
173 =head1 AUTHOR
174
175 Rob Kinyon (rob.kinyon@gmail.com)
176
177 =head1 SEE ALSO
178
179 L<LOOP|Excel::Template::Container::Loop>, L<VAR|Excel::Template::Element::Var>
180
181 =cut