line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::Component; |
2
|
|
|
|
|
|
|
|
3
|
20
|
|
|
20
|
|
28492
|
use strict; |
|
20
|
|
|
|
|
43
|
|
|
20
|
|
|
|
|
694
|
|
4
|
20
|
|
|
20
|
|
104
|
use warnings; |
|
20
|
|
|
|
|
64
|
|
|
20
|
|
|
|
|
1055
|
|
5
|
|
|
|
|
|
|
our $VERSION = '0.17'; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
for my $method (qw/ load_components load_plugins new register_method register_hook remove_method remove_hook call run_hook NEXT /) { |
8
|
20
|
|
|
20
|
|
102
|
no strict 'refs'; |
|
20
|
|
|
|
|
35
|
|
|
20
|
|
|
|
|
2426
|
|
9
|
529
|
|
|
529
|
|
55849
|
*{__PACKAGE__."::$method"} = sub { Class::Component::Implement->$method(@_) }; |
10
|
|
|
|
|
|
|
} |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
for my $name (qw/ config components plugins methods hooks /) { |
13
|
|
|
|
|
|
|
my $method = "class_component_$name"; |
14
|
20
|
|
|
20
|
|
113
|
no strict 'refs'; |
|
20
|
|
|
|
|
43
|
|
|
20
|
|
|
|
|
3484
|
|
15
|
|
|
|
|
|
|
*{__PACKAGE__."::$method"} = sub { |
16
|
531
|
50
|
|
531
|
|
1341
|
$_[0]->{"_$method"} = $_[1] if $_[1]; |
17
|
531
|
|
|
|
|
13262
|
$_[0]->{"_$method"} |
18
|
|
|
|
|
|
|
}; |
19
|
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub import { |
22
|
38
|
|
|
38
|
|
472
|
my($class, %args) = @_; |
23
|
38
|
100
|
|
|
|
33187
|
return unless $class eq 'Class::Component'; |
24
|
20
|
|
|
|
|
84
|
my $pkg = caller(0); |
25
|
|
|
|
|
|
|
|
26
|
20
|
50
|
|
|
|
537
|
unless ($pkg->isa('Class::Component')) { |
27
|
20
|
|
|
20
|
|
134
|
no strict 'refs'; |
|
20
|
|
|
|
|
38
|
|
|
20
|
|
|
|
|
6904
|
|
28
|
20
|
|
|
|
|
44
|
unshift @{"$pkg\::ISA"}, $class; |
|
20
|
|
|
|
|
340
|
|
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
20
|
|
|
|
|
175
|
Class::Component::Implement->init($pkg, %args); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
25
|
|
|
25
|
1
|
128
|
sub class_component_load_component_resolver {} |
35
|
70
|
|
|
70
|
1
|
306
|
sub class_component_load_plugin_resolver {} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub class_component_reinitialize { |
38
|
2
|
|
|
2
|
1
|
44
|
my($class, %args) = @_; |
39
|
2
|
|
|
|
|
24
|
Class::Component::Implement->init($class, %args); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub class_component_clear_isa_list { |
43
|
3
|
|
|
3
|
0
|
6
|
my $class = shift; |
44
|
|
|
|
|
|
|
|
45
|
3
|
|
66
|
|
|
34
|
my $klass = $_[0] || ref($class) || $class; |
46
|
3
|
|
|
|
|
17
|
my $isa_list = Class::Component::Implement->component_isa_list; |
47
|
3
|
|
|
|
|
5
|
for my $key (keys %{ $isa_list }) { |
|
3
|
|
|
|
|
13
|
|
48
|
15
|
100
|
100
|
|
|
184
|
delete $isa_list->{$key} if $key =~ /^$klass-/ || $key eq $klass; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
3
|
|
|
|
|
15
|
my $pkg_require_cache = Class::Component::Implement->pkg_require_cache; |
52
|
3
|
|
|
|
|
4
|
for my $key (keys %{ $pkg_require_cache }) { |
|
3
|
|
|
|
|
12
|
|
53
|
11
|
50
|
33
|
|
|
91
|
delete $pkg_require_cache->{$key} if $key =~ /^$klass\::/ || $key eq $klass; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
package # hide from PAUSE |
58
|
|
|
|
|
|
|
Class::Component::Implement; |
59
|
|
|
|
|
|
|
|
60
|
20
|
|
|
20
|
|
134
|
use strict; |
|
20
|
|
|
|
|
36
|
|
|
20
|
|
|
|
|
626
|
|
61
|
20
|
|
|
20
|
|
138
|
use warnings; |
|
20
|
|
|
|
|
59
|
|
|
20
|
|
|
|
|
730
|
|
62
|
20
|
|
|
20
|
|
125
|
use base qw( Class::Data::Inheritable ); |
|
20
|
|
|
|
|
51
|
|
|
20
|
|
|
|
|
20666
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
my $component_isa_list = {}; |
65
|
|
|
|
|
|
|
my $default_components = {}; |
66
|
|
|
|
|
|
|
my $default_plugins = {}; |
67
|
|
|
|
|
|
|
my $default_configs = {}; |
68
|
|
|
|
|
|
|
my $reload_plugin_maps = {}; |
69
|
|
|
|
|
|
|
|
70
|
20
|
|
|
20
|
|
25324
|
use UNIVERSAL::require; |
|
20
|
|
|
|
|
34282
|
|
|
20
|
|
|
|
|
222
|
|
71
|
|
|
|
|
|
|
|
72
|
20
|
|
|
20
|
|
28892
|
use Carp::Clan qw/Class::Component/; |
|
20
|
|
|
|
|
93386
|
|
|
20
|
|
|
|
|
158
|
|
73
|
20
|
|
|
20
|
|
34845
|
use Class::Inspector; |
|
20
|
|
|
|
|
101521
|
|
|
20
|
|
|
|
|
468
|
|
74
|
|
|
|
|
|
|
|
75
|
106
|
|
|
106
|
|
425
|
sub component_isa_list { $component_isa_list } |
76
|
15
|
|
|
15
|
|
4807
|
sub default_components { $default_components } |
77
|
3
|
|
|
3
|
|
11
|
sub default_plugins { $default_plugins } |
78
|
6
|
|
|
6
|
|
131
|
sub default_configs { $default_configs } |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub init { |
81
|
22
|
|
|
22
|
|
159
|
my($class, $c, %args) = @_; |
82
|
22
|
|
|
|
|
89
|
$c = $class->_class($c); |
83
|
|
|
|
|
|
|
|
84
|
22
|
|
100
|
|
|
168
|
$default_components->{$c} ||= []; |
85
|
22
|
|
100
|
|
|
123
|
$default_plugins->{$c} ||= []; |
86
|
22
|
50
|
|
|
|
84
|
$default_configs->{$c} = delete $args{config} if defined $args{config}; |
87
|
|
|
|
|
|
|
|
88
|
22
|
|
|
|
|
51
|
delete $reload_plugin_maps->{$c}; |
89
|
22
|
100
|
|
|
|
864
|
$reload_plugin_maps->{$c} = \&_reload_plugin if $args{reload_plugin}; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub shared_configs { |
93
|
0
|
|
|
0
|
|
0
|
my($class, $from, $to) = @_; |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
0
|
$default_components->{$to} = $default_components->{$from}; |
96
|
0
|
|
|
|
|
0
|
$default_plugins->{$to} = $default_plugins->{$from}; |
97
|
0
|
|
|
|
|
0
|
$reload_plugin_maps->{$to} = $reload_plugin_maps->{$from}; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub load_components { |
101
|
22
|
|
|
22
|
|
76
|
my($class, $c, @components) = @_; |
102
|
|
|
|
|
|
|
|
103
|
22
|
|
|
|
|
65
|
for my $component (@components) { |
104
|
25
|
|
|
|
|
118
|
$class->_load_component($c, $component); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub _load_component { |
109
|
27
|
|
|
27
|
|
67
|
my($class, $c, $component, $reload) = @_; |
110
|
27
|
|
|
|
|
117
|
$c = $class->_class($c); |
111
|
|
|
|
|
|
|
|
112
|
27
|
|
|
|
|
52
|
my $pkg; |
113
|
27
|
100
|
66
|
|
|
296
|
if (($pkg = $component) =~ s/^\+// || ($pkg = $c->class_component_load_component_resolver($component))) { |
114
|
2
|
50
|
|
|
|
19
|
$pkg->require or croak $@; |
115
|
|
|
|
|
|
|
} else { |
116
|
25
|
50
|
|
|
|
142
|
unless ($pkg = $class->pkg_require($c => "Component::$component")) { |
117
|
0
|
0
|
|
|
|
0
|
$@ and croak $@; |
118
|
0
|
|
|
|
|
0
|
croak "$component is not installed"; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
27
|
100
|
|
|
|
146
|
unless ($reload) { |
123
|
25
|
|
|
|
|
41
|
for my $default (@{ $default_components->{$c} }) { |
|
25
|
|
|
|
|
105
|
|
124
|
10
|
100
|
|
|
|
58
|
return if $pkg eq $default; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
20
|
|
|
20
|
|
9716
|
no strict 'refs'; |
|
20
|
|
|
|
|
56
|
|
|
20
|
|
|
|
|
46896
|
|
129
|
25
|
|
|
|
|
48
|
unshift @{"$c\::ISA"}, $pkg; |
|
25
|
|
|
|
|
463
|
|
130
|
25
|
|
|
|
|
118
|
for my $isa_pkg (@{ $class->isa_list($c) }) { |
|
25
|
|
|
|
|
176
|
|
131
|
93
|
|
|
|
|
147
|
my $key = $c; |
132
|
93
|
|
|
|
|
110
|
my $from; |
133
|
93
|
100
|
|
|
|
407
|
unless ($c eq $isa_pkg) { |
134
|
68
|
|
|
|
|
147
|
$key .= "-$isa_pkg"; |
135
|
68
|
|
|
|
|
140
|
$from = $isa_pkg; |
136
|
|
|
|
|
|
|
} |
137
|
93
|
|
|
|
|
241
|
$class->component_isa_list->{$key} = $class->isa_list($c, $from); |
138
|
|
|
|
|
|
|
} |
139
|
25
|
100
|
|
|
|
113
|
push @{ $default_components->{$c} }, $pkg unless $reload; |
|
23
|
|
|
|
|
66
|
|
140
|
25
|
100
|
|
|
|
572
|
$pkg->class_component_load_component_init($c) if $pkg->can('class_component_load_component_init'); |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub load_plugins { |
144
|
65
|
|
|
65
|
|
186
|
my($class, $c, @plugins) = @_; |
145
|
|
|
|
|
|
|
|
146
|
65
|
100
|
|
|
|
259
|
return $class->load_plugins_default($c, @plugins) unless ref $c; |
147
|
|
|
|
|
|
|
|
148
|
46
|
|
|
|
|
111
|
for my $plugin (@plugins) { |
149
|
67
|
|
|
|
|
258
|
$class->_load_plugin($c, $plugin); |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub load_plugins_default { |
154
|
25
|
|
|
25
|
|
60
|
my($class, $c, @plugins) = @_; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
LOOP: |
157
|
25
|
|
|
|
|
62
|
for my $plugin (@plugins) { |
158
|
25
|
|
|
|
|
35
|
for my $default (@{ $default_plugins->{$c} }) { |
|
25
|
|
|
|
|
76
|
|
159
|
7
|
100
|
|
|
|
39
|
next LOOP if $plugin eq $default; |
160
|
|
|
|
|
|
|
} |
161
|
22
|
|
|
|
|
42
|
push @{ $default_plugins->{$c} }, $plugin; |
|
22
|
|
|
|
|
133
|
|
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub _load_plugin { |
166
|
79
|
|
|
79
|
|
161
|
my($class, $c, $plugin) = @_; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# config option support |
169
|
79
|
|
|
|
|
584
|
my $config; |
170
|
79
|
100
|
|
|
|
255
|
if (ref($plugin) eq 'HASH') { |
171
|
8
|
|
100
|
|
|
38
|
$config = $plugin->{config} || {}; |
172
|
8
|
|
|
|
|
225
|
$plugin = $plugin->{module}; |
173
|
|
|
|
|
|
|
} |
174
|
79
|
50
|
|
|
|
199
|
return unless $plugin; |
175
|
|
|
|
|
|
|
|
176
|
79
|
|
|
|
|
126
|
my $pkg; |
177
|
79
|
100
|
66
|
|
|
942
|
if (($pkg = $plugin) =~ s/^\+// || ($pkg = $c->class_component_load_plugin_resolver($plugin))) { |
178
|
9
|
50
|
|
|
|
119
|
$pkg->require or croak $@; |
179
|
|
|
|
|
|
|
} else { |
180
|
70
|
50
|
|
|
|
334
|
unless ($pkg = $class->pkg_require($c => "Plugin::$plugin")) { |
181
|
0
|
0
|
|
|
|
0
|
$@ and croak $@; |
182
|
0
|
|
|
|
|
0
|
croak "$plugin is not installed"; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
79
|
|
|
|
|
1521
|
my $class_component_plugins = $c->class_component_plugins; |
187
|
79
|
100
|
|
|
|
258
|
unless ($config) { |
188
|
71
|
|
|
|
|
109
|
for my $default (@{ $class_component_plugins }) { |
|
71
|
|
|
|
|
210
|
|
189
|
39
|
100
|
|
|
|
217
|
return if $pkg eq ref($default); |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
71
|
|
100
|
|
|
562
|
my $obj = $pkg->new($config || $c->class_component_config->{$plugin} || {}, $c); |
194
|
71
|
|
|
|
|
120
|
push @{ $class_component_plugins }, $obj; |
|
71
|
|
|
|
|
155
|
|
195
|
71
|
|
|
|
|
373
|
$obj->register($c); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub new { |
199
|
40
|
|
|
40
|
|
118
|
my($class, $c, $args) = @_; |
200
|
40
|
|
100
|
|
|
224
|
$args ||= {}; |
201
|
|
|
|
|
|
|
|
202
|
40
|
|
|
|
|
894
|
my $self = bless { |
203
|
40
|
|
100
|
|
|
78
|
%{ $args }, |
204
|
|
|
|
|
|
|
_class_component_plugins => [], |
205
|
|
|
|
|
|
|
_class_component_components => $default_components->{$c}, |
206
|
|
|
|
|
|
|
_class_component_methods => {}, |
207
|
|
|
|
|
|
|
_class_component_hooks => {}, |
208
|
|
|
|
|
|
|
_class_component_config => $args->{config} || $default_configs->{$c} || {}, |
209
|
|
|
|
|
|
|
_class_component_default_plugins => $default_plugins->{$c}, |
210
|
|
|
|
|
|
|
}, $c; |
211
|
|
|
|
|
|
|
|
212
|
40
|
100
|
|
|
|
98
|
$self->load_plugins(@{ $default_plugins->{$c} }, @{ $args->{load_plugins} || [] }); |
|
40
|
|
|
|
|
107
|
|
|
40
|
|
|
|
|
345
|
|
213
|
|
|
|
|
|
|
|
214
|
40
|
|
|
|
|
272
|
$self; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub register_method { |
218
|
108
|
|
|
108
|
|
277
|
my($class, $c, @methods) = @_; |
219
|
108
|
|
|
|
|
497
|
while (my($method, $plugin) = splice @methods, 0, 2) { |
220
|
108
|
|
|
|
|
402
|
$c->class_component_methods->{$method} = $plugin |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub register_hook { |
225
|
38
|
|
|
38
|
|
102
|
my($class, $c, @hooks) = @_; |
226
|
38
|
|
|
|
|
168
|
while (my($hook, $obj) = splice @hooks, 0, 3) { |
227
|
38
|
100
|
|
|
|
154
|
$c->class_component_hooks->{$hook} = [] unless $c->class_component_hooks->{$hook}; |
228
|
38
|
|
|
|
|
61
|
push @{ $c->class_component_hooks->{$hook} }, $obj; |
|
38
|
|
|
|
|
171
|
|
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub remove_method { |
233
|
4
|
|
|
4
|
|
11
|
my($class, $c, @methods) = @_; |
234
|
4
|
|
|
|
|
22
|
while (my($method, $plugin) = splice @methods, 0, 2) { |
235
|
5
|
100
|
|
|
|
11
|
next unless ref($c->class_component_methods->{$method}) eq $plugin; |
236
|
2
|
|
|
|
|
7
|
delete $c->class_component_methods->{$method}; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub remove_hook { |
241
|
2
|
|
|
2
|
|
8
|
my($class, $c, @hooks) = @_; |
242
|
2
|
|
|
|
|
13
|
while (my($hook, $remove_obj) = splice @hooks, 0, 3) { |
243
|
2
|
|
|
|
|
14
|
my $i = -1; |
244
|
2
|
|
|
|
|
5
|
for my $obj (@{ $c->class_component_hooks->{$hook} }) { |
|
2
|
|
|
|
|
110
|
|
245
|
2
|
|
|
|
|
4
|
$i++; |
246
|
2
|
50
|
33
|
|
|
22
|
next unless ref($obj->{plugin}) eq $remove_obj->{plugin} && $obj->{method} eq $remove_obj->{method}; |
247
|
2
|
|
|
|
|
4
|
splice @{ $c->class_component_hooks->{$hook} }, $i, 1; |
|
2
|
|
|
|
|
5
|
|
248
|
|
|
|
|
|
|
} |
249
|
2
|
50
|
|
|
|
7
|
delete $c->class_component_hooks->{$hook} unless @{ $c->class_component_hooks->{$hook} }; |
|
2
|
|
|
|
|
7
|
|
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub call { |
254
|
125
|
|
|
125
|
|
328
|
my($class, $c, $method, @args) = @_; |
255
|
125
|
100
|
|
|
|
364
|
return unless my $plugin = $c->class_component_methods->{$method}; |
256
|
106
|
100
|
|
|
|
392
|
if (ref $plugin eq 'HASH') { |
257
|
|
|
|
|
|
|
# extend method |
258
|
10
|
|
|
|
|
57
|
my $obj = $plugin; |
259
|
10
|
|
|
|
|
21
|
$plugin = $obj->{plugin}; |
260
|
10
|
|
|
|
|
23
|
my $real_method = $obj->{method}; |
261
|
10
|
50
|
33
|
|
|
103
|
return unless $plugin && $real_method; |
262
|
10
|
|
|
|
|
47
|
$class->reload_plugin($c, $plugin); |
263
|
10
|
100
|
|
|
|
151
|
if (ref $real_method eq 'CODE') { |
|
|
50
|
|
|
|
|
|
264
|
4
|
|
|
|
|
209
|
$real_method->($plugin, $c, @args); |
265
|
|
|
|
|
|
|
} elsif (!ref($real_method)) { |
266
|
6
|
|
|
|
|
23
|
$plugin->$real_method($c, @args); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
} else { |
269
|
96
|
|
|
|
|
311
|
$class->reload_plugin($c, $plugin); |
270
|
96
|
|
|
|
|
706
|
$plugin->$method($c, @args); |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
sub run_hook { |
275
|
63
|
|
|
63
|
|
156
|
my($class, $c, $hook, $args) = @_; |
276
|
63
|
100
|
|
|
|
212
|
return unless my $hooks = $c->class_component_hooks->{$hook}; |
277
|
54
|
|
|
|
|
422
|
$class->reload_plugin($c, $hooks->[0]->{plugin}); |
278
|
|
|
|
|
|
|
|
279
|
54
|
|
|
|
|
197
|
my @ret; |
280
|
54
|
|
|
|
|
85
|
for my $obj (@{ $hooks }) { |
|
54
|
|
|
|
|
133
|
|
281
|
62
|
|
|
|
|
212
|
my($plugin, $method) = ($obj->{plugin}, $obj->{method}); |
282
|
62
|
|
|
|
|
256
|
my $ret = $plugin->$method($c, $args); |
283
|
62
|
|
|
|
|
649
|
push @ret, $ret; |
284
|
|
|
|
|
|
|
} |
285
|
54
|
|
|
|
|
370
|
\@ret; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub _reload_plugin { |
289
|
14
|
|
|
14
|
|
22
|
my($class, $c, $pkg) = @_; |
290
|
14
|
100
|
|
|
|
37
|
return if Class::Inspector->loaded($class->_class($pkg)); |
291
|
|
|
|
|
|
|
|
292
|
4
|
|
|
|
|
353
|
$default_components->{$class->_class($c)} = $c->class_component_components; |
293
|
4
|
|
|
|
|
21
|
$default_plugins->{$class->_class($c)} = $c->class_component_plugins; |
294
|
|
|
|
|
|
|
|
295
|
4
|
|
|
|
|
9
|
for my $component (@{ $default_components->{$class->_class($c)} }) { |
|
4
|
|
|
|
|
12
|
|
296
|
2
|
|
|
|
|
5
|
$class->_load_component($c, '+' . $class->_class($component), 1); |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
4
|
|
|
|
|
16
|
for my $plugin (@{ $c->class_component_plugins }) { |
|
4
|
|
|
|
|
18
|
|
300
|
6
|
|
|
|
|
17
|
$class->_load_plugin($c, '+' . $class->_class($plugin)); |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub reload_plugin { |
306
|
160
|
|
|
160
|
|
273
|
my($class, $c) = @_; |
307
|
160
|
100
|
|
|
|
488
|
return unless my $code = $reload_plugin_maps->{$class->_class($c)}; |
308
|
14
|
|
|
|
|
47
|
goto $code; |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub NEXT { |
312
|
62
|
|
|
62
|
|
161
|
my($class, $c, $method, @args) = @_; |
313
|
62
|
|
66
|
|
|
199
|
my $klass = ref $c || $c; |
314
|
62
|
|
|
|
|
134
|
my $caller = caller(1); |
315
|
|
|
|
|
|
|
|
316
|
62
|
|
66
|
|
|
284
|
my $isa_list_cache = $component_isa_list->{"$klass-$caller"} || $class->isa_list_cache($c, $caller); |
317
|
62
|
|
|
|
|
89
|
my @isa = @{ $isa_list_cache }; |
|
62
|
|
|
|
|
169
|
|
318
|
|
|
|
|
|
|
|
319
|
62
|
|
|
|
|
133
|
for my $pkg (@isa) { |
320
|
67
|
100
|
|
|
|
615
|
next unless $pkg->can($method);; |
321
|
42
|
|
|
|
|
109
|
my $next = "$pkg\::$method"; |
322
|
42
|
|
|
|
|
182
|
return $c->$next(@args); |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
20
|
|
|
|
|
46
|
for my $pkg (@isa) { |
326
|
22
|
50
|
|
|
|
252
|
next unless $pkg->can('AUTOLOAD'); |
327
|
0
|
|
|
|
|
0
|
my $next = "$pkg\::$method"; |
328
|
0
|
|
|
|
|
0
|
return $c->$next(@args); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub isa_list_cache { |
333
|
135
|
|
|
135
|
|
246
|
my($class, $c, $from) = @_; |
334
|
135
|
|
66
|
|
|
589
|
my $key = ref $c || $c; |
335
|
135
|
100
|
|
|
|
351
|
$key .= "-$from" if $from; |
336
|
135
|
100
|
|
|
|
512
|
$component_isa_list->{$key} = $class->isa_list($c, $from) unless $component_isa_list->{$key}; |
337
|
135
|
|
|
|
|
642
|
$component_isa_list->{$key}; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub isa_list { |
341
|
145
|
|
|
145
|
|
273
|
my($class, $c, $from) = @_; |
342
|
145
|
|
66
|
|
|
593
|
$c = ref $c || $c; |
343
|
|
|
|
|
|
|
|
344
|
145
|
|
|
|
|
406
|
my $isa_list = $class->_fetch_isa_list($c); |
345
|
145
|
|
|
|
|
378
|
my $isa_mark = {}; |
346
|
145
|
|
|
|
|
461
|
$class->_mark_isa_list($isa_list, $isa_mark, 0); |
347
|
145
|
|
|
|
|
509
|
my @isa = $class->_sort_isa_list($isa_list, $isa_mark, 0); |
348
|
|
|
|
|
|
|
|
349
|
145
|
|
|
|
|
238
|
my @next_classes; |
350
|
145
|
|
|
|
|
210
|
my $f = 0; |
351
|
145
|
100
|
|
|
|
336
|
$f = 1 unless $from; |
352
|
145
|
|
|
|
|
237
|
for my $pkg (@isa) { |
353
|
574
|
100
|
|
|
|
1003
|
if ($f) { |
354
|
325
|
|
|
|
|
674
|
push @next_classes, $pkg; |
355
|
|
|
|
|
|
|
} else { |
356
|
249
|
100
|
|
|
|
786
|
next unless $pkg eq $from; |
357
|
77
|
|
|
|
|
179
|
$f = 1; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
} |
360
|
145
|
|
|
|
|
1440
|
\@next_classes; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub _fetch_isa_list { |
364
|
622
|
|
|
622
|
|
1878
|
my($class, $base) = @_; |
365
|
|
|
|
|
|
|
|
366
|
622
|
|
|
|
|
1803
|
my $isa_list = { pkg => $base, isa => [] }; |
367
|
20
|
|
|
20
|
|
170
|
no strict 'refs'; |
|
20
|
|
|
|
|
48
|
|
|
20
|
|
|
|
|
20205
|
|
368
|
622
|
|
|
|
|
827
|
for my $pkg (@{"$base\::ISA"}) { |
|
622
|
|
|
|
|
2432
|
|
369
|
477
|
|
|
|
|
559
|
push @{ $isa_list->{isa} }, $class->_fetch_isa_list($pkg); |
|
477
|
|
|
|
|
1494
|
|
370
|
|
|
|
|
|
|
} |
371
|
622
|
|
|
|
|
1761
|
$isa_list; |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub _mark_isa_list { |
375
|
622
|
|
|
622
|
|
941
|
my($class, $isa_list, $isa_mark, $nest) = @_; |
376
|
|
|
|
|
|
|
|
377
|
622
|
|
|
|
|
5839
|
for my $list (@{ $isa_list->{isa} }) { |
|
622
|
|
|
|
|
1303
|
|
378
|
477
|
|
|
|
|
1769
|
$class->_mark_isa_list($list, $isa_mark, $nest + 1); |
379
|
|
|
|
|
|
|
} |
380
|
622
|
|
|
|
|
1127
|
my $pkg = $isa_list->{pkg}; |
381
|
622
|
100
|
66
|
|
|
3101
|
$isa_mark->{$pkg} = { nest => $nest, count => 0 } if !$isa_mark->{$pkg} || $isa_mark->{$pkg}->{nest} < $nest; |
382
|
622
|
|
|
|
|
14634
|
$isa_mark->{$pkg}->{count}++; |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub _sort_isa_list { |
386
|
622
|
|
|
622
|
|
1194
|
my($class, $isa_list, $isa_mark, $nest) = @_; |
387
|
|
|
|
|
|
|
|
388
|
622
|
|
|
|
|
695
|
my @isa; |
389
|
622
|
|
|
|
|
1389
|
my $pkg = $isa_list->{pkg}; |
390
|
622
|
100
|
|
|
|
1731
|
unless (--$isa_mark->{$pkg}->{count}) { |
391
|
574
|
|
|
|
|
851
|
push @isa, $pkg; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
622
|
|
|
|
|
683
|
for my $list (@{ $isa_list->{isa} }) { |
|
622
|
|
|
|
|
1307
|
|
395
|
477
|
|
|
|
|
1515
|
my @ret = $class->_sort_isa_list($list, $isa_mark, $nest + 1); |
396
|
477
|
|
|
|
|
1194
|
push @isa, @ret; |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
622
|
|
|
|
|
1993
|
@isa; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub _class { |
403
|
243
|
|
|
243
|
|
418
|
my($class, $c) = @_; |
404
|
243
|
100
|
|
|
|
1415
|
ref($c) || $c; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
my $pkg_require_cache = {}; |
408
|
3
|
|
|
3
|
|
6
|
sub pkg_require_cache { $pkg_require_cache } |
409
|
0
|
|
|
0
|
|
0
|
sub pkg_require_cache_clear { $pkg_require_cache = {} } |
410
|
|
|
|
|
|
|
sub pkg_require { |
411
|
267
|
|
|
267
|
|
539
|
my($class, $c, $pkg) = @_; |
412
|
267
|
|
66
|
|
|
869
|
$c = ref $c || $c; |
413
|
|
|
|
|
|
|
|
414
|
267
|
|
|
|
|
346
|
my $isa_list; |
415
|
267
|
100
|
|
|
|
876
|
if ($isa_list = $component_isa_list->{$c}) { |
416
|
249
|
100
|
|
|
|
782
|
if (my $cache = $pkg_require_cache->{$pkg}) { |
417
|
181
|
100
|
|
|
|
296
|
if ($cache->{isa_list} eq join('-', @{ $isa_list })) { |
|
181
|
|
|
|
|
802
|
|
418
|
141
|
|
|
|
|
600
|
return $cache->{pkg}; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
} |
422
|
126
|
|
100
|
|
|
433
|
$isa_list ||= []; |
423
|
|
|
|
|
|
|
|
424
|
126
|
|
|
|
|
208
|
my $obj = { isa_list => join('-', @{ $isa_list }) }; |
|
126
|
|
|
|
|
592
|
|
425
|
126
|
|
|
|
|
362
|
$pkg_require_cache->{$pkg} = $obj; |
426
|
126
|
|
|
|
|
237
|
for my $isa_pkg (@{ $class->isa_list_cache($c) }) { |
|
126
|
|
|
|
|
458
|
|
427
|
232
|
50
|
|
|
|
34624
|
unless ($isa_list) { |
428
|
0
|
|
|
|
|
0
|
$isa_list = $component_isa_list->{$c}; |
429
|
0
|
|
|
|
|
0
|
$obj->{isa_list} = join('-', @{ $isa_list }); |
|
0
|
|
|
|
|
0
|
|
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
232
|
|
|
|
|
570
|
my $new_pkg = "$isa_pkg\::$pkg"; |
433
|
232
|
100
|
|
|
|
1134
|
next unless Class::Inspector->installed($new_pkg); |
434
|
126
|
50
|
|
|
|
12092
|
$new_pkg->require or return; |
435
|
126
|
|
|
|
|
14494
|
$obj->{pkg} = $new_pkg; |
436
|
126
|
|
|
|
|
1053
|
return $new_pkg; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
package Class::Component; |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
1; |
443
|
|
|
|
|
|
|
__END__ |