File Coverage

blib/lib/Sietima/HeaderURI.pm
Criterion Covered Total %
statement 39 39 100.0
branch 4 4 100.0
condition 2 2 100.0
subroutine 11 11 100.0
pod 2 2 100.0
total 58 58 100.0


line stmt bran cond sub pod time code
1             package Sietima::HeaderURI;
2 3     3   4665 use Moo;
  3         6  
  3         21  
3 3     3   850 use Sietima::Policy;
  3         6  
  3         13  
4 3     3   16 use Sietima::Types qw(Address AddressFromStr is_Address);
  3         5  
  3         45  
5 3     3   1809 use Types::Standard qw(Str is_Str ClassName HashRef Optional);
  3         6  
  3         20  
6 3     3   3185 use Type::Params qw(compile);
  3         6  
  3         20  
7 3     3   1539 use Types::URI qw(Uri is_Uri);
  3         207178  
  3         33  
8 3     3   1370 use Email::Address;
  3         8  
  3         71  
9 3     3   13 use namespace::clean;
  3         6  
  3         21  
10              
11             our $VERSION = '1.0.5'; # VERSION
12             # ABSTRACT: annotated URI for list headers
13              
14              
15             has uri => (
16             is => 'ro',
17             isa => Uri,
18             required => 1,
19             coerce => 1,
20             );
21              
22              
23             has comment => (
24             is => 'ro',
25             isa => Str,
26             );
27              
28              
29             sub _args_from_address {
30 14     14   30 my ($address, $query) = @_;
31 14   100     59 $query ||= {};
32              
33 14         46 my $uri = URI->new($address->address,'mailto');
34 14         3921 $uri->query_form($query->%*);
35              
36 14         574 my $comment = $address->comment;
37             # Email::Address::comment always returns a string in paretheses,
38             # but we don't want that, since we add them back in as_header_raw
39 14 100       98 $comment =~ s{\A\((.*)\)\z}{$1} if $comment;
40              
41             return {
42 14         274 uri => $uri,
43             comment => $comment,
44             };
45             }
46              
47             around BUILDARGS => sub {
48             my ($orig, $class, @args) = @_;
49             if (@args != 1 or ref($args[0]) eq 'HASH' and $args[0]->{uri}) {
50             return $class->$orig(@args);
51             }
52              
53             my $item = $args[0];
54             if (is_Address($item)) {
55             return _args_from_address($item);
56             }
57             elsif (is_Uri($item)) {
58             return { uri => $item };
59             }
60             elsif (is_Str($item) and my $address = AddressFromStr->coerce($item)) {
61             return _args_from_address($address);
62             }
63             else {
64             return { uri => $item };
65             };
66             };
67              
68              
69             sub new_from_address {
70 4     4 1 2425 state $check = compile(
71             ClassName,
72             Address->plus_coercions(AddressFromStr),
73             Optional[HashRef],
74             );
75 4         5188 my ($class, $address, $query) = $check->(@_);
76              
77 4         305 return $class->new(_args_from_address($address,$query));
78             }
79              
80              
81             sub as_header_raw {
82 19     19 1 4789 my ($self) = @_;
83              
84 19         186 my $str = sprintf '<%s>',$self->uri;
85 19 100       127 if (my $c = $self->comment) {
86 6         19 $str .= sprintf ' (%s)',$c;
87             }
88              
89 19         88 return $str;
90             }
91              
92             1;
93              
94             __END__
95              
96             =pod
97              
98             =encoding UTF-8
99              
100             =head1 NAME
101              
102             Sietima::HeaderURI - annotated URI for list headers
103              
104             =head1 VERSION
105              
106             version 1.0.5
107              
108             =head1 SYNOPSIS
109              
110             around list_addresses => sub($orig,$self) {
111             return +{
112             $self->$orig->%*,
113             one => Sietima::HeaderURI->new({
114             uri => 'http://foo/',
115             comment => 'a thing',
116             }),
117             two => Sietima::HeaderURI->new_from_address(
118             $self->owner,
119             { subject => 'Hello' },
120             ),
121             three => Sietima::HeaderURI->new('http://some/url'),
122             four => Sietima::HeaderURI->new('(comment) address@example.com'),
123             };
124             }
125              
126             =head1 DESCRIPTION
127              
128             This class pairs a L<< C<URI> >> with a comment, and knows how to
129             render itself as a string that can be used in a list management header
130             (see L<< C<Sietima::Role::Headers> >>).
131              
132             =head1 ATTRIBUTES
133              
134             All attributes are read-only.
135              
136             =head2 C<uri>
137              
138             Required L<< C<URI> >> object, coercible from a string or a hashref
139             (see L<< C<Types::Uri> >> for the details). This is the URI that users
140             should follow to perform the action implied by the list management
141             header.
142              
143             =head2 C<comment>
144              
145             Optional string, will be added to the list management header as a
146             comment (in parentheses).
147              
148             =head1 METHODS
149              
150             =head2 C<new>
151              
152             Sietima::HeaderURI->new({
153             uri => 'http://foo/', comment => 'a thing',
154             });
155              
156             Sietima::HeaderURI->new(
157             Email::Address->parse('(comment) address@example.com'),
158             );
159              
160             Sietima::HeaderURI->new( '(comment) address@example.com' );
161              
162             Sietima::HeaderURI->new(
163             URI->new('http://some/url'),
164             );
165              
166             Sietima::HeaderURI->new( 'http://some/url' );
167              
168             Objects of this class can be constructed in several ways.
169              
170             You can pass a hashref with URI (or something that L<< C<Types::Uri>
171             >> can coerce into a URI) and a comment string, as in the first
172             example.
173              
174             Or you can pass a single value that can be (or can be coerced into)
175             either a L<< C<Email::Address> >> or a L<< C<URI> >>.
176              
177             Email addresse became C<mailto:> URIs, and the optional comment is
178             preserved.
179              
180             =head2 C<new_from_address>
181              
182             Sietima::HeaderURI->new_from_address(
183             $email_address,
184             \%query,
185             );
186              
187             This constructor builds a complex C<mailto:> URI with the query hash
188             you provide. It's a shortcut for:
189              
190             my $uri = URI->new("mailto:$email_address");
191             $uri->query_form(\%query);
192              
193             Common query keys are C<subject> and C<body>. See RFC 6068 ("The
194             'mailto' URI Scheme") for details.
195              
196             =head2 C<as_header_raw>
197              
198             $mail->header_raw_set('List-Thing' => $headeruri->as_header_raw);
199              
200             This method returns a string representation of the L</URI> and
201             L</comment> in the format specified by RFC 2369 ("The Use of URLs as
202             Meta-Syntax for Core Mail List Commands and their Transport through
203             Message Header Fields").
204              
205             For example:
206              
207             Sietima::HeaderURI->new({
208             uri => 'http://foo/', comment => 'a thing',
209             })->as_header_raw eq '<http://foo/> (a thing)';
210              
211             Sietima::HeaderURI->new( '(comment) address@example.com' )
212             ->as_header_raw eq '<mailto:address@example.com> (comment)';
213              
214             Sietima::HeaderURI->new( 'http://some/url' )
215             ->as_header_raw eq '<http://some/url>';
216              
217             Notice that, since the list management headers are I<structured>, they
218             should always be set with L<<
219             C<header_raw_set>|Email::Simple::Header/header_raw_set >>.
220              
221             =for Pod::Coverage BUILDARGS
222              
223             =head1 AUTHOR
224              
225             Gianni Ceccarelli <dakkar@thenautilus.net>
226              
227             =head1 COPYRIGHT AND LICENSE
228              
229             This software is copyright (c) 2017 by Gianni Ceccarelli <dakkar@thenautilus.net>.
230              
231             This is free software; you can redistribute it and/or modify it under
232             the same terms as the Perl 5 programming language system itself.
233              
234             =cut