Snorlax
Snorlax

Reputation: 293

How to make changes to a column in WooCommerce admin orders list without modifying the core file

Before asking this question I noticed that there are other similar questions on Stack Overflow without an accepted answer. Although each issue has a different context, I believe there is something in common.

I found these questions but they didn't help:

  1. Overriding WooCommerce function in includes folder

  2. Override woocommerce files from includes folder

  3. How to override a function in Woocommerce WC_Order_Data_Store_CPT Class

I need to make some changes to the WooCommerce core file, but I don't want to touch the original files. So is there a way to override the functions of the files located in the includes folder?

Specifically, the file is this:

https://woocommerce.github.io/code-reference/files/woocommerce-includes-admin-list-tables-class-wc-admin-list-table-orders.html

I need to modify this piece of code (lines 235 and 237), the match would be the last two printf. My question is if this piece of code can be modified with some filter or functions in functions.php file, so if WooCommerce updates I don't lose the changes.

/**
 * Render column: order_status.
 */
protected function render_order_status_column() {
    $tooltip                 = '';
    $comment_count           = get_comment_count( $this->object->get_id() );
    $approved_comments_count = absint( $comment_count['approved'] );

    if ( $approved_comments_count ) {
        $latest_notes = wc_get_order_notes(
            array(
                'order_id' => $this->object->get_id(),
                'limit'    => 1,
                'orderby'  => 'date_created_gmt',
            )
        );

        $latest_note = current( $latest_notes );

        if ( isset( $latest_note->content ) && 1 === $approved_comments_count ) {
            $tooltip = wc_sanitize_tooltip( $latest_note->content );
        } elseif ( isset( $latest_note->content ) ) {
            /* translators: %d: notes count */
            $tooltip = wc_sanitize_tooltip( $latest_note->content . '<br/><small style="display:block">' . sprintf( _n( 'Plus %d other note', 'Plus %d other notes', ( $approved_comments_count - 1 ), 'woocommerce' ), $approved_comments_count - 1 ) . '</small>' );
        } else {
            /* translators: %d: notes count */
            $tooltip = wc_sanitize_tooltip( sprintf( _n( '%d note', '%d notes', $approved_comments_count, 'woocommerce' ), $approved_comments_count ) );
        }
    }

    if ( $tooltip ) {
        printf( '<mark class="order-status %s tips" data-tip="%s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), wp_kses_post( $tooltip ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) );
    } else {
        printf( '<mark class="order-status %s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) );
    }
}

Upvotes: 1

Views: 1448

Answers (2)

7uc1f3r
7uc1f3r

Reputation: 29650

What you can do is remove the original order-status column, and then add a new custom order-status column in the same location:

function filter_manage_edit_shop_order_columns( $columns ) {
    // Loop trough existing columns
    foreach ( $columns as $key => $name ) {
        // NOT equal
        if ( $key !== 'order_status' ) {        
            $new_columns[$key] = $name;
        } else {
            // Replace with custom column
            $new_columns['my_order_status'] = __( 'Status', 'woocommerce' );
        }
    }

    return $new_columns;
}
add_filter( 'manage_edit-shop_order_columns', 'filter_manage_edit_shop_order_columns', 10, 1 );

Then you take over the existing code, and adjust it where desired:

function action_manage_shop_order_posts_custom_column( $column, $post_id ) {
    // Get order
    $order = wc_get_order( $post_id );
    
    /**
     * Render column: order_status.
     */
    if ( $column == 'my_order_status' ) {
        $tooltip                 = '';
        $comment_count           = get_comment_count( $order->get_id() );
        $approved_comments_count = absint( $comment_count['approved'] );

        if ( $approved_comments_count ) {
            $latest_notes = wc_get_order_notes(
                array(
                    'order_id' => $order->get_id(),
                    'limit'    => 1,
                    'orderby'  => 'date_created_gmt',
                )
            );

            $latest_note = current( $latest_notes );

            if ( isset( $latest_note->content ) && 1 === $approved_comments_count ) {
                $tooltip = wc_sanitize_tooltip( $latest_note->content );
            } elseif ( isset( $latest_note->content ) ) {
                /* translators: %d: notes count */
                $tooltip = wc_sanitize_tooltip( $latest_note->content . '<br/><small style="display:block">' . sprintf( _n( 'Plus %d other note', 'Plus %d other notes', ( $approved_comments_count - 1 ), 'woocommerce' ), $approved_comments_count - 1 ) . '</small>' );
            } else {
                /* translators: %d: notes count */
                $tooltip = wc_sanitize_tooltip( sprintf( _n( '%d note', '%d notes', $approved_comments_count, 'woocommerce' ), $approved_comments_count ) );
            }
        }

        if ( $tooltip ) {
            printf( '<mark class="order-status %s tips" data-tip="%s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $order->get_status() ) ), wp_kses_post( $tooltip ), wp_kses( wc_get_order_status_name( $order->get_status() ) ) );
        } else {
            printf( '<mark class="order-status %s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $order->get_status() ) ), wp_kses( wc_get_order_status_name( $order->get_status() ) ) );
        }
    }
}
add_action( 'manage_shop_order_posts_custom_column' , 'action_manage_shop_order_posts_custom_column', 10, 2 );

Upvotes: 2

Diego
Diego

Reputation: 1716

For your specific case you can override the whole class, if you look at the source code it starts with:

if ( class_exists( 'WC_Admin_List_Table_Orders', false ) ) {
    return;
}
//rest of the code

That means that when WC loads that .php file if the class already exists it exit and live with your implementation.

This is a good compromise between directly modifying a wc core file and having your chance to edit the code.

Be careful tho, wordpress doesn't offer a real priority system when loading plugins, to have this override have effect you have to include the new file containing your implementation BEFORE wc loading time span.

The best dirty way is to create a plugin called something like "aa-my-wc-override" and make it an easy plugin that just includes a file containing the new WC_Admin_List_Table_Orders class implementation. I suggest this way because Wordpress loads the plugin alphabetically.

Another possibile way, if you just need to edit some HTML, maybe to inject some .js file in the backend that takes care of the needed modification. Maybe using AJAX or pure JS, depending on your needs

Upvotes: 0

Related Questions