1
votes

I am trying to exclude certain posts from the Shop Order page e.g. '/wp-admin/edit.php?post_type=shop_order' if don't have a certain meta_key/meta_value combination present.

I have tried two approaches and neither seems to work properly:

Option 1: Pre Get Posts

add_action( 'pre_get_posts', 'so_filter_shop_order' );

function so_filter_shop_order($query) {

    global $typenow;

    /** @var $query WP_Query */

    if ($query->is_main_query() && $typenow === 'shop_order' && is_admin()) {

        $query->set( 'meta_key', '_method_created' );
        $query->set( 'meta_value', 'booking' );
    }

}

Limitations of Option 1 The problem with this option is that it doesn't seem to target other queries on this page (e.g. the count of different post statuses). I am also worried that this code will be targeting other queries elsewhere.

Option 2: Filter 'request'

This was an idea I got from WooCommerce CSV Export Plugin (as they filter this loop too).

add_filter( 'request', 'so_order_filters');

function so_order_filters( $vars ) {
    global $typenow;

    if ( 'shop_order' === $typenow ) {

        $vars['meta_key']   = '_method_created';
        $vars['meta_value'] = 'booking';
    }

    return $vars;
 }

Limitations of Option 2 This approach also does not target other things on the page and it also conflicts with the CSV Export plugin because only one 'meta_key' can be added to the $vars array. I am also 95% sure this is not the right way to do it.

Where I would like help

It would be great to get some feedback on if either approach is worth pursuing or a suggested alternative please.

It would also be good to know if there are other things I can add to Option 1 to make sure it is only targeting the correct queries

Finally, any advice on how to target the other things on the other related queries on the page would be extremely useful.

Thanks in advance.

1

1 Answers

0
votes

Here is another approach.

  1. To get all post ID-s which has certain metakey+metavalue combination via SQL.

  2. To include it with post__in parameter.

     add_action( 'pre_get_posts', 'so_filter_shop_order' );
    
     function so_filter_shop_order($query) {
    
        global $wpdb;$excluded_results=array();
        $excluded_results=$wpdb->query("select post_id from $wpdb->postmeta where meta_key='_method_created' and meta_value='booking' ");
        foreach ($variable as $key => $value) {$excluded_results[]=$value;}
    
        if (strpos($_SERVER["REQUEST_URI"],'post_type=shop_order') && is_admin()) {
            $query->set( 'post__in',  $excluded_results);
        }
    }
    

To affect table header part which shows the number of posts can't be done with pre_get_posts. It works through wp_count_posts filter. So you need to create a filter for this. Here is sample boilerplate for that:

add_filter('wp_count_posts','changenumbers',0,3);
function changenumbers ($counts, $type, $perm){
 if (strpos($_SERVER["REQUEST_URI"],'post_type=product') && is_admin()) {
                $counts->publish=0;
                //var_dump($counts);
                //you need to write some wp_query there which would get the number of posts by their status. Then you will only need to return those values.
            }
            return $counts;
}