File Coverage

blib/lib/MooX/Role/Parameterized.pm
Criterion Covered Total %
statement 89 95 93.6
branch 27 34 79.4
condition 14 21 66.6
subroutine 17 18 94.4
pod 5 6 83.3
total 152 174 87.3


line stmt bran cond sub pod time code
1             package MooX::Role::Parameterized 0.601;
2              
3 13     13   1186532 use v5.12;
  13         46  
4 13     13   72 use strict;
  13         42  
  13         457  
5 13     13   70 use warnings;
  13         22  
  13         902  
6              
7             # ABSTRACT: MooX::Role::Parameterized - roles with composition parameters
8              
9 13     13   6904 use Module::Runtime qw(use_module);
  13         26988  
  13         126  
10 13     13   943 use Carp qw(carp croak);
  13         23  
  13         888  
11 13     13   73 use Exporter qw(import);
  13         26  
  13         358  
12 13     13   4499 use Moo::Role qw();
  13         87113  
  13         299  
13 13     13   5905 use MooX::BuildClass;
  13         133426  
  13         98  
14 13     13   6882 use MooX::Role::Parameterized::Mop;
  13         38  
  13         16044  
15              
16             our @EXPORT = qw(parameter role apply apply_roles_to_target);
17              
18             our $VERBOSE = 0;
19              
20             our %INFO;
21              
22             sub apply {
23 0 0   0 1 0 carp "apply method is deprecated, please use 'apply_roles_to_target'"
24             if $VERBOSE;
25              
26 0         0 goto &apply_roles_to_target;
27             }
28              
29             sub apply_roles_to_target {
30 26     26 1 946286 my ( $role, $args, %extra ) = @_;
31              
32 26 50       162 croak
33             "unable to apply parameterized role: not an MooX::Role::Parameterized"
34             if !__PACKAGE__->is_role($role);
35              
36 26 100       129 $args = [$args] if ref($args) ne ref( [] );
37              
38 26 100       416 my $target = defined( $extra{target} ) ? $extra{target} : (caller)[0];
39              
40 26 100 66     426 if ( exists $INFO{$role}
      66        
41             && exists $INFO{$role}{code_for}
42             && ref $INFO{$role}{code_for} eq "CODE" )
43             {
44 25         179 my $mop = MooX::Role::Parameterized::Mop->new(
45             target => $target,
46             role => $role
47             );
48              
49 25         117 my $parameter_definition_klass =
50             _fetch_parameter_definition_klass($role);
51              
52 25         91 foreach my $params ( @{$args} ) {
  25         64  
53 27 100       103 if ( defined $parameter_definition_klass ) {
54 5         8 eval { $params = $parameter_definition_klass->new($params); };
  5         58  
55              
56 5 100       4010 croak(
57             "unable to apply parameterized role '${role}' to '${target}': $@"
58             ) if $@;
59             }
60              
61 26         145 $INFO{$role}{code_for}->( $params, $mop );
62             }
63             }
64              
65 25         5952 Moo::Role->apply_roles_to_package( $target, $role );
66             }
67              
68             sub role(&) { ##no critic (Subroutines::ProhibitSubroutinePrototypes)
69 14     14 1 171546 my $package = (caller)[0];
70              
71 14   100     217 $INFO{$package} ||= { is_role => 1 };
72              
73             croak "role subroutine called multiple times on '$package'"
74 14 50       48 if exists $INFO{$package}{code_for};
75              
76 14         49 $INFO{$package}{code_for} = shift;
77             }
78              
79             sub parameter {
80 5     5 1 584382 my $package = (caller)[0];
81              
82 5   50     54 $INFO{$package} ||= { is_role => 1 };
83              
84 5   50     24 push @{ $INFO{$package}{parameters_definition} ||= [] }, \@_;
  5         34  
85             }
86              
87             sub is_role {
88 47     47 1 5550 my ( $klass, $role ) = @_;
89              
90 47   66     356 return !!( $INFO{$role} && $INFO{$role}->{is_role} );
91             }
92              
93             sub build_apply_roles_to_package {
94 14     14 0 51 my ( $klass, $orig ) = @_;
95              
96             return sub {
97 15     15   558779 my $target = (caller)[0];
98              
99 15         236 while (@_) {
100 19         48 my $role = shift;
101              
102 19         37 eval { use_module($role) };
  19         1757  
103              
104 19 100       24058 if ( MooX::Role::Parameterized->is_role($role) ) {
105 16         45 my $params = [ {} ];
106              
107 16 100 66     100 if ( @_ && ref $_[0] ) {
108 13         37 $params = shift;
109              
110 13 100       56 $params = [$params] if ref($params) ne ref( [] );
111             }
112              
113 16         33 foreach my $args ( @{$params} ) {
  16         45  
114 17         794 $role->apply_roles_to_target( $args, target => $target );
115             }
116              
117 15         26175 next;
118             }
119              
120 3 100 66     54 if ( defined $orig && ref $orig eq 'CODE' ) {
121 2         9 $orig->($role);
122              
123 2         5595 next;
124             }
125              
126 1 50       6 if ( Moo::Role->is_role($role) ) {
127 0         0 Moo::Role->apply_roles_to_package( $target, $role );
128 0         0 eval {
129 0         0 Moo::Role->_maybe_reset_handlemoose($target); ##no critic(Subroutines::ProtectPrivateSubs)
130             };
131              
132 0         0 next;
133             }
134              
135 1         86 croak "Can't apply role to '${target}' - '${role}' is neither a "
136             . "MooX::Role::Parameterized, Moo::Role or Role::Tiny role";
137             }
138 14         101 };
139             }
140              
141              
142             sub _fetch_parameter_definition_klass {
143 25     25   59 my $role = shift;
144              
145 25 50       81 return if !exists $INFO{$role};
146              
147 25 100       86 if ( !exists $INFO{$role}{parameter_definition_klass} ) {
148 23 100       93 return if !exists $INFO{$role}{parameters_definition};
149              
150 3         5 my $parameters_definition = $INFO{$role}{parameters_definition};
151              
152             $INFO{$role}{parameter_definition_klass} =
153 3         10 _create_parameters_klass( $role, $parameters_definition );
154              
155 3         39 delete $INFO{$role}{parameters_definition};
156             }
157              
158 5         12 return $INFO{$role}{parameter_definition_klass};
159             }
160              
161             sub _create_parameters_klass {
162 3     3   6 my ( $package, $parameters_definition ) = @_;
163              
164 3         8 my $klass = "${package}::__MOOX_ROLE_PARAMETERIZED_PARAMS__";
165              
166 3 50       33 return $klass if $klass->isa("Moo::Object");
167              
168 3         9 my @klass_definition = ( extends => "Moo::Object" );
169              
170 3         6 foreach my $parameter_definition ( @{$parameters_definition} ) {
  3         6  
171 3         8 push @klass_definition, has => $parameter_definition;
172             }
173              
174 3         18 BuildClass $klass => @klass_definition;
175              
176 3         59341 return $klass;
177             }
178              
179             1;
180             __END__