File Coverage

blib/lib/Class/Component/Plugin.pm
Criterion Covered Total %
statement 75 79 94.9
branch 17 28 60.7
condition 3 5 60.0
subroutine 22 22 100.0
pod 5 6 83.3
total 122 140 87.1


line stmt bran cond sub pod time code
1             package Class::Component::Plugin;
2              
3 20     20   14447 use strict;
  20         163  
  20         839  
4 20     20   114 use warnings;
  20         42  
  20         588  
5 20     20   103 use base qw( Class::Accessor::Fast Class::Data::Inheritable );
  20         34  
  20         18359  
6              
7             __PACKAGE__->mk_accessors(qw/ config /);
8             __PACKAGE__->mk_classdata( '__attr_cache' => {} );
9             __PACKAGE__->mk_classdata( '__methods_cache' );
10              
11 20     20   71287 use Carp::Clan qw/Class::Component/;
  20         49  
  20         245  
12 20     20   3225 use Class::Inspector;
  20         45  
  20         254  
13 20     20   492 use UNIVERSAL::require;
  20         82  
  20         230  
14              
15             sub new {
16 72     72 1 181 my($class, $config, $c) = @_;
17 72         228 my $self = bless {}, $class;
18 72         460 $self->config($config);
19 72         1072 $self->init($c);
20 72         224 $self;
21             }
22              
23 72     72 1 184 sub init {}
24              
25             my %attribute_detect_cache = ();
26 72     72 1 193 sub class_component_plugin_attribute_detect_cache_enable { 1 };
27             sub class_component_plugin_attribute_detect {
28 80     80 1 159 my($self, $attr, $cache_key) = @_;
29 80         299 $attribute_detect_cache{$cache_key} = [];
30              
31 80 50       825 return unless my($key, $value) = ($attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/);
32 80 100       285 unless (defined $value) {
33 32         158 $attribute_detect_cache{$cache_key} = [$key, $value];
34 32         181 return ($key, $value);
35             }
36              
37 49         102 my $pkg = ref $self;
38             # from Attribute::Handlers
39 15     15   213 my $evaled = eval "package $pkg; no warnings; local \$SIG{__WARN__} = sub{ die \@_ }; [$value]"; ## no critic
  15     13   111  
  15     1   1203  
  13     1   83  
  13     1   27  
  13     1   786  
  49     1   3968  
        1      
        1      
40 49 50       215 $@ and croak "$pkg: $value: $@";
41 49   50     153 my $data = $evaled || [$value];
42 49 100       151 $value = (@{ $data } > 1) ? $data : $data->[0];
  49         207  
43              
44 49         182 $attribute_detect_cache{$cache_key} = [$key, $value];
45 49         385 return ($key, $value);
46             }
47              
48 173     173 1 471 sub class_component_load_attribute_resolver { }
49              
50             sub register {
51 72     72 0 134 my($self, $c) = @_;
52              
53 72 100       472 unless ($self->__methods_cache) {
54 34         313 my @methods;
55 34 50       70 for my $method (@{ Class::Inspector->methods(ref $self) || [] }) {
  34         362  
56 1245 50       38178 next unless my $code = $self->can($method);
57 1245 100       4879 next unless my $attrs = $self->__attr_cache->{$code};
58 88         1121 push @methods, { method => $method, code => $code, attrs => $attrs };
59             }
60 34         497 $self->__methods_cache( \@methods );
61             }
62              
63 72         1680 my $is_attribute_detect_cache = $self->class_component_plugin_attribute_detect_cache_enable;
64 72         239 my $class = ref $self;
65 72         129 for my $data (@{ $self->__methods_cache }) {
  72         222  
66 147         1098 for my $attr (@{ $data->{attrs} }) {
  147         413  
67 173         214 my($key, $value);
68 173         458 my $cache_key = "$class\::$attr";
69 173         526 my $attr_res = $attribute_detect_cache{$cache_key};
70 173 100 66     859 if ($is_attribute_detect_cache && $attr_res) {
71 94         343 ($key, $value) = ( $attr_res->[0], $attr_res->[1] );
72             } else {
73 79 50       226 next unless ($key, $value) = $self->class_component_plugin_attribute_detect($attr, $cache_key);
74             }
75              
76 172         280 my $attr_class;
77 172 50       483 if (my $pkg = $self->class_component_load_attribute_resolver($key)) {
78 0 0       0 $pkg->require or croak $@;
79 0         0 $attr_class = $pkg;
80             } else {
81 172         6726 $attr_class = Class::Component::Implement->pkg_require($c => "Attribute::$key");
82             }
83 172 50       534 unless ($attr_class) {
84 0 0       0 next unless $@;
85 0         0 croak "'$key' is not supported attribute";
86             }
87 172         919 $attr_class->register($self, $c, $data->{method}, $value, $data->{code});
88             }
89             }
90             }
91              
92             sub MODIFY_CODE_ATTRIBUTES {
93 99     100   73551 my($class, $code, @attrs) = @_;
94 99         665 $class->__attr_cache->{$code} = [@attrs];
95 99         1168 return ();
96             }
97              
98             1;
99             __END__