phpwordpressduplicatespolylang

Wordpress Polylang plugin: Problem with transferring categories to duplicated posts in Polylang


I am using the plugin Polylang in WordPress and trying to do the following:

The Goal Avoid the default behaviour of Polylang of creating category translations when a post gets duplicated using Polylang duplication featured. Only categories that already have translations should be transferred to the duplicated post.

How I am doing so far I am using the pll_copy_taxonomies() in my functions to fire the code and using pll_get_term() to identify which categories have translations, and finally transferring only those ones using wp_set_object_terms() (I've also tried wp_set_post_terms() and wp_set_post_categories() which generate same effect here).

The problem So, the code does transfer only the existing categories without creating new translations. But when I have a duplicated post and I eventually delete the original post, the categories of the original post that don't have any translations will start duplicating themselves to the hundreds. Each copied category will have the slug like exampleslug-1, exampleslug-2, exampleslug-3 ... exampleslug-176...

It seems Polylang handles categories in a different way and when I am doing it without Polylang functions it creates this bug, I can't figure out.

add_filter('pll_copy_taxonomies', 'donotsync', 10, 5);
function donotsync($taxonomies, $sync, $from, $to, $lang) {
    //Bail early if not WP built-in posts
    if ('post' !== get_post_type($from)) {
        return $taxonomies;
    }

    //*** Get the post categories and transfer only the ones already translated
    //*** PROBLEM: This seems to work, but when the article with the default language gets eventually deleted, WP starts duplicating hundreds of copys of the categories from that post that don't have translations yet. Without this block of code, the categories aren't transferred and there's no error.
    $post_categories = get_the_category($from);
    foreach ($post_categories as $key => $terms) {
        $category_id = $terms->term_id;
        //Check if Polylang function exists
        if (function_exists('pll_get_term')) {
            //Check if translation for the category already exists and than transfer it to the duplicated post
            $term_translation = pll_get_term($category_id, $lang);
                if (!empty($term_translation)) {
                    wp_set_object_terms($to, $term_translation, 'category', true);
                }
        }
    }

    //Remove taxonomy sync
    unset($taxonomies['category']);
    return $taxonomies;
}

Solution

  • I actually found the solution myself. The problem was I wasn't using the given $taxonomies from the pll_copy_taxonomies filter to create the loop. Looking up at the plugin files I realized how it was done.

    I also added to transfer the Yoast SEO primary category if it is translated:

    if (function_exists('yoast_get_primary_term_id')) {$primary_category = yoast_get_primary_term_id('category', $from);}

    if ($primary_category == $term){update_post_meta($to,'_yoast_wpseo_primary_category',$term_translation);}

    And to also transfer each tag if it is translated:

        //Get the tag terms
        foreach ($taxonomies as $tax) {
            if ($tax == 'post_tag') {
                if ($terms = get_the_terms($from, $tax)) {
                    $terms = array_map('intval', wp_list_pluck($terms, 'term_id'));
                    foreach ($terms as $term) {
                        //Check if Polylang function exists
                        if (function_exists('pll_get_term')) {
                            //Filter terms with translations only
                            if ($term_translation = pll_get_term($term, $lang)) {
                                //Transfer only terms with translations
                                wp_set_object_terms($to, $term_translation, $tax, true);
                            }
                        }
                    }
                }
    

    Below is the full working code

    add_filter('pll_copy_taxonomies', 'donotsync', 10, 5);
    function donotsync($taxonomies, $sync, $from, $to, $lang) {
        //Bail early if not WP built-in posts
        if ('post' !== get_post_type($from)) {
            return $taxonomies;
        }
        //Check if primary category is set using Yoast SEO
        if (function_exists('yoast_get_primary_term_id')) {$primary_category = yoast_get_primary_term_id('category', $from);}
        //Get the category terms
        foreach ($taxonomies as $tax) {
            if ($tax == 'category') {
                if ($terms = get_the_terms($from, $tax)) {
                    $terms = array_map('intval', wp_list_pluck($terms, 'term_id'));
                    foreach ($terms as $term) {
                        //Check if Polylang function exists
                        if (function_exists('pll_get_term')) {
                            //Filter terms with translations only
                            if ($term_translation = pll_get_term($term, $lang)) {
                                //Transfer only terms with translations
                                wp_set_object_terms($to, $term_translation, $tax, true);
                                //Transfer the primary category if it is translated
                                if ($primary_category == $term){update_post_meta($to,'_yoast_wpseo_primary_category',$term_translation);}
                            }
                        }
                    }
                }
            }
        }
        //Get the tag terms
        foreach ($taxonomies as $tax) {
            if ($tax == 'post_tag') {
                if ($terms = get_the_terms($from, $tax)) {
                    $terms = array_map('intval', wp_list_pluck($terms, 'term_id'));
                    foreach ($terms as $term) {
                        //Check if Polylang function exists
                        if (function_exists('pll_get_term')) {
                            //Filter terms with translations only
                            if ($term_translation = pll_get_term($term, $lang)) {
                                //Transfer only terms with translations
                                wp_set_object_terms($to, $term_translation, $tax, true);
                            }
                        }
                    }
                }
            }
        }
        //Remove taxonomy sync
        unset($taxonomies['category']);
        unset($taxonomies['post_tag']);
        return $taxonomies;
    }