Trigger action when new post is insert in wordpress - wordpress

My question is,
Is there any filter or action that trigger when new post is insert in database..?
The reason behind it is I want to add key in post meta when new post is insert from admin side.
I got Action called "save_post" but after refer link .This action trigger in created and update post.
but I only want to add meta key when post is created not at update time

You can use wp_insert_post so you will get post_id as soon as post inserted and you can then use that to add meta_key.
If you are not using wp_insert_post and want to use action then you can simply put below code :
if ( wp_is_post_revision( $post_id ) )
return;
which means that if you are updating the post, then it will return back from function.
EDITED
Method-1 to achieve it.
You can simply check with the get_post method that post is there or not.something like below:
add_action('save_post', 'check_for_post_in_database');
function check_for_post_in_database($post_id) {
//check if the post is in the database or not with get_post( $post_id ) == null
if( get_post( $post_id ) == null ) {
//your code to add meta
}
}
//You can do same thing with publish_post
Method-2 to achieve it.
add_action('publish_post', 'check_for_meta_in_database');
function check_for_meta_in_database($post_id) {
global $wpdb;
$your_meta = get_post_meta($post_id, 'meta_key', true);
if( empty( $your_meta ) && ! wp_is_post_revision( $post_id ) ) {
update_post_meta($post_id, 'meta_key', 'meta_value');
}
}
But as you said there are many meta there, this method will be bit long.
Method-3 to achieve it.
You can do as rnevius suggested which is the one even I would opt. Its like :
add_action( 'transition_post_status', 'check_transition_and_then_add_meta', 10, 3 );
function check_transition_and_then_add_meta( $new_status, $old_status, $post ) {
if ( ( 'draft' === $old_status || 'auto-draft' === $old_status ) && $new_status === 'publish' ) {
add_post_meta($post->ID, 'your_meta_key', 'your_meta_value');
}
}
or else you can do it with draft_to_publish like:
//as rnevius suggested {$old_status}_to_{$new_status}
add_action( 'draft_to_publish', 'add_meta_when_status_change' );
function add_meta_when_status_change() {
add_post_meta($post->ID, 'your_meta_key', 'your_meta_value');
}
You can refer codex for more information about post transition.

You're looking for draft_to_publish.
An {old_status}_to_{new_status} action will execute when a post transitions from {old_status} to {new_status}. The action is accompanied by the $post object.

Related

Creating a WordPress post publish button on the front end

How can I create a button in the frontend that when the user clicks on the button, the post changes from draft to published?
I use the default function to generate the shortcode but it doesn't work
In fact, the post that is currently available and in the draft status in the front form, the user clicks on the button to publish it.
function wp_publish_post( $post ) {
global $wpdb;
$post = get_post( $post );
if ( ! $post ) {
return;
}
if ( 'publish' === $post->post_status ) {
return;
}
$post_before = get_post( $post->ID );
add_shortcode('publish_post','wp_publish_post');
tanks

WPML how to add a featured image without duplicate to a translated post (wordpress)?

I translated a post using WPML.
The problem is that it doesn't add a featured image to the translated post.
It takes up too many size to duplicate images using a WPML media transltion,
so I'd like to add a featured image without duplicate to a tranlsated post (wordpress).
Would you please let me know how to solve this problem?
Thank you.
In case there is someone who needs this.
I solved the problem using the foolowing code.
add_action( 'wp_insert_post', 'my_duplicate_on_publish' );
function my_duplicate_on_publish( $post_id ) {
global $post;
// don't save for autosave
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// dont save for revisions
if ( isset( $post->post_type ) && $post->post_type == 'revision' ) {
return $post_id;
}
if ($post->post_type=='your-post-type') {
//we need this to avoid recursion see add_action at the end
remove_action( 'wp_insert_post', 'my_duplicate_on_publish' );
// make duplicates if the post being saved
// #1. itself is not a duplicate of another or
// #2. does not already have translations
$is_translated = apply_filters( 'wpml_element_has_translations', '', $post_id, $post->post_type );
if ( !$is_translated ) {
do_action( 'wpml_admin_make_post_duplicates', $post_id );
}
//must hook again - see remove_action further up
add_action( 'wp_insert_post', 'my_duplicate_on_publish' );
}
}

Set Wordpress excerpt and post thumbnail based on custom field

As stated in the title, I would like to automatically save/update the value of post_excerpt and post_thumbnail based on an ACF custom field (mostly for compatibily reasons with other plugins). Now, while tring to accomplish this I encountered 2 issues, first being with the following function:
function test_FeaturedImageSetByACF() {
$current_screen = get_current_screen(); // Current admin screen needed to identify the current cpt
$current_cpt_name = $current_screen->post_type; // Current cpt name
$current_cpt_support = 'thumbnail'; // We want to check if the CPT supports this feature
$post_id = get_the_ID(); // Current post ID
$post_image_field = get_field('post_head_img'); // ACF field we want to sync
$post_image_id = $post_image_field['id']; // ACF image filed ID
$post_image_url = $post_image_field['url']; // ACF image filed URL
// If current cpt supports thumbnails/featured images
if ( post_type_supports( $current_cpt_name, $current_cpt_support ) ) {
if ( ( $post_image_url ) AND ( ( $post_image_url ) != ( get_the_post_thumbnail() ) ) ) {
delete_post_thumbnail( $post_id );
set_post_thumbnail( $post_id, $post_image_id );
}
}
}
add_action('save_post', 'test_FeaturedImageSetByACF', 13, 2 );
add_action('publish_post', 'test_FeaturedImageSetByACF', 10, 2 );
It does work, however sometimes it seems to update the value only the second time I save (which means I have to save twice). I understand I'm either using a wrong hook, a wrong priority or something like that, but I can't figure out which one it is.
Second issue I have, is I would like to accomplish something similar for post excerpts. Now the functions's will look alike the previous one quite a lot, but I don't know which value to update. Can anyone point me in the right direction?
Thanks in advance
You can use acf/save_post hook. Object ID is passed
add_action('acf/save_post', 'handle_acf', 20);
function handle_acf($object_id)
{
// Do your stuff
}
Since this became more of an ACF specific question rather than a generic one, I decided to post on ACF's support forums aswell were user John Huebner pointed me in the right direction. For anyone interested, the topic can be found at https://support.advancedcustomfields.com/forums/topic/set-wordpress-excerpt-and-post-thumbnail-based-on-custom-field/ while (in the event that post may get deleted or something) this is the code I used both for the excerpt part and the custom post thumbnail/featured image:
add_action('save_post', 'flex_CustomExcerptSetByACF', 50);
function flex_CustomExcerptSetByACF() {
global $post;
$post_id = ( $post->ID ); // Current post ID
$post_excerpt = get_field( 'post_excerpt', $post_id ); // ACF field
if ( ( $post_id ) AND ( $post_excerpt ) ) {
$post_array = array(
'ID' => $post_id,
'post_excerpt' => $post_excerpt
);
remove_action('save_post', 'flex_CustomExcerptSetByACF', 50); // Unhook this function so it doesn't loop infinitely
wp_update_post( $post_array );
add_action( 'save_post', 'flex_CustomExcerptSetByACF', 50); // Re-hook this function
}
}
add_action('save_post', 'flex_FeaturedImageSetByACF', 50);
function flex_FeaturedImageSetByACF() {
$current_screen = get_current_screen(); // Current admin screen needed to identify the current cpt
$current_cpt_name = $current_screen->post_type; // Current cpt name
$current_cpt_support = 'thumbnail'; // We want to check if the CPT supports this feature
global $post;
$post_id = ( $post->ID ); // Current post ID
$post_image_field = get_field('post_head_img', $post_id ); // ACF field
if ( ( $post_id ) AND ( $post_image_field ) ) {
$post_image_id = $post_image_field['id']; // ACF image filed ID
$post_image_url = $post_image_field['url']; // ACF image filed URL
// If current cpt supports thumbnails/featured images
if ( post_type_supports( $current_cpt_name, $current_cpt_support ) ) {
if ( ( $post_image_url ) AND ( ( $post_image_url ) != ( get_the_post_thumbnail() ) ) ) {
update_post_meta($post_id, '_thumbnail_id', $post_image_id);
}
}
}
}

Attach media to post WordPress hook

I need an action to be triggered when a detached media is being attached to a post.
It seems that this behavior is handled in wp-admin/upload.php on line 76 by setting the parent of the attachment post with a DB query. There are no hooks in the file.
Is there a way to get an action triggered on this event (some low level DB write hook or whatever) in which I could get the ID of the parent post to which the attachment is being attached?
You could hook into wp_redirect and get the parent post ID from the $_REQUEST. The following is based on an answer I gave here:
add_filter( 'wp_redirect', 'so16798615_wp_redirect', 25, 1 );
function so16798615_wp_redirect( $location )
{
if( ! is_admin() )
return $location;
global $pagenow;
if( 'upload.php' == $pagenow && isset( $_REQUEST['found_post_id'] ) )
{
$parent_id = (int) $_REQUEST['found_post_id'];
if ( ! $parent_id )
return $location;
$parent = get_post( $parent_id );
// do stuff with parent
}
return $location;
}

Wordpress Custom Meta Boxes Validation

Is there any way to validate custom meta box fields without using javascript. If it doesn't validate I want to stop the post from being saved to the database.
Since the 'save_post' action is run AFTER publishing and updating, there's really no way of validating custom keys without a hackish alternative.
However, I'm thinking you can mimic the functionality you want by employing 'save_post' in the way Viral suggested, but rather than interrupt or cancel the saving process upon a validation error, you can just delete the post altogether:
add_action('save_post', 'validate_meta');
function validate_meta($post_id)
{
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $post_id;
/*USE THIS ONLY IF YOU ARE UTILIZING NONCE FIELDS IN A CUSTOM META BOX
if ( !wp_verify_nonce( $_POST['metabox_nonce'], basename(__FILE__) ) )
return $post_id;*/
/*Use plugin_basename(__FILE__) if this is an actual plugin, rather than
a part of your theme*/
if ( 'page' == $_POST['post_type'] )
{
if ( !current_user_can( 'edit_page', $post_id ) )
return $post_id;
}
else
{
if ( !current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
/*VALIDATE YOUR METADATA HERE HOWEVER YOU LIKE
if(is_valid($_POST['metadata']))
$validated = true;
else
$validated = false;
*/
if(!$validated)
wp_delete_post($post_id, true);
else
return $post_id;
}
The only thing to watch out for with this approach is that it will run upon both Publishing and Updating as well. You may want to consider adding a check to ensure that the post is deleted only for newly published posts, and updated posts are rolled back to a previous version and the invalid revision is deleted.
The wp_insert_post_data filter is what you are looking for. Something like this should do the trick:
add_filter( 'wp_insert_post_data', 'my_validation_function' );
function my_validation_function( $data ) {
// Don't want to do this on autosave
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $data;
if ( $data['some_key'] != 'some_value' ||
$_POST['some_meta_key'] != 'some_meta_value' ) {
$data['post_status'] = 'draft'; // or whatever status to revert to
add_filter( 'redirect_post_location', 'remove_message'); // remove the publish success message
}
return $data;
}
function remove_message( $location ) {
return remove_query_arg( 'message', $location);
}
Straight from the WP Codex # http://codex.wordpress.org/Function_Reference/add_meta_box, you call the save_post hook and specify the function that will be run to validate/save your data:
/* Do something with the data entered */
add_action('save_post', 'myplugin_save_postdata');
Then you define that function, which will automatically be passed the post id. Additionally, you can access the $_POST array to get the values in your metaboxes:
/* When the post is saved, saves our custom data */
function myplugin_save_postdata( $post_id ) {
// verify if this is an auto save routine.
// If it is our form has not been submitted, so we dont want to do anything
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return $post_id;
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
return $post_id;
// Check permissions
if ( 'page' == $_POST['post_type'] )
{
if ( !current_user_can( 'edit_page', $post_id ) )
return $post_id;
}
else
{
if ( !current_user_can( 'edit_post', $post_id ) )
return $post_id;
}
// OK, we're authenticated: we need to find and save the data
$mydata = $_POST['myplugin_new_field'];
// Do something with $mydata
// probably using add_post_meta(), update_post_meta(), or
// a custom table (see Further Reading section below)
return $mydata;
}
All of your routines to valid data will be done within this function. In the end, you will likely save the data using something like:
update_post_meta('meta_key', 'meta_value');

Resources