File Coverage

blib/lib/Soo.pm
Criterion Covered Total %
statement 67 70 95.7
branch 10 18 55.5
condition 5 11 45.4
subroutine 16 16 100.0
pod n/a
total 98 115 85.2


line stmt bran cond sub pod time code
1 4     4   4955 use strict;
  4         8  
  4         113  
2 4     4   19 use warnings;
  4         5  
  4         154  
3              
4             package Soo;
5              
6 4     4   21 use Carp 'croak';
  4         7  
  4         630  
7              
8             our $VERSION = '0.0.2';
9              
10              
11             my $extends = sub {
12 2     2   950 eval "package ${\scalar(caller)}; use parent '${\shift}';";
  2     2   726  
  2         10  
  2         12  
  2         9  
  2         121  
13             };
14              
15             my $has = sub {
16 30     30   213 my ($method, $meta) = @_;
17              
18 30         55 my $package = caller;
19              
20 4     4   31 no strict 'refs';
  4         6  
  4         192  
21              
22 30 50       59 if($method eq 'new') {
23 4     4   24 no warnings;
  4         8  
  4         1517  
24 0 0       0 *{"$package\::__soo_new_set__"} = $meta->{set} if($meta->{set});
  0         0  
25 0         0 return;
26             }
27              
28             my $fn = sub {
29 28     28   2137 my $self = shift;
30              
31 28   50 4   228 my $set = $meta->{set} || sub {$_[1]};
  4         17  
32              
33 28         225 my ($callpkg, $callfn) = split(/::/, +(caller(1))[3]);
34              
35 28 50 33     165 $self->__soo_get_set__($method, $set->($self, shift)) if(@_ && ( $meta->{rw} || ($callpkg eq 'Soo' && $callfn eq '__ANON__') ));
      66        
36              
37 28 100       71 $self->__soo_get_set__($method) || $meta->{default};
38 30         95 };
39              
40             # set method
41 30         43 *{"$package\::$method"} = $fn;
  30         119  
42              
43             };
44              
45             my $new = sub {
46 4     4   5846 my ($class, $params) = @_;
47              
48 4         9 my $self = bless({}, $class);
49              
50             # init/clean context
51 4         14 $self->__soo_init__;
52              
53             # constructor set
54 4         17 $params = $self->__soo_new_set__($params);
55              
56             # default behaviour of the constructor is receive a hash ref
57 4         33 $self->$_($params->{$_}) foreach (keys %$params);
58              
59 4         17 $self;
60             };
61              
62             sub import {
63 7     7   780 my $package = caller;
64              
65 4     4   31 no strict 'refs';
  4         8  
  4         1359  
66              
67             # context, we will use this closure context to encapsulate data and provide readonly or readwrite capabilities
68             # the context is at class level and will differ object data by using the object ref as key
69 7         14 my $context = {};
70              
71 7         38 *{"$package\::__soo_init__"} = sub {
72 4     4   24 $context->{+shift} = {};
73 7         24 };
74              
75 7         27 *{"$package\::__soo_get_set__"} = sub {
76 32     32   54 my $self = shift;
77 32         43 my $field = shift;
78              
79 32 50       59 return unless($field);
80              
81 32         172 my ($callpkg, $callfn) = split(/::/, +(caller(1))[3]);
82              
83 32 50 33     146 croak "Access denied for $callpkg\::$callfn" unless($callpkg eq 'Soo' && $callfn eq '__ANON__');
84              
85 32 100       68 $context->{$self}->{$field} = shift if(@_);
86              
87 32         252 $context->{$self}->{$field};
88 7         26 };
89              
90             # export extends
91 7         15 *{"$package\::extends"} = $extends;
  7         22  
92              
93             # export has
94 7         10 *{"$package\::has"} = $has;
  7         18  
95              
96             # default constructor
97 7 50       60 *{"$package\::new"} = $new unless(defined(*{"$package\::new"}));
  7         24  
  7         40  
98              
99             # default constructor setter
100 7 50   4   9 *{"$package\::__soo_new_set__"} = sub {$_[1]} unless(defined(*{"$package\::__soo_new_set__"}));
  7         493  
  4         7  
  7         71  
101              
102             }
103              
104              
105             1;
106              
107             __END__