phpwordpresswoocommercehook-woocommerce

WooCommerce Hook add_meta_data not working inside of woocommerce_new_order


I am currently trying to add meta to a product on order creation so its visible in the order admin screen.

I'm a little confused because it should be a relatively straight forward task but it's simply not playing ball.

The below function is called via woocommerce_new_order

public function process_new_order($order_id) {

    $order = wc_get_order($order_id);

    // Loop over order items (products)
    foreach ($order->get_items() as $item_id => $item) {
        $product = $item->get_product();

        // Check if the product has variations
        if ($product->is_type('variation')) {
            // Get the variation attributes (including "License Type")
            $variation_attributes = $product->get_variation_attributes();
            
            // Check for "License Type" variation
            if (isset($variation_attributes['attribute_license-type'])) {
                $license_type = $variation_attributes['attribute_license-type'];

                if ($license_type == 'Simple') {
                    $this->generate_and_save_license_keys($order_id, $item, 1);
                } elseif ($license_type == 'Business') {
                    $this->generate_and_save_license_keys($order_id, $item, 10);
                }
            }
        }
    }
}

I know this code works, the generate_and_save_license_keys is called and it corrently generates a key which is then added to the database, and the meta exists and is correctly logged via the error log as per this code:

private function generate_and_save_license_keys($order_id, $item, $count) {
    global $wpdb;

    $product_id = $item->get_product_id(); // Get the product ID (plugin_id)
    $subscription_id = 0; // For simplicity, we assume no subscriptions for now

    // Initialize an array to hold the generated license keys
    $license_keys = [];

    // Generate the required number of license keys
    for ($i = 0; $i < $count; $i++) {
        $license_key = $this->generate_license_key();
        
        // Add license key to the array
        $license_keys[] = $license_key;

        // Insert the license key into the database
        $wpdb->insert(
            $wpdb->prefix . 'llm_licenses',
            [
                'license_code'    => $license_key,
                'staging_url'     => null, // Set staging URL as NULL
                'subscription_id' => $subscription_id,
                'plugin_id'       => $product_id,
                'order_id'        => $order_id
            ]
        );
    }

    // Store the license keys as a single meta field// Debug to check meta data
    $item->add_meta_data('_license_keys', implode(', ', $license_keys), true);
    error_log('Meta keys for item ' . $item->get_id() . ': ' . print_r($item->get_meta('_license_keys', true), true));
}

However, this data isn't displaying under the product on the admin single order screen.

I've tried adding it to it manually using a function as well which is being called via woocommerce_order_item_meta_end but that only seems to fire when i change the order to "Processing" instead of on every page load and even then it isn't displayed and the error log is showing 0 data for the get_meta even though it was logged when using get_meta via generate_and_save_license_keys.

public function display_license_keys_on_order_screen($item_id, $item, $order, $plain_text) {
    // Retrieve the meta data
    $license_keys = $item->get_meta('_license_keys', true);
    var_dump($license_keys);
    print_r("fired");

    // Log the meta data for debugging
    error_log('Displaying license keys for item ' . $item_id . ': ' . print_r($license_keys, true));

    if ($license_keys) {
        // Display license keys on the order item page
        echo '<p><strong>' . __('License Keys', 'text-domain') . ':</strong> ' . esc_html($license_keys) . '</p>';
    } else {
        // Log if no license keys found for the item
        error_log('No license keys found for item ' . $item_id);
    }
}

Solution

  • What is missing is in your code is the save() method usage, after adding item metadata on the item object, and specifically on the order object.

    Try the following code replacement:

    public function process_new_order($order_id) {
    
        $order = wc_get_order($order_id);
        $use_save = false; // Initializing
    
        // Loop over order items (products)
        foreach ($order->get_items() as $item_id => $item) {
            $product = $item->get_product();
    
            // Check if the product has variations
            if ($product->is_type('variation')) {
                // Get the variation attributes (including "License Type")
                $variation_attributes = $product->get_variation_attributes();
                
                // Check for "License Type" variation
                if (isset($variation_attributes['attribute_license-type'])) {
                    $license_type = $variation_attributes['attribute_license-type'];
    
                    if ($license_type == 'Simple') {
                        $this->generate_and_save_license_keys($order_id, $item, 1);
                        $use_save = true;
                    } elseif ($license_type == 'Business') {
                        $this->generate_and_save_license_keys($order_id, $item, 10);
                        $use_save = true;
                    }
                }
            }
        }
        if ( $use_save ) {
            $order->save(); // Grab changes to data the database
        }
    }
    
    private function generate_and_save_license_keys($order_id, $item, $count) {
        global $wpdb;
    
        $product_id = $item->get_product_id(); // Get the product ID (plugin_id)
        $subscription_id = 0; // For simplicity, we assume no subscriptions for now
    
        // Initialize an array to hold the generated license keys
        $license_keys = [];
    
        // Generate the required number of license keys
        for ($i = 0; $i < $count; $i++) {
            $license_key = $this->generate_license_key();
            
            // Add license key to the array
            $license_keys[] = $license_key;
    
            // Insert the license key into the database
            $wpdb->insert(
                $wpdb->prefix . 'llm_licenses',
                [
                    'license_code'    => $license_key,
                    'staging_url'     => null, // Set staging URL as NULL
                    'subscription_id' => $subscription_id,
                    'plugin_id'       => $product_id,
                    'order_id'        => $order_id
                ]
            );
        }
    
        // Store the license keys as a single meta field// Debug to check meta data
        $item->add_meta_data('_license_keys', implode(', ', $license_keys), true);
        $item->save(); // Apply changes to the item object
    
        error_log('Meta keys for item ' . $item->get_id() . ': ' . print_r($item->get_meta('_license_keys'), true));
    }
    

    It should work.

    Note that the 2nd argument in get_meta() method is true by default.