/**
  * Add the simulated relationship to the current users memberships.
  *
  * @since  1.0.0
  */
 public function add_simulation_membership($subscriptions)
 {
     $subscription = false;
     if (!isset($subscriptions[$this->membership_id])) {
         $this->start_simulation();
         $subscription = MS_Model_Relationship::create_ms_relationship($this->membership_id, 0, 'simulation');
     }
     if (is_a($subscription, 'MS_Model_Relationship')) {
         $membership = $subscription->get_membership();
         if (MS_Model_Membership::PAYMENT_TYPE_PERMANENT == $membership->payment_type) {
             $subscription->expire_date = '2999-12-31';
         }
         $key = 'ms_model_relationship--1';
         MS_Factory::set_singleton($subscription, $key);
         $this->_subscription = $subscription;
         $subscriptions[$this->membership_id] = $subscription;
     }
     return $subscriptions;
 }
 /**
  * Export specific data.
  *
  * @since  1.0.0
  * @param  MS_Model_Relationship $src
  * @return object Export data
  */
 protected function export_relationship($src)
 {
     $obj = (object) array();
     $obj->id = $this->exp_id('relationship', $src->id);
     $obj->membership = $this->exp_id('membership', $src->membership_id);
     $obj->status = $src->status;
     $obj->gateway = $src->gateway_id;
     $obj->start = $src->start_date;
     $obj->end = $src->expire_date;
     $obj->trial_finished = $src->trial_period_completed;
     if (!$obj->trial_finished) {
         $obj->trial_end = $src->trial_expire_date;
     }
     $obj->invoices = array();
     $invoices = $src->get_invoices();
     foreach ($invoices as $invoice) {
         $obj->invoices[] = $this->export_invoice($invoice);
     }
     return $obj;
 }
 /**
  * Save invoices using the invoices model.
  *
  * @since  1.0.0
  *
  * @param mixed $fields Transaction fields
  */
 private function save_invoice($fields)
 {
     $msg = MS_Helper_Billing::BILLING_MSG_NOT_UPDATED;
     if ($this->is_admin_user() && is_array($fields) && !empty($fields['user_id']) && !empty($fields['membership_id'])) {
         $member = MS_Factory::load('MS_Model_Member', $fields['user_id']);
         $membership_id = $fields['membership_id'];
         $gateway_id = 'admin';
         $subscription = MS_Model_Relationship::get_subscription($member->id, $membership_id);
         if (empty($subscription)) {
             $subscription = MS_Model_Relationship::create_ms_relationship($membership_id, $member->id, $gateway_id);
         } else {
             $subscription->gateway_id = $gateway_id;
             $subscription->save();
         }
         $invoice_id = intval($fields['invoice_id']);
         $invoice = MS_Factory::load('MS_Model_Invoice', $invoice_id);
         if (!$invoice->is_valid()) {
             $invoice = $subscription->get_current_invoice();
             $msg = MS_Helper_Billing::BILLING_MSG_ADDED;
         } else {
             $msg = MS_Helper_Billing::BILLING_MSG_UPDATED;
         }
         foreach ($fields as $field => $value) {
             $invoice->{$field} = $value;
         }
         $invoice->save();
         if (!empty($fields['execute'])) {
             $invoice->changed();
         }
     }
     return apply_filters('ms_controller_billing_save_invoice', $msg, $fields, $this);
 }
    /**
     * Returns the contens of the dialog
     *
     * @since  1.0.0
     *
     * @return object
     */
    public function get_contents($data)
    {
        $member = $data['model'];
        $currency = MS_Plugin::instance()->settings->currency;
        $show_trial = MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_TRIAL);
        $all_subscriptions = MS_Model_Relationship::get_subscriptions(array('user_id' => $member->id, 'status' => 'all', 'meta_key' => 'expire_date', 'orderby' => 'meta_value', 'order' => 'DESC'));
        // Prepare the form fields.
        $inp_dialog = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'dialog', 'value' => 'View_Member_Dialog');
        $inp_id = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'member_id', 'value' => $member->id);
        $inp_nonce = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => '_wpnonce', 'value' => wp_create_nonce(self::ACTION_SAVE));
        $inp_action = array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'dialog_action', 'value' => self::ACTION_SAVE);
        $inp_save = array('type' => MS_Helper_Html::INPUT_TYPE_SUBMIT, 'value' => __('Save', 'membership2'), 'class' => 'ms-submit-form', 'data' => array('form' => 'ms-edit-member'));
        $inp_cancel = array('type' => MS_Helper_Html::INPUT_TYPE_BUTTON, 'value' => __('Close', 'membership2'), 'class' => 'close');
        ob_start();
        ?>
		<div>
			<form class="ms-form wpmui-ajax-update ms-edit-member" data-wpmui-ajax="<?php 
        echo esc_attr('save');
        ?>
">
				<div class="ms-form wpmui-form wpmui-grid-8">
					<table class="widefat">
					<thead>
						<tr>
							<th class="column-membership">
								<?php 
        _e('Membership', 'membership2');
        ?>
							</th>
							<th class="column-status">
								<?php 
        _e('Status', 'membership2');
        ?>
							</th>
							<th class="column-start">
								<?php 
        _e('Subscribed on', 'membership2');
        ?>
							</th>
							<th class="column-expire">
								<?php 
        _e('Expires on', 'membership2');
        ?>
							</th>
							<?php 
        if ($show_trial) {
            ?>
							<th class="column-trialexpire">
								<?php 
            _e('Trial until', 'membership2');
            ?>
							</th>
							<?php 
        }
        ?>
							<th class="column-payments">
								<?php 
        _e('Payments', 'membership2');
        ?>
							</th>
						</tr>
					</thead>
					<tbody>
					<?php 
        foreach ($all_subscriptions as $subscription) {
            $membership = $subscription->get_membership();
            $payments = $subscription->get_payments();
            $num_payments = count($payments);
            $amount_payments = 0;
            foreach ($payments as $payment) {
                $amount_payments += $payment['amount'];
            }
            $subscription_info = array('subscription_id' => $subscription->id);
            $update_info = array('subscription_id' => $subscription->id, 'statuscheck' => 'yes');
            ?>
						<tr>
							<td class="column-membership">
								<?php 
            $membership->name_tag();
            ?>
							</td>
							<td class="column-status">
								<?php 
            printf('<a href="#" data-ms-dialog="View_Member_Subscription" data-ms-data="%2$s">%1$s</a>
									<a href="#" data-ms-dialog="View_Member_Subscription" data-ms-data="%3$s" title="%5$s">%4$s</a>', $subscription->status, esc_attr(json_encode($subscription_info)), esc_attr(json_encode($update_info)), '<i class="dashicons dashicons-update"></i>', __('Check and update subscription status', 'membership2'));
            ?>
							</td>
							<td class="column-start">
								<?php 
            echo $subscription->start_date;
            ?>
							</td>
							<td class="column-expire">
								<?php 
            echo $subscription->expire_date;
            ?>
							</td>
							<?php 
            if ($show_trial) {
                ?>
							<td class="column-trialexpire">
								<?php 
                if ($subscription->start_date == $subscription->trial_expire_date) {
                    echo '-';
                } else {
                    echo $subscription->trial_expire_date;
                }
                ?>
							</td>
							<?php 
            }
            ?>
							<td class="column-payments">
								<?php 
            $total = sprintf('<b>%1$s</b> (%3$s %2$s)', $num_payments, MS_Helper_Billing::format_price($amount_payments), $currency);
            printf('<a href="#" data-ms-dialog="View_Member_Payment" data-ms-data="%1$s">%2$s</a>', esc_attr(json_encode($subscription_info)), $total);
            ?>
							</td>
						</tr>
					<?php 
        }
        ?>
					</tbody>
					</table>
				</div>
				<?php 
        MS_Helper_Html::html_element($inp_id);
        MS_Helper_Html::html_element($inp_dialog);
        MS_Helper_Html::html_element($inp_nonce);
        MS_Helper_Html::html_element($inp_action);
        ?>
			</form>
			<div class="buttons">
				<?php 
        MS_Helper_Html::html_element($inp_cancel);
        // MS_Helper_Html::html_element( $inp_save );
        ?>
			</div>
		</div>
		<?php 
        $html = ob_get_clean();
        return apply_filters('ms_view_member_dialog_to_html', $html);
    }
 /**
  * Render membership payment information.
  *
  * Related Filter Hooks:
  * - the_content
  *
  * @since  1.0.0
  *
  * @param string $content The page content to filter.
  * @return string The filtered content.
  */
 public function payment_table($content)
 {
     $data = array();
     $subscription = null;
     $member = MS_Model_Member::get_current_member();
     $membership_id = 0;
     lib2()->array->equip_request('membership_id', 'move_from_id', 'ms_relationship_id');
     if (!empty($_POST['ms_relationship_id'])) {
         // Error path, showing payment table again with error msg
         $subscription = MS_Factory::load('MS_Model_Relationship', absint(intval($_POST['ms_relationship_id'])));
         $membership = $subscription->get_membership();
         $membership_id = $membership->id;
         if (!empty($_POST['error'])) {
             lib2()->array->strip_slashes($_POST, 'error');
             $data['error'] = $_POST['error'];
         }
     } elseif (!empty($_REQUEST['membership_id'])) {
         // First time loading
         $membership_id = intval($_REQUEST['membership_id']);
         $membership = MS_Factory::load('MS_Model_Membership', $membership_id);
         $move_from_id = absint($_REQUEST['move_from_id']);
         $subscription = MS_Model_Relationship::create_ms_relationship($membership_id, $member->id, '', $move_from_id);
     } else {
         MS_Helper_Debug::log('Error: missing POST params');
         MS_Helper_Debug::log($_POST);
         return $content;
     }
     $invoice = $subscription->get_current_invoice();
     /**
      * Notify Add-ons that we are preparing payment details for a membership
      * subscription.
      *
      * E.g. Coupon discount is applied by this hook.
      *
      * @since  1.0.0
      */
     $invoice = apply_filters('ms_signup_payment_details', $invoice, $subscription, $membership);
     $invoice->save();
     $data['invoice'] = $invoice;
     $data['membership'] = $membership;
     $data['member'] = $member;
     $data['ms_relationship'] = $subscription;
     $view = MS_Factory::load('MS_View_Frontend_Payment');
     $view->data = apply_filters('ms_view_frontend_payment_data', $data, $membership_id, $subscription, $member, $this);
     return apply_filters('ms_controller_frontend_payment_table', $view->to_html(), $this);
 }
 /**
  * Completely whipe all Membership data from Database.
  *
  * Note: This function is not used currently...
  *
  * @since  1.0.0
  */
 private static function cleanup_db()
 {
     global $wpdb;
     $sql = array();
     $trash_ids = array();
     // Delete membership meta-data from users.
     $users = MS_Model_Member::get_members();
     foreach ($users as $user) {
         $user->delete_all_membership_usermeta();
         $user->save();
     }
     // Determine IDs of Membership Pages.
     $page_types = MS_Model_Pages::get_page_types();
     foreach ($page_types as $type => $name) {
         $page_id = MS_Model_Pages::get_setting($type);
         $trash_ids[] = $page_id;
     }
     /**
      * Delete all plugin settings.
      * Settings are saved by classes that extend MS_Model_option
      */
     foreach (MS_Model_Gateway::get_gateways() as $option) {
         $option->delete();
     }
     MS_Factory::load('MS_Model_Addon')->delete();
     MS_Factory::load('MS_Model_Pages')->delete();
     MS_Factory::load('MS_Model_Settings')->delete();
     /**
      * Delete transient data
      * Transient data is saved by classed that extend MS_Model_Transient
      */
     MS_Factory::load('MS_Model_Simulate')->delete();
     /**
      * Delete all plugin content.
      * Content is saved by classes that extend MS_Model_CustomPostType
      */
     $ms_posttypes = array(MS_Model_Communication::get_post_type(), MS_Model_Event::get_post_type(), MS_Model_Invoice::get_post_type(), MS_Model_Transactionlog::get_post_type(), MS_Model_Membership::get_post_type(), MS_Model_Relationship::get_post_type(), MS_Addon_Coupon_Model::get_post_type(), MS_Addon_Invitation_Model::get_post_type());
     foreach ($ms_posttypes as $type) {
         $sql[] = $wpdb->prepare("DELETE FROM {$wpdb->posts} WHERE post_type = %s;", $type);
     }
     // Remove orphaned post-metadata.
     $sql[] = "\n\t\tDELETE FROM {$wpdb->postmeta}\n\t\tWHERE NOT EXISTS (\n\t\t\tSELECT 1 FROM {$wpdb->posts} tmp WHERE tmp.ID = post_id\n\t\t);\n\t\t";
     // Clear all WP transient cache.
     $sql[] = "\n\t\tDELETE FROM {$wpdb->options}\n\t\tWHERE option_name LIKE '_transient_%';\n\t\t";
     foreach ($sql as $s) {
         $wpdb->query($s);
     }
     // Move Membership pages to trash.
     foreach ($trash_ids as $id) {
         wp_delete_post($id, true);
     }
     // Clear all data from WP Object cache.
     wp_cache_flush();
     // Redirect to the main page.
     wp_safe_redirect(MS_Controller_Plugin::get_admin_url());
     exit;
 }
 /**
  * Get post types that are part of this plugin.
  *
  * @since  1.0.0
  *
  * @return array The plugin core post types.
  */
 public static function get_ms_post_types()
 {
     $cpts = array(MS_Model_Membership::get_post_type(), MS_Model_Invoice::get_post_type(), MS_Model_Communication::get_post_type(), MS_Model_Relationship::get_post_type(), MS_Model_Event::get_post_type());
     return apply_filters('ms_rule_cptgroup_model_get_ms_post_types', $cpts);
 }
 /**
  * Creates a new subscription for the specified user/membership and returns
  * the MS_Model_Relationship object.
  *
  * @since  1.0.0
  * @return MS_Model_Relationship
  */
 public static function subscribe($user_key, $membership_key, $gateway_id = '')
 {
     if (!is_numeric($user_key)) {
         $user_key = self::id('user', $user_key);
     }
     if (!is_numeric($membership_key)) {
         $membership_key = self::id('membership', $membership_key);
     }
     $subscription = MS_Model_Relationship::create_ms_relationship($membership_key, $user_key, $gateway_id, 0);
     return $subscription;
 }
 /**
  * Called by MS_Model_Invoice before a new invoice is saved. We apply the
  * coupon discount to the total amount, if a coupon was used.
  *
  * @since  1.0.0
  * @param  MS_Model_Invoice $invoice
  * @param  MS_Model_Relationship $subscription
  * @return MS_Model_Invoice
  */
 public function apply_discount($invoice, $subscription)
 {
     $membership = $subscription->get_membership();
     $member = MS_Factory::load('MS_Model_Member', $subscription->user_id);
     if (isset($_POST['apply_coupon_code'])) {
         $coupon = apply_filters('ms_addon_coupon_model', MS_Addon_Coupon_Model::load_by_code($_POST['coupon_code']));
         $coupon->save_application($subscription);
     } else {
         $coupon = MS_Addon_Coupon_Model::get_application($member->id, $membership->id);
         if (!empty($_POST['remove_coupon_code'])) {
             $note = sprintf(__('Remove Coupon "%s"', MS_TEXT_DOMAIN), $coupon->code);
             $invoice->add_notes($note);
             $coupon->remove_application($member->id, $membership->id);
             $coupon = false;
         }
     }
     self::the_coupon($coupon);
     if ($coupon && $coupon->is_valid($membership->id)) {
         $discount = $coupon->get_discount_value($subscription);
         $invoice->coupon_id = $coupon->id;
         $invoice->discount = $discount;
         $note = sprintf(__('Apply Coupon "%s": Discount %s %s!', MS_TEXT_DOMAIN), $coupon->code, $invoice->currency, $discount);
         $invoice->add_notes($note);
     } else {
         $invoice->coupon_id = '';
         $invoice->discount = 0;
     }
     return $invoice;
 }
 /**
  * Replace comm_vars with corresponding values.
  *
  * @since  1.0.0
  *
  * @param MS_Model_Relationship $subscription The membership relationship to send message to.
  * @param MS_Model_Member $member The member object to get info from.
  * @return array {
  *     Returns array of ( $var_name => $var_replace ).
  *
  *     @type string $var_name The variable name to replace.
  *     @type string $var_replace The variable corresponding replace string.
  * }
  */
 public function get_comm_vars($subscription, $member)
 {
     $currency = MS_Plugin::instance()->settings->currency . ' ';
     $invoice = null;
     $membership = null;
     if ($subscription && $subscription instanceof MS_Model_Relationship) {
         // First try to fetch the current invoice.
         $invoice = $subscription->get_current_invoice(false);
         $prev_invoice = $subscription->get_previous_invoice();
         // If no current invoice exists then fetch the previous invoice.
         if (empty($invoice)) {
             $invoice = $prev_invoice;
         }
         $membership = $subscription->get_membership();
     }
     $comm_vars = apply_filters('ms_model_communication_comm_vars', $this->comm_vars, $this->type, $member, $subscription);
     $wp_user = $member->get_user();
     foreach ($comm_vars as $key => $description) {
         $var_value = '';
         switch ($key) {
             case self::COMM_VAR_BLOG_NAME:
                 $var_value = get_option('blogname');
                 break;
             case self::COMM_VAR_BLOG_URL:
                 $var_value = get_option('home');
                 break;
             case self::COMM_VAR_USERNAME:
                 $var_value = $member->username;
                 break;
             case self::COMM_VAR_PASSWORD:
                 /**
                  * $member->password is ONLY available in the same request
                  * when the new user account was created! After this we only
                  * have the encrypted password in the DB, and the plain-text
                  * version will never be available again in code...
                  *
                  * @since 1.0.1.1
                  */
                 if (self::COMM_TYPE_SIGNUP == $this->type) {
                     $var_value = $member->password;
                 }
                 break;
             case self::COMM_VAR_USER_DISPLAY_NAME:
                 $var_value = $wp_user->display_name;
                 break;
             case self::COMM_VAR_USER_FIRST_NAME:
                 $var_value = $member->first_name;
                 break;
             case self::COMM_VAR_USER_LAST_NAME:
                 $var_value = $member->last_name;
                 break;
             case self::COMM_VAR_NET_NAME:
                 $var_value = get_site_option('site_name');
                 break;
             case self::COMM_VAR_NET_URL:
                 $var_value = get_site_option('siteurl');
                 break;
             case self::COMM_VAR_MS_ACCOUNT_PAGE_URL:
                 $var_value = sprintf('<a href="%s">%s</a>', MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_ACCOUNT), __('account page', MS_TEXT_DOMAIN));
                 break;
                 // Needs: $membership
             // Needs: $membership
             case self::COMM_VAR_MS_NAME:
                 if ($membership && $membership->name) {
                     $var_value = $membership->name;
                 }
                 break;
                 // Needs: $invoice
             // Needs: $invoice
             case self::COMM_VAR_MS_INVOICE:
                 if ($invoice) {
                     if ($invoice->total > 0 || $invoice->uses_trial) {
                         $attr = array('post_id' => $invoice->id, 'pay_button' => 0);
                         $scode = MS_Factory::load('MS_Controller_Shortcode');
                         $var_value = $scode->membership_invoice($attr);
                     }
                 }
                 break;
                 // Needs: $subscription
             // Needs: $subscription
             case self::COMM_VAR_MS_REMAINING_DAYS:
                 if ($subscription) {
                     $days = $subscription->get_remaining_period();
                     $var_value = sprintf(__('%s day%s', MS_TEXT_DOMAIN), $days, abs($days) > 1 ? 's' : '');
                 }
                 break;
                 // Needs: $subscription
             // Needs: $subscription
             case self::COMM_VAR_MS_REMAINING_TRIAL_DAYS:
                 if ($subscription) {
                     $days = $subscription->get_remaining_trial_period();
                     $var_value = sprintf(__('%s day%s', MS_TEXT_DOMAIN), $days, abs($days) > 1 ? 's' : '');
                 }
                 break;
                 // Needs: $subscription
             // Needs: $subscription
             case self::COMM_VAR_MS_EXPIRY_DATE:
                 if ($subscription) {
                     $var_value = $subscription->expire_date;
                 }
                 break;
         }
         $comm_vars[$key] = apply_filters('ms_model_communication_send_message_comm_var-' . $key, $var_value, $this->type, $member, $subscription, $invoice);
     }
     return apply_filters('ms_model_communication_get_comm_vars', $comm_vars, $member);
 }
 /**
  * Make sure that we respect the Single-Membership rule.
  * This rule is active when the "Multiple-Memberships" Add-on is DISABLED.
  *
  * @since  1.0.0
  *
  * @param  MS_Model_Relationship $new_relationship
  */
 protected function validate_membership_states($new_relationship)
 {
     if (MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_MULTI_MEMBERSHIPS)) {
         // Multiple memberships allowed. No need to check anything.
         return;
     }
     $cancel_these = array(MS_Model_Relationship::STATUS_TRIAL, MS_Model_Relationship::STATUS_ACTIVE, MS_Model_Relationship::STATUS_PENDING);
     $member = $new_relationship->get_member();
     foreach ($member->subscriptions as $subscription) {
         if ($subscription->id === $new_relationship->id) {
             continue;
         }
         if (in_array($subscription->status, $cancel_these)) {
             $subscription->cancel_membership();
         }
     }
 }
Exemple #12
0
 /**
  * A payment was received, award affiliate reward to the referrer.
  *
  * Whenever a Membership2 invoice is paid we try to find the referrer of
  * the member and award a reward to him according to the payment settings.
  *
  * This function uses the Membership2 hook `ms_invoice_paid` which is called
  * when a user does either
  * (1) sucessfully make a payment for a paid membership or
  * (2) successfully subscribe to a free membership.
  *
  * @since  1.0.0
  * @param  MS_Model_Invoice $invoice The invoice which was paid.
  * @param  MS_Model_Relationship $subscription
  */
 public function payment_processed($invoice, $subscription)
 {
     global $affiliate;
     // Used for communication with Affiliates plugin.
     global $blog_id, $site_id;
     // Used for logging.
     $user_id = $invoice->user_id;
     $membership = $subscription->get_membership();
     $pay_once = defined('AFFILIATE_PAYONCE') && 'yes' == AFFILIATE_PAYONCE;
     $user_id_referrer = get_user_meta($user_id, 'affiliate_referred_by', true);
     if (empty($user_id_referrer)) {
         // We do not know who referred the user, don't pay a commission.
         return;
     }
     $affiliate_paid = get_user_meta($user_id, 'affiliate_paid', true);
     if ($pay_once && 'yes' == $affiliate_paid) {
         // The referrer already got a one-time commission, don't pay again.
         return;
     }
     $complete_records = $affiliate->get_complete_records($user_id_referrer, date('Ym'), array(self::AREA_KEY), $user_id);
     if (is_array($complete_records)) {
         // Make sure that this subscription was not commissioned before.
         foreach ($complete_records as $record) {
             $meta = maybe_unserialize($record->meta);
             if ($meta['subscription_id'] == $subscription->id) {
                 // It seems this subscription was already commissioned.
                 return;
             }
         }
     }
     // Okay, the referrer is entitiled to the commission!
     /*
      * Reward is the money that the user receives.
      * It is stored in cents/milli-percent.
      * I.e. '100' $ -> 1.00 $  and '100' % -> 1.00 %
      */
     $reward = $this->get_value($membership);
     $type = $this->get_type($membership);
     switch ($type) {
         case 'inv':
             $base = $invoice->subtotal;
             // Invoice amount without taxes.
             $reward = $base * $reward / 100;
             break;
         case 'mem':
             $base = $membership->price;
             // Membership price setting.
             $reward = $base * $reward / 100;
             break;
         case 'abs':
         default:
             // Reward already has correct value.
             break;
     }
     $reward = round($reward, 2, PHP_ROUND_HALF_DOWN);
     // Note: lib2() used here is provided by the Membership2 plugin.
     $meta = array('subscription_id' => $subscription->id, 'invoice_id' => $invoice->id, 'gateway_id' => $invoice->gateway_id, 'transaction_id' => $invoice->external_id, 'blog_id' => $blog_id, 'site_id' => $site_id, 'current_user_id' => get_current_user_id(), 'REMOTE_URL' => $_SERVER['HTTP_REFERER'], 'LOCAL_URL' => lib2()->net->current_url(), 'IP' => lib2()->net->current_ip()->ip);
     do_action('affiliate_purchase', $user_id_referrer, $reward, self::AREA_KEY, $user_id, __('Membership2', 'affiliate'), $meta);
     if ($pay_once) {
         update_user_meta($user_id, 'affiliate_paid', 'yes');
     }
 }
 /**
  * Adds the Pro-Rating discount to an invoice.
  *
  * @since  1.0.1.0
  * @param  MS_Model_Invoice $invoice
  * @return MS_Model_Invoice Modified Invoice.
  */
 public function add_discount($invoice)
 {
     // Only the first invoice can be pro-rated.
     if ($invoice->invoice_number > 1) {
         return $invoice;
     }
     $subscription = $invoice->get_subscription();
     $membership = $invoice->get_membership();
     if (!$subscription->move_from_id) {
         return $invoice;
     }
     $ids = explode(',', $subscription->move_from_id);
     if (empty($ids)) {
         return $invoice;
     }
     if ($membership->is_free()) {
         return $invoice;
     }
     // Calc pro rate discount if moving from another membership.
     $pro_rate = 0;
     foreach ($ids as $id) {
         if (!$id) {
             continue;
         }
         $move_from = MS_Model_Relationship::get_subscription($subscription->user_id, $id);
         if ($move_from->is_valid() && $move_from->id == $id) {
             $pro_rate += $this->get_discount($move_from);
         }
     }
     $pro_rate = floatval(apply_filters('ms_addon_prorate_apply_discount', abs($pro_rate), $invoice));
     if ($pro_rate > $invoice->amount) {
         $pro_rate = $invoice->amount;
     }
     if ($pro_rate > 0) {
         $invoice->pro_rate = $pro_rate;
         $notes[] = sprintf(__('Pro-Rate Discount: %s.', MS_TEXT_DOMAIN) . ' ', $invoice->currency . ' ' . $pro_rate);
     }
     return $invoice;
 }
 /**
  * Load MS_Model_Member Object.
  *
  * Load from user and user meta.
  * This data is always network-wide.
  *
  * @since  1.0.0
  *
  * @param MS_Model_Member $model The empty member instance.
  * @param int $user_id The user/member ID.
  *
  * @return MS_Model_Member The retrieved object.
  */
 protected static function load_from_wp_user($model, $user_id, $name = null)
 {
     $class = get_class($model);
     $cache = wp_cache_get($user_id, $class);
     if ($cache) {
         $model = $cache;
     } else {
         $wp_user = new WP_User($user_id, $name);
         if (!empty($wp_user->ID)) {
             $member_details = get_user_meta($user_id);
             $model->id = $wp_user->ID;
             $model->username = $wp_user->user_login;
             $model->email = $wp_user->user_email;
             $model->name = $wp_user->display_name;
             $model->first_name = $wp_user->first_name;
             $model->last_name = $wp_user->last_name;
             $model->wp_user = $wp_user;
             if (!$model->name) {
                 if ($model->first_name) {
                     $model->name = $model->first_name . ' ' . $model->last_name;
                 } else {
                     $model->name = $wp_user->user_login;
                 }
                 $model->name = ucwords(strtolower($model->name));
             }
             $model->name = trim($model->name);
             /**
              * Manually customize the display name of the user via a filter.
              *
              * @since  1.0.1.2
              * @param  string $name The default display name used by M2.
              * @param  WP_User $wp_user The user object used to populate the name.
              */
             $model->name = apply_filters('ms_model_user_set_name', $model->name, $wp_user);
             // Remove automatic populated values from metadata, if present.
             unset($member_details['ms_username']);
             unset($member_details['ms_email']);
             unset($member_details['ms_name']);
             unset($member_details['ms_first_name']);
             unset($member_details['ms_last_name']);
             self::populate_model($model, $member_details, 'ms_');
             // Load membership_relationships
             $model->subscriptions = MS_Model_Relationship::get_subscriptions(array('user_id' => $model->id));
         }
     }
     return apply_filters('ms_factory_load_from_wp_user', $model, $class, $user_id);
 }
 /**
  * Sort function used as second param by `uasort()` to sort a subscription
  * list by membership priority.
  * Memberships with equal priority are sorted alphabeically.
  *
  * @since  1.0.1.0
  * @param  MS_Model_Relationship $a
  * @param  MS_Model_Relationship $b
  * @return int -1: a < b | 0: a = b | +1: a > b
  */
 public static function sort_by_priority($a, $b)
 {
     $m1 = $a->get_membership();
     $m2 = $b->get_membership();
     if ($m1->priority == $m2->priority) {
         return $m1->name < $m2->name ? -1 : 1;
     } else {
         return $m1->priority - $m2->priority;
     }
 }
 /**
  * Checks if a subscription has reached the maximum paycycle repetitions.
  * If the last paycycle was paid then the subscription is cancelled.
  *
  * @since  1.0.0
  * @internal Called by process_purchase() and request_payment()
  *
  * @param  MS_Model_Relationship $subscription
  * @param  M2_Stripe_Subscription $stripe_sub
  */
 protected function cancel_if_done($subscription, $stripe_sub)
 {
     $membership = $subscription->get_membership();
     if ($membership->pay_cycle_repetitions < 1) {
         return;
     }
     $payments = $subscription->payments;
     if (count($payments) < $membership->pay_cycle_repetitions) {
         return;
     }
     $stripe_sub->cancel(array('at_period_end' => true));
 }
    /**
     * Echo a member-list. This function can be overwritten by other views
     * to customize the list.
     *
     * @since  1.0.0
     *
     * @param array $members List of members to display.
     */
    protected function members_panel_data($members, $membership_id)
    {
        $item = 0;
        $max_items = 10;
        $class = '';
        $status_types = MS_Model_Relationship::get_status_types();
        ?>
		<table class="ms-list-table widefat">
			<thead>
				<th><?php 
        _e('Member', 'membership2');
        ?>
</th>
				<th><?php 
        _e('Since', 'membership2');
        ?>
</th>
				<th><?php 
        _e('Status', 'membership2');
        ?>
</th>
			</thead>
			<tbody>
			<?php 
        foreach ($this->data['members'] as $member) {
            $item += 1;
            if ($item > $max_items) {
                break;
            }
            $class = $class == 'alternate' ? '' : 'alternate';
            $subscription = $member->get_subscription($membership_id);
            ?>
				<tr class="<?php 
            echo esc_attr($class);
            ?>
">
					<td><?php 
            echo esc_html($member->username);
            ?>
</td>
					<td><?php 
            echo esc_html(MS_Helper_Period::format_date($subscription->start_date));
            ?>
</td>
					<td><?php 
            echo esc_html($status_types[$subscription->status]);
            ?>
</td>
				</tr>
			<?php 
        }
        ?>
			</tbody>
		</table>
		<?php 
    }
 /**
  * Check membership status.
  *
  * Execute actions when time/period condition are met.
  * E.g. change membership status, add communication to queue, create invoices.
  *
  * @since  1.0.0
  */
 public function check_membership_status()
 {
     do_action('ms_model_plugin_check_membership_status_before', $this);
     if ($this->member->is_simulated_user()) {
         return;
     }
     /*
      * For performance reasons we only process a small batch at once.
      * Here we find out, which subscriptions should be processed during
      * the current request.
      */
     $offset = (int) MS_Factory::get_option('ms_batch_check_offset_flag');
     // Find the next X subscriptions from DB.
     $args = apply_filters('ms_model_plugin_check_membership_status_get_subscription_args', array('status' => 'valid', 'orderby' => 'ID', 'posts_per_page' => $this->_process_per_batch, 'offset' => $offset, 'nopaging' => false));
     $subscriptions = MS_Model_Relationship::get_subscriptions($args);
     if (count($subscriptions) < $this->_process_per_batch) {
         // We processed all subscriptions. Clean up.
         MS_Factory::delete_option('ms_batch_check_offset_flag');
     } else {
         // We did not process all subscriptions. Remember where to continue.
         MS_Factory::update_option('ms_batch_check_offset_flag', $offset + $this->_process_per_batch);
         // Re-scheduling the cron job will run it again on next page load.
         $hook = 'ms_cron_check_membership_status';
         wp_clear_scheduled_hook($hook);
         $this->setup_cron_services($hook);
     }
     // Perform the actual status checks!
     foreach ($subscriptions as $subscription) {
         error_log('This is ' . $subscription->id);
         $subscription->check_membership_status();
     }
     do_action('ms_model_plugin_check_membership_status_after', $this);
 }
 public function can_change_payment()
 {
     // Allow if Membership is new/unsaved.
     if (empty($this->id)) {
         return true;
     }
     // Allow if no payment detail was entered yet (incomplete setup).
     if (empty($this->payment_type)) {
         return true;
     }
     // Allow if no members signed up yet.
     $members = MS_Model_Relationship::get_subscription_count(array('membership_id' => $this->id));
     if (empty($members)) {
         return true;
     }
     // Otherwise payment details cannot be changed anymore.
     return false;
 }
 /**
  * Check membership status.
  *
  * Execute actions when time/period condition are met.
  * E.g. change membership status, add communication to queue, create invoices.
  *
  * @since  1.0.0
  */
 public function check_membership_status()
 {
     do_action('ms_model_plugin_check_membership_status_before', $this);
     if ($this->member->is_simulated_user()) {
         return;
     }
     $args = apply_filters('ms_model_plugin_check_membership_status_get_subscription_args', array('status' => 'valid'));
     $subscriptions = MS_Model_Relationship::get_subscriptions($args);
     foreach ($subscriptions as $subscription) {
         $subscription->check_membership_status();
     }
     do_action('ms_model_plugin_check_membership_status_after', $this);
 }
 /**
  * Move a membership.
  *
  * @since  1.0.0
  * @api
  *
  * @param int $old_membership_id The membership id to move from.
  * @param int $mew_membership_id The membership id to move to.
  */
 public function move_membership($old_membership_id, $mew_membership_id)
 {
     $old_subscription = $this->get_subscription($old_membership_id);
     if ($old_subscription) {
         $new_subscription = MS_Model_Relationship::create_ms_relationship($mew_membership_id, $this->id, $old_subscription->gateway_id, $old_membership_id);
         $this->cancel_membership($old_membership_id);
         $this->subscriptions[] = $new_subscription;
         MS_Model_Event::save_event(MS_Model_Event::TYPE_MS_MOVED, $new_subscription);
     }
     do_action('ms_model_membership_move_membership', $old_membership_id, $mew_membership_id, $this);
 }
Exemple #22
0
 /**
  * Load MS_Model_Member Object.
  *
  * Load from user and user meta.
  * This data is always network-wide.
  *
  * @since  1.0.0
  *
  * @param MS_Model_Member $model The empty member instance.
  * @param int $user_id The user/member ID.
  *
  * @return MS_Model_Member The retrieved object.
  */
 protected static function load_from_wp_user($model, $user_id, $name = null)
 {
     $class = get_class($model);
     $cache = wp_cache_get($user_id, $class);
     if ($cache) {
         $model = $cache;
     } else {
         $wp_user = new WP_User($user_id, $name);
         if (!empty($wp_user->ID)) {
             $member_details = get_user_meta($user_id);
             $model->id = $wp_user->ID;
             $model->username = $wp_user->user_login;
             $model->email = $wp_user->user_email;
             $model->name = $wp_user->user_nicename;
             $model->first_name = $wp_user->first_name;
             $model->last_name = $wp_user->last_name;
             $model->wp_user = $wp_user;
             self::populate_model($model, $member_details, 'ms_');
             // Load membership_relationships
             $model->subscriptions = MS_Model_Relationship::get_subscriptions(array('user_id' => $model->id));
         }
     }
     return apply_filters('ms_factory_load_from_wp_user', $model, $class, $user_id);
 }
Exemple #23
0
 /**
  * Register plugin custom post types.
  *
  * @since  1.0.0
  */
 public function register_custom_post_types()
 {
     do_action('ms_plugin_register_custom_post_types_before', $this);
     $cpts = apply_filters('ms_plugin_register_custom_post_types', array(MS_Model_Membership::get_post_type() => MS_Model_Membership::get_register_post_type_args(), MS_Model_Relationship::get_post_type() => MS_Model_Relationship::get_register_post_type_args(), MS_Model_Invoice::get_post_type() => MS_Model_Invoice::get_register_post_type_args(), MS_Model_Communication::get_post_type() => MS_Model_Communication::get_register_post_type_args(), MS_Model_Event::get_post_type() => MS_Model_Event::get_register_post_type_args()));
     foreach ($cpts as $cpt => $args) {
         MS_Helper_Utility::register_post_type($cpt, $args);
     }
 }
 /**
  * Removes all subscriptions and memberships from the current site.
  * This is done before the import if the "Replace existing data" flag is set.
  *
  * @since  1.0.0
  */
 protected function clear_memberships()
 {
     // Delete all Relationships.
     $subscriptions = MS_Model_Relationship::get_subscriptions(array('status' => 'all'));
     foreach ($subscriptions as $subscription) {
         $subscription->delete();
     }
     // Delete all Memberships.
     $memberships = MS_Model_Membership::get_memberships();
     foreach ($memberships as $membership) {
         if ($membership->is_base()) {
             continue;
         }
         $membership->delete(true);
     }
 }
 /**
  * Display Membership Overview page.
  *
  * @since  1.0.0
  */
 public function page_overview()
 {
     $membership = $this->load_membership();
     $membership_id = $membership->id;
     $data = array();
     $data['step'] = $this->get_step();
     $data['action'] = self::ACTION_SAVE;
     $data['membership'] = $membership;
     $data['bread_crumbs'] = $this->get_bread_crumbs();
     $data['members'] = array();
     $subscriptions = MS_Model_Relationship::get_subscriptions(array('membership_id' => $membership->id));
     foreach ($subscriptions as $subscription) {
         $data['members'][] = $subscription->get_member();
     }
     switch ($membership->type) {
         case MS_Model_Membership::TYPE_DRIPPED:
             $view = MS_Factory::create('MS_View_Membership_Overview_Dripped');
             break;
         default:
         case MS_Model_Membership::TYPE_STANDARD:
             $view = MS_Factory::create('MS_View_Membership_Overview_Simple');
             break;
     }
     // Select Events args
     $args = array();
     $args['meta_query']['membership_id'] = array('key' => 'membership_id', 'value' => array($membership_id, 0), 'compare' => 'IN');
     $data['events'] = MS_Model_Event::get_events($args);
     $view = apply_filters('ms_view_membership_overview', $view);
     $view->data = apply_filters('ms_view_membership_overview_data', $data, $this);
     $view->render();
 }
 /**
  * Membership account page shortcode callback function.
  *
  * @since  1.0.0
  *
  * @param mixed[] $atts Shortcode attributes.
  */
 public function membership_account($atts)
 {
     MS_Helper_Shortcode::did_shortcode(MS_Helper_Shortcode::SCODE_MS_ACCOUNT);
     $data = apply_filters('ms_controller_shortcode_membership_account_atts', shortcode_atts(array('show_membership' => true, 'show_membership_change' => true, 'membership_title' => __('Your Membership', 'membership2'), 'membership_change_label' => __('Change', 'membership2'), 'show_profile' => true, 'show_profile_change' => true, 'profile_title' => __('Personal details', 'membership2'), 'profile_change_label' => __('Edit', 'membership2'), 'show_invoices' => true, 'limit_invoices' => 10, 'show_all_invoices' => true, 'invoices_title' => __('Invoices', 'membership2'), 'invoices_details_label' => __('View all', 'membership2'), 'show_activity' => true, 'limit_activities' => 10, 'show_all_activities' => true, 'activity_title' => __('Activities', 'membership2'), 'activity_details_label' => __('View all', 'membership2')), $atts));
     $data['show_membership'] = lib3()->is_true($data['show_membership']);
     $data['show_membership_change'] = lib3()->is_true($data['show_membership_change']);
     $data['show_profile'] = lib3()->is_true($data['show_profile']);
     $data['show_profile_change'] = lib3()->is_true($data['show_profile_change']);
     $data['show_invoices'] = lib3()->is_true($data['show_invoices']);
     $data['show_all_invoices'] = lib3()->is_true($data['show_all_invoices']);
     $data['show_activity'] = lib3()->is_true($data['show_activity']);
     $data['show_all_activities'] = lib3()->is_true($data['show_all_activities']);
     $data['limit_invoices'] = absint($data['limit_invoices']);
     $data['limit_activities'] = absint($data['limit_activities']);
     $data['member'] = MS_Model_Member::get_current_member();
     $data['membership'] = array();
     $subscriptions = MS_Model_Relationship::get_subscriptions(array('user_id' => $data['member']->id, 'status' => 'all'));
     if (is_array($subscriptions)) {
         foreach ($subscriptions as $subscription) {
             // Do not display system-memberships in Account
             if ($subscription->is_system()) {
                 continue;
             }
             // Do not display deactivated memberships in Account
             if ($subscription->get_status() == MS_Model_Relationship::STATUS_DEACTIVATED) {
                 continue;
             }
             $data['subscription'][] = $subscription;
         }
     }
     $data['invoices'] = MS_Model_Invoice::get_public_invoices($data['member']->id, $data['limit_invoices']);
     $data['events'] = MS_Model_Event::get_events(array('author' => $data['member']->id, 'posts_per_page' => $data['limit_activities']));
     $view = MS_Factory::create('MS_View_Shortcode_Account');
     $view->data = apply_filters('ms_view_shortcode_account_data', $data, $this);
     return $view->to_html();
 }
 /**
  * Returns a query arg structure tailored to give the defined results
  *
  * @since  1.0.0
  * @return array Query args
  */
 protected function prepare_query_args($args)
 {
     lib2()->array->equip_request('s', 'membership_id', 'search_options', 'status');
     // Prepare order by statement.
     if (!empty($_REQUEST['orderby']) && !empty($_REQUEST['order'])) {
         $args['orderby'] = $_REQUEST['orderby'];
         $args['order'] = $_REQUEST['order'];
     }
     // Filter by search-term
     $search_filter = $_REQUEST['s'];
     if (!empty($search_filter)) {
         $this->search_string = $search_filter;
         $search_option = $_REQUEST['search_options'];
         switch ($search_option) {
             case 'email':
             case 'username':
                 $args['search'] = sprintf('*%s*', $search_filter);
                 break;
             default:
                 $args['meta_query'][$search_option] = array('key' => $search_option, 'value' => $search_filter, 'compare' => 'LIKE');
                 break;
         }
         $args['posts_per_page'] = -1;
         $args['number'] = false;
         $args['offset'] = 0;
     }
     // Filter by membership_id and membership status
     $membership_id = $_REQUEST['membership_id'];
     $members = array();
     $filter = array();
     if (!empty($membership_id)) {
         $filter['membership_id'] = $membership_id;
     }
     if (!empty($status)) {
         $filter['status'] = $status;
     }
     if (!empty($filter)) {
         $subscriptions = MS_Model_Relationship::get_subscriptions($filter);
         foreach ($subscriptions as $subscription) {
             $members[$subscription->user_id] = $subscription->user_id;
         }
         // Workaround to invalidate query
         if (empty($members)) {
             $members[0] = 0;
         }
         $args['include'] = $members;
     }
     return $args;
 }
 /**
  * Update the subscription details after the invoice has changed.
  *
  * Process transaction status change related to this membership relationship.
  * Change status accordinly to transaction status.
  *
  * @since  1.0.0
  * @param MS_Model_Invoice $invoice The invoice to process.
  * @return MS_Model_Invoice The processed invoice.
  */
 public function changed()
 {
     do_action('ms_model_invoice_changed_before', $this);
     if (!$this->ms_relationship_id) {
         MS_Helper_Debug::log('Cannot process transaction: No relationship defined (inv #' . $this->id . ')');
     } else {
         $subscription = $this->get_subscription();
         $member = MS_Factory::load('MS_Model_Member', $this->user_id);
         $membership = $subscription->get_membership();
         switch ($this->status) {
             case self::STATUS_NEW:
             case self::STATUS_BILLED:
                 break;
             case self::STATUS_PAID:
                 if ($this->total > 0) {
                     MS_Model_Event::save_event(MS_Model_Event::TYPE_PAID, $subscription);
                 }
                 do_action('ms_model_invoice_changed-paid', $this, $member);
                 // Check for moving memberships
                 if ($subscription->move_from_id) {
                     $ids = explode(',', $subscription->move_from_id);
                     foreach ($ids as $id) {
                         $move_from = MS_Model_Relationship::get_subscription($subscription->user_id, $id);
                         if ($move_from->is_valid()) {
                             $move_from->cancel_membership();
                         }
                     }
                     $subscription->cancelled_memberships = $subscription->move_from_id;
                     $subscription->move_from_id = '';
                 }
                 /*
                  * Memberships with those payment types can have multiple
                  * invoices for a single subscription.
                  */
                 $multi_invoice = array(MS_Model_Membership::PAYMENT_TYPE_RECURRING, MS_Model_Membership::PAYMENT_TYPE_FINITE);
                 if (in_array($membership->payment_type, $multi_invoice)) {
                     // Update the current_invoice_number counter.
                     $subscription->current_invoice_number = max($subscription->current_invoice_number, $this->invoice_number + 1);
                 }
                 if (MS_Gateway_Manual::ID == $this->gateway_id) {
                     $this->pay_it($this->gateway_id);
                 }
                 break;
             case self::STATUS_DENIED:
                 MS_Model_Event::save_event(MS_Model_Event::TYPE_PAYMENT_DENIED, $subscription);
                 break;
             case self::STATUS_PENDING:
                 MS_Model_Event::save_event(MS_Model_Event::TYPE_PAYMENT_PENDING, $subscription);
                 break;
             default:
                 do_action('ms_model_invoice_changed-unknown', $this);
                 break;
         }
         $member->save();
         $subscription->gateway_id = $this->gateway_id;
         $subscription->save();
         $this->gateway_id = $this->gateway_id;
         $this->save();
     }
     return apply_filters('ms_model_invoice_changed', $this, $this);
 }
 /**
  * Apply coupon to get discount.
  *
  * If trial period is enabled, the discount will be applied in the trial price (even if it is free).
  * If the membership price is free, the discount will be zero.
  * If discount is bigger than the price, the discount will be equal to the price.
  *
  * @since  1.0.0
  *
  * @param MS_Model_Relationship $subscription The membership relationship to apply coupon.
  * @return float The discount value.
  */
 public function get_discount_value($subscription)
 {
     $membership = $subscription->get_membership();
     $price = $membership->price;
     // Excluding Tax
     $original_price = $price;
     $discount = 0;
     if ($this->is_valid($membership->id)) {
         $discount = $this->discount;
         if (self::TYPE_PERCENT == $this->discount_type) {
             $discount = $price * $discount / 100;
         }
         $price -= $discount;
         if ($price < 0) {
             $price = 0;
         }
         $discount = $original_price - $price;
         $this->coupon_message = sprintf(__('Coupon applied: %1$s', 'membership2'), $this->code);
     }
     return apply_filters('ms_addon_coupon_model_apply_discount', $discount, $membership, $this);
 }
 /**
  * Save invitation application.
  *
  * Saving the application to keep track of the application in gateway return.
  * Using INVITATION_REDEMPTION_TIME to expire invitation application.
  *
  * This is a non-static function, as it saves the current object!
  *
  * @since  1.0.0
  * @param MS_Model_Relationship $subscription The subscription to apply the invitation.
  */
 public function save_application($subscription)
 {
     // Don't save empty invitations.
     if (empty($this->code)) {
         return false;
     }
     $membership = $subscription->get_membership();
     $time = apply_filters('ms_addon_invitation_model_save_application_redemption_time', self::INVITATION_REDEMPTION_TIME);
     // Grab the user account as we should be logged in by now.
     $user = MS_Model_Member::get_current_member();
     $key = self::get_transient_name($user->id, $membership->id);
     $transient = apply_filters('ms_addon_invitation_model_transient_value', array('id' => $this->id, 'user_id' => $user->id, 'membership_id' => $membership->id, 'message' => $this->invitation_message));
     MS_Factory::set_transient($key, $transient, $time);
     $this->save();
     do_action('ms_addon_invitation_model_save_application', $subscription, $this);
 }