Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Merging post data from post ID on edit screen WordPress

  • SOLVED

I have a political website which displays candidates and their responses to a survey. Candidate records are initially stored in a CPT called people, and need to exist from the moment the survey is sent out. At the same time, they may then complete survey results which need to be approved/verified before the results show publicly.

To that end I’ve setup a front end form which fires insert_post to create a new entry in a “temporary” CPT called pending.

What I’m looking to do now is as follows:
- create a new meta box (easy) with a button to “merge”
- this button would need to run a function which copies all the newly collected data (survey response meta field values, featured image) to the original “person” post for the candidate.
- the post ID I need to merge into is also available as a custom field called “sourcepost”
- ideally once this merge process has happened, the “response” post will now move directly to the trash since the responses have been approved and merged into the real record.

While I know this probably relies on update_post to do the heavy lifting, my Ajax skills are not great so I’m unsure what the best way to package all this up and fire the action from a post edit screen (as well as how to post all the changes from the currently view post.

Answers (4)

2020-06-09

Arnav Joy answers:

Hello Andrew,
Cam you please show me these live in action somewhere?
I mean if you can share url etc.

Also please share code that you are using so far.

2020-06-09

Andrea P answers:

I would suggest adding a button to the "pending" cpt, with an AJAX call to run the "merge" logic.
Then I would avoid auto-bin, because when the ajax comes back successful you can double check the "person" post and manually bin the "pending" post you just merged. it's safer and it's an easy flow.

this good tutorial explains step by step how to make a mini plugin which adds a button connected to an ajax call:
https://www.sitepoint.com/how-to-use-ajax-in-wordpress-a-real-world-example/

the tutorial basic structure is basically the same as what you need. with these differences:

1- the tutorial adds the button to the frontend content, you need it in backend. so instead of using these 2 hooks
add_filter( 'the_excerpt', array( $this, 'rml_button' ) );
add_filter( 'the_content', array( $this, 'rml_button' ) );

you should add the button to this hook:
add_action( 'post_submitbox_misc_actions', array( $this, 'rml_button' ) );

2- then you also have to load the scripts to the admin. And you don't need to load any styles for your purpose. So at the beginning, remove the register/enqueue related to the styles and then modify this hook:
add_action( ‘plugins_loaded’, array( $this, 'enqueue_rml_scripts' ) );
so that it's like this:
add_action( ‘admin_enqueue_scripts’, array( $this, 'enqueue_rml_scripts' ) );
and you could also just put the register_scripts() and wp_enqueue_scripts() in the same function enqueue_rml_scripts() so you can tidy up a bit those things

3- also modify the function for printing the button so that it adds the source post id as well as the current post
public function rml_button( $post ) {

if( get_post_type() == 'pending' ) {
echo '<div id="merging-actions"><a href="#" class="rml_bttn" data-id="' . $post->ID. '" data-source="'. get_post_meta($post->ID, 'sourcepost') .'">Merge</a></div>';
}
}



4- modify the js so that it pulls the ids from the button and pass them to ajax. (and also change the ajax action name to something that makes more sense for you)
jQuery(document).ready( function(){
jQuery('#submitdiv').on('click', 'a.rml_bttn', function(e) {
e.preventDefault();
var post_id = jQuery(this).data( 'id' );
var source_id = jQuery(this).data( 'source' );
jQuery.ajax({
url : readmelater_ajax.ajax_url,
type : 'post',
data : {
action : 'merge_survey_to_person',
post_id : post_id,
source_id : source_id
},
success : function( response ) {
jQuery('.rml_contents').html(response);
}
});
jQuery(this).hide();
});
});


5- modify the php action hook entirely. Here is where your plugin will be completely different, but it's basically just one function.
first modify the action name and the function name rather than using "read_me_later":
// Setup Ajax action hook
add_action( 'wp_ajax_merge_survey_to_person', array( $this, 'merge_survey_to_person' ) );

then modify the function read_me_later so that it looks something like this:
public function merge_survey_to_person() {
// get values from the data posted by ajax
$post_id = $_POST['post_id'];
$source_id = $_POST['source_id'];
$source = get_post($source_id);

if (!$source) {
echo "could not find the associated person";
die();
}

// retrieve all your metafields from the "pending" survey post like this
$answer_1 = get_post_meta($post_id, 'answer_1');

// add same metafield to the source post
update_post_meta($source_id, 'answer_1', $answer_1);

// print some success message
echo '<div>Survey successfully merged to Person ID '. $source_id .'</div>';

die();
}


6- Skip the part related to the widget

7- Please do follow the instruction at the end of the tutorial, regarding how to make the ajax call more secure and check nonce referrer etc... And go back and modify my sample code accordingly.


I would suggest to change the naming of functions so that they make sense for you and they don't have the rml_ prefix. I haven't changed them in most of my sample code so that you can easily refer to the tutorial.

Then I think the tutorial is missing a bit where it tells how to actually run-up the logic, because I haven't seen anything that fire the run() method.
In order to do so, you should add something like this at the bottom of your plugin file, after the main class is closed:
(assuming you changed the name of the class from ReadMeLater to MergeSurveyToPerson )

$my_plugin = new MergeSurveyToPerson();
$my_plugin->run();


Andrea P comments:

I edited the answer because in my samples in point 5 I changed the name of the read_me_later action and function in the hook, but then forgot to change the name of the actual function below as well


Andrew Clemente comments:

Thank you! Will give this a go tomorrow

2020-06-09

Bob answers:

can you please provide code you already have and share few screenshots how it's working right now.

It will be great if you can share login details to in personal message to check everything.

2020-06-09

Sébastien Méric answers:

Hi,

Why don't you use the "pending status" on the original people post type when you first create it ?

That way, the new entry would be immediately a people post type that may be reviewed and validated or rejected from the back-end by any editor with the right to do so :)


Andrew Clemente comments:

As I mentioned above, the original posts needs to be published initially. This is because some people may never respond to the questionnaire, but we still need to show the rest of their candidate information. So that post must already exist/be published, and it's only the changes/custom fields additions which need a place to be reviewed/verified before being added back to the live post.