i need a hook for the moment when an admin updates a post. (Click on update button). After the post is successfully updated.
The reason is, i have to call a function to update something for another plugin.
Everything i tried so far, is not working.
add_action( 'save_post', 'wpse41912_save_post' );
add_action( 'edit_post', 'wpse41912_edit_post' );
add_action( 'transition_post_status', 'wpse41912_transition_post_status' );
add_filter( "edit_post_{$field}", 'filter_edit_post_field', 10, 2 );
add_action( 'admin_head-post.php', 'admin_head_post_editing' );
add_action( 'admin_head-post-new.php', 'admin_head_post_new' );
add_action( 'admin_head-edit.php', 'admin_head_post_listing' );
In Everything function i wrote this, and i didnt see the echo or the alert box.
echo "my_update_user_meta";
$text = "my_update_user_meta";
echo '<script type="text/javascript">alert("' . $text . '")</script>';
Edit: i was missing the 3,4th parameter.
My Code now
add_action( 'save_post', 'mmx_save_post_action', 10, 3 );
function mmx_save_post_action( $post_id, $post, $update ) {
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) { // keine Aktion bei Autosave
//autosave
}else{
//no autosave
if ( is_admin() && current_user_can( 'manage_options' ) ) {
//admin panel && permission ok
//call function
}
}
}
When a post is updated there are some hooks that are fired:
'pre_post_update' is an action fired just before the post is updated, the argument passed are 2: $post_ID and $data that is an array of all the other database colums of the post table
'transition_post_status' is an hook fired on update, and pass 3 arguments: $new_post_status, $old_post_status and $post (object).
Then, there are other 2 transition hooks fired, but they are dynamic named, it means that the effective action fired depends on the old and the new post status.
"{$old_status}_to_{$new_status}" and "{$new_status}_{$post->post_type}". First pass the only the post object as argument, the second pass the post id and the post object. Find documentation here.
'edit_post' that pass 2 arguments: $post_ID and $post (object)
'post_updated' that pass 3 arguments: $post_ID, $post_after (post object after the update), $post_before (post object before the update)
Another dynamic hook: "save_post_{$post->post_type}" that depends on post type, e.g. for standard posts is 'save_post_post' and for pages is 'save_post_page', this hook pass 3 arguments: $post_ID, $post (object) and $update that is a boolean (true or false) that is true when you perform an update, in fact this hook is fired also when a post is saved for first time.
'save_post' that is fired both on update and on first saving, and pass the same 3 arguments of the previous hook.
'save_post_{$post_type}' that is fired both on update and on first saving, and pass the same first 2 arguments of the previous hook.
Finally you have 'wp_insert_post', that is fired both on update and on first saving, and pass the same 3 arguments of the previous 2 hooks.
These hook are fired every time a post is updated, both via admin pages in backend and via when updated "manually" using wp_update_post or wp_insert_post functions.
When the post is updated using admin pages there are additional hooks fired, an example is 'update_post_redirect' or 'post_updated_messages'. (See this and this WPSE answers for usage examples).
Note that if you want make use of some hooks argument, that isn't the first, one you have to explicitly declare it in add_action call.
E.g. if you want to use the '$update' argument (that is the 3rd) of the 'save_post' hook you need to add 3 as $accepted_args param on add_action (see docs):
// if you don't add 3 as as 4th argument, this will not work as expected
add_action( 'save_post', 'my_save_post_function', 10, 3 );
function my_save_post_function( $post_ID, $post, $update ) {
$msg = 'Is this un update? ';
$msg .= $update ? 'Yes.' : 'No.';
wp_die( $msg );
}
Last note regard timing: you must be sure that add_action is called before the action is triggered, or it will do nothing.
E.g. this code:
wp_update_post( $post );
add_action( 'save_post', 'my_function', 10, 3 );
will do nothing, because the action is added after the hook is fired. Here is simple to recognize it, in real world code isn't always so.
Related
I have a custom post type called "Booking" in WP travel plugin. I want it to fire an event when i change the status of that custom post type from 'pending' to 'booked'.
The event should send a confirmation email to the user in question.
I tried the following :
function show_alert_msg( $new_status, $old_status, $post ) {
if ( 'Booked' === $new_status && 'pending' !== $old_status && $post->post_type=='Booking' )
{
echo '<script>alert(Show message after transition to booked)</script>' ;
}else{
echo '<script>alert(failed)</script>' ;
}
}
add_action( 'transition_post_status', 'show_alert_msg', 10, 3 );
but whenever i change the status nothing happens.
what i am doing wrong? and how can I approach this correctly so that when the booking status changes from pending to Booked, the confirmation email is sent to the user ?
It's because there are several bugs in your code!
You're using WP travel plugin. This plugin register its custom post type as "itinerary-booking", but in your code, you're checking for a custom post type called "Booking" which doesn't exist, so that condition never returns true!
You could navigate to this path:
"your website folder > wp-content > plugins > wp-travel > inc"
and open up class-post-types.php file on line 126 you see this register_post_type( 'itinerary-booking', $args );
Also, you're using transition_post_status action hook which is used for the checking a post status. The status of pending and booked are custom post meta data and saved into the database under the wp_travel_booking_status name and have nothing to do with the post status itself! Which means it's totally different than what you're trying to do.
So, this filter hook transition_post_status is not responsible to pick up those statuses.
Also, when trying to debug/test your code, specially on transition_post_status and save_post hooks, do NOT use javascript alert, console.log and/or php echo, print_r, var_dump etc. because when you hit those hooks, printing, echoing, alerting won't work. Just use php die function which will stop the app and lets you know that you hit the hook.
Also capitalization matters! Make sure you're using the right capitalization for your values, for example, in this case, everything is lowercase. So keep an eye on that!
Now what can you do about it?
Well, you could change your hook to save_post action hook which means every time that you update your post, it'll fire!
You could change your conditional check to look for itinerary-booking custom post type.
Also you could use get_post_meta function, to check for your status change!
Now putting it all together, you could use the following code:
add_action( 'save_post', 'sending_email_confirmation_to_user');
function sending_email_confirmation_to_user( $post_id )
{
if ( 'itinerary-booking' == get_post_type( $post_id ) ){
$post_status_after_update = get_post_meta( $post_id, 'wp_travel_booking_status', true );
if( 'booked' === $post_status_after_update ){
die("Send your email here!");
} else {
die("your post status is not booked!");
}
}
}
Note:
I used die statement just to give you an example, so make sure to replace die("Send your email here!"); with your custom function that sends out emails!
Status of booked is lowercase, so don't change it to uppercase like the one you tried in your code! Otherwise it won't work!
When your post status is not "booked", you don't have to do anything, i used die("your post status is not booked!"); just to give you an example!
Update
When you use save_post hook, it runs every time you update your custom post data, BUT you do NOT want to send an email every single time. Right?
When you change the status from 'pending' to 'booked' you could save a meta data in the database so that you know you've already sent an email confirmation and you don't want to send another email. You could do that using update_post_meta function.
add_action( 'save_post', 'sending_email_confirmation_to_user');
function sending_email_confirmation_to_user( $post_id )
{
if ( 'itinerary-booking' == get_post_type( $post_id ) ){
$post_email_status = get_post_meta( $post_id, 'custom_confirmation_email', true );
$post_status_after_update = get_post_meta( $post_id, 'wp_travel_booking_status', true );
if( 'booked' === $post_status_after_update && empty( $post_email_status )){
$email_sent = update_post_meta( $post_id, 'custom_confirmation_email', 'sent-at-'. date( 'M_d_Y-H_i_s' ) );
die("Send your email here!");
}
}
}
Note:
This will make sure that you only send your email confirmation once!
If the email confirmation data is empty in the database, it'll send the email and update the value in the database and won't send extra emails.
Also, I've stored a meta data in your database called custom_confirmation_email and used 'sent-at-'. date('M_d_Y-H_i_s') as its value which looks like this: sent-at-Oct_01_2021-17_42_42 which is the date and time when the status changed from 'pending' to 'booked' for the first time.
All of the snippets and explanations have been fully tested and work!
in my site I have 2 differents forms for registration. The difference between them that is when I use the second I update a meta info for a user that normally is blank.
I've added the Facebook SSO and works fine only for the first form.
When I use it for the second it doesn't recognize the origin and register the user as the first one (without update meta info).
I've tried to use the register_user hook
function myplugin_registration_save( $user_id ) {
global $post;
if ($post->ID == 816) {
update_user_meta($user_id, 'user_type', 'couple');
}
}
add_action( 'user_register', 'myplugin_registration_save', 999 );
but this hook doesn't return the post ID.
How can I detect I'm in the second form and launch the update_user_meta function when the post id is 816?
Thanks
function myplugin_registration_save( $user_id ) {
$currentPageId = get_the_ID();
if ($currentPageId == 816) {
update_user_meta($user_id, 'user_type', 'couple');
}
}
add_action( 'user_register', 'myplugin_registration_save', 999 );
Try this one it will surely give you the current page id..
So I have a custom field X that saves it's value naturally upon submitting or updating post. User enters the value of this field.
What I want to do, is after the post is updated, I want to update another custom post meta field called Y automatically with the value of X. So the Y field should be updated without the user knowing it (in the back end), what is the correct hook and function that I need to use?
Hello Here you can use save_post hook which is call wether the post is created or updated.
function my_custom_field_save( $post_id ) {
// do your stuff here....
}
add_action('save_post', 'my_custom_field_save');
More About save_post hook
i hope this will help you.
you can used the save_post action hook to update meta after the triggered whenever a post or page is created or updated
add_action( 'save_post', 'update_custom_value', 10, 3 );
function update_custom_value( $post_id,$post, $update ) {
if ( 'post'== $post->post_type ) {
if ( isset( $_REQUEST['x'] ) ) {
$x= $_REQUEST['x'];
update_post_meta($post_id,'Y', $x);
}
}
}
//Edit For update Y only one time when post is create
add_action( 'save_post', 'update_custom_value', 10, 3 );
function update_custom_value( $post_id,$post, $update ) {
if ( 'post'== $post->post_type ) {
if ( isset( $_REQUEST['x'] ) ) {
$x= $_REQUEST['x'];
if(get_post_meta($post_id,'Y',true)=='')
{
update_post_meta($post_id,'Y', $x);
}
}
}
}
I use Advance Custom Fields plugin to create some custom fields.
While creating new post or update post, I need to use api (vimeo) to take values to other custom field.
Example:
1 field: ID of video
2 field: duration
3 field: plays count
I enter value in first field, press "Publish" and use this hook:
add_action( 'save_post', 'vimeo_api', 10, 2 );
function vimeo_api( $post_id, $post ) {
// request to vimeo with video ID
update_post_meta( $post_id, 'video-duration', $vimeo_single['body']['duration']);
update_post_meta( $post_id, 'video-plays', $vimeo_single['body']['stats']['plays'] );
}
If I hard-code vimeo ID - it works!
But I can't get value from field 1.
For example I can get value of post title like this:
$title = $post->post_type;
But it doesn't works with ACF field.
In developer tools I see this in "headers" tab, form data:
_wpnonce:83ab5bcf5f
_wp_http_referer:/wp-admin/post.php?post=37&action=edit&message=1
user_ID:1
action:editpost
originalaction:editpost
post_author:1
post_type:video
...
fields[field_5423b0bb92209]:
fields[field_5423aff492207]:103222207
fields[field_5423b04192208]:
fields[field_5424dd92c4f3d]:
This return error Warning: Illegal string offset:
$vimeo_id = $post->fields['field_5423aff492207'];
Solved with acf/save_post hook
function get_video_info_from_vimeo ($post_id) {
$vimeo_id = get_field('field_5423aff492207', $post_id); // get id
// use api and get $duration and $plays
// unhook this function so it doesn't loop infinitely
remove_action('acf/save_post', 'get_video_info_from_vimeo');
// update ACF Price Field
update_field( 'field_5423b04192208', $duration, $post_id );
update_field( 'field_5424dd92c4f3d', $plays, $post_id );
// re-hook this function
add_action('acf/save_post', 'get_video_info_from_vimeo');
}
add_action( 'acf/save_post', 'get_video_info_from_vimeo' );
I am developing a plugin for that I have to black list users, so I need to be display one more dropdown item called Black List inside the Bulk Actions dropdown in the Users page, after the Delete option. But I'm unable to see from where these two actions are coming from and also how to black list a particular user.
My idea is to add one more field is_blacklisted in user table as Boolean with default value false and when apply Black List action it changes to true. Any other thoughts?
There's a filter, but it's only useful to remove bulk actions.
From this WPSE question, answer and comments, there's the following workaround: add a custom option to the dropdown with jQuery and hook into admin_action_$your-action to catch the submission.
The hook admin_footer-$current_page is used to print our JavaScript on a specific admin page (adjust to use in other screens).
add_action( 'admin_footer-users.php', 'bulk_footer_so_23541269' );
add_action( 'admin_action_black_list', 'bulk_request_so_23541269' );
function bulk_footer_so_23541269()
{
# global $typenow; if( $typenow != 'page' ) return; // if used on edit.php screen
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('<option>').val('black_list').text('Black list')
.appendTo("select[name='action'], select[name='action2']");
});
</script>
<?php
}
function bulk_request_so_23541269()
{
# Array with the selected User IDs
wp_die( '<pre>' . print_r( $_REQUEST['users'], true ) . '</pre>' );
// $_REQUEST['post'] if used on edit.php screen
}
Your doubt about blocking a user deserves another question, but I'd start a research here first.
Proper support with add_filter( 'bulk_actions-screenid', 'register_my_bulk_actions' ) is arriving in Wordpress 4.7 .
Quoting the announcement post:
To add an option in the Bulk Actions dropdown HTML element, register a callback on the bulk_actions-{screen_id} filter that adds the new option onto the array. Replace {screen_id} with the ID of the admin screen to offer the bulk action on.
To add a bulk action “Email to Eric,” we could use the following code:
add_filter( 'bulk_actions-edit-post', 'register_my_bulk_actions' );
function register_my_bulk_actions($bulk_actions)
{
$bulk_actions['email_to_eric'] = __( 'Email to Eric', 'email_to_eric');
return $bulk_actions;
}
To handle a bulk action form submission, register a callback on the handle_bulk_actions-{screen_id} filter for the corresponding screen. The filter expects the redirect URL to be modified, so be sure to modify the passed $redirect_url. This allows us to carry success or failure state into the next request to display a notice to the user. The other callback arguments will differ depending on the screen here to include contextually relevant data.
To add a bulk action handler for emailing the selected posts, we could use the following code:
add_filter( 'handle_bulk_actions-edit-post', 'my_bulk_action_handler', 10, 3 );
function my_bulk_action_handler( $redirect_to, $doaction, $post_ids )
{
if ( $doaction !== 'email_to_eric' ) {
return $redirect_to;
}
foreach ( $post_ids as $post_id ) {
// Perform action for each post.
}
$redirect_to = add_query_arg( 'bulk_emailed_posts', count( $post_ids ), $redirect_to );
return $redirect_to;
}
Showing notices: We could use the existing notice hooks to let the user know what happened, depending on the state we set in the URL:
add_action( 'admin_notices', 'my_bulk_action_admin_notice' );
function my_bulk_action_admin_notice()
{
if ( ! empty( $_REQUEST['bulk_emailed_posts'] ) ) {
$emailed_count = intval( $_REQUEST['bulk_emailed_posts'] );
printf( '<div id="message" class="updated fade">' .
_n( 'Emailed %s post to Eric.',
'Emailed %s posts to Eric.',
$emailed_count,
'email_to_eric'
) . '</div>', $emailed_count );
}
}