Look into wp_set_object_terms()
You could do something along the lines of:
wp_set_object_terms( $post_id, 'exclude-from-catalog', 'product_visibility' );
Getting all posts by status, use Wp_Query. I added the 'fields' => 'ids'
param to limit the query to only ids, rather than gathering whole post objects.
On an array of posts that have Draft or Pending as a status or are an auto-draft
function catalog_exclude_drafts() {
$args = array(
'post_type' => 'product',
'post_status' => array( 'pending', 'draft', 'auto-draft' ),
'posts_per_page' => -1,
'fields' => 'ids'
);
$drafts = new WP_Query( $args );
$ids = $drafts->posts;
$map = array_map( 'wrapper_for_set_obj', $ids );
}
function wrapper_for_set_obj( $post_id ) {
wp_set_object_terms( $post_id, 'exclude-from-catalog', 'product_visibility' );
}
You could hook the above (or some perfected variant) on init
to run once on localhost or something. To future proof your Drafts, hook it on save_post
. In fact, you can hook it on save_post_products
since WP 3.7 introduced save_post{post_type}
.
One time update:
add_action( 'init', 'catalog_exclude_drafts' );
Going forward:
add_action( 'save_post_products', 'wrapper_for_set_obj' );