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.
Related
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);
});
To begin with I have created a simple plugin that contains this piece of code:
function woo_create_credit_attribute_taxonomy() {
$attributes = wc_get_attribute_taxonomies();
$slugs = wp_list_pluck( $attributes, 'remaining_credits' );
if ( ! in_array( 'remaining_creds', $slugs ) ) {
$args = array(
'slug' => 'remaining_creds',
'name' => __( 'Remaining Credits', 'bidrop-credits' ),
'type' => 'select',
'orderby' => 'menu_order',
'has_archives' => false,
);
$result = wc_create_attribute( $args );
}
}
// On Activation create the credit attribute taxonomy
add_action( 'admin_init', 'woo_create_credit_attribute_taxonomy' );
This piece of code, simply creates a new Woocommerce Product Attribute.
And in the uninstall.php file of the same plugin, I use the WPDB query below to remove it uppon uninstall.
global $wpdb;
$wpdb->query("DELETE FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE 1");
Notes: The Attribute is succesfully being deleted from the Database, but remains visible on front-end and when I try deleting it from the front-end it seems to be stuck there, Until I deactive and Reactivate Woocommerce.
Any ways I could adjust this code to flush_rewrite the woocommerces rules?
I have already tried the cassual flush_rewrite_rules() built-in function from wordpress. But it has no better results.
Thanks in advance for your time and effort
I am using a custom post type in my Wordpress install called 'profiles'. I have a custom plugin that creates the type and then pre-fills the custom post type with the content I want visible on EVERY instance of that CPT. See below:
function profile_content_write() {
$args = array(
'post_type' => 'profiles'
);
$pages = get_posts( $args );
foreach( $pages as $page ){
$post = array(
'ID' => $page->ID,
'post_content' => 'page content...',
);
wp_update_post( $post );
}
}
add_action( 'init', 'profile_content_write' );
However, from time to time I will need to modify the default content. While new posts using the 'profiles' type will feature the new content (if I change my plugin code above), existing posts will NOT.
Anyone have an effective way to update the content of a post type? I am fine modifying the content by updating a plugin. Alternatively, I am comfortable making a menu item that can run the update. I am just unsure of HOW to update the content.
Note: I do not want to "append" content, but "rewrite content." Also, I will NOT write content in this post type outside what is displayed through the plugin function.
UPDATED, WORKING CONTENT
This works by activating and then deactivating the plugin files. Activating it rewrites all CPT post content. To update the content, modify the plugin file, then reactivate/deactivate.
function profile_content_write() {
$args = array(
'post_type' => 'profiles',
'numberposts' => -1
);
$pages = get_posts( $args );
foreach( $pages as $page ){
$post = array(
'ID' => $page->ID,
'post_content' => 'page content...',
);
wp_update_post( $post );
}
}
add_action( 'init', 'profile_content_write' );
I am adding one CPT to another CPT dynmaically. When using wp_insert_post() it creates duplicates when I add_action('init', 'function_name'); Any idea what hook to use to simply add them:
function cpt_to_cpt(){
// Grab posts
$args = array(
'post_type' => ' custom_type1 ',
'order' => 'ASC',
'post_status' => 'publish',
'numberposts' => -1,
);
$posts = get_posts($args);
foreach ( $posts as $post ) {
wp_insert_post(array(
'post_type' => 'custom_type2',
'post_title' => $post->post_title,
'post_date' => $post->post_date,
'post_author' => $post->post->author,
'post_status' => 'publish',
)
);
}
add_action('init', 'cpt_to_cpt');
Try using:
wp_loaded
add_action('wp_loaded', 'cpt_to_cpt');
or
wp
add_action('wp', 'cpt_to_cpt')
WordPress init and wp_loaded hooks fire on the "loading" stage. It means they both can fire more than one time when refreshing the page.
Solution 1
You can use another hook that fires later.
wp hook, for instance, fires on the "processing" stage and should run only once.
add_action('wp', 'cpt_to_cpt');
Order of precedence: init 🠆 wp_loaded 🠆 wp
Solution 2
If you really want to use init hook and make sure it will run one time. You can use the snippet below.
function cpt_to_cpt() {
$runtime = 'run_only_01;
if (get_option('my_run_only_once_option') != $runtime) {
$updated = update_option('my_run_only_once_option', $runtime);
if ($updated === true) {
// do some stuff
}
}
}
add_action('init', 'cpt_to_cpt');
It will create an option on your wp_option table. In the end, you need to delete the option manually (on your database) or in your code.
delete_option('my_run_only_once_option');
Solution 3
Maybe the best professional solution to create multiple posts or CPTs (custom post types) should be using wp-cli (command line interface for WordPress).
Please take a look in the documentation here: https://developer.wordpress.org/cli/commands/post/
I have a Portfolio on my website built with Wordpress custom post types and Advanced custom fields - I currently have this bit of code, looping through the 'brand' category of my portfolio:
<?php
$portfolio_args = array(
'post_type' => 'portfolio',
'portfolio-category' => 'brand',
'posts_per_page' => -1
);
$portfolio = new WP_Query($portfolio_args);
while($portfolio->have_posts()) {
$portfolio->the_post();
$post = new SeedPost(get_the_ID());
$post->display(true);
}
wp_reset_query();
?>
This works fine, but I would like to bring in the category name dynamically from a custom field... So, this is the line I think I should edit...
'portfolio-category' => 'brand',
I have tried the following two options but neither seem to work:
'portfolio-category' => '<?php the_field('category_to_show'); ?>',
'portfolio-category' => 'the_field('category_to_show');',
I understand the first option probably doesn't work because I have more PHP tags in there so I removed them for the second attempt - Still isn't working though - Can anyone help?
You should be able to get what you need like this:
$portfolio_args = array(
'post_type' => 'portfolio',
'portfolio-category' => get_field('category_to_show'),
'posts_per_page' => -1
);
The get_field() function returns the value of the specified field.
Hope this helps...
Ref: https://www.advancedcustomfields.com/resources/get_field/