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/
Related
I'm stuck on something that I'm sure must be pretty simple but is getting me nuts. I'm forced at work to use WordPress, which I have zero experience with, and I'm struggling so far to understand how it operates regarding hooks and filters.
What I want is pretty simple:I'm using the latest posts block to display posts written by users. Except that the page I'm working on would be the front end for the website's moderator who would have to see the posts with the 'pending' status, not the 'publish' one. I couldn't find any option to change that in the editor, so I'm trying to set a hook to change the query from 'post_status' => 'publish' to 'post_status' => 'pending', but it's not working, I get a 'Oops! That page can’t be found.'
Here's what I wrote in my functions.php:
function name_of_the_function( $query ) {
if( get_query_var('pagename') == 'name_of_the_page' && current_user_can('publish_posts') && $query->is_main_query() ) {
$query->set( 'post_status', 'pending' );
return $query;
}
}
add_filter( 'pre_get_posts', 'name_of_the_function' );
If I leave this function exactly like that but write 'publish' instead of 'pending' the page displays correctly the last published posts, but with 'pending' I get the message I mentioned before. And I tried with add_action instead of add_filter and got hte same results.
I'd like to add that I do have pending posts awaiting, and if I write the following in my page template, they are found:
$args = array (
'cat' => 5,
'post_status' => 'pending'
);
$query = new WP_Query( $args );
while ( $query->have_posts() ) {
$query->the_post();
echo get_the_title();
}
Just to check, directly in the wp-includes/latest-posts.php file, I changed :
$args = array(
'posts_per_page' => $attributes['postsToShow'],
'post_status' => 'publish',
'order' => $attributes['order'],
'orderby' => $attributes['orderBy'],
'suppress_filters' => false,
);
to :
$args = array(
'posts_per_page' => $attributes['postsToShow'],
'post_status' => 'pending',
'order' => $attributes['order'],
'orderby' => $attributes['orderBy'],
'suppress_filters' => false,
);
It works and displays the pending posts but of course I can't use that as the file would be erased at every WordPress update.
Sorry for the long post but I'm lost now and don't know what else to do, I've looked all other the intrnet but can't find an answer to this, I would really appreciate any help regarding that matter, thanks in advance.
By using the pre_get_posts with $query->is_main_query(), you apply this to the query that WordPress uses to find the page (the main query). Your code needs to be changed to:
function name_of_the_function( $query ) {
if ( is_admin() || $query->is_main_query() ) {
return $query;
}
if( get_query_var('pagename') == 'name_of_the_page' && current_user_can('publish_posts') ) {
$query->set( 'post_status', 'pending' );
}
return $query;
}
add_filter( 'pre_get_posts', 'name_of_the_function' );
So basically, don't run this on any query in the admin or any query that is the main query, but only run it on a specific page for people with specific capabilities.
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.
I am using JetPack's Infinite Scroll on the homepage of our site and it is working fine but I also want to display certain posts on there.
If a post is displayed outside the infinite loop I want it to be removed from the so there is no duplication.
I have a global array set up using bm_ignoreposts and have added it to the infinite loop render but for some reason it is not working. Here is the code.
Functions.php
The infinite renderer.
add_filter( 'infinite_scroll_archive_supported', 'tweakjp_custom_is_support' );
function mm_infinite_scroll_render() {
global $post;
while ( have_posts() ) : the_post();
bm_ignorePost($post->ID);
get_template_part( 'content-inf' );
endwhile;
}
The query
function mm_infinite_scroll_query_args($args) {
$new_args = array(
'posts_per_page' => $args['posts_per_page'],
'paged' => $args['paged'],
'orderby' => 'date',
'order' => 'DESC',
'post_type' => array( 'post', 'features', 'it_hardware', 'videos' ),
'post_status' => 'publish',
);
return $new_args;
}
For reference here is the ignore posts code:
function bm_ignorePost ($id) {
if (!is_page()) {
global $bmIgnorePosts;
$bmIgnorePosts[] = $id;
}
}
I decided to not use JetPack anymore and go for a custom Javascript version which uses AJAX to load new posts running a new query.
After speaking to Jetpack support, they believe it is not possible based on how the plugin works.
What code/filter can I add to my wordpress functions.php file to modify the order of grouped products by post date instead of menu_order? class-wc-product-grouped.php
$args = apply_filters( 'woocommerce_grouped_children_args', array(
'post_parent' => $this->id,
'post_type' => 'product',
'orderby' => 'menu_order',
'order' => 'ASC',
'fields' => 'ids',
'post_status' => 'publish',
'numberposts' => -1,
) );
I'm pretty sure you can hook into it but just not sure how to configure the following filter/hook woocommerce_grouped_children_args
As you have mentioned, you just need to filter the $args being passed through the woocommerce_grouped_children_args filter.
add_filter( 'woocommerce_grouped_children_args', 'so_29973708_grouped_children_args' );
function so_29973708_grouped_children_args( $args ){
$args['orderby'] = 'date';
$args['order'] = 'DESC';
return $args;
}
If you need help understanding filters, I wrote what I think is a pretty good tutorial on how to use filters
Update If you aren't seeing any changes, chances are that the grouped product's children have already been stored in a transient. You will need to delete this transient to see changes right away. You can clear all WooCommerce product transients via the Admin. Navigate to WooCommerce>System Status>Tools and click on the button to clear transients.
I have been trying this project of mine for a while now and I have got no luck. I'm trying to create 8 post programmatically in functions.php. I need these to only post 1 time. The problem I've been having is everytime I refresh the page the post will just auto create more. Here is my code to create post progammatically in functions.php.
<?php // Create post object
$my_post = array(
'post_title' => 'How to make your diet success',
'post_name' => '7-ways-to-make-succes-Diet',
'post_content' => 'my content',
'post_status' => 'publish',
'post_author' => 1,
'post_category' => array(8,39)
);
// Insert the post into the database
wp_insert_post( $my_post ); ?>
The only proble with this code is that it auto creates more post every time the page refreshes. I'm going to be creating 8 of these functions and I only want them to be created once. A code example would be great.
Next, I want to display the post on my index.php. I want to get these post individually. Here is my code I have so far.
<div class="post1"><?php $post_id = wp_insert_post( $post, $wp_error );
//now you can use $post_id withing add_post_meta or update_post_meta ?> </div>
<div class="post2"><?php $post_id = wp_insert_post( $post, $wp_error );
//now you can use $post_id withing add_post_meta or update_post_meta ?> </div>
I'm pretty sure I need to either call the slugs or post name to get them individually. Yes, I have tried this method as well as 10 other methods but nothing has worked. The closest I got was it to display the post name. Code examples would be great. I will be so grateful and probably donate some money via paypal if someone can get this working for me. Thanks.
functions.php is not a good place for programatically create pages nor posts. You should create a plugin (it is simple as creating custom theme) and create posts in its activation function. This function is called only on your plugin activation. Read also about plugin deactivation a uninstall hooks
The reason why your posts get created again and again is that file functions.php is called each time the page is requested. If you insist on creating posts in functions.php, you should wrap your wp_insert_post by a condition chcecking whether your posts are already created - than get_posts function would suit your needs.
<?php
//Use either post slug (post_name)
$post = get_posts( array( 'name' => '7-ways-to-make-success-diet' ) );
/*or $post = get_posts( array( 'name' => sanitize_title('My Single.php Test') ) );
if you do not set the post_name attribute and let WordPress to set it up for you */
if ( empty($post) ) {
// Create post object
$my_post = array( 'post_title' => 'My Single.php Test', 'post_name' => '7-ways-to-make-success-diet', 'post_content' => 'my content4654654', 'post_status' => 'publish', 'post_author' => 1, 'post_category' => array(8,39) );
// Insert the post into the database
wp_insert_post( $my_post );
}
?>
Also, get_posts will help you to bring your posts on front page. Eg.
<?php
$post = get_posts( array( 'name' => 'How to make your diet success' ) );
echo $post->post_title;
...
?>