File Coverage

lib/Petal/Hash.pm
Criterion Covered Total %
statement 84 89 94.3
branch 19 22 86.3
condition 9 15 60.0
subroutine 18 19 94.7
pod 0 5 0.0
total 130 150 86.6


line stmt bran cond sub pod time code
1             package Petal::Hash;
2 77     77   1153 use strict;
  77         138  
  77         2154  
3 77     77   354 use warnings;
  77         121  
  77         1792  
4 77     77   379 use Carp;
  77         159  
  77         114590  
5              
6             our $MODIFIERS = {};
7              
8             # import all plugins once
9             foreach my $include_dir (@INC)
10             {
11             my $dir = "$include_dir/Petal/Hash";
12             if (-e $dir and -d $dir)
13             {
14             opendir DD, $dir or do {
15             warn "Cannot open directory $dir. Reason: $!";
16             next;
17             };
18            
19             my @modules = map { s/\.pm$//; $_ }
20             grep /\.pm$/,
21             grep !/^\./,
22             readdir (DD);
23            
24             closedir DD;
25            
26             foreach my $module (@modules)
27             {
28             $module =~ /^(\w+)$/;
29             $module = $1;
30 77     77   25237 eval "use Petal::Hash::$module";
  77     77   202  
  77     77   1371  
  77     77   23410  
  77     77   204  
  77     77   1362  
  77     77   26723  
  77     77   197  
  77     77   1570  
  77         569  
  77         146  
  77         1025  
  77         476  
  77         153  
  77         924  
  77         431  
  77         133  
  77         790  
  77         475  
  77         133  
  77         908  
  77         435  
  77         161  
  77         928  
  77         420  
  77         137  
  77         794  
31             $@ and warn "Cannot import module $module. Reason: $@";
32             $MODIFIERS->{lc ($module) . ':'} = "Petal::Hash::$module";
33             }
34             }
35             }
36              
37              
38             # set modifier
39             $MODIFIERS->{'set:'} = sub {
40             my $hash = shift;
41             my $argument = shift;
42             my @split = split /\s+/, $argument;
43             my $set = shift (@split) or confess "bad syntax for 'set:': $argument (\$set)";
44             my $value = $hash->fetch (join ' ', @split);
45             $hash->{$set} = $value;
46             delete $hash->{__petal_hash_cache__}->{$set};
47             return '';
48             };
49             $MODIFIERS->{'def:'} = $MODIFIERS->{'set:'};
50             $MODIFIERS->{'define:'} = $MODIFIERS->{'set:'};
51              
52              
53             # true modifier
54             $MODIFIERS->{'true:'} = sub {
55             my $hash = shift;
56             my $variable = $hash->fetch (@_);
57             return unless (defined $variable);
58            
59             (scalar @{$variable}) ? return 1 : return
60             if (ref $variable eq 'ARRAY' or (ref $variable and $variable =~ /=ARRAY\(/));
61            
62             ($variable) ? return 1 : return;
63             };
64              
65              
66             # false modifier
67             $MODIFIERS->{'false:'} = sub {
68             my $hash = shift;
69             my $variable = join ' ', @_;
70             return not $hash->fetch ("true:$variable");
71             };
72              
73             $MODIFIERS->{'not:'} = $MODIFIERS->{'false:'};
74              
75             # encode: modifier (deprecated stuff)
76             $MODIFIERS->{'encode:'} = sub {
77             warn "Petal modifier encode: is deprecated";
78             my $hash = shift;
79             my $argument = shift;
80             return $hash->fetch ($argument);
81             };
82             $MODIFIERS->{'xml:'} = $MODIFIERS->{'encode:'};
83             $MODIFIERS->{'html:'} = $MODIFIERS->{'encode:'};
84             $MODIFIERS->{'encode_html:'} = $MODIFIERS->{'encode:'};
85              
86              
87             # Instanciates a new Petal::Hash object which should
88             # be tied to a hash.
89             sub new
90             {
91 365     365 0 604 my $thing = shift;
92             my $self = (ref $thing) ?
93 365 100       1063 bless { %{$thing} }, ref $thing :
  232         1432  
94             bless { @_ }, $thing;
95            
96 365         1089 $self->{__petal_hash_cache__} = {};
97 365         2419 return $self;
98             }
99              
100              
101             # Gets a value...
102             sub get
103             {
104 765     765 0 806 my $self = shift;
105 765         756 my $key = shift;
106 765         1066 my $fresh = $key =~ s/^\s*fresh\s+//;
107 765 50       1194 delete $self->{__petal_hash_cache__}->{$key} if ($fresh);
108 765 100       1674 exists $self->{__petal_hash_cache__}->{$key} and return $self->{__petal_hash_cache__}->{$key};
109              
110 654         694 my $res = undef;
111 654 100       871 if ($Petal::HTML_ERRORS)
112             {
113 3         7 $res = eval { $self->__FETCH ($key) };
  3         14  
114 3 100       344 $@ and return "[ Cannot fetch $key. ]";
115             }
116             else
117             {
118 651         1009 $res = $self->__FETCH ($key);
119             }
120              
121 646         1308 $self->{__petal_hash_cache__}->{$key} = $res;
122 646         2149 return $res;
123             }
124              
125              
126             sub get_encoded
127             {
128 612     612 0 838 my $self = shift;
129 612         956 my $key = shift;
130 612         998 my $res = $self->get ($key);
131 607 100       1129 return unless (defined $res);
132              
133 593         819 my $no_encode = $key =~ s/^\s*structure\s+//;
134 593 100 66     1028 unless ($no_encode and $no_encode)
135             {
136 590         741 $res =~ s/\&/\&/g;
137 590         596 $res =~ s/\
138 590         648 $res =~ s/\"/\"/g;
139             }
140              
141 593         5866 return $res;
142             }
143              
144              
145             sub delete_cached
146             {
147 0     0 0 0 my $self = shift;
148 0         0 my $regex = shift;
149 0         0 for (keys %{$self->{__petal_hash_cache__}})
  0         0  
150             {
151 0 0       0 /$regex/ and delete $self->{__petal_hash_cache__}->{$_};
152             }
153             }
154              
155              
156             sub __FETCH
157             {
158 654     654   680 my $self = shift;
159 654         713 my $key = shift;
160 654         821 my $no_encode = $key =~ s/^\s*structure\s+//;
161 654 100 66     1901 if (defined $no_encode and $no_encode)
162             {
163 3         8 return $self->fetch ($key);
164             }
165             else
166             {
167             # can anyone explain why keys beginning with 'text' are not allowed???
168 651         758 $key =~ s/^\s*text\s*//;
169 651         1016 return $self->fetch ($key);
170             }
171             }
172              
173              
174             # this method fetches a Petal expression and returns it
175             # without XML encoding. FETCH is basically a wrapper around
176             # fetch() which looks for the special keyword 'structure'.
177             sub fetch
178             {
179 794     794 0 812 my $self = shift;
180 794         829 my $key = shift;
181            
182 794         1177 my $mod = $self->_fetch_mod ($key);
183 794         4078 $key =~ s/^\Q$mod\E//;
184 794         1763 $key =~ s/^\s+//;
185            
186 794   33     1695 my $module = $MODIFIERS->{$mod} || confess "$mod is not a known modifier";
187 794 100 66     2599 (defined $module and ref $module and ref $module eq 'CODE') and return $module->($self, $key);
      66        
188 713         1922 $module->process ($self, $key);
189             }
190              
191              
192             sub _fetch_mod
193             {
194 794     794   798 my $self = shift;
195 794         859 my $key = shift;
196 794         1697 my ($mod) = $key =~ /^([A-Za-z0-9_-]+?\:).*/;
197 794 100       1744 defined $mod || return 'var:';
198 143         256 return $mod;
199             }
200              
201              
202             1;
203              
204              
205             __END__