<commit_before># WFV
## WordPress Form Validation

#### *Declarative input validation API for WordPress*

Intended for developers who want to build forms in a theme using custom markup and validate the input in a declarative way.


# Table of Contents
1. [Basic Example](#basic-example)
2. [Problem](#problem)
3. [Solution](#solution)
4. [Features](#features)
5. [TODO](#todo)
6. [Install](#install)
7. [Usage](#usage)
    1. [Rules](#configure-validation-rules)
    2. [Custom Rules](#custom-validation-rules)
    3. [Error Messages](#custom-error-messages)
    4. [Validation Action](#callback-for-successful-validation)
    5. [Validation Instance](#create-the-validation-instance)
    6. [Markup a Form](#create-a-form-somewhere-in-your-theme)
    7. [Retrieve User Input](#retrieve-user-input)
    8. [Retrieve Errors](#retrieve-error-messages)

## Basic example

`functions.php` or in some plugin:
```php
<?php

// declare the rules
$my_form = array(
  'action'  => 'contact_form',
  'rules'   => array(
    'first_name' => ['required'],
    'email'      => ['required', 'email']
  )
);

// hook for validation pass
function my_form_valid( $form ) {
  // form validated, do something...
}
add_action( $my_form['action'], 'my_form_valid' );

// activate the form
wfv_create( $my_form );

```
Theme template:
```php
<form method="post">
  <input name="first_name" type="text">
  <input name="email" type="text">
  <?php $my_form->get_token_fields(); ?>
  <input type="submit" value="Send">
</form>
```
<br>

---


## Problem
Working with custom forms in WordPress presents several challenges:

WordPress does not have an elegant way to validate user input. It does not offer much beyond some general [sanitation methods](https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data).

And,

The [WordPress way](https://codex.wordpress.org/Plugin_API/Action_Reference/admin_post_%28action%29) to work with `$_POST` is to create an action hook that triggers after a http request to `/wp-admin/admin-post.php`

This means when the form is submitted, the user is sent to `http://yoursite.com/wp-admin/admin-post.php`.

Why is this a problem?

The user is no longer on the form. To send them back (i.e a required field was missed), we need to do a HTTP redirect. At this point the `$_POST` with the input is gone... which would have been useful to repopulate the form. In order to persist the users input, it needs to be stored in `GET`, a session, or a cookie.

Neither is elegant, and both are clunky.

Far too common the solution to `SELF_POST` the form is to capture the `$_POST` and run the logic in a template file. Albeit this solves the redirect problem, having logic in a template file is a poor separation of concerns and an anti-pattern. It gets messy and confusing fast.

Most form building plugins have large footprints that generate rendered markup configured through the admin dashboard. Although it sounds much easier to point and click, and drag and drop; until something breaks or it can't meet some specific requirement. Enter hacks...

## Solution
WFV gives you the ability to declare form validation constraints in a similar way found in MVC frameworks such as [Laravel](https://laravel.com/).

Markup a form in a template and define its constraints in `functions.php` or a plugin.

WFV uses [Valitron](https://github.com/vlucas/valitron) as the validation library.

## Features
Just an API for input validation with WordPress.

...nothing more, nothing less

* 32 built-in validation rules from [Valitron](https://github.com/vlucas/valitron#built-in-validation-rules)
* Create custom rules
* Default and custom error messages
* Self POST. No redirects, GET vars, sessions, or cookies
* Declarative API
* None intrusive and lightweight
* Stays away from your admin dashboard
* No rendered markup
* Developer freedom

## TODO
- Expose an api for the front end to support singe configuration.
- Standardize storage for default error messages.

# Install

Currently there is no release available.

Under active development

If you can't wait, install as development.

`$ git clone` inside `./wp-content/plugins`

`$ composer install`

Once a release is packaged, install will be the usual WordPress way.

# Usage

## Configure validation rules

```php
<?php
$my_form = array(
  'action'  => 'contact_form', // unique identifier
  'rules'   => array(
    'name'      => ['required'],
    'email'     => ['required', 'email'],
  )
);
```

For available validation rules, reference the [Valitron](https://github.com/vlucas/valitron#built-in-validation-rules) doc.

## Custom validation rules

Prepend `custom:` to rule, name of rule is the callback.
```php
<?php
$my_form = array(
  'action'  => 'contact_form', // unique identifier
  'rules'   => array(
    'name'      => ['required'],
    'email'     => ['required', 'email'],
    'phone'     => ['required', 'custom:phone']
  )
);
```
Create the callback:
```php
<?php
// phone field will validate only if the input is 'hi' ...how cruel
function wfv__phone( $value ) {
  return ( 'hi' === $value ) ? true : false;
}
```

## Custom error messages

```php
<?php
$my_form = array(
  'action'  => 'contact_form', // unique identifier
  'rules'   => array(
    'name'      => ['required'],
    'email'     => ['required', 'email'],
    'msg'       => ['required']
  ),

  // override an error msg
  'messages' => [
    'email' => array(
      'required' => 'Your email is required so we can reply back'
    )
  ]<commit_msg>readme - simplfied and shortened $form array examples<commit_after># WFV
## WordPress Form Validation

#### *Declarative input validation API for WordPress*

Intended for developers who want to build forms in a theme using custom markup and validate the input in a declarative way.


# Table of Contents
1. [Basic Example](#basic-example)
2. [Problem](#problem)
3. [Solution](#solution)
4. [Features](#features)
5. [TODO](#todo)
6. [Install](#install)
7. [Usage](#usage)
    1. [Rules](#configure-validation-rules)
    2. [Custom Rules](#custom-validation-rules)
    3. [Error Messages](#custom-error-messages)
    4. [Validation Action](#callback-for-successful-validation)
    5. [Validation Instance](#create-the-validation-instance)
    6. [Markup a Form](#create-a-form-somewhere-in-your-theme)
    7. [Retrieve User Input](#retrieve-user-input)
    8. [Retrieve Errors](#retrieve-error-messages)

## Basic example

`functions.php` or in some plugin:
```php
<?php

// declare the rules
$my_form = array(
  'action'  => 'contact_form',
  'rules'   => array(
    'first_name' => ['required'],
    'email'      => ['required', 'email']
  )
);

// hook for validation pass
function my_form_valid( $form ) {
  // form validated, do something...
}
add_action( $my_form['action'], 'my_form_valid' );

// activate the form
wfv_create( $my_form );

```
Theme template:
```php
<form method="post">
  <input name="first_name" type="text">
  <input name="email" type="text">
  <?php $my_form->get_token_fields(); ?>
  <input type="submit" value="Send">
</form>
```
<br>

---


## Problem
Working with custom forms in WordPress presents several challenges:

WordPress does not have an elegant way to validate user input. It does not offer much beyond some general [sanitation methods](https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data).

And,

The [WordPress way](https://codex.wordpress.org/Plugin_API/Action_Reference/admin_post_%28action%29) to work with `$_POST` is to create an action hook that triggers after a http request to `/wp-admin/admin-post.php`

This means when the form is submitted, the user is sent to `http://yoursite.com/wp-admin/admin-post.php`.

Why is this a problem?

The user is no longer on the form. To send them back (i.e a required field was missed), we need to do a HTTP redirect. At this point the `$_POST` with the input is gone... which would have been useful to repopulate the form. In order to persist the users input, it needs to be stored in `GET`, a session, or a cookie.

Neither is elegant, and both are clunky.

Far too common the solution to `SELF_POST` the form is to capture the `$_POST` and run the logic in a template file. Albeit this solves the redirect problem, having logic in a template file is a poor separation of concerns and an anti-pattern. It gets messy and confusing fast.

Most form building plugins have large footprints that generate rendered markup configured through the admin dashboard. Although it sounds much easier to point and click, and drag and drop; until something breaks or it can't meet some specific requirement. Enter hacks...

## Solution
WFV gives you the ability to declare form validation constraints in a similar way found in MVC frameworks such as [Laravel](https://laravel.com/).

Markup a form in a template and define its constraints in `functions.php` or a plugin.

WFV uses [Valitron](https://github.com/vlucas/valitron) as the validation library.

## Features
Just an API for input validation with WordPress.

...nothing more, nothing less

* 32 built-in validation rules from [Valitron](https://github.com/vlucas/valitron#built-in-validation-rules)
* Create custom rules
* Default and custom error messages
* Self POST. No redirects, GET vars, sessions, or cookies
* Declarative API
* None intrusive and lightweight
* Stays away from your admin dashboard
* No rendered markup
* Developer freedom

## TODO
- Expose an api for the front end to support singe configuration.
- Standardize storage for default error messages.

# Install

Currently there is no release available.

Under active development

If you can't wait, install as development.

`$ git clone` inside `./wp-content/plugins`

`$ composer install`

Once a release is packaged, install will be the usual WordPress way.

# Usage

## Configure validation rules

```php
<?php
$my_form = array(
  'action'  => 'contact_form', // unique identifier
  'rules'   => array(
    'first_name' => ['required'],
    'email'      => ['required', 'email'],
  )
);
```

For available validation rules, reference the [Valitron](https://github.com/vlucas/valitron#built-in-validation-rules) doc.

## Custom validation rules

Prepend `custom:` to rule, name of rule is the callback.
```php
<?php
$my_form = array(
  'action'  => 'contact_form', // unique identifier
  'rules'   => array(
    'phone'      => ['required', 'custom:phone'],
  )
);
```
Create the callback:
```php
<?php
// phone field will validate only if the input is 'hi' ...how cruel
function wfv__phone( $value ) {
  return ( 'hi' === $value ) ? true : false;
}
```

## Custom error messages

```php
<?php
$my_form = array(
  'action'  => 'contact_form', // unique identifier
  'rules'   => array(
    'email'     => ['required', 'email']
  ),

  // override an error msg
  'messages' => [
    'email' => array(
      'required' => 'No email, no reply... get it?'
    )
  ]
{'fraction_non_alphanumeric': 0.12354183889041977, 'fraction_numerical': 0.0038578120694406173, 'mean_word_length': 3.97396071265418, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 57, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '549911', 'n_tokens_mistral': 3318, 'n_tokens_neox': 3179, 'n_words': 1268}