array(
array(
'key' => 'size',
'type' => 'width',
'label' => __( 'How wide', '2ranq-forms' ),
'help' => __( 'Two half fields sit side by side in one row.', '2ranq-forms' ),
'default' => 'full',
'options' => array(
'full' => __( 'Whole row', '2ranq-forms' ),
'half' => __( 'Half', '2ranq-forms' ),
'third' => __( 'Third', '2ranq-forms' ),
),
),
array(
'key' => 'label',
'type' => 'text',
'label' => __( 'Label', '2ranq-forms' ),
),
array(
'key' => 'description',
'type' => 'textarea',
'label' => __( 'Description', '2ranq-forms' ),
'help' => __( 'Shown under the field.', '2ranq-forms' ),
),
array(
'key' => 'required',
'type' => 'toggle',
'label' => __( 'Required', '2ranq-forms' ),
),
),
'advanced' => array(
array(
'key' => 'placeholder',
'type' => 'text',
'label' => __( 'Placeholder', '2ranq-forms' ),
),
array(
'key' => 'required_message',
'type' => 'text',
'label' => __( 'Message when empty', '2ranq-forms' ),
'help' => __( 'Leave empty to use the default message.', '2ranq-forms' ),
),
array(
'key' => 'label_hidden',
'type' => 'toggle',
'label' => __( 'Hide label', '2ranq-forms' ),
),
array(
'key' => 'default_value',
'type' => 'text',
'label' => __( 'Starting value', '2ranq-forms' ),
'help' => __( 'Filled in before the visitor types anything.', '2ranq-forms' ),
),
array(
'key' => 'css_class',
'type' => 'text',
'label' => __( 'CSS class', '2ranq-forms' ),
),
),
'logic' => array(
array(
'key' => 'conditional',
'type' => 'conditional',
'label' => __( 'Show this field only when', '2ranq-forms' ),
'help' => __( 'Leave empty and the field is always shown.', '2ranq-forms' ),
),
),
);
}
/**
* Prints the field on the site.
*
* @param array $field The field settings.
* @param int $form_id The form id.
*
* @return void
*/
abstract public function render( $field, $form_id );
/**
* Cleans a value that arrived from a visitor.
*
* What arrives is never trusted. This is the only point through which a
* value enters the plugin.
*
* @param mixed $value The raw value.
* @param array $field The field settings.
*
* @return mixed
*/
public function sanitize( $value, $field ) {
unset( $field );
return sanitize_text_field( is_scalar( $value ) ? (string) $value : '' );
}
/**
* Validates the value. Returns an error message, or an empty string when
* everything is fine.
*
* This runs on the server, always, no matter that the browser already
* checked the same thing.
*
* @param mixed $value The cleaned value.
* @param array $field The field settings.
*
* @return string An empty string means it passed.
*/
public function validate( $value, $field ) {
if ( ! empty( $field['required'] ) && '' === trim( (string) $value ) ) {
return $this->required_message( $field );
}
return '';
}
/**
* The value prepared for display in the entry and in the email.
*
* @param mixed $value The cleaned value.
* @param array $field The field settings.
*
* @return string
*/
public function format_value( $value, $field ) {
unset( $field );
return is_array( $value ) ? implode( ', ', array_map( 'strval', $value ) ) : (string) $value;
}
/**
* The message shown when a required field is left empty.
*
* @param array $field The field settings.
*
* @return string
*/
protected function required_message( $field ) {
if ( ! empty( $field['required_message'] ) ) {
return (string) $field['required_message'];
}
return __( 'This field is required.', '2ranq-forms' );
}
/**
* Extra classes on the field wrapper: the width and whatever the person
* typed in themselves.
*
* @param array $field The field settings.
*
* @return string Starts with a space, or is empty.
*/
/**
* Attributes on the field wrapper: the conditional logic rules.
*
* They are printed as a plain attribute, so the script reads them and hides
* the field right away, while the person is still filling the form in. The
* server checks the same rules again.
*
* @param array $field The field settings.
*
* @return string Starts with a space, or is empty.
*/
protected function wrapper_data( $field ) {
$logic = Ranq_Forms_Conditions::attribute( $field );
return '' === $logic ? '' : ' data-ranq-cond="' . esc_attr( $logic ) . '"';
}
protected function extra_classes( $field ) {
$classes = array();
$size = isset( $field['size'] ) ? sanitize_key( $field['size'] ) : 'full';
// A field that failed validation is marked, so it is obvious which one it is.
$errors = Ranq_Forms_Submission::get_errors();
$key = $this->field_key( $field );
if ( '' !== $key && isset( $errors[ $key ] ) ) {
$classes[] = 'has-error';
}
if ( in_array( $size, array( 'half', 'third' ), true ) ) {
$classes[] = 'ranq-field--' . $size;
}
if ( ! empty( $field['css_class'] ) ) {
foreach ( preg_split( '/\s+/', (string) $field['css_class'] ) as $custom ) {
$custom = sanitize_html_class( $custom );
if ( '' !== $custom ) {
$classes[] = $custom;
}
}
}
return $classes ? ' ' . implode( ' ', $classes ) : '';
}
/**
* The name the value arrives under in the request.
*
* @param array $field The field settings.
*
* @return string
*/
protected function input_name( $field ) {
return 'ranq_fields[' . $this->field_key( $field ) . ']';
}
/**
* The key of the field inside the form.
*
* @param array $field The field settings.
*
* @return string
*/
protected function field_key( $field ) {
return isset( $field['id'] ) ? sanitize_key( $field['id'] ) : '';
}
/**
* The value the field shows when the form comes back after a failed send.
*
* A send can fail long after the visitor wrote their text: a required field
* was missed, the spam check said no, the page had been cached for a week. A
* blank form at that moment throws the whole message away, and nobody types
* it twice. So every field that can, gives the text back. The value is
* cleaned by the field's own sanitize(), because what came in is as raw as
* any other sent value. Null means there is nothing to give back, and the
* field falls back to its default. A password and a file stay out of this on
* purpose: a password is never printed back into a page, and a browser does
* not allow a file input to be prefilled at all.
*
* @param array $field The field settings.
* @param int $form_id The form id.
*
* @return mixed The cleaned sent value, or null when there is none.
*/
protected function sticky_value( $field, $form_id ) {
$raw = Ranq_Forms_Submission::posted_raw( $form_id, $this->field_key( $field ) );
if ( null === $raw ) {
return null;
}
return $this->sanitize( $raw, $field );
}
/**
* The element id in the HTML, has to be unique per form.
*
* @param array $field The field settings.
* @param int $form_id The form id.
*
* @return string
*/
protected function input_id( $field, $form_id ) {
return 'ranq-field-' . absint( $form_id ) . '-' . $this->field_key( $field );
}
/**
* Prints the field label above the input.
*
* @param array $field The field settings.
* @param int $form_id The form id.
*
* @return void
*/
protected function render_label( $field, $form_id ) {
if ( ! empty( $field['label_hidden'] ) || empty( $field['label'] ) ) {
return;
}
?>
input_id( $field, $form_id ) . '-desc';
}
}