File Coverage

blib/lib/Module/Loader.pm
Criterion Covered Total %
statement 40 40 100.0
branch 6 6 100.0
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 57 57 100.0


line stmt bran cond sub pod time code
1             package Module::Loader;
2             $Module::Loader::VERSION = '0.02';
3 4     4   51160 use 5.006;
  4         11  
  4         128  
4 4     4   2851 use Moo;
  4         47926  
  4         20  
5 4     4   7903 use Path::Iterator::Rule;
  4         44520  
  4         153  
6 4     4   502 use File::Spec::Functions qw/ catfile splitdir /;
  4         623  
  4         237  
7 4     4   17 use Carp qw/ croak /;
  4         5  
  4         1345  
8              
9             has 'max_depth' => (is => 'rw', clearer => 1);
10              
11             sub find_modules
12             {
13 7     7 1 3272 my ($self, $base) = @_;
14 7         30 my @baseparts = split(/::/, $base);
15 7         9 my %modules;
16              
17 7         16 foreach my $directory (@INC) {
18 84         250 my $path = catfile($directory, @baseparts);
19 84 100       2831 next unless -d $path;
20              
21 7         49 my $rule = Path::Iterator::Rule->new->perl_module;
22 7 100       1082 $rule->max_depth($self->max_depth) if $self->max_depth;
23              
24 7         98 foreach my $file ($rule->all($path)) {
25 17         5878 (my $modpath = $file) =~ s!^\Q$directory\E.|\.pm$!!g;
26              
27 17         43 my $module = join('::', splitdir($modpath));
28              
29             # Using a hash means that even if a module is installed
30             # in more than one place, it will only be reported once
31 17         281 $modules{ $module }++;
32             }
33             }
34              
35 7         34 return keys(%modules);
36             }
37              
38             sub search
39             {
40 3     3 1 2347 my $self = shift;
41 3         13 my $max_depth = $self->max_depth;
42              
43 3         8 $self->max_depth(1);
44              
45 3         7 my @modules = $self->find_modules(@_);
46              
47 3 100       9 if (defined $max_depth) {
48 2         6 $self->max_depth($max_depth);
49             }
50             else {
51 1         5 $self->clear_max_depth();
52             }
53              
54 3         360 return @modules;
55             }
56              
57             sub load
58             {
59 2     2 1 1447 my ($self, @modules) = @_;
60              
61 2         12 require Module::Runtime;
62 2         5 foreach my $module (@modules) {
63 2         8 Module::Runtime::require_module($module);
64             }
65             }
66              
67             1;
68              
69             =encoding utf8
70              
71             =head1 NAME
72              
73             Module::Loader - finding and loading modules in a given namespace
74              
75             =head1 SYNOPSIS
76              
77             use Module::Loader;
78              
79             my $loader = Module::Loader->new;
80             my @plugins = $loader->find_modules('MyApp::Plugin');
81              
82             foreach my $plugin (@plugins) {
83             $loader->load($plugin);
84             }
85              
86             =head1 DESCRIPTION
87              
88             This module provides methods for finding modules in a given namespace,
89             and then loading them. It is intended for use in situations where
90             you're looking for plugins, and then loading one or more of them.
91              
92             This module was inspired by L, which I have used in
93             a number of projects. But some people were wary of requiring L
94             just to get a module loader, which prompted me to create C.
95              
96             Note: this module was initially called C, but I realised
97             that C was a more appropriate name.
98              
99             =head2 max_depth
100              
101             C has an optional C attribute.
102             If you set this to 1, then C will only report modules
103             that are immediately within the namespace specified.
104              
105             Let's say you have all of the CPAN plugins for the template toolkit
106             installed locally. If you don't specify C, then C
107             would return L
108             as well as L. If you set C to 1,
109             then you'd get the latter but not the former.
110              
111             Why might you want to do that?
112              
113             You might have a convention where plugins are the modules immediately
114             within the specified namespace, but that each plugin can have additional
115             modules within its own namespace.
116              
117             So typically you'll either not set C, or you'll set it to 1.
118              
119             =head1 METHODS
120              
121             =head2 find_modules
122              
123             Takes a namespace, and returns all installed modules in that namespace,
124             that were found in C<@INC>. For example:
125              
126             @plugins = $loader->find_modules('Template::Plugin');
127              
128             By default this will find all modules in the given namespace,
129             unless you've specified a maximum search depth, as described above.
130              
131             =head2 search
132              
133             This is the same as C above, but it hard-codes the search depth
134             to 1. This method is provided for compatibility with M:
135              
136             @plugins = $loader->search('Template::Plugin');
137              
138             It preserves your current setting of the C attribute,
139             in the unlikely event that you want to interleave calls to C
140             and C.
141              
142             =head2 load
143              
144             Takes a module name and tries to load the module.
145             If loading fails, then we C.
146              
147             =head1 SEE ALSO
148              
149             L was the inspiration for this module, but has
150             a slightly different interface. In particular, it has C
151             hard-coded to 1.
152              
153             L is effectively a role which gives a class the ability
154             to find plugins within its namespace.
155              
156             L is similar to L,
157             but lets you control the order in which modules are loaded.
158              
159             L will load all modules in a given namespace, eg with C
160              
161             L will load all modules found in a given I
162             (as opposed to a namespace).
163              
164             L provides functions for loading modules,
165             but not for finding them.
166              
167             L provides a number of functions for finding and loading
168             modules. It provides different functions depending on whether you want
169             to limit the search depth to 1 or not: C vs C.
170              
171             L will load all modules in a given namespace,
172             and return a list of the modules found / loaded.
173             It lets you provide regexps for filtering out certain namespaces.
174              
175             L provides two functions, C
176             and C which will load all locally installed modules
177             whose name matches a pattern (specified as a regular expression
178             or glob-style pattern).
179              
180             =head1 REPOSITORY
181              
182             L
183              
184             =head1 AUTHOR
185              
186             Neil Bowers Eneilb@cpan.orgE
187              
188             =head1 COPYRIGHT AND LICENSE
189              
190             This software is copyright (c) 2014 by Neil Bowers .
191              
192             This is free software; you can redistribute it and/or modify it under
193             the same terms as the Perl 5 programming language system itself.
194              
195             =cut
196