Skip Navigation

[Resolved] Pass post title and post ID to duplicated custom post slug

This thread is resolved. Here is a description of the problem and solution.

Problem: I have a CRED form that allows users to clone a post by clicking the "Submit" button. This works, but I want the post's URL to change. I want the URL to be the same as the original post, but I want to append "-" and the post ID at the end.

Solution: Use the cred_save_data hook to modify the post after it's created. Tweak the slug, update the post, and copy any postmeta over into the duplicated post.

add_action('cred_save_data_22086', 'duplicate_post', 10, 2);
function duplicate_post($post_id, $form_data) {
  // get data of original post
  $post = get_post( $_POST['wpcf-container_id'] );
  $orig_slug = $post->post_name;
  $orig_id = $post->ID;
  $pos = strpos( $orig_slug, '-' . $orig_id);
  if ( $pos > -1 ) {
    // the -ID is part of the slug, so we need to get rid of that
    $orig_slug = substr( $orig_slug, 0, $pos);
  }
  $new_slug = $orig_slug . '-' . $post_id;
  // update the new post ID and slug
  $post->ID = $post_id;
  $post->post_name = $new_slug;
  wp_update_post( $post );
  // get fields of original post
  $fields = get_post_custom( $_POST['wpcf-container_id'] );
  // update the new post with these fields
  foreach ($fields as $key => $values) {
    foreach ($values as $value) {
      add_post_meta($post_id, $key, $value, false);
    }
  }
}

Relevant Documentation:
http://php.net/manual/en/function.strpos.php
http://php.net/manual/en/function.substr.php
https://toolset.com/documentation/programmer-reference/cred-api/#cred_save_data
https://codex.wordpress.org/Function_Reference/get_post
https://developer.wordpress.org/reference/functions/get_post_custom/
https://developer.wordpress.org/reference/functions/wp_update_post/
https://codex.wordpress.org/Function_Reference/add_post_meta

This support ticket is created 7 years, 3 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

Tagged: 

This topic contains 15 replies, has 2 voices.

Last updated by Rita 7 years, 3 months ago.

Assisted by: Christian Cox.

Author
Posts
#556053

Hi there
I have a custom post with cred form to create and edit.
And I have another cred form to duplicate the post (submit button only) with the following code in functions php to both copy original post data across to new post and redirect the user to the cred edit form on submission.

//** DUPLICATE EVENT **//
add_action('cred_save_data_22086', 'duplicate_post', 10, 2);
function duplicate_post($post_id, $form_data) {
// get data of original post
$post = get_post( $form_data['container_id'], ARRAY_A );
// update the new post with this data
$post['ID'] = $post_id;
$post['post_title'] = $post['post_title'];
wp_update_post( $post );
// get fields of original post
$fields = get_post_custom( $form_data['container_id'] );
// update the new post with these fields
foreach ($fields as $key => $values) {
foreach ($values as $value) {
add_post_meta($post_id, $key, $value, false);
}
}
}

//** REDIRECT DUPLICATE POST BUTTON TO CRED EVENT EDIT **//
add_filter('cred_success_redirect_22086', 'custom_redirect_for_form_with_id_11222',10,3);
function custom_redirect_for_form_with_id_11222($url, $post_id, $form_data)
{
//if ($form_data['id']==22086)
return get_permalink( $post_id ) . '?cred-edit-form=22093';
//return $url;
}

This is all good and working fine. However, as time passes and my members keep duplicating their event posts the inevitable occurs and we have slugs like this:

hidden link

What I would like to do is add the new post's ID to the copied post title on the new duplicated custom post.

Example using the above 'event' custom post:

Lets say that the ORIGINAL post's title is: Tango178 Class and Milonga
and its post slug is: /post_type/post_title-post_id
which in this example could be: /event/tango178-class-and-milonga-123456

When the user duplicates the post the new duplicated post's title is the same: Tango178 Class and Milonga
and its post slug is the same: /post_type/post_title-post_id
which in this example could be: /event/tango178-class-and-milonga-890876

This way every event post slug is unique and we avoid the long string of wordpress duplicated post versions.

Do you think this is possible?
If so how would I change the code above to make this happen?
Any advice would be great with thanks!

Rita

PS: This idea doesn't work... https://toolset.com/forums/topic/use-post-id-in-permalink-of-custom-post-type/

#556186

I think that idea you linked to is a good start, but it needs to be applied to your case a bit differently. You should modify this bit of code in your cred_save_data hook:

$post['post_title'] = $post['post_title'];

What you need to do here is to capture the old post title, then manipulate it in a way that removes the "-[postid]" at the end of the string if it exists (it won't for the original post). Then add "-[newpost id]" at the end of the string. Does this sound like a good plan to you, or am I overlooking something?

#556204

Yes, this is exactly what I had in mind. Do you think its a good idea? Am open to suggestions but this is the only way I can think of to easily resolve the issue...
So then... how to make that happen in the code?

I figured out that its this line that needs to change, like you said:
$post['post_title'] = $post['post_title'];

But I just don't know php enough to know what to do. Have googled pretty much most of the day 🙂

We should use 'if'?

#556220

Ok sure, I'll go step by step.

1. We need to store the original post title and ID in temporary variables:

$orig_title = $post->post_title;
$orig_id = $post->ID;

2. We need to check the old post title to see if the old post ID is included, and if so, we need to know the position of the ID string in relation to the beginning of the title. We can use strpos for this:

$pos = strpos( $orig_title, '-' . $orig_id);

3. We can test that position to determine whether or not we should remove an ID string, and use substr to do that if necessary:

if ( $pos > -1 ) {
  // the -ID is part of the title, so we need to get rid of that
  $orig_title = substr( $orig_title, 0, $pos);
}

4. Add the new post ID string to the original title and save it in a temporary variable:

$new_title = $orig_title . '-' . $post_id;

5. Finally set the new post title with this variable:

$post->post_title = $new_title;

The complete code is:

add_action('cred_save_data_22086', 'duplicate_post', 10, 2);
function duplicate_post($post_id, $form_data) {
  // get data of original post
  $post = get_post( $form_data['container_id'], ARRAY_A );
  $orig_title = $post->post_title;
  $orig_id = $post->ID;
  $pos = strpos( $orig_title, '-' . $orig_id);
  if ( $pos > -1 ) {
    // the -ID is part of the title, so we need to get rid of that
    $orig_title = substr( $orig_title, 0, $pos);
  }
  $new_title = $orig_title . '-' . $post_id;
  // update the new post ID and title
  $post->ID = $post_id;
  $post->post_title = $new_title;
  wp_update_post( $post );
  // get fields of original post
  $fields = get_post_custom( $form_data['container_id'] );
  // update the new post with these fields
  foreach ($fields as $key => $values) {
    foreach ($values as $value) {
      add_post_meta($post_id, $key, $value, false);
    }
  }
}

Please try this and let me know the results.

#557110

Hi Christian
Sorry for the delay.
I tried this code quickly and it doesn't work. Will try again and test properly this morning and come back to you.
Rita

#557260

Okay I understand, let me know if you have any luck later or we can try to figure out what's going wrong.

#558425

Hi Christian

Ok, I have tested properly now. The new 'copied' post displays all custom field data except for the Title, Description and Category fields.

Category and Description are simply blank, no data. And the title given to the copyied event is like this: CRED Auto Draft c7167fed23cec465814d1f778b718151

Does this give any clues?

#558633

Okay I believe I see the problem, the original post isn't being set correctly. Your form is a "new post" form, correct? And you have a field in the form called "container_id", which contains the ID of the post you want to duplicate? If that's right, please try this code instead:

add_action('cred_save_data_22086', 'duplicate_post', 10, 2);
function duplicate_post($post_id, $form_data) {
  // get data of original post
  $post = get_post( $_POST['container_id'] );
  $orig_title = $post->post_title;
  $orig_id = $post->ID;
  $pos = strpos( $orig_title, '-' . $orig_id);
  if ( $pos > -1 ) {
    // the -ID is part of the title, so we need to get rid of that
    $orig_title = substr( $orig_title, 0, $pos);
  }
  $new_title = $orig_title . '-' . $post_id;
  // update the new post ID and title
  $post->ID = $post_id;
  $post->post_title = $new_title;
  wp_update_post( $post );
  // get fields of original post
  $fields = get_post_custom( $_POST['container_id'] );
  // update the new post with these fields
  foreach ($fields as $key => $values) {
    foreach ($values as $value) {
      add_post_meta($post_id, $key, $value, false);
    }
  }
}

If this isn't working, I'll probably need to access your wp-admin area to see what's going wrong. Please provide login credentials for me in the private reply fields enabled here.

#558749

Hi Christian

Yes, thats right. The cred form is a 'new post' form.
I did not have the post ID field however... So I

1. inserted a new custom field called 'container_id' in the duplicate event cred form
2. double checked it was picking up the corred id of the original post - yes it does
3. inserted the above you code in functions.php

and tested again.

Now, the website thinks that a new post has been created - I know this because various website notifications are triggered, however, there is no new post.

We still get the new title like this (this flashes up on one of the notifications): CRED Auto Draft c7167fed23cec465814d1f778b718151

and the user is now redirected to a 404 with slug format similar to this if helpful:

hidden link

Really sorry but I can't figure out what is amiss... have tested quite a few ideas with the code and my forms etc

So yes please, would you mind to open a private channel with your reply and I will give you admin access credentials to come in and take a look.

Thanks much in advance Christian

#558760

Private reply fields are enabled here. If I need to run tests, I will create a clone of your site using the Duplicator plugin so I can test locally without modifying anything on your site.

#558788

I'm not able to see a copy button, but I think I see the issue anyway. Edit your CRED form ID 22086, and look at the container_id field. Your input value is set to '[wpv-post-id]', which is most likely the problem. In this case, you need to reference the current page in order to get the proper ID. Otherwise, wpv-post-id will refer to the ID of the CRED form itself. So change that to:

[cred_field field='container_id' post='event' value='[wpv-post-id id='$current_page']' urlparam='']

Please try this modification and let me know the results.

#558791

Hi 🙂

I updated the shortcode with the current page selector but there is no change to the results...

Sorry you should have access now. The buttons were only visible to specified users so I have added you to the conditional. You will see them at the top of the post.

The 'Copy to New Draft' at top right.

#559314

Please check now. I see that we were trying to access the container_id field incorrectly. The updated code is here:

add_action('cred_save_data_22086', 'duplicate_post', 10, 2);
function duplicate_post($post_id, $form_data) {
  // get data of original post
  $post = get_post( $_POST['wpcf-container_id'] );
  $orig_title = $post->post_title;
  $orig_id = $post->ID;
  $pos = strpos( $orig_title, '-' . $orig_id);
  if ( $pos > -1 ) {
    // the -ID is part of the title, so we need to get rid of that
    $orig_title = substr( $orig_title, 0, $pos);
  }
  $new_title = $orig_title . '-' . $post_id;
  // update the new post ID and title
  $post->ID = $post_id;
  $post->post_title = $new_title;
  wp_update_post( $post );
  // get fields of original post
  $fields = get_post_custom( $_POST['wpcf-container_id'] );
  // update the new post with these fields
  foreach ($fields as $key => $values) {
    foreach ($values as $value) {
      add_post_meta($post_id, $key, $value, false);
    }
  }
}

I created one duplicate post and was redirected to the proper edit form. Can you confirm?

#560219

Hi Christian

Yes, this code works nicely now - thank you for your persistence! (I would love to learn this coding language...)

But... it isn't what I was thinking of as per my initial message above. Sorry!

The title on the new post displays the post ID but the URL is still displaying the version and if that user keeps copying that post it will still end up looking like this:

hidden link

Which is what we are trying to prevent. 🙂

What I was thinking in the beginning is to only replace the version numbers in the URL with the new post's ID. Not the title. So the new 'copied' post would look like this (34419 being the post's id):

URL - hidden link
TITLE DISPLAYED ON POST - Tango178 Class and Milonga

and if the user copied his event again the new copied post would like this this:

URL - hidden link
TITLE DISPLAYED ON POST - Tango178 Class and Milonga

and so on...

What do you think? Maybe there is another solution that works better... Am absolutely open to suggestions!

R

#560430

Okay sure, a few minor changes can fix this up. Use the following code instead:

add_action('cred_save_data_22086', 'duplicate_post', 10, 2);
function duplicate_post($post_id, $form_data) {
  // get data of original post
  $post = get_post( $_POST['wpcf-container_id'] );
  $orig_slug = $post->post_name;
  $orig_id = $post->ID;
  $pos = strpos( $orig_slug, '-' . $orig_id);
  if ( $pos > -1 ) {
    // the -ID is part of the slug, so we need to get rid of that
    $orig_slug = substr( $orig_slug, 0, $pos);
  }
  $new_slug = $orig_slug . '-' . $post_id;
  // update the new post ID and slug
  $post->ID = $post_id;
  $post->post_name = $new_slug;
  wp_update_post( $post );
  // get fields of original post
  $fields = get_post_custom( $_POST['wpcf-container_id'] );
  // update the new post with these fields
  foreach ($fields as $key => $values) {
    foreach ($values as $value) {
      add_post_meta($post_id, $key, $value, false);
    }
  }
}

Try this and let me know how it works.