/** * 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); }
/** * 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') . ' » ' . __('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); }
/** * 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') . ' » ' . __('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 }
/** * 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); }