File Coverage

blib/lib/Validation/Class/Util.pm
Criterion Covered Total %
statement 82 92 89.1
branch 33 52 63.4
condition 5 9 55.5
subroutine 23 27 85.1
pod 0 13 0.0
total 143 193 74.0


line stmt bran cond sub pod time code
1             # Utility Functions for Validation Classes
2              
3             package Validation::Class::Util;
4              
5 109     109   625 use strict;
  109         199  
  109         2680  
6 109     109   473 use warnings;
  109         177  
  109         3761  
7              
8             our $VERSION = '7.900058'; # VERSION
9              
10 109     109   43794 use Module::Runtime 'use_module';
  109         162867  
  109         574  
11 109     109   5071 use Scalar::Util 'blessed';
  109         195  
  109         4668  
12 109     109   569 use Carp 'confess';
  109         198  
  109         3561  
13 109     109   491 use Exporter ();
  109         186  
  109         38895  
14              
15             our @ISA = qw(Exporter);
16             our @EXPORT = qw(
17              
18             build_args
19             build_args_collection
20             has
21             hold
22             isa_arrayref
23             isa_classref
24             isa_coderef
25             isa_hashref
26             isa_listing
27             isa_mapping
28             isa_prototype
29             isa_regexp
30             prototype_registry
31              
32             );
33              
34             sub build_args {
35              
36 47652     47652 0 59119 my $self = shift;
37              
38 47652   66     94133 my $class = ref $self || $self;
39              
40 47652 100       84920 if ( scalar @_ == 1 ) {
    50          
41 19684 50 33     56390 confess
42             "The new() method for $class expects single arguments to " .
43             "take the form of a hash reference"
44             unless defined $_[0] && ref $_[0] eq 'HASH'
45             ;
46 19684         23891 return {%{$_[0]}};
  19684         103781  
47             }
48              
49             elsif ( @_ % 2 ) {
50 0         0 confess
51             "The new() method for $class expects a hash reference or a " .
52             "key/value list. You passed an odd number of arguments"
53             ;
54             }
55              
56             else {
57 27968         60654 return {@_};
58             }
59              
60             }
61              
62             sub build_args_collection {
63              
64 0     0 0 0 my $class = shift;
65              
66             # Validation::Class::Mapping should already be loaded
67 0         0 return Validation::Class::Mapping->new($class->build_args(@_));
68              
69             }
70              
71             sub has {
72              
73 30193     30193 0 51471 my ( $attrs, $default ) = @_;
74              
75 30193 50       48940 return unless $attrs;
76              
77 30193 50 66     63458 confess "Error creating accessor, default must be a coderef or constant"
78             if ref $default && ref $default ne 'CODE';
79              
80 30193 50       62488 $attrs = [$attrs] unless ref $attrs eq 'ARRAY';
81              
82 30193         47552 for my $attr (@$attrs) {
83              
84 30193 50       84463 confess "Error creating accessor '$attr', name has invalid characters"
85             unless $attr =~ /^[a-zA-Z_]\w*$/;
86              
87 30193         35127 my $code;
88              
89 30193 50       42789 if ( defined $default ) {
90              
91             $code = sub {
92              
93 256778 100   256778   387028 if ( @_ == 1 ) {
94 255174 100       676051 return $_[0]->{$attr} if exists $_[0]->{$attr};
95 21717 100       54806 return $_[0]->{$attr}
96             = ref $default eq 'CODE'
97             ? $default->( $_[0] )
98             : $default;
99             }
100 1604         3316 $_[0]->{$attr} = $_[1];
101 1604         2759 $_[0];
102              
103 30193         95743 };
104              
105             }
106              
107             else {
108              
109             $code = sub {
110              
111 0 0   0   0 return $_[0]->{$attr} if @_ == 1;
112 0         0 $_[0]->{$attr} = $_[1];
113 0         0 $_[0];
114              
115 0         0 };
116              
117             }
118              
119 109     109   715 no strict 'refs';
  109         206  
  109         3536  
120 109     109   571 no warnings 'redefine';
  109         469  
  109         28803  
121              
122 30193         50419 my $class = caller(0);
123              
124 30193         34255 *{"$class\::$attr"} = $code;
  30193         114972  
125              
126             }
127              
128 30193         62759 return;
129              
130             }
131              
132             sub hold {
133              
134 1853     1853 0 3192 my ( $attrs, $default ) = @_;
135              
136 1853 50       3049 return unless $attrs;
137              
138 1853 50       3207 confess "Error creating accessor, default is required and must be a coderef"
139             if ref $default ne 'CODE';
140              
141 1853 50       4001 $attrs = [$attrs] unless ref $attrs eq 'ARRAY';
142              
143 1853         2867 for my $attr (@$attrs) {
144              
145 1853 50       5563 confess "Error creating accessor '$attr', name has invalid characters"
146             unless $attr =~ /^[a-zA-Z_]\w*$/;
147              
148 1853         2238 my $code;
149              
150             $code = sub {
151              
152 123912 50   123912   196642 if ( @_ == 1 ) {
153 123912 100       318264 return $_[0]->{$attr} if exists $_[0]->{$attr};
154 2084         6247 return $_[0]->{$attr} = $default->( $_[0] );
155             }
156              
157             # values are read-only cannot be changed
158 0         0 confess "Error attempting to modify the read-only attribute ($attr)";
159              
160 1853         5474 };
161              
162 109     109   765 no strict 'refs';
  109         223  
  109         3386  
163 109     109   561 no warnings 'redefine';
  109         189  
  109         34426  
164              
165 1853         3122 my $class = caller(0);
166              
167 1853         2113 *{"$class\::$attr"} = $code;
  1853         7218  
168              
169             }
170              
171 1853         3550 return;
172              
173             }
174              
175             sub import {
176              
177 6446     6446   27318 strict->import;
178 6446         49605 warnings->import;
179              
180 6446         566045 __PACKAGE__->export_to_level(1, @_);
181              
182 6446         3090700 return;
183              
184             }
185              
186             sub isa_arrayref {
187              
188 10739 100   10739 0 32356 return "ARRAY" eq ref(shift) ? 1 : 0;
189              
190             }
191              
192             sub isa_classref {
193              
194 65916     65916 0 86811 my ($object) = @_;
195              
196 65916 50       167253 return blessed(shift) ? 1 : 0;
197              
198             }
199              
200             sub isa_coderef {
201              
202 656 100   656 0 2294 return "CODE" eq ref(shift) ? 1 : 0;
203              
204             }
205              
206             sub isa_hashref {
207              
208 983 100   983 0 3536 return "HASH" eq ref(shift) ? 1 : 0;
209              
210             }
211              
212             sub isa_listing {
213              
214 0 0   0 0 0 return "Validation::Class::Listing" eq ref(shift) ? 1 : 0;
215              
216             }
217              
218             sub isa_mapping {
219              
220 12 100   12 0 205 return "Validation::Class::Mapping" eq ref(shift) ? 1 : 0;
221              
222             }
223              
224             sub isa_prototype {
225              
226 0 0   0 0 0 return prototype_registry->has(shift) ? 1 : 0;
227              
228             }
229              
230             sub isa_regexp {
231              
232 542 100   542 0 2282 return "REGEXP" eq uc(ref(shift)) ? 1 : 0;
233              
234             }
235              
236             sub prototype_registry {
237              
238             # Validation::Class::Prototype should be already loaded
239 1503     1503 0 4554 return Validation::Class::Prototype->registry;
240              
241             }
242              
243             1;