예제 #1
3
 /**
  * Process WooCommerce Memberships data to see if a member has any active
  * memberships or not. Cache the result in the Akses specific data base.
  *
  * @param int $userId User ID.
  */
 private static function process_wc_membership_member_status($userId)
 {
     $is_active = false;
     if (function_exists('wc_memberships')) {
         // check if the member has an active membership for any plan
         foreach (wc_memberships_get_membership_plans() as $plan) {
             if (wc_memberships_is_user_active_member($userId, $plan)) {
                 $is_active = true;
                 break;
             }
         }
     } else {
         error_log('Can not process membership statuses: WooCommerce Memberships is not installed.');
     }
     Akses_Membership::set_member_active($userId, $is_active);
 }
 /**
  * Add references
  *
  * @param array $references array of all myCRED references
  *
  * @return array $references array with our new references
  */
 public function mycred_wcm_register_references($references)
 {
     $references['mycred_woocommerce_memberships'] = __('Membership', $this->plugin_name);
     $membership_plans = wc_memberships_get_membership_plans();
     if (!empty($membership_plans)) {
         foreach ($membership_plans as $membership_plan) {
             $references['mycred_woocommerce_memberships_plan_' . str_replace('-', '_', $membership_plan->get_slug())] = sprintf(__('Membership: %s', $this->plugin_name), $membership_plan->get_name());
         }
     }
     return $references;
 }
 /**
  * Nonmember content shortcode
  *
  * @since 1.1.0
  * @param mixed $atts Shortcode attributes
  * @return string Shortcode result
  */
 public static function nonmember($atts, $content = null)
 {
     $plans = wc_memberships_get_membership_plans();
     $active_member = array();
     foreach ($plans as $plan) {
         $active = wc_memberships_is_user_active_member(get_current_user_id(), $plan);
         array_push($active_member, $active);
     }
     ob_start();
     if (!in_array(true, $active_member)) {
         echo do_shortcode($content);
     }
     return ob_get_clean();
 }
 /**
  * Construct
  *
  * @param array $hook_prefs configured preferences
  * @param string point type
  */
 function __construct($hook_prefs, $type = 'mycred_default')
 {
     if (!function_exists('wc_memberships_get_membership_plans')) {
         return;
     }
     $defaults = array();
     $this->membership_plans = wc_memberships_get_membership_plans();
     $this->textdomain = 'mycred-woocommerce-memberships';
     $defaults['any'] = array('creds' => 1, 'log' => '%plural% for any membership plan', 'limit' => '0/x');
     if (!empty($this->membership_plans)) {
         foreach ($this->membership_plans as $membership_plan) {
             $defaults[$this->sanitize_slug($membership_plan->get_slug())] = array('creds' => 1, 'log' => '%plural% for membership plan ' . $membership_plan->get_name(), 'limit' => '0/x');
         }
     }
     if (isset($hook_prefs['mycred_woocommerce_memberships'])) {
         $defaults = $hook_prefs['mycred_woocommerce_memberships'];
     }
     parent::__construct(array('id' => 'mycred_woocommerce_memberships', 'defaults' => $defaults), $hook_prefs, $type);
 }
    /**
     * Render groups import page
     *
     * @since 1.0.0
     */
    public function render_import_page()
    {
        // access_types check
        if (!current_user_can('manage_woocommerce')) {
            return;
        }
        if (!count($this->get_groups())) {
            _e("There are no groups to import.", WC_Memberships::TEXT_DOMAIN);
            return;
        }
        $membership_plans = wc_memberships_get_membership_plans();
        ?>

		<form method="post" id="import_groups">
			<?php 
        wp_nonce_field();
        ?>
			<div class="wrap">

				<h2><?php 
        _e("Import Members from Groups", WC_Memberships::TEXT_DOMAIN);
        ?>
</h2>
				<p><?php 
        _e("For each group, specify which plan should we import members to.", WC_Memberships::TEXT_DOMAIN);
        ?>
</p>

				<?php 
        foreach ($this->get_groups() as $group) {
            ?>

					<fieldset>
						<h4><?php 
            printf(__("Group: %s (ID #%d) "), $group->name, $group->group_id);
            ?>
</h4>

						<p><legend><?php 
            _e("What should be done with members of this group?", WC_Memberships::TEXT_DOMAIN);
            ?>
</legend></p>

						<ul style="list-style:none;">
							<li>
								<label>
									<input type="radio" id="import_groups_action_<?php 
            echo $group->group_id;
            ?>
_0" name="import_groups[<?php 
            echo $group->group_id;
            ?>
][action]" value="skip" class="js-import-action">
									<?php 
            _e("Skip", WC_Memberships::TEXT_DOMAIN);
            ?>
								</label>
							</li>

							<li>
								<label>
									<input type="radio" id="import_groups_action_<?php 
            echo $group->group_id;
            ?>
_1" name="import_groups[<?php 
            echo $group->group_id;
            ?>
][action]" value="import" class="js-import-action">
									<?php 
            _e("Import all members to:", WC_Memberships::TEXT_DOMAIN);
            ?>
								</label>

								<select name="import_groups[<?php 
            echo $group->group_id;
            ?>
][plan]" id="import_groups_plan_<?php 
            echo $group->group_id;
            ?>
" class="">
								<?php 
            foreach ($membership_plans as $plan) {
                ?>
									<option value="<?php 
                echo $plan->get_id();
                ?>
">
										<?php 
                echo $plan->get_name();
                ?>
									</option>
								<?php 
            }
            ?>
								</select>

							</li>
						</ul>
					</fieldset>

				<?php 
        }
        ?>

				<input type="hidden" name="action" value="wc_memberships_import_groups">
				<p class="submit">
					<input type="submit" name="submit" id="submit" class="button" value="<?php 
        _e("Confirm Import", WC_Memberships::TEXT_DOMAIN);
        ?>
" disabled="">
				</p>

			</div>
		</form>
		<?php 
        wc_enqueue_js("\n\t\t\tvar groups_count = " . count($this->get_groups()) . ";\n\t\t\tjQuery('#import_groups').on('change', 'input.js-import-action', function() {\n\t\t\t\tvar checked_count = jQuery('#import_groups').find('input.js-import-action:checked').length;\n\n\t\t\t\tif ( checked_count >= groups_count ) {\n\t\t\t\t\tjQuery('#submit').removeAttr('disabled');\n\t\t\t\t}\n\t\t\t});\n\t\t");
    }
    /**
     * Display the restrictions meta box
     *
     * @param WP_Post $post
     * @since 1.0.0
     */
    public function output(WP_Post $post)
    {
        // Prepare membership plan options
        $membership_plan_options = array();
        $membership_plans = wc_memberships_get_membership_plans(array('post_status' => array('publish', 'private', 'future', 'draft', 'pending', 'trash')));
        if (!empty($membership_plans)) {
            foreach ($membership_plans as $membership_plan) {
                $state = '';
                if ('publish' != $membership_plan->post->post_status) {
                    $state = ' ' . __('(inactive)', WC_Memberships::TEXT_DOMAIN);
                }
                $membership_plan_options[$membership_plan->get_id()] = $membership_plan->get_name() . $state;
            }
        }
        // Prepare period options
        $access_schedule_period_toggler_options = array('immediate' => __('immediately', WC_Memberships::TEXT_DOMAIN), 'specific' => __('specify a time', WC_Memberships::TEXT_DOMAIN));
        $period_options = array('days' => __('day(s)', WC_Memberships::TEXT_DOMAIN), 'weeks' => __('week(s)', WC_Memberships::TEXT_DOMAIN), 'months' => __('month(s)', WC_Memberships::TEXT_DOMAIN), 'years' => __('year(s)', WC_Memberships::TEXT_DOMAIN));
        // Get applied restriction rules
        $content_restriction_rules = wc_memberships()->rules->get_rules(array('rule_type' => 'content_restriction', 'object_id' => $post->ID, 'content_type' => 'post_type', 'content_type_name' => $post->post_type, 'exclude_inherited' => false, 'plan_status' => 'any'));
        // Add empty option to create a HTML template for new rules
        $membership_plan_ids = array_keys($membership_plan_options);
        $content_restriction_rules['__INDEX__'] = new WC_Memberships_Membership_Plan_Rule(array('rule_type' => 'content_restriction', 'object_ids' => array($post->ID), 'id' => '', 'membership_plan_id' => array_shift($membership_plan_ids), 'access_schedule' => 'immediate', 'access_type' => ''));
        ?>
		<h4><?php 
        esc_html_e('Content Restriction');
        ?>
</h4>

		<?php 
        woocommerce_wp_checkbox(array('id' => '_wc_memberships_force_public', 'class' => 'js-toggle-rules', 'label' => __('Disable restrictions', WC_Memberships::TEXT_DOMAIN), 'description' => __('Check this box if you want to force the content to be public regardless of any restriction rules that may apply now or in the future.', WC_Memberships::TEXT_DOMAIN)));
        ?>

		<div class="js-restrictions <?php 
        if (get_post_meta($post->ID, '_wc_memberships_force_public', true) == 'yes') {
            ?>
hide<?php 
        }
        ?>
">

			<?php 
        require wc_memberships()->get_plugin_path() . '/includes/admin/meta-boxes/views/html-content-restriction-rules.php';
        ?>

			<?php 
        if (!empty($membership_plans)) {
            ?>
				<p>
					<em><?php 
            esc_html_e('Need to add or edit a plan?', WC_Memberships::TEXT_DOMAIN);
            ?>
</em> <a target="_blank" href="<?php 
            echo admin_url('edit.php?post_type=wc_membership_plan');
            ?>
"><?php 
            esc_html_e('Manage Membership Plans', WC_Memberships::TEXT_DOMAIN);
            ?>
</a>
				</p>
			<?php 
        }
        ?>

			<h4><?php 
        esc_html_e('Custom Restriction Message');
        ?>
</h4>

			<?php 
        woocommerce_wp_checkbox(array('id' => '_wc_memberships_use_custom_content_restricted_message', 'class' => 'js-toggle-custom-message', 'label' => __('Use custom message', WC_Memberships::TEXT_DOMAIN), 'description' => __('Check this box if you want to customize the content restricted message for this content.', WC_Memberships::TEXT_DOMAIN)));
        ?>

			<div class="js-custom-message-editor-container <?php 
        if (get_post_meta($post->ID, '_wc_memberships_use_custom_content_restricted_message', true) !== 'yes') {
            ?>
hide<?php 
        }
        ?>
">
			<?php 
        $message = get_post_meta($post->ID, '_wc_memberships_content_restricted_message', true);
        echo '<p>' . sprintf(__('<code>%s</code> automatically inserts the product(s) needed to gain access. <code>%s</code> inserts the URL to my account page. HTML is allowed.', WC_Memberships::TEXT_DOMAIN), '{products}', '{login_url}') . '</p>';
        wp_editor($message, '_wc_memberships_content_restricted_message', array('textarea_rows' => 5, 'teeny' => true));
        ?>
			</div>

		</div>

		<?php 
    }
 /**
  * Prevent adding a user membership if user is already a member of all plans
  *
  * @since 1.0.0
  */
 public function maybe_prevent_adding_user_membership()
 {
     global $pagenow;
     if ('post-new.php' === $pagenow) {
         // Get user details
         $user_id = isset($_GET['user']) ? $_GET['user'] : null;
         $user = $user_id ? get_userdata($user_id) : null;
         if (!$user_id || !$user) {
             wc_memberships()->admin->message_handler->add_error(__('Please select a user to add as a member.', WC_Memberships::TEXT_DOMAIN));
             wp_redirect(wp_get_referer());
             exit;
         }
         // All the user memberships
         $user_memberships = wc_memberships_get_user_memberships($user->ID);
         $membership_plans = wc_memberships_get_membership_plans(array('post_status' => array('publish', 'private', 'future', 'draft', 'pending', 'trash')));
         if (count($user_memberships) == count($membership_plans)) {
             wc_memberships()->admin->message_handler->add_message(__('This user is already a member of every plan.', WC_Memberships::TEXT_DOMAIN));
             wp_redirect(wp_get_referer());
             exit;
         }
     }
 }
    /**
     * Display the membership data meta box
     *
     * @param WP_Post $post
     * @since 1.0.0
     */
    public function output(WP_Post $post)
    {
        global $pagenow;
        // Prepare variables
        $user_membership = wc_memberships_get_user_membership($post->ID);
        $user_id = 'post.php' == $pagenow ? $user_membership->get_user_id() : (isset($_GET['user']) ? $_GET['user'] : null);
        // Bail out if no user ID
        if (!$user_id) {
            return;
        }
        // Get user details
        $user = get_userdata($user_id);
        // All the user memberships
        $user_memberships = wc_memberships_get_user_memberships($user->ID);
        // Prepare options
        $status_options = array();
        foreach (wc_memberships_get_user_membership_statuses() as $status => $labels) {
            $status_options[$status] = $labels['label'];
        }
        /**
         * Filter status options that appear in the edit user membership screen
         *
         * @since 1.0.0
         * @param array $options Associative array of option value => label pairs
         * @param int $user_membership_id User membership ID
         */
        $status_options = apply_filters('wc_memberships_edit_user_membership_screen_status_options', $status_options, $post->ID);
        // prepare membership plan options
        $membership_plan_options = array();
        $membership_plans = wc_memberships_get_membership_plans(array('post_status' => array('publish', 'private', 'future', 'draft', 'pending', 'trash')));
        if (!empty($membership_plans)) {
            foreach ($membership_plans as $membership_plan) {
                $exists = false;
                // Each user can only have 1 membership per plan.
                // Check if user already has a membership for this plan.
                if (!empty($user_memberships)) {
                    foreach ($user_memberships as $membership) {
                        if ($membership->get_plan_id() == $membership_plan->get_id()) {
                            $exists = true;
                            break;
                        }
                    }
                }
                // Only add plan to options if user is not a member of this plan or
                // if the current membership has this plan.
                // Todo: instead of removing, disable the option once
                // https://github.com/woothemes/woocommerce/pull/8024 lands in stable
                if (!$exists || $user_membership->get_plan_id() == $membership_plan->get_id()) {
                    $membership_plan_options[$membership_plan->get_id()] = $membership_plan->get_name();
                }
            }
        }
        $current_membership = null;
        $order = $user_membership->get_order();
        $product = $user_membership->get_product();
        ?>

		<h3 class="membership-plans">
			<ul class="sections">
			<?php 
        if (!empty($user_memberships)) {
            foreach ($user_memberships as $membership) {
                ?>
				<li <?php 
                if ($membership->get_id() == $post->ID) {
                    $current_membership = $membership->get_id();
                    ?>
class="active"<?php 
                }
                ?>
><a href="<?php 
                echo esc_url(get_edit_post_link($membership->get_id()));
                ?>
"><?php 
                echo wp_kses_post($membership->get_plan()->get_name());
                ?>
</a></li>
			<?php 
            }
        }
        ?>
			<?php 
        if (count($user_memberships) != count($membership_plans)) {
            ?>
				<li <?php 
            if (!$current_membership) {
                ?>
class="active"<?php 
            }
            ?>
><a href="<?php 
            echo admin_url('post-new.php?post_type=wc_user_membership&user='******'Add a plan...', WC_Memberships::TEXT_DOMAIN);
            ?>
</a></li>
			<?php 
        }
        ?>
			</ul>
		</h3>

		<div class="plan-details">
			<h4><?php 
        esc_html_e('Membership Details', WC_Memberships::TEXT_DOMAIN);
        ?>
</h4>

			<div class="woocommerce_options_panel">

				<?php 
        /**
         * Fires before the membership details in edit user membership screen
         *
         * @since 1.0.0
         * @param WC_Memberships_User_Membership
         */
        do_action('wc_memberships_before_user_membership_details', $user_membership);
        ?>

				<?php 
        woocommerce_wp_select(array('id' => 'post_parent', 'label' => __('Plan:', WC_Memberships::TEXT_DOMAIN), 'options' => $membership_plan_options, 'value' => $user_membership->get_plan_id(), 'class' => 'wide', 'wrapper_class' => 'js-membership-plan'));
        ?>

				<?php 
        woocommerce_wp_select(array('id' => 'post_status', 'label' => __('Status:', WC_Memberships::TEXT_DOMAIN), 'options' => $status_options, 'value' => 'wcm-' . $user_membership->get_status(), 'class' => 'wide'));
        ?>

				<?php 
        woocommerce_wp_text_input(array('id' => '_start_date', 'label' => __('Member since:', WC_Memberships::TEXT_DOMAIN), 'class' => 'js-user-membership-date', 'description' => __('YYYY-MM-DD', WC_Memberships::TEXT_DOMAIN), 'value' => 'post.php' == $pagenow ? $user_membership->get_start_date('Y-m-d') : date('Y-m-d')));
        ?>

				<?php 
        woocommerce_wp_text_input(array('id' => '_end_date', 'label' => __('Expires:', WC_Memberships::TEXT_DOMAIN), 'class' => 'js-user-membership-date', 'description' => __('YYYY-MM-DD', WC_Memberships::TEXT_DOMAIN), 'value' => $user_membership->get_end_date('Y-m-d', false)));
        ?>

				<?php 
        if ($user_membership->get_paused_date()) {
            ?>
					<p class="form-field"><span class="description"><?php 
            printf(esc_html__('Paused since %s', WC_Memberships::TEXT_DOMAIN), date_i18n(get_option('date_format'), $user_membership->get_paused_date('timestamp')));
            ?>
</span></p>
				<?php 
        }
        ?>

				<?php 
        /**
         * Fires after the membership details in edit user membership screen
         *
         * @since 1.0.0
         * @param WC_Memberships_User_Membership
         */
        do_action('wc_memberships_after_user_membership_details', $user_membership);
        ?>

			</div>

		</div>

		<div class="billing-details">
			<h4><?php 
        esc_html_e('Billing Details', WC_Memberships::TEXT_DOMAIN);
        ?>
</h4>

			<?php 
        /**
         * Fires before the billing details in edit user membership screen
         *
         * @since 1.0.0
         * @param WC_Memberships_User_Membership
         */
        do_action('wc_memberships_before_user_membership_billing_details', $user_membership);
        ?>

			<?php 
        if ($order) {
            ?>
				<table>
					<tr>
						<td><?php 
            esc_html_e('Purchased in:', WC_Memberships::TEXT_DOMAIN);
            ?>
</td>
						<td><a href="<?php 
            echo esc_url(get_edit_post_link($order->id));
            ?>
"><?php 
            printf(esc_html__('Order %s', WC_Memberships::TEXT_DOMAIN), $order->get_order_number());
            ?>
</a></td>
					</tr>
					<tr>
						<td><?php 
            esc_html_e('Order Date:', WC_Memberships::TEXT_DOMAIN);
            ?>
</td>
						<td><?php 
            echo date_i18n(get_option('date_format'), strtotime($order->order_date));
            ?>
</td>
					</tr>
					<tr>
						<td><?php 
            esc_html_e('Order Total:', WC_Memberships::TEXT_DOMAIN);
            ?>
</td>
						<td><?php 
            echo $order->get_formatted_order_total();
            ?>
</td>
					</tr>
				</table>
			<?php 
        } else {
            ?>
				<p><?php 
            esc_html_e('No billing details - this membership was created manually.', WC_Memberships::TEXT_DOMAIN);
            ?>
</p>
			<?php 
        }
        ?>

			<?php 
        /**
         * Fires after the billing details in edit user membership screen
         *
         * @since 1.0.0
         * @param WC_Memberships_User_Membership
         */
        do_action('wc_memberships_after_user_membership_billing_details', $user_membership);
        ?>

		</div>

		<div class="clear"></div>

		<ul class="user_membership_actions submitbox">

			<?php 
        /**
         * Fires at the start of the user membership actions meta box
         *
         * @since 1.0.0
         * @param int $post_id The post id of the wc_user_membership post
         */
        do_action('wc_memberships_user_membership_actions_start', $post->ID);
        ?>

			<li class="wide">
				<div id="delete-action">
					<?php 
        if (current_user_can("delete_post", $post->ID)) {
            ?>
<a class="submitdelete deletion" href="<?php 
            echo esc_url(get_delete_post_link($post->ID, '', true));
            ?>
"><?php 
            esc_html_e('Delete User Membership', WC_Memberships::TEXT_DOMAIN);
            ?>
</a><?php 
        }
        ?>
				</div>

				<input type="submit" class="button save_user_membership save_action button-primary tips" value="<?php 
        esc_attr_e('Save Membership', WC_Memberships::TEXT_DOMAIN);
        ?>
" data-tip="<?php 
        esc_attr_e('Save/update the membership', WC_Memberships::TEXT_DOMAIN);
        ?>
" />
			</li>

			<?php 
        /**
         * Fires at the end of the user membership actions meta box
         *
         * @since 1.0.0
         * @param int $post_id The post id of the wc_user_membership post
         */
        do_action('wc_memberships_user_membership_actions_end', $post->ID);
        ?>

		</ul>

		<?php 
        // Render JS to have the admin confirm they really do indeed want to permanently
        // delete a member
        wc_enqueue_js("\n\t\t\tjQuery( '.user_membership_actions .submitdelete' ).click( function( e ) {\n\t\t\t\treturn confirm( '" . esc_html__('Are you sure you want to permanently delete this membership?', WC_Memberships::TEXT_DOMAIN) . "' );\n\t\t\t} );\n\t\t");
    }
 /**
  * Duplicate memberships data for a product
  *
  * @since 1.3.0
  * @param int $new_id
  * @param object $post
  */
 public function duplicate_product_memberships_data($new_id, $post)
 {
     // Get product restriction rules
     $product_restriction_rules = wc_memberships()->rules->get_rules(array('rule_type' => 'product_restriction', 'object_id' => $post->ID, 'content_type' => 'post_type', 'content_type_name' => $post->post_type, 'exclude_inherited' => true, 'plan_status' => 'any'));
     // Get purchasing discount rules
     $purchasing_discount_rules = wc_memberships()->rules->get_rules(array('rule_type' => 'purchasing_discount', 'object_id' => $post->ID, 'content_type' => 'post_type', 'content_type_name' => $post->post_type, 'exclude_inherited' => true, 'plan_status' => 'any'));
     $product_rules = array_merge($product_restriction_rules, $purchasing_discount_rules);
     // Duplicate rules
     if (!empty($product_rules)) {
         $all_rules = get_option('wc_memberships_rules');
         foreach ($product_rules as $rule) {
             $new_rule = $rule->get_raw_data();
             $new_rule['object_ids'] = array($new_id);
             $all_rules[] = $new_rule;
         }
         update_option('wc_memberships_rules', $all_rules);
     }
     // Duplicate custom messages
     foreach (array('product_viewing_restricted', 'product_purchasing_restricted') as $message_type) {
         $message = get_post_meta($post->ID, "_wc_memberships_{$message_type}_message", true);
         $use_custom = get_post_meta($post->ID, "_wc_memberships_use_custom_{$message_type}_message", true);
         if ($message) {
             update_post_meta($new_id, "_wc_memberships_{$message_type}_message", $message);
         }
         if ($use_custom) {
             update_post_meta($new_id, "_wc_memberships_use_custom_{$message_type}_message", $use_custom);
         }
     }
     // Duplicate 'grants access to'
     foreach (wc_memberships_get_membership_plans() as $plan) {
         if ($plan->has_product($post->ID)) {
             $product_ids = get_post_meta($plan->get_id(), '_product_ids', true);
             $product_ids[] = $new_id;
             update_post_meta($plan->get_id(), '_product_ids', $product_ids);
         }
     }
     // Duplicate other settings
     update_post_meta($new_id, '_wc_memberships_force_public', get_post_meta($post->ID, '_wc_memberships_force_public', true));
 }
/**
* Check if current page is restricted (works with BuddyPress who doesn't have any page/post id)
*
* @param string|int|array $plans Optional. The membership plan or plans to check against.
*                                Accepts a plan slug, ID, or an array of slugs or IDs. Default: all plans.
* @param string $delay
* @param bool $exclude_trial
*/
function kmpl_wc_memberships_has_access_to_restricted_page($plans = null, $delay = null, $exclude_trial = false)
{
    $has_access = false;
    $member_since = null;
    $access_time = null;
    // grant access to super users
    if (is_user_logged_in() && current_user_can('wc_memberships_access_all_restricted_content')) {
        $has_access = true;
    }
    // Convert to an array in all cases
    $plans = (array) $plans;
    // default to use all plans if no plan is specified
    if (empty($plans)) {
        $plans = wc_memberships_get_membership_plans();
    }
    foreach ($plans as $plan_id_or_slug) {
        $membership_plan = wc_memberships_get_membership_plan($plan_id_or_slug);
        if ($membership_plan && wc_memberships_is_user_active_member(get_current_user_id(), $membership_plan->get_id())) {
            $has_access = true;
            if (!$delay && !$exclude_trial) {
                break;
            }
            // Determine the earliest membership for the user
            $user_membership = wc_memberships()->user_memberships->get_user_membership(get_current_user_id(), $membership_plan->get_id());
            // Create a pseudo-rule to help applying filters
            $rule = new WC_Memberships_Membership_Plan_Rule(array('access_schedule_exclude_trial' => $exclude_trial ? 'yes' : 'no'));
            /** This filter is documented in includes/class-wc-memberships-capabilities.php **/
            $from_time = apply_filters('wc_memberships_access_from_time', $user_membership->get_start_date('timestamp'), $rule, $user_membership);
            // If there is no time to calculate the access time from, simply
            // use the current time as access start time
            if (!$from_time) {
                $from_time = current_time('timestamp', true);
            }
            if (is_null($member_since) || $from_time < $member_since) {
                $member_since = $from_time;
            }
        }
    }
    // Add delay
    if ($has_access && ($delay || $exclude_trial) && $member_since) {
        $access_time = $member_since;
        // Determine access time
        if (strpos($delay, 'month') !== false) {
            $parts = explode(' ', $delay);
            $amount = isset($parts[1]) ? (int) $parts[0] : '';
            $access_time = wc_memberships()->add_months($member_since, $amount);
        } else {
            if ($delay) {
                $access_time = strtotime($delay, $member_since);
            }
        }
        // Output or show delayed access message
        if ($access_time <= current_time('timestamp', true)) {
            $has_access = true;
        } else {
            $has_access = false;
            $message = __('This content is part of your membership, but not yet! You will gain access on {date}', 'woocommerce-memberships');
            // Apply the deprecated filter
            if (has_filter('get_content_delayed_message')) {
                /** This filter is documented in includes/frontend/class-wc-memberships-frontend.php **/
                $message = apply_filters('get_content_delayed_message', $message, null, $access_time);
                // Notify developers that this filter is deprecated
                _deprecated_function('The get_content_delayed_message filter', '1.3.1', 'wc_memberships_get_content_delayed_message');
            }
            /** This filter is documented in includes/frontend/class-wc-memberships-frontend.php **/
            $message = apply_filters('wc_memberships_get_content_delayed_message', $message, null, $access_time);
            $message = str_replace('{date}', date_i18n(wc_date_format(), $access_time), $message);
            $output = '<div class="wc-memberships-content-delayed-message">' . $message . '</div>';
            echo $output;
        }
    }
    return $has_access;
}
    /**
     * Display the memberships meta box
     *
     * @param WP_Post $post
     * @since 1.0.0
     */
    public function output(WP_Post $post)
    {
        $product = wc_get_product($post);
        $grant_access_to_plans = $this->get_product_membership_plans($post->ID);
        // Prepare membership plan options
        $membership_plan_options = array();
        $membership_plans = wc_memberships_get_membership_plans(array('post_status' => array('publish', 'private', 'future', 'draft', 'pending', 'trash')));
        if (!empty($membership_plans)) {
            foreach ($membership_plans as $membership_plan) {
                $state = '';
                if ('publish' != $membership_plan->post->post_status) {
                    $state = ' ' . __('(inactive)', WC_Memberships::TEXT_DOMAIN);
                }
                $membership_plan_options[$membership_plan->get_id()] = $membership_plan->get_name() . $state;
            }
        }
        // Prepare access_type options for product restriction rules
        $product_restriction_access_type_options = array('view' => __('view', WC_Memberships::TEXT_DOMAIN), 'purchase' => __('purchase', WC_Memberships::TEXT_DOMAIN));
        // Prepare period options
        $access_schedule_period_toggler_options = array('immediate' => __('immediately', WC_Memberships::TEXT_DOMAIN), 'specific' => __('specify a time', WC_Memberships::TEXT_DOMAIN));
        $period_options = array('days' => __('day(s)', WC_Memberships::TEXT_DOMAIN), 'weeks' => __('week(s)', WC_Memberships::TEXT_DOMAIN), 'months' => __('month(s)', WC_Memberships::TEXT_DOMAIN), 'years' => __('year(s)', WC_Memberships::TEXT_DOMAIN));
        // Get applied restriction rules
        $product_restriction_rules = wc_memberships()->rules->get_rules(array('rule_type' => 'product_restriction', 'object_id' => $post->ID, 'content_type' => 'post_type', 'content_type_name' => $post->post_type, 'exclude_inherited' => false, 'plan_status' => 'any'));
        // Add empty option to create a HTML template for new rules
        $membership_plan_ids = array_keys($membership_plan_options);
        $product_restriction_rules['__INDEX__'] = new WC_Memberships_Membership_Plan_Rule(array('rule_type' => 'product_restriction', 'object_ids' => array($post->ID), 'id' => '', 'membership_plan_id' => array_shift($membership_plan_ids), 'access_schedule' => 'immediate', 'access_type' => ''));
        // Get applied restriction rules
        $purchasing_discount_rules = wc_memberships()->rules->get_rules(array('rule_type' => 'purchasing_discount', 'object_id' => $post->ID, 'content_type' => 'post_type', 'content_type_name' => $post->post_type, 'exclude_inherited' => false, 'plan_status' => 'any'));
        // Add empty option to create a HTML template for new rules
        $purchasing_discount_rules['__INDEX__'] = new WC_Memberships_Membership_Plan_Rule(array('rule_type' => 'purchasing_discount', 'object_ids' => array($post->ID), 'id' => '', 'membership_plan_id' => '', 'discount_type' => '', 'discount_amount' => '', 'active' => ''));
        // prepare product restriction access_type options
        $purchasing_discount_type_options = array('percentage' => '%', 'amount' => '$');
        ?>

		<p class="grouped-notice <?php 
        if (!$product->is_type('grouped')) {
            ?>
hide<?php 
        }
        ?>
">
			<?php 
        esc_html_e("Memberships do not support grouped products.", WC_Memberships::TEXT_DOMAIN);
        ?>
		</p>

		<div class="panel-wrap wc-memberships-data <?php 
        if ($product->is_type('grouped')) {
            ?>
hide<?php 
        }
        ?>
">

			<?php 
        if (!SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3()) {
            ?>
				<div class="wc-tabs-back"></div>
			<?php 
        }
        ?>

			<ul class="memberships_data_tabs wc-tabs">
				<?php 
        /**
         * Filter product memberships data tabs
         *
         * @since 1.0.0
         * @param array $tabs Associative array of memberships data tabs
         */
        $memberships_data_tabs = apply_filters('wc_memberships_product_data_tabs', array('restrict_product' => array('label' => __('Restrict Content', WC_Memberships::TEXT_DOMAIN), 'class' => array('active'), 'target' => 'memberships-data-restrict-product'), 'grant_access' => array('label' => __('Grant Access', WC_Memberships::TEXT_DOMAIN), 'target' => 'memberships-data-grant-access'), 'purchasing_discounts' => array('label' => __('Discounts', WC_Memberships::TEXT_DOMAIN), 'target' => 'memberships-data-purchasing-discounts')));
        foreach ($memberships_data_tabs as $key => $tab) {
            $class = isset($tab['class']) ? $tab['class'] : array();
            ?>
<li class="<?php 
            echo sanitize_html_class($key);
            ?>
_options <?php 
            echo sanitize_html_class($key);
            ?>
_tab <?php 
            echo implode(' ', array_map('sanitize_html_class', $class));
            ?>
">
							<a href="#<?php 
            echo esc_attr($tab['target']);
            ?>
"><?php 
            echo esc_html($tab['label']);
            ?>
</a>
						</li><?php 
        }
        /**
         * Fires after the product memberships data write panel tabs are displayed
         *
         * @since 1.0.0
         */
        do_action('wc_memberships_data_product_write_panel_tabs');
        ?>
			</ul>


			<div id="memberships-data-restrict-product" class="panel woocommerce_options_panel">

				<p class="variable-notice <?php 
        if (!$product->is_type('variable')) {
            ?>
hide<?php 
        }
        ?>
">
					<?php 
        esc_html_e('These rules affect all variations. For variation-level control use the membership plan screen.', WC_Memberships::TEXT_DOMAIN);
        ?>
				</p>

				<?php 
        woocommerce_wp_checkbox(array('id' => '_wc_memberships_force_public', 'class' => 'js-toggle-rules', 'label' => __('Disable restrictions', WC_Memberships::TEXT_DOMAIN), 'description' => __('Check this box if you want to force this product to be public regardless of any restriction rules that may apply now or in the future.', WC_Memberships::TEXT_DOMAIN)));
        ?>

				<div class="js-restrictions <?php 
        if (get_post_meta($post->ID, '_wc_memberships_force_public', true) == 'yes') {
            ?>
hide<?php 
        }
        ?>
">

					<div class="options_group">
						<div class="table-wrap">
							<?php 
        require wc_memberships()->get_plugin_path() . '/includes/admin/meta-boxes/views/html-product-restriction-rules.php';
        ?>
						</div>
					</div>

					<?php 
        if (!empty($membership_plans)) {
            ?>
						<p>
							<em><?php 
            esc_html_e('Need to add or edit a plan?', WC_Memberships::TEXT_DOMAIN);
            ?>
</em> <a target="_blank" href="<?php 
            echo admin_url('edit.php?post_type=wc_membership_plan');
            ?>
"><?php 
            esc_html_e('Manage Membership Plans', WC_Memberships::TEXT_DOMAIN);
            ?>
</a>
						</p>
					<?php 
        }
        ?>

					<div class="options_group">

						<?php 
        woocommerce_wp_checkbox(array('id' => '_wc_memberships_use_custom_product_viewing_restricted_message', 'class' => 'js-toggle-custom-message', 'label' => __('Use custom message', WC_Memberships::TEXT_DOMAIN), 'description' => __('Check this box if you want to customize the <strong>viewing restricted message</strong> for this product.', WC_Memberships::TEXT_DOMAIN)));
        ?>

						<div class="js-custom-message-editor-container <?php 
        if (get_post_meta($post->ID, '_wc_memberships_use_custom_product_viewing_restricted_message', true) !== 'yes') {
            ?>
hide<?php 
        }
        ?>
">
						<?php 
        $message = get_post_meta($post->ID, '_wc_memberships_product_viewing_restricted_message', true);
        echo '<p>' . sprintf(__('<code>%s</code> automatically inserts the product(s) needed to gain access. <code>%s</code> inserts the URL to my account page. HTML is allowed.', WC_Memberships::TEXT_DOMAIN), '{products}', '{login_url}') . '</p>';
        wp_editor($message, '_wc_memberships_product_viewing_restricted_message', array('textarea_rows' => 5, 'teeny' => true));
        ?>
						</div>

					</div>

					<div class="options_group">

						<?php 
        woocommerce_wp_checkbox(array('id' => '_wc_memberships_use_custom_product_purchasing_restricted_message', 'class' => 'js-toggle-custom-message', 'label' => __('Use custom message', WC_Memberships::TEXT_DOMAIN), 'description' => __('Check this box if you want to customize the <strong>purchasing restricted message</strong> for this product.', WC_Memberships::TEXT_DOMAIN)));
        ?>

						<div class="js-custom-message-editor-container <?php 
        if (get_post_meta($post->ID, '_wc_memberships_use_custom_product_purchasing_restricted_message', true) !== 'yes') {
            ?>
hide<?php 
        }
        ?>
">
						<?php 
        $message = get_post_meta($post->ID, '_wc_memberships_product_purchasing_restricted_message', true);
        echo '<p>' . sprintf(__('<code>%s</code> automatically inserts the product(s) needed to gain access. <code>%s</code> inserts the URL to my account page. HTML is allowed.', WC_Memberships::TEXT_DOMAIN), '{products}', '{login_url}') . '</p>';
        wp_editor($message, '_wc_memberships_product_purchasing_restricted_message', array('textarea_rows' => 5, 'teeny' => true));
        ?>
						</div>

					</div>
				</div>

				<?php 
        /**
         * Fires after the product memberships data product restriction panel is displayed
         *
         * @since 1.0.0
         */
        do_action('wc_memberships_data_options_restrict_product');
        ?>
			</div><!-- //#memberships-data-restrict-products -->


			<div id="memberships-data-grant-access" class="panel woocommerce_options_panel">

				<p class="variable-notice <?php 
        if (!$product->is_type('variable')) {
            ?>
hide<?php 
        }
        ?>
">
					<?php 
        _e("These settings affect all variations. For variation-level control use the membership plan screen.", WC_Memberships::TEXT_DOMAIN);
        ?>
				</p>

				<!-- Plans that this product grants access to -->
				<div class="options_group">

				<?php 
        if (empty($membership_plans)) {
            ?>
					<p>
						<?php 
            esc_html_e('To grant membership access, please', WC_Memberships::TEXT_DOMAIN);
            ?>
 <a target="_blank" href="<?php 
            echo admin_url('post-new.php?post_type=wc_membership_plan');
            ?>
"><?php 
            esc_html_e('Add a Membership Plan', WC_Memberships::TEXT_DOMAIN);
            ?>
</a>.
					</p>
				<?php 
        } else {
            ?>

					<p class="form-field"><label for="_wc_memberships_membership_plan_ids"><?php 
            esc_html_e('Purchasing grants access to', WC_Memberships::TEXT_DOMAIN);
            ?>
</label>

					<?php 
            if (SV_WC_Plugin_Compatibility::is_wc_version_gte_2_3()) {
                ?>
						<input type="hidden" class="js-membership-plan-ids" style="width: 50%;" id="_wc_memberships_membership_plan_ids" name="_wc_memberships_membership_plan_ids" data-placeholder="<?php 
                esc_attr_e('Search for a membership plan&hellip;', WC_Memberships::TEXT_DOMAIN);
                ?>
" data-action="wc_memberships_search_membership_plans" data-multiple="true" data-selected="<?php 
                $json_ids = array();
                if (!empty($grant_access_to_plans)) {
                    foreach ($grant_access_to_plans as $plan) {
                        if (is_object($plan)) {
                            $json_ids[$plan->get_id()] = wp_kses_post(html_entity_decode($plan->get_name()));
                        }
                    }
                }
                echo esc_attr(wc_memberships()->wp_json_encode($json_ids));
                ?>
" value="<?php 
                echo esc_attr(implode(',', array_keys($json_ids)));
                ?>
" />

					<?php 
            } else {
                ?>
						<select name="_wc_memberships_membership_plan_ids[]" class="js-membership-plan-ids" id="_wc_memberships_membership_plan_ids" multiple="multiple" data-placeholder="<?php 
                esc_attr_e('Search for a membership plan&hellip;', WC_Memberships::TEXT_DOMAIN);
                ?>
">
							<?php 
                if (!empty($grant_access_to_plans)) {
                    foreach ($grant_access_to_plans as $plan) {
                        echo '<option value="' . esc_attr($plan->get_id()) . '" selected="selected">' . esc_html($plan->get_name()) . '</option>';
                    }
                }
                ?>
						</select>
					<?php 
            }
            ?>

					<img class="help_tip" data-tip="<?php 
            esc_attr_e('Select which membership plans does purchasing this product grant access tp.', WC_Memberships::TEXT_DOMAIN);
            ?>
" src="<?php 
            echo esc_url(WC()->plugin_url());
            ?>
/assets/images/help.png" height="16" width="16" /></p>

					<p>
						<em><?php 
            esc_html_e('Need to add or edit a plan?', WC_Memberships::TEXT_DOMAIN);
            ?>
</em> <a target="_blank" href="<?php 
            echo admin_url('edit.php?post_type=wc_membership_plan');
            ?>
"><?php 
            esc_html_e('Manage Membership Plans', WC_Memberships::TEXT_DOMAIN);
            ?>
</a>
					</p>

				<?php 
        }
        ?>

				</div>

				<?php 
        /**
         * Fires after the product memberships data grant access panel is displayed
         *
         * @since 1.0.0
         */
        do_action('wc_memberships_data_options_grant_access');
        ?>
			</div><!-- //#memberships-data-grant-access -->


			<div id="memberships-data-purchasing-discounts" class="panel woocommerce_options_panel">

				<p class="variable-notice <?php 
        if (!$product->is_type('variable')) {
            ?>
hide<?php 
        }
        ?>
">
					<?php 
        esc_html_e('These rules affect all variations. For variation-level control use the membership plan screen', WC_Memberships::TEXT_DOMAIN);
        ?>
				</p>

				<div class="table-wrap">
					<?php 
        require wc_memberships()->get_plugin_path() . '/includes/admin/meta-boxes/views/html-purchasing-discount-rules.php';
        ?>
				</div>

				<?php 
        /**
         * Fires after the membership plan purchasing discounts panel is displayed
         *
         * @since 1.0.0
         */
        do_action('wc_memberships_data_options_purchasing_discounts');
        ?>
			</div><!-- //#memberships-data-purchase-discounts -->

			<?php 
        /**
         * Fires after the product memberships data panels are displayed
         *
         * @since 1.0.0
         */
        do_action('wc_memberships_data_product_panels');
        ?>

			<div class="clear"></div>

		</div><!-- //.panel-wrap -->
		<?php 
    }
echo esc_url(WC()->plugin_url());
?>
/assets/images/help.png" height="16" width="16" />
			</th>

		</tr>
	</thead>

	<?php 
foreach ($product_restriction_rules as $index => $rule) {
    require wc_memberships()->get_plugin_path() . '/includes/admin/meta-boxes/views/html-product-restriction-rule.php';
}
?>
	
	<?php 
$membership_plans = wc_memberships_get_membership_plans(array('post_status' => array('publish', 'private', 'future', 'draft', 'pending', 'trash')));
?>

	<tbody class="norules <?php 
if (count($product_restriction_rules) > 1) {
    ?>
hide<?php 
}
?>
">
		<tr>
			<td colspan="<?php 
echo 'wc_membership_plan' == $post->post_type ? 5 : 4;
?>
">
				<?php