WordPress "save_post" call only on save post not on update - php

I am trying to send post data to third-party services when the post is saved via API. I am using hook add_action( 'save_post', [$this, 'save_post_callback'], 100, 3); but this hook seems to be called in update post as well as post-new.php in admin panel. So to get rid of running this hook in post-new.php, I have checked the $_POST request but I am not able to filter the update post since I want to call API only in save the post, not in an update.
There seems to be the third parameter in callback function $update but it's not working either. Below is my code that needs to be called only in save a post but it's not working. Any help would be greatly appreciated.
function save_post_callback( $post_id, $post, $update ) {
// (!$update) => this doesnot seems to work
if(!empty($_POST) && $post->post_type == "post"){
//run only when save post
}
}

simple way is to check if _wp_http_referer last part is post-new.php or not.
here is a simple code
function save_post_callback($post_id, $post, $update)
{
// (!$update) => this doesnot seems to work
if ( ! empty($_POST) && $post->post_type == "post" ){
$end = explode('/', $_POST[ '_wp_http_referer' ]);
$end = end($end);
if($end == 'post-new.php'){
//echo 'it is new post';exit();
//do what you want here.
}
}
}

From StackExchange here. It looks like a clever way is to compare the post_date & post_modified to determine it is a new post.
$is_new = $post->post_date === $post->post_modified;
if ( $is_new ) {
// first publish
}

Related

Show message after new post is published (WordPress)

When publishing a new post in WordPress I want to show an extra admin_notice to show a custom message. I'm using the admin_notices hooks for this. I tested this and it works. What doesn't work is to show it when the post is published.
I tried a couple of methods including the ' publish_post' hook. The hook is firing, when I put a var_dump('bla');exit(); I can see this working. I think the reason the admin_notices doesn't show is because the page is refreshing. So if there would be something like 'after_publish_post' that'd be great but I cannot find it.
I also tried something I've found in a similar question:
if( ( $_POST['post_status'] == 'publish' ) && ( $_POST['original_post_status'] != 'publish' ) ) { echo "New post!"; exit();}
This also has no effect
--
What I have at this moment is:
add_action('publish_post', array($this,'onInsertPost')); //does work, function gets triggered
public function onInsertPost($post_id, $post, $update) {
add_action( 'admin_notices', array($this, 'info_text_news') );
}
public function info_text_news() {
$class = 'notice notice-info';
$message = __( 'My message', 'admin_notice' );
printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), $message);
}
Like I earlier said, all this code is working but togheter the notice is not showing up. I think because of the refreshing page after pressing the publish button.
I've found a solution to do this. I'm checking the post date and comparing it to the date of today. If the post is posted today it triggers the hook. In my case, one day is fine. If you need to only show it after post you can adjust it to checking the time also.
global $pagenow;
if ( $pagenow == 'post.php' ) {
$currentPost = get_post( $_GET['post'] );
$postdate = substr($currentPost->post_date, 0 , 10);
//if post type is post and post is published today show info message
if($currentPost->post_type == 'post' && $postdate == date('Y-m-d')) {
add_action( 'admin_notices', array($this, 'info_text_news') );
}
}

Having trouble adding validation errors to ACF form

I'm using ACF with WordPress and I have a form that I am trying to add a validation error to, but it doesn't appear to be working (I think I know why)...
My code:
function my_acf_update_value( $value, $post_id, $field ) {
// Get the users numerical user id
$user_id = str_replace('user_', '', $post_id);
$value = sanitize_text_field($value);
/** #noinspection PhpParamsInspection */
$user_data = wp_update_user(array('ID' => $user_id, 'user_email' => $value ) );
if ( is_wp_error( $user_data ) ) {
$wp_error = $user_data->get_error_message();
$input = $field['prefix'] . '[' . $field['key'] . ']';
acf_add_validation_error($input, $wp_error);
}
return $value;
}
add_filter('acf/update_value/key=field_5c121023e119f', 'my_acf_update_value', 10, 3);
As you may be able to tell I am attempting to update the users email address field (default WP one) based off the email provided by a user in an email field on a frontend ACF Form.
I then check to see if the update caused any errors and obviously if it did I want to add to the ACF validation errors, but it passers through successfully.
I assume this is because the update function runs AFTER the validation and this is why it isn't working?
Because of this I thought about doing the update in the validation function such as:
function my_acf_validate_value( $valid, $value, $field, $input ){
// bail early if value is already invalid
if( !$valid ) {
return $valid;
}
// Some code...
// Return error here?
return $valid;
}
add_filter('acf/validate_value/key=field_5c121023e119f', 'my_acf_validate_value', 10, 4);
...but I don't seem to have access to the $post_id here, nor does this seem like the best way to handle it?
Is there a way to handle this better?
You can use var_dump to see what data you have within the function - either in one of the existing function attributes, or by using get_the_ID() or global $post; to access the current Post object. Beware when trying to manipulate the Post object here, though.

How to get current post type in functions.php in order to use globally?

I want to check the post type of any pages or posts and display some features depending on the post type. So I'm using a function in functions.php which returns the post type when used in admin pages but not on theme pages.
I need this function to include a php file if the post type is page. So it must work system wide (if it's possible). In templates, admin, edit and post pages.
Here is the function that I'm using:
function vart_current_post_type() {
global $post, $typenow, $current_screen;
if ( $post && $post->post_type ) {
return $post->post_type;
}
elseif ( isset( $_GET[ 'post' ] ) ) {
return get_post_type( $_GET[ 'post' ] );
}
elseif ( $typenow ) {
return $typenow;
}
elseif ( $current_screen && $current_screen->post_type ) {
return $current_screen->post_type;
}
elseif ( isset( $_REQUEST[ 'post_type' ] ) ) {
return sanitize_key( $_REQUEST[ 'post_type' ] );
}
return null;
}
add_action( 'init', 'vart_current_post_type' );
Please tell me what should I do in order to make it work on theme templates and pages?
Thanks.
There's a native method to find out current post type: https://developer.wordpress.org/reference/functions/get_post_type/
$post_type = get_post_type();
On the init hook, the $post object is not yet populated.
See this for WP hook (action) execution. As you can see, posts are selected much later after init. To be more precise, even the request is parsed after init hook. So there is no easy way to get post type in init action, I'm afraid.
With the wp hook you can get the post type with your function.

Wordpress: Access to post from wp_headers

I'm trying to set a new http Header for my wordpress installation but I'm not able to work with $post object inside my new wp_headers filter function. I want to send different headers for diferent post types and use Go(lang) for caching stuff (home project).
function add_new_header($headers) {
$headers['PostId'] = get_the_ID();
return $headers;
}
add_filter('wp_headers', 'add_new_header');
Seems Like I can't access to Post / get_queried_object_id() in the hook as it's not started.
So, referencing post attributes, you have to do in the "template_redirect" hook. As in that moment the Post exists...
add_action('template_redirect', 'add_new_header');
function add_new_header($headers) {
$post_id = get_queried_object_id();
if( $post_id ) {
header("PostId: " . $post_id) ;
}
}
Hope helps to someone.. someday...

Contact form 7 to custom post type

I would like to process a contact form from contact form 7 into a custom post type.
Currently, this is what I have:
<?php
if ( 'POST' == $_SERVER['REQUEST_METHOD'] && !empty( $_POST['action'] ) && $_POST['action'] == "front_post") {
//store our post vars into variables for later use
//now would be a good time to run some basic error checking/validation
//to ensure that data for these values have been set
$title = $_POST['title'];
$content = $_POST['content'];
$Interest = $_POST['Interest'];
$post_type = 'purchase';
//the array of arguements to be inserted with wp_insert_post
$new_post = array(
'post_title' => $title,
'post_content' => $content,
'tags_input' => $tags,
'posted_data' => $Interest,
'post_status' => 'publish',
'post_category' => array('0',$_POST['cat']),
'post_type' => $post_type
);
//insert the the post into database by passing $new_post to wp_insert_post
//store our post ID in a variable $pid
//we now use $pid (post id) to help add out post meta data
$pid=wp_insert_post($new_post);
//we now use $pid (post id) to help add out post meta data
add_post_meta($pid, 'cust_key', $custom_field);
}
?>
Here is a link to the actual form: http://stage.icardpromotions.com/create-purchase-order/
I need to be able to pull in all of the info form this form into the custom post type "purchase"
As you can see, I am currently pulling in the post_content, post_title, etc.
I have also tried to pull in content from content form by input name "Interest" but it dose not work.
Does anyone have a clue how to do this?
function save_posted_data( $posted_data ) {
$args = array(
'post_type' => 'post',
'post_status'=>'draft',
'post_title'=>$posted_data['your-name'],
'post_content'=>$posted_data['your-message'],
);
$post_id = wp_insert_post($args);
if(!is_wp_error($post_id)){
if( isset($posted_data['your-name']) ){
update_post_meta($post_id, 'your-name', $posted_data['your-name']);
}
// if( isset($posted_data['your-email']) ){
// update_post_meta($post_id, 'your-email', $posted_data['your-email']);
// }
// if( isset($posted_data['your-subject']) ){
// update_post_meta($post_id, 'your-subject', $posted_data['your-subject']);
// }
if( isset($posted_data['your-message']) ){
update_post_meta($post_id, 'your-message', $posted_data['your-message']);
}
//and so on ...
return $posted_data;
}
}
add_filter( 'wpcf7_posted_data', 'save_posted_data' );
-------------------- Explaining It-------------------------
First make function and add a hook wpcf7_posted_data to it
---first step---
function save_posted_data( $posted_data ) {
}
add_filter( 'wpcf7_posted_data', 'save_posted_data' );
---second step---
and now u need to add some arguments to the post that needs to be populated using wp_insert_post();
$args = array(
'post_type' => 'post',
'post_status'=>'draft',
'post_title'=>$posted_data['your-name'],
'post_content'=>$posted_data['your-message'],
);
$post_id = wp_insert_post($args);
---third step---
check if that populated items is error or not
if(!is_wp_error($post_id)){ //do ur stuffs }
---fourth step---
now checking isset the field or not and updating the metas
eg post
if( isset($posted_data['your-name']) ){
update_post_meta($post_id, 'your-name', $posted_data['your-name']);
}
and in last return the value
return $posted_data;
Full code is above.
here is a quick tip as to how to go about achieving the above using your own code, first register your custom post
add_action('init', 'my_custom_post');
function (){
$args = array(
/*post type registration parameters*/
);
register_post_type( 'my_custom_post', $args );
}
next, you want to capture your posted data and create a new post
add_filter( 'wpcf7_posted_data', 'save_posted_data' );
function save_posted_data( $posted_data ) {
$args = array(
'post_type' => 'my_custom_post',
/*other default parameters you want to set*/
);
$post_id = wp_insert_post($args);
if(!is_wp_error($post_id)){
if( isset($posted_data['form-field-name']) ){
update_post_meta($post_id, 'form-field-name', $posted_data['form-field-name']);
}
//and so on ...
return $posted_data;
}
While the answer with the most upvotes in this thread works it has some flaws.
First of which is: you can still submit the form and thus create a post in wordpress if for instance you remove "disabled" tag from your submit button. So you can essentially bypass the validation.
Second problem that I had, was probably specific to my usecase, since this function triggers on any cf7 form submission on website. If you have more than one cf7 form this will create posts even if users submit something in some totally different form.
To solve the first problem I think the best way is to hook custom function to "wpcf7_before_send_mail" instead of "wpcf7_posted_data"
And to solve the second problem is to check for id of the form you wish to trigger the effect on.
This is how I solved these problems:
function save_cf7_data_to_cpt( $contact_form ) {
if( $contact_form->id() !== $my_form_id )
return; //dont run the rest if it is not the form you want it to be, $my_form_id we look up in admin or shortcode...
$submission = WPCF7_Submission::get_instance();
if ( $submission ) {
$posted_data = $submission->get_posted_data();
} //we get to $post_data in this way since it is not provided like in the wpcf7_posted_data approach
$args = array(
'post_type' => 'testemonial',
'post_status'=>'draft',
'post_title'=>$posted_data['your-name'],
'post_content'=>$posted_data['your-message'],
);
$post_id = wp_insert_post($args);
if(!is_wp_error($post_id)){
if( isset($posted_data['your-name']) ){
update_post_meta($post_id, 'your-name', $posted_data['your-name']);
}
if( isset($posted_data['your-message']) ){
update_post_meta($post_id, 'your-message', $posted_data['your-message']);
}
//and so on ...
return $posted_data;
}
}
add_filter( 'wpcf7_before_send_mail', 'save_cf7_data_to_cpt' ); //hook into wpcf7_before_send_mail to ensure validation is ok
Can u also use
add_action('wpcf7_mail_sent','save_my_form_data_to_my_cpt');
add_action('wpcf7_mail_failed','save_my_form_data_to_my_cpt');
function save_my_form_data_to_my_cpt($contact_form){
$submission = WPCF7_Submission::get_instance();
if (!$submission){
return;
}
$posted_data = $submission->get_posted_data();
//The Sent Fields are now in an array
//Let's say you got 4 Fields in your Contact Form
//my-email, my-name, my-subject and my-message
//you can now access them with $posted_data['my-email']
//Do whatever you want like:
$new_post = array();
if(isset($posted_data['your-name']) && !empty($posted_data['your-name'])){
$new_post['post_title'] = $posted_data['your-name'];
} else {
$new_post['post_title'] = 'Message';
}
$new_post['post_type'] = 'inquiry'; //insert here your CPT
if(isset($posted_data['tel-901'])){
$new_post['post_content'] = $posted_data['tel-901'];
} else {
$new_post['post_content'] = 'No Message was submitted';
}
$new_post['post_status'] = 'publish';
//you can also build your post_content from all of the fields of the form, or you can save them into some meta fields
if(isset($posted_data['your-email']) && !empty($posted_data['your-email'])){
$new_post['meta_input']['sender_email_address'] = $posted_data['your-email'];
}
if(isset($posted_data['checkbox-674']) && !empty($posted_data['checkbox-674'])){
//$new_post['meta_input']['sender_name'] = $posted_data['checkbox-674'];
$ChildSeat=$posted_data['checkbox-674'];
$Child_Seat='';
for($a=0;$a<count($ChildSeat);$a++)
{
$data['checkbox-674']=$_POST['checkbox-674'][$a];
$Child_Seat.=$data['checkbox-674'].'<br>';
$new_post['post_content'] = $Child_Seat;
}
}
//When everything is prepared, insert the post into your Wordpress Database
if($post_id = wp_insert_post($new_post)){
//Everything worked, you can stop here or do whatever
} else {
//The post was not inserted correctly, do something (or don't ;) )
}
return;
}
there is a plugin to do this, Post My CF7 Form.
The plugin allows you to map a CF7 form and its fields to a an existing post type or a new custom post type.
The mapping process is done using an interactive UI admin page which gives you the option to map your fields to post fields (title, content, excerpt, slug, author) as well as post meta-fields.
In addition, the plugin also introduces a save submit button to allow users to save a draft version of the form, this is especially useful for large complex forms.
The plugin can automatically load taxonomy terms in select/checkbox/radio fields that have been mapped to that taxonomy, thus enabling created posts to be automatically assigned to users selected terms.
The plugin has multiple hooks & filters to customise the process flow.

Categories