: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
namespace WPForms\Forms\Fields\PaymentSingle;
* Single item payment field.
class Field extends \WPForms_Field {
const FORMAT_USER = 'user';
const FORMAT_SINGLE = 'single';
const FORMAT_HIDDEN = 'hidden';
* Minimum price default value.
const MIN_PRICE_DEFAULT = 10;
* Primary class constructor.
// Define field type information.
$this->name = esc_html__( 'Single Item', 'wpforms-lite' );
$this->keywords = esc_html__( 'product, store, ecommerce, pay, payment', 'wpforms-lite' );
$this->type = 'payment-single';
$this->icon = 'fa-file-o';
$this->group = 'payment';
* Define additional field hooks.
private function hooks() {
// Define additional field properties.
add_filter( "wpforms_field_properties_{$this->type}", [ $this, 'field_properties' ], 5, 3 );
add_action( 'wpforms_display_field_after', [ $this, 'field_minimum_price_description' ], 10, 2 );
add_filter( 'wpforms_field_preview_class', [ $this, 'preview_field_class' ], 10, 2 );
// Customize HTML field value.
add_filter( 'wpforms_html_field_value', [ $this, 'field_html_value' ], 10, 4 );
* Define additional field properties.
* @param array $properties Field properties.
* @param array $field Field settings.
* @param array $form_data Form data and settings.
public function field_properties( $properties, $field, $form_data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
$form_id = absint( $form_data['id'] );
$field_id = absint( $field['id'] );
// Set options container (<select>) properties.
$properties['input_container'] = [
'class' => [ 'wpforms-payment-price' ],
'id' => "wpforms-{$form_id}-field_{$field_id}",
// User format data and class.
$field_format = ! empty( $field['format'] ) ? $field['format'] : self::FORMAT_SINGLE;
if ( $this->is_user_defined( $field ) ) {
$properties['inputs']['primary']['data']['rule-currency'] = '["$",false]';
$properties['inputs']['primary']['class'][] = 'wpforms-payment-user-input';
if ( ! empty( $field['min_price'] ) ) {
$properties['inputs']['primary']['data']['rule-required-minimum-price'] = wpforms_sanitize_amount( $field['min_price'] );
// Null 'for' value for label as there no input for it.
if ( ! $this->is_user_defined( $field ) ) {
unset( $properties['label']['attr']['for'] );
$properties['inputs']['primary']['class'][] = 'wpforms-payment-price';
if ( ! empty( $field['size'] ) ) {
$properties['inputs']['primary']['class'][] = 'wpforms-field-' . esc_attr( $field['size'] );
$required = ! empty( $form_data['fields'][ $field_id ]['required'] );
$properties['inputs']['primary']['data']['rule-required-positive-number'] = true;
if ( ! empty( $field['price'] ) ) {
$field_value = wpforms_sanitize_amount( $field['price'] );
} elseif ( $required && $field_format === self::FORMAT_SINGLE ) {
$field_value = wpforms_format_amount( 0 );
$properties['inputs']['primary']['attr']['value'] = ! empty( $field_value ) ? wpforms_format_amount( $field_value, true ) : $field_value;
// Single item and hidden format should hide the input field.
if ( $this->is_hidden( $field ) ) {
$properties['container']['class'][] = 'wpforms-field-hidden';
if ( $this->is_payment_quantities_enabled( $field ) ) {
$properties['container']['class'][] = ' wpforms-payment-quantities-enabled';
* Get field populated single property value.
* @param string $raw_value Value from a GET param, always a string.
* @param string $input Represent a subfield inside the field. May be empty.
* @param array $properties Field properties.
* @param array $field Current field specific data.
* @return array Modified field properties.
protected function get_field_populated_single_property_value( $raw_value, $input, $properties, $field ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( ! is_string( $raw_value ) ) {
if ( ! $this->is_user_defined( $field ) ) {
$get_value = stripslashes( sanitize_text_field( $raw_value ) );
$get_value = ! empty( $get_value ) ? wpforms_sanitize_amount( $get_value ) : '';
$get_value_formatted = ! empty( $get_value ) ? wpforms_format_amount( $get_value ) : '';
isset( $properties['inputs'][ $input ] )
$properties['inputs'][ $input ]['attr']['value'] = $get_value_formatted;
* Field options panel inside the builder.
* @param array $field Field data and settings.
public function field_options( $field ) {
$this->field_option( 'basic-options', $field, [ 'markup' => 'open' ] );
$this->field_option( 'label', $field );
$this->field_option( 'description', $field );
$this->price_option( $field );
$this->format_option( $field );
$this->min_price_option( $field );
$this->field_option( 'quantity', $field, [ 'hidden' => ! $this->is_single_item( $field ) ] );
$this->field_option( 'required', $field );
$this->field_option( 'basic-options', $field, [ 'markup' => 'close' ] );
$this->field_option( 'advanced-options', $field, [ 'markup' => 'open' ] );
$this->field_option( 'size', $field );
$this->price_label_option( $field );
$visibility = ! empty( $field['format'] ) && $this->is_user_defined( $field ) ? '' : 'wpforms-hidden';
$this->field_option( 'placeholder', $field, [ 'class' => $visibility ] );
$this->field_option( 'css', $field );
$this->field_option( 'label_hide', $field );
$this->field_option( 'advanced-options', $field, [ 'markup' => 'close' ] );
* @param array $field Field Data.
private function price_label_option( array $field ) {
$output = $this->field_element(
'value' => esc_html__( 'Price Display', 'wpforms-lite' ),
'tooltip' => esc_html__( 'Specify how the price is displayed under the product name.', 'wpforms-lite' ),
$output .= $this->field_element(
'class' => 'wpforms-single-item-price-label-display',
'value' => $this->get_single_item_price_label( $field ),
'class' => $this->is_single_item( $field ) ? '' : 'wpforms-hidden',
* Get price label for single item type.
* @param array $field Field data and settings.
private function get_single_item_price_label( array $field ) {
if ( ! isset( $field['price_label'] ) ) {
return sprintf( /* translators: %s - Single item field price label. */
esc_html__( 'Price: %s', 'wpforms-lite' ),
return $field['price_label'];
* @param array $field Field data and settings.
private function price_option( $field ) {
$price = ! empty( $field['price'] ) ? wpforms_format_amount( wpforms_sanitize_amount( $field['price'] ) ) : '';
$tooltip = esc_html__( 'Enter the price of the item, without a currency symbol.', 'wpforms-lite' );
$output = $this->field_element(
'value' => esc_html__( 'Item Price', 'wpforms-lite' ),
$output .= $this->field_element(
'class' => 'wpforms-money-input',
'placeholder' => wpforms_format_amount( 0 ),
* @param array $field Field data and settings.
private function format_option( $field ) {
$format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : self::FORMAT_SINGLE;
$tooltip = esc_html__( 'Select the item type.', 'wpforms-lite' );
self::FORMAT_SINGLE => esc_html__( 'Single Item', 'wpforms-lite' ),
self::FORMAT_USER => esc_html__( 'User Defined', 'wpforms-lite' ),
self::FORMAT_HIDDEN => esc_html__( 'Hidden', 'wpforms-lite' ),
$output = $this->field_element(
'value' => esc_html__( 'Item Type', 'wpforms-lite' ),
$output .= $this->field_element(
* Field minimum price option.
* @param array $field Field data and settings.
private function min_price_option( $field ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( isset( $_POST['action'] ) && $_POST['action'] === 'wpforms_new_field_payment-single' ) {
// Use a default minimum price when adding new field.
$min_price = wpforms_format_amount( self::MIN_PRICE_DEFAULT );
} elseif ( isset( $field['min_price'] ) ) {
// Use saved minimum price if it exists.
$min_price = wpforms_format_amount( wpforms_sanitize_amount( $field['min_price'] ) );
// Use 0 as a fallback for old forms.
$tooltip = esc_html__( 'Enter the minimum price of the item, without a currency symbol.', 'wpforms-lite' );
$is_hidden = empty( $field['format'] ) || ! $this->is_user_defined( $field ) ? 'wpforms-hidden' : '';
$output = $this->field_element(
'value' => esc_html__( 'Minimum Price', 'wpforms-lite' ),
$output .= $this->field_element(
'minimum-price' => self::MIN_PRICE_DEFAULT,
'class' => 'wpforms-money-input',
$notice = sprintf( /* translators: %1$s - the default minimum price. */
esc_html__( 'Requiring a minimum price of at least %1$s helps protect you against card testing by fraudsters.', 'wpforms-lite' ),
esc_html( wpforms_format_amount( self::MIN_PRICE_DEFAULT, true ) )
$is_notice_hidden = $this->is_min_price_passed( $field ) || $is_hidden ? 'wpforms-hidden' : '';
'<div class="wpforms-alert-warning wpforms-alert wpforms-item-minimum-price-alert %1$s">
esc_attr( $is_notice_hidden ),
esc_html__( 'Security Recommendation', 'wpforms-lite' ),
* Field preview inside the builder.
* @param array $field Field data and settings.
public function field_preview( $field ) {
$price = ! empty( $field['price'] ) ? wpforms_format_amount( wpforms_sanitize_amount( $field['price'] ), true ) : wpforms_format_amount( 0, true );
$min_price = ! empty( $field['min_price'] ) ? wpforms_format_amount( wpforms_sanitize_amount( $field['min_price'] ), true ) : wpforms_format_amount( self::MIN_PRICE_DEFAULT, true );
$placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : wpforms_format_amount( 0 );
$format = ! empty( $field['format'] ) ? $field['format'] : self::FORMAT_SINGLE;
$value = ! empty( $field['price'] ) ? wpforms_format_amount( wpforms_sanitize_amount( $field['price'] ) ) : '';
$is_single = $this->is_single_item( $field );
$single_label = str_replace( '{price}', '<span class="price">' . esc_html( $price ) . '</span>', wp_kses( $this->get_single_item_price_label( $field ), wpforms_builder_preview_get_allowed_tags() ) );
$this->field_preview_option( 'label', $field );
echo '<div class="format-selected-' . esc_attr( $format ) . ' format-selected">';
$hidden = ! $is_single ? 'wpforms-hidden' : '';
echo '<p class="item-price item-price-single ' . esc_attr( $hidden ) . '">';
'<span class="price-label">' . $single_label . '</span>',
$hidden = ! $this->is_hidden( $field ) ? 'wpforms-hidden' : '';