PHP Hook Reference
Form Plant provides WordPress action / filter hooks at almost every stage of form behavior — submission processing, email sending, redirects, file uploads, fields, form settings, and more. Just add a hook in functions.php ( or similar ) to extend and customize behavior without modifying the plugin itself.
Hooks for input validation ( fplant_validate_* / fplant_validation_message_*, etc. ) are collected on Validation Hooks (PHP). This page covers everything else.
A rewrite mapping table from mwform_* hooks, with before/after examples, is available in Migrating from MW WP Form. Please refer to it as well.
Hook basics
Targeting a specific form
Many hooks fire for all forms on the site. If you want to target only a specific form, check the form ID ( $form_id ) inside your callback. The form ID is the number in the placement shortcode [fplant id="12"] or in the editor URL ( ...&id=12 ) .
add_filter( 'fplant_redirect_url', function ( $url, $form_id, $data ) {
if ( 12 !== $form_id ) {
return $url; // Return as-is for forms other than the target
}
return home_url( '/thanks/' );
}, 10, 3 );
Hooks targeted by field name (dynamic hooks)
Some hooks let you append a field name to target only a specific field ( e.g. fplant_field_choices_{name} ). Internally these are called in two stages, "common across all fields → per-field version," and the per-field version receives the return value of the common version.
- Common version:
fplant_field_choices… includes$field_namein its arguments - Per-field version: embed the name, as in
fplant_field_choices_inquiry_type
The field name used in hook names and callbacks is the name ( alphanumeric key ) you can check on the form editor screen. If you migrated from MW WP Form, Japanese names have been converted to alphanumeric ( e.g. お名前 → your_name ) .
Form display / submission control
Since v1.2.1, forms respect the post status. Published forms can be viewed and submitted by anyone, while private, draft, and pending-review forms are not shown to or submittable by general visitors — only users who can edit the form can preview and test-submit them. You can override this decision with the following filters.
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_form_is_viewable | filter | ( $viewable, $form ) | Whether the form may be displayed on the front end 🆕 |
fplant_form_is_submittable | filter | ( $submittable, $form ) | Whether the form accepts submissions 🆕 |
fplant_preview_notice | filter | ( $notice, $form ) | The HTML of the preview notice shown above an unpublished form 🆕 |
$form is a form array that includes id and status. Returning true allows display/submission regardless of status.
When a user with edit permission views an unpublished form, a preview notice reading "This form is not published" appears at the top. You can replace the text with fplant_preview_notice or return an empty string to hide it. This is useful for cases like members-only forms ( where fplant_form_is_viewable allows display to members ) , where the form is shown to non-editors too.
Example: revert to allowing all statuses to be viewed/submitted as before
add_filter( 'fplant_form_is_viewable', '__return_true' );
add_filter( 'fplant_form_is_submittable', '__return_true' );
Example: display only a specific form even when unpublished
add_filter( 'fplant_form_is_viewable', function ( $viewable, $form ) {
if ( 12 === (int) $form['id'] ) {
return true;
}
return $viewable;
}, 10, 2 );
Example: members-only form ( show an unpublished form only to logged-in members )
This example lets logged-in members view and submit an unpublished form, and hides the editor-facing preview notice.
// Allow form ID 12 to be viewed/submitted by anyone who is logged in
add_filter( 'fplant_form_is_viewable', function ( $viewable, $form ) {
return ( 12 === (int) $form['id'] && is_user_logged_in() ) ? true : $viewable;
}, 10, 2 );
add_filter( 'fplant_form_is_submittable', function ( $submittable, $form ) {
return ( 12 === (int) $form['id'] && is_user_logged_in() ) ? true : $submittable;
}, 10, 2 );
// Do not show the "unpublished" preview notice to members
add_filter( 'fplant_preview_notice', function ( $notice, $form ) {
return ( 12 === (int) $form['id'] ) ? '' : $notice;
}, 10, 2 );
Submission lifecycle
A form submission is processed in the following order. Hooks are provided at each stage. They are color-coded as ■ action / ■ filter.
| Hook | Type | Arguments | Timing / purpose |
|---|---|---|---|
fplant_before_submission | action | ( $form_id, $data ) | Before validation. For logging or preprocessing raw data |
fplant_sanitize_field_value | filter | ( $sanitized_value, $raw_value, $field, $form_id ) | Replace the sanitization of field types without a dedicated sanitizer ( text-like and custom field types ) . Return value = the value to store 🆕 v1.4.0 |
fplant_submission_data | filter | ( $data, $form_id ) | Modify data right after sanitization. Return value = the modified data |
fplant_before_save_submission_data | filter | ( $data, $form_id ) | Modify data right before saving to the DB ( before password masking ) . Also useful for unset-ing specific keys to exclude them from saving. Return value = the data to save |
fplant_after_submission | action | ( $submission_id, $form_id, $data ) | After saving to the DB, before sending emails |
fplant_after_submission_complete | action | ( $data, $form_id, $form, $submission_id ) | After emails are sent. The go-to hook for integrating with external services |
Example: integrate with an external service after submission completes
add_action( 'fplant_after_submission_complete', function ( $data, $form_id, $form, $submission_id ) {
if ( 12 !== $form_id ) {
return;
}
// e.g. notify Slack or a CRM
wp_remote_post( 'https://example.com/webhook', array(
'body' => array(
'submission_id' => $submission_id,
'email' => $data['email'] ?? '',
),
'timeout' => 5,
) );
}, 10, 4 );
Example: do not save a specific field to the DB
add_filter( 'fplant_before_save_submission_data', function ( $data, $form_id ) {
// Exclude fields you don't want to store, such as a credit card number
unset( $data['card_number'] );
return $data;
}, 10, 2 );
Post-submission actions (completion message / redirect)
Depending on the "Post-submission action" in the form settings, exactly one of these fires. All were added in v1.2.0.
| Hook | Type | Arguments | Setting that enables it |
|---|---|---|---|
fplant_complete_message | filter | ( $message, $form_id, $data, $form ) | "Message" |
fplant_success_html | filter | ( $html, $form_id, $data, $form ) | "Custom page" ( the HTML after placeholder replacement ) |
fplant_redirect_url | filter | ( $url, $form_id, $data, $form ) | "Redirect" ( before esc_url_raw ) |
The 4th argument
$form( the full form configuration array ) was added in v1.4.0. Use it for conditions based on form settings.
Example: change the completion message based on input values
add_filter( 'fplant_complete_message', function ( $message, $form_id, $data ) {
if ( 12 === $form_id ) {
$name = $data['your_name'] ?? 'Customer';
$message = 'Dear ' . $name . ', thank you for your inquiry.';
}
return $message;
}, 10, 3 );
Example: branch the redirect target by plan
add_filter( 'fplant_redirect_url', function ( $url, $form_id, $data ) {
if ( 12 === $form_id && 'premium' === ( $data['plan'] ?? '' ) ) {
$url = home_url( '/thanks-premium/' );
}
return $url;
}, 10, 3 );
Webhooks
Deliveries of the generic webhook feature ( added in v1.4.0; see Webhooks for an overview ) can be customized with filters.
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_webhook_should_send | filter | ( $should_send, $webhook, $payload, $form_id, $data ) | Return false to skip the delivery. For conditional delivery |
fplant_webhook_payload | filter | ( $payload, $form_id, $data, $submission_id ) | Modify the JSON payload |
fplant_webhook_request_args | filter | ( $args, $url ) | Change the wp_safe_remote_post() arguments ( timeout etc. ) |
fplant_webhook_allow_http | filter | ( $allow, $url ) | Return true to allow http:// URLs ( local development ) |
Example: skip delivery when a field is empty
add_filter( 'fplant_webhook_should_send', function ( $should_send, $webhook, $payload, $form_id, $data ) {
if ( 12 === $form_id && empty( $data['company'] ) ) {
return false; // don't forward submissions without a company name
}
return $should_send;
}, 10, 5 );
Example: add a custom item to the payload
add_filter( 'fplant_webhook_payload', function ( $payload, $form_id, $data, $submission_id ) {
$payload['environment'] = wp_get_environment_type();
return $payload;
}, 10, 4 );
Email sending
Paired hooks are provided for the admin email and the auto-reply ( user ) email. Replacing admin with user gives you the auto-reply side.
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_before_admin_email_send | action | ( $email_settings, $form_id ) | At the start of admin email processing |
fplant_skip_admin_email | filter | ( $skip, $form, $data, $submission_id ) | Return true to skip sending 🆕 |
fplant_before_send_email_data | filter | ( $data, $form, $submission_id, $type ) | Modify data before generating the body. $type is 'admin' / 'user' ( shared hook ) |
fplant_admin_email_to | filter | ( $to, $form_id, $data ) | The admin recipient ( array ) . An empty array skips sending 🆕 |
fplant_admin_email_subject | filter | ( $subject, $form_id, $data ) | Subject ( $data added in v1.4.0 ) |
fplant_admin_email_body | filter | ( $message, $form_id, $data ) | Body |
fplant_admin_email_headers | filter | ( $headers, $form_id, $data ) | Headers ( From / Cc / Bcc / Reply-To ) 🆕 |
fplant_after_admin_email_send | action | ( $email_settings, $form_id, $result ) | After wp_mail() runs. $result is success/failure |
Auto-reply side: fplant_before_user_email_send / fplant_skip_user_email 🆕 / fplant_user_email_to 🆕 / fplant_user_email_subject / fplant_user_email_body / fplant_user_email_headers 🆕 / fplant_after_user_email_send.
🆕 = added in v1.2.0.
The admin recipient ( fplant_admin_email_to ) returns an array, assuming multiple recipients, while the auto-reply recipient ( fplant_user_email_to ) returns a single string. The 2nd argument $form of fplant_skip_admin_email / fplant_skip_user_email is the form array, not the form ID ( get the ID with $form['id'] ) .
Example: route the admin email recipient based on input
add_filter( 'fplant_admin_email_to', function ( $to, $form_id, $data ) {
if ( 12 === $form_id && 'sales' === ( $data['category'] ?? '' ) ) {
$to = array( 'sales@example.com' );
}
return $to;
}, 10, 3 );
Example: add a BCC
add_filter( 'fplant_admin_email_headers', function ( $headers, $form_id, $data ) {
if ( 12 === $form_id ) {
$headers[] = 'Bcc: archive@example.com';
}
return $headers;
}, 10, 3 );
Example: do not send the auto-reply under certain conditions
add_filter( 'fplant_skip_user_email', function ( $skip, $form, $data, $submission_id ) {
if ( (int) $form['id'] === 12 && empty( $data['newsletter'] ) ) {
return true; // Cancel sending
}
return $skip;
}, 10, 4 );
File uploads
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_upload_dir | filter | ( $custom_dir, $form_id ) | The destination directory. $custom_dir is array( 'path' => ..., 'url' => ... ) 🆕 |
fplant_upload_filename | filter | ( $filename, $field_config, $form_id ) | The saved file name 🆕 |
The return value of fplant_upload_dir is restricted to within the WordPress uploads folder ( specifying outside it causes an error ) . The return value of fplant_upload_filename is re-sanitized, and dangerous extensions ( .php, etc. ) are rejected. These hooks are for organization ( date-based folders, naming conventions ) and cannot disable the protection mechanisms.
Example: save into year/month folders
add_filter( 'fplant_upload_dir', function ( $dir, $form_id ) {
$u = wp_upload_dir();
$sub = '/form-uploads/' . gmdate( 'Y-m' );
return array(
'path' => $u['basedir'] . $sub,
'url' => $u['baseurl'] . $sub,
);
}, 10, 2 );
Fields, choices, initial values
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_field_types | filter | ( $field_types ) | Add or change the definitions of available field types |
fplant_field_defaults | filter | ( $defaults, $field_type ) | Default settings per field type |
fplant_field_initial_value | filter | ( null, $field_name, $field, $form_id ) | A common initial value for all fields. Returning null passes to the next |
fplant_field_initial_value_{name} | filter | ( $value, $field, $form_id ) | A per-field initial value |
fplant_field_choices | filter | ( $options, $field_name, $field, $form_id ) | Common choices for all fields ( select / radio / checkbox ) 🆕 |
fplant_field_choices_{name} | filter | ( $options, $field, $form_id ) | Per-field choices 🆕 |
fplant_custom_mail_tag_value | filter | ( '', $field_name, $field, $form_id ) | The value of a custom mail tag ( common version ) 🆕 |
fplant_custom_mail_tag_value_{name} | filter | ( $value, $field, $form_id ) | The value of a custom mail tag ( per-field ) 🆕 |
Choices ( $options ) are an array of array( 'label' => display name, 'value' => value ).
Example: use the logged-in user's email as the initial value
add_filter( 'fplant_field_initial_value_email', function ( $value, $field, $form_id ) {
if ( is_user_logged_in() ) {
$value = wp_get_current_user()->user_email;
}
return $value;
}, 10, 3 );
Example: dynamically generate select choices from a post list
add_filter( 'fplant_field_choices_product', function ( $options, $field, $form_id ) {
foreach ( get_posts( array( 'post_type' => 'product' ) ) as $p ) {
$options[] = array( 'label' => $p->post_title, 'value' => (string) $p->ID );
}
return $options;
}, 10, 3 );
Example: inject the member rank into a custom mail tag
This supplies the value of a custom_mail_tag field ( name = member_rank ) via a hook.
add_filter( 'fplant_custom_mail_tag_value_member_rank', function ( $value, $field, $form_id ) {
return get_user_meta( get_current_user_id(), 'rank', true );
}, 10, 3 );
Extending form settings
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_custom_settings_fields | filter | ( $fields, $form_id ) | Add your own input fields to the form settings screen 🆕 |
fplant_form_settings_saved | action | ( $form_id, $settings ) | Right after the form settings are saved 🆕 |
Fields defined with fplant_custom_settings_fields are automatically rendered and saved on the settings screen, and can be referenced at runtime via $form['settings'][key].
Example: add a CRM endpoint URL input to the settings screen
add_filter( 'fplant_custom_settings_fields', function ( $fields, $form_id ) {
$fields[] = array(
'key' => 'x_crm_endpoint', // alphanumeric / underscore
'type' => 'text', // text / textarea / checkbox / select / number
'label' => 'CRM endpoint URL',
'description' => 'The CRM API endpoint',
);
return $fields;
}, 10, 2 );
// Use the saved value when submission completes
add_action( 'fplant_after_submission_complete', function ( $data, $form_id, $form, $submission_id ) {
if ( ! empty( $form['settings']['x_crm_endpoint'] ) ) {
// Processing that uses $form['settings']['x_crm_endpoint']
}
}, 10, 4 );
Templates / rendering
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_locate_template | filter | ( $template, $template_name, $template_path ) | Change the resolved path of a template file ( e.g. override on the theme side ) |
fplant_allowed_field_types | filter | ( $allowed_field_types ) | The whitelist of field types allowed in HTML templates |
fplant_template_values | filter | ( $values, $form_id ) | Inject values into {{key}} placeholders in the input screen HTML template, the confirmation screen template, and the completion page HTML ( values are esc_html-escaped ) |
For how to use the HTML template feature itself, see HTML Template.
Example: inject a dynamic value into a template
Write {{key}} in a template and it is replaced at render time with the value of that key in the array returned by the fplant_template_values filter. The replacement works in all three of the following places.
| Screen | Where to set it |
|---|---|
| Input screen | The input screen HTML template ( when "Use HTML template" is ON ) |
| Confirmation screen | The confirmation screen template ( when "Use confirmation screen HTML template" is ON ) |
| Completion screen | "Completion Page HTML" of the post-submission action |
add_filter( 'fplant_template_values', function ( $values, $form_id ) {
$values['today'] = wp_date( 'F j, Y' );
$values['shop_name'] = get_bloginfo( 'name' );
return $values;
}, 10, 2 );
Example confirmation screen template ( {{shop_name}} and {{today}} are replaced ) :
<h2>[fplant_confirmation_title]</h2>
<p>The following will be sent to {{shop_name}} ( received {{today}} ).</p>
[fplant_all_fields]
[fplant_back] [fplant_confirm_submit]
[fplant_all_fields] and the other tags above are confirmation-screen template tags ( they can be inserted from "Available Shortcodes" on the form edit screen ).
Since version 1.4.1, WordPress shortcodes are also expanded inside the confirmation screen template ( they are not expanded in 1.4.0 and earlier ). The value of this filter can also be the ( text ) output of a shortcode:
add_filter( 'fplant_template_values', function ( $values, $form_id ) {
// Example: show the output of a custom business-hours shortcode on the confirmation screen
$values['business_hours'] = do_shortcode( '[business_hours]' );
return $values;
}, 10, 2 );
- Values are escaped with
esc_html(), so only plain text can be injected ( HTML tags in a value are displayed as literal text ). - Replacement in iframe / JavaScript embeds works since version 1.4.1 ( 1.4.0 and earlier replace only for forms placed with the shortcode / block ).
- A
{{key}}whose key is not defined by the filter is left as is. - To inject values only into a specific form, branch on the second argument
$form_id.
Registering custom field types (for extension developers)
Plugins and themes can add their own field types ( the extension API was consolidated in v1.4.0 ). Registration takes just three filters:
| Step | Hook | Role |
|---|---|---|
| 1. Register the type | fplant_field_types | Show the type in the add-field dialog ( label, icon, description ) |
| 2. Allow rendering | fplant_allowed_field_types | Front-end rendering whitelist ( the field will not render at all if you forget this ) |
| 3. Resolve the template | fplant_locate_template | Serve form-fields/{type}.php from your own directory |
Example: adding a custom "rating" field type
// 1. Register the type
add_filter( 'fplant_field_types', function ( $types ) {
$types['rating'] = array(
'label' => 'Rating',
'icon' => 'dashicons-star-filled', // dashicons or your own CSS class
'description' => '5-star rating',
);
return $types;
} );
// 2. Add it to the rendering whitelist
add_filter( 'fplant_allowed_field_types', function ( $allowed ) {
$allowed[] = 'rating';
return $allowed;
} );
// 3. Resolve the template from your own directory
// ( $template arrives as an empty string when neither the theme nor
// the plugin itself provides the template )
add_filter( 'fplant_locate_template', function ( $template, $template_name, $template_path ) {
if ( '' !== (string) $template ) {
return $template; // respect theme overrides etc.
}
$candidate = plugin_dir_path( __FILE__ ) . 'templates/' . $template_name;
return file_exists( $candidate ) ? $candidate : $template;
}, 10, 3 );
For how to write the template file ( e.g. templates/form-fields/rating.php ), the built-in field
templates are a good reference ( see Overriding templates from a theme ).
Also implement the following:
- Validation: custom types pass through server-side validation except the required check.
Add server-side rules with the validation hooks (
fplant_validation_errorsetc. ), and instant client-side feedback withfplant.addValidator()if needed. - Sanitization: for types without a dedicated sanitizer, the stored value can be replaced per type
with
fplant_sanitize_field_value( see Submission lifecycle ). - Confirmation screen: the standard confirmation screen works as is. Only when a custom
confirmation template uses
[fplant_value name="..."]do you also need aconfirm-fields/{type}.phptemplate ( resolvable viafplant_locate_templateas well;[fplant_all_fields]does not need it ).
Storing structured (array) values
Since v1.4.0, custom field types can store array ( nested ) values as is.
- Submission data is stored as JSON, so array structures survive saving and re-reading
- Inputs with bracketed names such as
name="items[0][price]"are automatically collected as nested values ( row arrays / objects ) on submit ( see JavaScript Customization ) - The default sanitization applies text sanitization while preserving the structure
( replaceable via
fplant_sanitize_field_value)
Formatting submission values for display: fplant_format_submission_value
A shared filter ( v1.4.0 ) that formats a stored submission value as plain text. Every output path — the confirmation screen, emails, CSV export and the admin submission detail — goes through this formatting, so one hook unifies how your custom type is displayed.
| Argument | Description |
|---|---|
$formatted | The default formatting ( flat arrays are comma-joined; row arrays become numbered "label: value / …" lines ) |
$value | The raw stored value ( may be an array ) |
$field | The field configuration array |
$context | Output context: confirmation / email_all_fields / email_tag / admin_detail / csv_single / csv_all |
$form_id | Form ID ( 0 when unknown ) |
add_filter( 'fplant_format_submission_value', function ( $formatted, $value, $field, $context, $form_id ) {
if ( 'rating' !== ( $field['type'] ?? '' ) ) {
return $formatted;
}
return str_repeat( '★', (int) $value ); // e.g. 3 → ★★★
}, 10, 5 );
HTML is not supported here. Escaping and newline-to-<br> conversion are handled by each output
site, so returned HTML tags would be displayed as literal characters.
Attaching extra data to a submission (extras)
To attach your own data to a submission record ( e.g. a snapshot of settings at submit time ), use these static methods ( v1.4.0 ):
FPLANT_Database::set_submission_extra( $submission_id, $key, $value );
FPLANT_Database::get_submission_extra( $submission_id, $key, $default_value );
The submission ID is available from the fplant_after_submission /
fplant_after_submission_complete hooks.
Data export
| Hook | Type | Arguments | Purpose |
|---|---|---|---|
fplant_export_encoding | filter | ( $encoding, $form_id ) | The character encoding of the submission data CSV ( default UTF-8 ) 🆕 |
Example: output as Shift-JIS for Excel compatibility
add_filter( 'fplant_export_encoding', function ( $encoding, $form_id ) {
return 'sjis-win'; // Shift-JIS ( CP932 )
}, 10, 2 );
Hook list (quick reference)
🆕 = added in v1.2.0 / v1.2.1. 1.4 = added or arguments extended in v1.4.0.
| Hook | Type | Arguments |
|---|---|---|
fplant_form_is_viewable 🆕 | filter | ( $viewable, $form ) |
fplant_form_is_submittable 🆕 | filter | ( $submittable, $form ) |
fplant_preview_notice 🆕 | filter | ( $notice, $form ) |
fplant_before_submission | action | ( $form_id, $data ) |
fplant_sanitize_field_value 1.4 | filter | ( $sanitized_value, $raw_value, $field, $form_id ) |
fplant_submission_data | filter | ( $data, $form_id ) |
fplant_before_save_submission_data | filter | ( $data, $form_id ) |
fplant_after_submission | action | ( $submission_id, $form_id, $data ) |
fplant_after_submission_complete | action | ( $data, $form_id, $form, $submission_id ) |
fplant_complete_message 🆕 1.4 | filter | ( $message, $form_id, $data, $form ) |
fplant_success_html 🆕 1.4 | filter | ( $html, $form_id, $data, $form ) |
fplant_redirect_url 🆕 1.4 | filter | ( $url, $form_id, $data, $form ) |
fplant_webhook_should_send 1.4 | filter | ( $should_send, $webhook, $payload, $form_id, $data ) |
fplant_webhook_payload 1.4 | filter | ( $payload, $form_id, $data, $submission_id ) |
fplant_webhook_request_args 1.4 | filter | ( $args, $url ) |
fplant_webhook_allow_http 1.4 | filter | ( $allow, $url ) |
fplant_before_admin_email_send | action | ( $email_settings, $form_id ) |
fplant_skip_admin_email 🆕 | filter | ( $skip, $form, $data, $submission_id ) |
fplant_before_send_email_data | filter | ( $data, $form, $submission_id, $type ) |
fplant_admin_email_to 🆕 | filter | ( $to, $form_id, $data ) |
fplant_admin_email_subject 1.4 | filter | ( $subject, $form_id, $data ) |
fplant_admin_email_body | filter | ( $message, $form_id, $data ) |
fplant_admin_email_headers 🆕 | filter | ( $headers, $form_id, $data ) |
fplant_after_admin_email_send | action | ( $email_settings, $form_id, $result ) |
fplant_before_user_email_send | action | ( $email_settings, $form_id ) |
fplant_skip_user_email 🆕 | filter | ( $skip, $form, $data, $submission_id ) |
fplant_user_email_to 🆕 | filter | ( $to, $form_id, $data ) |
fplant_user_email_subject 1.4 | filter | ( $subject, $form_id, $data ) |
fplant_user_email_body | filter | ( $message, $form_id, $data ) |
fplant_user_email_headers 🆕 | filter | ( $headers, $form_id, $data ) |
fplant_after_user_email_send | action | ( $email_settings, $form_id, $result ) |
fplant_upload_dir 🆕 | filter | ( $custom_dir, $form_id ) |
fplant_upload_filename 🆕 | filter | ( $filename, $field_config, $form_id ) |
fplant_field_types | filter | ( $field_types ) |
fplant_field_defaults | filter | ( $defaults, $field_type ) |
fplant_field_initial_value ( _{name} ) | filter | ( $value, [$field_name,] $field, $form_id ) |
fplant_field_choices 🆕 ( _{name} ) | filter | ( $options, [$field_name,] $field, $form_id ) |
fplant_custom_mail_tag_value 🆕 ( _{name} ) | filter | ( $value, [$field_name,] $field, $form_id ) |
fplant_custom_settings_fields 🆕 | filter | ( $fields, $form_id ) |
fplant_form_settings_saved 🆕 | action | ( $form_id, $settings ) |
fplant_locate_template | filter | ( $template, $template_name, $template_path ) |
fplant_allowed_field_types | filter | ( $allowed_field_types ) |
fplant_template_values | filter | ( $values, $form_id ) |
fplant_format_submission_value 1.4 | filter | ( $formatted, $value, $field, $context, $form_id ) |
fplant_export_encoding 🆕 | filter | ( $encoding, $form_id ) |
For validation hooks (
fplant_validate_*/fplant_validation_message_*/fplant_before_validation/fplant_validation_errors), see Validation Hooks (PHP).
Security notes
- Always escape input received through hooks with
esc_html()/esc_attr()/esc_url(), etc. before output. - For processes that call external APIs, set a
timeoutand cache with the Transient API as needed. - The protection mechanisms of
fplant_upload_dir/fplant_upload_filename( restricted to under uploads, extension blacklist ) cannot be disabled.