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

  1. <?php 
  2. /** 
  3. * This file defines the MS_Controller_Membership class. 
  4. * 
  5. * @copyright Incsub (http://incsub.com/) 
  6. * 
  7. * @license http://opensource.org/licenses/GPL-2.0 GNU General Public License, version 2 (GPL-2.0) 
  8. * 
  9. * This program is free software; you can redistribute it and/or modify 
  10. * it under the terms of the GNU General Public License, version 2, as 
  11. * published by the Free Software Foundation. 
  12. * 
  13. * This program is distributed in the hope that it will be useful,  
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
  16. * GNU General Public License for more details. 
  17. * 
  18. * You should have received a copy of the GNU General Public License 
  19. * along with this program; if not, write to the Free Software 
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,  
  21. * MA 02110-1301 USA 
  22. * 
  23. */ 
  24.  
  25. /** 
  26. * Controller for managing Memberships and Membership Rules. 
  27. * 
  28. * @since 1.0.0 
  29. * 
  30. * @package Membership2 
  31. * @subpackage Controller 
  32. */ 
  33. class MS_Controller_Membership extends MS_Controller { 
  34.  
  35. /** 
  36. * AJAX action constants. 
  37. * 
  38. * @since 1.0.0 
  39. * 
  40. * @var string 
  41. */ 
  42. const AJAX_ACTION_TOGGLE_MEMBERSHIP = 'toggle_membership'; 
  43. const AJAX_ACTION_UPDATE_MEMBERSHIP = 'update_membership'; 
  44.  
  45. /** 
  46. * Membership page step constants. 
  47. * 
  48. * @since 1.0.0 
  49. * 
  50. * @var string 
  51. */ 
  52. const STEP_MS_LIST = 'ms_list'; 
  53. const STEP_OVERVIEW = 'ms_overview'; 
  54. const STEP_NEWS = 'ms_news'; 
  55. const STEP_WELCOME_SCREEN = 'welcome'; 
  56. const STEP_PROTECTED_CONTENT = 'protected_content'; 
  57. const STEP_ADD_NEW = 'add'; 
  58. const STEP_PAYMENT = 'payment'; 
  59.  
  60. // Actions 
  61. const ACTION_SAVE = 'save_membership'; 
  62.  
  63. /** 
  64. * The model to use for loading/saving Membership data. 
  65. * 
  66. * @since 4.0.0 
  67. * @var MS_Model_Membership 
  68. */ 
  69. private $model = null; 
  70.  
  71. /** 
  72. * The active page tab. 
  73. * 
  74. * @since 1.0.0 
  75. * @var string 
  76. */ 
  77. protected $active_tab; 
  78.  
  79. /** 
  80. * Prepare the Membership manager. 
  81. * 
  82. * @since 1.0.0 
  83. */ 
  84. public function __construct() { 
  85. parent::__construct(); 
  86.  
  87. $this->add_ajax_action( self::AJAX_ACTION_TOGGLE_MEMBERSHIP, 'ajax_action_toggle_membership' ); 
  88. $this->add_ajax_action( self::AJAX_ACTION_UPDATE_MEMBERSHIP, 'ajax_action_update_membership' ); 
  89.  
  90. /** 
  91. * Initialize the admin-side functions. 
  92. * 
  93. * @since 2.0.0 
  94. */ 
  95. public function admin_init() { 
  96. $hooks = array( 
  97. MS_Controller_Plugin::admin_page_hook(),  
  98. MS_Controller_Plugin::admin_page_hook( 'setup' ),  
  99. MS_Controller_Plugin::admin_page_hook( 'protection' ),  
  100. ); 
  101.  
  102. foreach ( $hooks as $hook ) { 
  103. $this->run_action( 'load-' . $hook, 'membership_admin_page_process' ); 
  104. $this->run_action( 'admin_print_scripts-' . $hook, 'enqueue_scripts' ); 
  105. $this->run_action( 'admin_print_styles-' . $hook, 'enqueue_styles' ); 
  106.  
  107. /** 
  108. * Handle Ajax toggle action. 
  109. * 
  110. * Related Action Hooks: 
  111. * - wp_ajax_toggle_membership 
  112. * 
  113. * @since 1.0.0 
  114. */ 
  115. public function ajax_action_toggle_membership() { 
  116. $msg = 0; 
  117.  
  118. $required = array( 'membership_id', 'field' ); 
  119.  
  120. if ( $this->verify_nonce() 
  121. && self::validate_required( $required, 'POST', false ) 
  122. && $this->is_admin_user() 
  123. ) { 
  124. $msg = $this->membership_list_do_action( 
  125. 'toggle_' . $_POST['field'],  
  126. array( $_POST['membership_id'] ) 
  127. ); 
  128.  
  129. do_action( 
  130. 'ms_controller_membership_ajax_action_toggle_membership',  
  131. $msg,  
  132. $this 
  133. ); 
  134.  
  135. wp_die( $msg ); 
  136.  
  137. /** 
  138. * Handle Ajax toggle action. 
  139. * 
  140. * Related Action Hooks: 
  141. * - wp_ajax_update_membership 
  142. * 
  143. * @since 1.0.0 
  144. */ 
  145. public function ajax_action_update_membership() { 
  146. $msg = 0; 
  147.  
  148. $required = array( 'membership_id', 'field', 'value' ); 
  149.  
  150. if ( $this->verify_nonce() 
  151. && self::validate_required( $required, 'POST', false ) 
  152. && $this->is_admin_user() 
  153. ) { 
  154. lib2()->array->strip_slashes( $_POST, 'value' ); 
  155.  
  156. $msg = $this->save_membership( 
  157. array( $_POST['field'] => $_POST['value'] ) 
  158. ); 
  159.  
  160. do_action( 
  161. 'ms_controller_membership_ajax_action_update_membership',  
  162. $msg,  
  163. $this 
  164. ); 
  165.  
  166. wp_die( $msg ); 
  167.  
  168. /** 
  169. * Load membership from request. 
  170. * 
  171. * @since 1.0.0 
  172. * 
  173. * @return MS_Model_Membership The membership model object. 
  174. */ 
  175. public function load_membership() { 
  176. $membership_id = 0; 
  177.  
  178. if ( empty( $this->model ) ) { 
  179. if ( ! empty( $_REQUEST['membership_id'] ) ) { 
  180. $membership_id = absint( $_REQUEST['membership_id'] ); 
  181.  
  182. if ( $membership_id == MS_Model_Membership::get_base()->id ) { 
  183. wp_safe_redirect( 
  184. esc_url_raw( 
  185. remove_query_arg( array( 'membership_id' ) ) 
  186. ); 
  187. } elseif ( MS_Controller_Plugin::is_page( 'protection' ) ) { 
  188. $membership_id = MS_Model_Membership::get_base()->id; 
  189.  
  190. $this->model = MS_Factory::load( 
  191. 'MS_Model_Membership',  
  192. $membership_id 
  193. ); 
  194.  
  195. $this->model = apply_filters( 
  196. 'ms_controller_membership_load_membership',  
  197. $this->model,  
  198. $this 
  199. ); 
  200.  
  201. return $this->model; 
  202.  
  203. /** 
  204. * Process membership pages requests 
  205. * 
  206. * Verifies GET and POST requests to manage memberships. 
  207. * Redirect to next step after processing. 
  208. * 
  209. * @since 1.0.0 
  210. */ 
  211. public function membership_admin_page_process() { 
  212. $msg = 0; 
  213. $next_step = null; 
  214. $step = $this->get_step(); 
  215. $goto_url = null; 
  216. $membership = $this->load_membership(); 
  217. $membership_id = $membership->id; 
  218. $completed = false; 
  219. $is_wizard = MS_Plugin::is_wizard(); 
  220. $save_data = array(); 
  221.  
  222. // Check if user came from WPMU Dashboard plugin 
  223. if ( ! MS_Plugin::is_wizard() ) { 
  224. $referer = $_SERVER['HTTP_REFERER']; 
  225. $params = parse_url( $referer, PHP_URL_QUERY ); 
  226. $fields = array(); 
  227. parse_str( $params, $fields ); 
  228. if ( isset( $fields['page'] ) && 'wpmudev-plugins' == $fields['page'] ) { 
  229. $url = MS_Controller_Plugin::get_admin_url( 'settings' ); 
  230.  
  231. wp_safe_redirect( $url ); 
  232. exit; 
  233.  
  234. // MS_Controller_Rule is executed using this action. 
  235. do_action( 
  236. 'ms_controller_membership_admin_page_process_' . $step,  
  237. $this->get_active_tab() 
  238. ); 
  239.  
  240. // Only accessible to admin users 
  241. if ( ! $this->is_admin_user() ) { return false; } 
  242.  
  243. if ( $this->verify_nonce( null, 'any' ) ) { 
  244. // Take next actions based in current step. 
  245.  
  246. // Check if we are editing a membership. 
  247. $save_membership = $this->verify_nonce( self::ACTION_SAVE ); 
  248.  
  249. if ( $save_membership ) { 
  250. // Save the current Setup-Process. 
  251. $save_data = $_POST; 
  252. unset( $save_data['_wpnonce'] ); 
  253. unset( $save_data['action'] ); 
  254.  
  255. if ( isset( $_POST['set_private_flag'] ) ) { 
  256. lib2()->array->equip_post( 'public' ); 
  257. $save_data['public'] = ! lib2()->is_true( $_POST['public'] ); 
  258. if ( isset( $_POST['set_paid_flag'] ) ) { 
  259. lib2()->array->equip_post( 'paid' ); 
  260. $save_data['is_free'] = ! lib2()->is_true( $_POST['paid'] ); 
  261.  
  262. $msg = $this->save_membership( $save_data ); 
  263.  
  264. // Refresh the $membership variable. 
  265. $membership = $this->load_membership(); 
  266. $membership_id = $membership->id; 
  267.  
  268. switch ( $step ) { 
  269. case self::STEP_MS_LIST: 
  270. // Display a list of all memberships 
  271.  
  272. $fields = array( 'action', 'membership_id' ); 
  273. if ( self::validate_required( $fields, 'GET' ) ) { 
  274. $msg = $this->membership_list_do_action( 
  275. $_GET['action'],  
  276. array( absint( $_GET['membership_id'] ) ) 
  277. ); 
  278. $next_step = self::STEP_MS_LIST; 
  279. break; 
  280.  
  281. case self::STEP_ADD_NEW: 
  282. // Create Membership: Select the Membership-Type 
  283.  
  284. $paid = isset( $_POST['set_paid_flag'] ) 
  285. && isset( $_POST['paid'] ) 
  286. && lib2()->is_true( $_POST['paid'] ); 
  287.  
  288. if ( $paid ) { 
  289. $next_step = self::STEP_PAYMENT; 
  290. } else { 
  291. $next_step = self::STEP_MS_LIST; 
  292. $msg = $this->mark_setup_completed(); 
  293. $completed = true; 
  294.  
  295. if ( $is_wizard ) { 
  296. // End the wizard! 
  297. $this->wizard_tracker( $next_step, true ); 
  298. break; 
  299.  
  300. case self::STEP_PAYMENT: 
  301. // Setup payment options 
  302.  
  303. $next_step = self::STEP_MS_LIST; 
  304. $msg = $this->mark_setup_completed(); 
  305. $completed = true; 
  306. break; 
  307.  
  308. if ( ! empty( $next_step ) ) { 
  309. $args = array( 
  310. 'step' => $next_step,  
  311. 'membership_id' => $membership_id,  
  312. ); 
  313.  
  314. if ( ! empty( $msg ) ) { 
  315. $args['msg'] = $msg; 
  316.  
  317. /** 
  318. * Param 'MENU_SLUG' forces the admin-URL to use the top-level 
  319. * menu slug instead of the current base_slug. 
  320. * During Setup-wizard the base_slug ends in '-setup', but when 
  321. * we reach this point the wizard is completed. 
  322. */ 
  323. $slug = 'MENU_SLUG'; 
  324.  
  325. $goto_url = esc_url_raw( 
  326. add_query_arg( 
  327. $args,  
  328. MS_Controller_Plugin::get_admin_url( $slug ) 
  329. ); 
  330.  
  331. $goto_url = apply_filters( 
  332. 'ms_controller_membership_membership_admin_page_process_goto_url',  
  333. $goto_url,  
  334. $next_step 
  335. ); 
  336.  
  337. if ( $completed ) { 
  338. MS_Plugin::flush_rewrite_rules( $goto_url ); 
  339. } else { 
  340. wp_safe_redirect( $goto_url ); 
  341. exit; 
  342. } elseif ( $this->verify_nonce( 'bulk' ) ) { 
  343. // Bulk-edit 
  344.  
  345. lib2()->array->equip_post( 'action', 'action2', 'item', 'rule_type' ); 
  346. $action = $_POST['action']; 
  347. if ( empty( $action ) || $action == '-1' ) { 
  348. $action = $_POST['action2']; 
  349. $items = $_POST['item']; 
  350. $rule_type = $_POST['rule_type']; 
  351.  
  352. /** 
  353. * The Bulk-Edit action is built like 'cmd-id' 
  354. * e.g. 'add-123' will add membership 123 to the selected items. 
  355. */ 
  356. if ( empty( $action ) ) { 
  357. $cmd = array(); 
  358. } elseif ( empty( $items ) ) { 
  359. $cmd = array(); 
  360. } elseif ( empty( $rule_type ) ) { 
  361. $cmd = array(); 
  362. } elseif ( '-1' == $action ) { 
  363. $cmd = array(); 
  364. } else { 
  365. $cmd = explode( '-', $action ); 
  366.  
  367. if ( 2 == count( $cmd ) ) { 
  368. $action = $cmd[0]; 
  369. $action_id = $cmd[1]; 
  370.  
  371. // Get a list of specified memberships... 
  372. if ( is_numeric( $action_id ) ) { 
  373. // ... either a single membership. 
  374. $memberships = array( 
  375. MS_Factory::load( 'MS_Model_Membership', $action_id ),  
  376. ); 
  377. } elseif ( 'all' == $action_id ) { 
  378. // ... or all memberships. 
  379. $memberships = MS_Model_Membership::get_memberships(); 
  380.  
  381. // Loop specified memberships and add the selected items. 
  382. foreach ( $memberships as $membership ) { 
  383. $rule = $membership->get_rule( $rule_type ); 
  384. foreach ( $items as $item ) { 
  385. switch ( $action ) { 
  386. case 'add': 
  387. $rule->give_access( $item ); 
  388. break; 
  389.  
  390. case 'rem': 
  391. $rule->remove_access( $item ); 
  392. break; 
  393. $membership->set_rule( $rule_type, $rule ); 
  394. $membership->save(); 
  395. } else { 
  396. // No action request found. 
  397.  
  398. /** 
  399. * Route page request to handling method. 
  400. * 
  401. * @since 1.0.0 
  402. */ 
  403. public function membership_admin_page_router() { 
  404. $this->wizard_tracker(); 
  405. $step = $this->get_step(); 
  406.  
  407. if ( self::is_valid_step( $step ) ) { 
  408. $method = 'page_' . $step; 
  409.  
  410. if ( method_exists( $this, $method ) ) { 
  411. $callback = apply_filters( 
  412. 'ms_controller_membership_admin_page_router_callback',  
  413. array( $this, $method ),  
  414. $this 
  415. ); 
  416. call_user_func( $callback ); 
  417. } else { 
  418. do_action( 
  419. 'ms_controller_membership_admin_page_router_' . $step,  
  420. $this 
  421. ); 
  422. MS_Helper_Debug::log( "Method $method not found for step $step" ); 
  423. } else { 
  424. MS_Helper_Debug::log( "Invalid step: $step" ); 
  425.  
  426. do_action( 
  427. 'ms_controller_membership_admin_page_router',  
  428. $step,  
  429. $this 
  430. ); 
  431.  
  432. /** 
  433. * Mark membership setup as complete. 
  434. * 
  435. * @since 1.0.0 
  436. * 
  437. * @return int $msg The action status message code. 
  438. */ 
  439. private function mark_setup_completed() { 
  440. $msg = 0; 
  441. $membership = $this->load_membership(); 
  442.  
  443. if ( $membership->setup_completed() ) { 
  444. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_ADDED; 
  445. do_action( 
  446. 'ms_controller_membership_setup_completed',  
  447. $membership 
  448. ); 
  449.  
  450. return apply_filters( 
  451. 'ms_controller_membership_mark_setup_completed',  
  452. $msg,  
  453. $this 
  454. ); 
  455.  
  456. /** 
  457. * Display Setup Membership2 page. 
  458. * 
  459. * @since 1.0.0 
  460. */ 
  461. public function page_protected_content() { 
  462. $data = array(); 
  463. $data['tabs'] = $this->get_available_tabs(); 
  464. $data['active_tab'] = $this->get_active_tab(); 
  465.  
  466. $view = MS_Factory::create( 'MS_View_Membership_ProtectedContent' ); 
  467. $view->data = apply_filters( 'ms_view_membership_protectedcontent_data', $data, $this ); 
  468. $view->render(); 
  469.  
  470. /** 
  471. * Display Choose Membership Type page. 
  472. * 
  473. * @since 1.0.0 
  474. */ 
  475. public function page_add() { 
  476. $data = array(); 
  477. $data['step'] = $this->get_step(); 
  478. $data['action'] = self::ACTION_SAVE; 
  479. $data['membership'] = $this->load_membership(); 
  480.  
  481. $view = MS_Factory::create( 'MS_View_Membership_Add' ); 
  482. $view->data = apply_filters( 'ms_view_membership_add_data', $data, $this ); 
  483. $view->render(); 
  484.  
  485. /** 
  486. * Display Membership List page. 
  487. * 
  488. * @since 1.0.0 
  489. */ 
  490. public function page_ms_list() { 
  491. $membership = $this->load_membership(); 
  492.  
  493. $data = array(); 
  494. $data['step'] = $this->get_step(); 
  495. $data['action'] = self::ACTION_SAVE; 
  496. $data['membership'] = $membership; 
  497. $data['create_new_url'] = MS_Controller_Plugin::get_admin_url( 
  498. false,  
  499. array( 'step' => self::STEP_ADD_NEW ) 
  500. ); 
  501.  
  502. $view = MS_Factory::create( 'MS_View_Membership_List' ); 
  503. $view->data = apply_filters( 'ms_view_membership_list_data', $data, $this ); 
  504. $view->render(); 
  505.  
  506. /** 
  507. * Display Setup Payment page. 
  508. * 
  509. * @since 1.0.0 
  510. */ 
  511. public function page_payment() { 
  512. $membership = $this->load_membership(); 
  513.  
  514. $data = array(); 
  515. $data['step'] = $this->get_step(); 
  516. $data['action'] = 'save_payment_settings'; 
  517. $data['membership'] = $membership; 
  518. $data['is_global_payments_set'] = MS_Plugin::instance()->settings->is_global_payments_set; 
  519. $data['bread_crumbs'] = $this->get_bread_crumbs(); 
  520.  
  521. if ( isset( $_GET['edit'] ) ) { 
  522. $data['show_next_button'] = false; 
  523. } else { 
  524. $data['show_next_button'] = array( 
  525. 'id' => 'next',  
  526. 'value' => __( 'Finish', MS_TEXT_DOMAIN ),  
  527. 'action' => 'next',  
  528. ); 
  529.  
  530. $view = MS_Factory::create( 'MS_View_Membership_Payment' ); 
  531. $view->data = apply_filters( 'ms_view_membership_payment_data', $data, $this ); 
  532. $view->render(); 
  533.  
  534. /** 
  535. * Display Membership Overview page. 
  536. * 
  537. * @since 1.0.0 
  538. */ 
  539. public function page_ms_overview() { 
  540. $membership = $this->load_membership(); 
  541. $membership_id = $membership->id; 
  542.  
  543. $data = array(); 
  544. $data['step'] = $this->get_step(); 
  545. $data['action'] = self::ACTION_SAVE; 
  546. $data['membership'] = $membership; 
  547. $data['bread_crumbs'] = $this->get_bread_crumbs(); 
  548.  
  549. $data['members'] = array(); 
  550. $ms_relationships = MS_Model_Relationship::get_subscriptions( 
  551. array( 'membership_id' => $membership->id ) 
  552. ); 
  553.  
  554. foreach ( $ms_relationships as $ms_relationship ) { 
  555. $data['members'][] = $ms_relationship->get_member(); 
  556.  
  557. switch ( $membership->type ) { 
  558. case MS_Model_Membership::TYPE_DRIPPED: 
  559. $view = MS_Factory::create( 'MS_View_Membership_Overview_Dripped' ); 
  560. break; 
  561.  
  562. default: 
  563. case MS_Model_Membership::TYPE_STANDARD: 
  564. $view = MS_Factory::create( 'MS_View_Membership_Overview_Simple' ); 
  565. break; 
  566.  
  567. // Select Events args 
  568. $args = array(); 
  569. $args['meta_query']['membership_id'] = array( 
  570. 'key' => 'membership_id',  
  571. 'value' => array( $membership_id, 0 ),  
  572. 'compare' => 'IN',  
  573. ); 
  574. $data['events'] = MS_Model_Event::get_events( $args ); 
  575.  
  576. $view = apply_filters( 'ms_view_membership_ms_overview', $view ); 
  577. $view->data = apply_filters( 'ms_view_membership_ms_overview_data', $data, $this ); 
  578. $view->render(); 
  579.  
  580. /** 
  581. * Display Membership News page. 
  582. * 
  583. * @since 1.0.0 
  584. */ 
  585. public function page_ms_news() { 
  586. $data = array(); 
  587. $data['step'] = $this->get_step(); 
  588. $data['action'] = ''; 
  589. $data['membership'] = $this->load_membership(); 
  590.  
  591. $args = apply_filters( 
  592. 'ms_controller_membership_page_ms_news_event_args',  
  593. array( 'posts_per_page' => -1 ) 
  594. ); 
  595. $data['events'] = MS_Model_Event::get_events( $args ); 
  596.  
  597. $view = MS_Factory::create( 'MS_View_Membership_News' ); 
  598. $view->data = apply_filters( 'ms_view_membership_news_data', $data, $this ); 
  599. $view->render(); 
  600.  
  601. /** 
  602. * Display a welcome screen. 
  603. * 
  604. * @since 1.1.0 
  605. */ 
  606. public function page_welcome() { 
  607. $data = array(); 
  608. $data['step'] = $this->get_step(); 
  609. $data['action'] = 'start'; 
  610.  
  611. $view = MS_Factory::create( 'MS_View_Welcome' ); 
  612. $view->data = apply_filters( 'ms_view_welcome_data', $data, $this ); 
  613. $view->render(); 
  614.  
  615. /** 
  616. * Get Membership setup steps. 
  617. * 
  618. * @since 1.0.0 
  619. * 
  620. * @return string[] The existing steps. 
  621. */ 
  622. public static function get_steps() { 
  623. static $steps; 
  624.  
  625. if ( empty( $steps ) ) { 
  626. $steps = array( 
  627. self::STEP_MS_LIST,  
  628. self::STEP_OVERVIEW,  
  629. self::STEP_NEWS,  
  630. self::STEP_PROTECTED_CONTENT,  
  631. self::STEP_ADD_NEW,  
  632. self::STEP_PAYMENT,  
  633. ); 
  634.  
  635. if ( MS_Plugin::is_wizard() ) { 
  636. $steps[] = self::STEP_WELCOME_SCREEN; 
  637.  
  638. return apply_filters( 
  639. 'ms_controller_membership_get_steps',  
  640. $steps 
  641. ); 
  642.  
  643. /** 
  644. * Validate Membership setup step. 
  645. * 
  646. * @since 1.0.0 
  647. * 
  648. * @param string $step The step name to validate. 
  649. * @return boolean True if valid step. 
  650. */ 
  651. public static function is_valid_step( $step ) { 
  652. $valid = false; 
  653.  
  654. $steps = self::get_steps(); 
  655. if ( in_array( $step, $steps ) ) { 
  656. $valid = true; 
  657.  
  658. return apply_filters( 
  659. 'ms_controller_membership_is_valid_step',  
  660. $valid,  
  661. $step 
  662. ); 
  663.  
  664. /** 
  665. * Get current step. 
  666. * 
  667. * Try to retrieve step from request. 
  668. * Validate the step, returning a default if not valid. 
  669. * 
  670. * since 1.0.0 
  671. * 
  672. * @return string The current step. 
  673. */ 
  674. public function get_step() { 
  675. // Initial step 
  676. $step = self::STEP_MS_LIST; 
  677. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  678. $membership = $this->load_membership(); 
  679.  
  680. // Get current step from request 
  681. if ( ! empty( $_REQUEST['step'] ) && self::is_valid_step( $_REQUEST['step'] ) ) { 
  682. $step = $_REQUEST['step']; 
  683.  
  684. // If user has left before completing the wizard, try to recover last wizard step. 
  685. elseif ( MS_Plugin::is_wizard() ) { 
  686. $wizard_steps = apply_filters( 
  687. 'ms_controller_membership_wizard_steps',  
  688. array( 
  689. self::STEP_WELCOME_SCREEN,  
  690. self::STEP_ADD_NEW,  
  691. ); 
  692.  
  693. if ( $settings->wizard_step 
  694. && in_array( $settings->wizard_step, $wizard_steps ) 
  695. ) { 
  696. $step = $settings->wizard_step; 
  697. } else { 
  698. $step = self::STEP_WELCOME_SCREEN; 
  699.  
  700. // Hack to use same page in two different menus 
  701. if ( MS_Controller_Plugin::is_page( 'protection' ) ) { 
  702. $step = self::STEP_PROTECTED_CONTENT; 
  703.  
  704. // Can't modify membership type 
  705. if ( self::STEP_ADD_NEW == $step && $membership->is_valid() ) { 
  706. $step = self::STEP_OVERVIEW; 
  707.  
  708. return apply_filters( 
  709. 'ms_controller_membership_get_next_step',  
  710. $step,  
  711. $this 
  712. ); 
  713.  
  714. /** 
  715. * Track wizard step. 
  716. * 
  717. * Save current step. 
  718. * 
  719. * since 1.0.0 
  720. * 
  721. * @param string $step Optional. The step to save. Default to current step. 
  722. * @param boolean $end_wizard Optional. Whether end the wizard mode. 
  723. * @return string The current step. 
  724. */ 
  725. public function wizard_tracker( $step = null, $end_wizard = false ) { 
  726. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  727.  
  728. if ( empty( $step ) ) { 
  729. $step = $this->get_step(); 
  730.  
  731. if ( MS_Plugin::is_wizard() ) { 
  732. $settings->wizard_step = $step; 
  733.  
  734. if ( $end_wizard ) { 
  735. $settings->initial_setup = false; 
  736. $settings->save(); 
  737.  
  738. do_action( 
  739. 'ms_controller_membership_wizard_tracker',  
  740. $step,  
  741. $end_wizard,  
  742. $settings,  
  743. $this 
  744. ); 
  745.  
  746. /** 
  747. * Get available tabs for Membership2 page. 
  748. * 
  749. * @since 1.0.0 
  750. * 
  751. * @return array The tabs configuration. 
  752. */ 
  753. public function get_available_tabs() { 
  754. static $Tabs = null; 
  755.  
  756. if ( null === $Tabs ) { 
  757. $membership = $this->load_membership(); 
  758. $membership_id = $membership->id; 
  759. $is_base = $membership->is_base(); 
  760. $settings = MS_Factory::load( 'MS_Model_Settings' ); 
  761.  
  762. // First create a list including all possible tabs. 
  763. $tabs = array( 
  764. MS_Rule_Page::RULE_ID => true,  
  765. MS_Rule_Post::RULE_ID => true,  
  766. MS_Rule_Category::RULE_ID => true,  
  767. MS_Rule_Content::RULE_ID => true,  
  768. MS_Rule_MenuItem::RULE_ID => true,  
  769. MS_Rule_ReplaceMenu::RULE_ID => true,  
  770. MS_Rule_ReplaceLocation::RULE_ID => true,  
  771. MS_Rule_Shortcode::RULE_ID => true,  
  772. MS_Rule_Url::RULE_ID => true,  
  773. MS_Rule_Special::RULE_ID => true,  
  774. MS_Rule_MemberCaps::RULE_ID => true,  
  775. MS_Rule_MemberRoles::RULE_ID => true,  
  776. ); 
  777.  
  778. // Now remove items from the list that are not available. 
  779.  
  780. // Optionally show "Posts" 
  781. if ( ! MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_POST_BY_POST ) ) { 
  782. $tabs[MS_Rule_Post::RULE_ID] = false; 
  783.  
  784. // Optionally show "Category" 
  785. if ( ! MS_Model_Addon::is_enabled( MS_Addon_Category::ID ) ) { 
  786. $tabs[MS_Rule_Category::RULE_ID] = false; 
  787.  
  788. // Either "Menu Item" or "Menus" or "Menu Location" 
  789. switch ( $settings->menu_protection ) { 
  790. case 'menu': 
  791. $tabs[MS_Rule_MenuItem::RULE_ID] = false; 
  792. $tabs[MS_Rule_ReplaceLocation::RULE_ID] = false; 
  793. break; 
  794.  
  795. case 'location': 
  796. $tabs[MS_Rule_MenuItem::RULE_ID] = false; 
  797. $tabs[MS_Rule_ReplaceMenu::RULE_ID] = false; 
  798. break; 
  799.  
  800. case 'item': 
  801. default: 
  802. $tabs[MS_Rule_ReplaceMenu::RULE_ID] = false; 
  803. $tabs[MS_Rule_ReplaceLocation::RULE_ID] = false; 
  804. break; 
  805.  
  806. // Maybe "Special Pages". 
  807. if ( ! MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_SPECIAL_PAGES ) ) { 
  808. $tabs[MS_Rule_Special::RULE_ID] = false; 
  809.  
  810. // Maybe "URLs" 
  811. if ( ! MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_URL_GROUPS ) ) { 
  812. $tabs[MS_Rule_Url::RULE_ID] = false; 
  813.  
  814. // Maybe "Shortcodes" 
  815. if ( ! MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_SHORTCODE ) ) { 
  816. $tabs[MS_Rule_Shortcode::RULE_ID] = false; 
  817.  
  818. // Maybe "Membercaps" 
  819. if ( MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_MEMBERCAPS ) ) { 
  820. if ( MS_Model_Addon::is_enabled( MS_Model_Addon::ADDON_MEMBERCAPS_ADV ) ) { 
  821. $tabs[MS_Rule_MemberRoles::RULE_ID] = false; 
  822. } else { 
  823. $tabs[MS_Rule_MemberCaps::RULE_ID] = false; 
  824. } else { 
  825. $tabs[MS_Rule_MemberRoles::RULE_ID] = false; 
  826. $tabs[MS_Rule_MemberCaps::RULE_ID] = false; 
  827.  
  828. lib2()->array->equip( $_GET, 'page' ); 
  829.  
  830. // Allow Add-ons to add or remove rule tabs 
  831. $tabs = apply_filters( 
  832. 'ms_controller_membership_tabs',  
  833. $tabs,  
  834. $membership_id 
  835. ); 
  836.  
  837. $url = admin_url( 'admin.php' ); 
  838. $page = sanitize_html_class( $_GET['page'], MS_Controller_Plugin::MENU_SLUG . '-memberships' ); 
  839. $rule_titles = MS_Model_Rule::get_rule_type_titles(); 
  840.  
  841. $result = array(); 
  842. foreach ( $tabs as $rule_type => $state ) { 
  843. if ( ! $state ) { continue; } 
  844.  
  845. $url .= sprintf( 
  846. '?page=%s&tab=%s',  
  847. $page,  
  848. $rule_type 
  849. ); 
  850.  
  851. // Try to keep the selected Membership and Status filter. 
  852. if ( ! empty( $_REQUEST['membership_id'] ) ) { 
  853. $url = esc_url_raw( 
  854. add_query_arg( 
  855. array( 'membership_id' => $_REQUEST['membership_id'] ),  
  856. $url 
  857. ); 
  858. if ( ! empty( $_REQUEST['status'] ) ) { 
  859. $url = esc_url_raw( 
  860. add_query_arg( 
  861. array( 'status' => $_REQUEST['status'] ),  
  862. $url 
  863. ); 
  864.  
  865. $result[ $rule_type ] = array( 
  866. 'title' => $rule_titles[ $rule_type ],  
  867. 'url' => $url,  
  868. ); 
  869.  
  870. $Tabs = apply_filters( 
  871. 'ms_controller_membership_get_protection_tabs',  
  872. $result,  
  873. $membership_id,  
  874. $this 
  875. ); 
  876.  
  877. return $Tabs; 
  878.  
  879. /** 
  880. * Get the current membership page's active tab. 
  881. * 
  882. * @since 1.0.0 
  883. * 
  884. * @return string The active tab. 
  885. */ 
  886. public function get_active_tab() { 
  887. $step = $this->get_step(); 
  888. $tabs = array(); 
  889.  
  890. $tabs = $this->get_available_tabs(); 
  891.  
  892. reset( $tabs ); 
  893. $first_key = key( $tabs ); 
  894.  
  895. // Setup navigation tabs. 
  896. $active_tab = isset( $_REQUEST['tab'] ) ? $_REQUEST['tab'] : ''; 
  897. $active_tab = sanitize_html_class( $active_tab, $first_key ); 
  898.  
  899. if ( ! array_key_exists( $active_tab, $tabs ) ) { 
  900. $active_tab = $first_key; 
  901.  
  902. $this->active_tab = apply_filters( 
  903. 'ms_controller_membership_get_active_tab',  
  904. $active_tab 
  905. ); 
  906.  
  907. return $this->active_tab; 
  908.  
  909. /** 
  910. * Execute action in Membership model. 
  911. * 
  912. * @since 1.0.0 
  913. * 
  914. * @todo There is no more bulk actions. Deprecate this method and create a specific one. 
  915. * 
  916. * @param string $action The action to execute. 
  917. * @param int[] $membership_ids The membership ids which action will be taken. 
  918. * @return number Resulting message id. 
  919. */ 
  920. private function membership_list_do_action( $action, $membership_ids ) { 
  921. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_NOT_UPDATED; 
  922.  
  923. if ( ! $this->is_admin_user() ) { 
  924. return $msg; 
  925.  
  926. $msg = 0; 
  927. foreach ( $membership_ids as $membership_id ) { 
  928. $membership = MS_Factory::load( 'MS_Model_Membership', $membership_id ); 
  929.  
  930. switch ( $action ) { 
  931. case 'toggle_active': 
  932. case 'toggle_activation': 
  933. $membership->active = ! $membership->active; 
  934. $membership->save(); 
  935. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_ACTIVATION_TOGGLED; 
  936. break; 
  937.  
  938. case 'toggle_public': 
  939. $membership->private = ! $membership->private; 
  940. $membership->save(); 
  941. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_STATUS_TOGGLED; 
  942. break; 
  943.  
  944. case 'delete': 
  945. try { 
  946. $membership->delete(); 
  947. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_DELETED; 
  948. catch( Exception $e ) { 
  949. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_NOT_DELETED; 
  950. break; 
  951.  
  952. return $msg; 
  953.  
  954. /** 
  955. * Get Membership page bread crumbs. 
  956. * 
  957. * @since 1.0.0 
  958. * 
  959. * @return array The bread crumbs array. 
  960. */ 
  961. public function get_bread_crumbs() { 
  962. $step = $this->get_step(); 
  963. $membership = $this->load_membership(); 
  964.  
  965. $bread_crumbs = array(); 
  966.  
  967. switch ( $step ) { 
  968. case self::STEP_OVERVIEW: 
  969. $bread_crumbs['prev'] = array( 
  970. 'title' => __( 'Memberships', MS_TEXT_DOMAIN ),  
  971. 'url' => MS_Controller_Plugin::get_admin_url( 
  972. false,  
  973. array( 'step' => self::STEP_MS_LIST ) 
  974. ),  
  975. ); 
  976. $bread_crumbs['current'] = array( 
  977. 'title' => $membership->name,  
  978. ); 
  979. break; 
  980.  
  981. case self::STEP_PAYMENT: 
  982. $bread_crumbs['prev'] = array( 
  983. 'title' => $membership->name,  
  984. 'url' => MS_Controller_Plugin::get_admin_url( 
  985. false,  
  986. array( 
  987. 'step' => self::STEP_OVERVIEW,  
  988. 'membership_id' => $membership->id,  
  989. ),  
  990. ); 
  991. $bread_crumbs['current'] = array( 
  992. 'title' => __( 'Payment', MS_TEXT_DOMAIN ),  
  993. ); 
  994. break; 
  995.  
  996. // Add the "edit" param if it is set. 
  997. if ( isset( $_GET['edit'] ) ) { 
  998. foreach ( $bread_crumbs as $key => $data ) { 
  999. if ( isset( $bread_crumbs[$key]['url'] ) ) { 
  1000. $bread_crumbs[$key]['url'] .= '&edit=1'; 
  1001.  
  1002. return apply_filters( 
  1003. 'ms_controller_membership_get_bread_crumbs',  
  1004. $bread_crumbs,  
  1005. $this 
  1006. ); 
  1007.  
  1008. /** 
  1009. * Save membership general tab fields 
  1010. * 
  1011. * @since 1.0.0 
  1012. * 
  1013. * @param mixed[] $fields 
  1014. */ 
  1015. private function save_membership( $fields ) { 
  1016. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_NOT_UPDATED; 
  1017.  
  1018. if ( $this->is_admin_user() ) { 
  1019. $membership = $this->load_membership(); 
  1020.  
  1021. if ( is_array( $fields ) ) { 
  1022. $updated = 0; 
  1023. $failed = 0; 
  1024. foreach ( $fields as $field => $value ) { 
  1025. $key = false; 
  1026.  
  1027. // Very basic support for array updates. 
  1028. // We only support updating arrays when one key is 
  1029. if ( strpos( $field, '[' ) ) { 
  1030. $field = str_replace( ']', '', $field ); 
  1031. list( $field, $key ) = explode( '[', $field, 2 ); 
  1032.  
  1033. try { 
  1034. $the_value = $membership->$field; 
  1035. if ( $key ) { 
  1036. $the_value[$key] = $value; 
  1037. } else { 
  1038. $the_value = $value; 
  1039. $membership->$field = $the_value; 
  1040.  
  1041. $updated += 1; 
  1042. catch ( Exception $e ) { 
  1043. $failed += 1; 
  1044. $membership->save(); 
  1045.  
  1046. if ( $updated > 0 ) { 
  1047. if ( ! $failed ) { 
  1048. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_UPDATED; 
  1049. } else { 
  1050. $msg = MS_Helper_Membership::MEMBERSHIP_MSG_PARTIALLY_UPDATED; 
  1051.  
  1052. return apply_filters( 
  1053. 'ms_controller_membership_save_membership_msg',  
  1054. $msg,  
  1055. $fields,  
  1056. $this 
  1057. ); 
  1058.  
  1059. /** 
  1060. * Load Membership manager specific styles. 
  1061. * 
  1062. * @since 1.0.0 
  1063. */ 
  1064. public function enqueue_styles() { 
  1065. switch ( $this->get_active_tab() ) { 
  1066. default: 
  1067. lib2()->ui->add( 'jquery-ui' ); 
  1068. break; 
  1069.  
  1070. do_action( 'ms_controller_membership_enqueue_styles', $this ); 
  1071.  
  1072. /** 
  1073. * Load Membership manager specific scripts. 
  1074. * 
  1075. * @since 1.0.0 
  1076. */ 
  1077. public function enqueue_scripts() { 
  1078. /** 
  1079. * Get a list of the dripped memberships: 
  1080. * We need this info in the javascript 
  1081. */ 
  1082. $dripped = array(); 
  1083. foreach ( MS_Model_Membership::get_dripped_memberships() as $item ) { 
  1084. $dripped[ $item->id ] = $item->name; 
  1085.  
  1086. $data = array( 
  1087. 'ms_init' => array(),  
  1088. 'lang' => array( 
  1089. 'msg_delete' => __( 'Do you want to completely delete the membership <strong>%s</strong> including all subscriptions?', MS_TEXT_DOMAIN ),  
  1090. 'btn_delete' => __( 'Delete', MS_TEXT_DOMAIN ),  
  1091. 'btn_cancel' => __( 'Cancel', MS_TEXT_DOMAIN ),  
  1092. 'quickedit_error' => __( 'Error while saving changes.', MS_TEXT_DOMAIN ),  
  1093. ),  
  1094. 'dripped' => $dripped,  
  1095. ); 
  1096.  
  1097. $step = $this->get_step(); 
  1098.  
  1099. switch ( $step ) { 
  1100. case self::STEP_WELCOME_SCREEN: 
  1101. break; 
  1102.  
  1103. case self::STEP_ADD_NEW: 
  1104. $data['ms_init'][] = 'view_membership_add'; 
  1105. $data['initial_url'] = MS_Controller_Plugin::get_admin_url(); 
  1106. break; 
  1107.  
  1108. case self::STEP_OVERVIEW: 
  1109. $data['ms_init'][] = 'view_membership_overview'; 
  1110. break; 
  1111.  
  1112. case self::STEP_PROTECTED_CONTENT: 
  1113. $data['ms_init'][] = 'view_protected_content'; 
  1114.  
  1115. switch ( $this->get_active_tab() ) { 
  1116. case 'url': 
  1117. $data['valid_rule_msg'] = __( 'Valid', MS_TEXT_DOMAIN ); 
  1118. $data['invalid_rule_msg'] = __( 'Invalid', MS_TEXT_DOMAIN ); 
  1119. $data['empty_msg'] = __( 'Before testing you have to first enter one or more Page URLs above.', MS_TEXT_DOMAIN ); 
  1120. $data['ms_init'][] = 'view_membership_urlgroup'; 
  1121. break; 
  1122.  
  1123. default: 
  1124. wp_enqueue_script( 'jquery-ui-datepicker' ); 
  1125. wp_enqueue_script( 'jquery-validate' ); 
  1126. break; 
  1127. break; 
  1128.  
  1129. case self::STEP_PAYMENT: 
  1130. $data['ms_init'][] = 'view_membership_payment'; 
  1131. $data['ms_init'][] = 'view_settings_payment'; 
  1132. wp_enqueue_script( 'jquery-validate' ); 
  1133. break; 
  1134.  
  1135. case self::STEP_MS_LIST: 
  1136. $data['ms_init'][] = 'view_membership_list'; 
  1137. $data['ms_init'][] = 'view_settings_setup'; 
  1138. break; 
  1139.  
  1140. lib2()->ui->data( 'ms_data', $data ); 
  1141. wp_enqueue_script( 'ms-admin' ); 
  1142.  
  1143. do_action( 'ms_controller_membership_enqueue_scripts', $this ); 
  1144.  
.