File Coverage

blib/lib/Template/Stash/AutoEscape.pm
Criterion Covered Total %
statement 82 95 86.3
branch 25 42 59.5
condition 9 17 52.9
subroutine 13 15 86.6
pod 3 6 50.0
total 132 175 75.4


line stmt bran cond sub pod time code
1             package Template::Stash::AutoEscape;
2              
3 3     3   15759 use strict;
  3         7  
  3         113  
4 3     3   16 use warnings;
  3         7  
  3         134  
5             our $VERSION = '0.03';
6              
7 3     3   2912 use Template::Config;
  3         10519  
  3         108  
8 3     3   24 use base ($Template::Config::STASH, 'Class::Data::Inheritable');
  3         6  
  3         915  
9              
10 3     3   66073 use Data::Dumper;
  3         10120  
  3         221  
11 3     3   2581 use UNIVERSAL::require;
  3         5156  
  3         32  
12 3     3   2029 use Template::Stash::AutoEscape::RawString;
  3         14  
  3         31  
13              
14             __PACKAGE__->mk_classdata('class_for_type');
15             __PACKAGE__->class_for_type({
16             HTML => __PACKAGE__ . '::Escaped::HTML',
17             YourCode => __PACKAGE__ . '::Escaped::YourCode',
18             });
19              
20             our $DEBUG = 0;
21             our $escape_count = 0;
22              
23             our $ESCAPE_ARGS = 0;
24              
25             sub new {
26 2     2 1 38 my $class = shift;
27 2         37 my $self = $class->SUPER::new(@_);
28 2   50     102 $self->{method_for_raw} ||= 'raw';
29 2   50     16 $self->{_raw_string_class} ||= __PACKAGE__ . '::' . 'RawString';
30 2   50     16 $self->{ignore_escape} ||= [];
31              
32 2 50       9 if (ref $self->{escape_method} eq "CODE") {
33 0         0 $self->{escape_type} = "YourCode";
34 0         0 my $escape_class = $class->class_for($self->{escape_type});
35 0 0       0 if (!$escape_class->can("escape")) {
36 0 0       0 $escape_class->require or die $@;
37             }
38 0         0 $escape_class->escape_method($self->{escape_method});
39             } else {
40 2   50     9 $self->{escape_type} ||= 'HTML';
41 2         8 my $escape_class = $class->class_for($self->{escape_type});
42 2 50       55 if (!$escape_class->can("escape")) {
43 0 0       0 $escape_class->require or die $@;
44             }
45             }
46            
47             $Template::Stash::SCALAR_OPS->{$self->{method_for_raw}} = sub {
48 6     6   13 my $scalar = shift;
49 6         44 $self->{_raw_string_class}->new($scalar);
50 2         18 };
51             $Template::Stash::LIST_OPS->{$self->{method_for_raw}} = sub {
52 0     0   0 my $scalar = shift;
53 0         0 $self->{_raw_string_class}->new($scalar);
54 2         13 };
55 2         20 return $self;
56             }
57              
58             sub get_raw_args {
59 18     18 0 32 my ( $args, $escaped_class ) = @_;
60 18         26 my $changed = 0;
61 18         24 my @raw_args;
62 18         23 for my $v (@{ $args }) {
  18         38  
63 69         71 my $new_v;
64 69 100       170 if ( ref $v eq $escaped_class ) {
    100          
65 2         5 $changed = 1;
66 2         104 $new_v = $v->[0];
67             } elsif (ref $v eq 'ARRAY') {
68 3         11 $new_v = get_raw_args($v, $escaped_class);
69 3 100       9 if ($new_v) {
70 1         2 $changed = 1;
71             } else {
72 2         3 $new_v = $v;
73             }
74             } else {
75 64         75 $new_v = $v;
76             }
77 69         134 push @raw_args, $new_v;
78             }
79              
80 18 100       67 return unless $changed;
81 3         8 return \@raw_args;
82             }
83              
84             sub get {
85 43     43 1 103961 my ( $self, @args ) = @_;
86             # get value
87 43 50       112 warn Dumper +{ args => \@args } if $DEBUG;
88              
89             # note: hack for [% hash.${key} %] [% hash.item(key) %]
90             # key expected raw string.
91 43 100 66     255 if (!$ESCAPE_ARGS && ref $args[0] eq "ARRAY" && (scalar @{$args[0]} > 2)){
  15   66     61  
92 15         47 my $escaped_class = $self->class_for($self->{escape_type});
93 15         189 my $changed = get_raw_args($args[0], $escaped_class);
94             # retry by non-escaped args
95 15 100       42 if ($changed) {
96 2         5 $args[0] = $changed;
97 2         12 return $self->get(@args);
98             }
99             }
100              
101 41         705 my ($var) = $self->SUPER::get(@args);
102 41 100       248 if (ref $args[0] eq "ARRAY") {
103 13         31 my $key = $args[0]->[0];
104 13 50       32 warn $key if $DEBUG;
105 13 50       19 if (grep { $key eq $_ } @{ $self->{ignore_escape} }) {
  0         0  
  13         47  
106 0 0       0 warn "ignore escape $key" if $DEBUG;
107 0         0 return $var;
108             }
109             }
110              
111 41         66 my $ref = ref $var;
112             # string
113 41 100       98 unless ($ref) {
114 31 50       67 $escape_count++ if $DEBUG;
115 31         91 return $self->escape($var);
116             }
117             # via .raw vmethod
118 10 100       36 if ($ref eq $self->{_raw_string_class}) {
119 6         98 return "$var";
120             }
121 4         144 return $var;
122             # my $escape_class = $self->class_for($self->{escape_type});
123             # warn $ref->isa($escape_class);
124             # if (!$ref->isa($escape_class)) {
125             # $escape_count++ if $DEBUG;
126             # return $self->escape($var);
127             # }
128             # return $var;
129             }
130              
131             sub class_for {
132 52     52 1 120 my $class = shift;
133 52 50       122 if (@_ == 1) {
    0          
134 52   33     164 return $class->class_for_type->{$_[0]} || __PACKAGE__ . '::Escaped::' . $_[0];
135             } elsif (@_ == 2) {
136 0         0 return $class->class_for_type->{$_[0]} = $_[1];
137             }
138             }
139              
140             sub escape {
141 31     31 0 45 my $self = shift;
142 31         36 my $text = shift;
143 31         77 my $class = $self->class_for($self->{escape_type});
144 31         313 my $stringify_callback = $self->{before_stringify};
145 31         161 $class->new($text, 0, undef, $stringify_callback);
146             }
147              
148             sub escape_count {
149 0     0 0   $escape_count;
150             }
151              
152             1;
153              
154              
155             __END__