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