File Coverage

blib/lib/App/Addex.pm
Criterion Covered Total %
statement 45 54 83.3
branch 9 14 64.2
condition 2 2 100.0
subroutine 10 12 83.3
pod 5 7 71.4
total 71 89 79.7


line stmt bran cond sub pod time code
1 5     5   24533 use strict;
  5         13  
  5         209  
2 5     5   28 use warnings;
  5         15  
  5         174  
3              
4             # because tests use open to open a string-ref, and I am not interested in ever
5             # supporting this module on ancient perls -- rjbs, 2007-12-17
6 5     5   127 use 5.008;
  5         24  
  5         296  
7              
8             package App::Addex;
9             # ABSTRACT: generate mail tool configuration from an address book
10             $App::Addex::VERSION = '0.026';
11 5     5   27 use Carp ();
  5         11  
  5         3229  
12              
13             #pod =head1 DESCRIPTION
14             #pod
15             #pod B<Achtung!> The API to this code may very well change. It is almost certain
16             #pod to be broken into smaller pieces, to support alternate sources of entries, and
17             #pod it might just get plugins.
18             #pod
19             #pod This module iterates through all the entries in an address book and produces
20             #pod configuration file based on the entries in the address book, using configured
21             #pod output plugins.
22             #pod
23             #pod It is meant to be run with the F<addex> command, which is bundled as part of
24             #pod this software distribution.
25             #pod
26             #pod =method new
27             #pod
28             #pod my $addex = App::Addex->new(\%arg);
29             #pod
30             #pod This method returns a new Addex.
31             #pod
32             #pod Valid parameters are:
33             #pod
34             #pod classes - a hashref of plugin/class pairs, described below
35             #pod
36             #pod Valid keys for the F<classes> parameter are:
37             #pod
38             #pod addressbook - the App::Addex::AddressBook subclass to use (required)
39             #pod output - an array of output producers (required)
40             #pod
41             #pod For each class given, an entry in C<%arg> may be given, which will be used to
42             #pod initialize the plugin before use.
43             #pod
44             #pod =cut
45              
46             # sub starting_section_name { 'classes' }
47 0     0 0 0 sub mvp_multivalue_args { qw(output plugin) }
48              
49             sub new {
50 7     7 1 4498 my ($class, $arg) = @_;
51              
52 7         22 my $self = bless {} => $class;
53              
54             # XXX: keep track of seen/unseen classes; carp if some go unused?
55             # -- rjbs, 2007-04-06
56              
57 7         17 for my $core (qw(addressbook)) {
58 7 100       314 my $class = $arg->{classes}{$core}
59             or Carp::confess "no $core class provided";
60              
61 6         38 $self->{$core} = $self->_initialize_plugin($class, $arg->{$class});
62             }
63              
64 6 100       22 my @output_classes = @{ $arg->{classes}{output} || [] }
  6 100       212  
65             or Carp::confess "no output classes provided";
66              
67 5         10 my @output_plugins;
68 5         11 for my $class (@output_classes) {
69 5         22 push @output_plugins, $self->_initialize_plugin($class, $arg->{$class});
70             }
71 4         35 $self->{output} = \@output_plugins;
72              
73 4 50       9 my @plugin_classes = @{ $arg->{classes}{plugin} || [] };
  4         49  
74 4         14 for my $class (@plugin_classes) {
75 0 0       0 eval "require $class" or die;
76 0 0       0 $class->import(%{ $arg->{$class} || {} });
  0         0  
77             }
78              
79 4         24 return $self;
80             }
81              
82             sub from_sequence {
83 0     0 0 0 my ($class, $seq) = @_;
84              
85 0         0 my %arg;
86 0         0 for my $section ($seq->sections) {
87 0         0 $arg{ $section->name } = $section->payload;
88             }
89              
90 0         0 $class->new(\%arg);
91             }
92              
93             sub _initialize_plugin {
94 11     11   31 my ($self, $class, $arg) = @_;
95 11   100     60 $arg ||= {};
96 11         21 $arg->{addex} = $self;
97              
98             # in most cases, this won't be needed, since the App::Addex::Config will have
99             # loaded plugins as a side effect, but let's be cautious -- rjbs, 2007-05-10
100 11 100       670 eval "require $class" or die;
101              
102 10         1623 return $class->new($arg);
103             }
104              
105             #pod =method addressbook
106             #pod
107             #pod my $abook = $addex->addressbook;
108             #pod
109             #pod This method returns the App::Addex::AddressBook object.
110             #pod
111             #pod =cut
112              
113 4     4 1 31 sub addressbook { $_[0]->{addressbook} }
114              
115             #pod =method output_plugins
116             #pod
117             #pod This method returns all of the output plugin objects.
118             #pod
119             #pod =cut
120              
121             sub output_plugins {
122 28     28 1 43 my ($self) = @_;
123 28         39 return @{ $self->{output} };
  28         84  
124             }
125              
126             #pod =method entries
127             #pod
128             #pod This method returns all the entries to be processed. By default it is
129             #pod delegated to the address book object. This method may change a good bit in the
130             #pod future, as we really want an iterator, not just a list.
131             #pod
132             #pod =cut
133              
134             sub entries {
135 4     4 1 10 my ($self) = @_;
136 4         23 return sort { $a->name cmp $b->name } $self->addressbook->entries;
  40         156  
137             }
138              
139             #pod =method run
140             #pod
141             #pod App::Addex->new({ ... })->run;
142             #pod
143             #pod This method performs all the work expected of an Addex: it iterates through the
144             #pod entries, invoking the output plugins for each one.
145             #pod
146             #pod =cut
147              
148             sub run {
149 4     4 1 2885 my ($self) = @_;
150              
151 4         20 for my $entry ($self->entries) {
152 24         220 for my $plugin ($self->output_plugins) {
153 24         84 $plugin->process_entry($self, $entry);
154             }
155             }
156              
157 4         100 for my $plugin ($self->output_plugins) {
158 4         41 $plugin->finalize;
159             }
160             }
161              
162             1;
163              
164             __END__
165              
166             =pod
167              
168             =encoding UTF-8
169              
170             =head1 NAME
171              
172             App::Addex - generate mail tool configuration from an address book
173              
174             =head1 VERSION
175              
176             version 0.026
177              
178             =head1 DESCRIPTION
179              
180             B<Achtung!> The API to this code may very well change. It is almost certain
181             to be broken into smaller pieces, to support alternate sources of entries, and
182             it might just get plugins.
183              
184             This module iterates through all the entries in an address book and produces
185             configuration file based on the entries in the address book, using configured
186             output plugins.
187              
188             It is meant to be run with the F<addex> command, which is bundled as part of
189             this software distribution.
190              
191             =head1 METHODS
192              
193             =head2 new
194              
195             my $addex = App::Addex->new(\%arg);
196              
197             This method returns a new Addex.
198              
199             Valid parameters are:
200              
201             classes - a hashref of plugin/class pairs, described below
202              
203             Valid keys for the F<classes> parameter are:
204              
205             addressbook - the App::Addex::AddressBook subclass to use (required)
206             output - an array of output producers (required)
207              
208             For each class given, an entry in C<%arg> may be given, which will be used to
209             initialize the plugin before use.
210              
211             =head2 addressbook
212              
213             my $abook = $addex->addressbook;
214              
215             This method returns the App::Addex::AddressBook object.
216              
217             =head2 output_plugins
218              
219             This method returns all of the output plugin objects.
220              
221             =head2 entries
222              
223             This method returns all the entries to be processed. By default it is
224             delegated to the address book object. This method may change a good bit in the
225             future, as we really want an iterator, not just a list.
226              
227             =head2 run
228              
229             App::Addex->new({ ... })->run;
230              
231             This method performs all the work expected of an Addex: it iterates through the
232             entries, invoking the output plugins for each one.
233              
234             =head1 AUTHOR
235              
236             Ricardo SIGNES <rjbs@cpan.org>
237              
238             =head1 COPYRIGHT AND LICENSE
239              
240             This software is copyright (c) 2006 by Ricardo SIGNES.
241              
242             This is free software; you can redistribute it and/or modify it under
243             the same terms as the Perl 5 programming language system itself.
244              
245             =cut