Woocommerce: Dynamically change attributes / parameters of a WC Render-Block - php

I use the Woocommerce “Handpicked products” Block in Wordpress Gutenberg to create a showcase of 3 products on my Frontpage. I saw that Woocommerce does not use Shortcodes for that, but that the page itself includes a paragraph which looks like this:
<!-- wp:woocommerce/handpicked-products {"contentVisibility":{"image":true,"title":true,"price":false,"rating":false,"button":false},"orderby":"menu_order","products":[181,225,179]} /-->"
I want to dynamically change the products (randomly shuffle) upon page load. Unfortunately, in the whole PHP-classes HandpickedProducts, AbstractProductGrid, AbstractDynamicBlock etc I do not see a Hook to change the Render parameter dynamically...
So what I found as possible solution is: To directly replace the product attribute in the Wordpress Post itself, therefore I implemented this hook:
function my_the_post_action(&$pobj) {
$pobj->post_content = str_replace('[181,225,179]', '[225, 220, 222]', $pobj->post_content );
}
add_action('the_post', 'my_the_post_action' );
It is actually replaced in the wp:woocommerce/handpicked-products paragraph, but doesnt take effect. Why does Woocommerce not consider the new Product IDs as parameters to his rendered block?
Thanks!!

Instead of modifying the "Blocks" entered via Pageeditor upon Pageload within the Frontpage - I came up with a better and cleaner option IMHO - by simply rendering such a Block within a customer Shortcode.
The following code consists of first the part where I randomly pick 3 products from the Database which have the Product-Tag "Featured" set so that the user can decide himself which products are open for selection ... and then I create my "Handpicked Products" block and render it:
add_shortcode('my_featured_prods', function($atts, $content = null)
{
// Get list of all Woocommerce products by Tag
$args = array(
'post_type' => 'product',
'posts_per_page' => 3,
'orderby' => 'rand',
'tax_query' => array(
array(
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => 'featured'
)
)
);
$products = new WP_Query($args);
$ids = [$fix];
foreach($products->posts as $p)
$ids[] = $p->ID;
// Shuffle array:
shuffle($ids);
// Output Hand Picked Products Widget with my settings ...
$args = (object) [
'editMode' => 0,
'contentVisibility' => (object) [
'image' => 1,
'title' => 1,
'price' => 0,
'rating' => 0,
'button' => 0,
],
'orderby' => 'random',
'products' => $ids,
'alignButtons' => 1,
];
$args = sprintf(
'<!-- wp:woocommerce/handpicked-products %s /-->',
json_encode( $args )
);
return do_blocks($args);
});

Related

Wordpress ACF meta query using a plugin

I am running the plugin WP Show Posts on a WP install with a custom post type (called 'trees') that has a custom post field called 'popularity' (formatted as “number”). The custom field was created by the Advanced Custom Fields plugin, the custom post type with the plugin Custom Post Type UI.
Now, I want to create a list, that only shows posts with a popularity value below the numeric value of 10.
To do so, I have followed the plugin author's instructions here and adjusted the plugin itself to allow for additional arguments.
I now use the following code, as suggested in this support article, but unfortunately, I can not get it to work. The output is the “no results message”. 🙁
This is the code I use in my functions.php:
add_filter( 'wp_show_posts_shortcode_args', function( $args, $settings ) {
if ( 4566 === $settings['list_id'] ) {
$args['meta_query'] = array(
array(
'key' => 'popularity',
'value' => 10,
'compare' => '<'
)
);
}
return $args;
}, 15, 2 );
What do I do wrong? For example, do I have to specify the custom post type (i.e. trees)?
If you really want to use this "WP Show Posts" plugin, at the moment that i'm writing this answer, you need to modify its core functionality in order to be able to modify its query.
Go to this path your site folder > wp-content > plugins > wp-show-posts, and open up wp-show-posts.php. On line 386:
Replace
$query = new WP_Query(apply_filters('wp_show_posts_shortcode_args', $args));
with this:
$query = new WP_Query(apply_filters('wp_show_posts_shortcode_args', $args, $settings));
Now you can modify the query. Use the following snippet in your functions.php file.
add_filter('wp_show_posts_shortcode_args', 'your_custom_query', 10, 2);
function your_custom_query($args, $settings)
{
$args = $args;
if (4566 === (int)$settings['list_id']) {
$args['meta_query'] = array(
array(
'key' => 'popularity',
'value' => '10',
'compare' => '<',
'type' => 'NUMERIC'
)
);
}
return $args;
}
Note:
Make sure 4566 is the id that WP Show Posts plugin gives you, otherwise it won't work.
By following these steps, you're modifying, WP Show Posts plugin core file (i.e. wp-show-posts.php) which is NOT RECOMMENDED. So on the next update of the plugin, make sure that the line you modified, stays intact, otherwise it'll break you page. So keep an eye on the updates!
Because your field type is numeric, i've added 'type' => 'NUMERIC' argument, otherwise it won't work.
Another solution using wp_query. NO EXTRA PLUGINS
This is a simple wp_query that allows you to do the job without using any third-party plugins.
$args = array(
'post_type' => 'trees',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'popularity',
'value' => '10',
'compare' => '<',
'type' => 'NUMERIC'
)
)
);
$query = new WP_Query($args);
if ($query) {
while ($query->have_posts()) {
$query->the_post(); ?>
<h4><?php the_title() ?></h4>
<?php
}
} else {
echo "no post found!";
}
wp_reset_postdata();
This has been fully tested on wordpress 5.8 and works.

Get page content by slug or title wordpress

I am creating a blog and I have difficulty with pages in wordpress, in my case I would like to insert content (raw content) from two pages randomly in modal system while people browse the blog.
Example:
Current Page> Modal Box> Page01 content or Page02 Content
I know it's possible by the page id. but I would like to make it more dynamic by getting the contents of the pages by slugs or by title.
here's the code
<?php
$term = get_taxonomy( $slug );
$args = array(
'post_type' => 'page',
'posts_per_page' => 1,
'orderby' => 'RAND',
'tax_query' => array( array(
'taxonomy' => $term,
'field' => 'slug',
'terms' => array('page-01', 'page-02'),
) )
);
$rand = new WP_Query($args);
if ($rand->have_posts()) {
while ($rand->have_posts()) {
$rand->the_post();
the_content();
}
}
?>
I know that removing taxonomy from query gets the contents of publish pages but, in my case, I need to get content from two specific pages
You can use post_name__in to filter by multiple slugs, eg:
$args = array(
'post_name__in' => array('page-slug-1', 'page-slug-2'),
'post_type' => 'page',
'posts_per_page' => 1,
'orderby' => 'RAND',
);
You can find more details on the WP_Query documentation page.

Find tags by custom field value - Wordpress

I'm customizing the admin of wordpress and I've created a new custom input field for the tags of a post.
It's a dropdown list with all the categories of a post. Now, I wanna find all the tags with an specific category. So, I'm using this:
$args = array(
'meta_key' => 'project',
'meta_value' => $idProject,
);
$allTags = get_tags( $args );
Is this the right way to get all the tags that I want? The problem is that the array list with the tags is coming with only one result. It should bring 2 tags with the project id that I'm passing on the variable $args.
Am I missing something?
I found a solution:
$args = array(
'hide_empty' => false, // also retrieve terms which are not used yet
'meta_query' => array(
array(
'key' => 'project',
'value' => $idProject
)
)
);
$terms = get_terms( 'post_tag', $args );

WooCommerce products widget for a specific category - set category array per widget

I had the same question as Quadie as answered in the following thread.
The code as provided by LoicTheAztec works great...
add_filter( 'woocommerce_products_widget_query_args', function( $query_args ){
// Set HERE your product category slugs
$categories = array( 'music', 'posters' );
$query_args['tax_query'] = array( array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $categories,
));
return $query_args;
}, 10, 1 );
... but I would like to know if there is an option to extend this code to be able to set the categories per seperate widget. E.g. I want a products widget for category 1 on a page x, while I want a products widget for category 2 somewhere else on page x.
I was thinking about using a shortcode & specifying the category as an array for this shortcode, but not sure on how to implement this.
Any thoughts on this issue?
This is the shortcode I tried to use:
[productsbycat cat1="broodjes"]
& it triggers the following code:
function productsbycat_func( $atts ) {
$categories = shortcode_atts( array(
'cat1' => 'something',
'cat2' => 'something else',
), $atts );
add_filter( 'woocommerce_products_widget_query_args', function ( $query_args ){
$query_args['tax_query'] = array( array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $categories,
));
return $query_args;
}, 10, 1 );
}
add_shortcode( 'productsbycat', 'productsbycat_func' );
However, it does not generate anything yet.
Is not possible to extend my code "to be able to set the categories per seperate widget".
For your shortcode only I think that you don't need any code customization for that.
I you look to the WooCommerce Official documentation related to WooCommerce Shortcodes, you will see on section "Product category" this short code: [product_category], which main argument is category
You can add one product category slugs this way:
[product_category category="clothing"] // One product category
Or for many product categories slugs (coma separated) this way:
[product_category category="posters,music"]
The default arguments settings (that you can change) are:
$args = array(
'per_page' => "12",
'columns' => "4",
'orderby' => 'title', // or by "menu_order"
'order' => "asc", // or "desc"
'category' => "" // Always only product category slugs
'operator' => "IN" // Possible values are "IN", "NOT IN", "AND".
);
But it will not work as you would like in your product widgets as it will display the product grid loop for the defined categories
You should need to build your own widgets.

Woocommerce related product array with user input

I am using the following code as the footer of my single-product.php page in Woocommerce (I've created a "Related Products" section) and I am wondering if there is a way that I can alter it to make it possible for admin to be able to add values from the product admin page; I want certain products to show closer related products instead of totally random ones.
Is there a way I can create a custom field for something like product ID or tag and then add that custom field as the orderby value so those products/tags have a better change of showing up vs. random products?
If not, is there anything else I can do? I am simply looking for a way to allow an admin to choose closer related products to appear.
$args = apply_filters( 'woocommerce_related_products_args', array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => 5,
'orderby' => rand,
'post__in' => $related,
'post__not_in' => array( $product->id )
) );
Here is my related-footer.php file with the complete code that includes the above snippet.
Yes you can achieve this task as with the following approach:
Create a custom field for the product you want to display a set of your desired related products say the custom field name be "wdm_related_products" set the value to a comma separated list of Product ids eg. 46,15,687,21,48.
Update the product.
Add the following code in functions.php of user child theme or a custom Plugin.
add_filter('woocommerce_related_products_args','wdm_custom_related_products',99,1);
function wdm_custom_related_products($array){
global $product;
if(get_post_meta($product->,'wdm_related_products',true)){
$related=get_post_meta($product->id,'wdm_related_products',true);
$array=array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => 5,
'orderby' => rand,
'post__in' => $related,
'post__not_in' => array( $product->id )
);
}
return $array;
}
Let me know it it resolved your issue.

Categories