: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( is_array( $field_submit ) ) {
$field_submit = array_filter( $field_submit );
$field_submit = implode( "\r\n", $field_submit );
$name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? sanitize_text_field( $form_data['fields'][ $field_id ]['label'] ) : '';
// Sanitize but keep line breaks.
$value = wpforms_sanitize_textarea_field( $field_submit );
wpforms()->get( 'process' )->fields[ $field_id ] = [
'id' => wpforms_validate_field_id( $field_id ),
* Return images, if any, for HTML supported values.
* @param string $value Field value.
* @param array $field Field settings.
* @param array $form_data Form data and settings.
* @param string $context Value display context.
public function field_html_value( $value, $field, $form_data = [], $context = '' ) {
if ( wpforms_payment_has_quantity( $field, $form_data ) ) {
return wpforms_payment_format_quantity( $field );
// Only use HTML formatting for checkbox fields, with image choices
// enabled, and exclude the entry table display. Lastly, provides a
// filter to disable fancy display.
! empty( $field['value'] ) &&
$field['type'] === $this->type &&
$context !== 'entry-table' &&
$this->filter_field_html_value_images( $context )
return $this->get_field_html( $field, $value, $form_data );
* Return HTML for a field value.
* @since 1.8.9 Add $form_data parameter.
* @param array $field Field settings.
* @param string $value Field value.
* @param array $form_data Form data.
private function get_field_html( $field, $value, $form_data ) {
if ( ! empty( $field['image'] ) ) {
$value = wpforms_get_choices_value( $field, $form_data );
return $this->get_field_html_image( $field['image'], $value );
if ( ! empty( $field['images'] ) ) {
$value = wpforms_get_choices_value( $field, $form_data );
$values = explode( "\n", $value );
foreach ( $values as $key => $choice_label ) {
if ( ! empty( $field['images'][ $key ] ) ) {
$choice_label = $this->get_field_html_image( $field['images'][ $key ], $choice_label );
$items[] = $choice_label;
return implode( '', $items );
* Return image HTML for a field value.
* @param string $url Image URL.
* @param string $label Field value.
private function get_field_html_image( $url, $label ) {
'<span style="max-width:200px;display:block;margin:0 0 5px 0;"><img src="%s" style="max-width:100%%;display:block;margin:0;" alt=""></span>%s',
* Return boolean determining if field HTML values uses images.
* Bail if field type is not set.
* @param string $context Context of the field.
private function filter_field_html_value_images( $context ) {
* Filters whether to use HTML formatting for a field with image choices enabled.
* @param bool $use_html Whether to use HTML formatting.
* @param string $context Value display context.
return (bool) apply_filters( "wpforms_{$this->type}_field_html_value_images", true, $context ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
* Get field name for an ajax error message.
* @param string|mixed $name Field name for error triggered.
* @param array $field Field settings.
* @param array $props List of properties.
* @param string|string[] $error Error message.
* @noinspection PhpMissingReturnTypeInspection
* @noinspection ReturnTypeCanBeDeclaredInspection
* @noinspection PhpMissingParamTypeInspection
public function ajax_error_field_name( $name, $field, $props, $error ) {
if ( is_array( $error ) && isset( $props['inputs'][ key( $error ) ] ) ) {
// Handle separate error messages for composed fields like name or date_time.
$input = $props['inputs'][ key( $error ) ];
$input = $props['inputs']['primary'] ?? end( $props['inputs'] );
return (string) isset( $input['attr']['name'] ) ? $input['attr']['name'] : '';
* Exclude empty dynamic choices from the entry preview.
* @param bool $hide Whether to hide the field.
* @param array $field Field data.
* @param array $form_data Form data.
public function exclude_empty_dynamic_choices( $hide, $field, $form_data ) {
if ( empty( $field['dynamic'] ) ) {
$field_id = $field['id'];
$fields = $form_data['fields'];
$form_field = $fields[ $field_id ];
return $this->is_dynamic_choices_empty( $form_field, $form_data );
* Enqueue Choicesjs script and config.
* @param array $forms Forms on the current page.
protected function enqueue_choicesjs_once( $forms ) {
if ( wpforms()->get( 'frontend' )->is_choicesjs_enqueued ) {
WPFORMS_PLUGIN_URL . 'assets/lib/choices.min.js',
'removeItemButton' => true,
// Forces the search to look for exact matches anywhere in the string.
'loadingText' => esc_html__( 'Loading...', 'wpforms-lite' ),
'noResultsText' => esc_html__( 'No results found', 'wpforms-lite' ),
'noChoicesText' => esc_html__( 'No choices to choose from', 'wpforms-lite' ),
'uniqueItemText' => esc_html__( 'Only unique values can be added', 'wpforms-lite' ),
'customAddItemText' => esc_html__( 'Only values matching specific conditions can be added', 'wpforms-lite' ),
* Allow theme/plugin developers to modify the provided or add own Choices.js settings.
* @param array $config Choices.js settings.
* @param array $forms Forms on the current page.
* @param WPForms_Field $field_obj Field object.
$config = apply_filters( 'wpforms_field_select_choicesjs_config', $config, $forms, $this );
'wpforms_choicesjs_config',
wpforms()->get( 'frontend' )->is_choicesjs_enqueued = true;
* Whether a Choicesjs search area should be shown.
* @param int $choices_count Choices amount.
protected function is_choicesjs_search_enabled( $choices_count ) {
// We should auto hide/remove search, if less than 8 choices.
return $choices_count >= (int) apply_filters( 'wpforms_field_choicesjs_search_enabled_items_min', 8 );
* Whether a Choicesjs search area should be shown for quantity select.
* @param array $field Field data.
protected function is_quantity_choicesjs_search_enabled( $field ) {
if ( ! isset( $field['max_quantity'] ) || ! isset( $field['min_quantity'] ) ) {
$choices_count = (int) $field['max_quantity'] - (int) $field['min_quantity'];
* We should auto hide/remove search, if less than 20 choices.
* @param int $limit Minimum limit.
return $choices_count >= (int) apply_filters( 'wpforms_field_quantity_choicesjs_search_enabled_items_min', 20 );
* Get instance of the class connected to the current field,
* and located in the `src/Forms/[Pro/]Fields/FieldType/Class.php` file.
* @param string $class_name Class name, for example `Frontend`.
protected function get_object( $class_name ) {
$property = strtolower( $class_name ) . '_obj';
if ( ! is_null( $this->$property ) ) {
$class_dir = implode( '', array_map( 'ucfirst', explode( '-', $this->type ) ) );
$class_name = ucfirst( $class_name );
$class_name = 'Forms\Fields\\' . $class_dir . '\\' . $class_name;
$fqdn_class = '\WPForms\Pro\\' . $class_name;
$fqdn_class = class_exists( $fqdn_class ) ? $fqdn_class : '\WPForms\Lite\\' . $class_name;
$fqdn_class = class_exists( $fqdn_class ) ? $fqdn_class : '\WPForms\\' . $class_name;
$this->$property = class_exists( $fqdn_class ) ? new $fqdn_class( $this ) : null;
* Add allowed HTML tags for field labels.
* @param array $strings Array of strings.
public function add_allowed_label_html_tags( $strings ) {
* Filter the allowed HTML tags for field labels.
* @param array $allowed_tags Allowed HTML tags.
$strings['allowed_label_html_tags'] = (array) apply_filters( 'wpforms_field_label_allowed_html_tags', $allowed_tags );
* Whether a field has dynamic choices.
* @param array $field Field settings.
protected function is_dynamic_choices( $field ) {
return ! empty( $field['dynamic_choices'] );
* Whether a field has dynamic choices and they are empty.
* @param array $field Field settings.
* @param array $form_data Form data and settings.
protected function is_dynamic_choices_empty( $field, $form_data ) {
if ( ! $this->is_dynamic_choices( $field ) ) {
$form_id = absint( $form_data['id'] );
$dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data );
return empty( $dynamic );
* Get empty dynamic choices message.
* @param array $field Field data and settings.
protected function get_empty_dynamic_choices_message( $field ) {
$dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
if ( empty( $field[ 'dynamic_' . $dynamic ] ) ) {
$source = esc_html__( 'Dynamic choices', 'wpforms-lite' );
$type = esc_html__( 'items', 'wpforms-lite' );
if ( $dynamic === 'post_type' ) {
$type = esc_html__( 'posts', 'wpforms-lite' );
$source_object = get_post_type_object( $field[ 'dynamic_' . $dynamic ] );
if ( $dynamic === 'taxonomy' ) {
$type = esc_html__( 'terms', 'wpforms-lite' );
$source_object = get_taxonomy( $field[ 'dynamic_' . $dynamic ] );
if ( $source_object !== null ) {
$source = $source_object->labels->name;
return sprintf( /* translators: %1$s - data source name (e.g. Categories, Posts), %2$s - data source type (e.g. post type, taxonomy). */
esc_html__( 'This field will not be displayed in your form since there are no %2$s belonging to %1$s.', 'wpforms-lite' ),
* Display empty dynamic choices message.
* @param array $field Field data and settings.
protected function display_empty_dynamic_choices_message( $field ) {
'<div class="wpforms-alert wpforms-alert-warning">%s</div>',
esc_html( $this->get_empty_dynamic_choices_message( $field ) )
* Get checkbox, choices and select field options label.
* @since 1.8.9 Added the `$field` parameter.
* @param string $label Choice option label.
* @param int $key Choice number.
* @param array $field Field data and settings.
protected function get_choices_label( $label, int $key, array $field ) {
$is_payment_field = ! empty( $field ) && ( $field['type'] === 'payment-checkbox' || $field['type'] === 'payment-multiple' );
$is_icon_image_choice = ! empty( $field['choices_icons'] ) || ! empty( $field['choices_images'] );
// Do not set a placeholder for an empty label in Icon and Image choices except for payment fields.
if ( ! $is_payment_field && $is_icon_image_choice && wpforms_is_empty_string( $label ) ) {
/* translators: %d - choice number. */
$placeholder = $is_payment_field ? __( 'Item %d', 'wpforms-lite' ) : __( 'Choice %d', 'wpforms-lite' );
return ! wpforms_is_empty_string( $label ) ?
* Display quantity dropdown on the front.
* @param array $field Field data and settings.
protected function display_quantity_dropdown( $field ) {
if ( ! $this->is_payment_quantities_enabled( $field ) ) {
$field_id = wpforms_validate_field_id( $field['id'] );
$form_id = absint( $this->form_data['id'] );