File Coverage

blib/lib/Plugin/Loader.pm
Criterion Covered Total %
statement 33 33 100.0
branch 4 4 100.0
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 46 46 100.0


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