Skip Navigation

[Resolved] Duplicate post with relationships

This support ticket is created 4 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
- 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 -
- 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 -

Supporter timezone: Europe/London (GMT+00:00)

This topic contains 9 replies, has 2 voices.

Last updated by caseyL 4 years, 2 months ago.

Assisted by: Nigel.

Author
Posts
#1839389

I used to be able to clone posts from a custom post type and the relationships would carry over, using Yoast Duplicate Post. With the change to Types 3.0, cloning this way no longer works. I see there was a post from 2018 asking this question: https://toolset.com/forums/topic/duplicate-post-plugin-cant-clone-parent-post-association/

I'm wondering if there is an easy way to do this now (e.g., a plugin that is known to work to clone posts and their relationships). If not, do you have a suggestion for how to accomplish this? It seems like this would be a generally useful feature. (For our site, we have a college course database, so every semester we need to create approximately 50 new posts based on old ones.)

Thanks!

#1839611

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

The post duplication plugins just duplicate the standard and custom fields of a post, they wouldn't know about data stored in custom tables relating to the post that needed duplication, too.

To carry over relationships to the duplicated posts you would need to use custom code. This comes up from time to time, so let me help you with that.

Can I get some details of your post types and how they are related to get started?

#1840077
relationships.png

Thanks, Nigel!

Tiny bit of background: This is a site for our university department that provides students with a searchable database of our course offerings each term (semester). It was started before Types 3.0, but more recently updated/migrated. The key search page is hidden link (By the way, Toolset was the perfect solution for this, so thank you!)

The relevant custom post types are Courses, Instructors, Academic Terms, and Offerings. The relevant relationships are:

  • Courses Offerings: one Course to many Offerings
  • Offerings Instructors: many Offerings to many Instructors (via intermediary post type offering-instructor)
  • Academic Terms Offerings: one Academic Term to many Offerings

I've attached a screenshot of the Relationships page in case that's better.

In advance of each semester we need to roll over the Offerings from the same semester the previous year (e.g., Spring 2020 to Spring 2021), and then edit them to change the Academic Term and to change the Instructors if applicable. Please let me know if you need more information.

Thanks again,
Mark

#1841233

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

Thanks for that Mark.

I'll try and work on a solution as soon as possible, but we have a couple of unanticipated absences at the moment and are consequently very busy. I'll keep this in my queue and return to it as soon as I have a few spare moments.

#1846239

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

I'm just about caught up with other issues as the team returns to normal, and I'll have a crack at this tomorrow.

#1846291

Thanks, Nigel!

#1847571

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

Hi Mark

It's a bit more involved than I expected, partly because on our own side we don't have an API to get all of the relationships without knowing the slugs of them beforehand etc.

So I got a concrete example working on my test site, working with repeatable field groups (which are stored in child posts, and not duplicated by the duplicate post plugin), but where I manually provided the slug of the RFG.

I'd like to come up with a generic solution but that might take some time, so can I ask you for the specifics from your site, which will shortcut the solution I can provide.

I need to know the slugs of any relationships you want this to work with (or the slugs of any repeatable field groups belonging to posts that will be duplicated).

In principle there could be the following use cases, and I'd like you to confirm which would apply.

RFGs (as mentioned).
One-to-many relationships where you copy the parent and want to duplicate all of its child posts and assign these duplicates to the new parent.
One-to-many relationships where you copy a child post and you want the copy to be assigned to the same existing parent.
Many-to-many relationship without intermediate posts where you duplicate a post and you want to duplicate all of its related posts and replicate the same relationships. Or would you intend to duplicate a post and just establish connections to the same existing related posts without also duplicating those?
Many-to-many relationship with intermediate posts, as above, but where relationship fields (stored on the intermediate post) should also be copied.

#1848021

Thanks, Nigel. Here is the information:

The relationship slugs are:

  • course-offering ["Courses Offerings", one Course to many Offerings]
  • semester-offering ["Academic Terms Offerings", one Academic Term to many Offerings]
  • offering-instructor ["Offerings Instructors", many Offerings to many Instructors; this relationship has an intermediary post but no custom fields attached to it]

There are no RFGs.

The simplest use case is to duplicate an Offering post and just establish connections to the same existing related posts (Courses and Instructors) without duplicating them. The relevant relationships are:

  • course-offering [one-to-many, so newly duplicated Offering would need to be assigned to same parent Course]
  • offering-instructor [many-to-many, so newly duplicated Offering would need to be assigned to all Instructors associated with the original Offering]

This duplication ignores the Academic Term (semester) but we can manually create a new one and manually connect all the newly duplicated Offerings to this new Academic Term. (The current "Connect existing Offering" button in the WordPress admin only does one at a time and so is a bit tedious. It would be very convenient, but not essential, to be able to select multiple Offerings to connect at once.)

A more complicated use case, if you want to tackle it, would be to duplicate an Academic Term and thereby to duplicate all of its child Offerings and to establish connections for each of these new Offerings as above to the Courses and Instructors as well as to the new Academic Term.

Please let me know if I missed anything you need. Thanks again!

#1850911

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

Hi Mark

Your first use case is straightforward enough, because you just want to connect the duplicated offerings to the same courses and instructors as before.

Here's some code that will do that (you can add it at Toolset > Settings > Custom Code):

/**
 * Hook into duplicate post plugin to make connections after duplicating a post
 * 
 * @param int $new_post_id The newly created post's ID.
 * @param WP_Post $post The original post's object.
 * @param string $status The destination status as set by the calling method: e.g. 'draft' if the function has been called using the "New Draft" links. Empty otherwise.
 * 
 */
function ts_custom_duplicate_post( $new_post_id, $post, $status ) {

    if ( $post->post_type === 'offering' ) {
        /** 
         * When duplicating an offering post connect duplicate to the same parent course 
         **/

        // get the parent course
        $course_id = toolset_get_related_post( $post, 'course-offering' );

        // now assign the duplicated offering to the same course
        if ( $course_id != 0 ){
            toolset_connect_posts( 'course-offering', $course_id, $new_post_id );
        }

        /**
         * When duplicating an offering post connect to the same existing instructors
         */

        // get the connected instructors
        $instructor_ids = toolset_get_related_posts( $post, 'offering-instructor', array(
            'query_by_role'     => 'parent',
            'role_to_return'    => 'child'
        ) );
        
        // connect these instructors to the new offering
        if ( isset( $instructor_ids ) && ( is_array( $instructor_ids ) ) ){

            foreach ($instructor_ids as $key => $instructor_id) {
                
                toolset_connect_posts( 'offering-instructor', $new_post_id, $instructor_id );
            }       
        }
    }
}
add_action( 'dp_duplicate_post', 'ts_custom_duplicate_post', 10, 3 );

I don't have a solution for you for the more complex use case, because it's not a single step, you want to clone a post then find the posts connected to it and clone them and then establish the relationships for all of these copies.

It can be done, of course, but that's very much crafting a custom solution for you, rather than something more generic I can recycle for other clients, and so it is really something you should recruit a developer to implement.

#1854123

Thanks, Nigel! Your code works perfectly. Thanks so much for helping with this.

Best,
Mark