/app/controller/class-ms-controller-frontend.php

  1. <?php 
  2. /** 
  3. * Creates the controller for Membership/User registration. 
  4. * 
  5. * @since 1.0.0 
  6. * 
  7. * @package Membership2 
  8. * @subpackage Controller 
  9. */ 
  10. class MS_Controller_Frontend extends MS_Controller { 
  11.  
  12. /** 
  13. * Signup/register process step constants. 
  14. * 
  15. * @since 1.0.0 
  16. * 
  17. * @var string 
  18. */ 
  19. const STEP_CHOOSE_MEMBERSHIP = 'choose_membership'; 
  20. const STEP_REGISTER_FORM = 'register'; 
  21. const STEP_REGISTER_FORM_ALT = 'register_form'; 
  22. const STEP_REGISTER_SUBMIT = 'register_submit'; 
  23. const STEP_PAYMENT_TABLE = 'payment_table'; 
  24. const STEP_GATEWAY_FORM = 'gateway_form'; 
  25. const STEP_PROCESS_PURCHASE = 'process_purchase'; 
  26.  
  27. /** 
  28. * AJAX action constants. 
  29. * 
  30. * @since 1.0.0 
  31. * 
  32. * @var string 
  33. */ 
  34. const ACTION_EDIT_PROFILE = 'edit_profile'; 
  35. const ACTION_VIEW_INVOICES = 'view_invoices'; 
  36. const ACTION_VIEW_ACTIVITIES = 'view_activities'; 
  37. const ACTION_VIEW_RESETPASS = 'rp'; 
  38.  
  39. /** 
  40. * Whether Membership2 will handle the registration process or not. 
  41. * This should not be changed directly but via filter ms_frontend_handle_registration 
  42. * 
  43. * @since 1.0.0 
  44. * 
  45. * @var bool 
  46. */ 
  47. static public $handle_registration = true; 
  48.  
  49. /** 
  50. * User registration errors. 
  51. * This variable is used by the class MS_View_Shortcode_RegisterUser. 
  52. * 
  53. * @since 1.0.0 
  54. * 
  55. * @var string 
  56. */ 
  57. static public $register_errors; 
  58.  
  59. /** 
  60. * Allowed actions to execute in template_redirect hook. 
  61. * 
  62. * @since 1.0.0 
  63. * 
  64. * @var string 
  65. */ 
  66. private $allowed_actions = array( 'signup_process', 'register_user' ); 
  67.  
  68. /** 
  69. * Prepare for Member registration. 
  70. * 
  71. * @since 1.0.0 
  72. */ 
  73. public function __construct() { 
  74. parent::__construct(); 
  75.  
  76. if ( MS_Plugin::is_enabled() ) { 
  77. do_action( 'ms_controller_frontend_construct', $this ); 
  78.  
  79. // Process actions like register new account. 
  80. $this->add_action( 'template_redirect', 'process_actions', 1 ); 
  81.  
  82. // Check if the current page is a Membership Page. 
  83. $this->add_action( 'template_redirect', 'check_for_membership_pages', 2 ); 
  84.  
  85. // Propagates SSL cookies when user logs in. 
  86. $this->add_action( 'wp_login', 'propagate_ssl_cookie', 10, 2 ); 
  87.  
  88. // Enqueue scripts. 
  89. $this->add_action( 'wp_enqueue_scripts', 'enqueue_scripts' ); 
  90.  
  91. // Add classes for all memberships the user is registered to. 
  92. $this->add_filter( 'body_class', 'body_class' ); 
  93.  
  94. // Clears the shortcode memory at the beginning of the_content 
  95. $this->add_filter( 'the_content', 'clear_content_memory', 1 ); 
  96.  
  97. // Compact code for output on the front end. 
  98. add_filter( 
  99. 'ms_compact_code',  
  100. array( 'MS_Helper_Html', 'compact_code' ) 
  101. ); 
  102.  
  103. /** 
  104. * This allows WordPress to provide the default register form. 
  105. * 
  106. * Set the filter response to FALSE to stop Membership2 from 
  107. * handling the registration process. WordPress or other plugins can 
  108. * register users in that case. 
  109. * 
  110. * @since 1.0.0 
  111. */ 
  112. self::$handle_registration = apply_filters( 
  113. 'ms_frontend_handle_registration',  
  114. true 
  115. ); 
  116.  
  117. if ( self::$handle_registration ) { 
  118. // Set the registration URL to the 'Register' Membership Page. 
  119. $this->add_filter( 'wp_signup_location', 'signup_location', 999 ); 
  120. $this->add_filter( 'register_url', 'signup_location', 999 ); 
  121.  
  122. // Redirect users to their Account page after login. 
  123. $this->add_filter( 'login_redirect', 'login_redirect', 10, 3 ); 
  124. $this->add_action( 'wp_logout', 'logout_redirect', 10 ); 
  125.  
  126. /** 
  127. * Handle URI actions for registration. 
  128. * 
  129. * Matches returned 'action' to method to execute. 
  130. * 
  131. * Related Action Hooks: 
  132. * - template_redirect 
  133. * 
  134. * @since 1.0.0 
  135. */ 
  136. public function process_actions() { 
  137. $action = $this->get_action(); 
  138.  
  139. /** 
  140. * If $action is set, then call relevant method. 
  141. * 
  142. * Methods: 
  143. * @see $allowed_actions property 
  144. * 
  145. */ 
  146. if ( ! empty( $action ) 
  147. && method_exists( $this, $action ) 
  148. && in_array( $action, $this->allowed_actions ) 
  149. ) { 
  150. $this->$action(); 
  151.  
  152. /** 
  153. * Check pages for the presence of Membership special pages. 
  154. * 
  155. * Related Action Hooks: 
  156. * - template_redirect 
  157. * 
  158. * @since 1.0.0 
  159. */ 
  160. public function check_for_membership_pages() { 
  161. global $post, $wp_query; 
  162.  
  163. // For invoice page purchase process 
  164. $fields = array( 'gateway', 'ms_relationship_id', 'step' ); 
  165.  
  166. if ( ! empty( $post ) 
  167. && isset( $post->post_type ) 
  168. && $post->post_type == MS_Model_Invoice::get_post_type() 
  169. && self::validate_required( $fields ) 
  170. && self::STEP_PROCESS_PURCHASE == $_POST['step'] 
  171. ) { 
  172. do_action( 
  173. 'ms_controller_frontend_signup_process_purchase',  
  174. $this 
  175. ); 
  176.  
  177. $the_page = MS_Model_Pages::current_page(); 
  178.  
  179. if ( $the_page ) { 
  180. // Fix the main query flags for best theme support: 
  181. // Our Membership-Pages are always single pages... 
  182.  
  183. $wp_query->is_single = false; 
  184. $wp_query->is_page = true; 
  185. $wp_query->is_singular = true; 
  186. $wp_query->is_home = false; 
  187. $wp_query->is_frontpage = false; 
  188. $wp_query->tax_query = null; 
  189.  
  190. $the_type = MS_Model_Pages::get_page_type( $the_page ); 
  191. switch ( $the_type ) { 
  192. case MS_Model_Pages::MS_PAGE_MEMBERSHIPS: 
  193. if ( ! MS_Model_Member::is_logged_in() ) { 
  194. wp_safe_redirect( 
  195. MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_REGISTER ) 
  196. ); 
  197. exit; 
  198. if ( MS_Helper_Membership::MEMBERSHIP_ACTION_CANCEL == $this->get_action() ) { 
  199. $this->membership_cancel(); 
  200. } else { 
  201. $this->signup_process(); 
  202. break; 
  203.  
  204. case MS_Model_Pages::MS_PAGE_REGISTER: 
  205. $step = $this->get_signup_step(); 
  206. if ( self::STEP_CHOOSE_MEMBERSHIP == $step && MS_Model_Member::is_logged_in() ) { 
  207. wp_safe_redirect( 
  208. MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_MEMBERSHIPS ) 
  209. ); 
  210. exit; 
  211. if ( MS_Helper_Membership::MEMBERSHIP_ACTION_CANCEL == $this->get_action() ) { 
  212. $this->membership_cancel(); 
  213. } else { 
  214. $this->signup_process(); 
  215. break; 
  216.  
  217. case MS_Model_Pages::MS_PAGE_ACCOUNT: 
  218. $this->user_account_manager(); 
  219. break; 
  220.  
  221. case MS_Model_Pages::MS_PAGE_PROTECTED_CONTENT: 
  222. // Set up the protection shortcode. 
  223. $scode = MS_Plugin::instance()->controller->controllers['membership_shortcode']; 
  224. $scode->page_is_protected(); 
  225. break; 
  226.  
  227. case MS_Model_Pages::MS_PAGE_REG_COMPLETE: 
  228. // Do nothing... 
  229. break; 
  230.  
  231. default: 
  232. // Do nothing... 
  233. break; 
  234.  
  235. /** 
  236. * Appends classes to the HTML body that identify all memberships that the 
  237. * current user is registered to. This allows webdesigners to adjust layout 
  238. * or hide elements based on the membership a user has. 
  239. * 
  240. * @since 1.0.0 
  241. * 
  242. * @param array $class Class-names to attach to the body. 
  243. * @return array Modified class-names to attach to the body. 
  244. */ 
  245. public function body_class( $classes ) { 
  246. $member = MS_Model_Member::get_current_member(); 
  247. if ( ! $member->is_logged_in() ) { 
  248. $classes[] = 'ms-guest'; 
  249. } else { 
  250. $classes[] = 'ms-member'; 
  251. $classes[] = 'ms-member-' . $member->id; 
  252.  
  253. $info = MS_Plugin::instance()->controller->get_access_info(); 
  254. foreach ( $info['memberships'] as $membership_id ) { 
  255. $classes[] = 'ms-' . absint( $membership_id ); 
  256.  
  257. return $classes; 
  258.  
  259. /** 
  260. * Clears the shortcode memory at the beginning of each call to the_content. 
  261. * 
  262. * This is required when there are several parts of the page that are 
  263. * rendered via the_content, e.g. a main content and a footer area (this 
  264. * is a theme-specific scenario). Or if the page contains an excerpt and a 
  265. * main content block, ... 
  266. * 
  267. * @since 1.0.0 
  268. * @param string $content The page content 
  269. * @return string Value of $content (unmodified) 
  270. */ 
  271. public function clear_content_memory( $content ) { 
  272. global $wp_current_filter; 
  273. $reset = false; 
  274.  
  275. // Correctly handle nesting. 
  276. foreach ( $wp_current_filter as $filter ) { 
  277. if ( 'the_content' === $filter ) { 
  278. if ( $reset ) { 
  279. /** 
  280. * the_content is called inside the_content. 
  281. * Don't reset again! 
  282. * This can happen for example: A shortcode parses the 
  283. * return code via apply_filters( 'the_content' ) 
  284. */ 
  285. $reset = false; 
  286. break; 
  287. } else { 
  288. $reset = true; 
  289.  
  290. if ( $reset ) { 
  291. MS_Helper_Shortcode::reset_shortcode_usage(); 
  292.  
  293. return $content; 
  294.  
  295. /** 
  296. * Handle entire signup process. 
  297. * 
  298. * @since 1.0.0 
  299. */ 
  300. public function signup_process() { 
  301. $step = $this->get_signup_step(); 
  302. $member = MS_Model_Member::get_current_member(); 
  303.  
  304. do_action( 'ms_frontend_register-' . $step ); 
  305.  
  306. switch ( $step ) { 
  307. /** 
  308. * Initial state. 
  309. */ 
  310. case self::STEP_CHOOSE_MEMBERSHIP: 
  311. // Nothing, simply display Membership page. 
  312. break; 
  313.  
  314. /** 
  315. * If not registered. 
  316. */ 
  317. case self::STEP_REGISTER_FORM: 
  318. case self::STEP_REGISTER_FORM_ALT: 
  319. $this->add_filter( 'the_content', 'register_form', 1 ); 
  320. break; 
  321.  
  322. /** 
  323. * Process user registration. 
  324. */ 
  325. case self::STEP_REGISTER_SUBMIT: 
  326. $this->register_user(); 
  327. break; 
  328.  
  329. /** 
  330. * Show payment table. 
  331. * 
  332. * The payment table is only available if the current user has 
  333. * permission to subscribe to the specified membership. 
  334. */ 
  335. case self::STEP_PAYMENT_TABLE: 
  336. $add_filter = false; 
  337. if ( ! empty( $_REQUEST['membership_id'] ) ) { 
  338. $membership_id = $_REQUEST['membership_id']; 
  339. if ( $member->can_subscribe_to( $membership_id ) ) { 
  340. $add_filter = true; 
  341.  
  342. if ( $add_filter ) { 
  343. $this->add_filter( 'the_content', 'payment_table', 1 ); 
  344. } else { 
  345. wp_safe_redirect( 
  346. esc_url_raw( 
  347. add_query_arg( 
  348. array( 'step' => self::STEP_CHOOSE_MEMBERSHIP ) 
  349. ); 
  350. break; 
  351.  
  352. /** 
  353. * Show gateway extra form. 
  354. * Handled by MS_Controller_Gateway. 
  355. */ 
  356. case self::STEP_GATEWAY_FORM: 
  357. do_action( 
  358. 'ms_controller_frontend_signup_gateway_form',  
  359. $this 
  360. ); 
  361. break; 
  362.  
  363. /** 
  364. * Process the purchase action. 
  365. * Handled by MS_Controller_Gateway. 
  366. */ 
  367. case self::STEP_PROCESS_PURCHASE: 
  368. do_action( 
  369. 'ms_controller_frontend_signup_process_purchase',  
  370. $this 
  371. ); 
  372. break; 
  373.  
  374. default: 
  375. MS_Helper_Debug::log( "No handler for step: $step" ); 
  376. break; 
  377.  
  378. /** 
  379. * Get signup process step (multi step form). 
  380. * 
  381. * @since 1.0.0 
  382. * 
  383. * @return string The current signup step after validation. 
  384. */ 
  385. private function get_signup_step() { 
  386. static $Valid_Steps = null; 
  387. static $Login_Steps = null; 
  388.  
  389. if ( empty( $Valid_Steps ) ) { 
  390. $Valid_Steps = apply_filters( 
  391. 'ms_controller_frontend_signup_steps',  
  392. array( 
  393. self::STEP_CHOOSE_MEMBERSHIP,  
  394. self::STEP_REGISTER_FORM,  
  395. self::STEP_REGISTER_FORM_ALT,  
  396. self::STEP_REGISTER_SUBMIT,  
  397. self::STEP_PAYMENT_TABLE,  
  398. self::STEP_GATEWAY_FORM,  
  399. self::STEP_PROCESS_PURCHASE,  
  400. ); 
  401.  
  402. // These steps are only available to logged-in users. 
  403. $Login_Steps = apply_filters( 
  404. 'ms_controller_frontend_signup_steps_private',  
  405. array( 
  406. self::STEP_PAYMENT_TABLE,  
  407. self::STEP_GATEWAY_FORM,  
  408. self::STEP_PROCESS_PURCHASE,  
  409. ); 
  410.  
  411. lib3()->array->equip_request( 'step', 'membership_id' ); 
  412.  
  413. if ( in_array( $_REQUEST['step'], $Valid_Steps ) ) { 
  414. $step = $_REQUEST['step']; 
  415. } else { 
  416. // Initial step 
  417. $step = self::STEP_CHOOSE_MEMBERSHIP; 
  418.  
  419. if ( self::STEP_PAYMENT_TABLE == $step ) { 
  420. if ( ! MS_Model_Membership::is_valid_membership( $_REQUEST['membership_id'] ) ) { 
  421. $step = self::STEP_CHOOSE_MEMBERSHIP; 
  422.  
  423. if ( self::STEP_CHOOSE_MEMBERSHIP == $step && ! empty( $_GET['membership_id'] ) ) { 
  424. $step = self::STEP_PAYMENT_TABLE; 
  425.  
  426. if ( ! MS_Model_Member::is_logged_in() && in_array( $step, $Login_Steps ) ) { 
  427. $step = self::STEP_REGISTER_FORM_ALT; 
  428.  
  429. return apply_filters( 
  430. 'ms_controller_frontend_get_signup_step',  
  431. $step,  
  432. $this 
  433. ); 
  434.  
  435. /** 
  436. * Returns the URL to user registration page. 
  437. * If Membership2 handles registration we can provide the registration 
  438. * step via function param $step. 
  439. * 
  440. * @since 1.0.0 
  441. * @param string $step Empty uses default step (choose_membership). 
  442. * 'choose_membership' show list of memberships. 
  443. * 'register' shows the registration form. 
  444. * @return string URL to the registration page. 
  445. */ 
  446. static public function get_registration_url( $step = null ) { 
  447. $url = wp_registration_url(); 
  448.  
  449. if ( self::$handle_registration && ! empty( $step ) ) { 
  450. $url = esc_url_raw( add_query_arg( 'step', $step, $url ) ); 
  451.  
  452. return $url; 
  453.  
  454. /** 
  455. * Show register user form. 
  456. * 
  457. * Related Filter Hooks: 
  458. * - the_content 
  459. * 
  460. * @since 1.0.0 
  461. * 
  462. * @param string $content The page content to filter. 
  463. * @return string The filtered content. 
  464. */ 
  465. public function register_form( $content ) { 
  466. // Check if the WordPress settings allow user registration. 
  467. if ( ! MS_Model_Member::can_register() ) { 
  468. return __( 'Registration is currently not allowed.', 'membership2' ); 
  469.  
  470. // Do not parse the form when building the excerpt. 
  471. global $wp_current_filter; 
  472. if ( in_array( 'get_the_excerpt', $wp_current_filter ) ) { 
  473. return ''; 
  474.  
  475. /** 
  476. * Add-ons or other plugins can use this filter to define a completely 
  477. * different registration form. If this filter returns any content, then 
  478. * the default form will not be generated 
  479. * 
  480. * @since 1.0.0 
  481. * @var string 
  482. */ 
  483. $custom_code = apply_filters( 
  484. 'ms_frontend_custom_registration_form',  
  485. '',  
  486. self::$register_errors,  
  487. $this 
  488. ); 
  489.  
  490. if ( $custom_code ) { 
  491. $content = $custom_code; 
  492. } else { 
  493. remove_filter( 'the_content', 'wpautop' ); 
  494.  
  495. $did_form = MS_Helper_Shortcode::has_shortcode( 
  496. MS_Helper_Shortcode::SCODE_REGISTER_USER,  
  497. $content 
  498. ); 
  499.  
  500. if ( ! $did_form ) { 
  501. $scode = sprintf( 
  502. '[%s]',  
  503. MS_Helper_Shortcode::SCODE_REGISTER_USER 
  504. ); 
  505. $reg_form = do_shortcode( $scode ); 
  506.  
  507. if ( ! MS_Model_Member::is_logged_in() ) { 
  508. $content = $reg_form; 
  509. } else { 
  510. $content .= $reg_form; 
  511.  
  512. return apply_filters( 
  513. 'ms_controller_frontend_register_form_content',  
  514. $content,  
  515. $this 
  516. ); 
  517.  
  518. /** 
  519. * Handles register user submit. 
  520. * 
  521. * On validation errors, step back to register form. 
  522. * 
  523. * @since 1.0.0 
  524. */ 
  525. public function register_user() { 
  526. do_action( 'ms_controller_frontend_register_user_before', $this ); 
  527.  
  528. if ( ! $this->verify_nonce() ) { 
  529. return; 
  530.  
  531. try { 
  532. $user = MS_Factory::create( 'MS_Model_Member' ); 
  533.  
  534. // Default WP registration filter 
  535. $fields = apply_filters( 'signup_user_init', $_REQUEST ); 
  536. foreach ( $fields as $field => $value ) { 
  537. $user->$field = $value; 
  538.  
  539. $user->save(); 
  540.  
  541. // Default WP action hook 
  542. do_action( 'signup_finished' ); 
  543. do_action( 'ms_controller_frontend_register_user_before_login', $user, $_REQUEST, $this ); 
  544.  
  545. $user->signon_user(); 
  546.  
  547. if ( MS_Model_Event::save_event( MS_Model_Event::TYPE_MS_REGISTERED, $user ) ) { 
  548. if( ! defined( 'MS_DISABLE_WP_NEW_USER_NOTIFICATION' ) ) { 
  549. wp_new_user_notification( $user->id, $user->password ); 
  550.  
  551. do_action( 'ms_controller_frontend_register_user_complete', $user, $_REQUEST, $this ); 
  552.  
  553. // Go to membership signup payment form. 
  554. if ( empty( $_REQUEST['membership_id'] ) ) { 
  555. $redirect = esc_url_raw( 
  556. add_query_arg( 
  557. array( 
  558. 'step' => self::STEP_CHOOSE_MEMBERSHIP,  
  559. ); 
  560. } else { 
  561. $redirect = esc_url_raw( 
  562. add_query_arg( 
  563. array( 
  564. 'step' => self::STEP_PAYMENT_TABLE,  
  565. 'membership_id' => absint( $_REQUEST['membership_id'] ),  
  566. ),  
  567. MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_REGISTER ) 
  568. ); 
  569.  
  570. wp_safe_redirect( $redirect ); 
  571. exit; 
  572. catch( Exception $e ) { 
  573. self::$register_errors = $e->getMessage(); 
  574.  
  575. // step back 
  576. $this->add_action( 'the_content', 'register_form', 1 ); 
  577. do_action( 
  578. 'ms_controller_frontend_register_user_error',  
  579. self::$register_errors 
  580. ); 
  581.  
  582. /** 
  583. * Render membership payment information. 
  584. * 
  585. * Related Filter Hooks: 
  586. * - the_content 
  587. * 
  588. * @since 1.0.0 
  589. * 
  590. * @param string $content The page content to filter. 
  591. * @return string The filtered content. 
  592. */ 
  593. public function payment_table( $content ) { 
  594. $data = array(); 
  595. $subscription = null; 
  596. $member = MS_Model_Member::get_current_member(); 
  597. $membership_id = 0; 
  598.  
  599. lib3()->array->equip_request( 'membership_id', 'move_from_id', 'ms_relationship_id' ); 
  600.  
  601. if ( ! empty( $_POST['ms_relationship_id'] ) ) { 
  602. // Error path, showing payment table again with error msg 
  603. $subscription = MS_Factory::load( 
  604. 'MS_Model_Relationship',  
  605. absint( intval( $_POST['ms_relationship_id'] ) ) 
  606. ); 
  607. $membership = $subscription->get_membership(); 
  608. $membership_id = $membership->id; 
  609.  
  610. if ( ! empty( $_POST['error'] ) ) { 
  611. lib3()->array->strip_slashes( $_POST, 'error' ); 
  612. $data['error'] = $_POST['error']; 
  613. } elseif ( ! empty( $_REQUEST['membership_id'] ) ) { 
  614. // First time loading 
  615. $membership_id = intval( $_REQUEST['membership_id'] ); 
  616. $membership = MS_Factory::load( 'MS_Model_Membership', $membership_id ); 
  617. $move_from_id = absint( $_REQUEST['move_from_id'] ); 
  618. $subscription = MS_Model_Relationship::create_ms_relationship( 
  619. $membership_id,  
  620. $member->id,  
  621. '',  
  622. $move_from_id 
  623. ); 
  624. } else { 
  625. MS_Helper_Debug::log( 'Error: missing POST params' ); 
  626. MS_Helper_Debug::log( $_POST ); 
  627. return $content; 
  628.  
  629. // Invalid membership ID was specified: Redirect to membership list. 
  630. if ( ! $subscription ) { 
  631. MS_Model_Pages::redirect_to( MS_Model_Pages::MS_PAGE_MEMBERSHIPS ); 
  632.  
  633. $invoice = $subscription->get_current_invoice(); 
  634.  
  635. /** 
  636. * Notify Add-ons that we are preparing payment details for a membership 
  637. * subscription. 
  638. * 
  639. * E.g. Coupon discount is applied by this hook. 
  640. * 
  641. * @since 1.0.0 
  642. */ 
  643. $invoice = apply_filters( 
  644. 'ms_signup_payment_details',  
  645. $invoice,  
  646. $subscription,  
  647. $membership 
  648. ); 
  649. $invoice->save(); 
  650.  
  651. $data['invoice'] = $invoice; 
  652. $data['membership'] = $membership; 
  653. $data['member'] = $member; 
  654. $data['ms_relationship'] = $subscription; 
  655.  
  656. $view = MS_Factory::load( 'MS_View_Frontend_Payment' ); 
  657. $view->data = apply_filters( 
  658. 'ms_view_frontend_payment_data',  
  659. $data,  
  660. $membership_id,  
  661. $subscription,  
  662. $member,  
  663. $this 
  664. ); 
  665.  
  666. return apply_filters( 
  667. 'ms_controller_frontend_payment_table',  
  668. $view->to_html(),  
  669. $this 
  670. ); 
  671.  
  672. /** 
  673. * Handles membership_cancel action. 
  674. * 
  675. * @since 1.0.0 
  676. */ 
  677. public function membership_cancel() { 
  678. if ( ! empty( $_REQUEST['membership_id'] ) && $this->verify_nonce( null, 'any' ) ) { 
  679. $membership_id = absint( $_REQUEST['membership_id'] ); 
  680. $member = MS_Model_Member::get_current_member(); 
  681. $member->cancel_membership( $membership_id ); 
  682. $member->save(); 
  683.  
  684. $url = MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_REGISTER ); 
  685. wp_safe_redirect( $url ); 
  686. exit; 
  687.  
  688. /** 
  689. * Manage user account actions. 
  690. * 
  691. * @since 1.0.0 
  692. * @internal 
  693. */ 
  694. public function user_account_manager() { 
  695. $action = $this->get_action(); 
  696. $member = MS_Model_Member::get_current_member(); 
  697.  
  698. /** 
  699. * These actions are always executed when any user account page loads. 
  700. * 
  701. * @since 1.0.1.0 
  702. */ 
  703. do_action( 
  704. 'ms_frontend_user_account_manager-' . $action,  
  705. $this 
  706. ); 
  707. do_action( 
  708. 'ms_frontend_user_account_manager',  
  709. $action,  
  710. $this 
  711. ); 
  712.  
  713. if ( $this->verify_nonce() ) { 
  714. /** 
  715. * The following two actions are only executed when a form was 
  716. * submitted on a user account page. 
  717. * 
  718. * @since 1.0.1.0 
  719. */ 
  720. do_action( 
  721. 'ms_frontend_user_account_manager_submit-' . $action,  
  722. $this 
  723. ); 
  724. do_action( 
  725. 'ms_frontend_user_account_manager_submit',  
  726. $action,  
  727. $this 
  728. ); 
  729.  
  730. switch ( $action ) { 
  731. case self::ACTION_EDIT_PROFILE: 
  732. $data = array(); 
  733.  
  734. if ( $this->verify_nonce() ) { 
  735. if ( is_array( $_POST ) ) { 
  736. foreach ( $_POST as $field => $value ) { 
  737. $member->$field = $value; 
  738.  
  739. try { 
  740. $member->validate_member_info(); 
  741. $member->save(); 
  742. do_action( 'ms_model_member_update_user', $member ); 
  743. wp_safe_redirect( 
  744. esc_url_raw( remove_query_arg( 'action' ) ) 
  745. ); 
  746. exit; 
  747.  
  748. catch ( Exception $e ) { 
  749. $data['errors'] = $e->getMessage(); 
  750. $view = MS_Factory::create( 'MS_View_Frontend_Profile' ); 
  751. $data['member'] = $member; 
  752. $data['action'] = $action; 
  753. $view->data = apply_filters( 'ms_view_frontend_profile_data', $data, $this ); 
  754. $view->add_filter( 'the_content', 'to_html', 1 ); 
  755. break; 
  756.  
  757. case self::ACTION_VIEW_INVOICES: 
  758. $data['invoices'] = MS_Model_Invoice::get_public_invoices( 
  759. $member->id 
  760. ); 
  761.  
  762. $view = MS_Factory::create( 'MS_View_Frontend_Invoices' ); 
  763. $view->data = apply_filters( 
  764. 'ms_view_frontend_frontend_invoices',  
  765. $data,  
  766. $this 
  767. ); 
  768. $view->add_filter( 'the_content', 'to_html', 1 ); 
  769. break; 
  770.  
  771. case self::ACTION_VIEW_ACTIVITIES: 
  772. $data['events'] = MS_Model_Event::get_events( 
  773. array( 
  774. 'author' => $member->id,  
  775. 'posts_per_page' => -1,  
  776. ); 
  777.  
  778. $view = MS_Factory::create( 'MS_View_Frontend_Activities' ); 
  779. $view->data = apply_filters( 
  780. 'ms_view_frontend_frontend_activities',  
  781. $data,  
  782. $this 
  783. ); 
  784. $view->add_filter( 'the_content', 'to_html', 1 ); 
  785. break; 
  786.  
  787. case self::ACTION_VIEW_RESETPASS: 
  788. /** 
  789. * Reset password action. 
  790. * This action is accessed via the password-reset email 
  791. * @see class-ms-controller-dialog.php 
  792. * 
  793. * The action is targeted to the Account-page but actually calls 
  794. * the Login-Shortcode. 
  795. */ 
  796. $view = MS_Factory::create( 'MS_View_Shortcode_Login' ); 
  797. $view->data = array( 'action' => 'resetpass' ); 
  798.  
  799. $view->add_filter( 'the_content', 'to_html', 1 ); 
  800. break; 
  801.  
  802. default: 
  803. // Do nothing... 
  804. break; 
  805.  
  806. /** 
  807. * Get the URL the user used to register for a subscription. 
  808. * 
  809. * Uses the default registration page unless the registration was embedded 
  810. * on another page (e.g. using a shortcode). 
  811. * 
  812. * Related Filter Hooks: 
  813. * - wp_signup_location 
  814. * - register_url 
  815. * 
  816. * @since 1.0.0 
  817. * 
  818. * @param string $url The url to filter. 
  819. * @return The new signup url. 
  820. */ 
  821. public function signup_location( $url ) { 
  822. $url = MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_REGISTER ); 
  823.  
  824. return apply_filters( 
  825. 'ms_controller_frontend_signup_location',  
  826. $url,  
  827. $this 
  828. ); 
  829.  
  830. /** 
  831. * Propagates SSL cookies when user logs in. 
  832. * 
  833. * Related Action Hooks: 
  834. * - wp_login 
  835. * 
  836. * @since 1.0.0 
  837. * 
  838. * @param type $login The login info. 
  839. * @param WP_User $user The user to login. 
  840. */ 
  841. public function propagate_ssl_cookie( $login, $user = null ) { 
  842. if ( empty( $user ) || ! is_a( $user, 'WP_User' ) ) { 
  843. $user = get_user_by( 'login', $login ); 
  844.  
  845. if ( is_a( $user, 'WP_User' ) && ! is_ssl() ) { 
  846. wp_set_auth_cookie( $user->ID, true, true ); 
  847.  
  848. do_action( 
  849. 'ms_controller_frontend_propagate_ssl_cookie',  
  850. $login,  
  851. $user,  
  852. $this 
  853. ); 
  854.  
  855. /** 
  856. * Redirect user to account page. 
  857. * 
  858. * Only redirect when no previous redirect_to is set or when going to /wp-admin/. 
  859. * 
  860. * @since 1.0.0 
  861. * 
  862. * @param string $redirect_to URL to redirect to. 
  863. * @param string $request URL the user is coming from. 
  864. * @param object $user Logged user's data. 
  865. * @return string The redirect url. 
  866. */ 
  867. public function login_redirect( $redirect_to, $request, $user ) { 
  868. if ( ! empty( $user->ID ) 
  869. && ! MS_Model_Member::is_admin_user( $user->ID ) 
  870. && ( empty( $redirect_to ) || admin_url() == $redirect_to ) 
  871. ) { 
  872. $redirect_to = MS_Model_Pages::get_page_url( MS_Model_Pages::MS_PAGE_ACCOUNT ); 
  873.  
  874. return apply_filters( 
  875. 'ms_controller_frontend_login_redirect',  
  876. $redirect_to,  
  877. $request,  
  878. $user,  
  879. $this 
  880. ); 
  881.  
  882. /** 
  883. * Redirect user to page. 
  884. * 
  885. * @since 1.0.2.4 
  886. * 
  887. * @return void 
  888. */ 
  889. public function logout_redirect() { 
  890. wp_redirect( MS_Model_Pages::get_url_after_logout() ); 
  891. exit; 
  892.  
  893. /** 
  894. * Adds CSS and JS for Membership special pages used in the front end. 
  895. * 
  896. * @since 1.0.0 
  897. * 
  898. * @return void 
  899. */ 
  900. public function enqueue_scripts() { 
  901. do_action( 
  902. 'ms_controller_frontend_enqueue_scripts',  
  903. $this->get_signup_step(),  
  904. $this->get_action(),  
  905. $this 
  906. ); 
  907.  
  908. $is_ms_page = MS_Model_Pages::is_membership_page(); 
  909. $is_profile = self::ACTION_EDIT_PROFILE == $this->get_action() 
  910. && MS_Model_Pages::is_membership_page( null, MS_Model_Pages::MS_PAGE_ACCOUNT ); 
  911.  
  912. if ( $is_ms_page ) { 
  913. $data = array( 
  914. 'ms_init' => array( 'shortcode' ),  
  915. 'cancel_msg' => __( 'Are you sure you want to cancel?', 'membership2' ),  
  916. ); 
  917.  
  918. lib3()->ui->css( 'ms-styles' ); 
  919. lib3()->ui->js( 'jquery-validate' ); 
  920. lib3()->ui->js( 'ms-public' ); 
  921. MS_Controller_Plugin::translate_jquery_validator(); 
  922.  
  923. if ( $is_profile ) { 
  924. $data['ms_init'][] = 'frontend_profile'; 
  925.  
  926. lib3()->ui->data( 'ms_data', $data ); 
.