File Coverage

blib/lib/Mail/Builder/List.pm
Criterion Covered Total %
statement 69 73 94.5
branch 22 30 73.3
condition 18 33 54.5
subroutine 13 14 92.8
pod 8 8 100.0
total 130 158 82.2


line stmt bran cond sub pod time code
1             # ============================================================================
2             package Mail::Builder::List;
3             # ============================================================================
4              
5 8     8   33 use namespace::autoclean;
  8         9  
  8         54  
6 8     8   574 use Moose;
  8         11  
  8         44  
7 8     8   22948 use Mail::Builder::TypeConstraints;
  8         12  
  8         155  
8              
9 8     8   27 use Carp;
  8         11  
  8         7429  
10              
11             our $VERSION = $Mail::Builder::VERSION;
12              
13             has 'type' => (
14             is => 'ro',
15             isa => 'Mail::Builder::Type::Class',
16             required => 1,
17             );
18              
19             has 'list' => (
20             is => 'rw',
21             isa => 'ArrayRef[Object]',
22             default => sub { return [] },
23             trigger => \&_check_list,
24             traits => ['Array'],
25             handles => {
26             length => 'count',
27             #all => 'elements',
28             },
29             );
30              
31             sub _check_list {
32 12     12   16 my ($self,$value) = @_;
33            
34 12         279 my $type = $self->type;
35            
36 12         20 foreach my $element (@$value) {
37 18 50 33     103 unless (blessed $element
38             && $element->isa($type)) {
39 0         0 croak("'$value' is not a '$type'");
40             }
41             }
42 12         254 return;
43             }
44              
45             around 'list' => sub {
46             my $orig = shift;
47             my $self = shift;
48            
49             my $result = $self->$orig(@_);
50            
51             return wantarray ? @{$result} : $result;
52             };
53              
54             around BUILDARGS => sub {
55             my $orig = shift;
56             my $class = shift;
57              
58             if (scalar @_ == 1
59             && ref($_[0]) eq '') {
60             return $class->$orig({ type => $_[0] });
61             } else {
62             return $class->$orig(@_);
63             }
64             };
65              
66              
67             __PACKAGE__->meta->make_immutable;
68              
69             sub _convert_item {
70 12     12   10 my ($self) = shift;
71            
72 12 50       26 croak(qq[Params missing])
73             unless scalar @_;
74            
75 12         298 my $type = $self->type;
76            
77 12 100       36 if (blessed($_[0])) {
78 4 100       55 croak(qq[Invalid item added to list: Must be of $type])
79             unless ($_[0]->isa($type));
80 3         6 return $_[0];
81             } else {
82 8         186 my $object = $type->new(@_);
83 8 50 33     75 croak(qq[Could not create $type object])
      33        
84             unless (defined $object
85             && blessed $object
86             && $object->isa($type));
87            
88 8         16 return $object;
89             }
90             }
91              
92             sub convert {
93 1     1 1 2 my ($class,@elements) = @_;
94            
95 1 50 33     8 my $elements_ref = (scalar @elements == 1 && ref $elements[0] eq 'ARRAY') ?
96             $elements[0] : \@elements;
97            
98 1         31 return $class->new(
99             type => ref($elements_ref->[0]),
100             list => $elements_ref,
101             );
102             }
103              
104             sub join {
105 13     13 1 19 my ($self,$join_string) = @_;
106            
107             return CORE::join $join_string,
108 14         180 grep { $_ }
109 13         29 map { $_->serialize }
  14         34  
110             $self->list;
111             }
112              
113             sub contains {
114 16     16 1 19 my ($self,$compare) = @_;
115            
116 16 50       30 return 0
117             unless (defined $compare);
118            
119 16         42 foreach my $item ($self->list) {
120 24 100 100     87 return 1
121             if (blessed($compare) && $item == $compare);
122 23 100       40 return 1
123             if ($item->compare($compare));
124             }
125 13         32 return 0;
126             }
127              
128             sub reset {
129 1     1 1 2 my ($self) = @_;
130            
131 1         4 $self->list([]);
132            
133 1         4 return 1;
134             }
135              
136             sub push {
137 0     0 1 0 my ($self) = @_;
138 0         0 return $self->add(@_);
139             }
140              
141             sub remove {
142 3     3 1 5 my ($self,$remove) = @_;
143            
144 3         9 my $list = $self->list;
145            
146             # No params: take last param
147 3 100       6 unless (defined $remove) {
148 1         1 return pop @{$list};
  1         3  
149             # Element
150             } else {
151 2         3 my $new_list = [];
152 2         2 my $old_value;
153 2         2 my $index = 0;
154 2         1 foreach my $item (@{$list}) {
  2         5  
155 7 100 66     60 if (blessed($remove) && $item == $remove
      100        
      33        
      100        
156             || ($remove =~ /^\d+$/ && $index == $remove)
157             || $item->compare($remove)) {
158 2         3 $remove = $item;
159             } else {
160 5         5 CORE::push(@{$new_list},$item);
  5         6  
161             }
162 7         10 $index ++;
163             }
164 2         6 $self->list($new_list);
165            
166             # Return old value
167 2 50       55 return $remove
168             if defined $remove;
169             }
170 0         0 return;
171             }
172              
173             sub add {
174 12     12 1 98 my ($self) = shift;
175            
176 12         30 my $item = $self->_convert_item(@_);
177            
178 11 100       34 unless ($self->contains($item)) {
179 10         7 CORE::push(@{$self->list}, $item);
  10         20  
180             }
181            
182 11         24 return $item;
183             }
184              
185              
186             sub item {
187 21     21 1 26 my ($self,$index) = @_;
188            
189 21 50 33     151 $index = 0
190             unless defined $index
191             && $index =~ m/^\d+$/;
192            
193             return
194 21 50 33     99 unless ($index =~ m/^\d+$/
195             && defined $self->list->[$index]);
196            
197 21         45 return $self->list->[$index];
198             }
199              
200             __PACKAGE__->meta->make_immutable;
201              
202             1;
203              
204             =encoding utf8
205              
206             =head1 NAME
207              
208             Mail::Builder::List - Helper module for handling various lists
209              
210             =head1 SYNOPSIS
211              
212             use Mail::Builder;
213            
214             # Create a list that accepts Mail::Builder::Address objects
215             my $list = Mail::Builder::List->new('Mail::Builder::Address');
216            
217             # Add aMail::Builder::Address object
218             $list->add($address_object);
219            
220             # Add an email (Unrecognized values will be passed to the constructor of
221             # the type class - Mail::Builder::Address)
222             $list->add('sasha.nein@psychonauts.org');
223            
224             # Add one more email (Unrecognized values will be passed to the constructor of
225             # the type class - Mail::Builder::Address)
226             $list->add({ email => 'raz.aquato@psychonauts.org', name => 'Razputin'} );
227            
228             # Remove email from list
229             $list->remove('raz.aquato@psychonauts.org');
230            
231             # Remove first element in list
232             $list->remove(1);
233            
234             # Reset list
235             $list->reset;
236            
237             # Add email
238             $list->add('milla.vodello@psychonauts.org','Milla Vodello');
239            
240             # Serialize email list
241             print $list->join(',');
242              
243             =head1 DESCRIPTION
244              
245             This is a helper module for handling various lists (e.g. recipient, attachment
246             lists). The class contains convinient array/list handling functions.
247              
248             =head1 METHODS
249              
250             =head2 Constructor
251              
252             =head3 new
253              
254             my $list = Mail::Builder::List->new(Class name);
255             OR
256             my $list = Mail::Builder::List->new({
257             type => Class name,
258             [ list => ArrayRef, ]
259             });
260              
261             This constructor takes the class name of the objects it should hold. It is
262             only possible to add objects of the given type. It is not possible to change
263             the assigned type later.
264              
265             =head3 convert
266              
267             my $list = Mail::Builder::List->convert(ArrayRef);
268              
269             Constructor that converts an array reference into a Mail::Builder::List
270             object. The list type is defined by the first element of the array.
271              
272             =head2 Public Methods
273              
274             =head3 length
275              
276             Returns the number of items in the list.
277              
278             =head3 add
279              
280             $obj->add(Object);
281             OR
282             $obj->add(Anything)
283              
284             Pushes a new item into the list. The methods either accepts an object or
285             any values. Values will be passed to the C<new> method in the
286             list type class.
287              
288             =head3 push
289              
290             Synonym for L<add>
291              
292             =head3 remove
293              
294             $obj->remove(Object)
295             OR
296             $obj->remove(Index)
297             OR
298             $obj->remove(Anything)
299             OR
300             $obj->remove()
301              
302             Removes the given element from the list. If no parameter is passed to the
303             method the last element from the list will be removed instead.
304              
305             =head3 reset
306              
307             Removes all elements from the list, leaving an empty list.
308              
309             =head3 item
310              
311             my $list_item = $obj->item(Index)
312              
313             Returns the list item with the given index.
314              
315             =head3 join
316              
317             my $list = $obj->join(String)
318              
319             Serializes all items in the list and joins them using the given string.
320              
321             =head3 contains
322              
323             $obj->contains(Object)
324             or
325             $obj->contains(Anything)
326              
327             Returns true if the given object is in the list. You can either pass an
328             object or scalar value. Uses the L<compare> method from the list type class.
329              
330             =head2 Accessors
331              
332             =head3 type
333              
334             Returns the class name which was initially passed to the constructor.
335              
336             =head3 list
337              
338             Raw list as list or array reference.
339              
340             =head1 AUTHOR
341              
342             MaroÅ¡ Kollár
343             CPAN ID: MAROS
344             maros [at] k-1.com
345             http://www.k-1.com
346              
347             =cut