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   764 use strict;
  109         228  
  109         3225  
6 109     109   563 use warnings;
  109         228  
  109         4405  
7              
8             our $VERSION = '7.900059'; # VERSION
9              
10 109     109   55169 use Module::Runtime 'use_module';
  109         196917  
  109         690  
11 109     109   5934 use Scalar::Util 'blessed';
  109         253  
  109         5430  
12 109     109   702 use Carp 'confess';
  109         256  
  109         4454  
13 109     109   629 use Exporter ();
  109         258  
  109         48049  
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 70536 my $self = shift;
37              
38 47652   66     113139 my $class = ref $self || $self;
39              
40 47652 100       102686 if ( scalar @_ == 1 ) {
    50          
41 19684 50 33     68330 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         29308 return {%{$_[0]}};
  19684         124102  
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         73437 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 63187 my ( $attrs, $default ) = @_;
74              
75 30193 50       60765 return unless $attrs;
76              
77 30193 50 66     77342 confess "Error creating accessor, default must be a coderef or constant"
78             if ref $default && ref $default ne 'CODE';
79              
80 30193 50       76365 $attrs = [$attrs] unless ref $attrs eq 'ARRAY';
81              
82 30193         58373 for my $attr (@$attrs) {
83              
84 30193 50       103083 confess "Error creating accessor '$attr', name has invalid characters"
85             unless $attr =~ /^[a-zA-Z_]\w*$/;
86              
87 30193         43198 my $code;
88              
89 30193 50       52115 if ( defined $default ) {
90              
91             $code = sub {
92              
93 256814 100   256814   478586 if ( @_ == 1 ) {
94 255210 100       814535 return $_[0]->{$attr} if exists $_[0]->{$attr};
95 21729 100       68437 return $_[0]->{$attr}
96             = ref $default eq 'CODE'
97             ? $default->( $_[0] )
98             : $default;
99             }
100 1604         3772 $_[0]->{$attr} = $_[1];
101 1604         3086 $_[0];
102              
103 30193         121638 };
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   865 no strict 'refs';
  109         281  
  109         4102  
120 109     109   726 no warnings 'redefine';
  109         570  
  109         34902  
121              
122 30193         63825 my $class = caller(0);
123              
124 30193         41881 *{"$class\::$attr"} = $code;
  30193         140656  
125              
126             }
127              
128 30193         77800 return;
129              
130             }
131              
132             sub hold {
133              
134 1853     1853 0 3949 my ( $attrs, $default ) = @_;
135              
136 1853 50       3738 return unless $attrs;
137              
138 1853 50       4198 confess "Error creating accessor, default is required and must be a coderef"
139             if ref $default ne 'CODE';
140              
141 1853 50       5033 $attrs = [$attrs] unless ref $attrs eq 'ARRAY';
142              
143 1853         3597 for my $attr (@$attrs) {
144              
145 1853 50       6840 confess "Error creating accessor '$attr', name has invalid characters"
146             unless $attr =~ /^[a-zA-Z_]\w*$/;
147              
148 1853         2771 my $code;
149              
150             $code = sub {
151              
152 123934 50   123934   239443 if ( @_ == 1 ) {
153 123934 100       381215 return $_[0]->{$attr} if exists $_[0]->{$attr};
154 2084         7897 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         7636 };
161              
162 109     109   945 no strict 'refs';
  109         306  
  109         4081  
163 109     109   647 no warnings 'redefine';
  109         275  
  109         42166  
164              
165 1853         3895 my $class = caller(0);
166              
167 1853         2605 *{"$class\::$attr"} = $code;
  1853         8747  
168              
169             }
170              
171 1853         4539 return;
172              
173             }
174              
175             sub import {
176              
177 6446     6446   32636 strict->import;
178 6446         58558 warnings->import;
179              
180 6446         674833 __PACKAGE__->export_to_level(1, @_);
181              
182 6446         3867137 return;
183              
184             }
185              
186             sub isa_arrayref {
187              
188 10688 100   10688 0 36760 return "ARRAY" eq ref(shift) ? 1 : 0;
189              
190             }
191              
192             sub isa_classref {
193              
194 65916     65916 0 106085 my ($object) = @_;
195              
196 65916 50       205840 return blessed(shift) ? 1 : 0;
197              
198             }
199              
200             sub isa_coderef {
201              
202 656 100   656 0 2557 return "CODE" eq ref(shift) ? 1 : 0;
203              
204             }
205              
206             sub isa_hashref {
207              
208 983 100   983 0 4198 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 257 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 2610 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 5158 return Validation::Class::Prototype->registry;
240              
241             }
242              
243             1;