File Coverage

blib/lib/Soo.pm
Criterion Covered Total %
statement 72 75 96.0
branch 12 22 54.5
condition 5 11 45.4
subroutine 16 16 100.0
pod n/a
total 105 124 84.6


line stmt bran cond sub pod time code
1 6     6   5689 use strict;
  6         19  
  6         152  
2 6     6   30 use warnings;
  6         8  
  6         177  
3              
4             package Soo;
5              
6 5     5   26 use Carp 'croak';
  5         8  
  5         921  
7              
8             our $VERSION = '0.0.4';
9              
10              
11             my $extends = sub {
12 5     5   28 my $parent = shift;
13 5         241 eval "require $parent;";
14 3     3   1480 eval "package ${\scalar(caller)}; use parent -norequire, '$parent';";
  3         1024  
  3         18  
  5         45  
  5         404  
15             };
16              
17             my $has = sub {
18 42     42   444 my ($method, $meta) = @_;
19              
20 42         66 my $package = caller;
21              
22 5     5   36 no strict 'refs';
  5         9  
  5         222  
23              
24 42 50       92 if($method eq 'new') {
25 5     5   44 no warnings;
  5         10  
  5         1965  
26 0 0       0 *{"$package\::__soo_new_set__"} = $meta->{set} if($meta->{set});
  0         0  
27 0         0 return;
28             }
29              
30             my $fn = sub {
31 49     49   2580 my $self = shift;
32              
33 49   50 7   323 my $set = $meta->{set} || sub {$_[1]};
  7         36  
34              
35 49         358 my @call = caller(1);
36 49 50       127 @call = caller(0) unless(@call);
37 49         169 my ($callpkg, $callfn) = split(/::/, $call[3]);
38              
39 49 50 33     231 $self->__soo_get_set__($method, $set->($self, shift)) if(@_ && ( $meta->{rw} || ($callpkg eq 'Soo' && $callfn eq '__ANON__') ));
      66        
40              
41 49 100       98 $self->__soo_get_set__($method) || $meta->{default};
42 42         148 };
43              
44             # set method
45 42         68 *{"$package\::$method"} = $fn;
  42         182  
46              
47             };
48              
49             my $new = sub {
50 7     7   7424 my ($class, $params) = @_;
51              
52 7         18 my $self = bless({}, $class);
53              
54             # init/clean context
55 7         19 $self->__soo_init__;
56              
57             # constructor set
58 7         25 $params = $self->__soo_new_set__($params);
59              
60             # default behaviour of the constructor is receive a hash ref
61 7         104 $self->$_($params->{$_}) foreach (keys %$params);
62              
63 7         21 $self;
64             };
65              
66             sub import {
67 11     11   254 my $package = caller;
68              
69 5     5   45 no strict 'refs';
  5         12  
  5         1843  
70              
71             # context, we will use this closure context to encapsulate data and provide readonly or readwrite capabilities
72             # the context is at class level and will differ object data by using the object ref as key
73 11         19 my $context = {};
74              
75 11         59 *{"$package\::__soo_init__"} = sub {
76 7     7   90 $context->{+shift} = {};
77 11         39 };
78              
79 11         43 *{"$package\::__soo_get_set__"} = sub {
80 56     56   71 my $self = shift;
81 56         121 my $field = shift;
82              
83 56 50       117 return unless($field);
84              
85 56         324 my @call = caller(1);
86 56 50       127 @call = caller(0) unless(@call);
87 56         153 my ($callpkg, $callfn) = split(/::/, $call[3]);
88              
89 56 50 33     241 croak "Access denied for $callpkg\::$callfn" unless($callpkg eq 'Soo' && $callfn eq '__ANON__');
90              
91 56 100       126 $context->{$self}->{$field} = shift if(@_);
92              
93 56         491 $context->{$self}->{$field};
94 11         53 };
95              
96             # export extends
97 11         20 *{"$package\::extends"} = $extends;
  11         36  
98              
99             # export has
100 11         17 *{"$package\::has"} = $has;
  11         33  
101              
102             # default constructor
103 11 50       17 *{"$package\::new"} = $new unless(defined(*{"$package\::new"}));
  11         33  
  11         50  
104              
105             # default constructor setter
106 11 50   7   16 *{"$package\::__soo_new_set__"} = sub {$_[1]} unless(defined(*{"$package\::__soo_new_set__"}));
  11         799  
  7         14  
  11         97  
107              
108             }
109              
110              
111             1;
112              
113             __END__