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   1220 use strict;
  77         141  
  77         2245  
3 77     77   363 use warnings;
  77         139  
  77         2004  
4 77     77   361 use Carp;
  77         167  
  77         122114  
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   26589 eval "use Petal::Hash::$module";
  77     77   215  
  77     77   1480  
  77     77   25000  
  77     77   205  
  77     77   1458  
  77     77   28265  
  77     77   229  
  77     77   2029  
  77         500  
  77         154  
  77         1103  
  77         441  
  77         139  
  77         1132  
  77         452  
  77         148  
  77         829  
  77         494  
  77         195  
  77         953  
  77         477  
  77         140  
  77         898  
  77         440  
  77         130  
  77         863  
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 612 my $thing = shift;
92             my $self = (ref $thing) ?
93 365 100       1112 bless { %{$thing} }, ref $thing :
  232         1754  
94             bless { @_ }, $thing;
95              
96 365         1135 $self->{__petal_hash_cache__} = {};
97 365         2559 return $self;
98             }
99              
100              
101             # Gets a value...
102             sub get
103             {
104 765     765 0 924 my $self = shift;
105 765         816 my $key = shift;
106 765         1218 my $fresh = $key =~ s/^\s*fresh\s+//;
107 765 50       1263 delete $self->{__petal_hash_cache__}->{$key} if ($fresh);
108 765 100       1703 exists $self->{__petal_hash_cache__}->{$key} and return $self->{__petal_hash_cache__}->{$key};
109              
110 654         759 my $res = undef;
111 654 100       996 if ($Petal::HTML_ERRORS)
112             {
113 3         6 $res = eval { $self->__FETCH ($key) };
  3         11  
114 3 100       641 $@ and return "[ Cannot fetch $key. ]";
115             }
116             else
117             {
118 651         1099 $res = $self->__FETCH ($key);
119             }
120              
121 646         1397 $self->{__petal_hash_cache__}->{$key} = $res;
122 646         2430 return $res;
123             }
124              
125              
126             sub get_encoded
127             {
128 612     612 0 849 my $self = shift;
129 612         731 my $key = shift;
130 612         1072 my $res = $self->get ($key);
131 607 100       1324 return unless (defined $res);
132              
133 593         933 my $no_encode = $key =~ s/^\s*structure\s+//;
134 593 100 66     1139 unless ($no_encode and $no_encode)
135             {
136 590         882 $res =~ s/\&/\&/g;
137 590         746 $res =~ s/\
138 590         679 $res =~ s/\"/\"/g;
139             }
140              
141 593         6819 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   743 my $self = shift;
159 654         788 my $key = shift;
160 654         973 my $no_encode = $key =~ s/^\s*structure\s+//;
161 654 100 66     2063 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         866 $key =~ s/^\s*text\s*//;
169 651         1133 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 916 my $self = shift;
180 794         894 my $key = shift;
181              
182 794         1474 my $mod = $self->_fetch_mod ($key);
183 794         4399 $key =~ s/^\Q$mod\E//;
184 794         1804 $key =~ s/^\s+//;
185              
186 794   33     1879 my $module = $MODIFIERS->{$mod} || confess "$mod is not a known modifier";
187 794 100 66     2926 (defined $module and ref $module and ref $module eq 'CODE') and return $module->($self, $key);
      66        
188 713         2133 $module->process ($self, $key);
189             }
190              
191              
192             sub _fetch_mod
193             {
194 794     794   878 my $self = shift;
195 794         886 my $key = shift;
196 794         1797 my ($mod) = $key =~ /^([A-Za-z0-9_-]+?\:).*/;
197 794 100       1843 defined $mod || return 'var:';
198 143         280 return $mod;
199             }
200              
201              
202             1;
203              
204              
205             __END__