=pod

=head1 NAME

Form::Tiny::Manual - reference for working with Form::Tiny

=head1 SYNOPSIS

	use Form::Tiny -base;
	use Types::Common::String qw(SimpleStr);
	use Types::Common::Numeric qw(PositiveInt);


	form_field "name" => (
		type => SimpleStr,
		adjust => sub { ucfirst shift },
		required => 1,
	);

	form_field "lucky_number" => (
		type => PositiveInt,
		required => 1,
	);

	form_cleaner sub {
		my ($self, $data) = @_;

		if ($data->{name} eq "Perl" && $data->{lucky_number} == 6) {
			$self->add_error(
				Form::Tiny::Error::DoesNotValidate->new(
					error =>"Perl6 is now Raku"
				)
			);
		}
	};

=head1 DESCRIPTION

L<Form::Tiny> is a form validation engine that can use all the type constraints you're already familiar with. The module does not ship with any field definitions on its own, instead it provides tools to reuse any type constraints from L<Type::Tiny> and other similar systems.

=head2 Policy

L<Form::Tiny> is designed to be a comprehensive data validation and filtering system based on existing validation solutions. Type::Tiny libraries cover most of the validation and coercion needs in models, and now with Form::Tiny they can be empowered to do the same with input data.

The module itself isn't much more than a hashref filter - it accepts one as input and returns the transformed one as output. The pipeline is as follows:

	input
	  |
	  |--> filtering -- coercion -- validation -- adjustment -- cleaning --|
	                                                                       v
	                                                                     output

I<(Note that not every step on that pipeline is ran every time - it depends on form configuration)>

The module always tries to get as much data from input as possible and copy that into output. B<It will never copy any data that is not explicitly specified in the form fields configuration>.

=head2 Moose-like syntax sugar

Starting with version 1.10, Form::Tiny now allows and encourages you to define forms much like you would define a Moose class. The new syntax is presented below:

	use Form::Tiny -base, -filtered; # -strict is also possible

	# basic form field definitions
	form_field 'name' => (
		type => Int,
		required => 1,
		... # the rest of a normal Form::Tiny field definition
	);

	form_field 'surname' => (
		...
	);

	# will run the sub for cleaning up the form
	form_cleaner sub {
		my ($self, $data) = @_;
		... # perform cleaning
	};

	# will filter Int values before they get validated
	form_filter Int, sub { abs shift };

Adding any argument to C<use Form::Tiny> line will cause it to enable this syntax. Currently supported flags are:

=over

=item * C<-base> - imports Moo into your package (turning it into a Moo class and enabling all Moo keywords), mixes in the L<Form::Tiny> role and adds C<form_field> and C<form_cleaner> functions to your namespace. This flag is optional if you specify any other flag for the import.

=item * C<-strict> - mixes in the L<Form::Tiny::Strict> role.

=item * C<-filtered> - mixes in the L<Form::Tiny::Filtered> role and adds C<form_filter> function to your namespace.

=back

This way you can have syntax that resembles and mixes in with Moose syntax. This may however be a suboptimal option if for example you want your class to use Moose instead of Moo or have more control over class building.

=head2 Composing as a role

If you don't want to have Moo imported automatically or want to create something a bit more complicated or custom, see L<Form::Tiny::Manual::Internals>.

=head2 Basic usage

Input can be passed as a hashref to the constructor or with the I<set_input> method. Every call to that method will cause the form instance to be cleared, so that it can be used again for different data.

	use MyForm;

	# either ...
	my $form = MyForm->new(input => \%data);

	# or ...
	my $form = MyForm->new;
	$form->set_input(\%data);

With input in place, a I<valid> method can be called, which will return a validation result and fill in the I<errors> and I<fields> properties. These properties are mutually exclusive: errors are only present if the validation is unsuccessful, otherwise the fields are present.

The example below illustrates how a form class could be used to validate data.

	use MyForm;

	my $form = MyForm->new;
	$form->set_input($some_input);

	if ($form->valid) {
		my $fields = $form->fields; # a hash reference
		...
	} else {
		my $errors = $form->errors; # an array reference
		...
	}

=head2 Form building

You can use I<form_field> function to declare form fields, just like you would use I<has> to declare class properties in Moo/se.

Each of field definition will be coerced into an object of the L<Form::Tiny::FieldDefinition> class.

	form_field 'some_name';
	form_field 'another_name' => (
		required => 'soft',
	);

	form_field 'complex_field' => sub {
		my ($self) = @_;

		return {
			required => 1,
			adjust => sub { $self->some_method(shift) },
		};
	};

The only required element of this hashref is key I<name>, which contains the string with name of the field in the form input. In I<form_field>, the name B<should not> be given explicitly, as it will be automatically overwritten by the first argument to that function. Other possible elements are:

=over

=item type

The type that the field will be validated against. Effectively, this needs to be an object with I<validate> and I<check> methods implemented. All types from Type::Tiny meet this criteria.

=item coerce

A coercion that will be made B<before> the type is validated and will change the value of the field. This can be a coderef or a boolean:

Value of I<1> means that coercion will be applied from the specified I<type>. This requires the type to also provide I<coerce> and I<has_coercion> method, and the return value of the second one must be true.

Value of I<0> means no coercion will be made. This is the default behavior.

Value that is a coderef will be passed a single scalar, which is the value of the field. It is required to make its own checks and return a scalar which will replace the old value.

=item adjust

An adjustment that will be made B<after> the type is validated and the validation is successful. This must be a coderef that gets passed the validated value and returns the new value for the field (just like the coderef version of coercion).

At the point of adjustment, you can be sure that the value passed to the coderef meets the type constraint specified. It's probably a good idea to provide a type along with the adjustment to avoid unnecessary checks in the subroutine - if no type is specified, then any value from the input data will end up in the coderef.

=item required

Controls if the field should be skipped silently if it has no value or the value is empty. Possible values are:

I<0> - The field can be non-existent in the input, empty or undefined. This is the default behavior

I<"soft"> - The field has to exist in the input, but can be empty or undefined

I<1> or I<"hard"> - The field has to exist in the input, must be defined and non-empty (a value I<0> is allowed, but an empty string is disallowed)

=item default

A coderef, which should return a scalar value that will be used in place of a non-existent input value. If the field is marked as hard-required as well, the default value will also replace undefined or empty values.

The default value needs to be in line with the type check for the field, if it is specified. It also does not support nested arrays, like I<array.*>. An exception will be thrown if these conditions are not met.

=item message

A static string that should be output instead of an error message returned by the I<type> when the validation fails.

=item data

While building your form fields, it's possible to save some extra data along with each field. This data can be used to prompt the user what to input, insert some HTML generation objects or store hints on how to fill the field properly.

	use Types::Common::String qw(NonEmptySimpleStr);

	form_field "first name" => (
		type => NonEmptySimpleStr,
		data => {
			element => "input",
			properties => {
				type => "text",
			},
		},
	);

The data field can hold any value you want and later retrieved with an instantiated form object:

	for my $def (@{$form->field_defs}) {
		say "field: " . $def->name;
		say "data: " . Dumper($def->data);
	}

=back

=head2 Cleaning

While the above properties allow for single-field validation, sometimes a need arises to check if some fields are synchronized correctly, or even to perform some more complex validation. This can be done with the I<cleaner> method, which will be only fired after the validation for every individual field was successful. The cleaner subroutine should look like this:

	sub {
		my ($self, $data) = @_;

		# do something with $data
		# call $self->add_error if necessary
	};

A subroutine like the one above should either be returned by I<build_cleaner> method, or specified in a I<form_cleaner> helper call.

	# either ...
	sub build_cleaner {
		return sub { ... }; # cleaner sub
	}

	# or
	form_cleaner sub { ... };

Cleaning sub is also allowed to change the $data, which is a hash reference to the running copy of the input. Note that this is the final step in the validation process, so anything that is in $data after cleaning will be available in the form's I<fields> after validation.

=head2 Optional behavior

Attaching more behavior to the form is possible by overriding I<pre_mangle> and I<pre_validate> methods in the final class. These methods do nothing by default, but roles that are introducing extra behavior set up C<around> hooks for them. It's okay not to invoke the SUPER version of these methods if you're overriding them, but you need to explicitly return the value you're passed in these methods.

B<pre_mangle> is fired for every field, just before it is changed ("mangled"). In addition to an object reference, this method will be passed the definition of the field (L<Form::Tiny::FieldDefinition>) and a scalar value of the field. The field must exist in the input data for this method to fire, but can be undefined. The return value of this method will become the new value for the field.

	sub pre_mangle {
		my ($self, $field_definition, $value) = @_;

		# do something with $value

		# don't forget to return!
		return $value;
	}

B<pre_validate> is fired just once for the form, before any field is validated. It is passed a single hashref - a copy of the input data. This method is free to do anything with the input, and its return value will become the real input to the validation.

	sub pre_validate {
		my ($self, $input_data) = @_;

		# do something with $input_data

		# don't forget to return!
		return $input_data;
	}

The module provides two roles which use these mechanisms to achieve common tasks.

=over

=item * L<Form::Tiny::Strict>

Enables strict mode for the form. Validation will fail if the form input contains any data not specified in the field definitions. Can also be mixed in with I<-strict> flag.

=item * L<Form::Tiny::Filtered>

Enables initial filtering for the input fields. By default, this will only cause strings to be trimmed, but any code can be attached to any field that meets a given type constraint. See the role documentation for details. Can also be mixed in with I<-filtered> flag.

=back

=head2 Inline forms

The module also enables a way to create a form without the need of a dedicated package. This is done with the L<Form::Tiny::Inline> class. This requires the user to pass all the data to the constructor, as shown in the example:

	my $form = Form::Tiny::Inline # An inline form ...
	           ->is(qw/Strict/)   # ... with the strict role mixed in (strict mode) ...
	           ->new(             # ... will be created with properties:
		field_defs => [{name => "my_field"}],
		cleaner => sub { ... },
	);

The names changes a little - form_fields calls become a I<field_defs> property, I<form_cleaner> becomes just a I<cleaner> property. For filtered forms, I<form_filter> becomes I<filters> property.

=head2 Advanced topics

=head3 Nested fields

A dot (I<.>) can be used in the name of a field to express hashref nesting. A field with C<< name => "a.b.c" >> will be expected to be found under the key "c", in the hashref under the key "b", in the hashref under the key "a", in the root input hashref.

This is the default behavior of a dot in a field name, so if what you want is the actual dot it has to be preceded with a backslash (I<\.>).

=head3 Nested arrays

Nesting adds many new options, but it can only handle hashes. Regular arrays can of course be handled by I<ArrayRef> type from Type::Tiny, but that's a hassle. Instead, you can use a star (I<*>) as the only element inside the nesting segment to expect an array there. Adding named fields can be resumed after that, but needn't.

For example, C<< name => "arr.*.some_key" >> expects I<arr> to be an array reference, with each element being a hash reference containing a key I<some_key>. Note that any array element that fails to contain wanted hash elements will cause the field to be ignored in the output (since input does not meet the specification entirely). If you want the validation to fail instead, you need to make the nested element required.

	# This input data ...
	{
		arr => [
			{ some_key => 1 },
			{ some_other_key => 2 },
			{ some_key => 3 },
		]
	}

	# Would not get copied into output and ignored, because the second element does not meet the specification
	# Make the element required to make the validation fail instead

Other example is two nested arrays that not necessarily contain a hash at the end: C<< name => "arr.*.*" >>. The leaf values here can be simple scalars.

=head3 Nested forms

Every form class created with I<Form::Tiny> is a consumer of L<Form::Tiny::Form> role, and can be used as a field definition type in other form. The outer and inner forms will validate independently, but inner form errors will be added to outer form with the outer field name prepended.

	# in Form2
	# everything under "nested" key will be validated using Form1 instance
	# every error for "nested" will also start with "nested"
	form_field "nested" => (
		type => Form1->new,
	);

Be aware of a special case, an adjustment will be inserted here automatically like the following:

	adjust => sub { $instance->fields }

this will make sure that any coercions and adjustments made in the nested form will be added to the outer form as well. If you want to specify your own adjustment here, make sure to use the data provided by the I<fields> method of the nested form.

=head3 Mixing form fields with class fields

It is possible and often very helpful to have both form and class fields inside the same form class:

	use Form::Tiny -base;
	use Types::Standard qw(Str);

	has 'user' => (
		is => 'rw',
	);

	form_field 'username' => (
		type => Str,
		required => 1,
	);

	form_field 'password' => (
		type => Str,
		required => 1,
	);

	form_cleaner sub {
		my ($self, $data) = @_;

		# load user from the storage service using $data->{username}
		my $user = ...;
		if ($user->validate_password($data->{password})) {
			# set the user for the class, will be available after validation
			$self->user($user);
		}
		else {
			$self->add_error(
				Form::Tiny::Error::DoesNotValidate->new(
					field => 'password',
					error => 'invalid password'
				)
			);
		}
	};

While doing so, make sure not to override any of the Form::Tiny symbols (Moo / Moose should complain about it when it happens).

=head1 SEE ALSO

=over

=item * L<Type::Tiny>, the awesome type system

=item * L<Form::Tiny>, the base class for this distribution

=back
