I'm using polylang plugin to having multi-languages website.
Using WooCommerce with polylang demands duplicating each product for each language, so assuming I have Hebrew and English, that means 2 duplications for each products.
It works fine with WooCommerce plugin, but when I'm displaying "related products" at the end of the product page, it's mixing products in English and Hebrew together.
I expect to filter the related product by website current language (if(get_locale() == 'en_US') - to check website current locale state, else will represent Hebrew).
Polylang functions
Here is what I have tried, but I got stuck on the part of filtering the product by language:
add_filter( 'woocommerce_product_related_posts', 'custom_related_products' );
function custom_related_products($product){
global $woocommerce;
// Meta query
$meta_query = array();
$meta_query[] = $woocommerce->query->visibility_meta_query();
$meta_query[] = $woocommerce->query->stock_status_meta_query();
$meta_query = array_filter( $meta_query );
// Get the posts
$related_posts = get_posts( array(
'orderby' => 'rand',
'posts_per_page' => '4',
'post_type' => 'product',
'fields' => 'ids',
'meta_query' => $meta_query
) );
if ( $related_posts->have_posts() ) {
while ( $related_posts->have_posts() ) : $related_posts->the_post();
if(pll_get_post_language(get_the_ID())){
//Not sure its the right approach for this..
}
endwhile;
}
$related_posts = array_diff( $related_posts, array( $product->id ), $product->get_upsells() );
return $related_posts;
}
How can I filter Woocommerce related product section by language?
Edit
So after a little bit of research and help in the comments I found out that 'lang' => 'en' argument does exist, but even when I use it, there is no change on related products language display.
Any ideas?
add_filter( 'woocommerce_product_related_posts', 'custom_related_products' );
function custom_related_products($product){
global $woocommerce;
// Meta query
$meta_query = array();
$meta_query[] = $woocommerce->query->visibility_meta_query();
$meta_query[] = $woocommerce->query->stock_status_meta_query();
$meta_query = array_filter( $meta_query );
// Get the posts
$related_posts = get_posts( array(
'orderby' => 'rand',
'posts_per_page' => '4',
'post_type' => 'product',
'fields' => 'ids',
'meta_query' => $meta_query,
'suppress_filters' => false
) );
if ( $related_posts->have_posts() ) {
while ( $related_posts->have_posts() ) : $related_posts->the_post();
if(pll_get_post_language(get_the_ID())){
//Not sure its the right approach for this..
}
endwhile;
}
$related_posts = array_diff( $related_posts, array( $product->id ), $product->get_upsells() );
return $related_posts;
}
suppress_filters There is a way to make get_posts cache the results however, the suppress_filters option is true by default, but if you set it to false, the caching mechanisms inside WordPress will do their work, and results will be saved for later.
You can try this code:
$related_posts = get_posts( array(
'orderby' => 'rand',
'posts_per_page' => '4',
'post_type' => 'product',
'meta_query' => $meta_query,
'lang' => 'en'
) );
if ($related_posts) {
foreach ($related_posts as $post) {
setup_postdata($post);
// something like <li><?php the_title(); ?></li>
}
}
wp_reset_postdata();
This code correctly returns code in selected language on my site
While working on a custom WordPress REST Api end point to fetch post by selected language or device language, this worked. See if it can help you out.
function mycustomplugin_posts($params) {
// get the url params
$page = $params->get_param('page') ? $params->get_param('page') : 0;
$per_page = $params->get_param('per_page') ? $params->get_param('per_page') : 10;
$offset = $params->get_param('offset') ? $params->get_param('offset') : 0;
$order = $params->get_param('order') ? $params->get_param('order') : 'desc';
$order_by = $params->get_param('order_by') ? $params->get_param('order_by') : 'date';
$lang = array_search($params->get_param('lang'),polylang_json_api_languages(), true) ? $params->get_param('lang') : pll_default_language();
$args = [
'post_type' => 'post',
'page' => $page,
'numberposts' => $per_page,
'offset' => $offset,
'order' => $order,
'orderby' => $order_by,
'tax_query' => [
[
'taxonomy' => 'language',
'field' => 'slug',
'terms' => $lang
]
]
];
$posts = get_posts($args);
$data = [];
$i = 0;
foreach($posts as $post) {
// Extract the post data
$data[$i]['id'] = $post->ID;
$data[$i]['title'] = $post->post_title;
$data[$i]['content'] = $post->post_content;
$data[$i]['excerpt'] = e42_the_short_content($post->post_content, 300);
$data[$i]['slug'] = $post->post_name;
$data[$i]['date'] = $post->post_date;
$data[$i]['link'] = get_permalink($post->ID);
$data[$i]['author'] = get_the_author_meta('display_name', $post->post_author);
$data[$i]['categories'] = array();
$data[$i]['featured_image']['thumbnail'] = get_the_post_thumbnail_url($post->ID, 'thumbnail');
$data[$i]['featured_image']['medium'] = get_the_post_thumbnail_url($post->ID, 'medium');
$data[$i]['featured_image']['large'] = get_the_post_thumbnail_url($post->ID, 'large');
foreach(get_the_category($post->ID) as $category){
array_push($data[$i]['categories'],$category->term_id);
}
$i++;
}
// Create the response object
$response = new WP_REST_Response( $data );
// Add a custom status code
$response->set_status( 200 );
return $response;
}
/plugins/woocommerce/templates/single-product/related.php
Move this to child theme
yourtheme/woocommerce/single-product/related.php
And add the following line to the foreach loop
if (pll_current_language()!=pll_get_post_language($post_object->ID)) {
continue;
}
Basically if current language does not match product language we skip over it.
I am writing a custom plugin and I need to automatically send information about every newly created coupon. Until now, I can only choose a specific coupon by its name(e.g. 1234):
$coupon = new WC_Coupon("1234");
But I cannot seem to find how to get a coupon right after its created, without knowing its name, or at least how to get all of the available coupons. Can someone help?
May be this might help. Tested and it's working. This will return all coupons since coupons are saved as post_type shop_coupon.
$args = array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'asc',
'post_type' => 'shop_coupon',
'post_status' => 'publish',
);
$coupons = get_posts( $args );
Try to get using custom post type or directly mysql query.
1) Using mysql query
// Run a query on the postmeta table to get the id of every coupon that has the email in the customer_email restrictions
$couponlist = $wpdb->get_results("SELECT
`wp_postmeta`.`post_id`
FROM `wp_postmeta`
WHERE `wp_postmeta`.`meta_key` LIKE 'customer_email'
AND `wp_postmeta`.`meta_value` LIKE '%".$email."%'");
$couponarrayfinal = array( ); //Create an array of the ids so we can use wp_query to more quickly grab the data
// Add the ids to the array in a foreach loop
foreach( $couponlist as $key => $row) {
$value = $row->post_id;
$couponarrayfinal[] = $value ;
}
2) Using get_posts method
$arg = array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'asc',
'post_type' => 'shop_coupon',
'post_status' => 'publish');
$coupons_list = get_posts( $arg );
Try with this you will get the all the data
// WP_Query arguments
$args = array(
'post_type' => array('shop_coupon'),
'post_status' => array('publish'),
'posts_per_page' => '-1',
'order' => 'DESC',
'orderby' => 'id',
);
// The Query
$query = new WP_Query($args);
// The Loop
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
// do something
$coupon = new WC_Coupon(get_the_ID());
$coupnCode = $coupon->code;
$coupnAmount = $coupon->amount;
$minAmount = wc_format_decimal($coupon->minimum_amount, 2);
$maximumAmount = wc_format_decimal($coupon->maximum_amount, 2);
$expire = $coupon->expiry_date;
}
} else {
// no posts found
}
// Restore original Post Data
wp_reset_postdata();
I have this plugin. It shows all products from woocommerce, but I want to show products from all Completed User Orders.
// Change product query settings here
$product_posts = get_posts( array(
'post_type' => 'product',
'post_status' => 'publish',
'numberposts' => -1,
) );
// Display product options
$values = array();
foreach ( $product_posts as $product ) {
$values[] = $product->post_title;
}
Suggestion?
Thank you!
I have some 30 orders in my shop. I am trying to loop over all orders, but I can't retrieve any orders. Here's the code:
$args = array (
'post_type' => 'shop_order',
'posts_per_page' => - 1
);
$loop = new WP_Query($args);
while ($loop->have_posts()) {
// do some work here
}
The loop never runs. I tried printing a count of all post types:
$args = array (
'post_type' => 'any',
'posts_per_page' => - 1
);
$loop = new WP_Query($args);
$types = array();
while ($loop->have_posts()) {
$loop->the_post();
$post_id = get_the_ID();
$type = get_post_type($post_id);
if ($types[$type]) $types[$type]++;
else $types[$type] = 1;
}
foreach ($types as $type => $count) {
echo "{$type}: {$count} ";
}
This is printing product: 30 page: 5 post: 1, i.e. no shop_orders. I guess I'm missing something very obvious, but it's not so obvious to me what that obvious thing is!
UPDATE: I am now retrieving all orders with this code:
$args = array(
'post_type' => 'shop_order',
'posts_per_page' => -1
);
$posts = get_posts($args);
That doesn't answer the question though. But it's a solution.
use 'post_status' => 'wc-processing' or 'post_status' => 'any'
I'm using this slightly modified script (inside a loop) which helps me generate two links which I use to add products to the cart:
<?php
// Get the ID of the product
$id = $_POST["post_var"];
// Get variations
$args = array(
'post_type' => 'product_variation',
'post_status' => array( 'publish' ),
'numberposts' => 2,
'orderby' => 'menu_order',
'order' => 'asc',
'post_parent' => $product->id
);
$variations = get_posts( $args );
$loop = 0;
if ( $variations ) {
foreach ( $variations as $variation ) {
$formats[$loop]["id"] = absint( $variation->ID );
$formats[$loop]["data"] = get_post_meta( $variation->ID );
$variation_label = "?????????";
$loop++;
}
foreach ( $formats as $type )
$response .= '' . $variation_label . '';
} ?>
<?php echo $response; ?>
The only thing I can't figure out is how to get the variation labels.
Every product has variation called "Format' with the options "Electronic" and "Physical" and I need those to be output into the link. So the $response would look something like this:
<a href="http://example.com/checkout?add-to-cart=93&variation_id=94&quantity=1&attribute_pa_format=Electronic">Electronic</a
Physical
You can see I've added a variable called $variation_label as a placeholder.
Stumped.