最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - How to Remove a Filter from the Admin List Table?

programmeradmin0浏览0评论

I don't want the "Registered customer" filter option for the Admin Orders page.

I have tried to search for how to remove it. I have been inside the WooCommerce codes to see how it's implemented.

And I can see that it's implemented inside the class WC_Admin_List_Table_Orders which extends WC_Admin_List_Table. The WC_Admin_List_Table_Orders class is located in:

/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-orders.php

From the _construct method in WC_Admin_List_Table there is an add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );.

So in WC_Admin_List_Table_Orders we'll find an restrict_manage_posts method calling the next method render_filter():

/**
 * See if we should render search filters or not.
 */
public function restrict_manage_posts() {
    global $typenow;

    if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
        $this->render_filters();
    }
}

/**
 * Render any custom filters and search inputs for the list table.
 */
protected function render_filters() {
    $user_string = '';
    $user_id     = '';

    if ( ! empty( $_GET['_customer_user'] ) ) { // phpcs:disable  WordPress.Security.NonceVerification.NoNonceVerification
        $user_id = absint( $_GET['_customer_user'] ); // WPCS: input var ok, sanitization ok.
        $user    = get_user_by( 'id', $user_id );

        $user_string = sprintf(
            /* translators: 1: user display name 2: user ID 3: user email */
            esc_html__( '%1$s (#%2$s – %3$s)', 'woocommerce' ),
            $user->display_name,
            absint( $user->ID ),
            $user->user_email
        );
    }
    ?>
    <select class="wc-customer-search" name="_customer_user" data-placeholder="<?php esc_attr_e( 'Filter by registered customer', 'woocommerce' ); ?>" data-allow_clear="true">
        <option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo htmlspecialchars( wp_kses_post( $user_string ) ); // htmlspecialchars to prevent XSS when rendered by selectWoo. ?><option>
    </select>
    <?php
}

So, the question now is just how to prevent any of these to be called. I like that there is an add_action hook included in the process. Cause that usually means that there's possible to use remove_action(). And that's what I have tried to do. Without success.

What Iv'e tried:

Following example with both WC_Admin_List_Table and WC_Admin_List_Table_Orders:

remove_action( 'restrict_manage_posts', array( 'WC_Admin_List_Table', 'restrict_manage_posts' ) );

Above but with priority with everything from 10 to 9999999:

remove_action( 'restrict_manage_posts', array( 'WC_Admin_List_Table', 'restrict_manage_posts' ), 10 );

Wrapping it to wp_loaded with a $wc_admin_post_types global variable. Found this from an online search. I also tried with another global variable, $wc_list_table. Tried it both with and without priority in the end:

add_action('wp_loaded', function() {
    global $wc_admin_post_types;
    remove_action( 'restrict_manage_posts', array($wc_admin_post_types, 'restrict_manage_posts'), 10, 2 );
});

And I have also tried with woocommerce_loaded and woocommerce_init. I have also tried above examples inside these init and loaded actions.

Nothing works.

Does anyone knows how to do?

I don't want the "Registered customer" filter option for the Admin Orders page.

I have tried to search for how to remove it. I have been inside the WooCommerce codes to see how it's implemented.

And I can see that it's implemented inside the class WC_Admin_List_Table_Orders which extends WC_Admin_List_Table. The WC_Admin_List_Table_Orders class is located in:

/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-orders.php

From the _construct method in WC_Admin_List_Table there is an add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );.

So in WC_Admin_List_Table_Orders we'll find an restrict_manage_posts method calling the next method render_filter():

/**
 * See if we should render search filters or not.
 */
public function restrict_manage_posts() {
    global $typenow;

    if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) {
        $this->render_filters();
    }
}

/**
 * Render any custom filters and search inputs for the list table.
 */
protected function render_filters() {
    $user_string = '';
    $user_id     = '';

    if ( ! empty( $_GET['_customer_user'] ) ) { // phpcs:disable  WordPress.Security.NonceVerification.NoNonceVerification
        $user_id = absint( $_GET['_customer_user'] ); // WPCS: input var ok, sanitization ok.
        $user    = get_user_by( 'id', $user_id );

        $user_string = sprintf(
            /* translators: 1: user display name 2: user ID 3: user email */
            esc_html__( '%1$s (#%2$s &ndash; %3$s)', 'woocommerce' ),
            $user->display_name,
            absint( $user->ID ),
            $user->user_email
        );
    }
    ?>
    <select class="wc-customer-search" name="_customer_user" data-placeholder="<?php esc_attr_e( 'Filter by registered customer', 'woocommerce' ); ?>" data-allow_clear="true">
        <option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo htmlspecialchars( wp_kses_post( $user_string ) ); // htmlspecialchars to prevent XSS when rendered by selectWoo. ?><option>
    </select>
    <?php
}

So, the question now is just how to prevent any of these to be called. I like that there is an add_action hook included in the process. Cause that usually means that there's possible to use remove_action(). And that's what I have tried to do. Without success.

What Iv'e tried:

Following example with both WC_Admin_List_Table and WC_Admin_List_Table_Orders:

remove_action( 'restrict_manage_posts', array( 'WC_Admin_List_Table', 'restrict_manage_posts' ) );

Above but with priority with everything from 10 to 9999999:

remove_action( 'restrict_manage_posts', array( 'WC_Admin_List_Table', 'restrict_manage_posts' ), 10 );

Wrapping it to wp_loaded with a $wc_admin_post_types global variable. Found this from an online search. I also tried with another global variable, $wc_list_table. Tried it both with and without priority in the end:

add_action('wp_loaded', function() {
    global $wc_admin_post_types;
    remove_action( 'restrict_manage_posts', array($wc_admin_post_types, 'restrict_manage_posts'), 10, 2 );
});

And I have also tried with woocommerce_loaded and woocommerce_init. I have also tried above examples inside these init and loaded actions.

Nothing works.

Does anyone knows how to do?

Share Improve this question asked May 10, 2019 at 12:18 Peter WesterlundPeter Westerlund 1,0775 gold badges14 silver badges31 bronze badges 3
  • Have you checked the answer? Did it work? – Sally CJ Commented May 13, 2019 at 19:52
  • @SallyCJ Sorry for the late respond! It works great! Apparently it was a little bit too complicated for me to figure out by myself. But when I see your answer I do somehow understand. And the solution, the code you did is so simple. I like that, thanks! – Peter Westerlund Commented May 15, 2019 at 11:14
  • You're welcome! And actually, the answer is basically saying, "use the global $wc_list_table to disable the filter; but make sure $wc_list_table is an instance of the WC_Admin_List_Table_Orders class". :) (And you may also want to check if the current screen's ID is edit-shop_order. See get_current_screen().) – Sally CJ Commented May 15, 2019 at 12:06
Add a comment  | 

1 Answer 1

Reset to default 2

I can see that it's implemented inside the class WC_Admin_List_Table_Orders which extends WC_Admin_List_Table.

Yes, that's correct.

And the orders list table is setup via WC_Admin_Post_Types::setup_screen() where the method is called via these hooks: (see WC_Admin_Post_Types::__construct())

// Load correct list table classes for current screen.
add_action( 'current_screen', array( $this, 'setup_screen' ) );
add_action( 'check_ajax_referer', array( $this, 'setup_screen' ) );

And in that setup_screen() method, the list table is instantiated like so where the instance is put into a global variable — $wc_list_table:

include_once 'list-tables/class-wc-admin-list-table-orders.php';
$wc_list_table = new WC_Admin_List_Table_Orders();

So you can remove the filter like so:

// Be sure to rename this function..
function my_func() {
    global $wc_list_table;
    if ( $wc_list_table instanceof WC_Admin_List_Table_Orders ) {
        remove_action( 'restrict_manage_posts', array( $wc_list_table, 'restrict_manage_posts' ) );
    }
}
add_action( 'current_screen', 'my_func', 11 );
add_action( 'check_ajax_referer', 'my_func', 11 );

Tried and tested working on WooCommerce 3.6.2.

发布评论

评论列表(0)

  1. 暂无评论