File Coverage

blib/lib/Form/Tiny/FieldDefinition.pm
Criterion Covered Total %
statement 94 95 98.9
branch 40 44 90.9
condition 18 24 75.0
subroutine 19 19 100.0
pod 2 6 33.3
total 173 188 92.0


line stmt bran cond sub pod time code
1             package Form::Tiny::FieldDefinition;
2             $Form::Tiny::FieldDefinition::VERSION = '2.19';
3 51     51   3273 use v5.10;
  51         198  
4 51     51   293 use strict;
  51         146  
  51         1160  
5 51     51   260 use warnings;
  51         125  
  51         1427  
6 51     51   365 use Moo;
  51         165  
  51         396  
7 51     51   17414 use Types::Standard qw(Enum Bool HasMethods CodeRef InstanceOf HashRef);
  51         155  
  51         1299  
8 51     51   142442 use Types::Common::String qw(NonEmptySimpleStr);
  51         2952081  
  51         609  
9 51     51   58716 use Types::TypeTiny qw(StringLike);
  51         131  
  51         367  
10 51     51   28422 use Carp qw(croak);
  51         174  
  51         3476  
11 51     51   376 use Scalar::Util qw(blessed);
  51         134  
  51         2494  
12              
13 51     51   357 use Form::Tiny::Utils qw(try has_form_meta);
  51         128  
  51         2704  
14 51     51   894 use Form::Tiny::Error;
  51         132  
  51         1157  
15 51     51   23354 use Form::Tiny::Path;
  51         185  
  51         58171  
16              
17             has 'name' => (
18             is => 'ro',
19             isa => NonEmptySimpleStr,
20             required => 1,
21             );
22              
23             has 'name_path' => (
24             is => 'ro',
25             isa => InstanceOf ['Form::Tiny::Path'],
26             reader => 'get_name_path',
27             init_arg => undef,
28             lazy => 1,
29             default => sub { Form::Tiny::Path->from_name(shift->name) },
30             );
31              
32             has 'required' => (
33             is => 'ro',
34             isa => Enum [0, 1, 'soft', 'hard'],
35             writer => 'set_required',
36             default => sub { 0 },
37             );
38              
39             has 'type' => (
40             is => 'ro',
41             isa => HasMethods ['validate', 'check'],
42             writer => 'set_type',
43             predicate => 'has_type',
44             );
45              
46             has 'addons' => (
47             is => 'ro',
48             writer => 'set_addons',
49             isa => HashRef,
50             default => sub { {} },
51             init_arg => undef,
52             );
53              
54             has 'coerce' => (
55             is => 'ro',
56             isa => Bool | CodeRef,
57             writer => 'set_coercion',
58             default => sub { 0 },
59             );
60              
61             has 'adjust' => (
62             is => 'ro',
63             isa => CodeRef,
64             predicate => 'is_adjusted',
65             writer => 'set_adjustment',
66             );
67              
68             has 'default' => (
69             is => 'ro',
70             isa => CodeRef,
71             writer => 'set_default',
72             predicate => 'has_default',
73             );
74              
75             has 'message' => (
76             is => 'ro',
77             isa => StringLike,
78             writer => 'set_message',
79             predicate => 'has_message',
80             );
81              
82             has 'data' => (
83             is => 'ro',
84             writer => 'set_data',
85             predicate => 'has_data',
86             );
87              
88             has '_subform' => (
89             is => 'ro',
90             isa => Bool,
91             reader => 'is_subform',
92             lazy => 1,
93             default => sub { $_[0]->has_type && has_form_meta($_[0]->type) },
94             init_arg => undef,
95             );
96              
97             sub BUILD
98             {
99 293     293 0 14966 my ($self, $args) = @_;
100              
101 293 100 100     1467 if ($self->coerce && ref $self->coerce ne 'CODE') {
102              
103             # checks for coercion == 1
104 16         93 my $t = $self->type;
105 16 100 33     155 croak 'type doesn\'t provide coercion'
      66        
      100        
106             if !$self->has_type
107             || !($t->can('coerce') && $t->can('has_coercion') && $t->has_coercion);
108             }
109              
110 291 100       2439 if ($self->has_default) {
111              
112             croak 'default value for an array field is unsupported'
113 12 100       18 if scalar grep { $_ eq 'ARRAY' } @{$self->get_name_path->meta};
  19         457  
  12         220  
114             }
115             }
116              
117             sub hard_required
118             {
119 31     31 1 85 my ($self) = @_;
120              
121 31   100     280 return $self->required eq '1' || $self->required eq 'hard';
122             }
123              
124             sub get_coerced
125             {
126 344     344 0 1650 my ($self, $form, $value) = @_;
127 344         835 my $coerce = $self->coerce;
128              
129 344 100       795 if ($coerce) {
130             my $error = try sub {
131 62 100   62   148 if (ref $coerce eq 'CODE') {
132 29         62 $value = $coerce->($form, $value);
133             }
134             else {
135 33         127 $value = $self->type->coerce($value);
136             }
137 62         362 };
138              
139 62 100       308 if ($error) {
140 3 50       72 $form->add_error(
141             Form::Tiny::Error::DoesNotValidate->new(
142             {
143             field => $self->name,
144             error => $self->has_message ? $self->message : $error,
145             }
146             )
147             );
148             }
149             }
150              
151 344         934 return $value;
152             }
153              
154             sub get_adjusted
155             {
156 275     275 0 505 my $self = shift;
157 275         484 my $value = pop;
158              
159 275 100       5658 if ($self->is_subform) {
160 6         102 $value = $self->type->fields;
161             }
162              
163 275 100       4874 return $value unless $self->is_adjusted;
164 24         82 return $self->adjust->(@_, $value);
165             }
166              
167             sub get_default
168             {
169 20     20 0 128 my ($self, $form) = @_;
170              
171 20 50       52 croak 'no default value set but was requested'
172             unless $self->has_default;
173              
174 20         67 my $default = $self->default->($form);
175 20 100       368 if ($self->is_subform) {
176 1         40 my $subform = $self->type;
177 1 50       5 croak 'subform default input is not valid'
178             unless $subform->check($default);
179              
180 1         5 $default = $subform->fields;
181             }
182              
183 20         408 return $default;
184             }
185              
186             sub validate
187             {
188 344     344 1 714 my ($self, $form, $value) = @_;
189              
190 344         532 my @errors;
191              
192 344 100       1052 if ($self->has_type) {
193 199 100       539 if ($self->has_message) {
194 8 100       49 push @errors, $self->message
195             if !$self->type->check($value);
196             }
197             else {
198 191         658 my $error = $self->type->validate($value);
199 191 100       9063 push @errors, $error
200             if defined $error;
201             }
202             }
203              
204 344 100 100     1776 if (@errors == 0 && (my $validators = $self->addons->{validators})) {
205 5         8 for my $validator (@{$validators}) {
  5         13  
206 9         20 my ($message, $code) = @{$validator};
  9         22  
207              
208 9 100       22 if (!$code->($form, $value)) {
209 4         19 push @errors, $message;
210             }
211             }
212             }
213              
214 344         2536 for my $error (@errors) {
215 70 100 66     403 if (ref $error eq 'ARRAY' && $self->is_subform) {
216 6         77 foreach my $exception (@$error) {
217 6 50 33     53 if (defined blessed $exception && $exception->isa('Form::Tiny::Error')) {
218 6         105 my $path = $self->get_name_path;
219 6 100       84 $path = $path->clone->append(HASH => $exception->field)
220             if defined $exception->field;
221              
222 6         29 $exception->set_field($path->join);
223 6         324 $exception = Form::Tiny::Error::NestedFormError->new(
224             field => $self->name,
225             error => $exception,
226             );
227             }
228             else {
229 0         0 $exception = Form::Tiny::Error::DoesNotValidate->new(
230             field => $self->name,
231             error => $exception,
232             );
233             }
234              
235 6         520 $form->add_error($exception);
236             }
237             }
238             else {
239 64         1556 $form->add_error(
240             Form::Tiny::Error::DoesNotValidate->new(
241             {
242             field => $self->name,
243             error => $error,
244             }
245             )
246             );
247             }
248             }
249              
250 344         1186 return @errors == 0;
251             }
252              
253             1;
254              
255             __END__