File Coverage

blib/lib/Soo.pm
Criterion Covered Total %
statement 75 78 96.1
branch 12 22 54.5
condition 5 11 45.4
subroutine 17 17 100.0
pod n/a
total 109 128 85.1


line stmt bran cond sub pod time code
1 6     6   5774 use strict;
  5         18  
  5         143  
2 6     6   32 use warnings;
  6         10  
  6         239  
3              
4             package Soo;
5              
6 6     6   185 use Carp 'croak';
  5         8  
  5         939  
7              
8             our $VERSION = '0.0.3';
9              
10              
11             my $extends = sub {
12 5     5   29 my $parent = shift;
13 3     3   1074 eval "use $parent;";
  2         65  
  2         37  
  5         277  
14 3     3   1436 eval "package ${\scalar(caller)}; use parent -norequire, '$parent';";
  3         1005  
  3         21  
  5         14  
  5         333  
15             };
16              
17             my $has = sub {
18 42     42   472 my ($method, $meta) = @_;
19              
20 42         67 my $package = caller;
21              
22 6     6   46 no strict 'refs';
  6         10  
  6         287  
23              
24 42 50       88 if($method eq 'new') {
25 5     5   43 no warnings;
  5         10  
  5         2016  
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   2562 my $self = shift;
32              
33 49   50 7   323 my $set = $meta->{set} || sub {$_[1]};
  7         29  
34              
35 49         343 my @call = caller(1);
36 49 50       132 @call = caller(0) unless(@call);
37 49         170 my ($callpkg, $callfn) = split(/::/, $call[3]);
38              
39 49 50 33     263 $self->__soo_get_set__($method, $set->($self, shift)) if(@_ && ( $meta->{rw} || ($callpkg eq 'Soo' && $callfn eq '__ANON__') ));
      66        
40              
41 49 100       96 $self->__soo_get_set__($method) || $meta->{default};
42 42         151 };
43              
44             # set method
45 42         72 *{"$package\::$method"} = $fn;
  42         185  
46              
47             };
48              
49             my $new = sub {
50 7     7   7300 my ($class, $params) = @_;
51              
52 7         19 my $self = bless({}, $class);
53              
54             # init/clean context
55 7         20 $self->__soo_init__;
56              
57             # constructor set
58 7         21 $params = $self->__soo_new_set__($params);
59              
60             # default behaviour of the constructor is receive a hash ref
61 7         41 $self->$_($params->{$_}) foreach (keys %$params);
62              
63 7         25 $self;
64             };
65              
66             sub import {
67 11     11   247 my $package = caller;
68              
69 5     5   44 no strict 'refs';
  5         11  
  5         1834  
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         22 my $context = {};
74              
75 11         59 *{"$package\::__soo_init__"} = sub {
76 7     7   41 $context->{+shift} = {};
77 11         36 };
78              
79 11         40 *{"$package\::__soo_get_set__"} = sub {
80 56     56   77 my $self = shift;
81 56         71 my $field = shift;
82              
83 56 50       145 return unless($field);
84              
85 56         271 my @call = caller(1);
86 56 50       128 @call = caller(0) unless(@call);
87 56         151 my ($callpkg, $callfn) = split(/::/, $call[3]);
88              
89 56 50 33     212 croak "Access denied for $callpkg\::$callfn" unless($callpkg eq 'Soo' && $callfn eq '__ANON__');
90              
91 56 100       119 $context->{$self}->{$field} = shift if(@_);
92              
93 56         455 $context->{$self}->{$field};
94 11         41 };
95              
96             # export extends
97 11         18 *{"$package\::extends"} = $extends;
  11         35  
98              
99             # export has
100 11         18 *{"$package\::has"} = $has;
  11         33  
101              
102             # default constructor
103 11 50       18 *{"$package\::new"} = $new unless(defined(*{"$package\::new"}));
  11         30  
  11         53  
104              
105             # default constructor setter
106 11 50   7   16 *{"$package\::__soo_new_set__"} = sub {$_[1]} unless(defined(*{"$package\::__soo_new_set__"}));
  11         811  
  7         11  
  11         100  
107              
108             }
109              
110              
111             1;
112              
113             __END__