File Coverage

blib/lib/MouseX/Object/Pluggable.pm
Criterion Covered Total %
statement 48 50 96.0
branch 8 14 57.1
condition n/a
subroutine 10 10 100.0
pod 0 2 0.0
total 66 76 86.8


line stmt bran cond sub pod time code
1             package MouseX::Object::Pluggable;
2 5     5   118735 use 5.00800;
  5         20  
  5         269  
3             our $VERSION = '0.022';
4 5     5   30 use Carp ();
  5         11  
  5         92  
5 5     5   4686 use Mouse::Role;
  5         143465  
  5         27  
6 5     5   5626 use Module::Pluggable::Object;
  5         20  
  5         183  
7 5     5   37 use Mouse::Util;
  5         11  
  5         60  
8              
9             has _plugin_ns => (
10             is => 'rw',
11             required => 1,
12             isa => 'Str',
13             default => sub {'Plugin'},
14             );
15              
16             has _plugin_app_ns => (
17             is => 'rw',
18             required => 1,
19             isa => 'ArrayRef',
20             default => sub { [ ref shift ] },
21             );
22              
23             has _plugin_loaded => (
24             is => 'rw',
25             required => 1,
26             isa => 'HashRef',
27             default => sub { {} }
28             );
29              
30             has _plugin_locator => (
31             is => 'rw',
32             required => 1,
33             lazy => 1,
34             isa => 'Module::Pluggable::Object',
35             clearer => '_clear_plugin_locator',
36             predicate => '_has_plugin_locator',
37             builder => '_build_plugin_locator'
38             );
39              
40             sub load_plugins {
41 4     4 0 9 my ( $self, @plugins ) = @_;
42 4 50       11 die("You must provide a plugin name") unless @plugins;
43              
44 4         16 my $loaded = $self->_plugin_loaded;
45 4         8 my @load = grep { not exists $loaded->{$_} } @plugins;
  4         17  
46 4         8 my @roles = map { $self->_role_from_plugin($_) } @load;
  4         11  
47              
48 4 50       22 if ( $self->_load_and_apply_role(@roles) ) {
49 4         7 @{$loaded}{@load} = @roles;
  4         14  
50 4         26 return 1;
51             }
52             else {
53 0         0 return;
54             }
55             }
56              
57             sub load_plugin {
58 4     4 0 23 my $self = shift;
59 4         13 $self->load_plugins(@_);
60             }
61              
62             sub _role_from_plugin {
63 13     13   94 my ( $self, $plugin ) = @_;
64              
65 13 100       88 return $1 if ( $plugin =~ /^\+(.*)/ );
66              
67 6         38 my $o = join '::', $self->_plugin_ns, $plugin;
68              
69             #Father, please forgive me for I have sinned.
70 6         50 my @roles = grep {/${o}$/} $self->_plugin_locator->plugins;
  18         156  
71              
72 6 50       23 Carp::croak("Unable to locate plugin '$plugin'") unless @roles;
73 6 50       44 return $roles[0] if @roles == 1;
74 0         0 return shift @roles;
75             }
76              
77             =head2 _load_and_apply_role @roles
78              
79             Require C<$role> if it is not already loaded and apply it. This is
80             the meat of this module.
81              
82             =cut
83              
84             sub _load_and_apply_role {
85 4     4   8 my ( $self, @roles ) = @_;
86 4 50       8 die("You must provide a role name") unless @roles;
87              
88 4         9 foreach my $role (@roles) {
89 4         5 eval { Mouse::load_class($role) };
  4         16  
90 4 50       3060 confess("Failed to load role: ${role} $@") if $@;
91             }
92 4         15 Mouse::Util::apply_all_roles( ( ref $self, @roles ) );
93 4         1831 return 1;
94             }
95              
96             sub _build_plugin_locator {
97 3     3   7 my $self = shift;
98 4         45 my $locator = Module::Pluggable::Object->new(
99             search_path => [
100 3         16 map { join '::', ( $_, $self->_plugin_ns ) }
101 3         7 @{ $self->_plugin_app_ns }
102             ]
103             );
104 3         46 return $locator;
105             }
106              
107             1;
108              
109             __END__