File Coverage

blib/lib/Locale/Utils/PlaceholderBabelFish.pm
Criterion Covered Total %
statement 73 73 100.0
branch 28 34 82.3
condition 1 3 33.3
subroutine 15 15 100.0
pod 2 2 100.0
total 119 127 93.7


line stmt bran cond sub pod time code
1             package Locale::Utils::PlaceholderBabelFish; ## no critic (TidyCode)
2            
3 5     5   154160 use strict;
  5         15  
  5         182  
4 5     5   66 use warnings;
  5         17  
  5         198  
5 5     5   37 use Carp qw(confess);
  5         20  
  5         313  
6 5     5   2770 use HTML::Entities qw(encode_entities);
  5         33218  
  5         561  
7 5     5   58 use List::Util qw(min);
  5         15  
  5         467  
8 5     5   2937 use Moo;
  5         65360  
  5         39  
9 5     5   11095 use MooX::StrictConstructor;
  5         74009  
  5         34  
10 5     5   143501 use MooX::Types::MooseLike::Base qw(Bool CodeRef);
  5         33918  
  5         706  
11 5     5   63 use Scalar::Util qw(looks_like_number);
  5         18  
  5         302  
12 5     5   2914 use namespace::autoclean;
  5         69557  
  5         32  
13            
14             our $VERSION = '0.006';
15            
16             has is_strict => (
17             is => 'rw',
18             isa => Bool,
19             );
20            
21             sub default_modifier_code {
22             return sub {
23 3     3   27 my ( $value, $attributes ) = @_;
24            
25 3 100       20 if ( $attributes =~ m{ \b html \b }xms ) {
26 1         8 $value = encode_entities( $value, q{<>&"} );
27             }
28            
29 3         323 return $value;
30             }
31 2     2 1 79 };
32            
33             has modifier_code => (
34             is => 'rw',
35             isa => CodeRef,
36             clearer => 'clear_modifier_code',
37             lazy => 1,
38             default => \&default_modifier_code,
39             );
40            
41             has plural_code => (
42             is => 'rw',
43             isa => CodeRef,
44             lazy => 1,
45             default => sub {
46             return sub {
47             my $n = shift;
48             0 + (
49             $n != 1 # en
50             );
51             };
52             },
53             clearer => 'clear_plural_code',
54             );
55            
56             sub _mangle_value {
57 47     47   181 my ($self, $placeholder, $value, $attribute) = @_;
58            
59 47 100       247 defined $value
    100          
60             or return $self->is_strict ? $placeholder : q{};
61 41 100       257 defined $attribute
62             or return $value;
63 7 50       157 $self->modifier_code
64             or return $value;
65 7         251 $value = $self->modifier_code->($value, $attribute);
66 7 50       101 defined $value
67             or confess 'modifier_code returns nothing or undef';
68            
69 7         51 return $value;
70             }
71            
72             sub expand_babel_fish {
73 26     26 1 6842 my ($self, $text, @args) = @_;
74            
75 26 100       102 defined $text
76             or return $text;
77 25 100       144 my $arg_ref = @args == 1
    50          
    100          
78             ? ( ref $args[0] eq 'HASH' ? $args[0] : { count => $args[0] } )
79             : {
80             @args % 2
81             ? confess 'Arguments expected pairwise'
82             : @args
83             };
84            
85             # placeholders
86 25         62 my $regex = join q{|}, map { quotemeta } keys %{$arg_ref};
  38         132  
  25         95  
87             ## no critic (EscapedMetacharacters)
88 25         777 $text =~ s{
89             ( \\ [#] ) # escaped
90             |
91             (
92             [#] \{
93             ( $regex ) # placeholder
94             (?: [ ]* [:] ( [^\}]+ ) )? # attribute
95             \}
96             )
97             }
98             {
99             $1
100             ? $1
101 50 100       286 : $self->_mangle_value($2, $arg_ref->{$3}, $4)
102             }xmsge;
103             ## use critic (EscapedMetacharacters)
104            
105             # plural
106             my $replace_code = sub {
107 21     21   69 my ( $match, $inner, $count ) = @_;
108            
109 21 100       93 looks_like_number($count)
110             or return $match;
111 16         36 $inner =~ s{ \\ [|] }{\0}xmsg;
112 16         25 my @special_plurals;
113             my @plurals
114             = map {
115             m{ \A [=] ( \d+ ) \s+ ( .* ) \z }xms
116 35 100       109 ? do {
117 1         6 push @special_plurals, [$1, $2];
118 1         5 ();
119             }
120             : $_;
121             }
122             map { ## no critic (ComplexMappings)
123 16         86 my $item = $_;
  35         63  
124 35         72 $item =~ s{ \0 }{\\|}xmsg;
125 35         84 $item;
126             }
127             split qr{ [|] }xms, $inner;
128 16         59 for my $plural ( @special_plurals ) {
129 1 50 33     13 if ( defined $plural->[0] && $plural->[0] == $count ) {
130 1         8 return $plural->[1];
131             }
132             }
133             @plurals
134 15 50       36 or return $match;
135 15         298 my $index = $self->plural_code->($count);
136 15         129 $index = min( $index, $#plurals );
137            
138 15         75 return $plurals[$index];
139 25         216 };
140             ## no critic (EscapedMetacharacters)
141 25         141 $text =~ s{
142             ( \\ \( \( ) # $1: escaped
143             |
144             ( # $2: match
145             \( \( # open
146             ( .*? ) # $3: inner
147             \) \) # close
148             (?: [:] ( \w+ ) )? # $4: count variable name
149             )
150             }
151             {
152             $1
153             ? $1
154             : $replace_code->( $2, $3, $4 ? $arg_ref->{$4} : $arg_ref->{count} )
155 21 100       98 }xmsge;
    50          
156             ## use critic (EscapedMetacharacters)
157            
158             # unescape
159 25         87 $text =~ s{ \\ (.) }{$1}xmsg;
160            
161 25         331 return $text;
162             }
163            
164             __PACKAGE__->meta->make_immutable;
165            
166             1;
167            
168             __END__