384 lines
13 KiB
PHP
384 lines
13 KiB
PHP
<?php
|
|
|
|
/**
|
|
* The concrete command that clone events.
|
|
*
|
|
* @author Time.ly Network Inc.
|
|
* @since 2.0
|
|
*
|
|
* @package AI1EC
|
|
* @subpackage AI1EC.Command
|
|
*/
|
|
class Ai1ec_Command_Clone extends Ai1ec_Command {
|
|
|
|
/**
|
|
* @var array The posts that must be cloned
|
|
*/
|
|
protected $_posts = array();
|
|
|
|
/**
|
|
* @var bool Whether to redirect or not
|
|
*/
|
|
protected $_redirect = false;
|
|
|
|
/**
|
|
* The abstract method concrete command must implement.
|
|
*
|
|
* Retrieve whats needed and returns it
|
|
*
|
|
* @return array
|
|
*/
|
|
public function do_execute() {
|
|
$id = 0;
|
|
foreach ( $this->_posts as $post ) {
|
|
$id = $this->ai1ec_duplicate_post_create_duplicate(
|
|
$post['post'],
|
|
$post['status']
|
|
);
|
|
}
|
|
if ( true === $this->_redirect ) {
|
|
if ( '' === $post['status'] ) {
|
|
return array(
|
|
'url' => ai1ec_admin_url(
|
|
'edit.php?post_type=' . AI1EC_POST_TYPE
|
|
),
|
|
'query_args' => array()
|
|
);
|
|
} else {
|
|
return array(
|
|
'url' => ai1ec_admin_url(
|
|
'post.php?action=edit&post=' . $id
|
|
),
|
|
'query_args' => array()
|
|
);
|
|
}
|
|
}
|
|
// no redirect, just go on with the page
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns whether this is the command to be executed.
|
|
*
|
|
* I handle the logi of execution at this levele, which is not usual for
|
|
* The front controller pattern, because othe extensions need to inject
|
|
* logic into the resolver ( oAuth or ics export for instance )
|
|
* and this seems to me to be the most logical way to do this.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function is_this_to_execute() {
|
|
$current_action = $this->_registry->get(
|
|
'http.request'
|
|
)->get_current_action();
|
|
|
|
if (
|
|
current_user_can( 'edit_ai1ec_events' ) &&
|
|
'clone' === $current_action &&
|
|
! empty( $_REQUEST['post'] ) &&
|
|
! empty( $_REQUEST['_wpnonce'] ) &&
|
|
wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-posts' )
|
|
) {
|
|
foreach ( $_REQUEST['post'] as $post_id ) {
|
|
$this->_posts[] = array(
|
|
'status' => '',
|
|
'post' => get_post( $post_id )
|
|
);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// other actions need the nonce to be verified
|
|
|
|
// duplicate single post
|
|
if (
|
|
$current_action === 'ai1ec_duplicate_post_save_as_new_post' &&
|
|
! empty( $_REQUEST['post'] )
|
|
) {
|
|
check_admin_referer( 'ai1ec_clone_'. $_REQUEST['post'] );
|
|
|
|
$this->_posts[] = array(
|
|
'status' => '',
|
|
'post' => get_post( $_REQUEST['post'] )
|
|
);
|
|
$this->_redirect = true;
|
|
return true;
|
|
}
|
|
// duplicate single post as draft
|
|
if (
|
|
$current_action === 'ai1ec_duplicate_post_save_as_new_post_draft' &&
|
|
! empty( $_REQUEST['post'] )
|
|
) {
|
|
check_admin_referer( 'ai1ec_clone_'. $_REQUEST['post'] );
|
|
$this->_posts[] = array(
|
|
'status' => 'draft',
|
|
'post' => get_post( $_REQUEST['post'] )
|
|
);
|
|
$this->_redirect = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Sets the render strategy.
|
|
*
|
|
* @param Ai1ec_Request_Parser $request
|
|
*/
|
|
public function set_render_strategy( Ai1ec_Request_Parser $request ) {
|
|
if ( true === $this->_redirect ) {
|
|
$this->_render_strategy = $this->_registry
|
|
->get( 'http.response.render.strategy.redirect' );
|
|
} else {
|
|
$this->_render_strategy = $this->_registry
|
|
->get( 'http.response.render.strategy.void' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a duplicate from a posts' instance
|
|
*/
|
|
public function ai1ec_duplicate_post_create_duplicate( $post, $status = '' ) {
|
|
$post = get_post( $post );
|
|
$new_post_author = $this->_ai1ec_duplicate_post_get_current_user();
|
|
$new_post_status = $status;
|
|
if ( empty( $new_post_status ) ) {
|
|
$new_post_status = $post->post_status;
|
|
}
|
|
$new_post_status = $this->_get_new_post_status( $new_post_status );
|
|
|
|
$new_post = array(
|
|
'menu_order' => $post->menu_order,
|
|
'comment_status' => $post->comment_status,
|
|
'ping_status' => $post->ping_status,
|
|
'pinged' => $post->pinged,
|
|
'post_author' => $new_post_author->ID,
|
|
'post_content' => $post->post_content,
|
|
'post_date' => $post->post_date,
|
|
'post_date_gmt' => get_gmt_from_date( $post->post_date ),
|
|
'post_excerpt' => $post->post_excerpt,
|
|
'post_parent' => $post->post_parent,
|
|
'post_password' => $post->post_password,
|
|
'post_status' => $new_post_status,
|
|
'post_title' => $post->post_title,
|
|
'post_type' => $post->post_type,
|
|
'to_ping' => $post->to_ping,
|
|
);
|
|
|
|
$new_post_id = wp_insert_post( $new_post );
|
|
$edit_event_url = esc_attr(
|
|
ai1ec_admin_url( "post.php?post={$new_post_id}&action=edit" )
|
|
);
|
|
$message = sprintf(
|
|
__( '<p>The event <strong>%s</strong> was cloned succesfully. <a href="%s">Edit cloned event</a></p>', AI1EC_PLUGIN_NAME ),
|
|
$post->post_title,
|
|
$edit_event_url
|
|
);
|
|
$notification = $this->_registry->get( 'notification.admin' );
|
|
$notification->store( $message );
|
|
$this->_ai1ec_duplicate_post_copy_post_taxonomies( $new_post_id, $post );
|
|
$this->_ai1ec_duplicate_post_copy_attachments( $new_post_id, $post );
|
|
$this->_ai1ec_duplicate_post_copy_post_meta_info( $new_post_id, $post );
|
|
|
|
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
|
$api->clear_event_metadata( $new_post_id );
|
|
|
|
if ( $this->_registry->get( 'acl.aco' )->is_our_post_type( $post ) ) {
|
|
try {
|
|
$old_event = $this->_registry->get( 'model.event', $post->ID );
|
|
$old_event->set( 'post_id', $new_post_id );
|
|
$old_event->set( 'post', null );
|
|
$old_event->set( 'ical_feed_url', null );
|
|
$old_event->set( 'ical_source_url', null );
|
|
$old_event->set( 'ical_organizer', null );
|
|
$old_event->set( 'ical_contact', null );
|
|
$old_event->set( 'ical_uid', null );
|
|
$old_event->save();
|
|
} catch ( Ai1ec_Event_Not_Found_Exception $exception ) {
|
|
/* ignore */
|
|
}
|
|
}
|
|
|
|
$meta_post = $this->_registry->get( 'model.meta-post' );
|
|
$meta_post->delete( $new_post_id, '_dp_original' );
|
|
$meta_post->add( $new_post_id, '_dp_original', $post->ID );
|
|
|
|
// If the copy gets immediately published, we have to set a proper slug.
|
|
if (
|
|
$new_post_status == 'publish' ||
|
|
$new_post_status == 'future'
|
|
) {
|
|
$post_name = wp_unique_post_slug(
|
|
$post->post_name,
|
|
$new_post_id,
|
|
$new_post_status,
|
|
$post->post_type,
|
|
$post->post_parent
|
|
);
|
|
|
|
$new_post = array();
|
|
$new_post['ID'] = $new_post_id;
|
|
$new_post['post_name'] = $post_name;
|
|
|
|
// Update the post into the database
|
|
wp_update_post( $new_post );
|
|
}
|
|
|
|
return $new_post_id;
|
|
}
|
|
|
|
/**
|
|
* Copy the meta information of a post to another post
|
|
*/
|
|
protected function _ai1ec_duplicate_post_copy_post_meta_info( $new_id, $post ) {
|
|
$post_meta_keys = get_post_custom_keys( $post->ID );
|
|
if ( empty( $post_meta_keys ) ) {
|
|
return;
|
|
}
|
|
|
|
foreach ( $post_meta_keys as $meta_key ) {
|
|
$meta_values = get_post_custom_values( $meta_key, $post->ID );
|
|
foreach ( $meta_values as $meta_value ) {
|
|
$meta_value = maybe_unserialize( $meta_value );
|
|
$meta_value = apply_filters(
|
|
'ai1ec_duplicate_post_meta_value',
|
|
$meta_value,
|
|
$meta_key,
|
|
$post,
|
|
$new_id
|
|
);
|
|
if ( null !== $meta_value ) {
|
|
add_post_meta( $new_id, $meta_key, $meta_value );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Copy the attachments
|
|
* It simply copies the table entries, actual file won't be duplicated
|
|
*/
|
|
protected function _ai1ec_duplicate_post_copy_attachments( $new_id, $post ) {
|
|
//if (get_option('ai1ec_duplicate_post_copyattachments') == 0) return;
|
|
|
|
// get old attachments
|
|
$attachments = get_posts(
|
|
array(
|
|
'post_type' => 'attachment',
|
|
'numberposts' => -1,
|
|
'post_status' => null,
|
|
'post_parent' => $post->ID,
|
|
)
|
|
);
|
|
// clone old attachments
|
|
foreach ( $attachments as $att ) {
|
|
$new_att_author = $this->_ai1ec_duplicate_post_get_current_user();
|
|
|
|
$new_att = array(
|
|
'menu_order' => $att->menu_order,
|
|
'comment_status' => $att->comment_status,
|
|
'guid' => $att->guid,
|
|
'ping_status' => $att->ping_status,
|
|
'pinged' => $att->pinged,
|
|
'post_author' => $new_att_author->ID,
|
|
'post_content' => $att->post_content,
|
|
'post_date' => $att->post_date,
|
|
'post_date_gmt' => get_gmt_from_date( $att->post_date ),
|
|
'post_excerpt' => $att->post_excerpt,
|
|
'post_mime_type' => $att->post_mime_type,
|
|
'post_parent' => $new_id,
|
|
'post_password' => $att->post_password,
|
|
'post_status' => $this->_get_new_post_status(
|
|
$att->post_status
|
|
),
|
|
'post_title' => $att->post_title,
|
|
'post_type' => $att->post_type,
|
|
'to_ping' => $att->to_ping,
|
|
);
|
|
|
|
$new_att_id = wp_insert_post( $new_att );
|
|
|
|
// get and apply a unique slug
|
|
$att_name = wp_unique_post_slug(
|
|
$att->post_name,
|
|
$new_att_id,
|
|
$att->post_status,
|
|
$att->post_type,
|
|
$new_id
|
|
);
|
|
$new_att = array();
|
|
$new_att['ID'] = $new_att_id;
|
|
$new_att['post_name'] = $att_name;
|
|
|
|
wp_update_post( $new_att );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Copy the taxonomies of a post to another post
|
|
*/
|
|
protected function _ai1ec_duplicate_post_copy_post_taxonomies( $new_id, $post ) {
|
|
$db = $this->_registry->get( 'dbi.dbi' );
|
|
if ( $db->are_terms_set() ) {
|
|
// Clear default category (added by wp_insert_post)
|
|
wp_set_object_terms( $new_id, NULL, 'category' );
|
|
|
|
$post_taxonomies = get_object_taxonomies( $post->post_type );
|
|
|
|
$taxonomies_blacklist = array();
|
|
$taxonomies = array_diff( $post_taxonomies, $taxonomies_blacklist );
|
|
foreach ( $taxonomies as $taxonomy ) {
|
|
$post_terms = wp_get_object_terms(
|
|
$post->ID,
|
|
$taxonomy,
|
|
array( 'orderby' => 'term_order' )
|
|
);
|
|
$terms = array();
|
|
for ( $i = 0; $i < count( $post_terms ); $i++ ) {
|
|
$terms[] = $post_terms[ $i ]->slug;
|
|
}
|
|
wp_set_object_terms( $new_id, $terms, $taxonomy );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the currently registered user
|
|
*/
|
|
protected function _ai1ec_duplicate_post_get_current_user() {
|
|
if ( function_exists( 'wp_get_current_user' ) ) {
|
|
return wp_get_current_user();
|
|
} else {
|
|
$db = $this->_registry->get( 'dbi.dbi' );
|
|
$query = $db->prepare(
|
|
'SELECT * FROM ' . $wpdb->users . ' WHERE user_login = %s',
|
|
$_COOKIE[ USER_COOKIE ]
|
|
);
|
|
$current_user = $db->get_results( $query );
|
|
return $current_user;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the status for `duplicate' post
|
|
*
|
|
* If user cannot publish post (event), and original post status is
|
|
* *publish*, then it will be duplicated with *pending* status.
|
|
* In other cases original status will remain.
|
|
*
|
|
* @param string $old_status Status of old post
|
|
*
|
|
* @return string Status for new post
|
|
*/
|
|
protected function _get_new_post_status( $old_status ) {
|
|
if (
|
|
'publish' === $old_status &&
|
|
! current_user_can( 'publish_ai1ec_events' )
|
|
) {
|
|
return 'pending';
|
|
}
|
|
return $old_status;
|
|
}
|
|
}
|