<?php
if(!defined('ABSPATH')) {
	exit; // Exit if accessed directly
}

/**
 * Class of WP Event Manager custom post types.
 * Admin UI for creating custom post types(CPT) and custom taxonomies in WordPress.
 * 
 */
class WP_Event_Manager_CPT {

	/**
	 * Constructor.
	 *
	 * @access public
	 * @return void
	 */
	public function __construct() {

		add_filter('enter_title_here', array($this, 'enter_title_here'), 1, 2);

		add_filter('manage_edit-event_listing_columns', array($this, 'columns'));

		add_filter('list_table_primary_column', array($this, 'primary_column'), 10, 2);
		add_filter('post_row_actions', array($this, 'row_actions'));

		add_action('manage_event_listing_posts_custom_column', array($this, 'custom_columns'), 2);

		add_filter('manage_edit-event_listing_sortable_columns', array($this, 'sortable_columns'));

		add_filter('request', array($this, 'sort_columns'));

		add_filter('manage_event_organizer_posts_columns', array($this, 'organizer_columns'), 10);
		add_action('manage_event_organizer_posts_custom_column', array($this, 'organizer_columns_data'), 10, 2);

		add_filter('post_updated_messages', array($this, 'post_updated_messages'));

		add_action('admin_footer-edit.php', array($this, 'add_bulk_actions'));

		add_filter('handle_bulk_actions-edit-event_listing', array($this, 'do_bulk_actions'), 10, 3);

		add_action('admin_init', array($this, 'approve_event'));
		add_action('admin_notices', array($this, 'approved_notice'));
		add_action('admin_notices', array($this, 'expired_notice'));

		if(get_option('event_manager_enable_categories')) {
			add_action('restrict_manage_posts', array($this, 'events_by_category'));
		}

		if(get_option('event_manager_enable_event_types') && get_option('event_manager_enable_categories')) {
			add_action('restrict_manage_posts', array($this, 'events_by_event_type'));
		}

		foreach (array('post', 'post-new') as $hook) {
			add_action("admin_footer-{$hook}.php", array($this, 'extend_submitdiv_post_status'));
		}
		add_action('admin_action_duplicate_event', array($this,'duplicate_event_post'));
	}
	
	/**
	 * Edit bulk actions.
	 */
	public function add_bulk_actions() {
		global $post_type, $wp_post_types;

		if($post_type == 'event_listing') { ?>
			<script type="text/javascript">
				jQuery(document).ready(function() {
					jQuery('<option>').val('approve_events').text('<?php printf(wp_kses('Approve %s', 'wp-event-manager'), esc_attr($wp_post_types['event_listing']->labels->name)); ?>').appendTo("select[name='action']");
					jQuery('<option>').val('approve_events').text('<?php printf(wp_kses('Approve %s', 'wp-event-manager'), esc_attr($wp_post_types['event_listing']->labels->name)); ?>').appendTo("select[name='action2']");
					jQuery('<option>').val('expire_events').text('<?php printf(wp_kses('Expire %s', 'wp-event-manager'), esc_attr($wp_post_types['event_listing']->labels->name)); ?>').appendTo("select[name='action']");
					jQuery('<option>').val('expire_events').text('<?php printf(wp_kses('Expire %s', 'wp-event-manager'), esc_attr($wp_post_types['event_listing']->labels->name)); ?>').appendTo("select[name='action2']");
				});
			</script>
		<?php
		}
	}

	/**
	 * Do custom bulk actions.
	 */
	public function do_bulk_actions($redirect_url, $action, $post_ids) {
		$wp_list_table = _get_list_table('WP_Posts_List_Table');

		switch ($action) {
			case 'approve_events':
				check_admin_referer('bulk-posts');
				$approved_events = array();
				if(!empty($post_ids)) {
					foreach ($post_ids as $post_id) {
						$event_data = array(
							'ID'          => $post_id,
							'post_status' => 'publish',
						);
						if(in_array(get_post_status($post_id), array('pending', 'pending_payment')) && current_user_can('publish_post', $post_id) && wp_update_post($event_data)) {
							$approved_events[] = $post_id;
						}
					}
				}
				wp_safe_redirect(
					add_query_arg(
						'approved_events',
						count( $approved_events ),
						$redirect_url
					)
				);
				exit;
				break;
			case 'expire_events':
				check_admin_referer('bulk-posts');
				$expired_events = array();
				if(!empty($post_ids)) {
					foreach ($post_ids as $post_id) {
						$event_data = array(
							'ID'          => $post_id,
							'post_status' => 'expired',
						);
						if(current_user_can('manage_event_listings') && wp_update_post($event_data)) {
							$expired_events[] = $post_id;
						}
					}
				}
				wp_safe_redirect(
					add_query_arg(
						'expire_events',
						count( $expired_events ),
						$redirect_url
					)
				);
				exit;
				break;
		}
		return;
	}

	/**
	 * Approve a single event.
	 */
	public function approve_event()	{
		if( isset($_REQUEST['_wpnonce']) && !empty($_GET['approve_event']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'approve_event') && current_user_can('publish_post',sanitize_text_field( wp_unslash( $_GET['approve_event'] )))) {
			$post_id = absint($_GET['approve_event']);
			$event_end_date    = esc_attr(get_post_meta($post_id, '_event_end_date', true));
			$current_timestamp = strtotime(current_time('Y-m-d H:i:s'));
			if(strtotime($event_end_date) > $current_timestamp) {
				$event_data = array(
					'ID'          => $post_id,
					'post_status' => 'publish',
				);
			} else {
				$event_data = array(
					'ID'          => $post_id,
					'post_status' => 'expired',
				);
			}
			wp_update_post($event_data);
			wp_safe_redirect(
				remove_query_arg(
					'approve_event',
					add_query_arg(
						'approved_events',
						$post_id,
						admin_url( 'edit.php?post_type=event_listing' )
					)
				)
			);
			exit;
		}
	}

	/**
	 * Show a notice if we did a bulk action or approval.
	 */
	public function approved_notice() {
		global $post_type, $pagenow;
		if($pagenow == 'edit.php' && $post_type == 'event_listing' && !empty($_REQUEST['approved_events']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'bulk-posts')) {
			$approved_events = sanitize_text_field(wp_unslash($_REQUEST['approved_events']));
			if(is_array($approved_events)) {
				$approved_events = array_map('absint', $approved_events);
				$titles = array();
				foreach ($approved_events as $event_id) {
					$titles[] = get_the_title($event_id);
				}
				echo wp_kses_post('<div class="updated"><p>' . sprintf('%s approved', 'wp-event-manager'), '&quot;' . implode('&quot;, &quot;', $titles) . '&quot;') . '</p></div>';
			} else {
				echo wp_kses_post('<div class="updated"><p>' . sprintf('%s approved', 'wp-event-manager'), '&quot;' . get_the_title($approved_events) . '&quot;') . '</p></div>';
			}
		}
	}

	/**
	 * Show a notice if we did a bulk action or approval.
	 */
	public function expired_notice() {
		global $post_type, $pagenow;

		if($pagenow == 'edit.php' && $post_type == 'event_listing' && !empty($_REQUEST['expired_events']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'bulk-posts')) {
			$expired_events = sanitize_text_field(wp_unslash($_REQUEST['expired_events']));
			if(is_array($expired_events)) {
				$expired_events = array_map('absint', $expired_events);
				$titles = array();
				foreach ($expired_events as $event_id) {
					$titles[] = get_the_title($event_id);
				}
				echo wp_kses_post('<div class="updated"><p>' . sprintf('%s expired', 'wp-event-manager'), '&quot;' . implode('&quot;, &quot;', $titles) . '&quot;') . '</p></div>';
			} else {
				echo wp_kses_post('<div class="updated"><p>' . sprintf('%s expired', 'wp-event-manager'), '&quot;' . get_the_title($expired_events) . '&quot;') . '</p></div>';
			}
		}
	}

	/**
	 * Show category dropdown.
	 */
	public function events_by_category() {
		global $typenow, $wp_query;

		// Only show this filter to users who can edit event listings.
		if ( ! current_user_can( 'edit_event_listings' ) ) {
			return;
		}

		if($typenow != 'event_listing' || !taxonomy_exists('event_listing_category')) {
			return;
		}
		include_once EVENT_MANAGER_PLUGIN_DIR . '/includes/wp-event-manager-category-walker.php';
		$args = array(
			'taxonomy'     => 'event_listing_category',
			'pad_counts'   => 1,
			'hierarchical' => 1,
			'hide_empty'   => false,
			'show_count'   => 1,
			'selected'     => isset($wp_query->query['event_listing_category']) ? $wp_query->query['event_listing_category'] : '',
			'menu_order'   => false,
		);
		$terms  = get_terms($args);
		$walker = new WPEM_Event_Manager_Category_Walker();

		if(!$terms) {
			return;
		}
		$selected_category = '';

		if ( isset( $_GET['event_listing_category'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'wpem_category_filter' ) ) {
			$selected_category = sanitize_text_field( wp_unslash( $_GET['event_listing_category'] ) );
		}
		$output = "<select name='event_listing_category' id='dropdown_event_listing_category'>";
		$output .= '<option value="" ' . selected($selected_category, '', false) . '>' . esc_html__('Select category', 'wp-event-manager') . '</option>';
		$output .= $walker->walk($terms, 0, $args);
		$output .= '</select>';
		// Allow select and option tags with their common attributes
		$allowed_html = array(
			'select' => array(
				'name' => true,
				'id' => true,
				'class' => true,
				'style' => true,
				'title' => true,
				'data-*' => true,
				'aria-*' => true,
			),
			'option' => array(
				'value' => true,
				'selected' => true,
				'disabled' => true,
				'class' => true,
				'data-*' => true,
			),
		);
		echo wp_kses($output, $allowed_html);
	}

	/**
	 * Show Event type dropdown.
	 */
	public function events_by_event_type() {
		global $typenow, $wp_query;

		if($typenow != 'event_listing' || !taxonomy_exists('event_listing_type')) {
			return;
		}

		$args = array(	
			'taxonomy'     => 'event_listing_type',
			'pad_counts'   => true,
			'hierarchical' => true,
			'hide_empty'   => false,
			'show_count'   => true,
			'selected'     => isset($wp_query->query['event_listing_type']) ? $wp_query->query['event_listing_type'] : '',
			'menu_order'   => false,
		);
		$terms   = get_terms($args);
		$walker  = new WPEM_Event_Manager_Category_Walker();

		if(!$terms) {
			return;
		}

		$selected_event_type = '';
		if ( isset( $_GET['event_listing_type'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'wpem_event_type_filter' ) ) {
			$selected_event_type = sanitize_text_field( wp_unslash( $_GET['event_listing_type'] ) );
		}
		echo wp_kses(
			"<select name='event_listing_type' id='event_listing_type'>" .
			'<option value="" ' . selected($selected_event_type, '', false) . '>' . esc_html__('Select Event Type', 'wp-event-manager') . '</option>' .
			$walker->walk($terms, 0, $args) .
			'</select>',
			array(
				'select' => array(
					'name' => true,
					'id' => true,
					'class' => true
				),
				'option' => array(
					'value' => true,
					'selected' => true,
					'class' => true
				)
			)
		);
	}

	/**
	 * enter_title_here function.
	 *
	 * @access public
	 * @return void
	 */
	public function enter_title_here($text, $post){
		if($post->post_type == 'event_listing') {
			return __('Event Title', 'wp-event-manager');
		}
		return $text;
	}

	/**
	 * Updated messages of event post.
	 *
	 * @access public
	 * @param mixed $messages
	 * @return void
	 */
	public function post_updated_messages( $messages ) {
		global $post, $post_ID, $wp_post_types;

		// Allowed HTML for messages
		$allowed_html = array(
			'a' => array(
				'href'   => array(),
				'target' => array(),
			),
			'strong' => array(),
		);

		// Sanitize revision ID if present
		$revision_id = isset( $_GET['revision'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'wpem_revision_check' ) ? absint( wp_unslash( $_GET['revision'] ) )	: 0;

		$messages['event_listing'] = array(
			0  => '',
			1  => sprintf(
				wp_kses( '%1$s updated. <a href="%2$s">View</a>', $allowed_html ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name ),
				esc_url( get_permalink( $post_ID ) )
			),
			2  => __( 'Custom field updated.', 'wp-event-manager' ),
			3  => __( 'Custom field deleted.', 'wp-event-manager' ),
			4  => sprintf(
				wp_kses( '%s updated.', $allowed_html ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name )
			),
			5  => $revision_id
				? sprintf(
					wp_kses( '%1$s restored to revision from %2$s', $allowed_html ),
					esc_html( $wp_post_types['event_listing']->labels->singular_name ),
					wp_post_revision_title( $revision_id, false )
				)
				: false,
			6  => sprintf(
				wp_kses( '%1$s published. <a href="%2$s">View</a>', $allowed_html ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name ),
				esc_url( get_permalink( $post_ID ) )
			),
			7 => sprintf(
				/* translators: %s: singular post type name */
				__( '%s saved.', 'wp-event-manager' ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name )
			),
			8  => sprintf(
				wp_kses( '%1$s submitted. <a target="_blank" href="%2$s">Preview</a>', $allowed_html ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name ),
				esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) )
			),
			9  => sprintf(
				wp_kses( '%s scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview</a>', $allowed_html ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name ),
				date_i18n(
					__( 'M j, Y @ G:i', 'wp-event-manager' ),
					strtotime( $post->post_date )
				),
				esc_url( get_permalink( $post_ID ) )
			),
			10 => sprintf(
				wp_kses( '%1$s draft updated. <a target="_blank" href="%2$s">Preview</a>', $allowed_html ),
				esc_html( $wp_post_types['event_listing']->labels->singular_name ),
				esc_url(
					add_query_arg(
						'preview',
						'true',
						get_permalink( $post_ID )
					)
				)
			),
		);

		return $messages;
	}

	/**
	 * Add columns.
	 *
	 * @param array $columns
	 * @return array
	 */
	public function columns($columns){
		if(!is_array($columns)) {
			$columns = array();
		}
		unset($columns['title'], $columns['date'], $columns['author']);
		$columns['event_title'] = __('Title', 'wp-event-manager');
		$columns['event_banner'] = '<span class="tips dashicons dashicons-format-image" data-tip="' . __('Banner', 'wp-event-manager') . '">' . __('Banner', 'wp-event-manager') . '</span>';
		$columns['event_listing_type'] = __('Type', 'wp-event-manager');
		$columns['event_location'] = __('Location', 'wp-event-manager');
		$columns['event_organizer'] = __('Organizer', 'wp-event-manager');
		$columns['event_start_date'] = __('Start Date', 'wp-event-manager');
		$columns['event_end_date'] = __('End Date', 'wp-event-manager');
		$columns['event_expires'] = __('Expiry Date', 'wp-event-manager');
		$columns['event_status'] = '<span class="tips" data-tip="' . __('Status', 'wp-event-manager') . '">' . __('Status', 'wp-event-manager') . '</span>';
		$columns['cancelled'] = '<span class="tips" data-tip="' . __('Cancelled?', 'wp-event-manager') . '">' . __('Cancelled?', 'wp-event-manager') . '</span>';
		$columns['featured_event'] = '<span class="tips" data-tip="' . __('Featured?', 'wp-event-manager') . '">' . __('Featured?', 'wp-event-manager') . '</span>';
		$columns['event_actions'] = __('Actions', 'wp-event-manager');
		if(!get_option('event_manager_enable_event_types')) {
			unset($columns['event_listing_type']);
		}
		if(!get_option('enable_event_organizer')) {
			unset($columns['event_organizer']);
		}
		return apply_filters('wpem_cpt_event_column', $columns);
	}

	/**
	 * This is required to make column responsive since WP 4.3.
	 *
	 * @access public
	 * @param string $column
	 * @param string $screen
	 * @return string
	 */
	public function primary_column($column, $screen) {
		// If we want to set the primary column for CPT
		if('edit-event_listing' === $screen) {
			$column = 'event_title';
		}
		return $column;
	}

	/**
	 * Removes all action links because WordPress add it to primary column.
	 * Note: Removing all actions also remove mobile "Show more details" toggle button.
	 * So the button need to be added manually in custom_columns callback for primary column.
	 *
	 * @access public
	 * @param array $actions
	 * @return array
	 */
	public function row_actions($actions) {
		if('event_listing' == get_post_type()) {
			return array();
		}
		return $actions;
	}

	/**
	 * Add custom columns.
	 *
	 * @access public
	 * @param mixed $column
	 * @return void
	 */
	public function custom_columns($column) {
		global $post;
		switch ($column) {
			case 'event_status':
				echo wp_kses_post('<span data-tip="' . esc_attr(wpem_get_event_status($post)) . '" class="tips status-' . esc_attr($post->post_status) . '">' . esc_attr(wpem_get_event_status($post)) . '</span>');
				break;
			case 'cancelled':
				if(wpem_is_event_cancelled($post)) {
					echo wp_kses_post('<span class="tips dashicons dashicons-no" data-tip="' . __('Cancelled', 'wp-event-manager') . '">' . __('Cancelled', 'wp-event-manager') . '</span>');
				} else {
					echo wp_kses_post('&ndash;');
				}
				break;
				'<span class="tips dashicons dashicons-format-image" data-tip="' . __('Banner', 'wp-event-manager') . '">' . __('Banner', 'wp-event-manager') . '</span>';
			case 'featured_event':
				if(wpem_is_event_featured($post)) {
					echo wp_kses_post('<span class="tips dashicons dashicons-star-filled" data-tip="' . __('Featured', 'wp-event-manager') . '">' . __('Featured', 'wp-event-manager') . '</span>');
				} else {
					echo wp_kses_post('<span class="tips dashicons dashicons-star-empty" data-tip="' . __('Not Featured', 'wp-event-manager') . '">' . __('Not Featured', 'wp-event-manager') . '</span>');
				}
				break;
			case 'event_banner':
				echo wp_kses_post('<div class="event_banner">');
				wpem_display_event_banner();
				echo wp_kses_post('</div>');
				break;
			case 'event_title':
				echo wp_kses_post('<div class="event_title">');
				echo wp_kses_post('<a href="' . esc_url(admin_url('post.php?post=' . $post->ID . '&action=edit')) . '" class="tips event_title" data-tip="' . sprintf(wp_kses('ID: %d', 'wp-event-manager'), $post->ID) . '">' . esc_html($post->post_title) . '</a>');
				echo wp_kses_post('</div>');
				echo wp_kses_post('<button type="button" class="toggle-row"><span class="screen-reader-text">' . esc_html__('Show more details', 'wp-event-manager') . '</span></button>');
				break;
			case 'event_listing_type':
				$types = wpem_get_event_type($post);
				if($types && !empty($types)) {
					foreach ($types as $type) {
						echo wp_kses_post('<span class="event-type ' . $type->slug . '">' . $type->name . '</span>');
					}
				}
				break;
			case 'event_location':
				wpem_display_event_location($post);
				break;
			case 'event_organizer':
				echo wp_kses_post('<div class="organizer">');
				echo wp_kses_post(wpem_get_organizer_name('', true, 'backend'));
				echo wp_kses_post('</div>');
				break;
			case 'event_start_date':
				if($post->_event_start_date) {
					$format = get_option('date_format');
					$datepicker_date_format = WP_Event_Manager_Date_Time::get_datepicker_format();
					if($datetime = DateTime::createFromFormat("'.$datepicker_date_format.'", "'.$post->_event_start_date.'")) {
						$date = 	$datetime->format($format);
					} else {
						$date = date_i18n(get_option('date_format'), strtotime($post->_event_start_date));
					}
					echo wp_kses_post($date);
				} else {
					echo wp_kses_post('&ndash;');
				}
				break;
			case 'event_end_date':
				if($post->_event_end_date) {
					$format = get_option('date_format');
					$datepicker_date_format = WP_Event_Manager_Date_Time::get_datepicker_format();
					if($datetime = DateTime::createFromFormat("'.$datepicker_date_format.'", "'.$post->_event_end_date.'")) {
						$date = 	$datetime->format($format);
					} else {
						$date = date_i18n(get_option('date_format'), strtotime($post->_event_end_date));
					}

					echo wp_kses_post($date);
				} else {
					echo wp_kses_post('&ndash;');
				}
				break;
			case 'event_expires':
				if($post->_event_expiry_date) {
					$format = get_option('date_format');
					$datepicker_date_format = WP_Event_Manager_Date_Time::get_datepicker_format();
					if($datetime = DateTime::createFromFormat("'.$datepicker_date_format.'", "'.$post->_event_expiry_date.'")) {
						$date = 	$datetime->format($format);
					} else {
						$date = date_i18n(get_option('date_format'), strtotime($post->_event_expiry_date));
					}
					echo wp_kses_post($date);
				} else {
					echo wp_kses_post('&ndash;');
				}
				break;
			case 'event_actions':
				echo wp_kses_post('<div class="actions">');
				$admin_actions = apply_filters('wpem_event_listing_row_actions', array(), $post);
				if(in_array($post->post_status, array('pending', 'pending_payment')) && current_user_can('publish_post', $post->ID)) {
					$admin_actions['approve'] = array(
						'action' => 'approve',
						'name'   => __('Approve', 'wp-event-manager'),
						'url'    => wp_nonce_url(add_query_arg('approve_event', $post->ID), 'approve_event'),
					);
				}
				if($post->post_status !== 'trash') {
					if(current_user_can('read_post', $post->ID)) {
						$admin_actions['view'] = array(
							'action' => 'view',
							'name'   => __('View', 'wp-event-manager'),
							'url'    => get_permalink($post->ID),
						);
					}
					if(current_user_can('edit_post', $post->ID)) {
						$admin_actions['edit'] = array(
							'action' => 'edit',
							'name'   => __('Edit', 'wp-event-manager'),
							'url'    => get_edit_post_link($post->ID),
						);
						$admin_actions['duplicate'] = array(
							'action' => 'duplicate',
							'name'   => __('Duplicate', 'wp-event-manager'),
							'url'    => esc_url(wpem_get_duplicate_post_link($post->ID)),
						);
					}
					if(current_user_can('delete_post', $post->ID)) {
						$admin_actions['delete'] = array(
							'action' => 'delete',
							'name'   => __('Delete', 'wp-event-manager'),
							'url'    => get_delete_post_link($post->ID),
						);
					}
				}
				$admin_actions = apply_filters('event_manager_admin_actions', $admin_actions, $post);
				foreach ($admin_actions as $action) {
					if(is_array($action)) {
						printf('<a class="button button-icon tips icon-%1$s" href="%2$s" data-tip="%3$s">%4$s</a>', esc_attr($action['action']), esc_url($action['url']), esc_attr($action['name']), esc_html($action['name']));
					} else {
						echo wp_kses_post(str_replace('class="', 'class="button ', $action));
					}
				}
				echo wp_kses_post('</div>');
				break;
			default :
				$value = get_post_meta($post->ID, $column, true);
				echo esc_attr(apply_filters('wpem_cpt_event_custom_column', wp_kses_post($value), $column, $post));
				break;
		}
	}

	/**
	 * Duplicate event.
	 *
	 * @access public
	 * @param mixed $columns
	 * @return void
	 */
	public function duplicate_event_post() {
		if (!isset($_GET['post']) || !current_user_can('edit_posts')) {
			wp_die('No permission or invalid request');
		}

		$post_id = absint($_GET['post']);
		$nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ?? '' ) );

		if (!wp_verify_nonce(sanitize_text_field(wp_unslash($nonce)), 'duplicate_event_' . $post_id)) {
			wp_die('Nonce verification failed');
		}

		$post = get_post($post_id);
		if (!$post || $post->post_type !== 'event_listing') {
			wp_die('Invalid event');
		}

		$new_post = array(
			'post_title'    => $post->post_title . ' (Copy)',
			'post_content'  => $post->post_content,
			'post_excerpt'  => $post->post_excerpt,
			'post_status'   => 'draft',
			'post_type'     => $post->post_type,
			'post_author'   => get_current_user_id(),
		);

		$new_post_id = wp_insert_post($new_post);

		$meta = get_post_meta($post_id);
		foreach ($meta as $key => $values) {
			foreach ($values as $value) {
				add_post_meta($new_post_id, $key, maybe_unserialize($value));
			}
		}

		$taxonomies = get_object_taxonomies($post->post_type);
		foreach ($taxonomies as $taxonomy) {
			$terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
			wp_set_object_terms($new_post_id, $terms, $taxonomy, false);
		}

		wp_safe_redirect(
			admin_url( 'post.php?action=edit&post=' . $new_post_id )
		);
		exit;
	}

	/**
	 * The table sortable columns.
	 *
	 * @access public
	 * @param mixed $columns
	 * @return void
	 */
	public function sortable_columns($columns) {
		$custom = array(
			'event_posted'     => 'date',
			'event_title'      => 'title',
			'event_location'   => 'event_location',
			'event_start_date' => 'event_start_date',
			'event_end_date'   => 'event_end_date',
			'event_expires'    => 'event_expires',
		);
		return wp_parse_args($custom, $columns);
	}

	/**
	 * Sort columns.
	 *
	 * @access public
	 * @param mixed $vars
	 * @return void
	 */
	public function sort_columns($vars) {
		if(isset($vars['orderby'])) {
			if('event_expires' === $vars['orderby']) {
				$vars = array_merge(
					$vars,
					array(
						'meta_key'  => '_event_expiry_date',
						'orderby'   => 'meta_value',
						'meta_type' => 'DATE',
					)
				);
			} elseif('event_start_date' === $vars['orderby']) {
				$vars = array_merge(
					$vars,
					array(
						'meta_key'  => '_event_start_date',
						'orderby'   => 'meta_value',
						'meta_type' => 'DATETIME',
					)
				);
			} elseif('event_end_date' === $vars['orderby']) {
				$vars = array_merge(
					$vars,
					array(
						'meta_key'  => '_event_end_date',
						'orderby'   => 'meta_value',
						'meta_type' => 'DATETIME',
					)
				);
			} elseif('event_location' === $vars['orderby']) {
				$vars = array_merge(
					$vars,
					array(
						'meta_key' => '_event_location',
						'orderby'  => 'meta_value',
					)
				);
			} elseif('event_organizer' === $vars['orderby']) {
				$vars = array_merge(
					$vars,
					array(
						'meta_key' => '_organizer_name',
						'orderby'  => 'meta_value',
					)
				);
			}
		}
		return $vars;
	}

	/**
	 * Columns of organizer.
	 *
	 * @access public
	 * @param $columns
	 * @return
	 * @since 3.1.16
	 */
	public function organizer_columns($columns)	{

		$columns = array_slice($columns, 0, 2, true) + array( 'organizer_id' => __('ID', 'wp-event-manager' ), 'organizer_email' => __('Email', 'wp-event-manager') ) + array_slice($columns, 2, count($columns) - 2, true);
		
		return $columns;
	}

	/**
	 * Columns data of organizer.
	 *
	 * @access public
	 * @param $column, $post_id
	 * @return
	 * @since 3.1.16
	 */
	public function organizer_columns_data($column, $post_id) {
		switch ($column) {
			case 'organizer_email':
				echo esc_html(get_post_meta($post_id, '_organizer_email', true));
				break;
			case 'organizer_id':
				echo esc_attr(get_the_ID());
				break;	
		}
	}

	/**
	 * Adds post status to the "submitdiv" Meta Box and post type WP List Table screens. Based on https://gist.github.com/franz-josef-kaiser/2930190
	 *
	 * @return void
	 */
	public function extend_submitdiv_post_status() {
		global $post, $post_type;
		// Abort if we're on the wrong post type, but only if we got a restriction
		if('event_listing' !== $post_type) {
			return;
		}
		
		// Ensure the function exists
		if(!function_exists('wpem_get_event_listing_post_statuses')) {
			return;
		}
		
		// Get all non-builtin post status and add them as <option>
		$options = $display = '';
		$post_statuses = wpem_get_event_listing_post_statuses();
		
		if(empty($post_statuses) || !is_array($post_statuses)) {
			return;
		}
		$display = isset($post_statuses[0]) ? $post_statuses[0] : 'draft';
		foreach ($post_statuses as $status => $name) {
			$selected = selected($post->post_status, $status, false);
			// If we one of our custom post status is selected, remember it
			if($selected) {
				$display = $name;
			}
			// Build the options
			$options .= "<option{$selected} value='{$status}'>{$name}</option>";
		}
		echo '<input type="hidden" name="' . esc_attr($post_type) . '_status" . " value="' . esc_attr($post->post_status) . '">';
		?>
		<script type="text/javascript">
			jQuery(document).ready(function($) {
				// Wait for the DOM to be fully loaded
				setTimeout(function() {
					var statusSelect = jQuery('#post-status-select').find('select');
					var default_status = jQuery('#event_listing_status').val();
					if(statusSelect.length > 0) {
						if(!empty(default_status)) {
							jQuery('#post-status-display').html('<?php echo wp_kses_post($display); ?>');
						}
						statusSelect.html("<?php echo esc_js($options); ?>");
					}
				}, 100);
			});
		</script>
	<?php }
}
new WP_Event_Manager_CPT();