class.swpm-members.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. <?php
  2. if ( ! class_exists( 'WP_List_Table' ) ) {
  3. require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
  4. }
  5. class SwpmMembers extends WP_List_Table {
  6. function __construct() {
  7. parent::__construct(
  8. array(
  9. 'singular' => SwpmUtils::_( 'Member' ),
  10. 'plural' => SwpmUtils::_( 'Members' ),
  11. 'ajax' => false,
  12. )
  13. );
  14. }
  15. function get_columns() {
  16. return array(
  17. 'cb' => '<input type="checkbox" />',
  18. 'member_id' => SwpmUtils::_( 'ID' ),
  19. 'user_name' => SwpmUtils::_( 'Username' ),
  20. 'first_name' => SwpmUtils::_( 'First Name' ),
  21. 'last_name' => SwpmUtils::_( 'Last Name' ),
  22. 'email' => SwpmUtils::_( 'Email' ),
  23. 'alias' => SwpmUtils::_( 'Membership Level' ),
  24. 'subscription_starts' => SwpmUtils::_( 'Access Starts' ),
  25. 'account_state' => SwpmUtils::_( 'Account State' ),
  26. 'last_accessed' => SwpmUtils::_( 'Last Login Date' ),
  27. 'birth_place' => SwpmUtils::_( 'Birth Place' ),
  28. );
  29. }
  30. function get_sortable_columns() {
  31. return array(
  32. 'member_id' => array( 'member_id', true ), //True means already sorted
  33. 'user_name' => array( 'user_name', false ),
  34. 'first_name' => array( 'first_name', false ),
  35. 'last_name' => array( 'last_name', false ),
  36. 'email' => array( 'email', false ),
  37. 'alias' => array( 'alias', false ),
  38. 'subscription_starts' => array( 'subscription_starts', false ),
  39. 'account_state' => array( 'account_state', false ),
  40. 'last_accessed' => array( 'last_accessed', false ),
  41. 'birth_place' => array( 'birth_place', false ),
  42. );
  43. }
  44. function get_bulk_actions() {
  45. $actions = array(
  46. 'bulk_delete' => SwpmUtils::_( 'Delete' ),
  47. 'bulk_active' => SwpmUtils::_( 'Set Status to Active' ),
  48. 'bulk_active_notify' => SwpmUtils::_( 'Set Status to Active and Notify' ),
  49. 'bulk_inactive' => SwpmUtils::_( 'Set Status to Inactive' ),
  50. 'bulk_pending' => SwpmUtils::_( 'Set Status to Pending' ),
  51. 'bulk_expired' => SwpmUtils::_( 'Set Status to Expired' ),
  52. );
  53. return $actions;
  54. }
  55. function column_default( $item, $column_name ) {
  56. return $item[ $column_name ];
  57. }
  58. function column_account_state( $item ) {
  59. $acc_state_str = ucfirst( $item['account_state'] );
  60. return SwpmUtils::_( $acc_state_str );
  61. }
  62. function column_member_id( $item ) {
  63. $delete_swpmuser_nonce = wp_create_nonce( 'delete_swpmuser_admin_end' );
  64. $actions = array(
  65. 'edit' => sprintf( '<a href="admin.php?page=simple_wp_membership&member_action=edit&member_id=%s">Edit/View</a>', $item['member_id'] ),
  66. 'delete' => sprintf( '<a href="admin.php?page=simple_wp_membership&member_action=delete&member_id=%s&delete_swpmuser_nonce=%s" onclick="return confirm(\'Are you sure you want to delete this entry?\')">Delete</a>', $item['member_id'], $delete_swpmuser_nonce ),
  67. );
  68. return $item['member_id'] . $this->row_actions( $actions );
  69. }
  70. function column_user_name( $item ) {
  71. $user_name = $item['user_name'];
  72. if ( empty( $user_name ) ) {
  73. $user_name = '[' . SwpmUtils::_( 'incomplete' ) . ']';
  74. }
  75. return $user_name;
  76. }
  77. function column_cb( $item ) {
  78. return sprintf(
  79. '<input type="checkbox" name="members[]" value="%s" />',
  80. $item['member_id']
  81. );
  82. }
  83. function prepare_items() {
  84. global $wpdb;
  85. $this->process_bulk_action();
  86. $records_query_head = 'SELECT member_id,user_name,first_name,last_name,email,alias,subscription_starts,account_state,last_accessed,birth_place';
  87. $count_query_head = 'SELECT COUNT(member_id)';
  88. $query = ' ';
  89. $query .= ' FROM ' . $wpdb->prefix . 'swpm_members_tbl';
  90. $query .= ' LEFT JOIN ' . $wpdb->prefix . 'swpm_membership_tbl';
  91. $query .= ' ON ( membership_level = id ) ';
  92. //Get the search string (if any)
  93. $s = filter_input( INPUT_GET, 's' );
  94. if ( empty( $s ) ) {
  95. $s = filter_input( INPUT_POST, 's' );
  96. }
  97. $status = filter_input( INPUT_GET, 'status' );
  98. $status = esc_attr( $status );//Escape value
  99. $filters = array();
  100. //Add the search parameter to the query
  101. if ( ! empty( $s ) ) {
  102. $s = sanitize_text_field( $s );
  103. $s = trim( $s ); //Trim the input
  104. $s = esc_attr( $s );
  105. $filters[] = "( user_name LIKE '%" . strip_tags( $s ) . "%' "
  106. . " OR first_name LIKE '%" . strip_tags( $s ) . "%' "
  107. . " OR last_name LIKE '%" . strip_tags( $s ) . "%' "
  108. . " OR email LIKE '%" . strip_tags( $s ) . "%' "
  109. . " OR address_city LIKE '%" . strip_tags( $s ) . "%' "
  110. . " OR address_state LIKE '%" . strip_tags( $s ) . "%' "
  111. . " OR country LIKE '%" . strip_tags( $s ) . "%' "
  112. . " OR company_name LIKE '%" . strip_tags( $s ) . "%' "
  113. . " OR birth_place LIKE '%" . strip_tags( $s ) . "%' )";
  114. }
  115. //Add account status filtering to the query
  116. if ( ! empty( $status ) ) {
  117. if ( $status == 'incomplete' ) {
  118. $filters[] = "user_name = ''";
  119. } else {
  120. $filters[] = "account_state = '" . $status . "'";
  121. }
  122. }
  123. //Add membership level filtering
  124. $membership_level = filter_input( INPUT_GET, 'membership_level', FILTER_SANITIZE_NUMBER_INT );
  125. if ( ! empty( $membership_level ) ) {
  126. $filters[] = sprintf( "membership_level = '%d'", $membership_level );
  127. }
  128. //Build the WHERE clause of the query string
  129. if ( ! empty( $filters ) ) {
  130. $filter_str = '';
  131. foreach ( $filters as $ind => $filter ) {
  132. $filter_str .= $ind === 0 ? $filter : ' AND ' . $filter;
  133. }
  134. $query .= 'WHERE ' . $filter_str;
  135. }
  136. //Build the orderby and order query parameters
  137. $orderby = filter_input( INPUT_GET, 'orderby' );
  138. $orderby = empty( $orderby ) ? 'member_id' : $orderby;
  139. $order = filter_input( INPUT_GET, 'order' );
  140. $order = empty( $order ) ? 'DESC' : $order;
  141. $sortable_columns = $this->get_sortable_columns();
  142. $orderby = SwpmUtils::sanitize_value_by_array( $orderby, $sortable_columns );
  143. $order = SwpmUtils::sanitize_value_by_array(
  144. $order,
  145. array(
  146. 'DESC' => '1',
  147. 'ASC' => '1',
  148. )
  149. );
  150. $query .= ' ORDER BY ' . $orderby . ' ' . $order;
  151. //Execute the query
  152. $totalitems = $wpdb->get_var( $count_query_head . $query );
  153. //Pagination setup
  154. $perpage = apply_filters( 'swpm_members_menu_items_per_page', 50 );
  155. $paged = filter_input( INPUT_GET, 'paged' );
  156. if ( empty( $paged ) || ! is_numeric( $paged ) || $paged <= 0 ) {
  157. $paged = 1;
  158. }
  159. $totalpages = ceil( $totalitems / $perpage );
  160. if ( ! empty( $paged ) && ! empty( $perpage ) ) {
  161. $offset = ( $paged - 1 ) * $perpage;
  162. $query .= ' LIMIT ' . (int) $offset . ',' . (int) $perpage;
  163. }
  164. $this->set_pagination_args(
  165. array(
  166. 'total_items' => $totalitems,
  167. 'total_pages' => $totalpages,
  168. 'per_page' => $perpage,
  169. )
  170. );
  171. $columns = $this->get_columns();
  172. $hidden = array();
  173. $sortable = $this->get_sortable_columns();
  174. $this->_column_headers = array( $columns, $hidden, $sortable );
  175. $this->items = $wpdb->get_results( $records_query_head . $query, ARRAY_A );
  176. }
  177. function get_user_count_by_account_state() {
  178. global $wpdb;
  179. $query = 'SELECT count(member_id) AS count, account_state FROM ' . $wpdb->prefix . 'swpm_members_tbl GROUP BY account_state';
  180. $result = $wpdb->get_results( $query, ARRAY_A );
  181. $count = array();
  182. $all = 0;
  183. foreach ( $result as $row ) {
  184. $count[ $row['account_state'] ] = $row['count'];
  185. $all += intval( $row['count'] );
  186. }
  187. $count ['all'] = $all;
  188. $count_incomplete_query = 'SELECT COUNT(*) FROM ' . $wpdb->prefix . "swpm_members_tbl WHERE user_name = ''";
  189. $count['incomplete'] = $wpdb->get_var( $count_incomplete_query );
  190. return $count;
  191. }
  192. function no_items() {
  193. _e( 'No member found.', 'simple-membership' );
  194. }
  195. function process_form_request() {
  196. if ( isset( $_REQUEST['member_id'] ) ) {
  197. //This is a member profile edit action
  198. $record_id = sanitize_text_field( $_REQUEST['member_id'] );
  199. if ( ! is_numeric( $record_id ) ) {
  200. wp_die( 'Error! ID must be numeric.' );
  201. }
  202. return $this->edit( absint( $record_id ) );
  203. }
  204. //This is an profile add action.
  205. return $this->add();
  206. }
  207. function add() {
  208. $form = apply_filters( 'swpm_admin_registration_form_override', '' );
  209. if ( ! empty( $form ) ) {
  210. echo $form;
  211. return;
  212. }
  213. global $wpdb;
  214. $member = SwpmTransfer::$default_fields;
  215. $member['member_since'] = SwpmUtils::get_current_date_in_wp_zone();//date( 'Y-m-d' );
  216. $member['subscription_starts'] = SwpmUtils::get_current_date_in_wp_zone();//date( 'Y-m-d' );
  217. if ( isset( $_POST['createswpmuser'] ) ) {
  218. $member = array_map( 'sanitize_text_field', $_POST );
  219. }
  220. extract( $member, EXTR_SKIP );
  221. $query = 'SELECT * FROM ' . $wpdb->prefix . 'swpm_membership_tbl WHERE id !=1 ';
  222. $levels = $wpdb->get_results( $query, ARRAY_A );
  223. $add_user_template_path = apply_filters('swpm_admin_registration_add_user_template_path', SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_add.php');
  224. include_once $add_user_template_path;
  225. return false;
  226. }
  227. function edit( $id ) {
  228. global $wpdb;
  229. $id = absint( $id );
  230. $query = "SELECT * FROM {$wpdb->prefix}swpm_members_tbl WHERE member_id = $id";
  231. $member = $wpdb->get_row( $query, ARRAY_A );
  232. if ( isset( $_POST['editswpmuser'] ) ) {
  233. $_POST['user_name'] = sanitize_text_field( $member['user_name'] );
  234. $_POST['email'] = sanitize_email( $member['email'] );
  235. foreach ( $_POST as $key => $value ) {
  236. $key = sanitize_text_field( $key );
  237. if ( $key == 'email' ) {
  238. $member[ $key ] = sanitize_email( $value );
  239. } else {
  240. $member[ $key ] = sanitize_text_field( $value );
  241. }
  242. }
  243. }
  244. extract( $member, EXTR_SKIP );
  245. $query = 'SELECT * FROM ' . $wpdb->prefix . 'swpm_membership_tbl WHERE id !=1 ';
  246. $levels = $wpdb->get_results( $query, ARRAY_A );
  247. $edit_user_template_path = apply_filters('swpm_admin_registration_edit_user_template_path', SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_edit.php');
  248. include_once $edit_user_template_path;
  249. return false;
  250. }
  251. function process_bulk_action() {
  252. //Detect when a bulk action is being triggered... then perform the action.
  253. $members = isset( $_REQUEST['members'] ) ? $_REQUEST['members'] : array();
  254. $members = array_map( 'sanitize_text_field', $members );
  255. $current_action = $this->current_action();
  256. if ( ! empty( $current_action ) ) {
  257. //Bulk operation action. Lets make sure multiple records were selected before going ahead.
  258. if ( empty( $members ) ) {
  259. echo '<div id="message" class="error"><p>Error! You need to select multiple records to perform a bulk action!</p></div>';
  260. return;
  261. }
  262. } else {
  263. //No bulk operation.
  264. return;
  265. }
  266. //perform the bulk operation according to the selection
  267. if ( 'bulk_delete' === $current_action ) {
  268. foreach ( $members as $record_id ) {
  269. if ( ! is_numeric( $record_id ) ) {
  270. wp_die( 'Error! ID must be numeric.' );
  271. }
  272. self::delete_user_by_id( $record_id );
  273. }
  274. echo '<div id="message" class="updated fade"><p>Selected records deleted successfully!</p></div>';
  275. return;
  276. } elseif ( 'bulk_active' === $current_action ) {
  277. $this->bulk_set_status( $members, 'active' );
  278. } elseif ( 'bulk_active_notify' == $current_action ) {
  279. $this->bulk_set_status( $members, 'active', true );
  280. } elseif ( 'bulk_inactive' == $current_action ) {
  281. $this->bulk_set_status( $members, 'inactive' );
  282. } elseif ( 'bulk_pending' == $current_action ) {
  283. $this->bulk_set_status( $members, 'pending' );
  284. } elseif ( 'bulk_expired' == $current_action ) {
  285. $this->bulk_set_status( $members, 'expired' );
  286. }
  287. echo '<div id="message" class="updated fade"><p>Bulk operation completed successfully!</p></div>';
  288. }
  289. function bulk_set_status( $members, $status, $notify = false ) {
  290. $ids = implode( ',', array_map( 'absint', $members ) );
  291. if ( empty( $ids ) ) {
  292. return;
  293. }
  294. global $wpdb;
  295. $query = 'UPDATE ' . $wpdb->prefix . 'swpm_members_tbl ' .
  296. " SET account_state = '" . $status . "' WHERE member_id in (" . $ids . ')';
  297. $wpdb->query( $query );
  298. if ( $notify ) {
  299. $settings = SwpmSettings::get_instance();
  300. $emails = $wpdb->get_col( 'SELECT email FROM ' . $wpdb->prefix . 'swpm_members_tbl ' . " WHERE member_id IN ( $ids ) " );
  301. $subject = $settings->get_value( 'bulk-activate-notify-mail-subject' );
  302. if ( empty( $subject ) ) {
  303. $subject = 'Account Activated!';
  304. }
  305. $body = $settings->get_value( 'bulk-activate-notify-mail-body' );
  306. if ( empty( $body ) ) {
  307. $body = 'Hi, Your account has been activated successfully!';
  308. }
  309. $from_address = $settings->get_value( 'email-from' );
  310. $headers = 'From: ' . $from_address . "\r\n";
  311. foreach ($emails as $to_email) {
  312. //Send the activation email one by one to all the selected members.
  313. $subject = apply_filters( 'swpm_email_bulk_set_status_subject', $subject );
  314. $body = apply_filters( 'swpm_email_bulk_set_status_body', $body );
  315. $to_email = trim($to_email);
  316. SwpmMiscUtils::mail( $to_email, $subject, $body, $headers );
  317. SwpmLog::log_simple_debug( 'Bulk activation email notification sent. Activation email sent to the following email: ' . $to_email, true );
  318. }
  319. }
  320. }
  321. function delete() {
  322. if ( isset( $_REQUEST['member_id'] ) ) {
  323. //Check we are on the admin end and user has management permission
  324. SwpmMiscUtils::check_user_permission_and_is_admin( 'member deletion by admin' );
  325. //Check nonce
  326. if ( ! isset( $_REQUEST['delete_swpmuser_nonce'] ) || ! wp_verify_nonce( $_REQUEST['delete_swpmuser_nonce'], 'delete_swpmuser_admin_end' ) ) {
  327. //Nonce check failed.
  328. wp_die( SwpmUtils::_( 'Error! Nonce verification failed for user delete from admin end.' ) );
  329. }
  330. $id = sanitize_text_field( $_REQUEST['member_id'] );
  331. $id = absint( $id );
  332. self::delete_user_by_id( $id );
  333. }
  334. }
  335. public static function delete_user_by_id( $id ) {
  336. if ( ! is_numeric( $id ) ) {
  337. wp_die( 'Error! Member ID must be numeric.' );
  338. }
  339. $swpm_user = SwpmMemberUtils::get_user_by_id( $id );
  340. $user_name = $swpm_user->user_name;
  341. self::delete_wp_user( $user_name ); //Deletes the WP User record
  342. self::delete_swpm_user_by_id( $id ); //Deletes the SWPM record
  343. }
  344. public static function delete_swpm_user_by_id( $id ) {
  345. self::delete_user_subs( $id );
  346. global $wpdb;
  347. $query = 'DELETE FROM ' . $wpdb->prefix . "swpm_members_tbl WHERE member_id = $id";
  348. $wpdb->query( $query );
  349. }
  350. public static function delete_wp_user( $user_name ) {
  351. $wp_user_id = username_exists( $user_name );
  352. if ( empty( $wp_user_id ) || ! is_numeric( $wp_user_id ) ) {
  353. return;
  354. }
  355. if ( ! self::is_wp_super_user( $wp_user_id ) ) {
  356. //Not an admin user so it is safe to delete this user.
  357. include_once ABSPATH . 'wp-admin/includes/user.php';
  358. wp_delete_user( $wp_user_id, 1 ); //assigns all related to this user to admin.
  359. } else {
  360. //This is an admin user. So not going to delete the WP User record.
  361. SwpmTransfer::get_instance()->set( 'status', 'For safety, we do not allow deletion of any associated WordPress account with administrator role.' );
  362. return;
  363. }
  364. }
  365. private static function delete_user_subs( $id ) {
  366. $member = SwpmMemberUtils::get_user_by_id( $id );
  367. if ( ! $member ) {
  368. return false;
  369. }
  370. // let's check if Stripe subscription needs to be cancelled
  371. global $wpdb;
  372. $q = $wpdb->prepare(
  373. 'SELECT *
  374. FROM `' . $wpdb->prefix . 'swpm_payments_tbl`
  375. WHERE email = %s
  376. AND (gateway = "stripe" OR gateway = "stripe-sca-subs")
  377. AND subscr_id != ""',
  378. array( $member->email )
  379. );
  380. $res = $wpdb->get_results( $q, ARRAY_A );
  381. if ( ! $res ) {
  382. return false;
  383. }
  384. foreach ( $res as $sub ) {
  385. if ( substr( $sub['subscr_id'], 0, 4 ) !== 'sub_' ) {
  386. //not Stripe subscription
  387. continue;
  388. }
  389. //let's find the payment button
  390. $q = $wpdb->prepare( "SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_key='subscr_id' AND meta_value=%s", $sub['subscr_id'] );
  391. $res_post = $wpdb->get_row( $q );
  392. if ( ! $res_post ) {
  393. //no button found
  394. continue;
  395. }
  396. $button_id = get_post_meta( $res_post->post_id, 'payment_button_id', true );
  397. $button = get_post( $button_id );
  398. if ( ! $button ) {
  399. //no button found
  400. continue;
  401. }
  402. SwpmLog::log_simple_debug( 'Attempting to cancel Stripe Subscription ' . $sub['subscr_id'], true );
  403. $is_live = get_post_meta( $button_id, 'is_live', true );
  404. //API Keys
  405. $api_keys = SwpmMiscUtils::get_stripe_api_keys_from_payment_button( $button_id, $is_live );
  406. //Include the Stripe library.
  407. SwpmMiscUtils::load_stripe_lib();
  408. \Stripe\Stripe::setApiKey( $api_keys['secret'] );
  409. $error = null;
  410. // Let's try to cancel subscription
  411. try {
  412. $sub = \Stripe\Subscription::retrieve( $sub['subscr_id'] );
  413. $sub->cancel();
  414. } catch ( Exception $e ) {
  415. SwpmLog::log_simple_debug( 'Error occurred during Stripe Subscription cancellation. ' . $e->getMessage(), false );
  416. $body = $e->getJsonBody();
  417. $error = $body['error'];
  418. $error_string = wp_json_encode( $error );
  419. SwpmLog::log_simple_debug( 'Error details: ' . $error_string, false );
  420. }
  421. if ( ! isset( $error ) ) {
  422. SwpmLog::log_simple_debug( 'Stripe Subscription has been cancelled.', true );
  423. }
  424. }
  425. }
  426. public static function is_wp_super_user( $wp_user_id ) {
  427. $user_data = get_userdata( $wp_user_id );
  428. if ( empty( $user_data ) ) {
  429. //Not an admin user if we can't find his data for the given ID.
  430. return false;
  431. }
  432. if ( isset( $user_data->wp_capabilities['administrator'] ) ) {//Check capability
  433. //admin user
  434. return true;
  435. }
  436. if ( $user_data->wp_user_level == 10 ) {//Check for old style wp user level
  437. //admin user
  438. return true;
  439. }
  440. //This is not an admin user
  441. return false;
  442. }
  443. function bulk_operation_menu() {
  444. echo '<div id="poststuff"><div id="post-body">';
  445. if ( isset( $_REQUEST['swpm_bulk_change_level_process'] ) ) {
  446. //Check nonce
  447. $swpm_bulk_change_level_nonce = filter_input( INPUT_POST, 'swpm_bulk_change_level_nonce' );
  448. if ( ! wp_verify_nonce( $swpm_bulk_change_level_nonce, 'swpm_bulk_change_level_nonce_action' ) ) {
  449. //Nonce check failed.
  450. wp_die( SwpmUtils::_( 'Error! Nonce security verification failed for Bulk Change Membership Level action. Clear cache and try again.' ) );
  451. }
  452. $errorMsg = '';
  453. $from_level_id = sanitize_text_field( $_REQUEST['swpm_bulk_change_level_from'] );
  454. $to_level_id = sanitize_text_field( $_REQUEST['swpm_bulk_change_level_to'] );
  455. if ( $from_level_id == 'please_select' || $to_level_id == 'please_select' ) {
  456. $errorMsg = SwpmUtils::_( 'Error! Please select a membership level first.' );
  457. }
  458. if ( empty( $errorMsg ) ) {//No validation errors so go ahead
  459. $member_records = SwpmMemberUtils::get_all_members_of_a_level( $from_level_id );
  460. if ( $member_records ) {
  461. foreach ( $member_records as $row ) {
  462. $member_id = $row->member_id;
  463. SwpmMemberUtils::update_membership_level( $member_id, $to_level_id );
  464. }
  465. }
  466. }
  467. $message = '';
  468. if ( ! empty( $errorMsg ) ) {
  469. $message = $errorMsg;
  470. } else {
  471. $message = SwpmUtils::_( 'Membership level change operation completed successfully.' );
  472. }
  473. echo '<div id="message" class="updated fade"><p><strong>';
  474. echo $message;
  475. echo '</strong></p></div>';
  476. }
  477. if ( isset( $_REQUEST['swpm_bulk_user_start_date_change_process'] ) ) {
  478. //Check nonce
  479. $swpm_bulk_start_date_nonce = filter_input( INPUT_POST, 'swpm_bulk_start_date_nonce' );
  480. if ( ! wp_verify_nonce( $swpm_bulk_start_date_nonce, 'swpm_bulk_start_date_nonce_action' ) ) {
  481. //Nonce check failed.
  482. wp_die( SwpmUtils::_( 'Error! Nonce security verification failed for Bulk Change Access Starts Date action. Clear cache and try again.' ) );
  483. }
  484. $errorMsg = '';
  485. $level_id = sanitize_text_field( $_REQUEST['swpm_bulk_user_start_date_change_level'] );
  486. $new_date = sanitize_text_field( $_REQUEST['swpm_bulk_user_start_date_change_date'] );
  487. if ( $level_id == 'please_select' ) {
  488. $errorMsg = SwpmUtils::_( 'Error! Please select a membership level first.' );
  489. }
  490. if ( empty( $errorMsg ) ) {//No validation errors so go ahead
  491. $member_records = SwpmMemberUtils::get_all_members_of_a_level( $level_id );
  492. if ( $member_records ) {
  493. foreach ( $member_records as $row ) {
  494. $member_id = $row->member_id;
  495. SwpmMemberUtils::update_access_starts_date( $member_id, $new_date );
  496. }
  497. }
  498. }
  499. $message = '';
  500. if ( ! empty( $errorMsg ) ) {
  501. $message = $errorMsg;
  502. } else {
  503. $message = SwpmUtils::_( 'Access starts date change operation successfully completed.' );
  504. }
  505. echo '<div id="message" class="updated fade"><p><strong>';
  506. echo $message;
  507. echo '</strong></p></div>';
  508. }
  509. ?>
  510. <div class="postbox">
  511. <h3 class="hndle"><label for="title"><?php SwpmUtils::e( 'Bulk Update Membership Level of Members' ); ?></label></h3>
  512. <div class="inside">
  513. <p>
  514. <?php SwpmUtils::e( 'You can manually change the membership level of any member by editing the record from the members menu. ' ); ?>
  515. <?php SwpmUtils::e( 'You can use the following option to bulk update the membership level of users who belong to the level you select below.' ); ?>
  516. </p>
  517. <form method="post" action="">
  518. <input type="hidden" name="swpm_bulk_change_level_nonce" value="<?php echo wp_create_nonce( 'swpm_bulk_change_level_nonce_action' ); ?>" />
  519. <table width="100%" border="0" cellspacing="0" cellpadding="6">
  520. <tr valign="top">
  521. <td width="25%" align="left">
  522. <strong><?php SwpmUtils::e( 'Membership Level: ' ); ?></strong>
  523. </td>
  524. <td align="left">
  525. <select name="swpm_bulk_change_level_from">
  526. <option value="please_select"><?php SwpmUtils::e( 'Select Current Level' ); ?></option>
  527. <?php echo SwpmUtils::membership_level_dropdown(); ?>
  528. </select>
  529. <p class="description"><?php SwpmUtils::e( 'Select the current membership level (the membership level of all members who are in this level will be updated).' ); ?></p>
  530. </td>
  531. </tr>
  532. <tr valign="top">
  533. <td width="25%" align="left">
  534. <strong><?php SwpmUtils::e( 'Level to Change to: ' ); ?></strong>
  535. </td>
  536. <td align="left">
  537. <select name="swpm_bulk_change_level_to">
  538. <option value="please_select"><?php SwpmUtils::e( 'Select Target Level' ); ?></option>
  539. <?php echo SwpmUtils::membership_level_dropdown(); ?>
  540. </select>
  541. <p class="description"><?php SwpmUtils::e( 'Select the new membership level.' ); ?></p>
  542. </td>
  543. </tr>
  544. <tr valign="top">
  545. <td width="25%" align="left">
  546. <input type="submit" class="button" name="swpm_bulk_change_level_process" value="<?php SwpmUtils::e( 'Bulk Change Membership Level' ); ?>" />
  547. </td>
  548. <td align="left"></td>
  549. </tr>
  550. </table>
  551. </form>
  552. </div></div>
  553. <div class="postbox">
  554. <h3 class="hndle"><label for="title"><?php SwpmUtils::e( 'Bulk Update Access Starts Date of Members' ); ?></label></h3>
  555. <div class="inside">
  556. <p>
  557. <?php SwpmUtils::e( 'The access starts date of a member is set to the day the user registers. This date value is used to calculate how long the member can access your content that are protected with a duration type protection in the membership level. ' ); ?>
  558. <?php SwpmUtils::e( 'You can manually set a specific access starts date value of all members who belong to a particular level using the following option.' ); ?>
  559. </p>
  560. <form method="post" action="">
  561. <input type="hidden" name="swpm_bulk_start_date_nonce" value="<?php echo wp_create_nonce( 'swpm_bulk_start_date_nonce_action' ); ?>" />
  562. <table width="100%" border="0" cellspacing="0" cellpadding="6">
  563. <tr valign="top">
  564. <td width="25%" align="left">
  565. <strong><?php SwpmUtils::e( 'Membership Level: ' ); ?></strong>
  566. </td><td align="left">
  567. <select name="swpm_bulk_user_start_date_change_level">
  568. <option value="please_select"><?php SwpmUtils::e( 'Select Level' ); ?></option>
  569. <?php echo SwpmUtils::membership_level_dropdown(); ?>
  570. </select>
  571. <p class="description"><?php SwpmUtils::e( 'Select the Membership level (the access start date of all members who are in this level will be updated).' ); ?></p>
  572. </td>
  573. </tr>
  574. <tr valign="top">
  575. <td width="25%" align="left">
  576. <strong>Access Starts Date: </strong>
  577. </td><td align="left">
  578. <input name="swpm_bulk_user_start_date_change_date" id="swpm_bulk_user_start_date_change_date" class="swpm-select-date" type="text" size="20" value="<?php echo ( date( 'Y-m-d' ) ); ?>" />
  579. <p class="description"><?php SwpmUtils::e( 'Specify the access starts date value.' ); ?></p>
  580. </td>
  581. </tr>
  582. <tr valign="top">
  583. <td width="25%" align="left">
  584. <input type="submit" class="button" name="swpm_bulk_user_start_date_change_process" value="<?php SwpmUtils::e( 'Bulk Change Access Starts Date' ); ?>" />
  585. </td>
  586. <td align="left"></td>
  587. </tr>
  588. </table>
  589. </form>
  590. </div></div>
  591. <script>
  592. jQuery(document).ready(function ($) {
  593. $('#swpm_bulk_user_start_date_change_date').datepicker({dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true, yearRange: "-100:+100"});
  594. });
  595. </script>
  596. <?php
  597. echo '</div></div>'; //<!-- end of #poststuff #post-body -->
  598. }
  599. function show_all_members() {
  600. ob_start();
  601. $status = filter_input( INPUT_GET, 'status' );
  602. include_once SIMPLE_WP_MEMBERSHIP_PATH . 'views/admin_members_list.php';
  603. $output = ob_get_clean();
  604. return $output;
  605. }
  606. function handle_main_members_admin_menu() {
  607. do_action( 'swpm_members_menu_start' );
  608. //Check current_user_can() or die.
  609. SwpmMiscUtils::check_user_permission_and_is_admin( 'Main Members Admin Menu' );
  610. $action = filter_input( INPUT_GET, 'member_action' );
  611. $action = empty( $action ) ? filter_input( INPUT_POST, 'action' ) : $action;
  612. $selected = $action;
  613. ?>
  614. <div class="wrap swpm-admin-menu-wrap"><!-- start wrap -->
  615. <h1><?php echo SwpmUtils::_( 'Simple WP Membership::Members' ); ?><!-- page title -->
  616. <a href="admin.php?page=simple_wp_membership&member_action=add" class="add-new-h2"><?php echo SwpmUtils::_( 'Add New' ); ?></a>
  617. </h1>
  618. <h2 class="nav-tab-wrapper swpm-members-nav-tab-wrapper"><!-- start nav menu tabs -->
  619. <a class="nav-tab <?php echo ( $selected == '' ) ? 'nav-tab-active' : ''; ?>" href="admin.php?page=simple_wp_membership"><?php echo SwpmUtils::_( 'Members' ); ?></a>
  620. <a class="nav-tab <?php echo ( $selected == 'add' ) ? 'nav-tab-active' : ''; ?>" href="admin.php?page=simple_wp_membership&member_action=add"><?php echo SwpmUtils::_( 'Add Member' ); ?></a>
  621. <a class="nav-tab <?php echo ( $selected == 'bulk' ) ? 'nav-tab-active' : ''; ?>" href="admin.php?page=simple_wp_membership&member_action=bulk"><?php echo SwpmUtils::_( 'Bulk Operation' ); ?></a>
  622. <?php
  623. if ( $selected == 'edit' ) {//Only show the "edit member" tab when a member profile is being edited from the admin side.
  624. echo '<a class="nav-tab nav-tab-active" href="#">Edit Member</a>';
  625. }
  626. //Trigger hooks that allows an extension to add extra nav tabs in the members menu.
  627. do_action( 'swpm_members_menu_nav_tabs', $selected );
  628. $menu_tabs = apply_filters( 'swpm_members_additional_menu_tabs_array', array() );
  629. foreach ( $menu_tabs as $member_action => $title ) {
  630. ?>
  631. <a class="nav-tab <?php echo ( $selected == $member_action ) ? 'nav-tab-active' : ''; ?>" href="admin.php?page=simple_wp_membership&member_action=<?php echo $member_action; ?>" ><?php SwpmUtils::e( $title ); ?></a>
  632. <?php
  633. }
  634. ?>
  635. </h2><!-- end nav menu tabs -->
  636. <?php
  637. do_action( 'swpm_members_menu_after_nav_tabs' );
  638. //Trigger hook so anyone listening for this particular action can handle the output.
  639. do_action( 'swpm_members_menu_body_' . $action );
  640. //Allows an addon to completely override the body section of the members admin menu for a given action.
  641. $output = apply_filters( 'swpm_members_menu_body_override', '', $action );
  642. if ( ! empty( $output ) ) {
  643. //An addon has overriden the body of this page for the given action. So no need to do anything in core.
  644. echo $output;
  645. echo '</div>'; //<!-- end of wrap -->
  646. return;
  647. }
  648. //Switch case for the various different actions handled by the core plugin.
  649. switch ( $action ) {
  650. case 'members_list':
  651. //Show the members listing
  652. echo $this->show_all_members();
  653. break;
  654. case 'add':
  655. //Process member profile add
  656. $this->process_form_request();
  657. break;
  658. case 'edit':
  659. //Process member profile edit
  660. $this->process_form_request();
  661. break;
  662. case 'bulk':
  663. //Handle the bulk operation menu
  664. $this->bulk_operation_menu();
  665. break;
  666. default:
  667. //Show the members listing page by default.
  668. echo $this->show_all_members();
  669. break;
  670. }
  671. echo '</div>'; //<!-- end of wrap -->
  672. }
  673. }