WooCommerce custom order item key removed when using custom hooks

Viewed 111

I need your help because I don't understand what I'm doing anymore. Currently, I'm adding a custom meta data to any order item inside the woocommerce_reduce_order_stock hook:

add_action( 'woocommerce_reduce_order_stock', 'woocommerce_reduce_order_stock_action', 10, 1 );
function woocommerce_reduce_order_stock_action( WC_Order $order ): void {
    $order_items = $order->get_items();

    if ( empty( $order_items ) ) {
        return;
    }

    foreach ( $order_items as $order_item ) {
        $data[20] = [
            'number' => 'ABC-2',
            'qty'    => 20
        ];

        $order_item->update_meta_data( '_test_data', $data );
        $order_item->save();
    }
}

Since I want to display my custom meta in every order item meta (mails, account....), I'm using this function here:

add_filter( 'woocommerce_order_item_get_formatted_meta_data', 'filter_woocommerce_order_item_get_formatted_meta_data', 10, 2 );
function filter_woocommerce_order_item_get_formatted_meta_data( array $formatted_meta, WC_Order_Item $order_item ): array {
    if ( $order_item === null ) {
        return $formatted_meta;
    }

    $data = $order_item->get_meta( '_test_data' );

    if ( ! empty( $data ) ) {
        foreach ( $data as $data_set ) {
            $value = $data_set['number'] . ' (' . $data_set['qty'] . 'x)';

            $formatted_meta[] = (object) [
                'key'           => 'test',
                'display_key'   => 'Test',
                'value'         => $value,
                'display_value' => '<p>' . $value . '</p>'
            ];
        }
    }

    return $formatted_meta;
}

So far so good. Now I'm using another hook to delete the custom meta data again, when the stock gets restored (can be triggered by setting the order to cancelled):

add_action( 'woocommerce_restore_order_stock', 'woocommerce_restore_order_stock_action', 10, 1 );
function woocommerce_restore_order_stock_action( $order ): void {
    $order_items = $order->get_items();

    if ( empty( $order_items ) ) {
        return;
    }
    error_log( print_r( $order_items, true ) );

    foreach ( $order_items as $order_item ) {
        if ( $order_item === null || ! is_object( $order_item ) ) {
            continue;
        }

        $data = $order_item->get_meta( '_test_data' );

        error_log( print_r( $data, true ) );

        $order_item->delete_meta_data( '_test_data' );
        $order_item->save();
    }
}

The strange thing is now that the delete don't works when the meta display filter woocommerce_order_item_get_formatted_meta_data is set. In this case the custom meta get's changed somehow as you can see in the logging here:

[7] => WC_Meta_Data Object
    (
        [current_data:protected] => Array
            (
                [id] => 3265
                [key] => test
                [value] => ABC-3 (3x)
            )
        [data:protected] => Array
            (
                [id] => 3265
                [key] => test
                [value] => ABC-3 (3x)
            )
    )

When I disable my filter hook, I'm getting back the correct meta and it can be deleted:

[9] => WC_Meta_Data Object
    (
        [current_data:protected] => Array
            (
                [id] => 3267
                [key] => _test_data
                [value] => Array
                    (
                        [9] => Array
                            (
                                [number] => ABC-3
                                [qty] => 3
                            )
                    )
            )
        [data:protected] => Array
            (
                [id] => 3267
                [key] => _test_data
                [value] => Array
                    (
                        [9] => Array
                            (
                                [number] => ABC-3
                                [qty] => 3
                            )
                    )
            )
    )

Why? I'm totally confused and can't find the reason after debugging for two hours now...

Edit

Don't be confused by the meta ids... I'm using two orders here because atfer changing the status to cancelled, the meta gets changed and it don't comes back when chaging the status again e.g. to completed.

0 Answers
Related