File Coverage

blib/lib/Micro/Container.pm
Criterion Covered Total %
statement 70 74 94.5
branch 17 22 77.2
condition 7 12 58.3
subroutine 12 12 100.0
pod 5 5 100.0
total 111 125 88.8


line stmt bran cond sub pod time code
1             package Micro::Container;
2              
3 3     3   103986 use strict;
  3         8  
  3         135  
4 3     3   18 use warnings;
  3         6  
  3         89  
5 3     3   164 use 5.008_001;
  3         25  
  3         206  
6             our $VERSION = '0.03';
7              
8 3     3   2645 use parent qw(Class::Data::Inheritable);
  3         839  
  3         20  
9              
10 3     3   4789 use Carp qw(croak);
  3         7  
  3         3505  
11              
12             __PACKAGE__->mk_classdata(objects => {});
13              
14             my %INSTANCES;
15             sub instance {
16 6     6 1 24 my $class = shift;
17 6   66     34 $INSTANCES{$class} ||= do {
18 3         10 my $self = bless {}, $class;
19 3         16 $self->{_parent_classes} = $self->_parent_classes($class);
20 3         19 $self;
21             };
22             }
23              
24             sub register {
25 7     7 1 25691 my $self = shift;
26 7         19 my $klass = ref $self;
27 7 100       24 unless ($klass) {
28 2         16 ($klass, $self) = ($self, $self->instance);
29             }
30              
31 7   100     29 my $objects = $self->objects->{$klass} ||= {};
32 7         5986 while (@_) {
33 8         39 my ($name, $args) = splice @_, 0, 2;
34 8 100       31 if (ref $args eq 'CODE') {
35 3         17 $objects->{$name} = $args->($self, $name);
36             }
37             else {
38 5         15 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
39 5         24 $objects->{$name} = $self->load_class($name)->new(@$args);
40             }
41             }
42             }
43             *add = *register;
44              
45             sub unregister {
46 5     5 1 3744 my ($self, @names) = @_;
47 5         10 my $klass = ref $self;
48 5 50       13 unless ($klass) {
49 0         0 ($klass, $self) = ($self, $self->instance);
50             }
51              
52 5   50     17 my $objects = $self->objects->{$klass} ||= {};
53 5         50 for my $name (@names) {
54 6         21 delete $objects->{$name};
55             }
56             }
57             *remove = *unregister;
58              
59             sub get {
60 15     15 1 5425 my ($self, $name) = @_;
61 15         44 my $klass = ref $self;
62 15 100       71 unless ($klass) {
63 3         12 ($klass, $self) = ($self, $self->instance);
64             }
65              
66 15         56 my $objects = $self->objects;
67 15         112 my $obj = $objects->{$klass}{$name};
68              
69             # find from parent classes
70 15 100       62 unless ($obj) {
71 8         19 my $classes = $self->{_parent_classes};
72 8         18 for my $class (@$classes) {
73 8 100       45 $obj = $objects->{$class}{$name} and last;
74             }
75             }
76              
77 15 100       62 $obj or croak "$name is not registered in @{[ ref $self ]}";
  7         1170  
78             }
79              
80             sub load_class {
81 8     8 1 35 my ($self, $class, $prefix) = @_;
82              
83             # taken from Plack::Util::load_class
84 8 50       20 if ($prefix) {
85 0 0 0     0 unless ($class =~ s/^\+// || $class =~ /^$prefix/) {
86 0         0 $class = "$prefix\::$class";
87             }
88             }
89              
90 8         14 my $file = $class;
91 8         37 $file =~ s!::!/!g;
92 8         14 eval {
93 8         3134 require "$file.pm"; ## no critic
94             };
95 8 50       517 if (my $e = $@) {
96 0         0 croak "$e";
97             }
98              
99 8         56 return $class;
100             }
101              
102             sub _parent_classes {
103 5     5   13 my ($self, $klass, $classes) = @_;
104 5   100     25 $classes ||= [];
105              
106 5         7 my @isa = do {
107 3     3   172 no strict 'refs';
  3         8  
  3         376  
108 5         7 @{"$klass\::ISA"};
  5         34  
109             };
110 5         13 push @$classes, @isa;
111              
112 5         9 for my $class (@isa) {
113 3 100       12 next if $class eq __PACKAGE__;
114 2         20 $self->_parent_classes($class, $classes);
115             }
116              
117 5         34 return $classes;
118             }
119              
120             1;
121             __END__