0
votes

The following code adds editable short description of the product as order item metadata in Woocommerce. The code is working as expected for simple products but for variable products the $item->get_formatted_meta_data('') returns empty array at first and only after editing the item, the short description shows as expected.

<?php
/**
 *  Add product description meta to order item
 */
add_action( 'woocommerce_before_order_itemmeta', 'add_order_item_description_meta', 10, 3 );
function add_order_item_description_meta( $item_id, $item, $product ) {
    // Add only if not present
    $product_description_meta = wc_get_order_item_meta( $item_id, '_product_short_desc', true );
    if( empty( $product_description_meta ) ) {
        if( $product->is_type('variation') ) {
            $parent_product = wc_get_product( $product->get_parent_id() );
            $excerpt = $product->get_description();
            $excerpt  = empty($excerpt) ? $parent_product->get_short_description() : $excerpt;
        } else {
            $excerpt = $product->get_short_description();
        }
        wc_add_order_item_meta( $item_id, '_product_short_desc', $excerpt );
    }
}

/**
 * Hide product description meta
 */
add_filter( 'woocommerce_hidden_order_itemmeta', 'custom_hidden_order_itemmeta' );
function custom_hidden_order_itemmeta( $hidden_order_itemmeta ) {
    $hidden_order_itemmeta[] = '_product_short_desc';
    return $hidden_order_itemmeta;
}

/**
 * Add custom column to display product description meta
 */
add_action( 'woocommerce_admin_order_item_headers', 'custom_admin_order_items_headers', 20, 1 );
function custom_admin_order_items_headers( $order ) {

    echo '<th class="item_short_description">';
    echo __('Short Description', 'woocommerce') . '</th>';
}

/**
 * Custom column content in table
 */
add_action( 'woocommerce_admin_order_item_values', 'custom_admin_order_item_values', 20, 3 );
function custom_admin_order_item_values( $product, $item, $item_id ) {
    ?>
    <td class="product_short_desc">
        <?php
        if( $meta_data = $item->get_formatted_meta_data( '' ) ) {
            $meta = array_filter( $meta_data, function( $value, $key ) {
                return '_product_short_desc' === $value->key;
            }, ARRAY_FILTER_USE_BOTH );

            if( ! empty( $meta ) ) {
                // Get the key of first value
                $meta_id = 0;
                foreach( $meta as $key => $value) {
                    $meta_id = $key;
                    break;
                }
                $product_desc_meta = $meta[$meta_id];
                ?>
                <div class="view">
                    <?php echo wp_kses_post( force_balance_tags( $product_desc_meta->display_value ) ); ?>
                </div>
                <div class="edit" style="display: none;">
                    <input type="hidden" placeholder="<?php esc_attr_e( 'Name (required)', 'woocommerce' ); ?>" name="meta_key[<?php echo esc_attr( $item_id ); ?>][<?php echo esc_attr( $meta_id ); ?>]" value="<?php echo esc_attr( $product_desc_meta->key ); ?>" />
                    <textarea placeholder="<?php esc_attr_e( 'Short Description', 'woocommerce' ); ?>" name="meta_value[<?php echo esc_attr( $item_id ); ?>][<?php echo esc_attr( $meta_id ); ?>]"><?php echo esc_textarea( rawurldecode( $product_desc_meta->value ) ); ?></textarea>
                </div>
            <?php
            }
        } else {
            echo '-';
        } ?>
    </td>
    <?php
}

For simple product the Short Description column is displaying value when adding the item to order but for variable product it shows - as it goes into else condition of function custom_admin_order_item_values at first and then after editing the item, it displays the short description correctly.

Here's screenshot for the simple and variable product added without being edited:

enter image description here

Please help to find the underlying bug.

UPDATE: Anyone trying to help on this, I can confirm that problem lies either in first hooked function i.e. add_order_item_description_meta or in the Woocommerce core because even if you comment out the later hooks and their respective functions the same problem is there.

So the meta data for the variable product is not loaded first time when product is added to the order, but when it is refreshed such as by editing it, the meta data loads fine. Also note as I mentioned earlier the meta data loads as expected for simple products at first time without need of refresh of order items.

1
I'm curious why you're doing it like this.. you already have your $product variable and the short description can be easily obtain by $product->get_short_description() which works for variable and simple productReigel
@Reigel I don't think you can directly get short description for variable product by using $product->get_short_description() on variable $product object. You need to get parent $product object as it holds the short description. Correct me if I misunderstood.rmalviya

1 Answers

0
votes

I have tried your code and it works using

        $meta = array_filter( $meta_data, function( $value ) {
            return '_product_short_desc' === $value->key;
        } );

instead of

        $meta = array_filter( $meta_data, function( $value, $key ) {
            return '_product_short_desc' === $value->key;
        }, ARRAY_FILTER_USE_BOTH );

and adding if statement in add_order_item_description_meta

function add_order_item_description_meta( $item_id, $item, $product ) {
    if ( !$product ) return;
    /*... rest of the code ...*/

Here's a screenshot: image by http://reigelgallarde.me