1
votes

In WooCommerce I have a specific product which price is set to 0 (the product id is 2938).

When adding that product to cart via href="http://yourdomain.com/?add-to-cart=2938", I'm trying to set the price dynamically based on the current user's custom post (it's a somewhat complicated calculation based on what posts the user has created, otherwise i'd just use groups/bundles.)

Based on "Change cart item prices in Woocommerce 3" answer code, here's what I've got:

add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {

    // ID of the product I've set up
    $product_id_to_change = 2938;

    $user_id = get_current_user_id();

    $studio_args = array(
        'post_type' => 'studio',
        'post_status' => 'published',
        'posts_per_page' => 1,
        'author' => $user_id
    );

    $studio_query = new WP_Query( $studio_args );

    foreach( $studio_query as $studio ) {
        $studio_listing_name = get_the_title();
        $studio_listing_option = get_post_meta( $studio->ID, 'wpcf-listing-option', true );
    }

    if ( $studio_listing_option = array( 1, 2 ) ) {
        $new_price = 180;
    } elseif ( $studio_listing_option = array( 3, 4 ) ) {
        $new_price = 345;
    } elseif ( $studio_listing_option = array( 5, 6, 7 ) ) {
        $new_price = 690;
    }

    $new_name = 'Payment for 2020 Listing: ' . $user_id . ' - ' . $studio_listing_name . ' - ' . 'Listing Option ' . $studio_listing_option;

    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $item ) {
        $item['data']->set_price( $new_price );
        $item['data']->set_name( $new_name );
    }

}

Important to note that each user can only have 1 studio. I think my foreach and if ( $studio_listing_option = array( 1, 2 ) ) check is wrong/can probably be done better. Any ideas on how I can get it working better?

How can I restrict the calculation to just product ID 2938?

Also, $studio_listing_name returns blank, and $studio_listing_option returns an array. Can I improve on that to get it working properly?

1

1 Answers

1
votes

First, it's difficult to help as we don't know anything about your "studio" custom post type and how the data is set on it for the customers.

There are some mistakes and missing things in your code like in your IF statements, where you should need to use in_array() conditional function.

I have tried to guess how the data is set in wpcf-listing-option meta data for your studio custom post type and I suppose that is a number between 1 (one) and 7 (seven).

Also in your code, when you loop through $studio_query, for $studio_listing_name and $studio_listing_option you will always get the values from the last item from the loop… so there's something wrong in your logic.

In the following code I am targeting your specified product Id only (without any guaranty, it should help even if it doesn't work completely):

add_action( 'woocommerce_before_calculate_totals', 'customize_cart_item_details', 20, 1);
function customize_cart_item_details( $cart ) {

    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Avoiding hook repetition (when using price calculations for example)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 || ! is_user_logged_in() )
        return;

    // ID of the product I've set up
    $defined_product_id = 2938;

    $customer_id = get_current_user_id();

    // Get "studio" custom post objects
    $studio_query = get_posts( array(
        'post_type' => 'studio',
        'post_status' => 'published',
        'posts_per_page' => 1,
        'author' => $customer_id
    ) );

    // Get the first "studio" post for the current user
    $studio = reset( $studio_query );

    $studio_name   = $studio->post_title;
    $studio_option = get_post_meta( $studio->ID, 'wpcf-listing-option', true );

    if ( in_array( $studio_option, array( 1, 2 ) ) ) {
        $new_price = 180;
    } elseif ( in_array( $studio_option, array( 3, 4 ) ) ) {
        $new_price = 345;
    } elseif ( in_array( $studio_option, array( 5, 6, 7 ) ) ) {
        $new_price = 690;
    }

    $new_name = sprintf( 
        __( "Payment for 2020 Listing: %s - %s - Listing Option %s", "woocommerce" ),
        $customer_id, $studio_name, $studio_option 
    );

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item ) {
        // Only for the defined product ID (or variation ID)
        if ( in_array( $defined_product_id, [ $cart_item['product_id'], $cart_item['variation_id'] ] ) ) {
            $cart_item['data']->set_price( $new_price );
            $cart_item['data']->set_name( $new_name );   
        }
    }
}