Search code examples
phpwordpresswoocommerceproductproduct-variations

Enable custom variations pricing options to WooCommerce simple products


I currently have this some custom pricing based on user roles set up to work for variable products.

Screen grab of now it looks

And this is the code that I'm using to make it work:

    // Add custom fields to variations option pricing
add_action( 'woocommerce_variation_options_pricing', 'add_variation_options_pricing', 20, 3 );
function add_variation_options_pricing( $loop, $variation_data, $post_variation )
{
    $value1  = get_post_meta( $post_variation->ID, '_food_price', true );
    $value2  = get_post_meta( $post_variation->ID, '_hot_food_price', true );
    $value3  = get_post_meta( $post_variation->ID, '_general_price', true );

    $symbol = ' (' . get_woocommerce_currency_symbol() . ')';

    $key_1 = '_food_price[' . $loop . ']';
    $key_2 = '_hot_food_price[' . $loop . ']';
    $key_3 = '_general_price[' . $loop . ']';

    // General
    echo '<div class="variable_general-price"><p class="form-row form-row-first">
        <label>' . __( "General", "woocommerce" ) . $symbol . '</label>
        <input type="text" size="5" name="' . $key_3 .'" value="' . esc_attr( $value3 ) . '" />
    </p></div>';

    // Food
    echo '<div class="variable_food-price"><p class="form-row form-row-first">
        <label>' . __( "Food", "woocommerce" ) . $symbol . '</label>
        <input type="text" size="5" name="' . $key_1 .'" value="' . esc_attr( $value1 ) . '" />
    </p></div>';

    // Hot Food
    echo '<div class="variable_hot-food-price"><p class="form-row form-row-first">
        <label>' . __( "Hot Food", "woocommerce" ) . $symbol . '</label>
        <input type="text" size="5" name="' . $key_2 .'" value="' . esc_attr( $value2 ) . '" />
    </p></div>';
}


// Save variations prices custom fields values
add_action( 'woocommerce_save_product_variation', 'save_product_variation_price', 20, 2 );
function save_product_variation_price( $variation_id, $i )
{
    if ( isset( $_POST['_food_price'][$i] ) )
    {
        update_post_meta( $variation_id, '_food_price', floatval( $_POST['_food_price'][$i] ) );
    }

    if ( isset( $_POST['_hot_food_price'][$i] ) )
    {
        update_post_meta( $variation_id, '_hot_food_price', floatval( $_POST['_hot_food_price'][$i] ) );
    }

    if ( isset( $_POST['_general_price'][$i] ) )
    {
        update_post_meta( $variation_id, '_general_price', floatval( $_POST['_general_price'][$i] ) );
    }
}


// Variable product price range
add_filter('woocommerce_variation_prices_price', 'variation_price', 900, 2 );

// Product variations (of a variable product)
add_filter('woocommerce_product_variation_get_price', 'variation_price', 900, 2 );
function variation_price( $price, $object )
{
    if( is_user_logged_in() ) {
        // Hot Food User
        if ( current_user_can( 'stallholder') && current_user_can( 'hot_food' ) ) {
            $new_price = (float) get_post_meta( $object->get_id(), '_hot_food_price', true );
            $price     = empty($new_price) ? $price : $new_price;
        }
        // Food User
        elseif ( current_user_can( 'stallholder') && current_user_can( 'food' ) ){
            $new_price = (float) get_post_meta( $object->get_id(), '_food_price', true );
            $price     = empty($new_price) ? $price : $new_price;
        }
        // General User
        else {
            $new_price = (float) get_post_meta( $object->get_id(), '_general_price', true );
            $price     = empty($new_price) ? $price : $new_price;
        }
    }
    return $price;
}

I'm wanting to now do the same for simple products and add these fields in here.

Where I'd like fields to go

I've tried researching on now to add these fields where I need them to go, but have drawn a blank.

Any help gratefully recieved. Thanks.


Solution

  • First, your code is a bit outdated since WooCommerce 3… The following will work for simple products and product variations:

    // Utility function: Array of fields key / Label pairs
    function get_custom_pricing_data_fields() {
        return array(
            '_general_price'    => esc_html('General price', 'woocommerce'),
            '_food_price'       => esc_html('Food price', 'woocommerce'),
            '_hot_food_price'   => esc_html('Hot Food price', 'woocommerce')
        );
    }
    
    // Add custom field to simple product option pricing
    add_action( 'woocommerce_product_options_pricing', 'add_product_custom_options_pricing' );
    function add_product_custom_options_pricing()
    {
        echo '<div class="hide_if_variable">';
    
        // Loop through pricing data fields array
        foreach ( get_custom_pricing_data_fields() as $key => $label ) {
    
            woocommerce_wp_text_input( array(
                'id'        => $key,
                'class'     => "wc_input_price short",
                'label'     => $label .' (' . get_woocommerce_currency_symbol() . ')',
                'data_type' => 'price'
            ));
        }
        echo '</div>';
    }
    
    // Add custom fields to variations option pricing
    add_action( 'woocommerce_variation_options_pricing', 'add_variation_custom_options_pricing', 20, 3 );
    function add_variation_custom_options_pricing( $loop, $variation_data, $variation )
    {
        $variation_object  = wc_get_product($variation->ID);
    
        // Loop through pricing data fields array
        foreach ( get_custom_pricing_data_fields() as $key => $label ) {
    
            woocommerce_wp_text_input(
                array(
                    'id'            => $key . $loop,
                    'name'          => "{$key}[{$loop}]",
                    'value'         => wc_format_localized_price( $variation_object->get_meta( $key ) ),
                    'label'         => $label . ' (' . get_woocommerce_currency_symbol() . ')',
                    'data_type'     => 'price',
                    'wrapper_class' => 'form-row form-row-wide',
                    'placeholder'   => $label . __( ' (required)', 'woocommerce' ),
                )
            ); /*
      
            printf( '<div class="variable%s"><p class="form-row form-row-wide"><label>%s</label>
                <input type="text" size="5" name="%s[%d]" value="%s" /></p></div>', 
            $key, $label . $currency_symbol, $key, $loop, $variation_object->get_meta($key) ); */
        }
    }
    
    // Save simple product option pricing custom fields values
    add_action( 'woocommerce_admin_process_product_object', 'save_simple_product_custom_prices', 20 );
    function save_simple_product_custom_prices( $product )
    {
        // Loop through pricing data fields array
        foreach ( get_custom_pricing_data_fields() as $key => $label ) {
            if ( isset( $_POST[$key] ) ) {
                $product->update_meta_data( $key, wc_clean( wp_unslash( $_POST[$key] ) ) );
            }
        }
    }
    
    // Save variation option pricing custom fields values
    add_action( 'woocommerce_admin_process_variation_object', 'save_product_variation_custom_prices', 20, 2 );
    function save_product_variation_custom_prices( $variation, $i )
    {
        // Loop through pricing data fields array
        foreach ( get_custom_pricing_data_fields() as $key => $label ) {
            if ( isset( $_POST[$key][$i] ) ) {
                $variation->update_meta_data($key, wc_clean( wp_unslash( $_POST[$key][$i]) ) );
            }
        }
    }
    
    // Variable product price range
    add_filter('woocommerce_variation_prices_price', 'display_custom_price', 900, 2 );
    
    // Product variations (of a variable product)
    add_filter('woocommerce_product_variation_get_price', 'display_custom_price', 900, 2 );
    
    // Simple product
    add_filter('woocommerce_product_get_price', 'display_custom_price', 900, 2 );
    function display_custom_price( $price, $product )
    {
        if( is_user_logged_in() ) {
            // Hot Food User
            if ( wc_current_user_has_role( 'stallholder') && wc_current_user_has_role( 'hot_food' ) ) {
                $new_price = (float) $product->get_meta('_hot_food_price');
                $price     = empty($new_price) ? $price : $new_price;
            }
            // Food User
            elseif ( wc_current_user_has_role( 'stallholder') && wc_current_user_has_role( 'food' ) ){
                $new_price = (float) $product->get_meta('_food_price');
                $price     = empty($new_price) ? $price : $new_price;
            }
            // General User
            else {
                $new_price = (float) $product->get_meta('_general_price');
                $price     = empty($new_price) ? $price : $new_price;
            }
        }
        return $price;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin).

    Simple product pricing options

    Also, to handle the variable product price range, which is cached, you need:

    // Handling the caching of variable product price range
    add_filter( 'woocommerce_get_variation_prices_hash', 'add_custom_pricing_options_to_variation_prices_hash', 99, 3 );
    function add_custom_pricing_options_to_variation_prices_hash( $price_hash, $product, $for_display ) {
        if( is_user_logged_in() ) {
            // Hot Food User
            if ( wc_current_user_has_role( 'stallholder') && wc_current_user_has_role( 'hot_food' ) ) {
                if ( ! empty( $product->get_meta('_hot_food_price') ) ) {
                    $price_hash[] = '2';
                }
            }
            // Food User
            elseif ( wc_current_user_has_role( 'stallholder') && wc_current_user_has_role( 'food' ) ) {
                if ( ! empty( $product->get_meta('_food_price') ) ) {
                    $price_hash[] = '3';
                }
            }
            // General User
            else {
                if ( ! empty( $product->get_meta('_general_price') ) ) {
                    $price_hash[] = '4';
                }
            }
        }
        return $price_hash;
    }
    

    See: Change product prices via a hook in WooCommerce 3+