Query metadata to display the orders. Woocommerce - wordpress

I am trying to display the orders using the query->set() with my customer metadata. The metadata - _admin_name is stored in the wp_postmeta, and I want the admins only can view their own orders which the admin_name same with their user name.
How how can I use query->set() with my metadata?
Here is my code:
function mypo_parse_query_useronly( $wp_query ) {
global $post;
if ( $wp_query->is_admin && strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php?post_type=shop_order') == true) {
add_action( 'views_edit-post', 'child_remove_some_post_views' );
global $current_user;
$userName = $current_user->user_login;
$meta_query_args = array(
array(
'key' => '_user_name',
'value' => $userName,
'compare' => '='
)
);
//trying use this code
// $query = new WP_Query( $meta_query_args );
$wp_query->set( 'author', $current_user->id );
}
}
add_filter('parse_query', 'mypo_parse_query_useronly' );
//don't display the order whish is not own by current user.
function child_remove_some_post_views( $views ) {
//header('Location: '.$newURL);
unset($views['all']);
unset($views['wc-processing']);
unset($views['wc-on-hold']);
unset($views['wc-completed']);
unset($views['pending']);
return $views;
}
Have so way to do this?
Thanks.

<?php
function mypo_parse_query_useronly( $wp_query ) {
global $post;
if ( $wp_query->is_admin && strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php?post_type=shop_order') == true) {
add_action( 'views_edit-post', 'child_remove_some_post_views' );
global $current_user;
$userName = $current_user->user_login;
$meta_query_args = array(
array(
'key' => '_user_name',
'value' => $userName,
'compare' => '='
)
);
//trying use this code
// $query = new WP_Query( $meta_query_args );
$wp_query->set( 'author', $current_user->id );
$wp_query->set( 'meta_query', array(
array(
'key' => '_user_name',
'value' => $userName,
'compare' => '='
)
));
}
}
add_filter('parse_query', 'mypo_parse_query_useronly' );
//don't display the order whish is not own by current user.
function child_remove_some_post_views( $views ) {
//header('Location: '.$newURL);
unset($views['all']);
unset($views['wc-processing']);
unset($views['wc-on-hold']);
unset($views['wc-completed']);
unset($views['pending']);
return $views;
}

Related

Why attribute from shortcode doesn't work?

I have such code with attribute extraction to use it in shortcode.
<?php
function wpusers_shortcode( $atts ) {
extract(shortcode_atts( array(
'Department' => '',
), $atts
)
);
$args = array(
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'Department',
'value' => $Department,
),
)
);
// The Query
$user_query = new WP_user_Query( $args );
// User Loop
if ( ! empty( $user_query->get_results() ) ) {
foreach ( $user_query->get_results() as $user ) {
echo '<p>' . $user->display_name . '</p>';
}
} else {
echo 'No users found.';
}
}
add_shortcode( 'wpusers', 'wpusers_shortcode' );
?>
The shortcode is [wpusers Department="IEDK"].
Users are assigned to custom field Department
enter image description here
But at front end I have a message - No Users Found.
When I add attr (IEDK) in the code I can see them
extract(shortcode_atts( array(
'Department' => 'IEDK',
or
'key' => 'Department',
'value' => 'IEDK',
Whhere can be a problem?
Thanks in advance.
Remove extract and then try to debug with uncomment lines
function wpusers_shortcode( $atts ) {
$ar = shortcode_atts(
array('Department' => ''),
$atts
);
// print_r($ar); die;
$args = array(
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'Department',
'value' => $ar['Department'],
),
)
);
// print_r($args); die;
$user_query = new WP_user_Query( $args );
if ( ! empty( $user_query->get_results() ) ) {
foreach ( $user_query->get_results() as $user ) {
echo '<p>' . $user->display_name . '</p>';
}
} else {
echo 'No users found.';
}
}
add_shortcode( 'wpusers', 'wpusers_shortcode' );
Solved.
The problem was in Uppercase of key [wpusers Department="IEDK"].
I changed to small "d" everywhere and now it works..........

WC Vendors - Custom Taxonomy Checklist Not Saving on Front-End

I'm using WC Vendors and have output the taxonomy named "location" on the products using wp_term_checklist per their suggestion. I've got it saving to the product, but it's not saving the checkbox selection on the front-end.
This is the code I've added to the product-edit.php template
$args = array(
'descendants_and_self' => 0,
'selected_cats' => false,
'popular_cats' => false,
'walker' => null,
'taxonomy' => 'location',
'checked_ontop' => false
);
wp_terms_checklist( $my_postid, $args );
$post_to_edit = array(
'ID' => $my_postid,
'tax_input' => array( 'location' => array($_POST['tax_input']['location']) )
);
$pid = wp_update_post($post_to_edit);
if ( isset($_POST['tax_input']['location']) && is_array( $_POST['tax_input']['location'] ) ) {
$location = array_map( 'intval', $_POST['tax_input']['location'] );
$location = array_unique( $location );
wp_set_post_terms($pid, $location, 'location');
}
This is their code where they use a multi-select, but we need checkboxes:
https://gist.github.com/digitalchild/128033d2d41f682acd4387b595d4f607
We have a custom terms checklist called wcv_terms_checklist() in our form helper. It didn't support custom taxonomies but I have modified it to support that now. You can use the following code from v1.7.10 and above to get working custom terms checklists on our front end.
// Output the location checklist
function form_location( $object_id ) {
$args = array(
'taxonomy' => 'location',
);
$field = array(
'id' => 'product_loc_list',
'label' => __( 'Location', 'wcvendors-pro' ),
'class' => 'product_cat_checklist',
);
WCVendors_Pro_Form_Helper::wcv_terms_checklist( $object_id, $args, $field );
}
add_action( 'wcv_after_product_details', 'form_location' );
// Save the terms
function save_location( $post_id ){
if ( isset( $_POST[ 'location' ] ) && is_array( $_POST[ 'location' ] ) ) {
$location = array_map( 'intval', $_POST[ 'location' ] );
$location = array_unique( $location );
wp_set_post_terms( $post_id, $location, 'location' );
}
}
add_action( 'wcv_save_product', 'save_location' );
Gist available here - https://gist.github.com/digitalchild/09e15649425845fef0b8d3af75c79dd1

How to get the first topic in a lesson in learndash

I want to retrieve the first topic in a lesson in learndash and redirect it through it. But for some reason am not sure how to do it.
I checked the API and doesn't see any appropriate filter/hook for it.
Here is my code:
function redirect_to_first_topic() {
// We only want to do this for Topics. But the below code can be adapted to work for Lessons
global $post;
$post_id = $post->ID;
if ( get_post_type( $post_id ) == 'sfwd-lessons' ) {
$progress = learndash_get_course_progress( null, $post_id );
$link = $progress['next'];
$parent_lesson_id = learndash_get_setting( $post, 'topic' );
$parent_lesson = get_post( $parent_lesson_id );
var_dump($parent_lesson);
}
// Always return $link
// return $link;
}
add_action('wp', 'redirect_to_first_topic');
So basically what am doing here is getting the parent which is the lesson.
A bit late, but mb it will help someone else. You can see how to get 1. lesson of a course and go deeper if needed fe. first topic of first lesson and so on :
add_action( 'template_redirect', 'course_overview_redirect' );
function course_overview_redirect() {
global $post;
if ( ! empty( $post ) && $post->post_type == 'sfwd-courses' && ! empty( $post->ID ) ) {
$lessons = learndash_get_course_lessons_list( $post->ID );
if ( ! empty( $lessons ) ) {
$lesson = array_shift( $lessons );
if ( ! empty( $lesson ) ) {
$url = get_permalink( $lesson[ "post" ]->ID );
if ( ! empty( $url ) ) {
wp_redirect( esc_url( $url ) ); // And redirect if needed
exit;
}
}
}
}
}
You can add a button like this;
$args = array(
'posts_per_page' => -1,
'post_type' => 'sfwd-lessons', // you can change here to find topics : 'sfwd-topics'
'suppress_filters' => true,
'fields' => 'ids',
'orderby' => 'menu_order', // ordering by menu_order will show lesson list, in their order in course.
'order' => 'ASC',
// this meta query is used if you want to search a lesson under a course, or if you search for a topic which is in a course but not under a lesson
'meta_query' => array(
array(
'key' => 'course_id',
'value' => $course_id, // this is id of your course
)
// if your topic is under a lesson than you should add lesson meta query
// your meta query should be changed like below
/*
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'course_id',
'value' => $course_id,
),
array(
'key' => 'lesson_id',
'value' => $lesson_id,
),
),
*/
),
);
$all_lessons = get_posts($args);
$first_lesson = $all_lessons[0]; // taking directly first element of array
$button_html = '' . __( 'Start the course', 'custom-text' ) . '';

Woocommerce : only show products between start and end dates

I'm trying to display only products between two dates. When I only put 1 array and one date it works, but when I put other arrays and my second date it doesn't work anymore, it shows all the products. Any idea ?
function custom_meta_query( $meta_query ){
$today = current_time('Ymd');
$args = array (
'meta_query' => array(
'relation' => 'AND',
array(
'key'=>'flash_sale_start',
'value' => $today,
'compare'=>'<=',
'type' => 'DATE'
),
array(
'key'=>'flash_sale_end',
'value' => $today,
'compare'=>'>=',
'type' => 'DATE'
)),);
$date_query = new WP_Query( $args );
//return $meta_query;
}
// The main shop and archives meta query
add_filter( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 10, 2 );
function custom_product_query_meta_query( $meta_query, $query ) {
if( ! is_admin() )
return custom_meta_query( $meta_query );
}
// The shortcode products query
add_filter( 'woocommerce_shortcode_products_query', 'custom__shortcode_products_query', 10, 3 );
function custom__shortcode_products_query( $query_args, $atts, $loop_name ) {
if( ! is_admin() )
$query_args['meta_query'] = custom_meta_query( $query_args['meta_query'] );
return $query_args;
}
// The widget products query
add_filter( 'woocommerce_products_widget_query_args', 'custom_products_widget_query_arg', 10, 1 );
function custom_products_widget_query_arg( $query_args ) {
if( ! is_admin() )
$query_args['meta_query'] = custom_meta_query( $query_args['meta_query'] );
return $query_args;
}
Thank you
I've found the solution, it was an array() problem
function custom_meta_query( $meta_query ){
$today = current_time('Ymd');
$args = array (
'numberposts' => -1,
'meta_query' => array(
'relation' => 'AND',
'start_clause' => array(
'key'=>'flash_sale_start',
'value' => $today,
'compare'=> '<=',
'type' => 'DATE'
),
'end_clause' => array(
'key' => 'flash_sale_end',
'value' => $today,
'compare' => '>=',
'type' => 'DATE'
),
));
return $args;
}
// The main shop and archives meta query
add_filter( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 10, 2 );
function custom_product_query_meta_query( $meta_query, $query ) {
if( ! is_admin() )
return custom_meta_query( $meta_query );
}
// The shortcode products query
add_filter( 'woocommerce_shortcode_products_query', 'custom__shortcode_products_query', 10, 3 );
function custom__shortcode_products_query( $query_args, $atts, $loop_name ) {
if( ! is_admin() )
$query_args['meta_query'] = custom_meta_query( $query_args['meta_query'] );
return $query_args;
}
// The widget products query
add_filter( 'woocommerce_products_widget_query_args', 'custom_products_widget_query_arg', 10, 1 );
function custom_products_widget_query_arg( $query_args ) {
if( ! is_admin() )
$query_args['meta_query'] = custom_meta_query( $query_args['meta_query'] );
return $query_args;
}

2 pre_get_posts functions to filter by custom fields

EDIT: See the last (3rd) code snippet, it's the working one.
I have an "Actions" page (an archive for a custom post type called Actions), which is an equivalent to "events".
I used this tutorial to filter them with custom fields: ville (city), action (type of action) and date and it works perfectly.
Then I created another function to filter by "date range": past, future actions. And it also works. But they "accumulate". When I select "Past" actions and a city, it shows me ALL past actions + ALL actions that happened or will happen in a city.
So these two functions work, but I don't know how to set their relation to AND or something that makes them work together instead of "accumulating".
Can someone please help me figure this out ?
Thank you.
Function to filter by Type/City/Date custom fields:
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date',
);
// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
return;
}
?>
Function for Future/Past actions:
<?php
add_action('pre_get_posts', 'future_past_actions', 10, 1);
function future_past_actions( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
if( isset($_GET['range']) ) {
$range = explode(',', $_GET['range']);
$meta_query[] = array(
'key' => 'range',
'value' => $range,
'compare' => 'IN',
);
if( $query->get( 'range' ) == 'future' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '>',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'past' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '<',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'toutes' ) {
return;
}
}
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('meta_query', $meta_query);
return;
}
?>
The final merged and working code:
<?php
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date'
);
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
if( ! is_post_type_archive( 'actions' ) ) return;
// CITY/TYPE/DATE filters
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) { continue; }
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
// FUTURE/PAST/ALL filters
if( isset($_GET['range']) ) {
$range = $_GET['range'];
if($range != "toutes") {
// Select what kind of compare you need
if($range == "past") {
$comparer = '<';
} else if($range == "future") {
$comparer = '>=';
}
// If you need to filter by date add this to meta_query array
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => $comparer,
);
}
}
// update meta query
$query->set('meta_query', $meta_query);
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('posts_per_page', '20');
}
?>
In this case best solution in my opinion is to have one action and check query arguments inside of it and then decide what kind of logic you want to do.
$query variable has all the arguments you assign, so your code might look something like this:
Editing considering the comments on situation, you have to use AND relation between two meta fields. Code inside action should look like this:
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
$meta_query = array(
'relation' => 'AND',
array(
'key' => 'ville',
'value' => '$value',
'compare' => '=',
)
);
// Select what kind of compare you need
if($range == "past") {
$compare = ">";
} else if($range == "future") {
$compare = "<";
}
if($range != "all") {
// If you need to filter by date add this to meta_query array
$date_query = array(
'key' => 'date',
'value' => 'date(\"Ymd\"),',
'compare' => $compare,
);
$meta_query[] = $date_query;
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
}
Because what you do now, you set query arguments multiple times.
If you need more parameters to filter out you can add them conditionally to $meta_query variable considering what kind of parameters you get.
I think if I understand correctly this kind of meta query should return needed results.

Resources