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