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   288 use strict;
  77         112  
  77         1785  
3 77     77   231 use warnings;
  77         84  
  77         1627  
4 77     77   232 use Carp;
  77         76  
  77         82156  
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   19069 eval "use Petal::Hash::$module";
  77     77   134  
  77     77   1092  
  77     77   18362  
  77     77   120  
  77     77   1192  
  77     77   19018  
  77     77   121  
  77     77   1367  
  77         301  
  77         95  
  77         865  
  77         284  
  77         79  
  77         754  
  77         267  
  77         84  
  77         628  
  77         297  
  77         82  
  77         694  
  77         247  
  77         876  
  77         704  
  77         303  
  77         82  
  77         688  
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 403 my $thing = shift;
92             my $self = (ref $thing) ?
93 365 100       823 bless { %{$thing} }, ref $thing :
  232         1225  
94             bless { @_ }, $thing;
95            
96 365         768 $self->{__petal_hash_cache__} = {};
97 365         2036 return $self;
98             }
99              
100              
101             # Gets a value...
102             sub get
103             {
104 765     765 0 576 my $self = shift;
105 765         509 my $key = shift;
106 765         792 my $fresh = $key =~ s/^\s*fresh\s+//;
107 765 50       1013 delete $self->{__petal_hash_cache__}->{$key} if ($fresh);
108 765 100       1488 exists $self->{__petal_hash_cache__}->{$key} and return $self->{__petal_hash_cache__}->{$key};
109              
110 654         474 my $res = undef;
111 654 100       737 if ($Petal::HTML_ERRORS)
112             {
113 3         5 $res = eval { $self->__FETCH ($key) };
  3         9  
114 3 100       273 $@ and return "[ Cannot fetch $key. ]";
115             }
116             else
117             {
118 651         807 $res = $self->__FETCH ($key);
119             }
120              
121 646         967 $self->{__petal_hash_cache__}->{$key} = $res;
122 646         1745 return $res;
123             }
124              
125              
126             sub get_encoded
127             {
128 612     612 0 511 my $self = shift;
129 612         441 my $key = shift;
130 612         758 my $res = $self->get ($key);
131 607 100       995 return unless (defined $res);
132              
133 593         579 my $no_encode = $key =~ s/^\s*structure\s+//;
134 593 100 66     943 unless ($no_encode and $no_encode)
135             {
136 590         536 $res =~ s/\&/\&/g;
137 590         465 $res =~ s/\
138 590         446 $res =~ s/\"/\"/g;
139             }
140              
141 593         5168 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   474 my $self = shift;
159 654         536 my $key = shift;
160 654         608 my $no_encode = $key =~ s/^\s*structure\s+//;
161 654 100 66     1869 if (defined $no_encode and $no_encode)
162             {
163 3         6 return $self->fetch ($key);
164             }
165             else
166             {
167             # can anyone explain why keys beginning with 'text' are not allowed???
168 651         541 $key =~ s/^\s*text\s*//;
169 651         822 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 571 my $self = shift;
180 794         582 my $key = shift;
181            
182 794         859 my $mod = $self->_fetch_mod ($key);
183 794         2961 $key =~ s/^\Q$mod\E//;
184 794         1108 $key =~ s/^\s+//;
185            
186 794   33     1414 my $module = $MODIFIERS->{$mod} || confess "$mod is not a known modifier";
187 794 100 66     2803 (defined $module and ref $module and ref $module eq 'CODE') and return $module->($self, $key);
      66        
188 713         1619 $module->process ($self, $key);
189             }
190              
191              
192             sub _fetch_mod
193             {
194 794     794   680 my $self = shift;
195 794         618 my $key = shift;
196 794         1136 my ($mod) = $key =~ /^([A-Za-z0-9_-]+?\:).*/;
197 794 100       1476 defined $mod || return 'var:';
198 143         271 return $mod;
199             }
200              
201              
202             1;
203              
204              
205             __END__