File Coverage

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


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