/**
     * Display a filter to select the current membership
     *
     * @since  1.0.0
     */
    public function membership_filter()
    {
        $memberships = MS_Model_Membership::get_membership_names(array('active' => true, 'include_guest' => false));
        $url = esc_url_raw(remove_query_arg(array('membership_id', 'paged')));
        $links = array();
        $links['all'] = array('label' => __('All', MS_TEXT_DOMAIN), 'url' => $url);
        foreach ($memberships as $id => $name) {
            if (empty($name)) {
                $name = __('(No Name)', MS_TEXT_DOMAIN);
            }
            $filter_url = esc_url_raw(add_query_arg(array('membership_id' => $id), $url));
            $links['ms-' . $id] = array('label' => esc_html($name), 'url' => $filter_url);
        }
        ?>
		<div class="wp-filter">
			<ul class="filter-links">
				<?php 
        foreach ($links as $key => $item) {
            $is_current = MS_Helper_Utility::is_current_url($item['url']);
            $class = $is_current ? 'current' : '';
            ?>
					<li>
						<a href="<?php 
            echo esc_url($item['url']);
            ?>
" class="<?php 
            echo esc_attr($class);
            ?>
">
							<?php 
            echo esc_html($item['label']);
            ?>
						</a>
					</li>
				<?php 
        }
        ?>
			</ul>
		</div>
		<?php 
    }
 /**
  * Implements a multi-dimensional array_intersect_assoc.
  *
  * The standard array_intersect_assoc does the intersection based on string
  * values of the keys.
  * We need to find a way to recursively check multi-dimensional arrays.
  *
  * Note that we are not passing values here but references.
  *
  * @since  1.0.0
  *
  * @param mixed $arr1 First array to intersect.
  * @param mixed $arr2 Second array to intersect.
  * @return array Combined array.
  */
 public static function array_intersect_assoc_deep(&$arr1, &$arr2)
 {
     // If not arrays, at least associate the strings.
     // If 1 argument is an array and the other not throw error.
     if (!is_array($arr1) && !is_array($arr2)) {
         $arr1 = (string) $arr1;
         $arr2 = (string) $arr2;
         return $arr1 == $arr2 ? $arr1 : false;
     } elseif (is_array($arr1) !== is_array($arr2)) {
         MS_Helper_Debug::log('WARNING: MS_Helper_Utility::array_intersect_assoc_deep() - ' . 'Both params need to be of same type (array or string).', true);
         return false;
     }
     $intersections = array_intersect(array_keys($arr1), array_keys($arr2));
     $assoc_array = array();
     // Time to recursively run through the arrays
     foreach ($intersections as $key) {
         $result = MS_Helper_Utility::array_intersect_assoc_deep($arr1[$key], $arr2[$key]);
         if ($result) {
             $assoc_array[$key] = $result;
         }
     }
     return apply_filters('ms_helper_utility_array_intersect_assoc_deep', $assoc_array, $arr1, $arr2);
 }
 /**
  * Returns the unique HEX color for this membership.
  * The color is calculated from the membership-ID and therefore will never
  * change.
  *
  * @since  1.0.0
  * @api
  *
  * @return string Hex color, e.g. '#FFFFFF'
  */
 public function get_color()
 {
     return MS_Helper_Utility::color_index($this->type . $this->id);
 }
예제 #4
0
 /**
  * Verify if current url has protection rules.
  *
  * @since  1.0.0
  *
  * @return boolean True if has access, false otherwise.
  */
 protected function has_rule_for_current_url()
 {
     $has_rules = false;
     if (MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_URL_GROUPS)) {
         $url = MS_Helper_Utility::get_current_url();
         if ($this->check_url_expression_match($url, $this->get_protected_urls())) {
             $has_rules = true;
         }
     }
     return apply_filters('ms_rule_url_model_has_access', $has_rules, $this);
 }
    /**
     * Display the full settings form, used either by first membership
     * "completed" popup and also by the general settings tab.
     *
     * @since  1.0.0
     * @return string HTML code
     */
    public function html_full_form()
    {
        $fields = $this->prepare_fields();
        ob_start();
        ?>
		<div class="ms-setup-form">
			<?php 
        if (!MS_Plugin::is_network_wide()) {
            ?>
			<div class="ms-setup-nav">
				<div class="ms-title">
					<i class="ms-icon dashicons dashicons-menu"></i>
					<?php 
            _e('Please select pages you want to appear in your Navigation', 'membership2');
            ?>
				</div>
				<div class="ms-description">
					<?php 
            printf(__('You can always change those later by going to %1$s in your admin sidebar.', 'membership2'), sprintf('<a href="%1$s" target="_blank">%2$s</a>', admin_url('nav-menus.php'), __('Appearance') . ' &raquo; ' . __('Menus')));
            ?>
				</div>
				<?php 
            echo $this->show_menu_controls();
            ?>
			</div>
			<?php 
        } else {
            ?>
			<div class="ms-setup-site">
				<div class="ms-title">
					<i class="ms-icon dashicons dashicons-admin-network"></i>
					<?php 
            _e('Select the Site that hosts Membership 2 Pages', 'membership2');
            ?>
				</div>
				<div class="ms-description">
					<?php 
            _e('When you change the site new Membership 2 Pages are created on the selected site. You can customize or replace these pages at any time.', 'membership2');
            ?>
				</div>
				<?php 
            $site_options = MS_Helper_Settings::get_blogs();
            $site_fields = array(array('type' => MS_Helper_Html::INPUT_TYPE_SELECT, 'id' => 'network_site', 'title' => __('Select the site that hosts the Membership 2 Pages', 'membership2'), 'value' => MS_Model_Pages::get_site_info('id'), 'field_options' => $site_options, 'class' => 'ms-site-options'), array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => 'action', 'value' => 'network_site'), array('type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'name' => '_wpnonce', 'value' => wp_create_nonce('network_site')), array('type' => MS_Helper_Html::INPUT_TYPE_SUBMIT, 'value' => __('Save', 'membership2')), array('type' => MS_Helper_Html::INPUT_TYPE_BUTTON, 'class' => 'ms-setup-pages-cancel', 'value' => __('Cancel', 'membership2')));
            ?>
				<div class="ms-setup-pages-site">
					<div class="ms-setup-pages-site-info"><?php 
            printf(__('Membership pages are located on site %s', 'membership2'), '<strong>' . MS_Model_Pages::get_site_info('title') . '</strong>');
            ?>
					<a href="#change-site" class="ms-setup-pages-change-site"><?php 
            _e('Change site...', 'membership2');
            ?>
</a></div>
					<div class="ms-setup-pages-site-form cf" style="display:none;">
						<?php 
            foreach ($site_fields as $field) {
                MS_Helper_Html::html_element($field);
            }
            ?>
					</div>
				</div>
			</div>
			<?php 
        }
        ?>
			<div class="ms-setup-pages">
				<div class="ms-title">
					<i class="ms-icon dashicons dashicons-admin-page"></i>
					<?php 
        _e('Membership 2 Pages', 'membership2');
        ?>
				</div>
				<div class="ms-description">
					<?php 
        _e('Set Up Membership 2 Pages that will be displayed on your website.', 'membership2');
        ?>
				</div>
				<?php 
        if (is_array($fields['pages'])) {
            $page_types = array_keys($fields['pages']);
            $page_types_menu = array('memberships', 'register', 'account');
            $page_types_rest = array_diff($page_types, $page_types_menu);
            $groups = array('in-menu' => $page_types_menu, 'no-menu' => $page_types_rest);
            $pages_site_id = MS_Model_Pages::get_site_info('id');
            MS_Factory::select_blog($pages_site_id);
            foreach ($groups as $group_key => $group_items) {
                printf('<div class="ms-pages-group %1$s">', esc_attr($group_key));
                foreach ($group_items as $key) {
                    $field = $fields['pages'][$key];
                    ?>
							<div class="ms-settings-page-wrapper">
								<?php 
                    MS_Helper_Html::html_element($field);
                    ?>
								<div class="ms-action">
									<?php 
                    MS_Helper_Html::html_link(array('id' => 'url_page_' . $field['value'], 'url' => '', 'value' => __('View Page', 'membership2'), 'target' => '_blank', 'data_ms' => array('base' => MS_Helper_Utility::get_home_url($pages_site_id, 'index.php?page_id='))));
                    ?>
									<span> | </span>
									<?php 
                    MS_Helper_Html::html_link(array('id' => 'edit_url_page_' . $field['value'], 'url' => '', 'value' => __('Edit Page', 'membership2'), 'target' => '_blank', 'data_ms' => array('base' => get_admin_url($pages_site_id, 'post.php?action=edit&post='))));
                    ?>
								</div>
							</div>
							<?php 
                }
                echo '</div>';
            }
        } else {
            echo $fields['pages'];
        }
        MS_Factory::revert_blog();
        ?>
			</div>
		</div>
		<?php 
        $html = ob_get_clean();
        return apply_filters('ms_view_settings_page_setup_to_html', $html);
    }
 /**
  * Get MS Page URL.
  *
  * @since  1.0.0
  *
  * @param string|WP_Post $page_type The page type name or a WP_Post object.
  * @param boolean $ssl If wanted a SSL url. Set to null to use auto detection.
  * @return string The MS Page URL.
  */
 public static function get_page_url($page_type, $ssl = null)
 {
     static $Urls = array();
     $site_id = self::get_site_info('id');
     $page_id = self::get_page_id($page_type);
     if (!isset($Urls[$page_id])) {
         if (is_multisite()) {
             $url = get_blog_permalink($site_id, $page_id);
         } else {
             $url = get_permalink($page_id);
         }
         if (null === $ssl) {
             $ssl = is_ssl();
         }
         if ($ssl) {
             $url = MS_Helper_Utility::get_ssl_url($url);
         }
         $Urls[$page_id] = apply_filters('ms_model_pages_get_ms_page_url', $url, $page_type, $ssl, $site_id);
     }
     return $Urls[$page_id];
 }
 /**
  * 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);
 }
예제 #8
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);
     }
 }
 /**
  * Force SSL when Stripe in Live mode
  *
  * @since  1.0.2.5
  *
  * @param String $url The modified or raw URL
  * @param String $page_type Check if this is a membership page
  * @param Bool $ssl If SSL enabled or not
  * @param Int $site_id The ID of site
  *
  * @return String $url Modified or raw URL
  */
 public function ms_model_pages_get_ms_page_url_cb($url, $page_type, $ssl, $site_id)
 {
     /**
      * Constant M2_FORCE_NO_SSL
      *
      * It's needed, if :
      *      - the user has no SSL
      *      - the user has SSL but doesn't want to force
      *      - The user has multiple gateways like Paypal and Stripe and doesn't want to force
      *
      * If the user has SSL certificate, this rule won't work
      */
     if (!defined('M2_FORCE_NO_SSL') || M2_FORCE_NO_SSL != false) {
         if ($this->active && $this->is_live_mode()) {
             if ($page_type == MS_Model_Pages::MS_PAGE_MEMBERSHIPS) {
                 $url = MS_Helper_Utility::get_ssl_url($url);
             }
         }
     }
     return $url;
 }
 /**
  * Localize the URL to the current language.
  *
  * @since  1.0.1.0
  * @param  string $url The default URL.
  * @param  string $page_type Not used.
  * @param  bool $ssl Should the URL use ssl protocol?
  * @return string Localized URL.
  */
 public function translate_page_url($url, $page_type, $ssl)
 {
     if ($this->current_lang != $this->default_lang) {
         $post_id = url_to_postid($url);
         $tr_post_id = apply_filters('wpml_object_id', $post_id, 'page', true, $this->current_lang);
         if ($tr_post_id) {
             $url = get_permalink($tr_page_id);
             if (null === $ssl) {
                 $ssl = is_ssl();
             }
             if ($ssl) {
                 $url = MS_Helper_Utility::get_ssl_url($url);
             }
         }
     }
     return $url;
 }
 /**
  * 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;
     }
 }
    /**
     * Display the full settings form, used either by first membership
     * "completed" popup and also by the general settings tab.
     *
     * @since  1.0.0
     * @return string HTML code
     */
    public function html_full_form()
    {
        $fields = $this->prepare_fields();
        ob_start();
        ?>
		<div class="ms-setup-form">
			<?php 
        if (!MS_Plugin::is_network_wide()) {
            ?>
			<div class="ms-setup-nav">
				<div class="ms-title">
					<i class="ms-icon dashicons dashicons-menu"></i>
					<?php 
            _e('Please select pages you want to appear in your Navigation', 'membership2');
            ?>
				</div>
				<div class="ms-description">
					<?php 
            printf(__('You can always change those later by going to %1$s in your admin sidebar.', 'membership2'), sprintf('<a href="%1$s" target="_blank">%2$s</a>', admin_url('nav-menus.php'), __('Appearance') . ' &raquo; ' . __('Menus')));
            ?>
				</div>
				<?php 
            echo $this->show_menu_controls();
            ?>
			</div>
			<?php 
            // Network-wide IS PRO ONLY!
            ?>
			<?php 
        }
        ?>
			<div class="ms-setup-pages">
				<div class="ms-title">
					<i class="ms-icon dashicons dashicons-admin-page"></i>
					<?php 
        _e('Membership 2 Pages', 'membership2');
        ?>
				</div>
				<div class="ms-description">
					<?php 
        _e('Set Up Membership 2 Pages that will be displayed on your website.', 'membership2');
        ?>
				</div>
				<?php 
        if (is_array($fields['pages'])) {
            $page_types = array_keys($fields['pages']);
            $page_types_menu = array('memberships', 'register', 'account');
            $page_types_rest = array_diff($page_types, $page_types_menu);
            $groups = array('in-menu' => $page_types_menu, 'no-menu' => $page_types_rest);
            $pages_site_id = MS_Model_Pages::get_site_info('id');
            MS_Factory::select_blog($pages_site_id);
            foreach ($groups as $group_key => $group_items) {
                printf('<div class="ms-pages-group %1$s">', esc_attr($group_key));
                foreach ($group_items as $key) {
                    $field = $fields['pages'][$key];
                    ?>
							<div class="ms-settings-page-wrapper">
								<?php 
                    MS_Helper_Html::html_element($field);
                    ?>
								<div class="ms-action">
									<?php 
                    MS_Helper_Html::html_link(array('id' => 'url_page_' . $field['value'], 'url' => '', 'value' => __('View Page', 'membership2'), 'target' => '_blank', 'data_ms' => array('base' => MS_Helper_Utility::get_home_url($pages_site_id, 'index.php?page_id='))));
                    ?>
									<span> | </span>
									<?php 
                    MS_Helper_Html::html_link(array('id' => 'edit_url_page_' . $field['value'], 'url' => '', 'value' => __('Edit Page', 'membership2'), 'target' => '_blank', 'data_ms' => array('base' => get_admin_url($pages_site_id, 'post.php?action=edit&post='))));
                    ?>
								</div>
							</div>
							<?php 
                }
                echo '</div>';
            }
        } else {
            echo $fields['pages'];
        }
        MS_Factory::revert_blog();
        ?>
			</div>
		</div>
		<?php 
        $html = ob_get_clean();
        return apply_filters('ms_view_settings_page_setup_to_html', $html);
    }
    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 
    }
예제 #14
0
 /**
  * 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;
 }
 /**
  * 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;
     $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;
     }
 }
 /**
  * Constructs the primary Plugin controller.
  *
  * Created by the MS_Plugin object during the setup_theme action.
  *
  * @since  1.0.0
  */
 public function __construct()
 {
     parent::__construct();
     /**
      * Fix for IE: This is a privacy policy which states, that we do not
      * collect personal contact information without consent.
      *
      * Note that other plugins that output this header later will overwrite
      * it! So this is a default value if no other file sends the P3P header.
      *
      * @since  1.0.2.2
      */
     $p3p_done = false;
     foreach (headers_list() as $header) {
         if (false !== stripos($header, 'P3P:')) {
             $p3p_done = true;
             break;
         }
     }
     if (!$p3p_done) {
         header('P3P:CP="NOI"');
     }
     /*
      * Remove the "&msg" attribute from the URL if it was already present in
      * the previous request.
      */
     if (empty($_POST)) {
         /*
          * No form was submitted:
          * It's save to redirect the request without losing form-data.
          */
         if (isset($_GET['msg']) && isset($_SERVER['HTTP_REFERER']) && MS_Helper_Utility::is_current_url($_SERVER['HTTP_REFERER'])) {
             // A msg is set AND the referer URL has the same msg flag!
             $url = esc_url_raw(remove_query_arg(array('msg')));
             wp_safe_redirect($url);
             exit;
         }
     }
     /**
      * We allow two ways to modify the default Admin-Capability setting:
      *
      * Either by defining the constant in wp-config or by using the filter.
      * The constant takes priority over the filter.
      *
      * @since  1.0.0
      */
     if (defined('MS_ADMIN_CAPABILITY')) {
         $this->capability = MS_ADMIN_CAPABILITY;
     } else {
         $this->capability = apply_filters('ms_admin_user_capability', $this->capability);
     }
     // Create core controllers that are available on every page.
     $this->model = MS_Factory::load('MS_Model_Plugin');
     $this->dialogs = MS_Factory::load('MS_Controller_Dialog');
     $this->controllers['widget'] = MS_Factory::load('MS_Controller_Widget');
     $this->controllers['membership'] = MS_Factory::load('MS_Controller_Membership');
     $this->controllers['protection'] = MS_Factory::load('MS_Controller_Protection');
     $this->controllers['rule'] = MS_Factory::load('MS_Controller_Rule');
     $this->controllers['member'] = MS_Factory::load('MS_Controller_Member');
     $this->controllers['billing'] = MS_Factory::load('MS_Controller_Billing');
     $this->controllers['addon'] = MS_Factory::load('MS_Controller_Addon');
     $this->controllers['pages'] = MS_Factory::load('MS_Controller_Pages');
     $this->controllers['settings'] = MS_Factory::load('MS_Controller_Settings');
     $this->controllers['communication'] = MS_Factory::load('MS_Controller_Communication');
     $this->controllers['gateway'] = MS_Factory::load('MS_Controller_Gateway');
     $this->controllers['admin_bar'] = MS_Factory::load('MS_Controller_Adminbar');
     $this->controllers['membership_metabox'] = MS_Factory::load('MS_Controller_Metabox');
     $this->controllers['membership_shortcode'] = MS_Factory::load('MS_Controller_Shortcode');
     $this->controllers['frontend'] = MS_Factory::load('MS_Controller_Frontend');
     $this->controllers['import'] = MS_Factory::load('MS_Controller_Import');
     $this->controllers['help'] = MS_Factory::load('MS_Controller_Help');
     // API should be the last Controller to create.
     $this->controllers['api'] = MS_Controller_Api::instance();
     // Register all available styles and scripts. Nothing is enqueued.
     $this->add_action('wp_loaded', 'wp_loaded');
     // Setup plugin admin UI.
     $this->add_action('admin_menu', 'add_menu_pages');
     if (MS_Plugin::is_network_wide()) {
         $this->add_action('network_admin_menu', 'add_menu_pages');
     }
     // Select the right page to display.
     $this->add_action('admin_init', 'route_submenu_request');
     // This will do the ADMIN-SIDE initialization of the controllers
     $this->add_action('ms_plugin_admin_setup', 'run_admin_init');
     // Changes the current themes "single" template to the invoice form when an invoice is displayed.
     $this->add_filter('single_template', 'custom_single_template');
     $this->add_filter('page_template', 'custom_page_template');
     // Register styles and javascripts for use in front-end
     $this->add_action('ms_register_public_scripts', 'register_public_scripts');
     $this->add_action('ms_register_public_scripts', 'register_public_styles');
     $this->add_action('wp_enqueue_scripts', 'enqueue_plugin_styles');
     $this->add_action('wp_enqueue_scripts', 'enqueue_plugin_scripts');
 }
 /**
  * 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;
     }
 }
 /**
  * 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);
 }
 /**
  * Checks member permissions and protects current page.
  *
  * Related Action Hooks:
  * - template_redirect
  *
  * @since  1.0.0
  */
 public function protect_current_page()
 {
     do_action('ms_model_plugin_protect_current_page_before', $this);
     // Admin user has access to everything
     if ($this->member->is_normal_admin()) {
         return;
     }
     $access = $this->get_access_info();
     if (!$access['has_access']) {
         MS_Model_Pages::create_missing_pages();
         $no_access_page_url = MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT, false);
         $current_page_url = MS_Helper_Utility::get_current_url();
         // Don't (re-)redirect the protection page.
         if (!MS_Model_Pages::is_membership_page(null, MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT)) {
             $no_access_page_url = esc_url_raw(add_query_arg(array('redirect_to' => urlencode($current_page_url)), $no_access_page_url));
             $no_access_page_url = apply_filters('ms_model_plugin_protected_content_page', $no_access_page_url);
             wp_safe_redirect($no_access_page_url);
             exit;
         }
     }
     do_action('ms_model_plugin_protect_current_page_after', $this);
 }
 /**
  * Display the bulk actions dropdown.
  *
  * @since  1.0.0
  * @access public
  *
  * @param  bool $echo Output or return the HTML code? Default is output.
  */
 public function bulk_actions($echo = true)
 {
     if (!$this->is_search() && !$this->has_items()) {
         return '';
     }
     if (is_null($this->_actions)) {
         $no_new_actions = $this->_actions = $this->get_bulk_actions();
         /**
          * Filter the list table Bulk Actions drop-down.
          *
          * The dynamic portion of the hook name, $this->screen->id, refers
          * to the ID of the current screen, usually a string.
          *
          * This filter can currently only be used to remove bulk actions.
          *
          * @since  1.0.0
          *
          * @param array $actions An array of the available bulk actions.
          */
         $this->_actions = apply_filters("bulk_actions-{$this->screen->id}", $this->_actions);
         $this->_actions = MS_Helper_Utility::array_intersect_assoc_deep($this->_actions, $no_new_actions);
         $two = '';
     } else {
         $two = '2';
     }
     if (empty($this->_actions)) {
         return '';
     }
     if (!$echo) {
         ob_start();
     }
     /**
      * Allow other files to add additional code before the bulk actions.
      *
      * Note that this action is only triggered when bulk actions are
      * actually displayed.
      *
      * @since  1.0.0
      */
     do_action('ms_listtable_before_bulk_actions', $this);
     printf('<select name="action%s">', esc_attr($two));
     printf('<option value="-1" selected="selected">%s</option>', __('Bulk Actions'));
     foreach ($this->_actions as $name => $title) {
         if (is_array($title)) {
             printf('<optgroup label="%s">', esc_attr($name));
             foreach ($title as $value => $label) {
                 printf('<option value="%s">%s</option>', esc_attr($value), esc_attr($label));
             }
             echo '</optgroup>';
         } else {
             printf('<option value="%s">%s</option>', esc_attr($name), esc_attr($title));
         }
     }
     echo '</select>';
     submit_button(__('Apply'), 'action', false, false, array('id' => 'doaction' . esc_attr($two)));
     if (!$echo) {
         return ob_get_clean();
     }
 }
 /**
  * Returns the HTML code.
  *
  * @since  1.0.0
  * @return string
  */
 public function to_html()
 {
     $res_html = '';
     $res_form = '';
     $html = '';
     $valid_forms = array('login', 'logout', 'reset', 'lost');
     extract($this->data);
     if (!isset($form) || !in_array($form, $valid_forms)) {
         if (MS_Model_Member::is_logged_in()) {
             $form = 'logout';
         } elseif (isset($action) && 'resetpass' === $action) {
             $form = 'reset';
         } else {
             $form = 'login';
         }
         $this->data['form'] = $form;
     }
     /**
      * Provide a customized login form.
      *
      * Possible filters to provide a customized login form:
      * - 'ms_shortcode_custom_form-login'
      * - 'ms_shortcode_custom_form-logout'
      * - 'ms_shortcode_custom_form-reset'
      * - 'ms_shortcode_custom_form-lost'
      *
      * @since  1.0.0
      */
     $html = apply_filters('ms_shortcode_custom_form-' . $form, '', $this->data);
     if (!empty($html)) {
         return $html;
     } else {
         $html = '';
     }
     if ('logout' === $form) {
         return $this->logout_form();
     } elseif ('reset' === $form) {
         return $this->reset_form();
     } else {
         if (empty($redirect_login)) {
             $redirect_login = MS_Helper_Utility::get_current_url();
         }
         // Build the Login Form.
         $res_form .= $prefix;
         $res_form .= $this->login_form($redirect_login);
         $res_form .= $this->lostpass_form();
         // Wrap form in optional wrappers.
         if (!empty($wrapwith)) {
             $res_form .= sprintf('<%s class="%s">', esc_attr($wrapwith), esc_attr($wrapwithclass));
             $res_form = sprintf('<%1$s class="%2$s">%3$s</%1$s>', esc_attr($wrapwith), esc_attr($wrapwithclass), $res_form);
         }
         if (!empty($item)) {
             $res_form = sprintf('<%1$s class="%2$s">%3$s</%1$s>', esc_attr($item), esc_attr($itemclass), $res_form);
         }
         if (!empty($holder)) {
             $res_form = sprintf('<%1$s class="%2$s">%3$s</%1$s>', esc_attr($holder), esc_attr($holderclass), $res_form);
         }
         // Complete the HTML output.
         if ($header) {
             $html .= $this->login_header_html();
         }
         $html .= $res_form;
         if ($register && !MS_Model_Member::is_logged_in()) {
             if (MS_Model_Member::can_register()) {
                 $link = sprintf('<a href="%1$s">%2$s</a>', MS_Controller_Frontend::get_registration_url('register'), __('Register', MS_TEXT_DOMAIN));
                 /**
                  * Filter documented in wp-includes/general-template.php
                  */
                 $html .= apply_filters('register', $link);
             }
         }
         // Load the ajax script that handles the Ajax login functions.
         wp_enqueue_script('ms-ajax-login');
         lib2()->ui->data('ms_ajax_login', array('ajaxurl' => admin_url('admin-ajax.php'), 'loadingmessage' => __('Please wait...', MS_TEXT_DOMAIN), 'errormessage' => __('Request failed, please try again.', MS_TEXT_DOMAIN)));
     }
     // Remove linebreaks to bypass the "wpautop" filter.
     $html = str_replace(array("\r\n", "\r", "\n"), '', $html);
     $html = '<div class="ms-membership-form-wrapper">' . $html . '</div>';
     $html = apply_filters('ms_compact_code', $html);
     /*
      * Possible filters to provide a customized login form:
      * - 'ms_shortcode_form-login'
      * - 'ms_shortcode_form-logout'
      * - 'ms_shortcode_form-reset'
      * - 'ms_shortcode_form-lost'
      */
     return apply_filters('ms_shortcode_form-' . $form, $html, $this->data);
 }
 /**
  * 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;
 }
 /**
  * Handle protected media access.
  *
  * Search for masked file and show the proper content, or no access image if don't have access.
  *
  * Realted Action Hooks:
  * - parse_request
  *
  * @since  1.0.0
  *
  * @param WP_Query $query The WP_Query object to filter.
  */
 public function handle_download_protection($query)
 {
     do_action('ms_rule_media_model_handle_download_protection_before', $query, $this);
     $the_file = false;
     $requested_item = false;
     $download_settings = MS_Plugin::instance()->settings->downloads;
     $protection_type = $download_settings['protection_type'];
     if (!MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_MEDIA)) {
         return;
     }
     if (!empty($query->query_vars['protectedfile']) && self::PROTECTION_TYPE_COMPLETE == $protection_type) {
         $requested_item = explode('/', $query->query_vars['protectedfile']);
         $requested_item = array_pop($requested_item);
     } elseif (!empty($_GET['ms_file']) && self::PROTECTION_TYPE_HYBRID == $protection_type) {
         $requested_item = $_GET['ms_file'];
     } else {
         $requested_item = MS_Helper_Utility::get_current_url();
     }
     if (!empty($requested_item)) {
         // At this point we know that the requested post is an attachment.
         $f_info = $this->extract_file_info($requested_item);
         switch ($protection_type) {
             case self::PROTECTION_TYPE_COMPLETE:
             case self::PROTECTION_TYPE_HYBRID:
                 // Work out the post_id again
                 $attachment_id = preg_replace('/^' . self::FILE_PROTECTION_PREFIX . '/', '', $f_info->filename);
                 $attachment_id -= (int) self::FILE_PROTECTION_INCREMENT;
                 $the_file = $this->restore_filename($attachment_id, $f_info->size_extension);
                 break;
             default:
             case self::PROTECTION_TYPE_BASIC:
                 $upload_dir = wp_upload_dir();
                 $original_url = $upload_dir['baseurl'];
                 $home = get_option('home');
                 $original_url = explode($home, $original_url);
                 $furl = untrailingslashit(str_replace('/' . $download_settings['masked_url'], $original_url[1], $requested_item));
                 $home = untrailingslashit(get_option('home'));
                 $attachment_id = $this->get_attachment_id($furl);
                 $the_file = $this->restore_filename($attachment_id, $f_info->size_extension);
                 break;
         }
         if (!empty($the_file) && !empty($attachment_id) && is_numeric($attachment_id)) {
             if ($this->can_access_file($attachment_id)) {
                 $upload_dir = wp_upload_dir();
                 $file = trailingslashit($upload_dir['basedir']) . $the_file;
                 $this->output_file($file);
             } else {
                 $this->show_no_access_image();
             }
         }
     }
     do_action('ms_rule_media_model_handle_download_protection_after', $query, $this);
 }