Изменение названия товара при оформлении заказа и заказе в WooCommerce с WPML - PullRequest
0 голосов
/ 31 мая 2019

Я использую WooCommerce с плагином WPML.Я хочу реализовать функцию при оформлении заказа, когда клиент при определенных условиях может обновить свой продукт, но сохранить прежнюю цену продукта.

Продукты являются переменными со многими переменными атрибутами.Поэтому, в частности, я хочу, чтобы, если покупатель выбрал конкретный вариант продукта с x ценой при оформлении заказа (при определенных условиях), я мог бы изменить его товар в корзине с другим вариантом продукта, но оставить цену x.

Сначала я попытался изменить только название продукта с помощью крюка woocommerce_order_item_name, но это изменение не последовало в заказе.Это важно, потому что некоторые данные заказа затем отправляются в API.

Впоследствии я использовал " Изменение имен элементов корзины WooCommerce " код ответа, который отлично работал для моегоЦель, пока я не установил WPML.По какой-то причине метод WC_Cart set_name() не работает с WPML.Я открыл ветку поддержки , но они все еще не могут найти решение.

Кто-нибудь может предложить другое решение?

Обновление

Я попробовал подход, при котором я удаляю товар в корзине, а затем добавляю тот, который мне нужен.После того, как я использую set_price (), чтобы изменить цену вновь добавленного элемента.Удаление / добавление, похоже, работает, но цена не изменяется на одном языке и не применяется на обоих языках после размещения заказа.Вот код, который я использую:

function berrytaxiplon_change_product_name( $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_key => $cart_item ) {

        // Get an instance of the WC_Product object
        $product = $cart_item['data'];

        // Get the product name (Added Woocommerce 3+ compatibility)
        $product_id = method_exists( $product, 'get_parent_id' ) ? $product->get_parent_id() : $product->post->post_parent;

        if ( ICL_LANGUAGE_CODE == 'en') {
            if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 12) {

                $new_product = wc_get_product( 82 );
                $atrributes = $product->get_attributes('view');
                foreach ($atrributes as $atrribute_key => $atrribute_value) {
                    $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                }
                $new_variation_id = find_matching_product_variation_id(82, $new_attributes);
                $cart->remove_cart_item( $cart_item_key );
                $cart->add_to_cart( 82, 1, $new_variation_id, $new_attributes, $cart_item );

                foreach ( WC()->cart->get_cart() as $new_item ) {

                    $new_item['data']->set_price( $cart_item['s-fare'] );
                }
            }
        } else {
            if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 282) {

                $new_product = wc_get_product( 303 );

                $atrributes = $product->get_attributes('view');
                foreach ($atrributes as $atrribute_key => $atrribute_value) {
                    $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                }
                $new_variation_id = find_matching_product_variation_id(303, $new_attributes);
                $cart->remove_cart_item( $cart_item_key );
                $cart->add_to_cart( 303, 1, $new_variation_id, $new_attributes, $cart_item );
                foreach ( WC()->cart->get_cart() as $new_item ) {
                    $new_item['data']->set_price( $cart_item['s-fare']);
                }

            }
        }

    }

}
add_action( 'woocommerce_before_calculate_totals', 'berrytaxiplon_change_product_name', 10, 1 );

Есть идеи, почему метод set_price () не применяется?

Обновление 2

WPMl использует'woocommerce_before_calculate_totals' и переопределяет действие, добавленное к functions.php

Поддержка WPML предоставила решение с использованием 3 фильтров:

https://wpml.org/forums/topic/cant-use-set_name-method-for-the-product-object-on-checkout/#post-3977153

Ответы [ 2 ]

0 голосов
/ 31 мая 2019

Код, предоставленный Фахамом, очень полезен, но шаблон страницы, который приводит к оформлению заказа, уже слишком сложен, поэтому я сосредоточился на том, чтобы использовать его логику на ловушке 'woocommerce_before_calculate_totals', которую я пробую все время.Поэтому вместо того, чтобы пытаться изменить имя, я удаляю элемент и добавляю новый.Затем, вызывая новый цикл, я устанавливаю цену товара, который был удален.

function berrytaxiplon_change_product_name( $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_key => $cart_item ) {

        // Get an instance of the WC_Product object
        $product = $cart_item['data'];

        // Get the product name (Added Woocommerce 3+ compatibility)
        $product_id = method_exists( $product, 'get_parent_id' ) ? $product->get_parent_id() : $product->post->post_parent;

        if ( ICL_LANGUAGE_CODE == 'en') {
            if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 12) {
            // SET THE NEW NAME
            $new_product = wc_get_product( 82 );

            $atrributes = $product->get_attributes('view');
            foreach ($atrributes as $atrribute_key => $atrribute_value) {
                $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
            }
            $new_variation_id = find_matching_product_variation_id(82, $new_attributes);
            $cart->remove_cart_item( $cart_item_key );
            $cart->add_to_cart( 82, 1, $new_variation_id, $new_attributes, $cart_item );

            foreach ( WC()->cart->get_cart() as $new_item ) {
                $new_item['data']->set_price( get_post_meta( $cart_item['variation_id'], '_price', true ) );
            }

            }
        } else {
            if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 282) {
                // SET THE NEW NAME
                $new_product = wc_get_product( 303 );

                $atrributes = $product->get_attributes('view');
                foreach ($atrributes as $atrribute_key => $atrribute_value) {
                    $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                }
                $new_variation_id = find_matching_product_variation_id(303, $new_attributes);
                $cart->remove_cart_item( $cart_item_key );
                $cart->add_to_cart( 303, 1, $new_variation_id, $new_attributes, $cart_item );
                foreach ( WC()->cart->get_cart() as $new_item ) {
                    $new_item['data']->set_price( get_post_meta( $cart_item['variation_id'], '_price', true ) );
                }

               }
        }

    }
}
add_action( 'woocommerce_before_calculate_totals', 'berrytaxiplon_change_product_name', 10, 1 );  

Я использую приведенную ниже функцию для сопоставления атрибутов, взятых из вопроса WooCommerce: получить идентификатор варианта продукта из совпадающих атрибутов

function find_matching_product_variation_id($product_id, $attributes)
{
    return (new \WC_Product_Data_Store_CPT())->find_matching_product_variation(
        new \WC_Product($product_id),
        $attributes
    );
}

Я немногоскептически относится к использованию add_to_cart () и второго foreach () внутри $ cart_item.Но я проверил и, кажется, работает без ошибок.

Обновление

На самом деле есть проблема с этим кодом (или снова с WPML).Кажется, что set_price () не применяется на дополнительном языке.Тем не менее, если я перезагружаю страницу оплаты и отправляю данные снова, применяется новая цена.

0 голосов
/ 31 мая 2019

Итак, это код, который я использую в одном из своих проектов для добавления варианта товара в корзину на основе некоторых фильтров и выбранного товара:

$product = new WC_Product($product_id); //The main product whose variation has to be added
$product_name = $product->get_name(); //Name of the main product
$quantity = sanitize_text_field($cData['quantity']); //You can set this to 1
$variation_id = sanitize_text_field($cData['variation_id']); //I had the variation ID from filters
$variation = array(
    'pa_duration' => sanitize_text_field($cData['duration']) //The variation slug was also available for me.
);
$cart_item_data = array('custom_price' => sanitize_text_field($custom_price));
$cart = WC()->cart->add_to_cart( (int)$product_id, (int)$quantity, (int)$variation_id, $variation, $cart_item_data ); //This will add products to cart but with the actual price of the variation being added and meta data holding the custom price.
WC()->cart->calculate_totals();
WC()->cart->set_session();
WC()->cart->maybe_set_cart_cookies();

Затем необходимо выполнить проверкудо подсчета итоговых сумм и установки цены на пользовательскую цену следующим образом:

function woocommerce_custom_price_to_cart_item( $cart_object ) {  
    if( !WC()->session->__isset( "reload_checkout" )) {
        foreach ( $cart_object->cart_contents as $key => $value ) {
            if( isset( $value["custom_price"] ) ) {
                $value['data']->set_price($value["custom_price"]);
            }
        }  
    }  
}
add_action( 'woocommerce_before_calculate_totals', 'woocommerce_custom_price_to_cart_item', 99 );
...