Last active
June 27, 2017 16:10
-
-
Save kjbenk/5029762544ff6b9dcb77487b774d3974 to your computer and use it in GitHub Desktop.
WordPress Post Cloning
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This file handles the cloning of any post type. | |
*/ | |
class Clone_Posts { | |
/** | |
* Instances of child classes. | |
* | |
* @var array | |
*/ | |
protected static $instances = array(); | |
/** | |
* Initialization typically happens via get_instance() method. | |
*/ | |
public function __construct() {} | |
/** | |
* Return an instance of a child class. | |
* | |
* @return ATT_Singleton | |
*/ | |
public static function get_instance() { | |
$class = get_called_class(); | |
if ( ! isset( self::$instances[ $class ] ) ) { | |
self::$instances[ $class ] = new static; | |
self::$instances[ $class ]->setup(); | |
} | |
return self::$instances[ $class ]; | |
} | |
/** | |
* Set up the class. | |
*/ | |
protected function setup() { | |
add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 ); | |
add_action( 'admin_post_clone_posts_action', array( $this, 'clone_post' ) ); | |
} | |
/** | |
* Get all of the post types that we will need to clone. | |
* | |
* @return array The post types to clone. | |
*/ | |
function get_post_types() { | |
/** | |
* Filter the post types that can be cloned. | |
* | |
* Example: | |
* array( | |
* 'custom-post-type' => array( | |
* 'cap' => 'custom-post-type', // Used to check for cap. | |
* 'action' => 'clone_custom_post_type', // Used to check for nonce. | |
* ) | |
* ), | |
* | |
* @param array An array of post types. | |
*/ | |
return apply_filters( 'clone_posts_get_post_types_to_clone', array() ); | |
} | |
/** | |
* Add a clone row action to the channel layout list table. | |
* | |
* @param array $actions The current list of actions. | |
* @param object $post WP_Post object. | |
* @return array $actions The new list of actions. | |
*/ | |
function post_row_actions( $actions, $post ) { | |
foreach ( $this->get_post_types() as $post_type => $args ) { | |
if ( $post_type === $post->post_type && current_user_can( 'edit_' . $args['cap'], $post->ID ) ) { | |
// Include a nonce in this link | |
$clone_link = wp_nonce_url( | |
add_query_arg( | |
array( | |
'action' => 'clone_posts_action', | |
'post_type' => $post->post_type, | |
'nonce_check' => $args['action'], | |
), | |
admin_url( 'admin-post.php?post=' . $post->ID ) | |
), | |
$args['action'] | |
); | |
/** | |
* Allow other plugins to determine if this post can have a clone link. | |
* | |
* @param WP_Post $post The current post object. | |
* @param array $post The current args. | |
*/ | |
if ( apply_filters( 'clone_posts_add_clone_link', true, $post, $args ) ) { | |
// Add the clone link to the list of actions. | |
$actions = array_merge( $actions, array( | |
'copy' => sprintf( '<a href="%1$s">%2$s</a>', esc_url( $clone_link ), esc_html( $this->get_row_action_title() ) ), | |
) ); | |
} | |
} | |
} | |
return $actions; | |
} | |
/** | |
* Clone a specific post type. This is called when the use clicks on the clone | |
* row action from the posts list view. | |
*/ | |
function clone_post() { | |
if ( | |
isset( $_GET['post'] ) | |
&& ! empty( $_GET['nonce_check'] ) | |
&& check_admin_referer( sanitize_text_field( wp_unslash( $_GET['nonce_check'] ) ) ) | |
) { | |
$post_id = absint( $_GET['post'] ); | |
$post = get_post( $post_id ); | |
/** | |
* Can this post be cloned? | |
* | |
* @param WP_Post $post The current post object. | |
*/ | |
if ( ! apply_filters( 'clone_posts_validate_post', true, $post ) ) { | |
wp_die( esc_html( __( ' Unable to clone post' ) . ': ' . $post_title ) ); | |
} | |
if ( ! empty( $post_id ) && $post instanceof WP_Post ) { | |
$clone_id = wp_insert_post( array( | |
'post_status' => 'draft', | |
'post_type' => $post->post_type, | |
'post_title' => $this->get_cloned_title_prefix() . $post->post_title, | |
'post_content' => $post->post_content, | |
'post_excerpt' => $post->post_excerpt, | |
) ); | |
// Add all custom fields | |
if ( $clone_id ) { | |
$custom_fields = get_post_custom( $post_id ); | |
foreach ( $custom_fields as $meta_key => $custom_field ) { | |
foreach ( $custom_field as $meta_value ) { | |
/** | |
* Allow other plugins to determine if this meta data | |
* should be added to this post. | |
* | |
* @param int $clone_id The cloned post ID. | |
* @param string $meta_key The meta key. | |
* @param mixed $meta_value The meta value. | |
*/ | |
if ( apply_filters( 'clone_posts_add_post_meta', true, $clone_id, $meta_key, $meta_value ) ) { | |
add_post_meta( $clone_id, $meta_key, maybe_unserialize( $meta_value ) ); | |
} | |
} | |
} | |
} | |
// Add the terms | |
$taxonomies = get_post_taxonomies( $post_id ); | |
foreach ( $taxonomies as $taxonomy ) { | |
$terms = get_the_terms( $post_id, $taxonomy ); | |
if ( ! empty( $terms ) ) { | |
/** | |
* Allow other plugins to determine if these terms should | |
* be added to the cloned post. | |
* | |
* @param int $clone_id The cloned post ID. | |
* @param string $taxonomy The term taxonomy. | |
* @param array $terms The terms. | |
*/ | |
if ( apply_filters( 'clone_posts_add_post_terms', true, $clone_id, $taxonomy, $terms ) ) { | |
wp_set_object_terms( $clone_id, wp_list_pluck( $terms, 'term_id' ), $taxonomy ); | |
} | |
} | |
} | |
} // End if(). | |
} // End if(). | |
wp_safe_redirect( esc_url_raw( get_admin_url() . '/edit.php?post_type=' . $post->post_type ) ); | |
} | |
/** | |
* Get the cloned post title prefix. | |
* | |
* @return string The cloned title prefix. | |
*/ | |
public function get_cloned_title_prefix() { | |
/** | |
* The cloned post title prefix. | |
*/ | |
return apply_filters( 'clone_posts_title_prefix', __( 'CLONED - ' ) ); | |
} | |
/** | |
* Get the row action title. | |
* | |
* @return string The row action title. | |
*/ | |
public function get_row_action_title() { | |
/** | |
* The row action title. | |
*/ | |
return apply_filters( 'clone_posts_row_action_title', __( 'Clone' ) ); | |
} | |
} | |
// Start it up! | |
Clone_Posts::get_instance(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Should be updated to not copy over certain meta data like
_edit_lock
.