Search code examples
phpwordpresswoocommercesimulationaction

simulating the opening of each individual product


I have a woocommerce_before_single_product action. When entering a single product, this action targets the route and extracts information about the quantity and price and updates my product. How can I simulate entering each product to update it?

add_action('woocommerce_before_single_product', 'custom_checkout_process');
function custom_checkout_process() {
    global $wpdb;
    $parent = get_the_id();
    $variations = wc_get_product($parent)->get_available_variations();

    foreach ($variations as $variation) {
        $variation_id = $variation['variation_id'];
        $sku = $variation['sku'];
        $quantity = $variation['max_qty']; 

        $requestData = [
            "request" => [
                "header" => [
                    "auth" => [
                        "key" => "my key"
                    ]
                ],
                "body" => [
                    "items" => [
                        [
                            'sku' => $sku,
                            'qty' => $quantity
                        ]
                    ]
                ]
            ]
        ];

        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => 'route',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_POSTFIELDS => json_encode($requestData),
            CURLOPT_HTTPHEADER => array(
                "cache-control: no-cache",
                "content-type: application/json"
            ),
        ));

        $response = curl_exec($curl);
        $err = curl_error($curl);
        curl_close($curl);
        $responseData = json_decode($response, true);

        if ($responseData && isset($responseData['response']['body']['items'])) {
            foreach ($responseData['response']['body']['items'] as $item) {
                if ($item['sku'] == $sku) {
                    $fulfillableQty = $item['fulfillableQty'];
                    $listPrice = $item['price']['listPrice']; 

                   
                    update_post_meta($variation_id, '_regular_price', $listPrice);
                    update_post_meta($variation_id, '_price', $listPrice);
                    update_post_meta($variation_id, '_stock', $fulfillableQty);
                }
            }
        }
    }
}

I would like to write it in a separate file and when I call it to do it on every product.


Solution

  • You can get directly all published variations in your shop and update them.

    But this is only possible for a limited batch of products, as the script will stop on PHP timeout if too many products are processed.

    Here I set the limit to 500 products (see at the end for other arguments).

    The code:

    function update_product_variations() {
        // get all variations
        $variations = wc_get_products( array(
            'limit'         => 200, // -1 for all products
            'status'        => 'publish',
            'type'          => 'product_variation',
        ) );
    
        // Loop through variation products (objects)
        foreach ($variations as $variation) {
            
            $sku      = $variation->get_sku();
            $quantity = 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : ''; 
    
            $requestData = [
                "request" => [
                    "header" => [
                        "auth" => [
                            "key" => "my key"
                        ]
                    ],
                    "body" => [
                        "items" => [
                            [
                                'sku' => $sku,
                                'qty' => $quantity
                            ]
                        ]
                    ]
                ]
            ];
    
            $curl = curl_init();
            curl_setopt_array($curl, array(
                CURLOPT_URL => 'route',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_POSTFIELDS => json_encode($requestData),
                CURLOPT_HTTPHEADER => array(
                    "cache-control: no-cache",
                    "content-type: application/json"
                ),
            ));
    
            $response = curl_exec($curl);
            $err = curl_error($curl);
            curl_close($curl);
            $responseData = json_decode($response, true);
    
            if ($responseData && isset($responseData['response']['body']['items'])) {
                foreach ($responseData['response']['body']['items'] as $item) {
                    if ($item['sku'] == $sku) {
                        $fulfillableQty = $item['fulfillableQty'];
                        $listPrice = $item['price']['listPrice']; 
    
                        update_post_meta($variation_id, '_regular_price', $listPrice);
                        update_post_meta($variation_id, '_price', $listPrice);
                        update_post_meta($variation_id, '_stock', $fulfillableQty);
                    }
                }
            }
        }
    }
    

    You will need to adapt the code for batches of products to update using limit, page and/or offset arguments for wc_get_products.

    See wc_get_products and WC_Product_Query documentation