2

I'm working on a giftcard product whereof I need the customer to be able to set the price as long as it is 100 or more. Problem is, I'm not sure how to create the value check.

The customer should then be able to add to cart as normal and to checkout as usual.

I've included a remove_action for the product price (which for some reason does not work) if the product is assigned to the giftcard category.

The field input has been created and the data should be carried over to the cart and checkout and into the order -- but it does not work for some reason.

The next step is to set the product price into whatever the customer submits as the giftcard value (as long as it is 100 or more) and to display that as the product price on cart and checkout.

If anyone can review and help me out, that would be awesome.

add_action( 'woocommerce_before_add_to_cart_form', 'giftcard_price_field' );
function giftcard_price_field() {
global $product;

    if( has_term('giftcard', 'product_cat', $product->get_id() ) ) {
    
    // if the product is assigned to the giftcard category, remove the product price
    remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );

    // add a new input field for the price, allowing the customer to set the price
    echo '<div class="giftcard-product-price">
    <label for="giftcard-product-price">Giftcard value: </label>
    <input type="text" id="giftcard-product-price" name="giftcard-product-price" placeholder="Giftcard value" maxlength="1000">
    </div>';
    }
}

add_filter( 'woocommerce_add_cart_item_data', 'giftcard_price_field_cart_data', 10, 3 ); 
function giftcard_price_field_cart_data( $cart_item_data, $product_id, $variation_id ) {

    if( ! empty ( $_POST[ 'giftcard-product-price' ] ) ) {

        // need to check that the value is NOT below 100 and if so, create a wc_notice warning
        $cart_item_data['giftcard-product-price'] = sanitize_text_field( $_POST['giftcard-product-price']);
    }

    return $cart_item_data;
}

add_filter( 'woocommerce_get_item_data', 'giftcard_price_field_display_data', 10, 2 ); 
function giftcard_price_field_display_data( $item_data, $cart_item ) {

    if( ! empty ( $cart_item[ 'giftcard-product-price' ] ) ) {

    $item_data[] = array (
    'key' => 'Giftcard value',
    'value' => $cart_item['giftcard-product-price'],
    'display' => '',
    );
}
    return $item_data;
}

add_action( 'woocommerce_checkout_create_order_line_item', 'giftcard_price_field_order_data', 10, 4 ); 
function giftcard_price_field_order_data( $item, $cart_item_key, $values, $order ) {

    if( ! empty ( $values[ 'giftcard-product-price' ] ) ) {

        $item->add_meta_data( 'Giftcard value', $values['giftcard-product-price'] );
    }
}
7uc1f3r
  • 28,449
  • 17
  • 32
  • 50

1 Answers1

1
  • Add a new field 'giftcard_product_price' on single product page if has_term()
  • Removes the original product price on the single product page
  • Various validations have been added and are possible
  • The price of the product (giftcard) is adjusted to the price entered by the customer
function giftcard_price_field() {
    global $product;
    
    // Instanceof
    if ( $product instanceof WC_Product ) {
        
        // Set category(ies)
        $cats = array ( 'giftcard' );

        // True
        if ( has_term( $cats, 'product_cat', $product->get_id() ) ) {
            // add a new input field for the price, allowing the customer to set the price
            echo '<div class="giftcard-product-price">
            <label for="giftcard-product-price">Giftcard value: </label>
            <input type="text" id="giftcard_product_price" name="giftcard_product_price" placeholder="Giftcard value" maxlength="1000">
            </div>';
        }
    }
}
add_action( 'woocommerce_before_add_to_cart_button', 'giftcard_price_field', 10, 0 );

// Remove price
function action_woocommerce_single_product_summary() {
    global $product;
    
    // Instanceof
    if ( $product instanceof WC_Product ) {
        
        // Set category(ies)
        $cats = array ( 'giftcard' );

        // True
        if ( has_term( $cats, 'product_cat', $product->get_id() ) ) {   
            remove_action('woocommerce_single_product_summary','woocommerce_template_single_price', 10 );
        }
    }
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 5 );

// Validate
function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
    // Isset
    if ( isset ( $_POST['giftcard_product_price'] ) ) {
        $giftcard_product_price = $_POST['giftcard_product_price'];

        // Error = empty, not numeric or less than 100
        if ( empty ( $giftcard_product_price ) ) {
            wc_add_notice( __( 'Field is empty', 'woocommerce' ), 'error' );
            $passed = false;
        } elseif ( ! is_numeric ( $giftcard_product_price ) ) {
            wc_add_notice( __( 'NOT a number or a numeric string', 'woocommerce' ), 'error' );
            $passed = false;                
        } elseif ( $giftcard_product_price < 100 ) {
            wc_add_notice( __( 'Less than 100', 'woocommerce' ), 'error' );
            $passed = false;                
        }   
    }
    
    return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );

function filter_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
    if ( isset ( $_POST['giftcard_product_price'] ) ) {
        $cart_item_data['giftcard_product_price'] = sanitize_text_field( $_POST['giftcard_product_price'] );
    }
    
    return $cart_item_data; 
}
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data', 10, 3 );

// Set price
function action_woocommerce_before_calculate_totals( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item ) {
        if ( isset ( $cart_item['giftcard_product_price'] ) ) {
            $cart_item['data']->set_price( $cart_item['giftcard_product_price'] );
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
7uc1f3r
  • 28,449
  • 17
  • 32
  • 50
  • Your second edit made it work. Thanks for taking the time to make it. I'll ask a new question about the minicart since the price does not change there. –  Aug 23 '20 at 16:10
  • I believe [this](https://stackoverflow.com/a/39295870/11987538) should work for the mini cart (not tested), also see [Custom Prices for WooCommerce Mini Cart Widget](https://stackoverflow.com/questions/47488607/custom-prices-for-woocommerce-mini-cart-widget) – 7uc1f3r Aug 23 '20 at 17:09