File Coverage

blib/lib/Config/MVP/Reader/Finder.pm
Criterion Covered Total %
statement 37 41 90.2
branch 9 18 50.0
condition 2 5 40.0
subroutine 9 12 75.0
pod 4 4 100.0
total 61 80 76.2


line stmt bran cond sub pod time code
1             package Config::MVP::Reader::Finder;
2             # ABSTRACT: a reader that finds an appropriate file
3             $Config::MVP::Reader::Finder::VERSION = '2.200012';
4 1     1   4695 use Moose;
  1         3  
  1         6  
5             extends 'Config::MVP::Reader';
6              
7             #pod =head1 DESCRIPTION
8             #pod
9             #pod The Finder reader multiplexes many other readers that implement the
10             #pod L<Config::MVP::Reader::Findable> role. It uses L<Module::Pluggable> to search
11             #pod for modules, limits them to objects implementing the Findable role, and then
12             #pod selects the those which report that they are able to read a configuration file
13             #pod found in the config root directory. If exactly one findable configuration
14             #pod reader finds a file, it is used to read the file and the configuration sequence
15             #pod is returned. Otherwise, an exception is raised.
16             #pod
17             #pod Config::MVP::Reader::Finder's C<build_assembler> method will decline a new
18             #pod assembler, so if none was passed to C<read_config>, the Findable reader to
19             #pod which reading is delegated will be responsible for building the assembler,
20             #pod unless a Finder subclass overrides C<build_assembler> to set a default across
21             #pod all possible delegates.
22             #pod
23             #pod =cut
24              
25 1     1   6618 use Config::MVP::Error;
  1         2  
  1         22  
26 1     1   545 use Module::Pluggable::Object;
  1         7057  
  1         34  
27 1     1   8 use Try::Tiny;
  1         2  
  1         578  
28              
29             #pod =method default_search_path
30             #pod
31             #pod This is the default search path used to find configuration readers. This
32             #pod method should return a list, and by default returns:
33             #pod
34             #pod qw( Config::MVP::Reader )
35             #pod
36             #pod =cut
37              
38             sub default_search_path {
39 1     1 1 12 return qw(Config::MVP::Reader)
40             }
41              
42             our @DONT_FIND;
43              
44             has _module_pluggable_object => (
45             is => 'ro',
46             init_arg => undef,
47             default => sub {
48             my ($self) = @_;
49             Module::Pluggable::Object->new(
50             search_path => [ $self->default_search_path ],
51             inner => 0,
52             require => 1,
53              
54             # This facility here entirely for testing. -- rjbs, 2014-07-02
55             except => \@DONT_FIND,
56             );
57             },
58             );
59              
60             sub _which_reader {
61 1     1   17 my ($self, $location) = @_;
62              
63 1         5 my @options;
64              
65 1         44 for my $pkg ($self->_module_pluggable_object->plugins) {
66 5 100       2787 next unless $pkg->isa('Moose::Object');
67 3 100       21 next unless $pkg->does('Config::MVP::Reader::Findable');
68              
69 1         358 my $location = $pkg->refined_location($location);
70              
71 1 50       4 next unless defined $location;
72              
73 1         6 push @options, [ $pkg, $location ];
74             }
75              
76 1 50       5 Config::MVP::Error->throw("no viable configuration could be found")
77             unless @options;
78              
79             # XXX: Improve this error message -- rjbs, 2010-05-24
80 1 50       5 Config::MVP::Error->throw("multiple possible config plugins found")
81             if @options > 1;
82              
83             return {
84 1         11 'package' => $options[0][0],
85             'location' => $options[0][1],
86             };
87             }
88              
89             has if_none => (
90             is => 'ro',
91             isa => 'Maybe[Str|CodeRef]',
92             );
93              
94             sub read_config {
95 1     1 1 1227 my ($self, $location, $arg) = @_;
96 1 50       41 $self = $self->new unless blessed($self);
97 1   50     368 $arg ||= {};
98              
99 1   33     7 local $arg->{assembler} = $arg->{assembler} || $self->build_assembler;
100              
101 1         2426 my $which;
102             my $instead;
103             try {
104 1     1   51 $which = $self->_which_reader($location);
105             } catch {
106 0 0   0   0 die $_ unless $_ =~ /^no viable configuration/;
107 0 0       0 die $_ unless defined (my $handler = $self->if_none);
108 0         0 $instead = $self->$handler($location, $arg);
109 1         11 };
110              
111 1 50       27 return $instead unless $which;
112              
113             my $reader = $which->{package}->new({
114 1         44 add_cwd_to_lib => $self->add_cwd_to_lib,
115             });
116              
117 1         792 return $reader->read_config( $which->{location}, $arg );
118             }
119              
120       0 1   sub build_assembler { }
121              
122             sub read_into_assembler {
123 0     0 1   confess "This method should never be called or reachable";
124             }
125              
126 1     1   10 no Moose;
  1         2  
  1         7  
127             __PACKAGE__->meta->make_immutable;
128             1;
129              
130             __END__
131              
132             =pod
133              
134             =encoding UTF-8
135              
136             =head1 NAME
137              
138             Config::MVP::Reader::Finder - a reader that finds an appropriate file
139              
140             =head1 VERSION
141              
142             version 2.200012
143              
144             =head1 DESCRIPTION
145              
146             The Finder reader multiplexes many other readers that implement the
147             L<Config::MVP::Reader::Findable> role. It uses L<Module::Pluggable> to search
148             for modules, limits them to objects implementing the Findable role, and then
149             selects the those which report that they are able to read a configuration file
150             found in the config root directory. If exactly one findable configuration
151             reader finds a file, it is used to read the file and the configuration sequence
152             is returned. Otherwise, an exception is raised.
153              
154             Config::MVP::Reader::Finder's C<build_assembler> method will decline a new
155             assembler, so if none was passed to C<read_config>, the Findable reader to
156             which reading is delegated will be responsible for building the assembler,
157             unless a Finder subclass overrides C<build_assembler> to set a default across
158             all possible delegates.
159              
160             =head1 METHODS
161              
162             =head2 default_search_path
163              
164             This is the default search path used to find configuration readers. This
165             method should return a list, and by default returns:
166              
167             qw( Config::MVP::Reader )
168              
169             =head1 AUTHOR
170              
171             Ricardo Signes <rjbs@cpan.org>
172              
173             =head1 COPYRIGHT AND LICENSE
174              
175             This software is copyright (c) 2021 by Ricardo Signes.
176              
177             This is free software; you can redistribute it and/or modify it under
178             the same terms as the Perl 5 programming language system itself.
179              
180             =cut