/**
  * Returns a list of special pages that can be configured by this rule.
  *
  * @since  1.0.0
  *
  * @return array List of special pages.
  */
 protected function get_special_pages()
 {
     if (!is_array($this->_content)) {
         $this->_content = array();
         $front_type = get_option('show_on_front');
         $front_url = MS_Helper_Utility::home_url('/');
         if ('page' === $front_type) {
             $home_url = get_permalink(get_option('page_for_posts'));
         } else {
             $home_url = $front_url;
         }
         $arch_year = get_year_link('');
         $arch_month = get_month_link('', '');
         $arch_day = get_day_link('', '', '');
         $arch_hour = esc_url_raw(add_query_arg('hour', '15', $arch_day));
         // Archive pages
         $this->_content['archive'] = (object) array('label' => __('Any Archive page', 'membership2'), 'url' => '');
         $this->_content['author'] = (object) array('label' => __('Author Archives', 'membership2'), 'url' => '');
         $this->_content['date'] = (object) array('label' => __('Any Date or Time Archive', 'membership2'), 'url' => '');
         $this->_content['year'] = (object) array('label' => __('Archive: Year', 'membership2'), 'url' => $arch_year);
         $this->_content['month'] = (object) array('label' => __('Archive: Month', 'membership2'), 'url' => $arch_month);
         $this->_content['day'] = (object) array('label' => __('Archive: Day', 'membership2'), 'url' => $arch_day);
         $this->_content['time'] = (object) array('label' => __('Archive: Time', 'membership2'), 'url' => $arch_hour);
         // Singular pages
         $this->_content['front'] = (object) array('label' => __('Front Page', 'membership2'), 'url' => $front_url);
         $this->_content['home'] = (object) array('label' => __('Blog Index', 'membership2'), 'url' => $home_url);
         $this->_content['notfound'] = (object) array('label' => __('404 Not Found', 'membership2'), 'url' => '');
         $this->_content['search'] = (object) array('label' => __('Search Results', 'membership2'), 'url' => '');
         $this->_content['single'] = (object) array('label' => __('Any single page or post', 'membership2'), 'url' => '');
         $this->_content['attachment'] = (object) array('label' => __('Any attachment page', 'membership2'), 'url' => '');
     }
     return $this->_content;
 }
 /**
  * Get the protection type available.
  *
  * @since  1.0.0
  *
  * @return array {
  *     The protection type => Description.
  *     @type string $protection_type The media protection type.
  *     @type string $description The media protection description.
  * }
  */
 public static function get_protection_types()
 {
     $settings = MS_Factory::load('MS_Model_Settings');
     $mask = $settings->downloads['masked_url'];
     $example1 = MS_Helper_Utility::home_url($mask . date('/Y/m/') . 'my-image.jpg');
     $example2 = MS_Helper_Utility::home_url($mask . '/ms_12345.jpg');
     $example3 = MS_Helper_Utility::home_url($mask . '/?ms_file=ms_12345.jpg');
     $example1 = '<br /><small>' . __('Example:', 'membership2') . ' ' . $example1 . '</small>';
     $example2 = '<br /><small>' . __('Example:', 'membership2') . ' ' . $example2 . '</small>';
     $example3 = '<br /><small>' . __('Example:', 'membership2') . ' ' . $example3 . '</small>';
     $protection_types = array(self::PROTECTION_TYPE_BASIC => __('Basic protection (default)', 'membership2') . $example1, self::PROTECTION_TYPE_COMPLETE => __('Complete protection', 'membership2') . $example2, self::PROTECTION_TYPE_HYBRID => __('Hybrid protection', 'membership2') . $example3);
     return apply_filters('ms_rule_media_model_get_protection_types', $protection_types);
 }
 /**
  * Url that fires handle_return of this gateway (IPN).
  *
  * @since  1.0.0
  * @return string The return url.
  */
 public function get_return_url()
 {
     $url = MS_Helper_Utility::home_url('/ms-payment-return/' . $this->id);
     return apply_filters('ms_gateway_get_return_url', $url, $this);
 }
 /**
  * Returns an URL for a front-end page with the correct URL schema.
  *
  * @since  1.0.1.2
  * @param  string $path Argument passed to the home_url() function.
  * @return string The correct URL for a front-end page.
  */
 function ms_home_url($path)
 {
     return MS_Helper_Utility::home_url($path);
 }
 /**
  * Returns HTML partial that contains the logout form
  *
  * @since  1.0.0
  *
  * @return string
  */
 private function logout_form()
 {
     if (!MS_Model_Member::is_logged_in()) {
         return '';
     }
     $member = MS_Model_Member::get_current_member();
     extract($this->data);
     if (empty($redirect_logout)) {
         $redirect_logout = MS_Helper_Utility::home_url('/');
     }
     $yourname = sprintf(__('You are logged in as %s.', 'membership2'), ucfirst($member->name));
     $yourname = apply_filters('ms_shortcode_logout_message', $yourname, $member);
     $logout_text = apply_filters('ms_shortcode_logout_link_text', __('Logout', 'membership2'), $member);
     $redirect_logout = apply_filters('ms_shortcode_logout_redirect', $redirect_logout, $member);
     $html = sprintf('%1$s <a class="login_button" href="%2$s">%3$s</a>', $yourname, wp_logout_url($redirect_logout), $logout_text);
     if (!empty($holder)) {
         $html = sprintf('<%1$s class="%2$s">%3$s</%1$s>', esc_attr($holder), esc_attr($holderclass), $html);
     }
     return $html;
 }
 /**
  * Processes gateway IPN return.
  *
  * @since  1.0.0
  * @param  MS_Model_Transactionlog $log Optional. A transaction log item
  *         that will be updated instead of creating a new log entry.
  */
 public function handle_return($log = false)
 {
     $success = false;
     $exit = false;
     $redirect = false;
     $notes = '';
     $status = null;
     $invoice_id = 0;
     $subscription_id = 0;
     $amount = 0;
     do_action('ms_gateway_paypalsingle_handle_return_before', $this);
     lib3()->array->strip_slashes($_POST, 'pending_reason');
     if ((isset($_POST['payment_status']) || isset($_POST['txn_type'])) && !empty($_POST['invoice'])) {
         if ($this->is_live_mode()) {
             $domain = 'https://www.paypal.com';
         } else {
             $domain = 'https://www.sandbox.paypal.com';
         }
         // Ask PayPal to validate our $_POST data.
         $ipn_data = (array) stripslashes_deep($_POST);
         $ipn_data['cmd'] = '_notify-validate';
         $response = wp_remote_post($domain . '/cgi-bin/webscr', array('timeout' => 60, 'sslverify' => false, 'httpversion' => '1.1', 'body' => $ipn_data));
         $invoice_id = intval($_POST['invoice']);
         $external_id = $_POST['txn_id'];
         $amount = (double) $_POST['mc_gross'];
         $currency = $_POST['mc_currency'];
         $invoice = MS_Factory::load('MS_Model_Invoice', $invoice_id);
         if (!is_wp_error($response) && !MS_Model_Transactionlog::was_processed(self::ID, $external_id) && 200 == $response['response']['code'] && !empty($response['body']) && 'VERIFIED' == $response['body'] && $invoice->id == $invoice_id) {
             $new_status = false;
             $subscription = $invoice->get_subscription();
             $membership = $subscription->get_membership();
             $member = $subscription->get_member();
             $subscription_id = $subscription->id;
             // Process PayPal response
             switch ($_POST['payment_status']) {
                 // Successful payment
                 case 'Completed':
                 case 'Processed':
                     $success = true;
                     if ($amount == $invoice->total) {
                         $notes .= __('Payment successful', 'membership2');
                     } else {
                         $notes .= __('Payment registered, though amount differs from invoice.', 'membership2');
                     }
                     break;
                 case 'Reversed':
                     $notes = __('Last transaction has been reversed. Reason: Payment has been reversed (charge back). ', 'membership2');
                     $status = MS_Model_Invoice::STATUS_DENIED;
                     break;
                 case 'Refunded':
                     $notes = __('Last transaction has been reversed. Reason: Payment has been refunded', 'membership2');
                     $status = MS_Model_Invoice::STATUS_DENIED;
                     break;
                 case 'Denied':
                     $notes = __('Last transaction has been reversed. Reason: Payment Denied', 'membership2');
                     $status = MS_Model_Invoice::STATUS_DENIED;
                     break;
                 case 'Pending':
                     $pending_str = array('address' => __('Customer did not include a confirmed shipping address', 'membership2'), 'authorization' => __('Funds not captured yet', 'membership2'), 'echeck' => __('eCheck that has not cleared yet', 'membership2'), 'intl' => __('Payment waiting for aproval by service provider', 'membership2'), 'multi-currency' => __('Payment waiting for service provider to handle multi-currency process', 'membership2'), 'unilateral' => __('Customer did not register or confirm his/her email yet', 'membership2'), 'upgrade' => __('Waiting for service provider to upgrade the PayPal account', 'membership2'), 'verify' => __('Waiting for service provider to verify his/her PayPal account', 'membership2'), '*' => '');
                     $reason = $_POST['pending_reason'];
                     $notes = __('Last transaction is pending. Reason: ', 'membership2') . (isset($pending_str[$reason]) ? $pending_str[$reason] : $pending_str['*']);
                     $status = MS_Model_Invoice::STATUS_PENDING;
                     break;
                 default:
                 case 'Partially-Refunded':
                 case 'In-Progress':
                     $success = null;
                     break;
             }
             if ('new_case' == $_POST['txn_type'] && 'dispute' == $_POST['case_type']) {
                 // Status: Dispute
                 $status = MS_Model_Invoice::STATUS_DENIED;
                 $notes = __('Dispute about this payment', 'membership2');
             }
             if (!empty($notes)) {
                 $invoice->add_notes($notes);
             }
             $invoice->save();
             if ($success) {
                 $invoice->pay_it($this->id, $external_id);
             } elseif (!empty($status)) {
                 $invoice->status = $status;
                 $invoice->save();
                 $invoice->changed();
             }
             do_action('ms_gateway_paypalsingle_payment_processed_' . $status, $invoice, $subscription);
         } else {
             $reason = 'Unexpected transaction response';
             switch (true) {
                 case is_wp_error($response):
                     $reason = 'Response is error';
                     break;
                 case 200 != $response['response']['code']:
                     $reason = 'Response code is ' . $response['response']['code'];
                     break;
                 case empty($response['body']):
                     $reason = 'Response is empty';
                     break;
                 case 'VERIFIED' != $response['body']:
                     $reason = sprintf('Expected response "%s" but got "%s"', 'VERIFIED', (string) $response['body']);
                     break;
                 case $invoice->id != $invoice_id:
                     $reason = sprintf('Expected invoice_id "%s" but got "%s"', $invoice->id, $invoice_id);
                     break;
                 case MS_Model_Transactionlog::was_processed(self::ID, $external_id):
                     $reason = 'Duplicate: Already processed that transaction.';
                     break;
             }
             $notes = 'Response Error: ' . $reason;
             $exit = true;
         }
     } else {
         // Did not find expected POST variables. Possible access attempt from a non PayPal site.
         $u_agent = $_SERVER['HTTP_USER_AGENT'];
         if (false === strpos($u_agent, 'PayPal')) {
             // Very likely someone tried to open the URL manually. Redirect to home page
             $notes = 'Error: Missing POST variables. Redirect user to Home-URL.';
             $redirect = MS_Helper_Utility::home_url('/');
         } else {
             $notes = 'Error: Missing POST variables. Identification is not possible.';
         }
         $exit = true;
     }
     if (!$log) {
         do_action('ms_gateway_transaction_log', self::ID, 'handle', $success, $subscription_id, $invoice_id, $amount, $notes, $external_id);
         if ($redirect) {
             wp_safe_redirect($redirect);
             exit;
         }
         if ($exit) {
             exit;
         }
     } else {
         $log->invoice_id = $invoice_id;
         $log->subscription_id = $subscription_id;
         $log->amount = $amount;
         $log->description = $notes;
         $log->external_id = $external_id;
         if ($success) {
             $log->manual_state('ok');
         }
         $log->save();
     }
     do_action('ms_gateway_paypalsingle_handle_return_after', $this, $log);
     if ($log) {
         return $log;
     }
 }
 /**
  * Processes gateway IPN return.
  *
  * @since  1.0.0
  * @param  MS_Model_Transactionlog $log Optional. A transaction log item
  *         that will be updated instead of creating a new log entry.
  */
 public function handle_return($log = false)
 {
     $success = false;
     $exit = false;
     $redirect = false;
     $notes = '';
     $status = null;
     $external_id = null;
     $invoice_id = 0;
     $subscription_id = 0;
     $amount = 0;
     if (!empty($_POST['vendor_order_id']) && !empty($_POST['md5_hash'])) {
         $invoice_id = intval($_POST['vendor_order_id']);
         $invoice = MS_Factory::load('MS_Model_Invoice', $invoice_id);
         $raw_hash = $_POST['sale_id'] . $this->seller_id . $_POST['invoice_id'] . $this->secret_word;
         $md5_hash = strtoupper(md5($raw_hash));
         if ($md5_hash == $_POST['md5_hash'] && !empty($_POST['message_type']) && ($invoice->id = $invoice_id)) {
             $subscription = $invoice->get_subscription();
             $membership = $subscription->get_membership();
             $member = $subscription->get_member();
             $subscription_id = $subscription->id;
             $external_id = $_POST['invoice_id'];
             $amount = (double) $_POST['invoice_list_amount'];
             switch ($_POST['message_type']) {
                 case 'RECURRING_INSTALLMENT_SUCCESS':
                     $notes = 'Payment received';
                     // Not sure if the invoice was already paid via the
                     // INVOICE_STATUS_CHANGED message
                     if (!$invoice->is_paid()) {
                         $success = true;
                     }
                     break;
                 case 'INVOICE_STATUS_CHANGED':
                     $notes = sprintf('Invoice was %s', $_POST['invoice_status']);
                     switch ($_POST['invoice_status']) {
                         case 'deposited':
                             // Not sure if invoice was already paid via the
                             // RECURRING_INSTALLMENT_SUCCESS message.
                             if (!$invoice->is_paid()) {
                                 $success = true;
                             }
                             break;
                         case 'declied':
                             $status = MS_Model_Invoice::STATUS_DENIED;
                             break;
                     }
                     break;
                 case 'RECURRING_STOPPED':
                     $notes = 'Recurring payments stopped manually';
                     $member->cancel_membership($membership->id);
                     $member->save();
                     break;
                 case 'FRAUD_STATUS_CHANGED':
                     $notes = 'Ignored: Users Fraud-status was checked';
                     $success = null;
                     break;
                 case 'ORDER_CREATED':
                     $notes = 'Ignored: 2Checkout created a new order';
                     $success = null;
                     break;
                 case 'RECURRING_RESTARTED':
                     $notes = 'Ignored: Recurring payments started';
                     $success = null;
                     break;
                 case 'RECURRING_COMPLETE':
                     $notes = 'Ignored: Recurring complete';
                     $success = null;
                     break;
                 case 'RECURRING_INSTALLMENT_FAILED':
                     $notes = 'Ignored: Recurring payment failed';
                     $success = null;
                     $status = MS_Model_Invoice::STATUS_PENDING;
                     break;
                 default:
                     $notes = sprintf('Warning: Unclear command "%s"', $_POST['message_type']);
                     break;
             }
             $invoice->add_notes($notes);
             $invoice->save();
             if ($success) {
                 $invoice->pay_it($this->id, $external_id);
             } elseif (!empty($status)) {
                 $invoice->status = $status;
                 $invoice->save();
                 $invoice->changed();
             }
             do_action('ms_gateway_2checkout_payment_processed_' . $status, $invoice, $subscription);
         } else {
             $reason = 'Unexpected transaction response';
             switch (true) {
                 case $md5_hash != $_POST['md5_hash']:
                     $reason = 'MD5 Hash invalid';
                     break;
                 case empty($_POST['message_type']):
                     $reason = 'Message type is empty';
                     break;
                 case $invoice->id != $invoice_id:
                     $reason = sprintf('Expected invoice_id "%s" but got "%s"', $invoice->id, $invoice_id);
                     break;
             }
             $notes = 'Response Error: ' . $reason;
             MS_Helper_Debug::log($notes);
             MS_Helper_Debug::log($response);
             $exit = true;
         }
     } else {
         // Did not find expected POST variables. Possible access attempt from a non PayPal site.
         $notes = 'Error: Missing POST variables. Identification is not possible.';
         MS_Helper_Debug::log($notes);
         $redirect = MS_Helper_Utility::home_url('/');
         $exit = true;
     }
     if (!$log) {
         do_action('ms_gateway_transaction_log', self::ID, 'handle', $success, $subscription_id, $invoice_id, $amount, $notes, $external_id);
         if ($redirect) {
             wp_safe_redirect($redirect);
             exit;
         }
         if ($exit) {
             exit;
         }
     } else {
         $log->invoice_id = $invoice_id;
         $log->subscription_id = $subscription_id;
         $log->amount = $amount;
         $log->description = $notes;
         $log->external_id = $external_id;
         if ($success) {
             $log->manual_state('ok');
         }
         $log->save();
     }
     do_action('ms_gateway_2checkout_handle_return_after', $this);
     if ($log) {
         return $log;
     }
 }
 /**
  * Processes gateway IPN return.
  *
  * @since  1.0.0
  * @param  MS_Model_Transactionlog $log Optional. A transaction log item
  *         that will be updated instead of creating a new log entry.
  */
 public function handle_return($log = false)
 {
     $success = false;
     $ignore = false;
     $exit = false;
     $redirect = false;
     $notes = '';
     $status = null;
     $notes_pay = '';
     $notes_txn = '';
     $external_id = null;
     $invoice_id = 0;
     $subscription_id = 0;
     $amount = 0;
     $transaction_type = '';
     $payment_status = '';
     $ext_type = false;
     if (!empty($_POST['txn_type'])) {
         $transaction_type = strtolower($_POST['txn_type']);
     }
     if (isset($_POST['mc_gross'])) {
         $amount = (double) $_POST['mc_gross'];
     } elseif (isset($_POST['mc_amount3'])) {
         // mc_amount1 and mc_amount2 are for trial period prices.
         $amount = (double) $_POST['mc_amount3'];
     }
     if (!empty($_POST['payment_status'])) {
         $payment_status = strtolower($_POST['payment_status']);
     }
     if (!empty($_POST['txn_id'])) {
         $external_id = $_POST['txn_id'];
     }
     if (!empty($_POST['mc_currency'])) {
         $currency = $_POST['mc_currency'];
     }
     // Step 1: Find the invoice_id and determine if payment is M2 or M1.
     if ($payment_status || $transaction_type) {
         if (!empty($_POST['invoice'])) {
             // BEST CASE:
             // 'invoice' is set in all regular M2 subscriptions!
             $invoice_id = intval($_POST['invoice']);
             /*
              * PayPal only knows the first invoice of the subscription.
              * So we need to check: If the invoice is already paid then the
              * payment is for a follow-up invoice.
              */
             $invoice = MS_Factory::load('MS_Model_Invoice', $invoice_id);
             if ($invoice->is_paid()) {
                 $subscription = $invoice->get_subscription();
                 $invoice_id = $subscription->first_unpaid_invoice();
             }
         } elseif (!empty($_POST['custom'])) {
             // FALLBACK A:
             // Maybe it's an imported M1 subscription.
             $infos = explode(':', $_POST['custom']);
             if (count($infos) > 2) {
                 // $infos should contain [timestamp, user_id, sub_id, key]
                 $m1_user_id = intval($infos[1]);
                 $m1_sub_id = intval($infos[2]);
                 // Roughtly equals M2 membership->id.
                 // M1 payments use the following type/status values.
                 $pay_types = array('subscr_signup', 'subscr_payment');
                 $pay_stati = array('completed', 'processed');
                 if ($m1_user_id > 0 && $m1_sub_id > 0) {
                     if (in_array($transaction_type, $pay_types)) {
                         $ext_type = 'm1';
                     } elseif (in_array($payment_status, $pay_stati)) {
                         $ext_type = 'm1';
                     }
                 }
                 if ('m1' == $ext_type) {
                     $is_linked = false;
                     // Seems to be a valid M1 payment:
                     // Find the associated imported subscription!
                     $subscription = MS_Model_Import::find_subscription($m1_user_id, $m1_sub_id, 'source', self::ID);
                     if (!$subscription) {
                         $membership = MS_Model_Import::membership_by_source($m1_sub_id);
                         if ($membership) {
                             $is_linked = true;
                             $notes = sprintf('Error: User is not subscribed to Membership %s.', $membership->id);
                         }
                     }
                     $invoice_id = $subscription->first_unpaid_invoice();
                     if (!$is_linked && !$invoice_id) {
                         MS_Model_Import::need_matching($m1_sub_id, 'm1');
                     }
                 }
                 // end if: 'm1' == $ext_type
             }
         } elseif (!empty($_POST['btn_id']) && !empty($_POST['payer_email'])) {
             // FALLBACK B:
             // Payment was made by a custom PayPal Payment button.
             $user = get_user_by('email', $_POST['payer_email']);
             if ($user && $user->ID) {
                 $ext_type = 'pay_btn';
                 $is_linked = false;
                 $subscription = MS_Model_Import::find_subscription($user->ID, $_POST['btn_id'], 'pay_btn', self::ID);
                 if (!$subscription) {
                     $membership = MS_Model_Import::membership_by_matching('pay_btn', $_POST['btn_id']);
                     if ($membership) {
                         $is_linked = true;
                         $notes = sprintf('Error: User is not subscribed to Membership %s.', $membership->id);
                     }
                 }
                 $invoice_id = $subscription->first_unpaid_invoice();
                 if (!$is_linked && !$invoice_id) {
                     MS_Model_Import::need_matching($_POST['btn_id'], 'pay_btn');
                 }
             } else {
                 $notes = sprintf('Error: Could not find user "%s".', $_POST['payer_email']);
             }
             // end if: 'pay_btn' == $ext_type
         }
     }
     // Step 2a: Check if the txn_id was already processed by M2.
     if (MS_Model_Transactionlog::was_processed(self::ID, $external_id)) {
         $notes = 'Duplicate: Already processed that transaction.';
         $success = false;
         $ignore = true;
     } elseif ($invoice_id) {
         if ($this->is_live_mode()) {
             $domain = 'https://www.paypal.com';
         } else {
             $domain = 'https://www.sandbox.paypal.com';
         }
         // PayPal post authenticity verification.
         $ipn_data = (array) stripslashes_deep($_POST);
         $ipn_data['cmd'] = '_notify-validate';
         $response = wp_remote_post($domain . '/cgi-bin/webscr', array('timeout' => 60, 'sslverify' => false, 'httpversion' => '1.1', 'body' => $ipn_data));
         $invoice = MS_Factory::load('MS_Model_Invoice', $invoice_id);
         if (!is_wp_error($response) && 200 == $response['response']['code'] && !empty($response['body']) && 'VERIFIED' == $response['body'] && $invoice->id == $invoice_id) {
             $subscription = $invoice->get_subscription();
             $membership = $subscription->get_membership();
             $member = $subscription->get_member();
             $subscription_id = $subscription->id;
             // Process PayPal payment status
             if ($payment_status) {
                 switch ($payment_status) {
                     // Successful payment
                     case 'completed':
                     case 'processed':
                         $success = true;
                         if ($amount == $invoice->total) {
                             $notes .= __('Payment successful', 'membership2');
                         } else {
                             $notes .= __('Payment registered, though amount differs from invoice.', 'membership2');
                         }
                         break;
                     case 'reversed':
                         $notes_pay = __('Last transaction has been reversed. Reason: Payment has been reversed (charge back).', 'membership2');
                         $status = MS_Model_Invoice::STATUS_DENIED;
                         $ignore = true;
                         break;
                     case 'refunded':
                         $notes_pay = __('Last transaction has been reversed. Reason: Payment has been refunded.', 'membership2');
                         $status = MS_Model_Invoice::STATUS_DENIED;
                         $ignore = true;
                         break;
                     case 'denied':
                         $notes_pay = __('Last transaction has been reversed. Reason: Payment Denied.', 'membership2');
                         $status = MS_Model_Invoice::STATUS_DENIED;
                         $ignore = true;
                         break;
                     case 'pending':
                         lib3()->array->strip_slashes($_POST, 'pending_reason');
                         $notes_pay = __('Last transaction is pending.', 'membership2') . ' ';
                         switch ($_POST['pending_reason']) {
                             case 'address':
                                 $notes_pay .= __('Customer did not include a confirmed shipping address', 'membership2');
                                 break;
                             case 'authorization':
                                 $notes_pay .= __('Funds not captured yet', 'membership2');
                                 break;
                             case 'echeck':
                                 $notes_pay .= __('The eCheck has not cleared yet', 'membership2');
                                 break;
                             case 'intl':
                                 $notes_pay .= __('Payment waiting for approval by service provider', 'membership2');
                                 break;
                             case 'multi-currency':
                                 $notes_pay .= __('Payment waiting for service provider to handle multi-currency process', 'membership2');
                                 break;
                             case 'unilateral':
                                 $notes_pay .= __('Customer did not register or confirm his/her email yet', 'membership2');
                                 break;
                             case 'upgrade':
                                 $notes_pay .= __('Waiting for service provider to upgrade the PayPal account', 'membership2');
                                 break;
                             case 'verify':
                                 $notes_pay .= __('Waiting for service provider to verify his/her PayPal account', 'membership2');
                                 break;
                             default:
                                 $notes_pay .= __('Unknown reason', 'membership2');
                                 break;
                         }
                         $status = MS_Model_Invoice::STATUS_PENDING;
                         $ignore = true;
                         break;
                     default:
                     case 'partially-refunded':
                     case 'in-progress':
                         $notes_pay = sprintf(__('Not handling payment_status: %s', 'membership2'), $payment_status);
                         $ignore = true;
                         break;
                 }
             }
             // Check for subscription details
             if ($transaction_type) {
                 switch ($transaction_type) {
                     case 'subscr_signup':
                     case 'subscr_payment':
                         // Payment was received
                         $notes_txn = __('PayPal Subscripton has been created.', 'membership2');
                         if (0 == $invoice->total) {
                             $success = true;
                         } else {
                             $ignore = true;
                         }
                         break;
                     case 'subscr_modify':
                         // Payment profile was modified
                         $notes_txn = __('PayPal Subscription has been modified.', 'membership2');
                         $ignore = true;
                         break;
                     case 'recurring_payment_profile_canceled':
                     case 'subscr_cancel':
                         // Subscription was manually cancelled.
                         $notes_txn = __('PayPal Subscription has been canceled.', 'membership2');
                         $member->cancel_membership($membership->id);
                         $member->save();
                         $ignore = true;
                         break;
                     case 'recurring_payment_suspended':
                         // Recurring subscription was manually suspended.
                         $notes_txn = __('PayPal Subscription has been suspended.', 'membership2');
                         $member->cancel_membership($membership->id);
                         $member->save();
                         $ignore = true;
                         break;
                     case 'recurring_payment_suspended_due_to_max_failed_payment':
                         // Recurring subscription was automatically suspended.
                         $notes_txn = __('PayPal Subscription has failed.', 'membership2');
                         $member->cancel_membership($membership->id);
                         $member->save();
                         $ignore = true;
                         break;
                     case 'new_case':
                         // New Dispute was filed for a payment.
                         $status = MS_Model_Invoice::STATUS_DENIED;
                         $ignore = true;
                         break;
                     case 'subscr_eot':
                         /*
                          * Meaning: Subscription expired.
                          *
                          *   - after a one-time payment was made
                          *   - after last transaction in a recurring subscription
                          *   - payment failed
                          *   - ...
                          *
                          * We do not handle this event...
                          *
                          * One time payment sends 3 messages:
                          *   1. subscr_start (new subscription starts)
                          *   2. subscr_payment (payment confirmed)
                          *   3. subscr_eot (subscription ends)
                          */
                         $notes_txn = __('No more payments will be made for this subscription.', 'membership2');
                         $ignore = true;
                         break;
                     default:
                         // Other event that we do not have a case for...
                         $notes_txn = sprintf(__('Not handling txn_type: %s', 'membership2'), $transaction_type);
                         $ignore = true;
                         break;
                 }
             }
             if (!empty($notes_pay)) {
                 $invoice->add_notes($notes_pay);
             }
             if (!empty($notes_txn)) {
                 $invoice->add_notes($notes_txn);
             }
             if ($notes_pay) {
                 $notes .= ($notes ? ' | ' : '') . $notes_pay;
             }
             if ($notes_txn) {
                 $notes .= ($notes ? ' | ' : '') . $notes_txn;
             }
             $invoice->save();
             if ($success) {
                 $invoice->pay_it($this->id, $external_id);
             } elseif (!empty($status)) {
                 $invoice->status = $status;
                 $invoice->save();
                 $invoice->changed();
             }
             do_action('ms_gateway_paypalstandard_payment_processed_' . $status, $invoice, $subscription);
         } else {
             $reason = 'Unexpected transaction response';
             switch (true) {
                 case is_wp_error($response):
                     $reason = 'PayPal did not verify this transaction: Unknown error';
                     break;
                 case 200 != $response['response']['code']:
                     $reason = sprintf('PayPal did not verify the transaction: Code %s', $response['response']['code']);
                     break;
                 case empty($response['body']):
                     $reason = 'PayPal did not verify this transaction: Empty response';
                     break;
                 case 'VERIFIED' != $response['body']:
                     $reason = sprintf('PayPal did not verify this transaction: "%s"', $response['body']);
                     break;
                 case !$invoice->id:
                     $reason = sprintf('Specified invoice does not exist: "%s"', $invoice_id);
                     break;
             }
             $notes = 'Response Error: ' . $reason;
             $exit = true;
         }
     } else {
         // Did not find expected POST variables. Possible access attempt from a non PayPal site.
         $u_agent = $_SERVER['HTTP_USER_AGENT'];
         if (!$log && false === strpos($u_agent, 'PayPal')) {
             // Very likely someone tried to open the URL manually. Redirect to home page
             if (!$notes) {
                 $notes = 'Ignored: Missing POST variables. Redirect to Home-URL.';
             }
             $redirect = MS_Helper_Utility::home_url('/');
             $ignore = true;
             $success = false;
         } elseif ('m1' == $ext_type) {
             /*
              * The payment belongs to an imported M1 subscription and could
              * not be auto-matched.
              * Do not return an error code, but also do not modify any
              * invoice/subscription.
              */
             $notes = 'M1 Payment detected. Manual matching required.';
             $ignore = false;
             $success = false;
         } elseif ('pay_btn' == $ext_type) {
             /*
              * The payment was made by a PayPal Payment button that was
              * created in the PayPal account and not by M1/M2.
              */
             $notes = 'PayPal Payment button detected. Manual matching required.';
             $ignore = false;
             $success = false;
         } else {
             // PayPal sent us a IPN notice about a non-Membership payment:
             // Ignore it, but add it to the logs.
             if (!empty($notes)) {
                 // We already have an error message, do nothing.
             } elseif (!$payment_status || !$transaction_type) {
                 $notes = 'Ignored: Payment_status or txn_type not specified. Cannot process.';
             } elseif (empty($_POST['invoice']) && empty($_POST['custom'])) {
                 $notes = 'Ignored: No invoice or custom data specified.';
             } else {
                 $notes = 'Ignored: Missing POST variables. Identification is not possible.';
             }
             $ignore = true;
             $success = false;
         }
         $exit = true;
     }
     if ($ignore && !$success) {
         $success = null;
         $notes .= ' [Irrelevant IPN call]';
     }
     if (!$log) {
         do_action('ms_gateway_transaction_log', self::ID, 'handle', $success, $subscription_id, $invoice_id, $amount, $notes, $external_id);
         if ($redirect) {
             wp_safe_redirect($redirect);
             exit;
         }
         if ($exit) {
             exit;
         }
     } else {
         $log->invoice_id = $invoice_id;
         $log->subscription_id = $subscription_id;
         $log->amount = $amount;
         $log->description = $notes;
         $log->external_id = $external_id;
         if ($success) {
             $log->manual_state('ok');
         } elseif ($ignore) {
             $log->manual_state('ignore');
         }
         $log->save();
     }
     do_action('ms_gateway_paypalstandard_handle_return_after', $this);
     if ($log) {
         return $log;
     }
 }
    protected function gateway_item_settings($gateway)
    {
        $is_online = lib3()->net->is_online(MS_Helper_Utility::home_url('/'));
        $row_class = 'gateway-' . $gateway->id;
        $active_class = 'ms-gateway-not-configured';
        if ($gateway->is_configured()) {
            $row_class .= ' is-configured';
            $active_class = 'ms-gateway-configured';
        } else {
            $row_class .= ' not-configured';
        }
        if ($gateway->is_live_mode()) {
            $row_class .= ' is-live';
        } else {
            $row_class .= ' is-sandbox';
        }
        if (!$is_online) {
            $row_class .= ' is-offline';
        } else {
            $row_class .= ' is-online';
        }
        $actions = array(sprintf('<a href="%1$s">%2$s</a>', MS_Controller_Plugin::get_admin_url('billing', array('gateway_id' => $gateway->id)), __('View Transactions', 'membership2')), sprintf('<a href="%1$s">%2$s</a>', MS_Controller_Plugin::get_admin_url('billing', array('show' => 'logs', 'gateway_id' => $gateway->id)), __('View Logs', 'membership2')));
        $actions = apply_filters('gateway_settings_actions', $actions, $gateway);
        $action_tag = array();
        foreach ($actions as $action => $link) {
            $action_tag[] = "<span class='{$action}'>{$link}</span>";
        }
        $toggle = array('id' => 'ms-toggle-' . $gateway->id, 'type' => MS_Helper_Html::INPUT_TYPE_RADIO_SLIDER, 'value' => $gateway->active, 'data_ms' => array('action' => MS_Controller_Gateway::AJAX_ACTION_TOGGLE_GATEWAY, 'gateway_id' => $gateway->id));
        $settings_class = 'MS_Gateway_' . ucwords(esc_attr($gateway->id)) . '_View_Settings';
        $settings = MS_Factory::create($settings_class);
        $settings->data = array('model' => $gateway);
        // -- Output the form --
        ?>
		<div class="ms-gateway-item <?php 
        echo esc_attr($row_class);
        ?>
">
			<span class="gateway-title">
				<label class="gateway-toggle gateway-name" for="settings-<?php 
        echo esc_attr($gateway->id);
        ?>
">
					<i class="row-status-close wpmui-fa wpmui-fa-caret-right"></i>
					<i class="row-status-open wpmui-fa wpmui-fa-caret-down"></i>
					<?php 
        echo esc_html($gateway->name);
        ?>
				</label>
				<span class="gateway-description">
					<?php 
        echo esc_html($gateway->description);
        ?>
				</span>
				<span class="wpmui-fa offline-flag" title="<?php 
        echo __('Website seems to be not publicly available. This payment method might not work.', 'membership2');
        ?>
">
				</span>
			</span>

			<span class="mode">
				<span class="mode-sandbox"><?php 
        _e('Sandbox', 'membership2');
        ?>
</span>
				<span class="mode-live"><?php 
        _e('Live', 'membership2');
        ?>
</span>
			</span>

			<div class="ms-gateway-status <?php 
        echo esc_attr($active_class);
        ?>
 ms-active-wrapper-<?php 
        echo esc_attr($gateway->id);
        ?>
">
				<?php 
        MS_Helper_Html::html_element($toggle);
        ?>
				<div class="ms-gateway-setup-wrapper">
					<label for="settings-<?php 
        echo esc_attr($gateway->id);
        ?>
" class="button">
						<i class="wpmui-fa wpmui-fa-cog"></i> <?php 
        _e('Configure', 'membership2');
        ?>
					</label>
				</div>

			</div>

			<div class="row-actions"><?php 
        echo implode(' | ', $action_tag);
        ?>
</div>

			<input type="checkbox" class="show-settings" id="settings-<?php 
        echo esc_attr($gateway->id);
        ?>
"/>
			<div class="ms-gateway-settings">
				<?php 
        echo $settings->to_html();
        ?>
			</div>

		</div>
		<?php 
    }
 /**
  * Returns the URL to display after successful logout.
  *
  * @since  1.0.0
  *
  * @param  bool $filter Optional. If set to false then the URL is not
  *                      filtered and the default value is returned.
  * @return string URL of the page to display after logout.
  */
 public static function get_url_after_logout($filter = true)
 {
     if (isset($_REQUEST['redirect_to'])) {
         $url = $_REQUEST['redirect_to'];
         $enforce = true;
         // This redirection was enforced via REUQEST param.
     } else {
         $url = MS_Helper_Utility::home_url('/');
         $enforce = false;
         // This is the default redirection.
     }
     if ($filter) {
         $url = apply_filters('ms_url_after_logout', $url, $enforce);
     }
     return $url;
 }