Hide products published by certain users on Woocommerce - php

I'm trying to hide products in Woocommerce according to the user ID who published them.
I have created the following code but it doesn't work well.
function Products_for_vendor() {
$args = array( 'post_type' => 'product', 'post_author' => '2' );
$products = get_posts( $args );
foreach ($products as $product->ID) {
$post_id = $product->ID
$terms = array( 'exclude-from-catalog', 'exclude-from-search' );
wp_set_object_terms( $post_id, $terms, 'product_visibility', false );
}
}
add_action( 'init', 'Products_for_vendor' );
to hide the post I extracted the code mentioned in this query: Change product visibility via PHP on Woocommerce 3+
Any help or comment is well received.
Thanks in advance.

You shouldn't be changing things like this directly - WooCommerce has special functions to ensure future compatibility with any database structural changes, and to ensure that product data is properly synchronised within its internal caches.
Instead, inside of your foreach loop, use this:
// Get an instance of the product
$theproduct = wc_get_product($product->ID);
// Change the product visibility (options are: 'hidden', 'visible', 'search' and 'catalog'.
$theproduct->set_catalog_visibility('hidden');
// Finally, save and sync the product changes
$theproduct->save();

Related

Fixing custom query for wordpress/elementor with Advanced Custom Fields relationship field post types

I was wondering if someone could help me out.
I can't seem to get this case working (since I am a noob in PHP).
Case:
My wordpress site has two 'post types':
Webinar
Spreker (speaker in dutch)
Via Advanced Custom Posts i've set up a relationship field in the webinar post type. So I can pick the speakers related to that particular post.
I use elementor and need to use the elementor's post widget to display the related speaker(s) via the single webinar page template. This has to be done by a custom query. In elementor you can set a custom query ID. This calls for a php query code.
Now I can't seem to get this query array code right.
Elementor documentation about custom queries:
https://developers.elementor.com/custom-query-filter/#Using_the_Custom_Filter
Some related answers on internet (but can't still seem to get it working):
Custom Query Filter for Elementor Posts by relationship field (ACF)
The custom query ID i use in Elementor is 'Spreker_filter'
My code:
add_action( 'elementor/query/spreker_filter', function( $query ) {
// Get current meta Query
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
// Append our meta query
$meta_query[] = [
'key' => 'sprekers',
'value' => '"' . get_the_ID() . '"',
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
} );
It looks like i was having the same problem.
I've resolved it with this custom query
add_action( 'elementor/query/retrieveLinkedCpts', function( $query ) {
$ids = get_field( 'my_relationship_field', false, false );
$query->set( 'post__in', $ids );
});
source : https://github.com/elementor/elementor/issues/4916
Let me know if it works

How to execute script inside function that is triggered

function when_a_review_gets_submitted ($review, $post_id) {
// Do something
}
add_action('rwp_after_saving_review', 'when_a_review_gets_submitted', 11, 2);
I have this WP_Query and loop to update a custom field of every childpage of the parentpage were somebody has left a review.
// Set up the objects needed
$hosting_provider_query = new WP_Query();
global $post;
$hosting_pagina_titel = $post->post_title;
$search_all_pages = $hosting_provider_query->query(array(
'post_type' => 'page',
'post_status' => 'publish',
//Only get pages where custom field 'name_hosting_provider' equals Page title
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'naam_hosting_provivder',
'value' => $hosting_pagina_titel,
'compare' => '='
),
),
));
// Loop through all pages and find Page's children
$loop_through_all_child_pages = get_page_children( get_the_ID(), $search_all_pages );
// Loop through everything we got back
if(!empty($loop_through_all_child_pages)){
foreach($loop_through_all_child_pages as $child_page){
// get the ID of each childpage
$get_child_page_ID = $child_page->ID;
// get the ID of each parent page of the child pages
$get_parent_page_ID = get_queried_object_id();
// Get the average score from post_meta of the parent page
$get_average_score = get_post_meta( $get_parent_page_ID, 'rwp_user_score', true );
// update each custom field of the childs with the average score data from the post meta of parent page
update_field('gemiddelde_score_hosting_provider', $get_average_score, $get_child_page_ID);
}
}
How can I correctly execute this code within the above function?
EDIT
Ok I figured this out, the function is working properly when I remove the parameters $review and $post_id. And when I remove the add action:
add_action('rwp_after_saving_review', 'when_a_review_gets_submitted', 11, 2);
and replace it with:
add_action( 'template_redirect', 'when_a_review_gets_submitted' );
but I think this is a bit overkill for what I am trying to achieve. If I understand template_redirect it executes the function everytime a page is visited with that template? Am I correct?
So when I have 900 child pages it updates every custom field "gemiddelde_score_hosting_provider" when a page with that template is visited? So 900 times every single time a page with that template is visited? Am I correct in this one?
Is there a way to only update the custom field of the childs from the parent page where the review is submitted?

WooCommerce execute function if product is from a certain category

I'm trying to translate my products in WooCommerce based on the category.
When WooCommerce is loaded, I run an action hook:
add_action( 'woocommerce_init', 'translate_products' );
In my function translate_products I run a WP_Query so I can translate the products based on the current ID of the loop. It only translates all products, not only the ones with the category 'en' though. I am unable to get only the ID of the products assigned to the 'en' category.
It would be more than great, if someone could help me. Thanks in advance!
I'm fairly new to Wordpress and especially WooCommerce coding, so please excuse me, if I'm doing a stupid mistake. ;)
Here's my code:
function translate_products() {
$args = array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => 'en' );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
global $product;
$current_id = get_the_id();
pll_set_post_language($current_id,'en');
endwhile;
wp_reset_query();
}
Use own function for fetch WooCommerce product is not good idea of wordpress programming.
Please read official document of WooCommerce. Open the link and find "Product Categories".
https://docs.woocommerce.com/document/woocommerce-shortcodes/
If you want to use category name of that product then you have to find its term id and use id and use in shortcode

Enabling permanently review checkbox option for all WooCommerce products

I would like to enable review checkbox permanently for all existing products and for newly added products too. I have looked in WooCommerce settings, but thatís not possible. I have search over internet, and I didnít find anything.
How can I bulk edit all existing products to get reviews Enabled?
When we add a new product it should be automatically checked too.
Is there a way to do it?
Is it possible?
Thanks in advance.
This is possible, but you will need 2 functions. One to update all existing products inn your shop, that you will use only one time, and the other for all newly published products.
Step 1 - Use this just once on function.php and go to front-end and navigate to any page. Once done comment this code or remove it. All your existing products have been updated.
// Updating all products that have a 'comment_status' => 'closed' to 'open'
function updating_existing_products_once(){
$args = array(
// WC product post type
'post_type' => 'product',
// all posts
'numberposts' => -1,
'comment_status' => 'closed',
'post_status' => 'publish',
);
$shop_products = get_posts( $args );
foreach( $shop_products as $item){
$product = new WC_Product($item->ID);
wp_update_post( array(
'ID' => $item->ID,
'comment_status' => 'open',
) );
}
}
// After usage comment this line below
updating_existing_products_once();
Step 2 - This function will update new created products that have a 'comment_status' => 'closed' to 'open' (reviews on WooCommerce)…
add_action('transition_post_status', 'creating_a_new_product', 10, 3);
function creating_a_new_product($new_status, $old_status, $post) {
if( $old_status != 'publish' && $new_status == 'publish' && !empty($post->ID) && in_array( $post->post_type, array( 'product') ) ) {
if ($post->comment_status != 'open' ){
$product = new WC_Product($post->ID);
wp_update_post( array(
'ID' => $post->ID,
'comment_status' => 'open',
) );
}
}
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
In addition to LoicTheAztec's excellent answer, I'd like to add a different option for "Step 1".
You could just run a simple query that doesn't require iterating over a loop:
global $wpdb;
$wpdb->query("UPDATE {$wpdb->posts} SET comment_status = 'open' WHERE post_type = 'product'");
Note the intentional omission of the comment_status and post_status in the WHERE clause. It would not matter that unpublished products have an open comment status, nor would it matter that products that already have comment_status set to open are being re-set to open.
Just add the above code to the bottom of your theme's functions.php file, and then comment them out after it has been run once:
// Commented out so it won't run
// global $wpdb;
// $wpdb->query("UPDATE {$wpdb->posts} SET comment_status = 'open' WHERE post_type = 'product'");
I know it's old question but function below could help someone if LoicTheAztec's answer won't work (like for me). It will check reviews' checkbox by default by using jQuery on "Add product" page. I hope help someone, cheers! :-)
add_action( 'woocommerce_product_options_advanced', 'enable_reviews_by_default' );
function enable_reviews_by_default() {
?>
<script>
(function($){
$('input[name=comment_status]').prop('checked', true);
})(jQuery);
</script>
<?php
}
By the way a dirty method of fixing things immediately (reversable). All credits to a guy Evgeniy
https://developer.wordpress.org/reference/functions/comments_open/
While the original thread discusses how to disable comments everywhere, I reversed the effect :)
This disables the possibility for you to decide on a per-product basis, because overrides the checkbox site-wide!
Disclaimer: do at your own risk!
add_filter( 'comments_open', '__return_true' );

Accessing woocommerce product attributes using query_posts

I am querying the posts as shown below:
query_posts('post_type=Product&showposts=-1');
This returns all post of type product. But I have custom attributes on my products that have been created in wooCommerce but I can't seem find this info anywhere.
I tried using:
$thePost = get_post_custom()
I also tried:
$thePost = get_post_meta(get_the_ID)
when I print_r these I get a lot of information but I can't see the product attributes from woocommerce anywhere
the image below shows how this information is set on the product.
How do I access this information after querying the post?
specifically I need to extract the colours and sizes.
Product variations are saved as another child posts (custom post type product_variation). Following code is untested, but you should get the point.
query_posts('post_type=Product&showposts=-1');
while( have_posts() ){
the_post();
$product_id = get_the_ID();
$variations = get_posts( array('post_type' => 'product_variation', 'post_parent' => $product_id, 'posts_per_page' => -1 ) );
foreach( $variations as $var){
$var_customs = get_post_customs( $var->ID );
// now you can inspect "meta" fields
}
}
So you have Product with ID=7 ->post_type=product, its variations are post_type=product_variation&post_parent=7. And sizes and coulours are saved as meta values of these variations. Meta keys start with attribute_pa_....

Categories