File Coverage

blib/lib/MooX/ClassStash.pm
Criterion Covered Total %
statement 76 113 67.2
branch 16 32 50.0
condition 2 6 33.3
subroutine 21 35 60.0
pod 24 26 92.3
total 139 212 65.5


line stmt bran cond sub pod time code
1             package MooX::ClassStash;
2             BEGIN {
3 3     3   151530 $MooX::ClassStash::AUTHORITY = 'cpan:GETTY';
4             }
5             {
6             $MooX::ClassStash::VERSION = '0.005';
7             }
8             # ABSTRACT: Extra class information for Moo
9              
10              
11 3     3   24 use Moo;
  3         5  
  3         16  
12 3     3   3263 use Package::Stash;
  3         20083  
  3         99  
13 3     3   2515 use Class::Method::Modifiers qw( install_modifier );
  3         4317  
  3         4496  
14              
15             my %stash_cache;
16              
17             sub import {
18 3     3   22 my ( $class, @args ) = @_;
19 3         10 my $target = caller;
20 3 50       46 unless ($target->can('has')) {
21 0         0 warn "Not using ".$class." on a class which is not Moo, doing nothing";
22 0         0 return;
23             }
24 3 50       126 return if defined $stash_cache{$target};
25 3         14 $stash_cache{$target} = $class->new($target);
26             }
27              
28              
29             has class => (
30             is => 'ro',
31             required => 1,
32             );
33              
34              
35             has package_stash => (
36             is => 'ro',
37             lazy => 1,
38             builder => 1,
39             handles => [qw(
40             name
41             namespace
42             add_symbol
43             remove_glob
44             has_symbol
45             get_symbol
46             get_or_add_symbol
47             remove_symbol
48             list_all_symbols
49             get_all_symbols
50             )],
51             );
52              
53 3     3   2575 sub _build_package_stash { Package::Stash->new(shift->class) }
54              
55              
56             has attributes => (
57             is => 'ro',
58             default => sub {{}},
59             );
60              
61              
62             has data => (
63             is => 'ro',
64             default => sub {{}},
65             );
66              
67              
68             has keyword_functions => (
69             is => 'ro',
70             default => sub {[qw(
71             after
72             around
73             before
74             extends
75             has
76             with
77             )]},
78             );
79              
80              
81 0     0 1 0 sub add_keyword_functions { push @{shift->keyword_functions}, @_ }
  0         0  
82              
83             sub BUILDARGS {
84 3     3 0 9798 my ( $class, @args ) = @_;
85 3 50 33     60 return $_[0] if (scalar @args == 1 and ref $_[0] eq 'HASH');
86 3 50       20 unshift @args, "class" if @args % 2 == 1;
87 3         76 return { @args };
88             }
89              
90             sub BUILD {
91 3     3 0 23 my ( $self ) = @_;
92 3     18   25 $self->add_method('class_stash', sub { return $self });
  18         9450  
93 3     0   90 $self->add_method('package_stash', sub { return $self->package_stash });
  0         0  
94             $self->around_method('has',sub {
95 5     5   1071 my $orig = shift;
96 5         13 my $method = shift;
97 5         21 my $data = { @_ };
98 5 100       26 for (ref $method eq 'ARRAY' ? @{$method} : ($method)) {
  1         2  
99 6         38 $self->attributes->{$_} = $data;
100             }
101 5         29 $orig->($method, @_);
102             })
103 3         136 }
104              
105              
106             sub add_data {
107 2     2 1 2 my $self = shift;
108 2         6 my $target = caller;
109 2 50       14 $self->data->{$target} = {} unless defined $self->data->{$target};
110 2         4 my $key = shift;
111 2         11 $self->data->{$target}->{$key} = shift;
112             }
113              
114              
115             sub get_data {
116 2     2 1 3 my $self = shift;
117 2         4 my $target = caller;
118 2 50       7 return unless defined $self->data->{$target};
119 2         5 my $key = shift;
120 2 50       5 if (defined $key) {
121 0 0       0 return $self->data->{$target}->{$key} if defined $self->data->{$target}->{$key};
122             } else {
123 2         24 return $self->data->{$target};
124             }
125             }
126              
127              
128             sub remove_data {
129 0     0 1 0 my $self = shift;
130 0         0 my $target = caller;
131 0 0       0 return unless defined $self->data->{$target};
132 0         0 my $key = shift;
133 0 0       0 delete $self->data->{$target}->{$key} if defined $self->data->{$target}->{$key};
134             }
135              
136              
137             sub add_keyword {
138 0     0 1 0 my $self = shift;
139 0         0 my $keyword = shift;
140 0         0 push @{$self->keyword_functions}, $keyword;
  0         0  
141 0         0 $self->add_symbol('&'.$keyword,@_);
142             }
143              
144             # so far no check if its not a keyword
145              
146              
147 0     0 1 0 sub get_keyword { shift->get_method(@_) }
148              
149              
150 0     0 1 0 sub has_keyword { shift->has_method(@_) }
151              
152              
153             sub remove_keyword {
154 0     0 1 0 my $self = shift;
155 0         0 my $keyword = shift;
156 0         0 $self->keyword_functions([
157 0         0 grep { $_ ne $keyword }
158 0         0 @{$self->keyword_functions}
159             ]);
160 0         0 $self->remove_method($keyword, @_);
161             }
162              
163              
164             sub get_or_add_keyword {
165 0     0 1 0 my $self = shift;
166 0         0 my $keyword = shift;
167 0         0 push @{$self->keyword_functions}, $keyword;
  0         0  
168 0         0 $self->get_or_add_method($keyword, @_)
169             }
170              
171              
172             sub add_attribute {
173 2     2 1 3 my $self = shift;
174 2         21 my $has = $self->class->can('has');
175 2         73 $has->(@_);
176             }
177              
178              
179             sub get_attribute {
180 5     5 1 8 my $self = shift;
181 5         10 my $attribute = shift;
182 5         7 my $key = shift;
183 5 100       30 return unless defined $self->attributes->{$attribute};
184 4 100       11 if ($key) {
185 2         15 return $self->attributes->{$attribute}->{$key};
186             } else {
187 2         14 return $self->attributes->{$attribute};
188             }
189             }
190              
191              
192             sub has_attribute {
193 0     0 1 0 my $self = shift;
194 0         0 my $attribute = shift;
195 0 0       0 defined $self->attributes->{$attribute} ? 1 : 0;
196             }
197              
198              
199 0     0 1 0 sub remove_attribute { die "If you need MooX::ClassStash->remove_attribute, patches welcome" }
200              
201              
202             sub get_or_add_attribute {
203 2     2 1 6 my $self = shift;
204 2         3 my $attribute = shift;
205 2 50 33     41 die __PACKAGE__."->get_or_add_attribute requires complete attribute definition" if @_ % 2 or @_ == 0;
206 2 100       14 $self->add_attribute($attribute => @_) unless defined $self->attributes->{$attribute};
207 2         351 return $self->attributes->{$attribute};
208             }
209              
210              
211             sub list_all_keywords {
212 1     1 1 1 my $self = shift;
213 1         2 my %keywords = map { $_ => 1 } @{$self->keyword_functions};
  6         16  
  1         6  
214             return
215 10         20 sort { $a cmp $b }
  15         61  
216 1         27 grep { $keywords{$_} }
217             $self->list_all_symbols('CODE');
218             }
219              
220              
221 6     6 1 94 sub add_method { shift->add_symbol('&'.(shift),@_) }
222              
223              
224 0     0 1 0 sub get_method { shift->get_symbol('&'.(shift),@_) }
225              
226              
227 0     0 1 0 sub has_method { shift->has_symbol('&'.(shift),@_) }
228              
229              
230 0     0 1 0 sub remove_method { shift->remove_symbol('&'.(shift),@_) }
231              
232              
233 0     0 1 0 sub get_or_add_method { shift->get_or_add_symbol('&'.(shift),@_) }
234              
235              
236             sub list_all_methods {
237 1     1 1 3 my $self = shift;
238 1         2 my %keywords = map { $_ => 1 } @{$self->keyword_functions};
  6         14  
  1         6  
239             return
240 21         30 sort { $a cmp $b }
  15         528  
241 1         8 grep { !$keywords{$_} }
242             $self->list_all_symbols('CODE');
243             }
244              
245              
246 1     1 1 348 sub after_method { install_modifier(shift->class,'after',@_) }
247              
248              
249 1     1 1 331 sub before_method { install_modifier(shift->class,'before',@_) }
250              
251              
252 4     4 1 388 sub around_method { install_modifier(shift->class,'around',@_) }
253              
254             1;
255              
256             __END__