duplicate_edit_post($post_id, $post_status); } public function duplicate_edit_post($post_id, $post_status = 'draft') { $post = get_post($post_id); if (empty($post)) { wp_die(esc_html__('No posts found.', 'wp-extra')); } $current_user = wp_get_current_user(); $args = [ 'comment_status' => $post->comment_status, 'ping_status' => $post->ping_status, 'post_author' => $current_user->ID, 'post_content' => wp_slash($post->post_content), 'post_excerpt' => wp_slash($post->post_excerpt), 'post_parent' => $post->post_parent, 'post_password' => $post->post_password, 'post_status' => $post_status, 'post_title' => wp_slash($post->post_title . ' ' . __('(Copy)', 'wp-extra')), 'post_type' => $post->post_type, 'to_ping' => $post->to_ping, 'menu_order' => $post->menu_order, ]; $new_post_id = wp_insert_post($args); if (is_wp_error($new_post_id)) { wp_die(esc_html($new_post_id->get_error_message())); } // Copy taxonomies $taxonomies = get_object_taxonomies($post->post_type); if (!empty($taxonomies) && is_array($taxonomies)) { foreach ($taxonomies as $taxonomy) { $post_terms = wp_get_object_terms($post_id, $taxonomy, ['fields' => 'ids']); if (!empty($post_terms) && !is_wp_error($post_terms)) { wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false); } } } // Copy post meta (excluding internal locks and edits) $exclude_meta = ['_edit_lock', '_edit_last']; $post_meta = get_post_custom($post_id); if (!empty($post_meta) && is_array($post_meta)) { foreach ($post_meta as $meta_key => $meta_values) { if (in_array($meta_key, $exclude_meta, true)) { continue; } foreach ($meta_values as $meta_value) { add_post_meta($new_post_id, $meta_key, maybe_unserialize($meta_value)); } } } // Copy post format if supported if (current_theme_supports('post-formats') && post_type_supports($post->post_type, 'post-formats')) { $format = get_post_format($post_id); if ($format) { set_post_format($new_post_id, $format); } } wp_safe_redirect(esc_url_raw(admin_url('post.php?action=edit&post=' . intval($new_post_id)))); exit; } public function duplicate_post_link($actions, $post) { if ($post->post_type === 'acf-field-group') { return $actions; } $duplicate_types = (array) Helper::get_option('duplicate', []); if (current_user_can('edit_post', $post->ID) && in_array($post->post_type, $duplicate_types, true)) { $actions['duplicate'] = '' . __('Copy', 'wp-extra') . ''; } return $actions; } public function add_admin_notice() { if (isset($_GET['duplicated']) && $_GET['duplicated'] === 'true') { echo '

' . esc_html__('Term duplicated successfully.', 'wp-extra') . '

'; } } public function process_duplicate_term() { check_admin_referer('duplicate-term'); $term_id = (int) filter_input(INPUT_GET, 'term_id'); $taxonomy = sanitize_key(filter_input(INPUT_GET, 'taxonomy')); $tax_obj = get_taxonomy($taxonomy); if (!$tax_obj || !current_user_can($tax_obj->cap->edit_terms)) { wp_die(esc_html__('Sorry, you are not allowed to edit this taxonomy.', 'wp-extra')); } $new_term = $this->duplicate_term($term_id, $taxonomy); if (is_wp_error($new_term)) { wp_die(esc_html($new_term->get_error_message())); } $url = wp_get_referer() ?: admin_url("edit-tags.php?taxonomy={$taxonomy}"); $url = add_query_arg('duplicated', 'true', $url); wp_safe_redirect($url); exit; } public function add_tag_row_action($actions, $tag) { $duplicate_tax = (array) Helper::get_option('duplicate_tax', []); $tax_obj = get_taxonomy($tag->taxonomy); if ($tax_obj && current_user_can($tax_obj->cap->edit_terms) && in_array($tag->taxonomy, $duplicate_tax, true)) { $actions['duplicate'] = sprintf( '%s', esc_url($this->get_duplicate_term_url($tag)), __('Copy', 'wp-extra') ); } return $actions; } private function get_duplicate_term_url($tag) { return wp_nonce_url(add_query_arg([ 'term_id' => $tag->term_id, 'taxonomy' => $tag->taxonomy, 'action' => 'duplicate-term', ], admin_url('admin-post.php')), 'duplicate-term'); } private function get_new_term_name($name, $taxonomy, $parent) { $i = 1; do { $new_name = sprintf(__('%1$s (%2$d)', 'wp-extra'), $name, $i++); } while (term_exists($new_name, $taxonomy, $parent)); return $new_name; } private function duplicate_term($term_id, $taxonomy) { $term = get_term($term_id, $taxonomy); if (is_wp_error($term) || !$term) { return $term ?: new \WP_Error('invalid_term', __('Term not found.', 'wp-extra')); } $new_term = wp_insert_term($this->get_new_term_name($term->name, $term->taxonomy, $term->parent), $term->taxonomy, [ 'description' => $term->description, 'parent' => $term->parent, ]); if (is_wp_error($new_term)) { return $new_term; } $new_term_id = (int) $new_term['term_id']; // Duplicate term meta $term_meta = get_term_meta($term_id); if (!empty($term_meta) && is_array($term_meta)) { foreach ($term_meta as $meta_key => $meta_values) { foreach ($meta_values as $meta_value) { add_term_meta($new_term_id, $meta_key, maybe_unserialize($meta_value)); } } } // Fast & memory-safe batch assignment of posts to the new term $this->duplicate_posts_by_taxonomy($term_id, $new_term_id, $taxonomy); return $new_term; } private function duplicate_posts_by_taxonomy($old_term_id, $new_term_id, $taxonomy) { $object_ids = get_objects_in_term((int)$old_term_id, $taxonomy); if (!empty($object_ids) && !is_wp_error($object_ids)) { foreach (array_chunk($object_ids, 200) as $chunk) { foreach ($chunk as $object_id) { wp_set_object_terms((int)$object_id, (int)$new_term_id, $taxonomy, true); } } } } }