File Coverage

blib/lib/Form/Factory/Feature/RequireNoneOrAll.pm
Criterion Covered Total %
statement 32 32 100.0
branch 7 8 87.5
condition 9 9 100.0
subroutine 5 5 100.0
pod 1 1 100.0
total 54 55 98.1


line stmt bran cond sub pod time code
1             package Form::Factory::Feature::RequireNoneOrAll;
2             $Form::Factory::Feature::RequireNoneOrAll::VERSION = '0.022';
3 1     1   814 use Moose;
  1         1  
  1         7  
4              
5 1     1   5414 use Moose::Util qw( english_list );
  1         1  
  1         15  
6              
7             with qw(
8             Form::Factory::Feature
9             Form::Factory::Feature::Role::Check
10             );
11              
12 1     1   179 use Carp ();
  1         1  
  1         234  
13              
14             # ABSTRACT: if one control has a value, all should
15              
16              
17             has groups => (
18             is => 'ro',
19             isa => 'HashRef[ArrayRef[Str]]',
20             required => 1,
21             );
22              
23              
24             sub check {
25 13     13 1 31 my $self = shift;
26 13         523 my $action = $self->action;
27              
28 13         23 GROUP: for my $control_names (values %{ $self->groups }) {
  13         429  
29 26         44 my $has_a_value = 0;
30 26         32 my $has_all_values = 1;
31 26         32 my $valued_control;
32              
33 26         51 CONTROL: for my $name (@$control_names) {
34 72         2081 my $control = $action->controls->{$name};
35              
36 72         189 my $has_current_value = $control->has_current_value;
37 72   100     199 $has_a_value ||= $has_current_value;
38 72   100     187 $has_all_values &&= $has_current_value;
39              
40 72 100       123 $valued_control = $name if $has_current_value;
41              
42 72 100 100     277 if ($has_a_value and not $has_all_values) {
43 9         273 $self->result->is_valid(0);
44 27         51 $self->result->error(
45             sprintf('if you enter a value in %s you must enter a value for %s',
46             $self->_control_label($valued_control),
47 9         305 english_list(map { $self->_control_label($_) } @$control_names),
48             )
49             );
50 9         43 next GROUP;
51             }
52             }
53             }
54              
55 13 100       480 $self->result->is_valid(1) unless $self->result->is_validated;
56             }
57              
58             sub _control_label {
59 36     36   46 my ($self, $name) = @_;
60 36         1253 my $control = $self->action->controls->{$name};
61              
62 36 50       114 my $control_label
63             = $control->does('Form::Factory::Control::Role::Labeled') ? $control->label
64             : $control->name
65             ;
66              
67 36         126 return $control_label;
68             }
69              
70             __PACKAGE__->meta->make_immutable;
71              
72             __END__
73              
74             =pod
75              
76             =encoding UTF-8
77              
78             =head1 NAME
79              
80             Form::Factory::Feature::RequireNoneOrAll - if one control has a value, all should
81              
82             =head1 VERSION
83              
84             version 0.022
85              
86             =head1 SYNOPSIS
87              
88             package MyApp::Action::Foo;
89             use Form::Factory::Processor;
90              
91             use_feature require_none_or_all => {
92             groups => {
93             password => [ qw(
94             old_password
95             new_password
96             confirm_password
97             ) ],
98             },
99             };
100              
101             has_control old_password => (
102             control => 'password',
103             prediate => 'has_old_password',
104             );
105              
106             has_control new_password => (
107             control => 'password',
108             );
109              
110             has_control confirm_password => (
111             control => 'password',
112             );
113              
114             sub run {
115             my $self = shift;
116              
117             if ($self->has_old_password) {
118             # change password, we know new_password and confirm_password are set
119             }
120             }
121              
122             =head1 DESCRIPTION
123              
124             This feature allows you to make groups of controls work together. If any one of the named controls have a value when checked, then all of them must or the form will be invalid and an error will be displayed.
125              
126             =head1 ATTRIBUTES
127              
128             =head2 groups
129              
130             This is how the control groups are configured. Each key is used to name a control group and the values are arrays of controls that are grouped together. This way more than one none-or-all requirement can be set on a given form.
131              
132             At this time, the control group names are ignored, but might be used in the future for linking additional settings together.
133              
134             =head1 METHODS
135              
136             =head2 check
137              
138             This runs the checks to make sure that for each group of controls, either all have a value or none do.
139              
140             =head1 AUTHOR
141              
142             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
143              
144             =head1 COPYRIGHT AND LICENSE
145              
146             This software is copyright (c) 2015 by Qubling Software LLC.
147              
148             This is free software; you can redistribute it and/or modify it under
149             the same terms as the Perl 5 programming language system itself.
150              
151             =cut