/bp-members/classes/class-bp-members-admin.php

  1. <?php 
  2. /** 
  3. * BuddyPress Members Admin 
  4. * 
  5. * @package BuddyPress 
  6. * @subpackage MembersAdmin 
  7. * @since 2.0.0 
  8. */ 
  9.  
  10. // Exit if accessed directly. 
  11. defined( 'ABSPATH' ) || exit; 
  12.  
  13. if ( !class_exists( 'BP_Members_Admin' ) ) : 
  14.  
  15. /** 
  16. * Load Members admin area. 
  17. * 
  18. * @since 2.0.0 
  19. */ 
  20. class BP_Members_Admin { 
  21.  
  22. /** Directory *************************************************************/ 
  23.  
  24. /** 
  25. * Path to the BP Members Admin directory. 
  26. * 
  27. * @var string $admin_dir 
  28. */ 
  29. public $admin_dir = ''; 
  30.  
  31. /** URLs ******************************************************************/ 
  32.  
  33. /** 
  34. * URL to the BP Members Admin directory. 
  35. * 
  36. * @var string $admin_url 
  37. */ 
  38. public $admin_url = ''; 
  39.  
  40. /** 
  41. * URL to the BP Members Admin CSS directory. 
  42. * 
  43. * @var string $css_url 
  44. */ 
  45. public $css_url = ''; 
  46.  
  47. /** 
  48. * URL to the BP Members Admin JS directory. 
  49. * 
  50. * @var string 
  51. */ 
  52. public $js_url = ''; 
  53.  
  54. /** Other *****************************************************************/ 
  55.  
  56. /** 
  57. * Screen id for edit user's profile page. 
  58. * 
  59. * @var string 
  60. */ 
  61. public $user_page = ''; 
  62.  
  63. /** 
  64. * Setup BP Members Admin. 
  65. * 
  66. * @since 2.0.0 
  67. * 
  68. */ 
  69. public static function register_members_admin() { 
  70. if ( ! is_admin() ) { 
  71. return; 
  72.  
  73. $bp = buddypress(); 
  74.  
  75. if ( empty( $bp->members->admin ) ) { 
  76. $bp->members->admin = new self; 
  77.  
  78. return $bp->members->admin; 
  79.  
  80. /** 
  81. * Constructor method. 
  82. * 
  83. * @since 2.0.0 
  84. */ 
  85. public function __construct() { 
  86. $this->setup_globals(); 
  87. $this->setup_actions(); 
  88.  
  89. /** 
  90. * Set admin-related globals. 
  91. * 
  92. * @since 2.0.0 
  93. */ 
  94. private function setup_globals() { 
  95. $bp = buddypress(); 
  96.  
  97. // Paths and URLs 
  98. $this->admin_dir = trailingslashit( $bp->plugin_dir . 'bp-members/admin' ); // Admin path. 
  99. $this->admin_url = trailingslashit( $bp->plugin_url . 'bp-members/admin' ); // Admin URL. 
  100. $this->css_url = trailingslashit( $this->admin_url . 'css' ); // Admin CSS URL. 
  101. $this->js_url = trailingslashit( $this->admin_url . 'js' ); // Admin CSS URL. 
  102.  
  103. // Capability depends on config. 
  104. $this->capability = bp_core_do_network_admin() ? 'manage_network_users' : 'edit_users'; 
  105.  
  106. // The Edit Profile Screen id. 
  107. $this->user_page = ''; 
  108.  
  109. // The Show Profile Screen id. 
  110. $this->user_profile = is_network_admin() ? 'users' : 'profile'; 
  111.  
  112. // The current user id. 
  113. $this->current_user_id = get_current_user_id(); 
  114.  
  115. // The user id being edited. 
  116. $this->user_id = 0; 
  117.  
  118. // Is a member editing their own profile. 
  119. $this->is_self_profile = false; 
  120.  
  121. // The screen ids to load specific css for. 
  122. $this->screen_id = array(); 
  123.  
  124. // The stats metabox default position. 
  125. $this->stats_metabox = new StdClass(); 
  126.  
  127. // BuddyPress edit user's profile args. 
  128. $this->edit_profile_args = array( 'page' => 'bp-profile-edit' ); 
  129. $this->edit_profile_url = ''; 
  130. $this->edit_url = ''; 
  131.  
  132. // Data specific to signups. 
  133. $this->users_page = ''; 
  134. $this->signups_page = ''; 
  135. $this->users_url = bp_get_admin_url( 'users.php' ); 
  136. $this->users_screen = bp_core_do_network_admin() ? 'users-network' : 'users'; 
  137.  
  138. // Specific config: BuddyPress is not network activated. 
  139. $this->subsite_activated = (bool) is_multisite() && ! bp_is_network_activated(); 
  140.  
  141. // When BuddyPress is not network activated, only Super Admin can moderate signups. 
  142. if ( ! empty( $this->subsite_activated ) ) { 
  143. $this->capability = 'manage_network_users'; 
  144.  
  145. /** 
  146. * Set admin-related actions and filters. 
  147. * 
  148. * @since 2.0.0 
  149. */ 
  150. private function setup_actions() { 
  151.  
  152. /** Extended Profile ************************************************* 
  153. */ 
  154.  
  155. // Enqueue all admin JS and CSS. 
  156. add_action( 'bp_admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); 
  157.  
  158. // Add some page specific output to the <head>. 
  159. add_action( 'bp_admin_head', array( $this, 'admin_head' ), 999 ); 
  160.  
  161. // Add menu item to all users menu. 
  162. add_action( 'admin_menu', array( $this, 'admin_menus' ), 5 ); 
  163. add_action( 'network_admin_menu', array( $this, 'admin_menus' ), 5 ); 
  164. add_action( 'user_admin_menu', array( $this, 'user_profile_menu' ), 5 ); 
  165.  
  166. // Create the Profile Navigation (Profile/Extended Profile). 
  167. add_action( 'edit_user_profile', array( $this, 'profile_nav' ), 99, 1 ); 
  168. add_action( 'show_user_profile', array( $this, 'profile_nav' ), 99, 1 ); 
  169.  
  170. // Editing users of a specific site. 
  171. add_action( "admin_head-site-users.php", array( $this, 'profile_admin_head' ) ); 
  172.  
  173. // Add a row action to users listing. 
  174. if ( bp_core_do_network_admin() ) { 
  175. add_filter( 'ms_user_row_actions', array( $this, 'row_actions' ), 10, 2 ); 
  176. add_action( 'admin_init', array( $this, 'add_edit_profile_url_filter' ) ); 
  177. add_action( 'wp_after_admin_bar_render', array( $this, 'remove_edit_profile_url_filter' ) ); 
  178.  
  179. // Add user row actions for single site. 
  180. add_filter( 'user_row_actions', array( $this, 'row_actions' ), 10, 2 ); 
  181.  
  182. // Process changes to member type. 
  183. add_action( 'bp_members_admin_load', array( $this, 'process_member_type_update' ) ); 
  184.  
  185. /** Signups ********************************************************** 
  186. */ 
  187.  
  188. if ( is_admin() ) { 
  189.  
  190. // Filter non multisite user query to remove sign-up users. 
  191. if ( ! is_multisite() ) { 
  192. add_action( 'pre_user_query', array( $this, 'remove_signups_from_user_query' ), 10, 1 ); 
  193.  
  194. // Reorganise the views navigation in users.php and signups page. 
  195. if ( current_user_can( $this->capability ) ) { 
  196. $user_screen = $this->users_screen; 
  197.  
  198. /** 
  199. * Users screen on multiblog is users, but signups 
  200. * need to be managed in the network for this case 
  201. */ 
  202. if ( bp_is_network_activated() && bp_is_multiblog_mode() && false === strpos( $user_screen, '-network' ) ) { 
  203. $user_screen .= '-network'; 
  204.  
  205. add_filter( "views_{$user_screen}", array( $this, 'signup_filter_view' ), 10, 1 ); 
  206. add_filter( 'set-screen-option', array( $this, 'signup_screen_options' ), 10, 3 ); 
  207.  
  208. // Registration is turned on. 
  209. add_action( 'update_site_option_registration', array( $this, 'multisite_registration_on' ), 10, 2 ); 
  210. add_action( 'update_option_users_can_register', array( $this, 'single_site_registration_on' ), 10, 2 ); 
  211.  
  212. /** Users List - Members Types *************************************** 
  213. */ 
  214.  
  215. if ( is_admin() && bp_get_member_types() ) { 
  216.  
  217. // Add "Change type" <select> to WP admin users list table and process bulk members type changes. 
  218. add_action( 'restrict_manage_users', array( $this, 'users_table_output_type_change_select' ) ); 
  219. add_action( 'load-users.php', array( $this, 'users_table_process_bulk_type_change' ) ); 
  220.  
  221. // Add the member type column to the WP admin users list table. 
  222. add_filter( 'manage_users_columns', array( $this, 'users_table_add_type_column' ) ); 
  223. add_filter( 'manage_users_custom_column', array( $this, 'users_table_populate_type_cell' ), 10, 3 ); 
  224.  
  225. // Filter WP admin users list table to include users of the specified type. 
  226. add_filter( 'pre_get_users', array( $this, 'users_table_filter_by_type' ) ); 
  227.  
  228. /** 
  229. * Create registration pages when multisite user registration is turned on. 
  230. * 
  231. * @since 2.7.0 
  232. * 
  233. * @param string $option_name Current option name; value is always 'registration'. 
  234. * @param string $value 
  235. */ 
  236. public function multisite_registration_on( $option_name, $value ) { 
  237. if ( 'user' === $value || 'all' === $value ) { 
  238. bp_core_add_page_mappings( array( 
  239. 'register' => 1,  
  240. 'activate' => 1 
  241. ) ); 
  242.  
  243. /** 
  244. * Create registration pages when single site registration is turned on. 
  245. * 
  246. * @since 2.7.0 
  247. * 
  248. * @param string $old_value 
  249. * @param string $value 
  250. */ 
  251. public function single_site_registration_on( $old_value, $value ) { 
  252. // Single site. 
  253. if ( ! is_multisite() && ! empty( $value ) ) { 
  254. bp_core_add_page_mappings( array( 
  255. 'register' => 1,  
  256. 'activate' => 1 
  257. ) ); 
  258.  
  259. /** 
  260. * Get the user ID. 
  261. * 
  262. * Look for $_GET['user_id']. If anything else, force the user ID to the 
  263. * current user's ID so they aren't left without a user to edit. 
  264. * 
  265. * @since 2.1.0 
  266. * 
  267. * @return int 
  268. */ 
  269. private function get_user_id() { 
  270. if ( ! empty( $this->user_id ) ) { 
  271. return $this->user_id; 
  272.  
  273. $this->user_id = (int) get_current_user_id(); 
  274.  
  275. // We'll need a user ID when not on self profile. 
  276. if ( ! empty( $_GET['user_id'] ) ) { 
  277. $this->user_id = (int) $_GET['user_id']; 
  278.  
  279. return $this->user_id; 
  280.  
  281. /** 
  282. * Can the current user edit the one displayed. 
  283. * 
  284. * Self profile editing / or bp_moderate check. 
  285. * This might be replaced by more granular capabilities 
  286. * in the future. 
  287. * 
  288. * @since 2.1.0 
  289. * 
  290. * @param int $user_id ID of the user being checked for edit ability. 
  291. * 
  292. * @return bool 
  293. */ 
  294. private function member_can_edit( $user_id = 0 ) { 
  295. $retval = false; 
  296.  
  297. // Bail if no user ID was passed. 
  298. if ( empty( $user_id ) ) { 
  299. return $retval; 
  300.  
  301. // Member can edit if they are viewing their own profile. 
  302. if ( $this->current_user_id === $user_id ) { 
  303. $retval = true; 
  304.  
  305. // Trust the 'bp_moderate' capability. 
  306. } else { 
  307. $retval = bp_current_user_can( 'bp_moderate' ); 
  308.  
  309. return $retval; 
  310.  
  311. /** 
  312. * Get admin notice when saving a user or member profile. 
  313. * 
  314. * @since 2.1.0 
  315. * 
  316. * @return array 
  317. */ 
  318. private function get_user_notice() { 
  319.  
  320. // Setup empty notice for return value. 
  321. $notice = array(); 
  322.  
  323. // Updates. 
  324. if ( ! empty( $_REQUEST['updated'] ) ) { 
  325. switch ( $_REQUEST['updated'] ) { 
  326. case 'avatar': 
  327. $notice = array( 
  328. 'class' => 'updated',  
  329. 'message' => __( 'Profile photo was deleted.', 'buddypress' ) 
  330. ); 
  331. break; 
  332. case 'ham' : 
  333. $notice = array( 
  334. 'class' => 'updated',  
  335. 'message' => __( 'User removed as spammer.', 'buddypress' ) 
  336. ); 
  337. break; 
  338. case 'spam' : 
  339. $notice = array( 
  340. 'class' => 'updated',  
  341. 'message' => __( 'User marked as spammer. Spam users are visible only to site admins.', 'buddypress' ) 
  342. ); 
  343. break; 
  344. case 1 : 
  345. $notice = array( 
  346. 'class' => 'updated',  
  347. 'message' => __( 'Profile updated.', 'buddypress' ) 
  348. ); 
  349. break; 
  350.  
  351. // Errors. 
  352. if ( ! empty( $_REQUEST['error'] ) ) { 
  353. switch ( $_REQUEST['error'] ) { 
  354. case 'avatar': 
  355. $notice = array( 
  356. 'class' => 'error',  
  357. 'message' => __( 'There was a problem deleting that profile photo. Please try again.', 'buddypress' ) 
  358. ); 
  359. break; 
  360. case 'ham' : 
  361. $notice = array( 
  362. 'class' => 'error',  
  363. 'message' => __( 'User could not be removed as spammer.', 'buddypress' ) 
  364. ); 
  365. break; 
  366. case 'spam' : 
  367. $notice = array( 
  368. 'class' => 'error',  
  369. 'message' => __( 'User could not be marked as spammer.', 'buddypress' ) 
  370. ); 
  371. break; 
  372. case 1 : 
  373. $notice = array( 
  374. 'class' => 'error',  
  375. 'message' => __( 'An error occurred while trying to update the profile.', 'buddypress' ) 
  376. ); 
  377. break; 
  378. case 2: 
  379. $notice = array( 
  380. 'class' => 'error',  
  381. 'message' => __( 'Please make sure you fill in all required fields in this profile field group before saving.', 'buddypress' ) 
  382. ); 
  383. break; 
  384. case 3: 
  385. $notice = array( 
  386. 'class' => 'error',  
  387. 'message' => __( 'There was a problem updating some of your profile information. Please try again.', 'buddypress' ) 
  388. ); 
  389. break; 
  390.  
  391. return $notice; 
  392.  
  393. /** 
  394. * Create the /user/ admin Profile submenus for all members. 
  395. * 
  396. * @since 2.1.0 
  397. * 
  398. */ 
  399. public function user_profile_menu() { 
  400.  
  401. // Setup the hooks array. 
  402. $hooks = array(); 
  403.  
  404. // Add the faux "Edit Profile" submenu page. 
  405. $hooks['user'] = $this->user_page = add_submenu_page( 
  406. 'profile.php',  
  407. __( 'Edit Profile', 'buddypress' ),  
  408. __( 'Edit Profile', 'buddypress' ),  
  409. 'exist',  
  410. 'bp-profile-edit',  
  411. array( $this, 'user_admin' ) 
  412. ); 
  413.  
  414. // Setup the screen ID's. 
  415. $this->screen_id = array( 
  416. $this->user_page . '-user',  
  417. $this->user_profile . '-user' 
  418. ); 
  419.  
  420. // Loop through new hooks and add method actions. 
  421. foreach ( $hooks as $key => $hook ) { 
  422. add_action( "load-{$hook}", array( $this, $key . '_admin_load' ) ); 
  423.  
  424. // Add the profile_admin_head method to proper admin_head actions. 
  425. add_action( "admin_head-{$this->user_page}", array( $this, 'profile_admin_head' ) ); 
  426. add_action( "admin_head-profile.php", array( $this, 'profile_admin_head' ) ); 
  427.  
  428. /** 
  429. * Create the All Users / Profile > Edit Profile and All Users Signups submenus. 
  430. * 
  431. * @since 2.0.0 
  432. * 
  433. */ 
  434. public function admin_menus() { 
  435.  
  436. // Setup the hooks array. 
  437. $hooks = array(); 
  438.  
  439. // Manage user's profile. 
  440. $hooks['user'] = $this->user_page = add_submenu_page( 
  441. $this->user_profile . '.php',  
  442. __( 'Edit Profile', 'buddypress' ),  
  443. __( 'Edit Profile', 'buddypress' ),  
  444. 'read',  
  445. 'bp-profile-edit',  
  446. array( $this, 'user_admin' ) 
  447. ); 
  448.  
  449. // Only show sign-ups where they belong. 
  450. if ( ( ! bp_is_network_activated() && ! is_network_admin() ) || ( is_network_admin() && bp_is_network_activated() ) ) { 
  451.  
  452. // Manage signups. 
  453. $hooks['signups'] = $this->signups_page = add_users_page( 
  454. __( 'Manage Signups', 'buddypress' ),  
  455. __( 'Manage Signups', 'buddypress' ),  
  456. $this->capability,  
  457. 'bp-signups',  
  458. array( $this, 'signups_admin' ) 
  459. ); 
  460.  
  461. $edit_page = 'user-edit'; 
  462. $profile_page = 'profile'; 
  463. $this->users_page = 'users'; 
  464.  
  465. // Self profile check is needed for this pages. 
  466. $page_head = array( 
  467. $edit_page . '.php',  
  468. $profile_page . '.php',  
  469. $this->user_page,  
  470. $this->users_page . '.php',  
  471. ); 
  472.  
  473. // Append '-network' to each array item if in network admin. 
  474. if ( is_network_admin() ) { 
  475. $edit_page .= '-network'; 
  476. $profile_page .= '-network'; 
  477. $this->user_page .= '-network'; 
  478. $this->users_page .= '-network'; 
  479. $this->signups_page .= '-network'; 
  480.  
  481. // Setup the screen ID's. 
  482. $this->screen_id = array( 
  483. $edit_page,  
  484. $this->user_page,  
  485. $profile_page 
  486. ); 
  487.  
  488. // Loop through new hooks and add method actions. 
  489. foreach ( $hooks as $key => $hook ) { 
  490. add_action( "load-{$hook}", array( $this, $key . '_admin_load' ) ); 
  491.  
  492. // Add the profile_admin_head method to proper admin_head actions. 
  493. foreach ( $page_head as $head ) { 
  494. add_action( "admin_head-{$head}", array( $this, 'profile_admin_head' ) ); 
  495.  
  496. /** 
  497. * Highlight the Users menu if on Edit Profile and check if on the user's admin profile. 
  498. * 
  499. * @since 2.1.0 
  500. */ 
  501. public function profile_admin_head() { 
  502. global $submenu_file, $parent_file; 
  503.  
  504. // Is the user editing their own profile? 
  505. if ( is_user_admin() || ( defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) ) { 
  506. $this->is_self_profile = true; 
  507.  
  508. // Is the user attempting to edit their own profile. 
  509. } elseif ( isset( $_GET['user_id' ] ) || ( isset( $_GET['page'] ) && ( 'bp-profile-edit' === $_GET['page'] ) ) ) { 
  510. $this->is_self_profile = (bool) ( $this->get_user_id() === $this->current_user_id ); 
  511.  
  512. // Force the parent file to users.php to open the correct top level menu 
  513. // but only if not editing a site via the network site editing page. 
  514. if ( 'sites.php' !== $parent_file ) { 
  515. $parent_file = 'users.php'; 
  516. $submenu_file = 'users.php'; 
  517.  
  518. // Editing your own profile, so recheck some vars. 
  519. if ( true === $this->is_self_profile ) { 
  520.  
  521. // Use profile.php as the edit page. 
  522. $edit_page = 'profile.php'; 
  523.  
  524. // Set profile.php as the parent & sub files to correct the menu nav. 
  525. if ( is_blog_admin() || is_user_admin() ) { 
  526. $parent_file = 'profile.php'; 
  527. $submenu_file = 'profile.php'; 
  528.  
  529. // Not editing yourself, so use user-edit.php. 
  530. } else { 
  531. $edit_page = 'user-edit.php'; 
  532.  
  533. if ( is_user_admin() ) { 
  534. $this->edit_profile_url = add_query_arg( $this->edit_profile_args, user_admin_url( 'profile.php' ) ); 
  535. $this->edit_url = user_admin_url( 'profile.php' ); 
  536.  
  537. } elseif ( is_blog_admin() ) { 
  538. $this->edit_profile_url = add_query_arg( $this->edit_profile_args, admin_url( 'users.php' ) ); 
  539. $this->edit_url = admin_url( $edit_page ); 
  540.  
  541. } elseif ( is_network_admin() ) { 
  542. $this->edit_profile_url = add_query_arg( $this->edit_profile_args, network_admin_url( 'users.php' ) ); 
  543. $this->edit_url = network_admin_url( $edit_page ); 
  544.  
  545. /** 
  546. * Remove the Edit Profile page. 
  547. * 
  548. * We add these pages in order to integrate with WP's Users panel, but 
  549. * we want them to show up as a row action of the WP panel, not as separate 
  550. * subnav items under the Users menu. 
  551. * 
  552. * @since 2.0.0 
  553. */ 
  554. public function admin_head() { 
  555. remove_submenu_page( 'users.php', 'bp-profile-edit' ); 
  556. remove_submenu_page( 'profile.php', 'bp-profile-edit' ); 
  557.  
  558. /** Community Profile *****************************************************/ 
  559.  
  560. /** 
  561. * Add some specific styling to the Edit User and Edit User's Profile page. 
  562. * 
  563. * @since 2.0.0 
  564. */ 
  565. public function enqueue_scripts() { 
  566. if ( ! in_array( get_current_screen()->id, $this->screen_id ) ) { 
  567. return; 
  568.  
  569. $min = bp_core_get_minified_asset_suffix(); 
  570. $css = $this->css_url . "admin{$min}.css"; 
  571.  
  572. /** 
  573. * Filters the CSS URL to enqueue in the Members admin area. 
  574. * 
  575. * @since 2.0.0 
  576. * 
  577. * @param string $css URL to the CSS admin file to load. 
  578. */ 
  579. $css = apply_filters( 'bp_members_admin_css', $css ); 
  580.  
  581. wp_enqueue_style( 'bp-members-css', $css, array(), bp_get_version() ); 
  582.  
  583. wp_style_add_data( 'bp-members-css', 'rtl', true ); 
  584. if ( $min ) { 
  585. wp_style_add_data( 'bp-members-css', 'suffix', $min ); 
  586.  
  587. // Only load JavaScript for BuddyPress profile. 
  588. if ( get_current_screen()->id == $this->user_page ) { 
  589. $js = $this->js_url . "admin{$min}.js"; 
  590.  
  591. /** 
  592. * Filters the JS URL to enqueue in the Members admin area. 
  593. * 
  594. * @since 2.0.0 
  595. * 
  596. * @param string $js URL to the JavaScript admin file to load. 
  597. */ 
  598. $js = apply_filters( 'bp_members_admin_js', $js ); 
  599. wp_enqueue_script( 'bp-members-js', $js, array( 'jquery' ), bp_get_version(), true ); 
  600.  
  601. /** 
  602. * Fires after all of the members JavaScript and CSS are enqueued. 
  603. * 
  604. * @since 2.0.0 
  605. * 
  606. * @param string $id ID of the current screen. 
  607. * @param array $screen_id Array of allowed screens to add scripts and styles to. 
  608. */ 
  609. do_action( 'bp_members_admin_enqueue_scripts', get_current_screen()->id, $this->screen_id ); 
  610.  
  611. /** 
  612. * Create the Profile navigation in Edit User & Edit Profile pages. 
  613. * 
  614. * @since 2.0.0 
  615. * 
  616. * @param object|null $user User to create profile navigation for. 
  617. * @param string $active Which profile to highlight. 
  618. * @return string 
  619. */ 
  620. public function profile_nav( $user = null, $active = 'WordPress' ) { 
  621.  
  622. // Bail if no user ID exists here. 
  623. if ( empty( $user->ID ) ) { 
  624. return; 
  625.  
  626. // Add the user ID to query arguments when not editing yourself. 
  627. if ( false === $this->is_self_profile ) { 
  628. $query_args = array( 'user_id' => $user->ID ); 
  629. } else { 
  630. $query_args = array(); 
  631.  
  632. // Conditionally add a referer if it exists in the existing request. 
  633. if ( ! empty( $_REQUEST['wp_http_referer'] ) ) { 
  634. $query_args['wp_http_referer'] = urlencode( stripslashes_deep( $_REQUEST['wp_http_referer'] ) ); 
  635.  
  636. // Setup the two distinct "edit" URL's. 
  637. $community_url = add_query_arg( $query_args, $this->edit_profile_url ); 
  638. $wordpress_url = add_query_arg( $query_args, $this->edit_url ); 
  639.  
  640. $bp_active = false; 
  641. $wp_active = ' nav-tab-active'; 
  642. if ( 'BuddyPress' === $active ) { 
  643. $bp_active = ' nav-tab-active'; 
  644. $wp_active = false; 
  645. } ?> 
  646.  
  647. <h2 id="profile-nav" class="nav-tab-wrapper"> 
  648. <?php 
  649. /** 
  650. * In configs where BuddyPress is not network activated, as regular 
  651. * admins do not have the capacity to edit other users, we must add 
  652. * this check. 
  653. */ 
  654. if ( current_user_can( 'edit_user', $user->ID ) ) : ?> 
  655.  
  656. <a class="nav-tab<?php echo esc_attr( $wp_active ); ?>" href="<?php echo esc_url( $wordpress_url );?>"><?php _e( 'Profile', 'buddypress' ); ?></a> 
  657.  
  658. <?php endif; ?> 
  659.  
  660. <a class="nav-tab<?php echo esc_attr( $bp_active ); ?>" href="<?php echo esc_url( $community_url );?>"><?php _e( 'Extended Profile', 'buddypress' ); ?></a> 
  661. </h2> 
  662.  
  663. <?php 
  664.  
  665. /** 
  666. * Set up the user's profile admin page. 
  667. * 
  668. * Loaded before the page is rendered, this function does all initial 
  669. * setup, including: processing form requests, registering contextual 
  670. * help, and setting up screen options. 
  671. * 
  672. * @since 2.0.0 
  673. */ 
  674. public function user_admin_load() { 
  675.  
  676. // Get the user ID. 
  677. $user_id = $this->get_user_id(); 
  678.  
  679. // Can current user edit this profile? 
  680. if ( ! $this->member_can_edit( $user_id ) ) { 
  681. wp_die( __( 'You cannot edit the requested user.', 'buddypress' ) ); 
  682.  
  683. // Build redirection URL. 
  684. $redirect_to = remove_query_arg( array( 'action', 'error', 'updated', 'spam', 'ham', 'delete_avatar' ), $_SERVER['REQUEST_URI'] ); 
  685. $doaction = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : false; 
  686.  
  687. if ( ! empty( $_REQUEST['user_status'] ) ) { 
  688. $spam = (bool) ( 'spam' === $_REQUEST['user_status'] ); 
  689.  
  690. if ( $spam !== bp_is_user_spammer( $user_id ) ) { 
  691. $doaction = $_REQUEST['user_status']; 
  692.  
  693. /** 
  694. * Fires at the start of the signups admin load. 
  695. * 
  696. * @since 2.0.0 
  697. * 
  698. * @param string $doaction Current bulk action being processed. 
  699. * @param array $_REQUEST Current $_REQUEST global. 
  700. */ 
  701. do_action_ref_array( 'bp_members_admin_load', array( $doaction, $_REQUEST ) ); 
  702.  
  703. /** 
  704. * Filters the allowed actions for use in the user admin page. 
  705. * 
  706. * @since 2.0.0 
  707. * 
  708. * @param array $value Array of allowed actions to use. 
  709. */ 
  710. $allowed_actions = apply_filters( 'bp_members_admin_allowed_actions', array( 'update', 'delete_avatar', 'spam', 'ham' ) ); 
  711.  
  712. // Prepare the display of the Community Profile screen. 
  713. if ( ! in_array( $doaction, $allowed_actions ) ) { 
  714. add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) ); 
  715.  
  716. get_current_screen()->add_help_tab( array( 
  717. 'id' => 'bp-profile-edit-overview',  
  718. 'title' => __( 'Overview', 'buddypress' ),  
  719. 'content' => 
  720. '<p>' . __( 'This is the admin view of a user's profile.', 'buddypress' ) . '</p>' . 
  721. '<p>' . __( 'In the main column, you can edit the fields of the user's extended profile.', 'buddypress' ) . '</p>' . 
  722. '<p>' . __( 'In the right-hand column, you can update the user's status, delete the user's avatar, and view recent statistics.', 'buddypress' ) . '</p>' 
  723. ) ); 
  724.  
  725. // Help panel - sidebar links. 
  726. get_current_screen()->set_help_sidebar( 
  727. '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 
  728. '<p>' . __( '<a href="https://codex.buddypress.org/administrator-guide/extended-profiles/">Managing Profiles</a>', 'buddypress' ) . '</p>' . 
  729. '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 
  730. ); 
  731.  
  732. // Register metaboxes for the edit screen. 
  733. add_meta_box( 
  734. 'submitdiv',  
  735. _x( 'Status', 'members user-admin edit screen', 'buddypress' ),  
  736. array( $this, 'user_admin_status_metabox' ),  
  737. get_current_screen()->id,  
  738. 'side',  
  739. 'core' 
  740. ); 
  741.  
  742. // In case xprofile is not active. 
  743. $this->stats_metabox->context = 'normal'; 
  744. $this->stats_metabox->priority = 'core'; 
  745.  
  746. /** 
  747. * Fires before loading the profile fields if component is active. 
  748. * 
  749. * Plugins should not use this hook, please use 'bp_members_admin_user_metaboxes' instead. 
  750. * 
  751. * @since 2.0.0 
  752. * 
  753. * @param int $user_id Current user ID for the screen. 
  754. * @param string $id Current screen ID. 
  755. * @param object $stats_metabox Object holding position data for use with the stats metabox. 
  756. */ 
  757. do_action_ref_array( 'bp_members_admin_xprofile_metabox', array( $user_id, get_current_screen()->id, $this->stats_metabox ) ); 
  758.  
  759. // If xProfile is inactive, difficult to know what's profile we're on. 
  760. if ( 'normal' === $this->stats_metabox->context ) { 
  761. $display_name = bp_core_get_user_displayname( $user_id ); 
  762. } else { 
  763. $display_name = __( 'Member', 'buddypress' ); 
  764.  
  765. // User Stat metabox. 
  766. add_meta_box( 
  767. 'bp_members_admin_user_stats',  
  768. sprintf( _x( "%s's Stats", 'members user-admin edit screen', 'buddypress' ), $display_name ),  
  769. array( $this, 'user_admin_stats_metabox' ),  
  770. get_current_screen()->id,  
  771. sanitize_key( $this->stats_metabox->context ),  
  772. sanitize_key( $this->stats_metabox->priority ) 
  773. ); 
  774.  
  775. // Member Type metabox. Only added if member types have been registered. 
  776. $member_types = bp_get_member_types(); 
  777. if ( ! empty( $member_types ) ) { 
  778. add_meta_box( 
  779. 'bp_members_admin_member_type',  
  780. _x( 'Member Type', 'members user-admin edit screen', 'buddypress' ),  
  781. array( $this, 'user_admin_member_type_metabox' ),  
  782. get_current_screen()->id,  
  783. 'side',  
  784. 'core' 
  785. ); 
  786.  
  787. /** 
  788. * Fires at the end of the Community Profile screen. 
  789. * 
  790. * Plugins can restrict metabox to "bp_moderate" admins by checking if 
  791. * the first argument ($this->is_self_profile) is false in their callback. 
  792. * They can also restrict their metabox to self profile editing 
  793. * by setting it to true. 
  794. * 
  795. * @since 2.0.0 
  796. * 
  797. * @param bool $is_self_profile Whether or not it is the current user's profile. 
  798. * @param int $user_id Current user ID. 
  799. */ 
  800. do_action( 'bp_members_admin_user_metaboxes', $this->is_self_profile, $user_id ); 
  801.  
  802. // Enqueue JavaScript files. 
  803. wp_enqueue_script( 'postbox' ); 
  804. wp_enqueue_script( 'dashboard' ); 
  805.  
  806. // Spam or Ham user. 
  807. } elseif ( in_array( $doaction, array( 'spam', 'ham' ) ) && empty( $this->is_self_profile ) ) { 
  808.  
  809. check_admin_referer( 'edit-bp-profile_' . $user_id ); 
  810.  
  811. if ( bp_core_process_spammer_status( $user_id, $doaction ) ) { 
  812. $redirect_to = add_query_arg( 'updated', $doaction, $redirect_to ); 
  813. } else { 
  814. $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 
  815.  
  816. bp_core_redirect( $redirect_to ); 
  817.  
  818. // Update other stuff once above ones are done. 
  819. } else { 
  820. $this->redirect = $redirect_to; 
  821.  
  822. /** 
  823. * Fires at end of user profile admin load if doaction does not match any available actions. 
  824. * 
  825. * @since 2.0.0 
  826. * 
  827. * @param string $doaction Current bulk action being processed. 
  828. * @param int $user_id Current user ID. 
  829. * @param array $_REQUEST Current $_REQUEST global. 
  830. * @param string $redirect Determined redirect url to send user to. 
  831. */ 
  832. do_action_ref_array( 'bp_members_admin_update_user', array( $doaction, $user_id, $_REQUEST, $this->redirect ) ); 
  833.  
  834. bp_core_redirect( $this->redirect ); 
  835.  
  836. /** 
  837. * Display the user's profile. 
  838. * 
  839. * @since 2.0.0 
  840. */ 
  841. public function user_admin() { 
  842.  
  843. if ( ! bp_current_user_can( 'bp_moderate' ) && empty( $this->is_self_profile ) ) { 
  844. die( '-1' ); 
  845.  
  846. // Get the user ID. 
  847. $user_id = $this->get_user_id(); 
  848. $user = get_user_to_edit( $user_id ); 
  849.  
  850. // Construct title. 
  851. if ( true === $this->is_self_profile ) { 
  852. $title = __( 'Profile', 'buddypress' ); 
  853. } else { 
  854. $title = __( 'Edit User', 'buddypress' ); 
  855.  
  856. // Construct URL for form. 
  857. $request_url = remove_query_arg( array( 'action', 'error', 'updated', 'spam', 'ham' ), $_SERVER['REQUEST_URI'] ); 
  858. $form_action_url = add_query_arg( 'action', 'update', $request_url ); 
  859. $wp_http_referer = false; 
  860. if ( ! empty( $_REQUEST['wp_http_referer'] ) ) { 
  861. $wp_http_referer = remove_query_arg( array( 'action', 'updated' ), $_REQUEST['wp_http_referer'] ); 
  862.  
  863. // Prepare notice for admin. 
  864. $notice = $this->get_user_notice(); 
  865.  
  866. if ( ! empty( $notice ) ) : ?> 
  867.  
  868. <div <?php if ( 'updated' === $notice['class'] ) : ?>id="message" <?php endif; ?>class="<?php echo esc_attr( $notice['class'] ); ?>"> 
  869.  
  870. <p><?php echo esc_html( $notice['message'] ); ?></p> 
  871.  
  872. <?php if ( !empty( $wp_http_referer ) && ( 'updated' === $notice['class'] ) ) : ?> 
  873.  
  874. <p><a href="<?php echo esc_url( $wp_http_referer ); ?>"><?php esc_html_e( '← Back to Users', 'buddypress' ); ?></a></p> 
  875.  
  876. <?php endif; ?> 
  877.  
  878. </div> 
  879.  
  880. <?php endif; ?> 
  881.  
  882. <div class="wrap" id="community-profile-page"> 
  883. <h1><?php echo esc_html( $title ); ?> 
  884.  
  885. <?php if ( empty( $this->is_self_profile ) ) : ?> 
  886.  
  887. <?php if ( current_user_can( 'create_users' ) ) : ?> 
  888.  
  889. <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'user', 'buddypress' ); ?></a> 
  890.  
  891. <?php elseif ( is_multisite() && current_user_can( 'promote_users' ) ) : ?> 
  892.  
  893. <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add Existing', 'user', 'buddypress' ); ?></a> 
  894.  
  895. <?php endif; ?> 
  896.  
  897. <?php endif; ?> 
  898. </h1> 
  899.  
  900. <?php if ( ! empty( $user ) ) : 
  901.  
  902. $this->profile_nav( $user, 'BuddyPress' ); ?> 
  903.  
  904. <form action="<?php echo esc_url( $form_action_url ); ?>" id="your-profile" method="post"> 
  905. <div id="poststuff"> 
  906.  
  907. <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>"> 
  908.  
  909. <div id="postbox-container-1" class="postbox-container"> 
  910. <?php do_meta_boxes( get_current_screen()->id, 'side', $user ); ?> 
  911. </div> 
  912.  
  913. <div id="postbox-container-2" class="postbox-container"> 
  914. <?php do_meta_boxes( get_current_screen()->id, 'normal', $user ); ?> 
  915. <?php do_meta_boxes( get_current_screen()->id, 'advanced', $user ); ?> 
  916. </div> 
  917. </div><!-- #post-body --> 
  918.  
  919. </div><!-- #poststuff --> 
  920.  
  921. <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?> 
  922. <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?> 
  923. <?php wp_nonce_field( 'edit-bp-profile_' . $user->ID ); ?> 
  924.  
  925. </form> 
  926.  
  927. <?php else : ?> 
  928.  
  929. <p><?php 
  930. printf( 
  931. '%1$s <a href="%2$s">%3$s</a>',  
  932. __( 'No user found with this ID.', 'buddypress' ),  
  933. esc_url( bp_get_admin_url( 'users.php' ) ),  
  934. __( 'Go back and try again.', 'buddypress' ) 
  935. ); 
  936. ?></p> 
  937.  
  938. <?php endif; ?> 
  939.  
  940. </div><!-- .wrap --> 
  941. <?php 
  942.  
  943. /** 
  944. * Render the Status metabox for user's profile screen. 
  945. * 
  946. * Actions are: 
  947. * - Update profile fields if xProfile component is active 
  948. * - Spam/Unspam user 
  949. * 
  950. * @since 2.0.0 
  951. * 
  952. * @param WP_User|null $user The WP_User object to be edited. 
  953. */ 
  954. public function user_admin_status_metabox( $user = null ) { 
  955.  
  956. // Bail if no user id or if the user has not activated their account yet. 
  957. if ( empty( $user->ID ) ) { 
  958. return; 
  959.  
  960. // Bail if user has not been activated yet (how did you get here?). 
  961. if ( isset( $user->user_status ) && ( 2 == $user->user_status ) ) : ?> 
  962.  
  963. <p class="not-activated"><?php esc_html_e( 'User account has not yet been activated', 'buddypress' ); ?></p><br/> 
  964.  
  965. <?php return; 
  966.  
  967. endif; ?> 
  968.  
  969. <div class="submitbox" id="submitcomment"> 
  970. <div id="minor-publishing"> 
  971. <div id="misc-publishing-actions"> 
  972. <?php 
  973.  
  974. // Get the spam status once here to compare against below. 
  975. $is_spammer = bp_is_user_spammer( $user->ID ); 
  976.  
  977. /** 
  978. * In configs where BuddyPress is not network activated,  
  979. * regular admins cannot mark a user as a spammer on front 
  980. * end. This prevent them to do it in the back end. 
  981. * 
  982. * Also prevent admins from marking themselves or other 
  983. * admins as spammers. 
  984. */ 
  985. if ( ( empty( $this->is_self_profile ) && ( ! in_array( $user->user_login, get_super_admins() ) ) && empty( $this->subsite_activated ) ) || ( ! empty( $this->subsite_activated ) && current_user_can( 'manage_network_users' ) ) ) : ?> 
  986.  
  987. <div class="misc-pub-section" id="comment-status-radio"> 
  988. <label class="approved"><input type="radio" name="user_status" value="ham" <?php checked( $is_spammer, false ); ?>><?php esc_html_e( 'Active', 'buddypress' ); ?></label><br /> 
  989. <label class="spam"><input type="radio" name="user_status" value="spam" <?php checked( $is_spammer, true ); ?>><?php esc_html_e( 'Spammer', 'buddypress' ); ?></label> 
  990. </div> 
  991.  
  992. <?php endif ;?> 
  993.  
  994. <div class="misc-pub-section curtime misc-pub-section-last"> 
  995. <?php 
  996.  
  997. // Translators: Publish box date format, see http://php.net/date. 
  998. $datef = __( 'M j, Y @ G:i', 'buddypress' ); 
  999. $date = date_i18n( $datef, strtotime( $user->user_registered ) ); 
  1000. ?> 
  1001. <span id="timestamp"><?php printf( __( 'Registered on: %s', 'buddypress' ), '<strong>' . $date . '</strong>' ); ?></span> 
  1002. </div> 
  1003. </div> <!-- #misc-publishing-actions --> 
  1004.  
  1005. <div class="clear"></div> 
  1006. </div><!-- #minor-publishing --> 
  1007.  
  1008. <div id="major-publishing-actions"> 
  1009.  
  1010. <div id="publishing-action"> 
  1011. <a class="button bp-view-profile" href="<?php echo esc_url( bp_core_get_user_domain( $user->ID ) ); ?>" target="_blank"><?php esc_html_e( 'View Profile', 'buddypress' ); ?></a> 
  1012. <?php submit_button( esc_html__( 'Update Profile', 'buddypress' ), 'primary', 'save', false ); ?> 
  1013. </div> 
  1014. <div class="clear"></div> 
  1015. </div><!-- #major-publishing-actions --> 
  1016.  
  1017. </div><!-- #submitcomment --> 
  1018.  
  1019. <?php 
  1020.  
  1021. /** 
  1022. * Render the fallback metabox in case a user has been marked as a spammer. 
  1023. * 
  1024. * @since 2.0.0 
  1025. * 
  1026. * @param WP_User|null $user The WP_User object to be edited. 
  1027. */ 
  1028. public function user_admin_spammer_metabox( $user = null ) { 
  1029. ?> 
  1030. <p><?php printf( __( '%s has been marked as a spammer. All BuddyPress data associated with the user has been removed', 'buddypress' ), esc_html( bp_core_get_user_displayname( $user->ID ) ) ) ;?></p> 
  1031. <?php 
  1032.  
  1033. /** 
  1034. * Render the Stats metabox to moderate inappropriate images. 
  1035. * 
  1036. * @since 2.0.0 
  1037. * 
  1038. * @param WP_User|null $user The WP_User object to be edited. 
  1039. */ 
  1040. public function user_admin_stats_metabox( $user = null ) { 
  1041.  
  1042. // Bail if no user ID. 
  1043. if ( empty( $user->ID ) ) { 
  1044. return; 
  1045.  
  1046. // If account is not activated last activity is the time user registered. 
  1047. if ( isset( $user->user_status ) && 2 == $user->user_status ) { 
  1048. $last_active = $user->user_registered; 
  1049.  
  1050. // Account is activated, getting user's last activity. 
  1051. } else { 
  1052. $last_active = bp_get_user_last_activity( $user->ID ); 
  1053.  
  1054. $datef = __( 'M j, Y @ G:i', 'buddypress' ); 
  1055. $date = date_i18n( $datef, strtotime( $last_active ) ); ?> 
  1056.  
  1057. <ul> 
  1058. <li class="bp-members-profile-stats"><?php printf( __( 'Last active: %1$s', 'buddypress' ), '<strong>' . $date . '</strong>' ); ?></li> 
  1059.  
  1060. <?php 
  1061. // Loading other stats only if user has activated their account. 
  1062. if ( empty( $user->user_status ) ) { 
  1063.  
  1064. /** 
  1065. * Fires in the user stats metabox if the user has activated their account. 
  1066. * 
  1067. * @since 2.0.0 
  1068. * 
  1069. * @param array $value Array holding the user ID. 
  1070. * @param object $user Current displayed user object. 
  1071. */ 
  1072. do_action( 'bp_members_admin_user_stats', array( 'user_id' => $user->ID ), $user ); 
  1073. ?> 
  1074. </ul> 
  1075.  
  1076. <?php 
  1077.  
  1078. /** 
  1079. * Render the Member Type metabox. 
  1080. * 
  1081. * @since 2.2.0 
  1082. * 
  1083. * @param WP_User|null $user The WP_User object to be edited. 
  1084. */ 
  1085. public function user_admin_member_type_metabox( $user = null ) { 
  1086.  
  1087. // Bail if no user ID. 
  1088. if ( empty( $user->ID ) ) { 
  1089. return; 
  1090.  
  1091. $types = bp_get_member_types( array(), 'objects' ); 
  1092. $current_type = bp_get_member_type( $user->ID ); 
  1093. ?> 
  1094.  
  1095. <label for="bp-members-profile-member-type" class="screen-reader-text"><?php 
  1096. /** translators: accessibility text */ 
  1097. esc_html_e( 'Select member type', 'buddypress' ); 
  1098. ?></label> 
  1099. <select name="bp-members-profile-member-type" id="bp-members-profile-member-type"> 
  1100. <option value="" <?php selected( '', $current_type ); ?>><?php 
  1101. /** translators: no option picked in select box */ 
  1102. esc_attr_e( '----', 'buddypress' ); 
  1103. ?></option> 
  1104. <?php foreach ( $types as $type ) : ?> 
  1105. <option value="<?php echo esc_attr( $type->name ) ?>" <?php selected( $type->name, $current_type ) ?>><?php echo esc_html( $type->labels['singular_name'] ) ?></option> 
  1106. <?php endforeach; ?> 
  1107. </select> 
  1108.  
  1109. <?php 
  1110.  
  1111. wp_nonce_field( 'bp-member-type-change-' . $user->ID, 'bp-member-type-nonce' ); 
  1112.  
  1113. /** 
  1114. * Process changes from the Member Type metabox. 
  1115. * 
  1116. * @since 2.2.0 
  1117. */ 
  1118. public function process_member_type_update() { 
  1119. if ( ! isset( $_POST['bp-member-type-nonce'] ) || ! isset( $_POST['bp-members-profile-member-type'] ) ) { 
  1120. return; 
  1121.  
  1122. $user_id = $this->get_user_id(); 
  1123.  
  1124. check_admin_referer( 'bp-member-type-change-' . $user_id, 'bp-member-type-nonce' ); 
  1125.  
  1126. // Permission check. 
  1127. if ( ! current_user_can( 'bp_moderate' ) && $user_id != bp_loggedin_user_id() ) { 
  1128. return; 
  1129.  
  1130. // Member type string must either reference a valid member type, or be empty. 
  1131. $member_type = stripslashes( $_POST['bp-members-profile-member-type'] ); 
  1132. if ( ! empty( $member_type ) && ! bp_get_member_type_object( $member_type ) ) { 
  1133. return; 
  1134.  
  1135. /** 
  1136. * If an invalid member type is passed, someone's doing something 
  1137. * fishy with the POST request, so we can fail silently. 
  1138. */ 
  1139. if ( bp_set_member_type( $user_id, $member_type ) ) { 
  1140. // @todo Success messages can't be posted because other stuff happens on the page load. 
  1141.  
  1142. /** 
  1143. * Add a link to Profile in Users listing row actions. 
  1144. * 
  1145. * @since 2.0.0 
  1146. * 
  1147. * @param array|string $actions WordPress row actions (edit, delete). 
  1148. * @param object|null $user The object for the user row. 
  1149. * @return array Merged actions. 
  1150. */ 
  1151. public function row_actions( $actions = '', $user = null ) { 
  1152.  
  1153. // Bail if no user ID. 
  1154. if ( empty( $user->ID ) ) { 
  1155. return; 
  1156.  
  1157. // Setup args array. 
  1158. $args = array(); 
  1159.  
  1160. // Add the user ID if it's not for the current user. 
  1161. if ( $user->ID !== $this->current_user_id ) { 
  1162. $args['user_id'] = $user->ID; 
  1163.  
  1164. // Add the referer. 
  1165. $args['wp_http_referer'] = urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ); 
  1166.  
  1167. // Add the "Extended" link if the current user can edit this user. 
  1168. if ( current_user_can( 'edit_user', $user->ID ) || bp_current_user_can( 'bp_moderate' ) ) { 
  1169.  
  1170. // Add query args and setup the Extended link. 
  1171. $edit_profile = add_query_arg( $args, $this->edit_profile_url ); 
  1172. $edit_profile_link = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $edit_profile ), esc_html__( 'Extended', 'buddypress' ) ); 
  1173.  
  1174. /** 
  1175. * Check the edit action is available 
  1176. * and preserve the order edit | profile | remove/delete. 
  1177. */ 
  1178. if ( ! empty( $actions['edit'] ) ) { 
  1179. $edit_action = $actions['edit']; 
  1180. unset( $actions['edit'] ); 
  1181.  
  1182. $new_edit_actions = array( 
  1183. 'edit' => $edit_action,  
  1184. 'edit-profile' => $edit_profile_link,  
  1185. ); 
  1186.  
  1187. // If not available simply add the edit profile action. 
  1188. } else { 
  1189. $new_edit_actions = array( 'edit-profile' => $edit_profile_link ); 
  1190.  
  1191. $actions = array_merge( $new_edit_actions, $actions ); 
  1192.  
  1193. return $actions; 
  1194.  
  1195. /** 
  1196. * Add a filter to edit profile url in WP Admin Bar. 
  1197. * 
  1198. * @since 2.1.0 
  1199. */ 
  1200. public function add_edit_profile_url_filter() { 
  1201. add_filter( 'bp_members_edit_profile_url', array( $this, 'filter_adminbar_profile_link' ), 10, 3 ); 
  1202.  
  1203. /** 
  1204. * Filter the profile url. 
  1205. * 
  1206. * @since 2.1.0 
  1207. * 
  1208. * 
  1209. * @param string $profile_link Profile Link for admin bar. 
  1210. * @param string $url Profile URL. 
  1211. * @param int $user_id User ID. 
  1212. * @return string 
  1213. */ 
  1214. public function filter_adminbar_profile_link( $profile_link = '', $url = '', $user_id = 0 ) { 
  1215. if ( ! is_super_admin( $user_id ) && is_admin() ) { 
  1216. $profile_link = user_admin_url( 'profile.php' ); 
  1217. return $profile_link; 
  1218.  
  1219. /** 
  1220. * Remove the filter to edit profile url in WP Admin Bar. 
  1221. * 
  1222. * @since 2.1.0 
  1223. */ 
  1224. public function remove_edit_profile_url_filter() { 
  1225. remove_filter( 'bp_members_edit_profile_url', array( $this, 'filter_adminbar_profile_link' ), 10 ); 
  1226.  
  1227. /** Signups Management ****************************************************/ 
  1228.  
  1229. /** 
  1230. * Display the admin preferences about signups pagination. 
  1231. * 
  1232. * @since 2.0.0 
  1233. * 
  1234. * @param int $value Value for signup option. 
  1235. * @param string $option Value for the option key. 
  1236. * @param int $new_value Value for the saved option. 
  1237. * @return int The pagination preferences. 
  1238. */ 
  1239. public function signup_screen_options( $value = 0, $option = '', $new_value = 0 ) { 
  1240. if ( 'users_page_bp_signups_network_per_page' != $option && 'users_page_bp_signups_per_page' != $option ) { 
  1241. return $value; 
  1242.  
  1243. // Per page. 
  1244. $new_value = (int) $new_value; 
  1245. if ( $new_value < 1 || $new_value > 999 ) { 
  1246. return $value; 
  1247.  
  1248. return $new_value; 
  1249.  
  1250. /** 
  1251. * Make sure no signups will show in users list. 
  1252. * 
  1253. * This is needed to handle signups that may have not been activated 
  1254. * before the 2.0.0 upgrade. 
  1255. * 
  1256. * @since 2.0.0 
  1257. * 
  1258. * @param WP_User_Query|null $query The users query. 
  1259. * @return WP_User_Query The users query without the signups. 
  1260. */ 
  1261. public function remove_signups_from_user_query( $query = null ) { 
  1262. global $wpdb; 
  1263.  
  1264. // Bail if this is an ajax request. 
  1265. if ( defined( 'DOING_AJAX' ) ) { 
  1266. return; 
  1267.  
  1268. // Bail if updating BuddyPress. 
  1269. if ( bp_is_update() ) { 
  1270. return; 
  1271.  
  1272. // Bail if there is no current admin screen. 
  1273. if ( ! function_exists( 'get_current_screen' ) || ! get_current_screen() ) { 
  1274. return; 
  1275.  
  1276. // Get current screen. 
  1277. $current_screen = get_current_screen(); 
  1278.  
  1279. // Bail if not on a users page. 
  1280. if ( ! isset( $current_screen->id ) || $this->users_page !== $current_screen->id ) { 
  1281. return; 
  1282.  
  1283. // Bail if already querying by an existing role. 
  1284. if ( ! empty( $query->query_vars['role'] ) ) { 
  1285. return; 
  1286.  
  1287. $query->query_where .= " AND {$wpdb->users}.user_status != 2"; 
  1288.  
  1289. /** 
  1290. * Filter the WP Users List Table views to include 'bp-signups'. 
  1291. * 
  1292. * @since 2.0.0 
  1293. * 
  1294. * @param array $views WP List Table views. 
  1295. * @return array The views with the signup view added. 
  1296. */ 
  1297. public function signup_filter_view( $views = array() ) { 
  1298. global $role; 
  1299.  
  1300. // Remove the 'current' class from All if we're on the signups view. 
  1301. if ( 'registered' === $role ) { 
  1302. $views['all'] = str_replace( 'class="current"', '', $views['all'] ); 
  1303. $class = 'current'; 
  1304. } else { 
  1305. $class = ''; 
  1306.  
  1307. $signups = BP_Signup::count_signups(); 
  1308.  
  1309. if ( is_network_admin() ) { 
  1310. $base_url = network_admin_url( 'users.php' ); 
  1311. } else { 
  1312. $base_url = bp_get_admin_url( 'users.php' ); 
  1313.  
  1314. $url = add_query_arg( 'page', 'bp-signups', $base_url ); 
  1315. $text = sprintf( _x( 'Pending %s', 'signup users', 'buddypress' ), '<span class="count">(' . number_format_i18n( $signups ) . ')</span>' ); 
  1316.  
  1317. $views['registered'] = sprintf( '<a href="%1$s" class="%2$s">%3$s</a>', esc_url( $url ), $class, $text ); 
  1318.  
  1319. return $views; 
  1320.  
  1321. /** 
  1322. * Load the Signup WP Users List table. 
  1323. * 
  1324. * @since 2.0.0 
  1325. * 
  1326. * @param string $class The name of the class to use. 
  1327. * @param string $required The parent class. 
  1328. * @return WP_List_Table The List table. 
  1329. */ 
  1330. public static function get_list_table_class( $class = '', $required = '' ) { 
  1331. if ( empty( $class ) ) { 
  1332. return; 
  1333.  
  1334. if ( ! empty( $required ) ) { 
  1335. require_once( ABSPATH . 'wp-admin/includes/class-wp-' . $required . '-list-table.php' ); 
  1336.  
  1337. return new $class(); 
  1338.  
  1339. /** 
  1340. * Set up the signups admin page. 
  1341. * 
  1342. * Loaded before the page is rendered, this function does all initial 
  1343. * setup, including: processing form requests, registering contextual 
  1344. * help, and setting up screen options. 
  1345. * 
  1346. * @since 2.0.0 
  1347. * 
  1348. * @global $bp_members_signup_list_table 
  1349. */ 
  1350. public function signups_admin_load() { 
  1351. global $bp_members_signup_list_table; 
  1352.  
  1353. // Build redirection URL. 
  1354. $redirect_to = remove_query_arg( array( 'action', 'error', 'updated', 'activated', 'notactivated', 'deleted', 'notdeleted', 'resent', 'notresent', 'do_delete', 'do_resend', 'do_activate', '_wpnonce', 'signup_ids' ), $_SERVER['REQUEST_URI'] ); 
  1355. $doaction = bp_admin_list_table_current_bulk_action(); 
  1356.  
  1357. /** 
  1358. * Fires at the start of the signups admin load. 
  1359. * 
  1360. * @since 2.0.0 
  1361. * 
  1362. * @param string $doaction Current bulk action being processed. 
  1363. * @param array $_REQUEST Current $_REQUEST global. 
  1364. */ 
  1365. do_action( 'bp_signups_admin_load', $doaction, $_REQUEST ); 
  1366.  
  1367. /** 
  1368. * Filters the allowed actions for use in the user signups admin page. 
  1369. * 
  1370. * @since 2.0.0 
  1371. * 
  1372. * @param array $value Array of allowed actions to use. 
  1373. */ 
  1374. $allowed_actions = apply_filters( 'bp_signups_admin_allowed_actions', array( 'do_delete', 'do_activate', 'do_resend' ) ); 
  1375.  
  1376. // Prepare the display of the Community Profile screen. 
  1377. if ( ! in_array( $doaction, $allowed_actions ) || ( -1 == $doaction ) ) { 
  1378.  
  1379. if ( is_network_admin() ) { 
  1380. $bp_members_signup_list_table = self::get_list_table_class( 'BP_Members_MS_List_Table', 'ms-users' ); 
  1381. } else { 
  1382. $bp_members_signup_list_table = self::get_list_table_class( 'BP_Members_List_Table', 'users' ); 
  1383.  
  1384. // The per_page screen option. 
  1385. add_screen_option( 'per_page', array( 'label' => _x( 'Pending Accounts', 'Pending Accounts per page (screen options)', 'buddypress' ) ) ); 
  1386.  
  1387. get_current_screen()->add_help_tab( array( 
  1388. 'id' => 'bp-signups-overview',  
  1389. 'title' => __( 'Overview', 'buddypress' ),  
  1390. 'content' => 
  1391. '<p>' . __( 'This is the administration screen for pending accounts on your site.', 'buddypress' ) . '</p>' . 
  1392. '<p>' . __( 'From the screen options, you can customize the displayed columns and the pagination of this screen.', 'buddypress' ) . '</p>' . 
  1393. '<p>' . __( 'You can reorder the list of your pending accounts by clicking on the Username, Email or Registered column headers.', 'buddypress' ) . '</p>' . 
  1394. '<p>' . __( 'Using the search form, you can find pending accounts more easily. The Username and Email fields will be included in the search.', 'buddypress' ) . '</p>' 
  1395. ) ); 
  1396.  
  1397. get_current_screen()->add_help_tab( array( 
  1398. 'id' => 'bp-signups-actions',  
  1399. 'title' => __( 'Actions', 'buddypress' ),  
  1400. 'content' => 
  1401. '<p>' . __( 'Hovering over a row in the pending accounts list will display action links that allow you to manage pending accounts. You can perform the following actions:', 'buddypress' ) . '</p>' . 
  1402. '<ul><li>' . __( '"Email" takes you to the confirmation screen before being able to send the activation link to the desired pending account. You can only send the activation email once per day.', 'buddypress' ) . '</li>' . 
  1403. '<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' . 
  1404. '<p>' . __( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' . 
  1405. '<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>' 
  1406. ) ); 
  1407.  
  1408. // Help panel - sidebar links. 
  1409. get_current_screen()->set_help_sidebar( 
  1410. '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 
  1411. '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 
  1412. ); 
  1413.  
  1414. // Add accessible hidden headings and text for the Pending Users screen. 
  1415. if ( bp_get_major_wp_version() >= 4.4 ) { 
  1416. get_current_screen()->set_screen_reader_content( array( 
  1417. /** translators: accessibility text */ 
  1418. 'heading_views' => __( 'Filter users list', 'buddypress' ),  
  1419. /** translators: accessibility text */ 
  1420. 'heading_pagination' => __( 'Pending users list navigation', 'buddypress' ),  
  1421. /** translators: accessibility text */ 
  1422. 'heading_list' => __( 'Pending users list', 'buddypress' ),  
  1423. ) ); 
  1424.  
  1425. } else { 
  1426. if ( ! empty( $_REQUEST['signup_ids' ] ) ) { 
  1427. $signups = wp_parse_id_list( $_REQUEST['signup_ids' ] ); 
  1428.  
  1429. // Handle resent activation links. 
  1430. if ( 'do_resend' == $doaction ) { 
  1431.  
  1432. // Nonce check. 
  1433. check_admin_referer( 'signups_resend' ); 
  1434.  
  1435. $resent = BP_Signup::resend( $signups ); 
  1436.  
  1437. if ( empty( $resent ) ) { 
  1438. $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 
  1439. } else { 
  1440. $query_arg = array( 'updated' => 'resent' ); 
  1441.  
  1442. if ( ! empty( $resent['resent'] ) ) { 
  1443. $query_arg['resent'] = count( $resent['resent'] ); 
  1444.  
  1445. if ( ! empty( $resent['errors'] ) ) { 
  1446. $query_arg['notsent'] = count( $resent['errors'] ); 
  1447. set_transient( '_bp_admin_signups_errors', $resent['errors'], 30 ); 
  1448.  
  1449. $redirect_to = add_query_arg( $query_arg, $redirect_to ); 
  1450.  
  1451. bp_core_redirect( $redirect_to ); 
  1452.  
  1453. // Handle activated accounts. 
  1454. } elseif ( 'do_activate' == $doaction ) { 
  1455.  
  1456. // Nonce check. 
  1457. check_admin_referer( 'signups_activate' ); 
  1458.  
  1459. $activated = BP_Signup::activate( $signups ); 
  1460.  
  1461. if ( empty( $activated ) ) { 
  1462. $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 
  1463. } else { 
  1464. $query_arg = array( 'updated' => 'activated' ); 
  1465.  
  1466. if ( ! empty( $activated['activated'] ) ) { 
  1467. $query_arg['activated'] = count( $activated['activated'] ); 
  1468.  
  1469. if ( ! empty( $activated['errors'] ) ) { 
  1470. $query_arg['notactivated'] = count( $activated['errors'] ); 
  1471. set_transient( '_bp_admin_signups_errors', $activated['errors'], 30 ); 
  1472.  
  1473. $redirect_to = add_query_arg( $query_arg, $redirect_to ); 
  1474.  
  1475. bp_core_redirect( $redirect_to ); 
  1476.  
  1477. // Handle sign-ups delete. 
  1478. } elseif ( 'do_delete' == $doaction ) { 
  1479.  
  1480. // Nonce check. 
  1481. check_admin_referer( 'signups_delete' ); 
  1482.  
  1483. $deleted = BP_Signup::delete( $signups ); 
  1484.  
  1485. if ( empty( $deleted ) ) { 
  1486. $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 
  1487. } else { 
  1488. $query_arg = array( 'updated' => 'deleted' ); 
  1489.  
  1490. if ( ! empty( $deleted['deleted'] ) ) { 
  1491. $query_arg['deleted'] = count( $deleted['deleted'] ); 
  1492.  
  1493. if ( ! empty( $deleted['errors'] ) ) { 
  1494. $query_arg['notdeleted'] = count( $deleted['errors'] ); 
  1495. set_transient( '_bp_admin_signups_errors', $deleted['errors'], 30 ); 
  1496.  
  1497. $redirect_to = add_query_arg( $query_arg, $redirect_to ); 
  1498.  
  1499. bp_core_redirect( $redirect_to ); 
  1500.  
  1501. // Plugins can update other stuff from here. 
  1502. } else { 
  1503. $this->redirect = $redirect_to; 
  1504.  
  1505. /** 
  1506. * Fires at end of signups admin load if doaction does not match any actions. 
  1507. * 
  1508. * @since 2.0.0 
  1509. * 
  1510. * @param string $doaction Current bulk action being processed. 
  1511. * @param array $_REQUEST Current $_REQUEST global. 
  1512. * @param string $redirect Determined redirect url to send user to. 
  1513. */ 
  1514. do_action( 'bp_members_admin_update_signups', $doaction, $_REQUEST, $this->redirect ); 
  1515.  
  1516. bp_core_redirect( $this->redirect ); 
  1517.  
  1518. /** 
  1519. * Display any activation errors. 
  1520. * 
  1521. * @since 2.0.0 
  1522. */ 
  1523. public function signups_display_errors() { 
  1524.  
  1525. // Look for sign-up errors. 
  1526. $errors = get_transient( '_bp_admin_signups_errors' ); 
  1527.  
  1528. // Bail if no activation errors. 
  1529. if ( empty( $errors ) ) { 
  1530. return; 
  1531.  
  1532. // Loop through errors and display them. 
  1533. foreach ( $errors as $error ) : ?> 
  1534.  
  1535. <li><?php echo esc_html( $error[0] );?>: <?php echo esc_html( $error[1] );?></li> 
  1536.  
  1537. <?php endforeach; 
  1538.  
  1539. // Delete the redirect transient. 
  1540. delete_transient( '_bp_admin_signups_errors' ); 
  1541.  
  1542. /** 
  1543. * Get admin notice when viewing the sign-up page. 
  1544. * 
  1545. * @since 2.1.0 
  1546. * 
  1547. * @return array 
  1548. */ 
  1549. private function get_signup_notice() { 
  1550.  
  1551. // Setup empty notice for return value. 
  1552. $notice = array(); 
  1553.  
  1554. // Updates. 
  1555. if ( ! empty( $_REQUEST['updated'] ) ) { 
  1556. switch ( $_REQUEST['updated'] ) { 
  1557. case 'resent': 
  1558. $notice = array( 
  1559. 'class' => 'updated',  
  1560. 'message' => '' 
  1561. ); 
  1562.  
  1563. if ( ! empty( $_REQUEST['resent'] ) ) { 
  1564. $notice['message'] .= sprintf( 
  1565. _nx( '%s activation email successfully sent! ', '%s activation emails successfully sent! ',  
  1566. absint( $_REQUEST['resent'] ),  
  1567. 'signup resent',  
  1568. 'buddypress' 
  1569. ),  
  1570. number_format_i18n( absint( $_REQUEST['resent'] ) ) 
  1571. ); 
  1572.  
  1573. if ( ! empty( $_REQUEST['notsent'] ) ) { 
  1574. $notice['message'] .= sprintf( 
  1575. _nx( '%s activation email was not sent.', '%s activation emails were not sent.',  
  1576. absint( $_REQUEST['notsent'] ),  
  1577. 'signup notsent',  
  1578. 'buddypress' 
  1579. ),  
  1580. number_format_i18n( absint( $_REQUEST['notsent'] ) ) 
  1581. ); 
  1582.  
  1583. if ( empty( $_REQUEST['resent'] ) ) { 
  1584. $notice['class'] = 'error'; 
  1585.  
  1586. break; 
  1587.  
  1588. case 'activated': 
  1589. $notice = array( 
  1590. 'class' => 'updated',  
  1591. 'message' => '' 
  1592. ); 
  1593.  
  1594. if ( ! empty( $_REQUEST['activated'] ) ) { 
  1595. $notice['message'] .= sprintf( 
  1596. _nx( '%s account successfully activated! ', '%s accounts successfully activated! ',  
  1597. absint( $_REQUEST['activated'] ),  
  1598. 'signup resent',  
  1599. 'buddypress' 
  1600. ),  
  1601. number_format_i18n( absint( $_REQUEST['activated'] ) ) 
  1602. ); 
  1603.  
  1604. if ( ! empty( $_REQUEST['notactivated'] ) ) { 
  1605. $notice['message'] .= sprintf( 
  1606. _nx( '%s account was not activated.', '%s accounts were not activated.',  
  1607. absint( $_REQUEST['notactivated'] ),  
  1608. 'signup notsent',  
  1609. 'buddypress' 
  1610. ),  
  1611. number_format_i18n( absint( $_REQUEST['notactivated'] ) ) 
  1612. ); 
  1613.  
  1614. if ( empty( $_REQUEST['activated'] ) ) { 
  1615. $notice['class'] = 'error'; 
  1616.  
  1617. break; 
  1618.  
  1619. case 'deleted': 
  1620. $notice = array( 
  1621. 'class' => 'updated',  
  1622. 'message' => '' 
  1623. ); 
  1624.  
  1625. if ( ! empty( $_REQUEST['deleted'] ) ) { 
  1626. $notice['message'] .= sprintf( 
  1627. _nx( '%s sign-up successfully deleted!', '%s sign-ups successfully deleted!',  
  1628. absint( $_REQUEST['deleted'] ),  
  1629. 'signup deleted',  
  1630. 'buddypress' 
  1631. ),  
  1632. number_format_i18n( absint( $_REQUEST['deleted'] ) ) 
  1633. ); 
  1634.  
  1635. if ( ! empty( $_REQUEST['notdeleted'] ) ) { 
  1636. $notice['message'] .= sprintf( 
  1637. _nx( '%s sign-up was not deleted.', '%s sign-ups were not deleted.',  
  1638. absint( $_REQUEST['notdeleted'] ),  
  1639. 'signup notdeleted',  
  1640. 'buddypress' 
  1641. ),  
  1642. number_format_i18n( absint( $_REQUEST['notdeleted'] ) ) 
  1643. ); 
  1644.  
  1645. if ( empty( $_REQUEST['deleted'] ) ) { 
  1646. $notice['class'] = 'error'; 
  1647.  
  1648. break; 
  1649.  
  1650. // Errors. 
  1651. if ( ! empty( $_REQUEST['error'] ) ) { 
  1652. switch ( $_REQUEST['error'] ) { 
  1653. case 'do_resend': 
  1654. $notice = array( 
  1655. 'class' => 'error',  
  1656. 'message' => esc_html__( 'There was a problem sending the activation emails. Please try again.', 'buddypress' ),  
  1657. ); 
  1658. break; 
  1659.  
  1660. case 'do_activate': 
  1661. $notice = array( 
  1662. 'class' => 'error',  
  1663. 'message' => esc_html__( 'There was a problem activating accounts. Please try again.', 'buddypress' ),  
  1664. ); 
  1665. break; 
  1666.  
  1667. case 'do_delete': 
  1668. $notice = array( 
  1669. 'class' => 'error',  
  1670. 'message' => esc_html__( 'There was a problem deleting sign-ups. Please try again.', 'buddypress' ),  
  1671. ); 
  1672. break; 
  1673.  
  1674. return $notice; 
  1675.  
  1676. /** 
  1677. * Signups admin page router. 
  1678. * 
  1679. * Depending on the context, display 
  1680. * - the list of signups,  
  1681. * - or the delete confirmation screen,  
  1682. * - or the activate confirmation screen,  
  1683. * - or the "resend" email confirmation screen. 
  1684. * 
  1685. * Also prepare the admin notices. 
  1686. * 
  1687. * @since 2.0.0 
  1688. */ 
  1689. public function signups_admin() { 
  1690. $doaction = bp_admin_list_table_current_bulk_action(); 
  1691.  
  1692. // Prepare notices for admin. 
  1693. $notice = $this->get_signup_notice(); 
  1694.  
  1695. // Display notices. 
  1696. if ( ! empty( $notice ) ) : 
  1697. if ( 'updated' === $notice['class'] ) : ?> 
  1698.  
  1699. <div id="message" class="<?php echo esc_attr( $notice['class'] ); ?>"> 
  1700.  
  1701. <?php else: ?> 
  1702.  
  1703. <div class="<?php echo esc_attr( $notice['class'] ); ?>"> 
  1704.  
  1705. <?php endif; ?> 
  1706.  
  1707. <p><?php echo $notice['message']; ?></p> 
  1708.  
  1709. <?php if ( ! empty( $_REQUEST['notactivated'] ) || ! empty( $_REQUEST['notdeleted'] ) || ! empty( $_REQUEST['notsent'] ) ) :?> 
  1710.  
  1711. <ul><?php $this->signups_display_errors();?></ul> 
  1712.  
  1713. <?php endif ;?> 
  1714.  
  1715. </div> 
  1716.  
  1717. <?php endif; 
  1718.  
  1719. // Show the proper screen. 
  1720. switch ( $doaction ) { 
  1721. case 'activate' : 
  1722. case 'delete' : 
  1723. case 'resend' : 
  1724. $this->signups_admin_manage( $doaction ); 
  1725. break; 
  1726.  
  1727. default: 
  1728. $this->signups_admin_index(); 
  1729. break; 
  1730.  
  1731.  
  1732. /** 
  1733. * This is the list of the Pending accounts (signups). 
  1734. * 
  1735. * @since 2.0.0 
  1736. * 
  1737. * @global $plugin_page 
  1738. * @global $bp_members_signup_list_table 
  1739. */ 
  1740. public function signups_admin_index() { 
  1741. global $plugin_page, $bp_members_signup_list_table; 
  1742.  
  1743. $usersearch = ! empty( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : ''; 
  1744.  
  1745. // Prepare the group items for display. 
  1746. $bp_members_signup_list_table->prepare_items(); 
  1747.  
  1748. if ( is_network_admin() ) { 
  1749. $form_url = network_admin_url( 'users.php' ); 
  1750. } else { 
  1751. $form_url = bp_get_admin_url( 'users.php' ); 
  1752.  
  1753. $form_url = add_query_arg( 
  1754. array( 
  1755. 'page' => 'bp-signups',  
  1756. ),  
  1757. $form_url 
  1758. ); 
  1759.  
  1760. $search_form_url = remove_query_arg( 
  1761. array( 
  1762. 'action',  
  1763. 'deleted',  
  1764. 'notdeleted',  
  1765. 'error',  
  1766. 'updated',  
  1767. 'delete',  
  1768. 'activate',  
  1769. 'activated',  
  1770. 'notactivated',  
  1771. 'resend',  
  1772. 'resent',  
  1773. 'notresent',  
  1774. 'do_delete',  
  1775. 'do_activate',  
  1776. 'do_resend',  
  1777. 'action2',  
  1778. '_wpnonce',  
  1779. 'signup_ids' 
  1780. ), $_SERVER['REQUEST_URI'] 
  1781. ); 
  1782.  
  1783. ?> 
  1784.  
  1785. <div class="wrap"> 
  1786. <h1><?php _e( 'Users', 'buddypress' ); ?> 
  1787.  
  1788. <?php if ( current_user_can( 'create_users' ) ) : ?> 
  1789.  
  1790. <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'user', 'buddypress' ); ?></a> 
  1791.  
  1792. <?php elseif ( is_multisite() && current_user_can( 'promote_users' ) ) : ?> 
  1793.  
  1794. <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add Existing', 'user', 'buddypress' ); ?></a> 
  1795.  
  1796. <?php endif; 
  1797.  
  1798. if ( $usersearch ) { 
  1799. printf( '<span class="subtitle">' . __( 'Search results for “%s”', 'buddypress' ) . '</span>', esc_html( $usersearch ) ); 
  1800.  
  1801. ?> 
  1802. </h1> 
  1803.  
  1804. <?php // Display each signups on its own row. ?> 
  1805. <?php $bp_members_signup_list_table->views(); ?> 
  1806.  
  1807. <form id="bp-signups-search-form" action="<?php echo esc_url( $search_form_url ) ;?>"> 
  1808. <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" /> 
  1809. <?php $bp_members_signup_list_table->search_box( __( 'Search Pending Users', 'buddypress' ), 'bp-signups' ); ?> 
  1810. </form> 
  1811.  
  1812. <form id="bp-signups-form" action="<?php echo esc_url( $form_url );?>" method="post"> 
  1813. <?php $bp_members_signup_list_table->display(); ?> 
  1814. </form> 
  1815. </div> 
  1816. <?php 
  1817.  
  1818. /** 
  1819. * This is the confirmation screen for actions. 
  1820. * 
  1821. * @since 2.0.0 
  1822. * 
  1823. * @param string $action Delete, activate, or resend activation link. 
  1824. * 
  1825. * @return string 
  1826. */ 
  1827. public function signups_admin_manage( $action = '' ) { 
  1828. if ( ! current_user_can( $this->capability ) || empty( $action ) ) { 
  1829. die( '-1' ); 
  1830.  
  1831. // Get the user IDs from the URL. 
  1832. $ids = false; 
  1833. if ( ! empty( $_POST['allsignups'] ) ) { 
  1834. $ids = wp_parse_id_list( $_POST['allsignups'] ); 
  1835. } elseif ( ! empty( $_GET['signup_id'] ) ) { 
  1836. $ids = absint( $_GET['signup_id'] ); 
  1837.  
  1838. if ( empty( $ids ) ) { 
  1839. return false; 
  1840.  
  1841. // Query for signups, and filter out those IDs that don't 
  1842. // correspond to an actual signup. 
  1843. $signups_query = BP_Signup::get( array( 
  1844. 'include' => $ids,  
  1845. ) ); 
  1846.  
  1847. $signups = $signups_query['signups']; 
  1848. $signup_ids = wp_list_pluck( $signups, 'signup_id' ); 
  1849.  
  1850. // Set up strings. 
  1851. switch ( $action ) { 
  1852. case 'delete' : 
  1853. $header_text = __( 'Delete Pending Accounts', 'buddypress' ); 
  1854. if ( 1 == count( $signup_ids ) ) { 
  1855. $helper_text = __( 'You are about to delete the following account:', 'buddypress' ); 
  1856. } else { 
  1857. $helper_text = __( 'You are about to delete the following accounts:', 'buddypress' ); 
  1858. break; 
  1859.  
  1860. case 'activate' : 
  1861. $header_text = __( 'Activate Pending Accounts', 'buddypress' ); 
  1862. if ( 1 == count( $signup_ids ) ) { 
  1863. $helper_text = __( 'You are about to activate the following account:', 'buddypress' ); 
  1864. } else { 
  1865. $helper_text = __( 'You are about to activate the following accounts:', 'buddypress' ); 
  1866. break; 
  1867.  
  1868. case 'resend' : 
  1869. $header_text = __( 'Resend Activation Emails', 'buddypress' ); 
  1870. if ( 1 == count( $signup_ids ) ) { 
  1871. $helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' ); 
  1872. } else { 
  1873. $helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' ); 
  1874. break; 
  1875.  
  1876. // These arguments are added to all URLs. 
  1877. $url_args = array( 'page' => 'bp-signups' ); 
  1878.  
  1879. // These arguments are only added when performing an action. 
  1880. $action_args = array( 
  1881. 'action' => 'do_' . $action,  
  1882. 'signup_ids' => implode( ', ', $signup_ids ) 
  1883. ); 
  1884.  
  1885. if ( is_network_admin() ) { 
  1886. $base_url = network_admin_url( 'users.php' ); 
  1887. } else { 
  1888. $base_url = bp_get_admin_url( 'users.php' ); 
  1889.  
  1890. $cancel_url = add_query_arg( $url_args, $base_url ); 
  1891. $action_url = wp_nonce_url( 
  1892. add_query_arg( 
  1893. array_merge( $url_args, $action_args ),  
  1894. $base_url 
  1895. ),  
  1896. 'signups_' . $action 
  1897. ); 
  1898.  
  1899. // Prefetch registration field data. 
  1900. $fdata = array(); 
  1901. if ( 'activate' === $action && bp_is_active( 'xprofile' ) ) { 
  1902. $fields = bp_xprofile_get_groups( array( 
  1903. 'profile_group_id' => 1,  
  1904. 'exclude_fields' => 1,  
  1905. 'update_meta_cache' => false,  
  1906. 'fetch_fields' => true,  
  1907. ) ); 
  1908. $fields = $fields[0]->fields; 
  1909. foreach( $fields as $f ) { 
  1910. $fdata[ $f->id ] = $f->name; 
  1911.  
  1912. ?> 
  1913.  
  1914. <div class="wrap"> 
  1915. <h1><?php echo esc_html( $header_text ); ?></h1> 
  1916. <p><?php echo esc_html( $helper_text ); ?></p> 
  1917.  
  1918. <ol class="bp-signups-list"> 
  1919. <?php foreach ( $signups as $signup ) : 
  1920. $last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent ); 
  1921. $profile_field_ids = array(); 
  1922.  
  1923. // Get all xprofile field IDs except field 1. 
  1924. if ( ! empty( $signup->meta['profile_field_ids'] ) ) { 
  1925. $profile_field_ids = array_flip( explode( ', ', $signup->meta['profile_field_ids'] ) ); 
  1926. unset( $profile_field_ids[1] ); 
  1927. } ?> 
  1928.  
  1929. <li> 
  1930. <strong><?php echo esc_html( $signup->user_login ) ?></strong> 
  1931.  
  1932. <?php if ( 'activate' == $action ) : ?> 
  1933. <table class="wp-list-table widefat fixed striped"> 
  1934. <tbody> 
  1935. <tr> 
  1936. <td class="column-fields"><?php esc_html_e( 'Display Name', 'buddypress' ); ?></td> 
  1937. <td><?php echo esc_html( $signup->user_name ); ?></td> 
  1938. </tr> 
  1939.  
  1940. <tr> 
  1941. <td class="column-fields"><?php esc_html_e( 'Email', 'buddypress' ); ?></td> 
  1942. <td><?php echo sanitize_email( $signup->user_email ); ?></td> 
  1943. </tr> 
  1944.  
  1945. <?php if ( bp_is_active( 'xprofile' ) && ! empty( $profile_field_ids ) ) : ?> 
  1946. <?php foreach ( $profile_field_ids as $pid => $noop ) : 
  1947. $field_value = isset( $signup->meta[ "field_{$pid}" ] ) ? $signup->meta[ "field_{$pid}" ] : ''; ?> 
  1948. <tr> 
  1949. <td class="column-fields"><?php echo esc_html( $fdata[ $pid ] ); ?></td> 
  1950. <td><?php echo $this->format_xprofile_field_for_display( $field_value ); ?></td> 
  1951. </tr> 
  1952.  
  1953. <?php endforeach; ?> 
  1954.  
  1955. <?php endif; ?> 
  1956.  
  1957. </tbody> 
  1958. </table> 
  1959. <?php endif; ?> 
  1960.  
  1961. <?php if ( 'resend' == $action ) : ?> 
  1962.  
  1963. <p class="description"> 
  1964. <?php printf( esc_html__( 'Last notified: %s', 'buddypress'), $last_notified ) ;?> 
  1965.  
  1966. <?php if ( ! empty( $signup->recently_sent ) ) : ?> 
  1967.  
  1968. <span class="attention wp-ui-text-notification"> <?php esc_html_e( '(less than 24 hours ago)', 'buddypress' ); ?></span> 
  1969.  
  1970. <?php endif; ?> 
  1971. </p> 
  1972.  
  1973. <?php endif; ?> 
  1974.  
  1975. </li> 
  1976.  
  1977. <?php endforeach; ?> 
  1978. </ol> 
  1979.  
  1980. <?php if ( 'delete' === $action ) : ?> 
  1981.  
  1982. <p><strong><?php esc_html_e( 'This action cannot be undone.', 'buddypress' ) ?></strong></p> 
  1983.  
  1984. <?php endif ; ?> 
  1985.  
  1986. <a class="button-primary" href="<?php echo esc_url( $action_url ); ?>"><?php esc_html_e( 'Confirm', 'buddypress' ); ?></a> 
  1987. <a class="button" href="<?php echo esc_url( $cancel_url ); ?>"><?php esc_html_e( 'Cancel', 'buddypress' ) ?></a> 
  1988. </div> 
  1989.  
  1990. <?php 
  1991.  
  1992. /** Users List Management ****************************************************/ 
  1993.  
  1994. /** 
  1995. * Display a dropdown to bulk change the member type of selected user(s). 
  1996. * 
  1997. * @since 2.7.0 
  1998. * 
  1999. * @param string $which Where this dropdown is displayed - top or bottom. 
  2000. */ 
  2001. public function users_table_output_type_change_select( $which = 'top' ) { 
  2002.  
  2003. // Bail if current user cannot promote users. 
  2004. if ( ! bp_current_user_can( 'promote_users' ) ) { 
  2005. return; 
  2006.  
  2007. // `$which` is only passed in WordPress 4.6+. Avoid duplicating controls in earlier versions. 
  2008. static $displayed = false; 
  2009. if ( version_compare( bp_get_major_wp_version(), '4.6', '<' ) && $displayed ) { 
  2010. return; 
  2011. $displayed = true; 
  2012.  
  2013. $id_name = 'bottom' === $which ? 'bp_change_type2' : 'bp_change_type'; 
  2014.  
  2015. $types = bp_get_member_types( array(), 'objects' ); ?> 
  2016.  
  2017. <label class="screen-reader-text" for="<?php echo $id_name; ?>"><?php _e( 'Change member type to…', 'buddypress' ) ?></label> 
  2018. <select name="<?php echo $id_name; ?>" id="<?php echo $id_name; ?>" style="display:inline-block;float:none;"> 
  2019. <option value=""><?php _e( 'Change member type to…', 'buddypress' ) ?></option> 
  2020.  
  2021. <?php foreach( $types as $type ) : ?> 
  2022.  
  2023. <option value="<?php echo esc_attr( $type->name ); ?>"><?php echo esc_html( $type->labels['singular_name'] ); ?></option> 
  2024.  
  2025. <?php endforeach; ?> 
  2026.  
  2027. <option value="remove_member_type"><?php _e( 'No Member Type', 'buddypress' ) ?></option> 
  2028.  
  2029. </select> 
  2030. <?php 
  2031. wp_nonce_field( 'bp-bulk-users-change-type-' . bp_loggedin_user_id(), 'bp-bulk-users-change-type-nonce' ); 
  2032. submit_button( __( 'Change', 'buddypress' ), 'button', 'bp_change_member_type', false ); 
  2033.  
  2034. /** 
  2035. * Process bulk member type change submission from the WP admin users list table. 
  2036. * 
  2037. * @since 2.7.0 
  2038. */ 
  2039. public function users_table_process_bulk_type_change() { 
  2040. // Output the admin notice. 
  2041. $this->users_type_change_notice(); 
  2042.  
  2043. // Bail if no users are specified or if this isn't a BuddyPress action. 
  2044. if ( empty( $_REQUEST['users'] ) 
  2045. || ( empty( $_REQUEST['bp_change_type'] ) && empty( $_REQUEST['bp_change_type2'] ) ) 
  2046. || empty( $_REQUEST['bp_change_member_type'] ) 
  2047. ) { 
  2048. return; 
  2049.  
  2050. // Bail if nonce check fails. 
  2051. check_admin_referer( 'bp-bulk-users-change-type-' . bp_loggedin_user_id(), 'bp-bulk-users-change-type-nonce' ); 
  2052.  
  2053. // Bail if current user cannot promote users. 
  2054. if ( ! bp_current_user_can( 'promote_users' ) ) { 
  2055. return; 
  2056.  
  2057. $new_type = ''; 
  2058. if ( ! empty( $_REQUEST['bp_change_type2'] ) ) { 
  2059. $new_type = sanitize_text_field( $_REQUEST['bp_change_type2'] ); 
  2060. } elseif ( ! empty( $_REQUEST['bp_change_type'] ) ) { 
  2061. $new_type = sanitize_text_field( $_REQUEST['bp_change_type'] ); 
  2062.  
  2063. // Check that the selected type actually exists. 
  2064. if ( 'remove_member_type' != $new_type && null === bp_get_member_type_object( $new_type ) ) { 
  2065. $error = true; 
  2066. } else { 
  2067. // Run through user ids. 
  2068. $error = false; 
  2069. foreach ( (array) $_REQUEST['users'] as $user_id ) { 
  2070. $user_id = (int) $user_id; 
  2071.  
  2072. // Get the old member type to check against. 
  2073. $member_type = bp_get_member_type( $user_id ); 
  2074.  
  2075. if ( 'remove_member_type' === $new_type ) { 
  2076. // Remove the current member type, if there's one to remove. 
  2077. if ( $member_type ) { 
  2078. $removed = bp_remove_member_type( $user_id, $member_type ); 
  2079. if ( false === $removed || is_wp_error( $removed ) ) { 
  2080. $error = true; 
  2081. } else { 
  2082. // Set the new member type. 
  2083. if ( $new_type !== $member_type ) { 
  2084. $set = bp_set_member_type( $user_id, $new_type ); 
  2085. if ( false === $set || is_wp_error( $set ) ) { 
  2086. $error = true; 
  2087.  
  2088. // If there were any errors, show the error message. 
  2089. if ( $error ) { 
  2090. $redirect = add_query_arg( array( 'updated' => 'member-type-change-error' ), wp_get_referer() ); 
  2091. } else { 
  2092. $redirect = add_query_arg( array( 'updated' => 'member-type-change-success' ), wp_get_referer() ); 
  2093.  
  2094. wp_redirect( $redirect ); 
  2095. exit(); 
  2096.  
  2097. /** 
  2098. * Display an admin notice upon member type bulk update. 
  2099. * 
  2100. * @since 2.7.0 
  2101. */ 
  2102. public function users_type_change_notice() { 
  2103. $updated = isset( $_REQUEST['updated'] ) ? $_REQUEST['updated'] : false; 
  2104.  
  2105. // Display feedback. 
  2106. if ( $updated && in_array( $updated, array( 'member-type-change-error', 'member-type-change-success' ), true ) ) { 
  2107.  
  2108. if ( 'member-type-change-error' === $updated ) { 
  2109. $notice = __( 'There was an error while changing member type. Please try again.', 'buddypress' ); 
  2110. $type = 'error'; 
  2111. } else { 
  2112. $notice = __( 'Member type was changed successfully.', 'buddypress' ); 
  2113. $type = 'updated'; 
  2114.  
  2115. bp_core_add_admin_notice( $notice, $type ); 
  2116.  
  2117. /** 
  2118. * Add member type column to the WordPress admin users list table. 
  2119. * 
  2120. * @since 2.7.0 
  2121. * 
  2122. * @param array $columns Users table columns. 
  2123. * 
  2124. * @return array $columns 
  2125. */ 
  2126. public function users_table_add_type_column( $columns = array() ) { 
  2127. $columns[ bp_get_member_type_tax_name() ] = _x( 'Member Type', 'Label for the WP users table member type column', 'buddypress' ); 
  2128.  
  2129. return $columns; 
  2130.  
  2131. /** 
  2132. * Return member's type for display in the WP admin users list table. 
  2133. * 
  2134. * @since 2.7.0 
  2135. * 
  2136. * @param string $retval 
  2137. * @param string $column_name 
  2138. * @param int $user_id 
  2139. * 
  2140. * @return string Member type as a link to filter all users. 
  2141. */ 
  2142. public function users_table_populate_type_cell( $retval = '', $column_name = '', $user_id = 0 ) { 
  2143. // Only looking for member type column. 
  2144. if ( bp_get_member_type_tax_name() !== $column_name ) { 
  2145. return $retval; 
  2146.  
  2147. // Get the member type. 
  2148. $type = bp_get_member_type( $user_id ); 
  2149.  
  2150. // Output the 
  2151. if ( $type_obj = bp_get_member_type_object( $type ) ) { 
  2152. $url = add_query_arg( array( 'bp-member-type' => urlencode( $type ) ) ); 
  2153. $retval = '<a href="' . esc_url( $url ) . '">' . esc_html( $type_obj->labels['singular_name'] ) . '</a>'; 
  2154.  
  2155. return $retval; 
  2156.  
  2157. /** 
  2158. * Filter WP Admin users list table to include users of the specified type. 
  2159. * 
  2160. * @param WP_Query $query 
  2161. * 
  2162. * @since 2.7.0 
  2163. */ 
  2164. public function users_table_filter_by_type( $query ) { 
  2165. global $pagenow; 
  2166.  
  2167. if ( is_admin() && 'users.php' === $pagenow && ! empty( $_REQUEST['bp-member-type'] ) ) { 
  2168. $type_slug = sanitize_text_field( $_REQUEST['bp-member-type'] ); 
  2169.  
  2170. // Check that the type is registered. 
  2171. if ( null == bp_get_member_type_object( $type_slug ) ) { 
  2172. return; 
  2173.  
  2174. // Get the list of users that are assigned to this member type. 
  2175. $type = bp_get_term_by( 'slug', $type_slug, bp_get_member_type_tax_name() ); 
  2176.  
  2177. if ( empty( $type->term_id ) ) { 
  2178. return; 
  2179.  
  2180. $user_ids = bp_get_objects_in_term( $type->term_id, bp_get_member_type_tax_name() ); 
  2181.  
  2182. if ( $user_ids && ! is_wp_error( $user_ids ) ) { 
  2183. $query->set( 'include', (array) $user_ids ); 
  2184.  
  2185. /** 
  2186. * Formats a signup's xprofile field data for display. 
  2187. * 
  2188. * Operates recursively on arrays, which are then imploded with commas. 
  2189. * 
  2190. * @since 2.8.0 
  2191. * 
  2192. * @param string|array $value Field value. 
  2193. * @return string 
  2194. */ 
  2195. protected function format_xprofile_field_for_display( $value ) { 
  2196. if ( is_array( $value ) ) { 
  2197. $value = array_map( array( $this, 'format_xprofile_field_for_display' ), $value ); 
  2198. $value = implode( ', ', $value ); 
  2199. } else { 
  2200. $value = stripslashes( $value ); 
  2201. $value = esc_html( $value ); 
  2202.  
  2203. return $value; 
  2204. endif; // End class_exists check. 
.