Intermediate commit - just have to add/fix POD for two classes, then done
[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 UNIVERSAL::isa($val, 'ARRAY');
30     $val = ${$val} while UNIVERSAL::isa($val, '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 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 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 be testing. It is resolved like any other
136 parameter. 
137
138 =item * VALUE
139
140 If VALUE is set, then a comparison operation is done. The value of NAME is
141 compared to VALUE using the value of OP.
142
143 =item * OP
144
145 If VALUE is set, then this is checked. If it isn't present, then '==' (numeric
146 equality) is assumed. OP must be one of the numeric comparison operators or the
147 string comparison operators. All 6 of each kind is supported.
148
149 =item * IS
150
151 If VALUE is not set, then IS is checked. IS is allowed to be either "TRUE" or
152 "FALSE". The boolean value of NAME is checked against IS.
153
154 =back
155
156 =head1 CHILDREN
157
158 None
159
160 =head1 EFFECTS
161
162 None
163
164 =head1 DEPENDENCIES
165
166 None
167
168 =head1 USAGE
169
170   <if name="__ODD__" is="false">
171     ... Children here
172   </if>
173
174 In the above example, the children will be executed if the value of __ODD__
175 (which is set by the LOOP node) is false. So, for all even iterations.
176
177 =head1 AUTHOR
178
179 Rob Kinyon (rob.kinyon@gmail.com)
180
181 =head1 SEE ALSO
182
183 LOOP
184
185 =cut