File Coverage

blib/lib/Courriel/Role/HeaderWithAttributes.pm
Criterion Covered Total %
statement 52 52 100.0
branch 7 8 87.5
condition n/a
subroutine 16 16 100.0
pod 0 2 0.0
total 75 78 96.1


line stmt bran cond sub pod time code
1             package Courriel::Role::HeaderWithAttributes;
2              
3 9     9   7644 use strict;
  9         19  
  9         371  
4 9     9   67 use warnings;
  9         17  
  9         354  
5 9     9   55 use namespace::autoclean;
  9         26  
  9         85  
6              
7             our $VERSION = '0.43';
8              
9 9     9   961 use Courriel::HeaderAttribute;
  9         20  
  9         362  
10 9     9   50 use Courriel::Helpers qw( parse_header_with_attributes );
  9         16  
  9         750  
11 9     9   55 use Courriel::Types qw( HashRef NonEmptyStr );
  9         18  
  9         75  
12 9     9   70316 use Params::ValidationCompiler qw( validation_for );
  9         17  
  9         661  
13 9     9   55 use Scalar::Util qw( blessed reftype );
  9         15  
  9         534  
14              
15 9     9   6550 use MooseX::Role::Parameterized;
  9         496187  
  9         46  
16              
17             parameter main_value_key => (
18             isa => NonEmptyStr,
19             required => 1,
20             );
21              
22             parameter main_value_method => (
23             isa => NonEmptyStr,
24             );
25              
26             has _attributes => (
27             traits => ['Hash'],
28             is => 'ro',
29             isa => HashRef ['Courriel::HeaderAttribute'],
30             init_arg => 'attributes',
31             default => sub { {} },
32             handles => {
33             attributes => 'elements',
34             _attribute => 'get',
35             _set_attribute => 'set',
36             _has_attributes => 'count',
37             },
38             );
39              
40             around BUILDARGS => sub {
41             my $orig = shift;
42             my $class = shift;
43              
44             my $p = $class->$orig(@_);
45              
46             return $p
47             unless $p->{attributes} && reftype( $p->{attributes} ) eq 'HASH';
48              
49             for my $name ( keys %{ $p->{attributes} } ) {
50             my $lc_name = lc $name;
51             $p->{attributes}{$lc_name} = delete $p->{attributes}{$name};
52              
53             next if blessed( $p->{attributes}{$lc_name} );
54              
55             $p->{attributes}{$lc_name} = Courriel::HeaderAttribute->new(
56             name => $name,
57             value => $p->{attributes}{$name},
58             );
59             }
60              
61             return $p;
62             };
63              
64             sub attribute {
65 80     80 0 119 my $self = shift;
66 80         141 my $key = shift;
67              
68 80 50       187 return unless defined $key;
69              
70 80         3797 return $self->_attribute( lc $key );
71             }
72              
73             {
74             my $validator = validation_for(
75             params => [ { type => NonEmptyStr } ],
76             );
77              
78             sub attribute_value {
79 40     40 0 67 my $self = shift;
80 40         913 my ($name) = $validator->(@_);
81              
82 40         964 my $attr = $self->attribute($name);
83              
84 40 100       1441 return $attr ? $attr->value : undef;
85             }
86             }
87              
88             sub _attributes_as_string {
89 1     1   2 my $self = shift;
90              
91 1         34 my $attr = $self->_attributes;
92              
93 1         2 return join '; ', map { $attr->{$_}->as_string } sort keys %{$attr};
  1         7  
  1         3  
94             }
95              
96             {
97             my $validator = validation_for(
98             params => [
99             name => { isa => NonEmptyStr, optional => 1 },
100             value => { isa => NonEmptyStr },
101             ],
102             named_to_list => 1,
103             );
104              
105             role {
106             my $p = shift;
107              
108             my $main_value_key = $p->main_value_key;
109              
110             method new_from_value => sub {
111 209     209   530 my $class = shift;
        206      
112 209         5488 my ( $name, $value ) = $validator->(@_);
113              
114 209         4584 my ( $main_value, $attributes )
115             = parse_header_with_attributes($value);
116              
117 209         1155 my %p = (
118             value => $value,
119             $main_value_key => $main_value,
120             attributes => $attributes,
121             );
122              
123 209 100       678 $p{name} = $name if defined $name;
124              
125 209         8543 return $class->new(%p);
126             };
127              
128             my $main_value_meth = $p->main_value_method || $p->main_value_key;
129              
130             method as_header_value => sub {
131 2     2   3 my $self = shift;
        2      
132              
133 2         69 my $string = $self->$main_value_meth;
134              
135 2 100       112 if ( $self->_has_attributes ) {
136 1         3 $string .= '; ';
137 1         5 $string .= $self->_attributes_as_string;
138             }
139              
140 2         63 return $string;
141             };
142             }
143             }
144              
145             1;