Form Schema
The FormSchema system provides a structured JSON representation of forms. It enables programmatic form manipulation, REST API field management, and round-tripping between HTML and structured data.
Schema Structure
{
"version": 1,
"fields": [
{
"name": "email",
"type": "email",
"label": "Email Address",
"placeholder": "you@example.com",
"required": true,
"position": 0,
"validation": { "pattern": "^[^@]+@[^@]+$" },
"conditions": [],
"attributes": { "autocomplete": "email" }
},
{
"name": "message",
"type": "textarea",
"label": "Your Message",
"placeholder": "Tell us more...",
"required": false,
"position": 1
}
],
"layout": {
"type": "single"
},
"form_settings": {}
}
Top-Level Properties
| Property | Type | Description |
|---|---|---|
version |
int | Schema format version (currently 1) |
fields |
Field[] | Ordered array of field definitions |
layout |
object | Layout configuration |
form_settings |
object | Schema-level form settings |
Layout Types
| Type | Description |
|---|---|
single |
Standard single-page form |
multi-step |
Multi-step wizard with navigation |
conversational |
One question at a time (fullscreen) |
Field Object
Each field has these properties:
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string | Yes | Unique identifier (maps to input name) |
|
type |
string | Yes | text |
Field type (see types below) |
label |
string | No | "" |
Human-readable label |
placeholder |
string | No | "" |
Placeholder text |
default_value |
string | No | "" |
Pre-filled value |
required |
bool | No | false |
Whether the field is required |
css_class |
string | No | "" |
CSS classes for the field |
description |
string | No | "" |
Help text shown below the field |
options |
array | No | [] |
Options for select/radio/checkbox |
validation |
object | No | {} |
Validation rules (min, max, pattern) |
conditions |
array | No | [] |
Conditional visibility rules |
attributes |
object | No | {} |
HTML attributes |
position |
int | No | 0 |
Display order (0-based) |
group |
string | No | null |
Step or group name |
Field Types
Input types: text, email, url, tel, number, date, time, datetime-local, password, color, range, hidden
Complex types: textarea, select, radio, checkbox, file
Composite types: name, address, consent, rating
Layout types: container, fieldset, heading, paragraph, divider
Action types: submit
Options Format
For select, radio, and checkbox fields:
{
"name": "priority",
"type": "select",
"options": [
{ "value": "low", "label": "Low Priority" },
{ "value": "medium", "label": "Medium Priority" },
{ "value": "high", "label": "High Priority" }
]
}
Validation Rules
{
"name": "age",
"type": "number",
"validation": {
"min": 18,
"max": 120,
"pattern": "^[0-9]+$"
}
}
Conditional Logic
{
"name": "other_reason",
"type": "textarea",
"conditions": [
{
"field": "reason",
"operator": "equals",
"value": "other"
}
]
}
Storage
Schemas are stored as post meta on the form post:
Meta key: _cf_form_schema
Meta value: JSON array (version, fields, layout, form_settings)
PHP API
FormSchema Class
use Core_Forms\Schema\FormSchema;
// Load from database
$schema = FormSchema::load( $form_id );
// Create from array
$schema = FormSchema::from_array( $data );
// Check if schema exists
if ( FormSchema::exists( $form_id ) ) { ... }
// Save to database
$schema->save( $form_id );
// Delete
FormSchema::delete( $form_id );
Working with Fields
use Core_Forms\Schema\Field;
// Add a field
$field = Field::from_array( [
'name' => 'phone',
'type' => 'tel',
'label' => 'Phone',
'required' => false,
] );
$schema->add_field( $field );
// Get a field
$email = $schema->get_field( 'email' );
// Remove a field
$schema->remove_field( 'phone' );
// Get only input fields (excludes headings, dividers, submit)
$inputs = $schema->get_input_fields();
// Get required field names
$required = $schema->get_required_field_names();
Convert to Array/JSON
$array = $schema->to_array();
$json = wp_json_encode( $schema ); // Uses JsonSerializable
MarkupParser: HTML to Schema
The MarkupParser class converts existing HTML form markup into a structured schema:
use Core_Forms\Schema\MarkupParser;
$parser = new MarkupParser();
$schema = $parser->parse( $html_markup );
Use the REST API to trigger parsing:
POST /wp-json/cf/v1/forms/{id}/schema/generate
SchemaRenderer: Schema to HTML
The SchemaRenderer class converts a schema back to HTML markup. The output can be filtered with cf_schema_markup:
$html = $renderer->render( $schema );
$html = apply_filters( 'cf_schema_markup', $html, $schema, $form );