File Coverage

blib/lib/JIP/ClassField.pm
Criterion Covered Total %
statement 73 73 100.0
branch 20 22 90.9
condition 8 9 88.8
subroutine 16 16 100.0
pod 0 3 0.0
total 117 123 95.1


line stmt bran cond sub pod time code
1             package JIP::ClassField;
2              
3 1     1   19748 use 5.006;
  1         2  
  1         32  
4 1     1   4 use strict;
  1         1  
  1         27  
5 1     1   4 use warnings;
  1         4  
  1         25  
6 1     1   3 use Carp qw(croak);
  1         1  
  1         57  
7 1     1   4 use English qw(-no_match_vars);
  1         1  
  1         4  
8              
9             our $VERSION = '0.04';
10              
11             my $maybe_set_subname = sub { $ARG[1]; };
12              
13             # Will be shipping with Perl 5.22
14             eval {
15             require Sub::Util;
16              
17             if (my $set_subname = Sub::Util->can('set_subname')) {
18             $maybe_set_subname = $set_subname;
19             }
20             };
21              
22             sub attr {
23 14     14 0 3227 my ($self, $attr, %param) = @ARG;
24              
25 14   66     53 my $class = ref $self || $self;
26              
27 14 100 100     263 croak q{Class not defined}
28             unless defined $class and length $class;
29              
30 12 100 100     384 croak q{Attribute not defined}
31             unless defined $attr and length $attr;
32              
33 10         8 my %patch;
34              
35 10 50       20 if (exists $param{'get'}) {
36 10         13 my ($method_name, $getter) = (q{}, $param{'get'});
37              
38 10 100       369 if ($getter eq q{+}) {
    100          
39 7         8 $method_name = $attr;
40             }
41             elsif ($getter eq q{-}) {
42 2         3 $method_name = q{_}. $attr;
43             }
44             else {
45 1         1 $method_name = $getter;
46             }
47              
48             $patch{$method_name} = sub {
49 9     9   15 my $self = shift;
50 9         26 return $self->{$attr};
51 10         32 };
52             }
53              
54 10 50       20 if (exists $param{'set'}) {
55 10         13 my ($method_name, $setter) = (q{}, $param{'set'});
56              
57 10 100       17 if ($setter eq q{+}) {
    100          
58 7         8 $method_name = q{set_}. $attr;
59             }
60             elsif ($setter eq q{-}) {
61 2         2 $method_name = q{_set_}. $attr;
62             }
63             else {
64 1         1 $method_name = $setter;
65             }
66              
67 10 100       17 if (exists $param{'default'}) {
68 2         2 my $default_value = $param{'default'};
69              
70             $patch{$method_name} = sub {
71 6     6   1999 my $self = shift;
72              
73 6 100       14 if (@ARG == 1) {
74 3         5 $self->{$attr} = shift;
75             }
76             else {
77 3 100       11 $self->{$attr} = ref($default_value) eq 'CODE' ?
78             $default_value->($self) : $default_value;
79             }
80              
81 6         24 return $self;
82 2         5 };
83             }
84             else {
85             $patch{$method_name} = sub {
86 3     3   1961 my ($self, $value) = @ARG;
87 3         17 $self->{$attr} = $value;
88 3         8 return $self;
89 8         25 };
90             }
91             }
92              
93 10         22 return monkey_patch($class, %patch);
94             }
95              
96             sub monkey_patch {
97 12     12 0 25 my ($class, %patch) = @ARG;
98              
99 1     1   668 no strict 'refs';
  1         2  
  1         28  
100 1     1   4 no warnings 'redefine';
  1         1  
  1         101  
101              
102 12         28 while(my ($method_name, $value) = each %patch) {
103 22         25 my $full_name = $class .q{::}. $method_name;
104              
105 22         32 *{$full_name} = $maybe_set_subname->($full_name, $value);
  22         106  
106             }
107              
108 12         57 return 1;
109             }
110              
111             sub cleanup_namespace {
112 1     1 0 287 my @names = @ARG;
113 1         2 my $caller = caller;
114              
115 1     1   4 no strict 'refs';
  1         1  
  1         100  
116 1         2 my $ref = \%{ $caller .'::' };
  1         2  
117              
118 1         2 map { delete $ref->{$_} } @names;
  2         9  
119              
120 1         2 return 1;
121             }
122              
123             sub import {
124 2     2   746 my $caller = caller;
125              
126 2     3   9 return monkey_patch($caller, 'has', sub { attr($caller, @ARG) });
  3         2632  
127             }
128              
129             1;
130              
131             __END__