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