all-in-one-event-calendar/lib/command/clone.php
2017-11-09 17:36:04 +01:00

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;
}
}