Skip to content
Advertisement

How to create a filter dropdown on WooCommerce admin orders list?

I am trying to create a shipping state filter dropdown on WooCommerce admin orders list

First I have added a custom column for shipping state to admin orders list:

add_filter( 'manage_edit-shop_order_columns', 'custom_shipping_state_column', 100 );
function custom_shipping_state_column( $columns ){
$ordered_columns = array();

foreach( $columns as $key => $column ){
    $ordered_columns[$key] = $column;
    if( 'order_notes' == $key ){
        $ordered_columns['order_state'] = __( 'State/Province', 'woocommerce');
    }
}

return $ordered_columns;
}

 add_action( 'manage_shop_order_posts_custom_column' , 'shipping_state_order_list_column', 10, 1 );
 function shipping_state_order_list_column( $column )
 {
  global $post;

   if ( 'order_state' === $column ) {

      $order    = wc_get_order( $post->ID );
      echo $order->get_shipping_state();
    }

 }

And here’s my dropdown filter, for shipping state:

add_action('restrict_manage_posts', 'filter_province');
    function filter_province(){
        global $typenow;
        global $wpdb;
        $table = $wpdb->prefix . 'woocommerce_shipping_zone_locations';
        $sql = 'SELECT location_code FROM `'. $table . '`'; 
        $location_state = array();
        $result = $wpdb->get_results($sql);
        $location_name = array(
            'ABR'=>'ABR:Abra',
            'AGN'=>'AGN:Agusan del Norte',
            'AGS'=>'AGS:Agusan del Sur',
            'AKL'=>'AKL:Aklan',
            'ALB'=>'ALB:Albay',
            'ANT'=>'ANT:Antique',
            'APA'=>'APA:Apayao',
            'AUR'=>'AUR:Aurora',
            'BAS'=>'BAS:Basilan',
            'BAN'=>'BAN:Bataan',
            'BTN'=>'BTN:Batanes',
            'BTG'=>'BTG:Batangas',
            'BEN'=>'BEN:Benguet',
            'BIL'=>'BIL:Bilaran',
            'BOH'=>'BOH:Bohol',
            'BUK'=>'BUK:Bukidnon',
            'BUL'=>'BUL:Bulacan',
            'CAG'=>'CAG:Cagayan',
            'CAN'=>'CAN:Camarines Norte',
            'CAS'=>'CAS:Camarines Sur',
            'CAM'=>'CAM:Camiguin',
            'CAP'=>'CAP:Capiz',
            'CAT'=>'CAT:Catanduanez',
            'CAV'=>'CAV:Cavite',
            'CEB'=>'CEB:Cebu',
            'COM'=>'COM:Compostela Valley',
            'NCO'=>'NCO:Cotobato',
            'DAV'=>'DAV:Davao del Norte',
            'DAS'=>'DAS:Davao del Sur',
            'DAC'=>'DAC:Davao Occidental',
            'DAO'=>'DAO:Davao Oriental',
            'DIN'=>'DIN:Dinangat Island',
            'EAS'=>'EAS:Eastern Samar',
            'GUI'=>'GUI:Guimaras',
            'IFU'=>'IFU:Ifugao',
            'ILN'=>'ILN:Ilocos Norte',
            'ILS'=>'ILS:Ilocos Sur',
            'ILI'=>'ILI:Iloilo',
            'ISA'=>'ISA:Isabela',
            'KAL'=>'KAL:Kalinga',
            'LUN'=>'LUN:La Union',
            'LAG'=>'LAG:Laguna',
            'LAN'=>'LAN:Lanao del Norte',
            'LAS'=>'LAS:Lanao del Sur',
            'LEY'=>'LEY:Leyte',
            'MAG'=>'MAG:Maguindanao',
            'MAD'=>'MAD:Marinduque',
            'MAS'=>'MAS:Masbate',
            'MSC'=>'MSC:Misamis Occidental',
            'MSR'=>'MSR:Misamis Oriental',
            'MOU'=>'MOU:Mountain Province',
            'NEC'=>'NEC:Negros Occidental',
            'NER'=>'NER:Negros Oriental',
            'NSA'=>'NSA:Nothern Samar',
            'NUE'=>'NUE:Nueva Ecija',
            'NUV'=>'NUV:Nueva Vizcaya',
            'MDC'=>'MDC:Occidental Mindoro',
            'MDR'=>'MDR:Oriental Mindoro',
            'PLW'=>'PLW:Palawan',
            'PAM'=>'PAM:Pampanga',
            'PAN'=>'PAN:Pangasinan',
            'QUE'=>'QUE:Quezon',
            'QUI'=>'QUI:Quirino',
            'RIZ'=>'RIZ:Rizal',
            'ROM'=>'ROM:Romblon',
            'WSA'=>'WSA:Samar',
            'SAR'=>'SAR:Sarangani',
            'SIQ'=>'SIQ:Siquijor',
            'SOR'=>'SOR:Sorsogon',
            'SCO'=>'SCO:South Cotobato',
            'SLE'=>'SLE:Southern Leyte',
            'SUK'=>'SUK:Sultan Kudarat',
            'SLU'=>'SLU:Sulu',
            'SUN'=>'SUN:Surigao del Norte',
            'SUR'=>'SUR:Surigao del Sur',
            'TAR'=>'TAR:Tarlac',
            'TAW'=>'TAW:Tawi-Tawi',
            'ZWB'=>'ZWB:Zambales',
            'ZAN'=>'ZAN:Zamboanga del Norte',
            'ZAS'=>'ZAS:Zamboanga del Sur',
            'ZSI'=>'ZSI:Zamboanga Sibugay',
            '00'=>'00:Metro Manila'
        );
        $getCount = count($location_name);
        $location = array_values($location_name);

        // if post type is shop_order
        if ($typenow=='shop_order') {
            //check if our select has been sent and if so, is it set to "Currently Due"
            if (isset($_GET["get_province"])){
                $get_province = $_GET["get_province"];
                $selected = $get_province;
            } else {
                $selected = "";
            }
            echo "<select id='get_province' name='get_province'>";
            echo "<option value='' ".selected("", $selected )." >".__( 'State/Province', 'woocommerce' )."</option>";
            foreach($result as $res) {
                $data = explode(':',$res->location_code);
                for($i=0;$i<$getCount;$i++){
                    $location_state = explode(':',$location[$i]);
                    if($location_state[0] == $data[1]){
                        echo    "<option value= ".$data[1]." ".selected($data[1], $selected ).">".$location_state[1]."</option>";
                    }
                }

            }
            echo "</select>";

        }

    }

And here’s my question: How to process the selected filter on admin orders list when I click the filter button?

Advertisement

Answer

There are some mistakes, complications and missing things in your code.

The following will display a functional dropdown filter based on the shipping state location on admin order list (based on shipping settings allowed countries/states):

// Utility function to get all available shipping zones locations
function get_wc_shipping_zones_locations( ){
    global $wpdb;

    return $wpdb->get_col("
        SELECT DISTINCT location_code 
        FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
    ");
}

// Add a dropdown to filter orders by state
add_action('restrict_manage_posts', 'add_shop_order_filter_by_state');
function add_shop_order_filter_by_state(){
    global $pagenow, $typenow;

    if( 'shop_order' === $typenow && 'edit.php' === $pagenow ) {
        // Get available countries codes with their states code/name pairs
        $country_states = WC()->countries->get_allowed_country_states();

        // Initializing
        $filter_id   = 'shipping_state';
        $current     = isset($_GET[$filter_id])? $_GET[$filter_id] : '';

        echo '<select name="'.$filter_id.'">
        <option value="">'.__( 'Filter by State/Province', 'woocommerce' )."</option>";

        // Loop through shipping zones locations array
        foreach( get_wc_shipping_zones_locations() as $country_state ) {
            $country_state = explode(':', $country_state);
            $country_code  = reset($country_state);
            $state_code    = end($country_state);

            if ( isset( $country_states[$country_code][$state_code] ) 
            && $state_name = $country_states[$country_code][$state_code] ) {
                printf( '<option value="%s"%s>%s</option>', $state_code, 
                    $state_code === $current ? '" selected="selected"' : '', 
                $state_name );
            }
        }
        echo '</select>';
    }
}

// Process the filter dropdown for orders by shipping state
add_filter( 'request', 'process_admin_shop_order_filtering_by_state', 99 );
function process_admin_shop_order_filtering_by_state( $vars ) {
    global $pagenow, $typenow;

    $filter_id = 'shipping_state';

    if ( $pagenow == 'edit.php' && 'shop_order' === $typenow 
    && isset( $_GET[$filter_id] ) && ! empty($_GET[$filter_id]) ) {
        $vars['meta_key']   = '_shipping_state';
        $vars['meta_value'] = $_GET[$filter_id];
        $vars['orderby']    = 'meta_value';
    }
    return $vars;
}

Then I have made some little changes to your shipping state custom column in admin orders list:

add_filter( 'manage_edit-shop_order_columns', 'custom_shipping_state_column', 100 );
function custom_shipping_state_column( $columns ){
    $sorted_columns = array();

    foreach( $columns as $key => $column ){
        $sorted_columns[$key] = $column;
        if( 'order_notes' == $key ){
            $sorted_columns['order_state'] = __( 'State/Province', 'woocommerce');
        }
    }
    return $sorted_columns;
}

 add_action( 'manage_shop_order_posts_custom_column' , 'shipping_state_order_list_column', 10, 1 );
 function shipping_state_order_list_column( $column ) {
     global $post, $the_order;

     if ( 'order_state' === $column && $shipping_state = $the_order->get_shipping_state() ) {
          echo $shipping_state;
     }
}

Code goes in functions.php file of your active child theme (or active theme). Tested and work.

Related answer: Filter orders by product post type in WooCommerce admin orders list page

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement