<?php
/**
 * The WP_Members Products Admin Class.
 *
 * @package WP-Members
 * @subpackage WP_Members_Products_Admin
 * @since 3.2.0
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit();
}

class WP_Members_Products_Admin {

	public $default_products;

	/**
	 * Class constructor.
	 *
	 * @since 3.2.0
	 *
	 * @global object $wpmem
	 */
	function __construct() {
		global $wpmem;
		if ( 1 == $wpmem->enable_products ) {
			add_filter( 'manage_wpmem_product_posts_columns',       array( $this, 'columns_heading' ) );
			add_action( 'manage_wpmem_product_posts_custom_column', array( $this, 'columns_content' ), 10, 2 );

			add_action( 'restrict_manage_posts', array( $this, 'filter_by_membership' ) );
			add_action( 'pre_get_posts',         array( $this, 'membership_filter'    ) );

			add_action( 'add_meta_boxes',                  array( $this, 'meta_boxes' ) );
			add_action( 'page_attributes_misc_attributes', array( $this, 'membership_attributes' ) );
			add_action( 'save_post',                       array( $this, 'save_details' ) );
			add_action( 'wpmem_admin_after_block_meta',    array( $this, 'add_product_to_post' ), 10, 2 );
			add_action( 'wpmem_admin_block_meta_save',     array( $this, 'save_product_to_post' ), 10, 3 );
			add_action( 'admin_footer',                    array( $this, 'enqueue_select2' ) );
			add_filter( 'manage_users_columns',            array( $this, 'user_columns' ) );
			add_filter( 'manage_users_custom_column',      array( $this, 'user_columns_content' ), 10, 3 );
			add_action( 'admin_head',                      array( $this, 'post_columns_width' ) );
			add_filter( 'manage_posts_columns',            array( $this, 'post_columns' ) );
			add_action( 'manage_posts_custom_column',      array( $this, 'post_columns_content' ), 10, 2 );
			add_filter( 'manage_pages_columns',            array( $this, 'post_columns' ) );
			add_action( 'manage_pages_custom_column',      array( $this, 'post_columns_content' ), 10, 2 );
			foreach( $wpmem->post_types as $key => $val ) {
				add_filter( 'manage_' . $key . '_posts_columns',       array( $this, 'post_columns' ) );
				add_action( 'manage_' . $key . '_posts_custom_column', array( $this, 'post_columns_content' ), 10, 2 );
			}
			
			add_filter( 'wpmem_user_profile_tabs',         array( $this, 'user_profile_tabs' ), 1 );
			add_action( 'wpmem_user_profile_tabs_content', array( $this, 'user_profile_tab_content' ), 10 );
			
			add_filter( 'wpmem_views_users', array( $this, 'user_views'  ), 10, 2 );
			add_filter( 'wpmem_query_where', array( $this, 'query_where' ), 10, 2 );

			add_action( 'after_delete_post', array( $this, 'refactor_membership_option' ), 10, 2 );
			add_action( 'untrashed_post',    array( $this, 'refactor_membership_option' ), 10, 2 );
			add_action( 'trashed_post',      array( $this, 'refactor_membership_option' ), 10, 2 );
		}
		
		$this->default_products = $wpmem->membership->get_default_products();
	}

	/**
	 * Column headings for list table.
	 *
	 * @since 3.2.0
	 *
	 * @param  array $columns
	 * @return array $columns
	 */
	function columns_heading( $columns ) {
		unset( $columns['date'] );
		$columns['slug']         = esc_html__( 'Slug', 'wp-members' );
		$columns['role']         = esc_html__( 'Role', 'wp-members' );
		$columns['expires']      = esc_html__( 'Expires', 'wp-members' );
		if ( $this->default_products ) {
			$columns['default_products'] = esc_html__( 'Default', 'wp-members' );
		}
		$columns['last_updated'] = esc_html__( 'Last updated', 'wp-members' );
		return $columns;
	}

	/**
	 * Column content for list table.
	 *
	 * @since 3.2.0
	 *
	 * @param  string $column_name
	 * @param  int    $post_id
	 */
	function columns_content( $column, $post_id ) {
		$post = get_post( $post_id );
		switch ( $column ) {
			case 'slug':
				echo $post->post_name;
				break;
			case 'role':
				$role_slug = $this->get_meta( 'wpmem_product_role' );
				if ( $role_slug ) {
					$wp_roles  = new WP_Roles;
					$names     = $wp_roles->get_names();

					$role      = $names[ $role_slug ] . ' (' . esc_html__( 'slug:', 'wp-members' ) . ' ' . $role_slug . ')';
					echo esc_html( $role );
				} else {
					__( 'No role required', 'wp-members' );
				}
				break;
			case 'expires':
				$expires = $this->get_meta( 'wpmem_product_expires' );
				$period = ( false !== $expires ) ? explode( "|", $expires[0] ) : esc_html__( 'Does not expire', 'wp-members' );
				echo ( is_array( $period ) ) ? esc_html( $period[0] . ' ' . $period[1] ) : esc_html( $period );
				break;
			case 'default_products':
				echo ( in_array( $post->post_name, $this->default_products ) ) ? esc_html__( 'Yes', 'wp-members' ) : '';
				break;
			case 'last_updated':
				echo date_i18n( get_option( 'date_format' ), strtotime( esc_attr( $post->post_modified ) ) );
				break;
		}
	}

	/**
	 * Adds filter option for Posts > All Posts to filter by membership.
	 * 
	 * @since 3.5.5
	 */
	function filter_by_membership() {

		global $typenow, $wpmem;

		// Only do this for managed post types.
		if ( 'post' == $typenow || 'page' == $typenow || array_key_exists( $typenow, $wpmem->post_types ) ) {

			$memberships = wpmem_get_memberships();
			
			// Only continue if there are memberships.
			if ( ! empty( $memberships ) ) {

				$sanitized_value = wpmem_get_sanitized( 'membership_filter', '', 'get' );
				echo '<select name="membership_filter">';
				echo '<option value="">' . esc_html__( 'Filter by membership', 'wp-members' ) . '</option>';
				foreach ( $memberships as $membership_meta => $membership_vals ) {
					printf(
						'<option value="%s"%s>%s</option>',
						esc_attr( $membership_vals['name'] ),
						$membership_vals['name'] == $sanitized_value ? ' selected="selected"' : '',
						esc_html( $membership_vals['title'] )
					);
				}
				echo '</select>';
			}
		}
	}

	/**
	 * Filters the Posts > All Posts view by membership.
	 * 
	 * @since 3.5.5
	 */
	function membership_filter( $query ) {
		global $pagenow;
		if ( is_admin() && $pagenow == 'edit.php' && wpmem_get( 'membership_filter', false, 'get' ) ) {
			$query->query_vars['meta_key'] = '_wpmem_products_' . wpmem_get_sanitized( 'membership_filter', false, 'get' );
			$query->query_vars['meta_value'] = 1;
		}
	}

	/**
	 * Gets value of requested post meta.
	 *
	 * @since 3.2.0
	 *
	 * @param  string $value
	 * @return string
	 */
	function get_meta( $value ) {
		global $post;
		$field = get_post_meta( $post->ID, $value, true );
		if ( ! empty( $field ) ) {
			return is_array( $field ) ? stripslashes_deep( $field ) : stripslashes( wp_kses_decode_entities( $field ) );
		} else {
			return false;
		}
	}

	/**
	 * Handles meta boxes for CPT editor.
	 *
	 * @since 3.2.0
	 * @since 3.3.4 Added message meta box.
	 */
	function meta_boxes() {
		remove_meta_box( 'slugdiv', 'wpmem_product', 'normal' );
		add_meta_box(
			'membership_product',
			__( 'Membership Product Details', 'wp-members' ),
			array( $this, 'details_html' ),
			'wpmem_product',
			'normal',
			'high'
		);
		add_meta_box(
			'membership_product_message',
			__( 'Membership Product Message (optional)', 'wp-members' ),
			array( $this, 'message_meta_box_detail' ),
			'wpmem_product'
		);
	}
	
	/**
	 * Adds child membership access option to Membership Attributes meta box.
	 *
	 * @since 3.4.1
	 */
	function membership_attributes( $post ) {
		if ( 'wpmem_product' == $post->post_type ) {
			$checked = get_post_meta( $post->ID, 'wpmem_product_child_access', true );
			echo '<p class="post-attributes-label-wrapper">
				<input name="wpmem_product_child_access" type="checkbox" value="1" ' .  checked( $checked, 1, false ) . ' />
				<label>' . esc_html__( 'Access by child membership', 'wp-members' ) . '</label><br />
			</p>';
		}
	}

	/**
	 * Gets an array of post types.
	 *
	 * @since 3.3.3
	 *
	 * @return array $post_types
	 */
	function get_post_types() {
		global $wpmem;
		// @todo This comes from option tab. Should consider it being an api function.
		$post_arr = array(
			'post' => esc_html__( 'Posts' ),
			'page' => esc_html__( 'Pages' ),
		);
		if ( ! empty( $wpmem->post_types ) ) {
			foreach ( $wpmem->post_types as $key => $post_type ) {
				$post_arr[ $key ] = $post_type;
			}
		}
		return $post_arr;
	}
	
	/**
	 * Outputs HTML for CPT editor.
	 *
	 * @since 3.2.0
	 *
	 * @param  object $post
	 */
	function details_html( $post ) {
		
		$product_default = $this->get_meta( 'wpmem_product_default' );
		$product_expires = $this->get_meta( 'wpmem_product_expires' );
		$product_role    = $this->get_meta( 'wpmem_product_role'    );
		$product_no_gap  = $this->get_meta( 'wpmem_product_no_gap'  );
		$product_fixed_period = $this->get_meta( 'wpmem_product_fixed_period' );

		$product_expires = ( false !== $product_expires ) ? $product_expires[0] : $product_expires;
		
		$periods = array( esc_html__( 'Period', 'wp-members' ) . '|', esc_html__( 'Day', 'wp-members' ) . '|day', esc_html__( 'Week', 'wp-members' ) . '|week', esc_html__( 'Month', 'wp-members' ) . '|month', esc_html__( 'Year', 'wp-members' ) . '|year' ); 
		$show_role_detail = ( false !== $product_role    ) ? 'show' : 'hide';
		$show_exp_detail  = ( false !== $product_expires ) ? 'show' : 'hide';
		$show_exp_fixed   = ( false !== $product_fixed_period ) ? 'show' : 'hide';

		/**
		 * Fires before membership product detail meta box.
		 *
		 * @since 3.3.5
		 */
		do_action( 'wpmem_membership_product_meta_before' ); ?>

			<?php wp_nonce_field( '_wpmem_product_nonce', 'wpmem_product_nonce' ); ?>
			<h3><?php _e( 'Name (slug)', 'wp-members' ); ?></h3>
			<p><strong><?php echo esc_attr( $post->post_name ); ?></strong></p>
			<h3><?php esc_html_e( 'Optional Defaults', 'wp-members' ); ?></h3>
			<p>
				<input type="checkbox" name="wpmem_product_default" id="wpmem_product_default" value="1" <?php echo ( 1 == $product_default  ) ? 'checked' : ''; ?> />
				<label for="wpmem_product_default"><?php _e( 'Assign as default at registration? (optional)', 'wp-members' ); ?></label>
			</p>
			<p>
			<?php
		
			foreach( $this->get_post_types() as $key => $post_type ) {
				echo '<div>';
				echo '<input type="checkbox" name="wpmem_product_set_default_' . $key . '" id="wpmem_product_set_default_' . $key . '" value ="1" '; echo ( 1 == $this->get_meta( "wpmem_product_set_default_" . $key ) ) ? 'checked' : ''; echo ' />';
				echo '<label for="wpmem_product_set_default_' . $key . '">' . sprintf( esc_html__( 'Pre-selected by default for new %s', 'wp-members' ), $post_type ) . '</label>';
				echo '</div>';
			}
		
			?>
			</p>
			<h3><?php esc_html_e( 'Optional Properties', 'wp-members' ); ?></h3>
			<p>
				<input type="checkbox" name="wpmem_product_role_required" id="wpmem_product_role_required" value="role-required" <?php echo ( false !== $product_role ) ? 'checked' : ''; ?> />
				<label for="wpmem_product_role_required"><?php _e( 'Role Required? (optional)', 'wp-members' ); ?></label>
				<label for="wpmem_product_role"></label>
				<select name="wpmem_product_role" id="wpmem_product_role">
					<option value=""><?php _e( 'No Role', 'wp-members' ); ?></option>
					<?php wp_dropdown_roles( $this->get_meta( 'wpmem_product_role' ) ); ?>
				</select>
			</p>
			<p>
				<input type="checkbox" name="wpmem_product_expires" id="wpmem_product_expires" value="expires" <?php echo ( false !== $product_expires ) ? 'checked' : ''; ?> />
				<label for="wpmem_product_expires"><?php _e( 'Expires (optional)', 'wp-members' ); ?></label>
				<span id="wpmem_product_expires_wrap">
					<label for="wpmem_product_number_of_periods" style="display:none;"><?php _e( 'Number', 'wp-members' ); ?></label>
					<?php $period = explode( '|', $product_expires ); ?>
					<input type="text" name="wpmem_product_number_of_periods" id="wpmem_product_number_of_periods" value="<?php echo esc_attr( $period[0] ); ?>" class="small-text" placeholder="<?php _e( 'Number', 'wp-members' ); ?>" style="width:66px;height:28px;vertical-align:middle;">
					<label for="wpmem_product_time_period" style="display:none;"><?php _e( 'Period', 'wp-members' ); ?></label>
					<?php echo wpmem_form_field( array( 'name'=>'wpmem_product_time_period', 'type'=>'select', 'value'=>$periods, 'compare'=>( ( isset( $period[1] ) ) ? $period[1] : '' ) ) ); ?>
					<br />

						<?php echo wpmem_form_field( array( 'name'=>'wpmem_product_no_gap', 'type'=>'checkbox', 'value'=>'1', 'compare'=>( ( isset( $product_no_gap ) ) && 1 == $product_no_gap ) ? $product_no_gap : '' ) ); ?>
						<label for="wpmem_product_no_gap"><?php esc_html_e( 'Use "no gap" renewal', 'wp-members' ); ?></label>

					<br />
						<?php echo wpmem_form_field( array( 'name'=>'wpmem_product_fixed_period', 'type'=>'checkbox', 'value'=>'1', 'compare'=>( false != $product_fixed_period ) ? 1 : '' ) ); ?>
						<label for="wpmem_product_fixed_period"><?php esc_html_e( 'Use a fixed period (such as Jan 1 - Dec 31, or Sept 1 - Aug 31)', 'wp-members' ); ?></label>
					<br />
					<div id="wpmem_product_fixed_period_select">
						<style>.ui-datepicker-year {
						  display: none;
						}</style>
						<?php
						if ( false !== $product_fixed_period ) {
							$period_parts = ( isset( $product_fixed_period ) ) ? explode( "-", $product_fixed_period ) : false;
							$period_start = ( $period_parts ) ? $period_parts[0] . '-' . $period_parts[1] : '';
							$period_end   = ( $period_parts ) ? $period_parts[2] . '-' . $period_parts[3] : '';
							$period_grace_num = ( $period_parts && isset( $period_parts[4] ) ) ? $period_parts[4] : '';
							$period_grace_per = ( $period_parts && isset( $period_parts[5] ) ) ? $period_parts[5] : '';
						} else {
							$period_start = $period_end = $period_grace_num = $period_grace_per = '';
						}
						?>
						<label for="wpmem_product_fixed_period_start"><?php esc_html_e( 'Period Start (dd-mm)', 'wp-members' ); ?></label><br />
						<input type="text" class="datepicker" name="wpmem_product_fixed_period_start" value="<?php echo $period_start; ?>" placeholder="<?php esc_html_e( 'Period Start (dd-mm)', 'wp-members' ); ?>" /><br />
						<label for="wpmem_product_fixed_period_end"><?php esc_html_e( 'Period End (dd-mm)', 'wp-members' ); ?></label><br />
						<input type="text" class="datepicker" name="wpmem_product_fixed_period_end" value="<?php echo $period_end; ?>" placeholder="<?php esc_html_e( 'Period End (dd-mm)', 'wp-members' ); ?>" />
						<script>
						jQuery(function() {
							jQuery( ".datepicker" ).datepicker({
								minDate: new Date((new Date()).getFullYear(), 0, 1),
								maxDate: new Date((new Date()).getFullYear(), 11, 31),
								hideIfNoPrevNext: true,
								dateFormat: 'dd-mm'
							});
						});
						</script>
						<br /><br />
						<span id="fixed_period_grace_period">
							<label style="margin-left: 24px;"><?php esc_html_e( "Fixed period grace period", 'wp-members' ); ?></label>

							<label for="wpmem_product_fixed_period_grace_number" style="display:none;"><?php esc_html_e( 'Number', 'wp-members' ); ?></label>
							<?php $period = explode( '|', $product_expires ); ?>
							<input type="text" name="wpmem_product_fixed_period_grace_number" id="wpmem_product_fixed_period_grace_number" value="<?php echo esc_attr( $period_grace_num ); ?>" class="small-text" placeholder="<?php _e( 'Number', 'wp-members' ); ?>" style="width:66px;margin-left:3px;margin-top:0px;">
							<label for="wpmem_product_fixed_period_grace_period" style="display:none;"><?php _e( 'Period', 'wp-members' ); ?></label>
							<?php echo wpmem_form_field( array( 'name'=>'wpmem_product_fixed_period_grace_period', 'type'=>'select', 'value'=>$periods, 'compare'=>( ( isset( $period_grace_per ) ) ? $period_grace_per : '' ) ) ); ?>
						</span>
						<br /><br />
						<span id="wpmem_product_fixed_period_explanation" class="description" style="margin-left: 24px;"><?php esc_html_e( "Grace period is the point at which expiration date is for following time period. For example, if user who register August 1st would be part of the following year's Sept 1 - Aug 31 membership, set this at 1 Month. Leave blank for no grace period.", 'wp-members' ); ?></span>
						<br />
					</div>
				</span>
			</p>
		<script>
			(function($) {
				$(document).ready(function() {
					$("#wpmem_product_role").<?php echo ( $show_role_detail ); ?>();
					$("#wpmem_product_expires_wrap").<?php echo ( $show_exp_detail ); ?>();
					$("#wpmem_product_fixed_period_select").<?php echo ( $show_exp_fixed ); ?>();
				});
				$(document).ready(function() {
				  $('#wpmem_product_role_required').on('change', function (){
					if ($(this).is(':checked')) {
						$('#wpmem_product_role').show();
						} else {
						$('#wpmem_product_role').hide();
						}
				  });
				 $('#wpmem_product_expires').on('change', function (){
					if ($(this).is(':checked')) {
						$('#wpmem_product_expires_wrap').show();
						} else {
						$('#wpmem_product_expires_wrap').hide();
						}
				  });
				 $('#wpmem_product_fixed_period').on('change', function (){
					if ($(this).is(':checked')) {
						$('#wpmem_product_fixed_period_select').show();
						} else {
						$('#wpmem_product_fixed_period_select').hide();
						}
				  });
				});
			})(jQuery);
		</script><?php
		
		/**
		 * Fires after membership product detail meta box.
		 *
		 * @since 3.3.5
		 */
		do_action( 'wpmem_membership_product_meta_after' );
	}

	/**
	 * Outputs HTML for CPT editor.
	 *
	 * @since 3.3.4
	 *
	 * @param  object $post
	 */
	function message_meta_box_detail( $post ) {
		$product_message = get_post_meta( $post->ID, 'wpmem_product_message', true );
		$message = ( $product_message ) ? $product_message : '';
		/**
		 * Fires before membership product message meta box.
		 *
		 * @since 3.3.5
		 */
		do_action( 'wpmem_membership_product_message_meta_before' );
		
		echo '<p>' . esc_html__( 'Restricted Message (displays when a user does not have access to a membership)', 'wp-members' ) . '</p>';
		
		$args = array(
			'media_buttons' => false,
			'textarea_rows' => 10,
		);

        wp_editor( $message, 'product_message', $args );
		
		/**
		 * Fires after membership product messate meta box.
		 *
		 * @since 3.3.5
		 */
		do_action( 'wpmem_membership_product_message_meta_after' );
	}
	
	/**
	 * Saves meta fields for CPT
	 *
	 * @since 3.2.0
	 * @since 3.3.4 Added message meta.
	 *
	 * @param  int $post_id
	 */
	function save_details( $post_id ) {

		global $wpmem;
		
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
		if ( ! isset( $_POST['wpmem_product_nonce'] ) || ! wp_verify_nonce( $_POST['wpmem_product_nonce'], '_wpmem_product_nonce' ) ) return;
		if ( ! current_user_can( 'edit_posts', $post_id ) ) return;
		
		$post = get_post( $post_id );
		
		$product_name = wpmem_get( 'wpmem_product_name', false );
		$product_name = ( $product_name ) ? $product_name : $post->post_name;
		update_post_meta( $post_id, 'wpmem_product_name', sanitize_text_field( $product_name ) );
		
		$product_default = wpmem_get( 'wpmem_product_default', false );
		update_post_meta( $post_id, 'wpmem_product_default', ( ( $product_default ) ? true : false ) );
		
		$role_required = wpmem_get( 'wpmem_product_role_required', false );
		if ( ! $role_required ) {
			update_post_meta( $post_id, 'wpmem_product_role', false );
		} else {
			update_post_meta( $post_id, 'wpmem_product_role', sanitize_text_field( wpmem_get( 'wpmem_product_role' ) ) );
		}
		
		$expires = wpmem_get( 'wpmem_product_expires', false );
		if ( ! $expires ) {
			update_post_meta( $post_id, 'wpmem_product_expires', false );
		} else {
			$number  = sanitize_text_field( wpmem_get( 'wpmem_product_number_of_periods' ) );
			$period  = sanitize_text_field( wpmem_get( 'wpmem_product_time_period' ) );
			$no_gap  = sanitize_text_field( wpmem_get( 'wpmem_product_no_gap' ) );
			$expires_array = array( $number . "|" . $period );
			update_post_meta( $post_id, 'wpmem_product_expires', $expires_array );
			if ( $no_gap ) {
				update_post_meta( $post_id, 'wpmem_product_no_gap', 1 );
			} else {
				delete_post_meta( $post_id, 'wpmem_product_no_gap' );
			}
			
			$fixed_period = sanitize_text_field( wpmem_get( 'wpmem_product_fixed_period' ) );
			if ( $fixed_period ) {
				
				// Start and end.
				$period_start = sanitize_text_field( wpmem_get( 'wpmem_product_fixed_period_start' ) );
				$period_end   = sanitize_text_field( wpmem_get( 'wpmem_product_fixed_period_end' ) );
				
				// Is there an entry grace period?
				$grace_number = sanitize_text_field( wpmem_get( 'wpmem_product_fixed_period_grace_number', false ) );
				$grace_period = sanitize_text_field( wpmem_get( 'wpmem_product_fixed_period_grace_period', false ) );
				$save_fixed_period = $period_start . '-' . $period_end;
				if ( $grace_number && $grace_period ) {
					$save_fixed_period .= '-' . $grace_number . '-' . $grace_period;
				}
				update_post_meta( $post_id, 'wpmem_product_fixed_period', $save_fixed_period );
			} else {
				delete_post_meta( $post_id, 'wpmem_product_fixed_period' );
			}
		}
		
		foreach( $this->get_post_types() as $key => $post_type ) {
			if ( false !== wpmem_get( 'wpmem_product_set_default_' . $key, false ) ) {
				update_post_meta( $post_id, 'wpmem_product_set_default_' . $key, 1 );
			} else {
				delete_post_meta( $post_id, 'wpmem_product_set_default_' . $key );
			}
		}

		$product_message =  wp_kses_post( wpmem_get( 'product_message', false ) );
		if ( false !== $product_message ) {
			if ( '' != $product_message ) {
				update_post_meta( $post_id, 'wpmem_product_message', $product_message );
			} else {
				delete_post_meta( $post_id, 'wpmem_product_message' );
			}
		}
		
		$child_access = intval( wpmem_get( 'wpmem_product_child_access', 0 ) );
		if ( 1 == $child_access ) {
			update_post_meta( $post_id, 'wpmem_product_child_access', $child_access );
		} else {
			delete_post_meta( $post_id, 'wpmem_product_child_access' );
		}

		// Anytime there's an update, update the global saved option.]
		$wpmem->membership->update_memberhips();
	}

	/**
	 * Add dropdown to post and page meta box for marking access by product..
	 *
	 * @since 3.2.0
	 * @since 3.3.3 Added defaults.
	 *
	 * @global object $pagenow
	 * @global object $wpmem
	 * @param  object $post
	 * @param  string $block
	 */
	function add_product_to_post( $post, $block ) {
		global $pagenow, $wpmem;
		
		// For checking default memberships.
		$is_new = ( 'post-new.php' == $pagenow ) ? true : false;
		
		$product  = $wpmem->membership->get_post_products( $post->ID ); //get_post_meta( $post->ID, $wpmem->membership->post_meta, true );
		$product  = ( $product ) ? $product : array();
		$values[] = esc_html__( 'None', 'wp-members' ) . '|';
		
		foreach ( wpmem_get_memberships() as $key => $value ) {
			
			if ( $is_new ) {
				if ( isset( $value[ 'set_default_' . $post->post_type ] ) && 1 == $value[ 'set_default_' . $post->post_type ] ) {
					$product[] = $key;
				}
			}
			
			$values[] = $value['title'] . '|' . $key;
		}
		
		echo wpmem_form_label( array( 
			'meta_key'=>$wpmem->membership->post_meta,
			'label'=>__( 'Restrict access by membership:', 'wp-members' ),
			'type'=> 'multiselect'
		) );
		echo "<br />";
		echo wpmem_form_field( array( 
			'name' => $wpmem->membership->post_meta, 
			'type' => 'multiselect',
			'value' => $values,
			'compare' => $product,
			'class' => 'wpmem-product-select2 populate placeholder',
		) );
	}

	/**
	 * Save custom post meta for access by product.
	 *
	 * @since 3.2.0
	 *
	 * @global object $wpmem
	 * @param  object $post
	 */
	function save_product_to_post( $post ) {
		global $wpmem;
		$products = wpmem_sanitize_array( wpmem_get( $wpmem->membership->post_meta ) );
		$products = ( $products ) ? $products : array();
		if ( empty( $products ) || ( 1 == count( $products ) && '' == $products[0] ) ) {
			delete_post_meta( $post->ID, $wpmem->membership->post_meta );
		} else {
			update_post_meta( $post->ID, $wpmem->membership->post_meta, $products );
		}
		foreach ( wpmem_get_memberships() as $key => $value ) {
			if ( in_array( $key, $products ) ) {
				update_post_meta( $post->ID, wpmem_get_membership_meta( $key ), 1 );
			} else {
				delete_post_meta( $post->ID, wpmem_get_membership_meta( $key ) );
			}
		}
	}
	
	/**
	 * Enqueue select2 JS.
	 *
	 * @since 3.2.3
	 */
	function enqueue_select2() { 
		$screen = get_current_screen();
		if ( $screen->base == 'post' && $screen->parent_base == 'edit' ) { ?>
			<script language="javascript">
				(function($) {
					$(document).ready(function() {
						$('.wpmem-product-select2').select2({width:"100%"});
					});
				})(jQuery);
			</script><?php
		}
	}
	
	/**
	 * Styles the width for membership post column.
	 *
	 * @since 3.4.0
	 */
	function post_columns_width() {
		if ( isset( $_REQUEST['post_type'] ) ) {
			echo '<style>.column-wpmem_product{ min-width:140px; width: 12%;}</style>';
		}
	}
	
	/**
	 * Add membership product column to post table.
	 *
	 * @since 3.2.4
	 *
	 * @global object $wpmem
	 * @param  array  $columns
	 * @return array  $columns
	 */
	function post_columns( $columns ){
		global $wpmem;
		$post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_text_field( $_REQUEST['post_type'] ) : 'post';
		if ( $post_type == 'page' || $post_type == 'post' || array_key_exists( $post_type, $wpmem->post_types ) ) {
			$product = array( 'wpmem_product' => esc_html__( 'Required Membership', 'wp-members' ) );
			$columns = wpmem_array_insert( $columns, $product, 'wpmem_block', 'before' );
		}
		return $columns;	
	}
	
	/**
	 * Membership product column data.
	 *
	 * @since 3.2.4
	 *
	 * @global object $wpmem
	 * @param  string $column_name
	 * @param  int    $post_id
	 */
	function post_columns_content( $column_name, $post_id ) {
		if ( 'wpmem_product' == $column_name ) {
			global $wpmem;
			$post_products = $wpmem->membership->get_post_products( $post_id );
			if ( $post_products ) {
				foreach ( $post_products as $meta ) {
					$display[] = wpmem_get_membership_name( $meta );
				}
				echo implode( ", ", $display );
			}
		}
	}
	
	/**
	 * Add membership product column to post table.
	 *
	 * @since 3.2.4
	 *
	 * @param  array $columns
	 * @return array $columns
	 */
	function user_columns( $columns ) {
		/**
		 * Filters the membership column name.
		 *
		 * @since 3.3.5
		 *
		 * @param string $column_name
		 */
		$columns['wpmem_product'] = apply_filters( 'wpmem_user_columns_membership_title', esc_html__( 'Membership', 'wp-members' ) );
		return $columns;	
	}
	
	/**
	 * Membership product column data.
	 *
	 * @since 3.2.4
	 *
	 * @global object $wpmem
	 * @param  string $column_name
	 * @param  int    $post_id
	 * @return array  $display
	 */
	function user_columns_content( $val, $column_name, $user_id ) {
		/**
		 * Filter the users > all users screen membership column default html.
		 * 
		 * @since 3.4.0
		 * 
		 * @param  array  $defaults
		 * @param  array  $val
		 * @param  array  $column_name
		 * @param  array  $user_id
		 */
		$defaults = apply_filters( 'wpmem_user_columns_membership_defaults', array(
			'item_wrap_before' => '<div class="wpmem-user-table-membership">',
			'item_wrap_after'  => '</div>',
		), $val, $column_name, $user_id );
		if ( 'wpmem_product' == $column_name ) {
			global $wpmem;
			$display = array();
			$user_products = wpmem_get_user_memberships( $user_id );
			if ( $user_products ) {
				foreach ( $user_products as $meta => $value ) {
					$expires = ( $user_products[ $meta ] > 1 ) ? '<br />' . esc_html__( 'expires:', 'wp-members' ) . ' ' . date_i18n( get_option( 'date_format' ), $user_products[ $meta ] ) : '';
					$display[] = $defaults['item_wrap_before'] . wpmem_get_membership_name( $meta ) . $expires . $defaults['item_wrap_after'];
				}
			}
			/**
			 * Filter the membership column value (per user).
			 *
			 * @since 3.3.5
			 *
			 * @param string $display
			 * @param array  $display_rows
			 * @param int    $user_id
			 * @param array  $user_products
			 */
			return apply_filters( 'wpmem_user_columns_membership_value', implode( " ", $display ), $display, $user_id, $user_products );
		}
		return $val;
	}

	/**
	 * Creates tab for user profile.
	 *
	 * @since 
	 *
	 * @param  array $tabs
	 */
	function user_profile_tabs( $tabs ) {
		$tabs['memberships'] = array(
			'tab' => esc_html__( 'Memberships', 'wp-members' ),
		);
		return $tabs;
	}
	
	/**
	 * Add user product access to user profile.
	 *
	 * @since 3.2.0
	 *
	 * @global string $pagenow
	 * @global object $wpmem
	 * @param  string $key
	 */
	public function user_profile_tab_content( $key ) { 
		// If product enabled
		if ( 'memberships' == $key ) {
			global $pagenow, $wpmem;
			
			/** This filter is documented in includes/class-wp-members-user-profile.php */
			$required_capability = apply_filters( 'wpmem_user_profile_caps', 'edit_users' );

			/*
			 * If an admin is editing their profile, we need their ID,
			 * otherwise, it's the user_id param from the URL. It's a 
			 * little more complicated than it sounds since you can't just
			 * check if the user is logged in, because the admin is always
			 * logged in when checking profiles.
			 */
			$user_id = ( 'profile' == $pagenow && current_user_can( $required_capability ) ) ? get_current_user_id() : sanitize_text_field( wpmem_get( 'user_id', false, 'get' ) );
			$user_products = wpmem_get_user_products( $user_id );
			echo '<h3>' . esc_html__( 'Membership Access', 'wp-members' ) . '</h3>';
			if ( ! empty( wpmem_get_memberships() ) ) {
				$expires_heading = "&nbsp;";
				foreach( wpmem_get_memberships() as $key => $value ) {
					$expires_heading = ( ! empty( $value['expires'] ) ) ? esc_html__( 'Expires', 'wp-members' ) : $expires_heading;
				}
				echo '<table>
					<tr>
						<th>' . esc_html__( 'Action',     'wp-members' ) . '</th>
						<th>' . esc_html__( 'Membership', 'wp-members' ) . '</th>
						<th>' . esc_html__( 'Enabled?',   'wp-members' ) . '</th>
						<th>' . $expires_heading . '</th>
					</tr>'; ?>	
				<?php

				foreach ( wpmem_get_memberships() as $key => $value ) {

					echo "<tr>";
					echo '<td style="padding:5px 5px;">
					<select name="_wpmem_membership_product[' . $key . ']">
						<option value="">----</option>
						<option value="enable">'  . esc_html__( 'Enable',  'wp-members' ) . '</option>
						<option value="disable">' . esc_html__( 'Disable', 'wp-members' ) . '</option>
						<option value="enable">'  . esc_html__( 'Update',  'wp-members' ) . '</option>
					</select></td><td style="padding:0px 0px;">' . $value['title'] . '</td>';

					// If user has date, display that; otherwise placeholder
					$date_value  = ( isset( $user_products[ $key ] ) && 1 != $user_products[ $key ] && 0 != $user_products[ $key ] && '' != $user_products[ $key ] ) ? date( 'Y-m-d', $user_products[ $key ] ) : "";
					$placeholder = ( ! isset( $user_products[ $key ] ) ) ? 'placeholder="' . esc_html__( 'Expiration date (optional)', 'wp-members' ) . '" ' : '';
					$product_date_field = ' <input type="text" name="_wpmem_membership_expiration_' . $key . '" value="' . $date_value . '" class="wpmem_datepicker" ' . $placeholder . ' />';

					if ( isset( $user_products[ $key ] ) ) {
						echo '<td align="center"><span id="wpmem_product_enabled" class="dashicons dashicons-yes"></span></td>';
						if ( $user_products[ $key ] != 1 ) {
							echo '<td>' . $product_date_field . '</td>';
						} else {
							echo '<td>&nbsp;</td>';
						}
					} else {
						if ( isset( $value['expires'] ) && ! empty( $value['expires'] ) ) {
							echo '<td><span id="wpmem_product_enabled" class="dashicons"></span></td>';
							echo '<td>' . $product_date_field . '</td>';
						} else {
							echo '<td>&nbsp;</td>';
						}
					}				
					echo '</tr>';
				}

					?></table>
				<script>
				jQuery(function() {
					jQuery( ".wpmem_datepicker" ).datepicker({
						dateFormat : "yy-mm-dd"
					});
				});
				</script>
				<?php
			} else {
				echo '<p>' . sprintf( esc_html__( 'No memberships have been created. %sCreate new memberships here%s', 'wp-members' ), '<a href="' . admin_url() . 'edit.php?post_type=wpmem_product">', '</a>' );
			}
		}
	}

	/** 
	 * Adds user view links to Users > All Users for each membership.
	 *
	 * @since 3.3.9
	 *
	 * @param  array   $views
	 * @param  string  $show  The slug of the current view.
	 * @return array   $views
	 */
	function user_views( $views, $show ) {

		global $wpmem;

		// Add a view for each membership
		foreach ( $wpmem->membership->membership_by_id as $membership_slug ) {
			$views = wpmem_add_user_view_link( 
				$views, 
				wpmem_get_membership_name( $membership_slug ), // $wpmem->membership->memberships[ $product_slug ]['title'],
				$membership_slug,
				wpmem_get_membership_meta( $membership_slug ), // "_wpmem_products_" . $product_slug,
				0,
				">"
			);
		}

		// Return the $views array with the added membership views.
		return $views;
	}

	/** 
	 * Filters the "where" query for user view links in Users > All Users for each membership.
	 *
	 * @since 3.3.9
	 *
	 * @param  string  $query_where
	 * @param  string  $show        The slug of the current view.
	 * @return string  $query_where
	 */
	function query_where( $query_where, $show ) {

		global $wpmem;

		// Check for membership views.
		foreach ( $wpmem->membership->membership_by_id as $membership_slug ) {
			// Check if we are viewing ($show) a membership ($prduct_slug).
			$query_where = wpmem_add_query_where( $query_where, $membership_slug, wpmem_get_membership_meta( $membership_slug ), 0, $compare = '>' );
		}

		return $query_where;
	}

	/**
	 * Refactors the saved membership option (settings) when memberships are deleted, trashed, or untrashed.
	 * 
	 * @since 3.5.2
	 */
	public function refactor_membership_option( $post_id, $second_arg ) {
		global $wpmem;
		if ( 'wpmem_product' != get_post_type( $post_id ) ) {
			$wpmem->membership->update_memberhips();
		}
	}
}