Cornerstone Forms Developer Guide

Learn how to integrate with Cornerstone Forms or extend its functionality.

  1. Actions API
  2. Validations API
  3. Input API
  4. Form Context API
  5. Submission API
  6. Frontend API
  7. Utility Functions
  8. PHP Actions & Filters

Actions API

Registering a Custom Action

cs_form_action_register(string $type, array $config)

This function handles registering a custom actions. Actions are also elements, however they have additional processing and helpers.

When using actions you don't need to specify omega data or controls. Loopers and conditions will be setup for you in this function.

Throwing an error in your render function will stop all future actions from running. It will also display a global form error on your page.

Action Example

The following is a sample from the Option Delete action.

<?php namespace Cornerstone\Forms\Actions\OptionDelete; use DomainException; // Values function values() { return [ 'key' => cs_value('', 'markup'), ]; } // Controls / Builder function controls() { return [ 'control_nav' => [ 'element' => __( 'Action', 'cornerstone' ), 'element:general' => __( 'General', 'cornerstone' ), ], 'controls' => [ [ 'type' => 'group', 'group' => 'element:general', 'controls' => [ // Key [ 'key' => 'key', 'type' => 'text', 'label' => __('Key', 'cornerstone'), 'description' => __('The name of the option key you wish to delete.', 'cornerstone'), 'options' => [ 'placeholder' => __('Option Key', 'cornerstone'), ], ], ], ], ], ]; } // Render / Action function render($data) { // Double check any option was passed if (empty($data['key'])) { throw new DomainException(__('No option key passed to Option Delete', 'cornerstone')); } // Update option delete_option($data['key']); return ''; } // Action register cs_form_action_register('cornerstone-actions-option-delete', [ 'title' => __('Option Delete', 'cornerstone'), 'values' => values(), 'icon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/></svg>', 'builder' => __NAMESPACE__ . '\controls', 'render' => __NAMESPACE__ . '\render', ]);

Action Helpers

cs_form_action_types()

The cs_form_action_types function will grab a string array of all Action element types.

Action Filters

cs_actions_can_run

You can utilize this filter to force actions not to run. The first argument will be true if a form submitted and has no errors. The second is the actual request data from the user. And the third argument is the data from the Form element in Cornerstone.

The following example checks if the form has data for the name run-actions.

add_filter('cs_actions_can_run', function($result, $formData, $formElement) { if (!$result) { return $result; } return !empty($formData['run-actions']); }, 10, 3);

Validations API

Registering a Custom Validation

cs_form_validation_register(string $type, array $config)

This function handles registering a custom validation.

label✔stringLocalized title to display under the validation selector.
validate✔functionThe main validation function.
controlsfunctionUsing Cornerstones Element API to build out controls or a function that returns an array.
valuesarrayAssociative array which saves value data used in controls.
KeyRequiredTypeDescription

Example

The following is a sample from the Number Comparison validation.

<?php /** * Number comparison validation * Such as >, <, == */ use Cornerstone\Forms\Validations; Validations::register('number-comparison', [ 'label' => __('Number Comparison', 'cornerstone'), 'values' => [ 'comparison' => '>=', 'compare_to' => 0, ], 'controls' => function() { // @TODO move for Conditionals.php as well $numeric_operators = apply_filters('cs_numeric_operators', [ 'eq' => '==', 'not-eq' => '!=', 'gt' => '>', //'gte' => '>=', // @TODO 'lt' => '<', //'lte' => '<=' // @TODO ]); $numeric_operators = cs_array_as_choices(array_values($numeric_operators)); return [ [ 'type' => 'select', 'label' => __('Comparison', 'cornerstone'), 'key' => 'comparison', 'options' => [ 'choices' => $numeric_operators, ], ], [ 'type' => 'text', 'label' => __('Compare To', 'cornerstone'), 'key' => 'compare_to', ], ]; }, 'validate' => function($value, $data) { $valid = false; $value = (float)$value; $compareTo = (float)$data['compare_to']; switch ($data['comparison']) { case '>': $valid = $value > $compareTo; break; case '<': $valid = $value < $compareTo; break; case '!=': $valid = $value !== $compareTo; break; case '==': $valid = $value === $compareTo; break; } return $valid; }, ]);

Helper Functions

cs_form_validate_element($element, $data)

Runs all configured validations on a single element against the provided request data. Returns an associative array of errors keyed by input name, or an empty array if all validations pass. This includes the required check even if it is set via the element's required flag rather than the validations list.

$errors = cs_form_validate_element($element, $data); if (!empty($errors)) { // handle errors }

cs_form_input_has_validation_type($element, $type)

You can utilize this function to check if a certain validation type exists on an element.

$hasCharacterComparison = cs_form_input_has_validation_type($element, 'character-comparison');

cs_form_input_is_required($element)

This function will check if an input element has the required validation or has Required selected. It internally also uses cs_form_input_has_validation_type.

$isRequired = cs_form_input_is_required($element);

Input API

Regsiter Custom Input Type

Registering a custom input will make sure your element only will show up in a Form, and will run validations.

cs_form_input_element_register($type, $config = [])

  • $type The element type name. Should be unique
  • $config this is the same config as the in the Element API.

There is an additional key option for $config called form_validate. You will be sent the request data and the element config as the second argument.

Below is an example of registering your own Custom Input. This element will always fail to validate.

<?php cs_form_input_element_register('my-custom-input', [ 'title' => __('My Custom Input', 'cornerstone'), 'values' => [ 'auto_fail' => cs_value(true, 'markup:bool'), ], 'builder' => function() { return []; }, 'render' => function() { return cs_tag('input', [], '...'); }, 'options' => [ 'form_validate' => function($data, $element) { if (!empty($element['auto_fail'])) { return [ $element['name'] => __('This element has auto_fail set to true.', 'cornerstone'), ]; } return null; }, ], ]);

Form Context API

The Form Context API lets you read and interact with the current form's state during page rendering. This is useful when building custom elements, template parts, or Dynamic Content that needs to know whether a form was submitted or had errors.

cs_form_set_context($data)

Sets the active form context. This is called internally when a Form element renders, but you can use it if you need to manually establish a form context outside of the normal rendering pipeline.

cs_form_remove_context()

Removes the currently active form context. Call this after manually setting a context to clean up when done.

cs_form_get_context()

Returns the current form context data array, or null if no context is active.

cs_form_has_context()

Returns true if a form context is currently active.

cs_form_did_submit()

Returns true if the current form context was submitted in this request.

if (cs_form_did_submit()) { // form was submitted }

cs_form_did_submit_without_errors()

Returns true if the current form was submitted and passed all validations with no errors.

if (cs_form_did_submit_without_errors()) { // show success message }

cs_form_context_id()

Returns the element ID of the currently active form.

cs_form_context_has_errors()

Returns true if the current form context has any validation errors.

cs_form_context_get_errors()

Returns the full errors array for the current form context, keyed by input name. The special key __global holds form-level errors not tied to a specific input.

cs_form_context_get_errors_json()

Returns the errors array encoded as a JSON string.

cs_form_add_error($error, $name = '__global')

Programmatically adds an error to the current form context. The $name parameter ties the error to a specific input. If omitted, the error is added as a global form error.

cs_form_add_error(__('Something went wrong.', 'my-plugin')); cs_form_add_error(__('Email is already in use.', 'my-plugin'), 'email');

cs_form_add_input($input)

Registers a single input name into the current form context. Only registered inputs are accepted when reading submitted data via cs_form_input_data.

cs_form_add_inputs($inputs)

Registers an array of input names at once into the current form context.

cs_form_get_inputs()

Returns the array of input names currently registered in the form context.

cs_form_input_data($key = '', $default = '')

Reads submitted form data for the current context. Only values for registered inputs are returned. Pass a $key to retrieve a single value, or omit it to get all input data as an associative array.

// All submitted values $allData = cs_form_input_data(); // Single value with a fallback $email = cs_form_input_data('email', '');

cs_form_set_validated()

Marks the current form context as having been validated. This is called internally after the validation pipeline runs.

cs_form_has_validated()

Returns true if the current form context has already run through validation.

Submission API

cs_form_has_any_submission()

Returns true if any form submission request is present in the current request, regardless of which form or whether it was valid.

cs_form_submitted_id()

Will return the form ID of the currently submitting form. Will return null if not submitting any Form.

cs_form_user_has_submitted($formID = null, $userID = null)

If no formID is specified it will use the current form context, or the nearest parent form ID. If no User is specified it will use the current logged in users ID.

cs_form_count_submissions($formID = null)

This function will count the number of submissions a form has based on the given form ID. If none specified it will use the nearest parent form ID.

Form Submitted Actions

The actions cs_form_submitted_successfully and cs_form_submitted_successfully_{FORM_ID} will run whenever a form is submitted and had no errors. This WordPress action happens after your Form Actions have run.

This example will use wp_mail to send an email for all form submissions.

add_action('cs_form_submitted_successfully', function($formData, $formElement) { wp_mail('me@example.com', 'Form submitted : ' . $formElement['id'], json_encode($formData)); }, 10, 2); add_action('cs_form_submitted_successfully_contact', function($formData, $formElement) { wp_mail('me@example.com', 'Contact form submitted', json_encode($formData)); }, 10, 2);

cs_form_submission_request

This action triggers whenever a form request has happened. When a form is sent the whole output will be in an output buffer, meaning you can alter and add headers to the request at any point.

In this example log the user id for every form submission request.

add_action('cs_form_submission_request', function() { $logFile = '/tmp/submission.log'; $logData = date() . ' - ' . get_current_user_id(); file_put_contents($logFile, $logData, FILE_APPEND); });

Frontend API

Filtering Form Data

Using the frontend filter cs_forms_submission_data, you can add additional processing to the frontend. This can be used to add additional data, remove data, or change how certain data is sent to your site. We use this interally for the CheckboxList delimiter return type.

In this example we remove form data for the input named uneeded_input.

window.addEventListener('load', function() { window.csGlobal.csHooks.filter('cs_forms_submission_data', function(formData, form) { formData.delete('uneeded_input'); return formData; }); });

Mapping inputs

The frontend filter cs_forms_inputs_by_name can be used to map a certain input to another input for validation purposes.

In this example, we change the validation to check a different input mapped by the attribute data-mapped-id.

const hooks = window.csGlobal.csHooks; hooks.filter('cs_forms_inputs_by_name', function(inputs) { return inputs.map(function(input) { const mappedID = input.getAttribute('data-mapped-id'); const mappedElement = document.getElementByID(mappedID); return mappedElement ? mappedElement : input; }); });

Datepicker / Flatpickr Filter

The filter cornerstone-form-datepicker can be used to alter our Datpicker. Internally we use Flatpickr and you can use this filter to utilize the library to do more advanced operations.

const hooks = window.csGlobal.csHooks; hooks.filter('cornerstone-form-datepicker', function(FlatpickrInstance, element, params) { // Alter FlatpickrInstance ... });

Utility Functions

cs_form_is_valid_file($file, $acceptedFiles)

Validates an uploaded file against an accepted types string. $file is a single entry from $_FILES (with name, type, tmp_name, error, and size keys). $acceptedFiles is a comma-separated string of allowed types, which can be MIME types (image/jpeg), wildcards (image/*), or file extensions (.pdf). Returns true if the file is acceptable.

This is used internally by the Dropzone element but is available if you are building a custom file input.

$isValid = cs_form_is_valid_file($file, 'image/*,application/pdf,.psd');

cs_forms_human_readable_value($value)

Formats any form value into a sanitized, human-readable string. Booleans become True or False, strings are HTML-escaped, and arrays are rendered as a comma-separated key: value list. Useful when displaying submitted data in email notifications or custom output.

echo cs_forms_human_readable_value($submittedValue);

PHP Actions & Filters

cs_forms_pre_boot

Fires before the Cornerstone Forms plugin initializes. Use this to register anything that needs to be in place before elements and actions are loaded.

add_action('cs_forms_pre_boot', function() { // runs before forms boot });

cs_forms_booted

Fires after Cornerstone Forms has fully initialized and all elements, actions, and validations are registered.

add_action('cs_forms_booted', function() { // forms are fully loaded });

cs_forms_dashboard_controls (filter)

Filters the array of controls shown on the Cornerstone Forms dashboard settings page. Used internally by captcha integrations to add their API key fields. You can use this to add your own settings to the dashboard.

add_filter('cs_forms_dashboard_controls', function($controls) { $controls[] = [ 'type' => 'text', 'key' => 'my_api_key', 'label' => __('My API Key', 'my-plugin'), ]; return $controls; });

cs_forms_php_directory (filter)

Filters the directory path where the PHP Action element writes its temporary PHP files before executing them. Defaults to the system temp directory under cornerstone/forms/. Override this if you need those files written to a different location.

add_filter('cs_forms_php_directory', function($dir) { return WP_CONTENT_DIR . '/my-custom-tmp/'; });

cs_forms_always_output_buffer (filter)

By default, Cornerstone Forms only activates output buffering when a form submission is present in the request. Return true from this filter to force output buffering on every request, regardless of whether a form was submitted.

add_filter('cs_forms_always_output_buffer', '__return_true');

See something inaccurate? Let us know