package Form::Factory::Feature::RequireNoneOrAll;
$Form::Factory::Feature::RequireNoneOrAll::VERSION = '0.021';
use Moose;
use Moose::Util qw( english_list );
with qw(
Form::Factory::Feature
Form::Factory::Feature::Role::Check
);
use Carp ();
=head1 NAME
Form::Factory::Feature::RequireNoneOrAll - if one control has a value, all should
=head1 VERSION
version 0.021
=head1 SYNOPSIS
package MyApp::Action::Foo;
use Form::Factory::Processor;
use_feature require_none_or_all => {
groups => {
password => [ qw(
old_password
new_password
confirm_password
) ],
},
};
has_control old_password => (
control => 'password',
prediate => 'has_old_password',
);
has_control new_password => (
control => 'password',
);
has_control confirm_password => (
control => 'password',
);
sub run {
my $self = shift;
if ($self->has_old_password) {
# change password, we know new_password and confirm_password are set
}
}
=head1 DESCRIPTION
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.
=head1 ATTRIBUTES
=head2 groups
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.
At this time, the control group names are ignored, but might be used in the future for linking additional settings together.
=cut
has groups => (
is => 'ro',
isa => 'HashRef[ArrayRef[Str]]',
required => 1,
);
=head1 METHODS
=head2 check
This runs the checks to make sure that for each group of controls, either all have a value or none do.
=cut
sub check {
my $self = shift;
my $action = $self->action;
GROUP: for my $control_names (values %{ $self->groups }) {
my $has_a_value = 0;
my $has_all_values = 1;
my $valued_control;
CONTROL: for my $name (@$control_names) {
my $control = $action->controls->{$name};
my $has_current_value = $control->has_current_value;
$has_a_value ||= $has_current_value;
$has_all_values &&= $has_current_value;
$valued_control = $name if $has_current_value;
if ($has_a_value and not $has_all_values) {
$self->result->is_valid(0);
$self->result->error(
sprintf('if you enter a value in %s you must enter a value for %s',
$self->_control_label($valued_control),
english_list(map { $self->_control_label($_) } @$control_names),
)
);
next GROUP;
}
}
}
$self->result->is_valid(1) unless $self->result->is_validated;
}
sub _control_label {
my ($self, $name) = @_;
my $control = $self->action->controls->{$name};
my $control_label
= $control->does('Form::Factory::Control::Role::Labeled') ? $control->label
: $control->name
;
return $control_label;
}
=head1 AUTHOR
Andrew Sterling Hanenkamp C<< <hanenkamp@cpan.org> >>
=head1 COPYRIGHT AND LICENSE
Copyright 2009 Qubling Software LLC.
This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
1;