PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.1
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / pages / page-mainwp-user.php

page-mainwp-user.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.1, at pages/page-mainwp-user.php

2,495 lines 121.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Users Page
4 *
5 * This page is used to Manage Users on child sites.
6 *
7 * @package MainWP/User
8 */
9
10 namespace MainWP\Dashboard;
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Class MainWP_User
19 *
20 * @uses page-mainwp-bulk-add::MainWP_Bulk_Add()
21 */
22 class MainWP_User { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
23
24 /**
25 * Get Class Name
26 *
27 * @return string __CLASS__
28 */
29 public static function get_class_name() {
30 return __CLASS__;
31 }
32
33 /**
34 * Public static varable to hold Subpages information.
35 *
36 * @var array $subPages
37 */
38 public static $subPages;
39
40 /**
41 * Method init()
42 *
43 * Initiate hooks for the users page.
44 */
45 public static function init() {
46 /**
47 * This hook allows you to render the User page header via the 'mainwp-pageheader-user' action.
48 *
49 * @link http://codex.mainwp.com/#mainwp-pageheader-user
50 *
51 * This hook is normally used in the same context of 'mainwp-getsubpages-user'
52 * @link http://codex.mainwp.com/#mainwp-getsubpages-user
53 *
54 * @see \MainWP_User::render_header
55 */
56 add_action( 'mainwp-pageheader-user', array( static::get_class_name(), 'render_header' ) );
57
58 /**
59 * This hook allows you to render the User page footer via the 'mainwp-pagefooter-user' action.
60 *
61 * @link http://codex.mainwp.com/#mainwp-pagefooter-user
62 *
63 * This hook is normally used in the same context of 'mainwp-getsubpages-user'
64 * @link http://codex.mainwp.com/#mainwp-getsubpages-user
65 *
66 * @see \MainWP_User::render_footer
67 */
68 add_action( 'mainwp-pagefooter-user', array( static::get_class_name(), 'render_footer' ) );
69
70 add_action( 'mainwp_help_sidebar_content', array( static::get_class_name(), 'mainwp_help_content' ) );
71 }
72
73 /**
74 * Method init_menu()
75 *
76 * Initiate menu.
77 *
78 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
79 */
80 public static function init_menu() {
81 $_page = add_submenu_page(
82 'mainwp_tab',
83 __( 'Users', 'mainwp' ),
84 '<span id="mainwp-Users">' . esc_html__( 'Users', 'mainwp' ) . '</span>',
85 'read',
86 'UserBulkManage',
87 array(
88 static::get_class_name(),
89 'render',
90 )
91 );
92
93 add_action( 'load-' . $_page, array( static::get_class_name(), 'on_load_page' ) );
94
95 add_submenu_page(
96 'mainwp_tab',
97 __( 'Users', 'mainwp' ),
98 '<div class="mainwp-hidden">' . esc_html__( 'Add New', 'mainwp' ) . '</div>',
99 'read',
100 'UserBulkAdd',
101 array(
102 static::get_class_name(),
103 'render_bulk_add',
104 )
105 );
106
107 add_submenu_page(
108 'mainwp_tab',
109 __( 'Import Users', 'mainwp' ),
110 '<div class="mainwp-hidden">' . esc_html__( 'Import Users', 'mainwp' ) . '</div>',
111 'read',
112 'BulkImportUsers',
113 array(
114 static::get_class_name(),
115 'render_bulk_import_users',
116 )
117 );
118
119 /**
120 * This hook allows you to add extra sub pages to the User page via the 'mainwp-getsubpages-user' filter.
121 *
122 * @link http://codex.mainwp.com/#mainwp-getsubpages-user
123 */
124 $sub_pages = apply_filters_deprecated( 'mainwp-getsubpages-user', array( array() ), '4.0.7.2', 'mainwp_getsubpages_user' ); // @deprecated Use 'mainwp_getsubpages_user' instead. NOSONAR - not IP.
125 static::$subPages = apply_filters( 'mainwp_getsubpages_user', $sub_pages );
126
127 if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
128 foreach ( static::$subPages as $subPage ) {
129 if ( MainWP_Menu::is_disable_menu_item( 3, 'UserBulk' . $subPage['slug'] ) ) {
130 continue;
131 }
132 add_submenu_page( 'mainwp_tab', $subPage['title'], '<div class="mainwp-hidden">' . esc_html( $subPage['title'] ) . '</div>', 'read', 'UserBulk' . $subPage['slug'], $subPage['callback'] );
133 }
134 }
135
136 static::init_left_menu( static::$subPages );
137 }
138
139 /**
140 * Initiates sub pages menu.
141 *
142 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
143 */
144 public static function init_subpages_menu() {
145 ?>
146 <div id="menu-mainwp-Users" class="mainwp-submenu-wrapper">
147 <div class="wp-submenu sub-open" style="">
148 <div class="mainwp_boxout">
149 <div class="mainwp_boxoutin"></div>
150 <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_users' ) ) { ?>
151 <a href="<?php echo esc_url( admin_url( 'admin.php?page=UserBulkManage' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Manage Users', 'mainwp' ); ?></a>
152 <?php } ?>
153 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'UserBulkAdd' ) ) { ?>
154 <a href="<?php echo esc_url( admin_url( 'admin.php?page=UserBulkAdd' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Add New', 'mainwp' ); ?></a>
155 <?php } ?>
156 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'BulkImportUsers' ) ) { ?>
157 <a href="<?php echo esc_url( admin_url( 'admin.php?page=BulkImportUsers' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Import Users', 'mainwp' ); ?></a>
158 <?php } ?>
159 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'UpdateAdminPasswords' ) ) { ?>
160 <a href="<?php echo esc_url( admin_url( 'admin.php?page=UpdateAdminPasswords' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Admin Passwords', 'mainwp' ); ?></a>
161 <?php } ?>
162 <?php if ( ! MainWP_Menu::is_disable_menu_item( 3, 'PasswordPolicy' ) ) { ?>
163 <a href="<?php echo esc_url( admin_url( 'admin.php?page=PasswordPolicy' ) ); ?>" class="mainwp-submenu"><?php esc_html_e( 'Password Policy', 'mainwp' ); ?></a>
164 <?php } ?>
165 <?php
166 if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
167 foreach ( static::$subPages as $subPage ) {
168 if ( MainWP_Menu::is_disable_menu_item( 3, 'UserBulk' . $subPage['slug'] ) ) {
169 continue;
170 }
171 ?>
172 <a href="<?php echo esc_url( admin_url( 'admin.php?page=UserBulk' . $subPage['slug'] ) ); ?>" class="mainwp-submenu"><?php echo esc_html( $subPage['title'] ); ?></a>
173 <?php
174 }
175 }
176 ?>
177 </div>
178 </div>
179 </div>
180 <?php
181 }
182
183 /**
184 * Method get_manage_columns()
185 *
186 * Get columns to display.
187 *
188 * @return array $colums Array of columns to display on the page.
189 *
190 * @uses \MainWP\Dashboard\MainWP_Utility::enabled_wp_seo()
191 */
192 public static function get_manage_columns() {
193 return array(
194 'name' => esc_html__( 'Name', 'mainwp' ),
195 'username' => esc_html__( 'Username', 'mainwp' ),
196 'email' => esc_html__( 'E-mail', 'mainwp' ),
197 'last_password_change' => esc_html__( 'Last Password Change', 'mainwp' ),
198 'password_status' => esc_html__( 'Password Status', 'mainwp' ),
199 'role' => esc_html__( 'Role', 'mainwp' ),
200 'posts' => esc_html__( 'Posts', 'mainwp' ),
201 'website' => esc_html__( 'Website', 'mainwp' ),
202 );
203 }
204
205 /**
206 * Method on_load_page()
207 *
208 * Used during init_menu() to get the class names of,
209 * admin_head and get_hidden_columns.
210 *
211 * @return void
212 */
213 public static function on_load_page() {
214 add_action( 'mainwp_screen_options_modal_bottom', array( static::get_class_name(), 'hook_screen_options_modal_bottom' ), 10, 2 );
215 }
216
217 /**
218 * Method hook_screen_options_modal_bottom()
219 *
220 * Render screen options modal bottom.
221 */
222 public static function hook_screen_options_modal_bottom() {
223 $page = isset( $_GET['page'] ) ? wp_unslash( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
224 if ( 'UserBulkManage' === $page ) {
225
226 $show_columns = get_user_option( 'mainwp_manageusers_show_columns' );
227
228 if ( ! is_array( $show_columns ) ) {
229 $show_columns = array();
230 }
231
232 $cols = static::get_manage_columns();
233 MainWP_UI::render_showhide_columns_settings( $cols, $show_columns, 'user' );
234 }
235 }
236
237 /**
238 * Initiates Users menu.
239 *
240 * @param array $subPages Sub pages array.
241 *
242 * @uses \MainWP\Dashboard\MainWP_Menu::add_left_menu()
243 * @uses \MainWP\Dashboard\MainWP_Menu::init_subpages_left_menu()
244 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
245 */
246 public static function init_left_menu( $subPages = array() ) {
247 MainWP_Menu::add_left_menu(
248 array(
249 'title' => esc_html__( 'Users', 'mainwp' ),
250 'parent_key' => 'managesites',
251 'slug' => 'UserBulkManage',
252 'href' => 'admin.php?page=UserBulkManage',
253 'icon' => '<i class="user icon"></i>',
254 'desc' => 'Manage users on your child sites',
255 'leftsub_order' => 7,
256 ),
257 1
258 );
259
260 $init_sub_subleftmenu = array(
261 array(
262 'title' => esc_html__( 'Manage Users', 'mainwp' ),
263 'parent_key' => 'UserBulkManage',
264 'href' => 'admin.php?page=UserBulkManage',
265 'slug' => 'UserBulkManage',
266 'right' => 'manage_users',
267 ),
268 array(
269 'title' => esc_html__( 'Add New', 'mainwp' ),
270 'parent_key' => 'UserBulkManage',
271 'href' => 'admin.php?page=UserBulkAdd',
272 'slug' => 'UserBulkAdd',
273 'right' => '',
274 ),
275 array(
276 'title' => esc_html__( 'Import Users', 'mainwp' ),
277 'parent_key' => 'UserBulkManage',
278 'href' => 'admin.php?page=BulkImportUsers',
279 'slug' => 'BulkImportUsers',
280 'right' => '',
281 ),
282 array(
283 'title' => esc_html__( 'Admin Passwords', 'mainwp' ),
284 'parent_key' => 'UserBulkManage',
285 'href' => 'admin.php?page=UpdateAdminPasswords',
286 'slug' => 'UpdateAdminPasswords',
287 'right' => '',
288 ),
289 array(
290 'title' => esc_html__( 'Password Policy', 'mainwp' ),
291 'parent_key' => 'UserBulkManage',
292 'href' => 'admin.php?page=PasswordPolicy',
293 'slug' => 'PasswordPolicy',
294 'right' => '',
295 ),
296 );
297
298 MainWP_Menu::init_subpages_left_menu( $subPages, $init_sub_subleftmenu, 'UserBulkManage', 'UserBulk' );
299
300 foreach ( $init_sub_subleftmenu as $item ) {
301 if ( MainWP_Menu::is_disable_menu_item( 3, $item['slug'] ) ) {
302 continue;
303 }
304 MainWP_Menu::add_left_menu( $item, 2 );
305 }
306 }
307
308 /**
309 * Method render_header()
310 *
311 * Render Users page header.
312 *
313 * @param string $shownPage The page slug shown at this moment.
314 *
315 * @uses \MainWP\Dashboard\MainWP_Menu::is_disable_menu_item()
316 * @uses \MainWP\Dashboard\MainWP_UI::render_top_header()
317 * @uses \MainWP\Dashboard\MainWP_UI::render_page_navigation()
318 */
319 public static function render_header( $shownPage = '' ) { //phpcs:ignore -- NOSONAR - complex.
320 $params = array(
321 'title' => esc_html__( 'Users', 'mainwp' ),
322 );
323 MainWP_UI::render_top_header( $params );
324
325 $renderItems = array();
326
327 if ( \mainwp_current_user_can( 'dashboard', 'manage_users' ) ) {
328 $renderItems[] = array(
329 'title' => esc_html__( 'Manage Users', 'mainwp' ),
330 'href' => 'admin.php?page=UserBulkManage',
331 'active' => ( '' === $shownPage ) ? true : false,
332 );
333 }
334
335 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'UserBulkAdd' ) ) {
336 $renderItems[] = array(
337 'title' => esc_html__( 'Add New', 'mainwp' ),
338 'href' => 'admin.php?page=UserBulkAdd',
339 'active' => ( 'Add' === $shownPage ) ? true : false,
340 );
341 }
342
343 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'BulkImportUsers' ) ) {
344 $renderItems[] = array(
345 'title' => esc_html__( 'Import Users', 'mainwp' ),
346 'href' => 'admin.php?page=BulkImportUsers',
347 'active' => ( 'Import' === $shownPage ) ? true : false,
348 );
349 }
350
351 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'UpdateAdminPasswords' ) ) {
352 $renderItems[] = array(
353 'title' => esc_html__( 'Admin Passwords', 'mainwp' ),
354 'href' => 'admin.php?page=UpdateAdminPasswords',
355 'active' => ( 'UpdateAdminPasswords' === $shownPage ) ? true : false,
356 );
357 }
358
359 if ( ! MainWP_Menu::is_disable_menu_item( 3, 'PasswordPolicy' ) ) {
360 $renderItems[] = array(
361 'title' => esc_html__( 'Password Policy', 'mainwp' ),
362 'href' => 'admin.php?page=PasswordPolicy',
363 'active' => ( 'PasswordPolicy' === $shownPage ) ? true : false,
364 );
365 }
366
367 if ( isset( static::$subPages ) && is_array( static::$subPages ) ) {
368 foreach ( static::$subPages as $subPage ) {
369 if ( MainWP_Menu::is_disable_menu_item( 3, 'UserBulk' . $subPage['slug'] ) ) {
370 continue;
371 }
372
373 $item = array();
374 $item['title'] = $subPage['title'];
375 $item['href'] = 'admin.php?page=UserBulk' . $subPage['slug'];
376 $item['active'] = ( $subPage['slug'] === $shownPage ) ? true : false;
377 $renderItems[] = $item;
378 }
379 }
380
381 MainWP_UI::render_page_navigation( $renderItems );
382 }
383
384 /**
385 * Method render_footer()
386 *
387 * Render Users page footer. Closes the page container.
388 */
389 public static function render_footer() {
390 echo '</div>';
391 }
392
393 /**
394 * Renders manage users dashboard.
395 *
396 * @return void
397 *
398 * @uses \MainWP\Dashboard\MainWP_Cache::get_cached_context()
399 */
400 public static function render() {
401 if ( ! \mainwp_current_user_can( 'dashboard', 'manage_users' ) ) {
402 \mainwp_do_not_have_permissions( esc_html__( 'manage users', 'mainwp' ) );
403
404 return;
405 }
406
407 $cachedSearch = MainWP_Cache::get_cached_context( 'Users' );
408
409 $selected_sites = array();
410 $selected_groups = array();
411 $selected_clients = array();
412
413 if ( null !== $cachedSearch ) {
414 if ( is_array( $cachedSearch['sites'] ) ) {
415 $selected_sites = $cachedSearch['sites'];
416 } elseif ( is_array( $cachedSearch['groups'] ) ) {
417 $selected_groups = $cachedSearch['groups'];
418 } elseif ( is_array( $cachedSearch['clients'] ) ) {
419 $selected_clients = $cachedSearch['clients'];
420 }
421 }
422
423 static::render_header( '' );
424 ?>
425 <div id="mainwp-manage-users">
426 <div class="mainwp-main-content">
427 <div class="mainwp-actions-bar ui mini form">
428 <div class="ui grid">
429 <div class="ui two column row">
430 <div class="column">
431 <select class="ui mini dropdown disabled" id="mainwp-bulk-actions">
432 <option value=""><?php esc_html_e( 'Bulk Actions', 'mainwp' ); ?></option>
433 <option value="edit"><?php esc_html_e( 'Edit', 'mainwp' ); ?></option>
434 <option value="delete"><?php esc_html_e( 'Delete', 'mainwp' ); ?></option>
435 <?php
436 /**
437 * Action: mainwp_users_bulk_action
438 *
439 * Adds new Bulk Actions option under on Manage Users.
440 *
441 * Suggested HTML Markup:
442 * <option value="Your custom value">Your custom label</option>
443 *
444 * @since 4.1
445 */
446 do_action( 'mainwp_users_bulk_action' );
447 ?>
448 </select>
449 <button class="ui mini button disabled" id="mainwp-do-users-bulk-actions"><?php esc_html_e( 'Apply', 'mainwp' ); ?></button>
450 <?php
451 /**
452 * Users actions bar (left)
453 *
454 * Fires at the left side of the actions bar on the Users screen, after the Bulk Actions menu.
455 *
456 * @since 4.0
457 */
458 do_action( 'mainwp_users_actions_bar_left' );
459 ?>
460 </div>
461 <div class="right aligned column">
462 <?php
463 /**
464 * Users actions bar (right)
465 *
466 * Fires at the right side of the actions bar on the Users screen.
467 *
468 * @since 4.0
469 */
470 do_action( 'mainwp_users_actions_bar_right' );
471 ?>
472 </div>
473 </div>
474 </div>
475 </div>
476 <div id="mainwp-loading-users-row" style="display: none;">
477 <div class="ui active page dimmer">
478 <div class="ui double text loader">
479 <?php esc_html_e( 'Loading...', 'mainwp' ); ?>
480 <span id="mainwp_users_loading_info" class="mainwp-grabbing-info-note"><br /><?php esc_html_e( 'Automatically refreshing to get up to date information.', 'mainwp' ); ?></span>
481 </div>
482 </div>
483 </div>
484 <div class="ui padded segment" id="mainwp_users_wrap_table">
485 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-manage-users-info-message' ) ) : ?>
486 <div class="ui info message">
487 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-manage-users-info-message"></i>
488 <?php /* translators: 1: opening anchor tag, 2: closing anchor tag */ printf( esc_html__( 'Manage existing users on your child sites. Here you can Delete, Edit or Change Role for existing users. For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/sites/users/manage-users/" target="_blank">', '</a>' ); ?>
489 </div>
490 <?php endif; ?>
491 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-password-policy-feature-info-message' ) ) : ?>
492 <div class="ui info message">
493 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-password-policy-feature-info-message"></i>
494 <div><?php esc_html_e( 'MainWP shows the Last password change and Status for each user. WordPress doesn\'t store a reliable password-change date by default, so tracking starts after this version of MainWP Child is installed/updated. Until a user changes their password, the date may appear as Unknown.', 'mainwp' ); ?></div><br/>
495 <div><?php esc_html_e( 'If your password policy is set to Never, MainWP will still record password changes, but no due/overdue notices are shown and status may remain OK/Disabled. When a policy is enabled, users with an Unknown date can still become Due/Overdue based on no password change recorded since the policy was enabled.', 'mainwp' ); ?></div>
496 </div>
497 <?php endif; ?>
498 <div class="ui message" id="mainwp-message-zone" style="display:none"></div>
499 <?php static::render_table( true ); ?>
500 </div>
501 <div id="mainwp-update-users-box" class="ui segment">
502 <?php static::render_update_users(); ?>
503 </div>
504 </div>
505 <div class="mainwp-side-content mainwp-no-padding">
506 <?php
507 /**
508 * Action: mainwp_manage_users_sidebar_top
509 *
510 * Fires on top of the sidebar on Manage Users page.
511 *
512 * @since 4.1
513 */
514 do_action( 'mainwp_manage_users_sidebar_top' );
515 ?>
516 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
517 <?php
518 /**
519 * Action: mainwp_manage_users_before_select_sites
520 *
521 * Fires before the Select Sites section on Manage Users page.
522 *
523 * @since 4.1
524 */
525 do_action( 'mainwp_manage_users_before_select_sites' );
526 ?>
527 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Sites', 'mainwp' ); ?></div>
528 <div class="content active">
529 <?php
530 $sel_params = array(
531 'selected_sites' => $selected_sites,
532 'selected_groups' => $selected_groups,
533 'selected_clients' => $selected_clients,
534 'class' => 'mainwp_select_sites_box_left',
535 'show_client' => true,
536 );
537 MainWP_UI_Select_Sites::select_sites_box( $sel_params );
538 ?>
539 </div>
540 <?php
541 /**
542 * Action: mainwp_manage_users_after_select_sites
543 *
544 * Fires after the Select Sites section on Manage Users page.
545 *
546 * @since 4.1
547 */
548 do_action( 'mainwp_manage_users_after_select_sites' );
549 ?>
550 </div>
551
552 <?php
553 $user_roles = array(
554 'subscriber' => esc_html__( 'Subscriber', 'mainwp' ),
555 'administrator' => esc_html__( 'Administrator', 'mainwp' ),
556 'editor' => esc_html__( 'Editor', 'mainwp' ),
557 'author' => esc_html__( 'Author', 'mainwp' ),
558 'contributor' => esc_html__( 'Contributor', 'mainwp' ),
559 );
560
561 $user_roles = apply_filters_deprecated( 'mainwp-users-manage-roles', array( $user_roles ), '4.0.7.2', 'mainwp_users_manage_roles' ); // @deprecated Use 'mainwp_users_manage_roles' instead. NOSONAR - not IP.
562 $user_roles = apply_filters( 'mainwp_users_manage_roles', $user_roles );
563
564 ?>
565
566 <div class="ui fitted divider"></div>
567 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
568 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Roles', 'mainwp' ); ?></div>
569 <div class="content active">
570 <?php
571 /**
572 * Action: mainwp_manage_users_before_search_options
573 *
574 * Fires before the Search Options section on Manage Users page.
575 *
576 * @since 4.1
577 */
578 do_action( 'mainwp_manage_users_before_search_options' );
579 ?>
580 <div class="ui mini form">
581 <div class="field">
582 <select multiple="" class="ui fluid mini dropdown" id="mainwp_user_roles">
583 <option value=""><?php esc_html_e( 'Select wanted role(s)', 'mainwp' ); ?></option>
584 <?php
585 foreach ( $user_roles as $r => $n ) {
586 if ( empty( $r ) ) {
587 continue;
588 }
589 ?>
590 <option value="<?php echo esc_html( $r ); ?>"><?php echo esc_html( $n ); ?></option>
591 <?php
592 }
593 ?>
594 </select>
595 </div>
596 </div>
597 <?php
598 /**
599 * Action: mainwp_manage_users_after_search_options
600 *
601 * Fires after the Search Options section on Manage Users page.
602 *
603 * @since 4.1
604 */
605 do_action( 'mainwp_manage_users_after_search_options' );
606 ?>
607 </div>
608 </div>
609 <div class="ui fitted divider"></div>
610 <div class="mainwp-search-options ui accordion mainwp-sidebar-accordion">
611 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Search Options', 'mainwp' ); ?></div>
612 <div class="content active"><?php static::render_search_options(); ?></div>
613 </div>
614 <div class="ui fitted divider"></div>
615 <div class="mainwp-search-submit">
616 <?php
617 /**
618 * Action: mainwp_manage_users_before_submit_button
619 *
620 * Fires before the Submit Button on Manage Users page.
621 *
622 * @since 4.1
623 */
624 do_action( 'mainwp_manage_users_before_submit_button' );
625 ?>
626 <input type="button" name="mainwp_show_users" id="mainwp_show_users" class="ui green big fluid button" value="<?php esc_attr_e( 'Show Users', 'mainwp' ); ?>"/>
627 <?php
628 /**
629 * Action: mainwp_manage_users_after_submit_button
630 *
631 * Fires after the Submit Button on Manage Users page.
632 *
633 * @since 4.1
634 */
635 do_action( 'mainwp_manage_users_after_submit_button' );
636 ?>
637 </div>
638 <?php
639 /**
640 * Action: mainwp_manage_users_sidebar_bottom
641 *
642 * Fires at the bottom of the sidebar on Manage Users page.
643 *
644 * @since 4.1
645 */
646 do_action( 'mainwp_manage_users_sidebar_bottom' );
647 ?>
648 </div>
649 <div class="ui hidden clearing divider"></div>
650 </div>
651 <?php
652 static::render_footer( '' );
653 }
654
655 /**
656 * Method render_search_options()
657 *
658 * Render User page search.
659 *
660 * @uses \MainWP\Dashboard\MainWP_Cache::get_cached_context()
661 */
662 public static function render_search_options() {
663 $cachedSearch = MainWP_Cache::get_cached_context( 'Users' );
664 $statuses = isset( $cachedSearch['status'] ) ? $cachedSearch['status'] : array();
665 if ( $cachedSearch && isset( $cachedSearch['keyword'] ) ) {
666 $cachedSearch['keyword'] = trim( $cachedSearch['keyword'] );
667 }
668 ?>
669
670 <div class="ui mini form">
671 <div class="field">
672 <div class="ui input fluid">
673 <input type="text" placeholder="<?php esc_attr_e( 'Username', 'mainwp' ); ?>" id="mainwp_search_users" class="text" value="<?php echo ( null !== $cachedSearch ) ? esc_attr( $cachedSearch['keyword'] ) : ''; ?>" />
674 </div>
675 </div>
676 </div>
677 <?php
678 if ( is_array( $statuses ) && ! empty( $statuses ) ) {
679 $status = '';
680 foreach ( $statuses as $st ) {
681 $status .= "'" . esc_html( $st ) . "',";
682 }
683 $status = rtrim( $status, ',' );
684 ?>
685 <script type="text/javascript">
686 jQuery( document ).ready( function () {
687 jQuery( '#mainwp_user_roles' ).dropdown( 'set selected', [<?php echo $status; //phpcs:ignore -- safe output. ?>] );
688 } );
689 </script>
690 <?php
691 }
692 }
693
694 /**
695 * Renders Edit Users Modal window.
696 */
697 public static function render_update_users() {
698
699 $editable_roles = array(
700 'donotupdate' => esc_html__( 'Do not update', 'mainwp' ),
701 'administrator' => esc_html__( 'Administrator', 'mainwp' ),
702 'subscriber' => esc_html__( 'Subscriber', 'mainwp' ),
703 'contributor' => esc_html__( 'Contributor', 'mainwp' ),
704 'author' => esc_html__( 'Author', 'mainwp' ),
705 'editor' => esc_html__( 'Editor', 'mainwp' ),
706 );
707
708 $editable_roles = apply_filters_deprecated( 'mainwp-users-manage-roles', array( $editable_roles ), '4.0.7.2', 'mainwp_users_manage_roles' ); // @deprecated Use 'mainwp_users_manage_roles' instead. NOSONAR - not IP.
709 $editable_roles = apply_filters( 'mainwp_users_manage_roles', $editable_roles );
710
711 $editable_roles[''] = esc_html__( '&mdash; No role for this site &mdash;', 'mainwp' );
712
713 ?>
714 <div id="mainwp-edit-users-modal" class="ui modal">
715 <i class="close icon"></i>
716 <div class="header"><?php esc_html_e( 'Edit User', 'mainwp' ); ?></div>
717 <div class="scrolling content">
718 <div class="ui info message"><?php esc_html_e( 'Empty fields will not be passed to child sites.', 'mainwp' ); ?></div>
719 <form id="update_user_profile" class="ui form">
720 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
721
722 <h3 class="ui header"><?php esc_html_e( 'Name', 'mainwp' ); ?></h3>
723
724 <div class="ui grid field">
725 <label class="six wide column middle aligned"><?php esc_html_e( 'Role', 'mainwp' ); ?></label>
726 <div class="ui six wide column">
727 <select name="role" id="role" class="ui selection dropdown">
728 <?php
729 foreach ( $editable_roles as $role_id => $role_name ) {
730 echo '<option value="' . esc_attr( $role_id ) . '" ' . ( 'donotupdate' === $role_id ? 'selected="selected"' : '' ) . '>' . esc_html( $role_name ) . '</option>';
731 }
732 ?>
733 </select>
734 </div>
735 </div>
736
737 <div class="ui grid field">
738 <label class="six wide column middle aligned"><?php esc_html_e( 'First Name', 'mainwp' ); ?></label>
739 <div class="ui six wide column">
740 <div class="ui input">
741 <input type="text" name="first_name" id="first_name" value="" />
742 </div>
743 </div>
744 </div>
745
746 <div class="ui grid field">
747 <label class="six wide column middle aligned"><?php esc_html_e( 'Last Name', 'mainwp' ); ?></label>
748 <div class="ui six wide column">
749 <div class="ui input">
750 <input type="text" name="last_name" id="last_name" value="" />
751 </div>
752 </div>
753 </div>
754
755 <div class="ui grid field">
756 <label class="six wide column middle aligned"><?php esc_html_e( 'Nickname', 'mainwp' ); ?></label>
757 <div class="ui six wide column">
758 <div class="ui input">
759 <input type="text" name="nickname" id="nickname" value="" />
760 </div>
761 </div>
762 </div>
763
764 <div class="ui grid field">
765 <label class="six wide column middle aligned"><?php esc_html_e( 'Display name publicly as', 'mainwp' ); ?></label>
766 <div class="ui six wide column">
767 <div class="ui input">
768 <select name="display_name" id="display_name" class="ui selection dropdown"></select>
769 </div>
770 </div>
771 </div>
772
773 <h3 class="ui header"><?php esc_html_e( 'Contact Info', 'mainwp' ); ?></h3>
774
775 <div class="ui grid field">
776 <label class="six wide column middle aligned"><?php esc_html_e( 'Email', 'mainwp' ); ?></label>
777 <div class="ui six wide column">
778 <div class="ui input">
779 <input type="email" name="email" id="email" value="" />
780 </div>
781 </div>
782 </div>
783
784 <div class="ui grid field">
785 <label class="six wide column middle aligned"><?php esc_html_e( 'Website', 'mainwp' ); ?></label>
786 <div class="ui six wide column">
787 <div class="ui input">
788 <input type="url" name="url" id="url" value="" />
789 </div>
790 </div>
791 </div>
792
793 <h3 class="ui header"><?php esc_html_e( 'About the user', 'mainwp' ); ?></h3>
794
795 <div class="ui grid field">
796 <label class="six wide column middle aligned"><?php esc_html_e( 'Biographical Info', 'mainwp' ); ?></label>
797 <div class="ui six wide column">
798 <div class="ui input">
799 <textarea name="description" id="description" rows="5" cols="30" style="width:100%"></textarea>
800 </div>
801 </div>
802 </div>
803
804 <h3 class="ui header"><?php esc_html_e( 'Account Management', 'mainwp' ); ?></h3>
805
806 <div class="ui grid field">
807 <label class="six wide column middle aligned"><?php esc_html_e( 'Password', 'mainwp' ); ?></label>
808 <div class="ui six wide column">
809 <div class="ui action input">
810 <input class="hidden" value=" "/>
811 <input type="text" id="password" name="password" autocomplete="off" value="">
812 </div>
813 </div>
814 </div>
815
816 </form>
817 </div>
818
819 <div class="actions">
820 <div id="mainwp_update_password_error" style="display: none"></div>
821 <span id="mainwp_users_updating"><i class="ui active inline loader tiny"></i></span>
822 <input type="button" class="ui green button" id="mainwp_btn_update_user" value="<?php esc_attr_e( 'Update', 'mainwp' ); ?>">
823 </div>
824 </div>
825 <?php
826 }
827
828 /**
829 * Renders Users Table.
830 *
831 * @param bool $cached true|false Cached or not.
832 * @param string $role Current user role.
833 * @param string $groups Current user groups.
834 * @param string $sites Current Child Sites the user is on.
835 * @param null $search Search field.
836 * @param mixed $clients Current Clients's Sites the user is on.
837 *
838 * @uses \MainWP\Dashboard\MainWP_Cache::echo_body()
839 */
840 public static function render_table( $cached = true, $role = '', $groups = '', $sites = '', $search = null, $clients = '' ) {
841
842 $has_cached_results = $cached && isset( $_SESSION['MainWPUsersSearch'] ) && ! empty( $_SESSION['MainWPUsersSearch'] );
843
844 /**
845 * Action: mainwp_before_users_table
846 *
847 * Fires before the User table.
848 *
849 * @since 4.1
850 */
851 do_action( 'mainwp_before_users_table' );
852
853 if ( ! $cached || $has_cached_results ) {
854 ?>
855 <table id="mainwp-users-table" class="ui unstackable single line table" style="width:100%">
856 <thead>
857 <tr>
858 <th class="no-sort collapsing check-column"><span class="ui checkbox"><input id="cb-select-all-top" type="checkbox" /></span></th>
859 <?php do_action( 'mainwp_users_table_header' ); ?>
860 <th id="name"><?php esc_html_e( 'Name', 'mainwp' ); ?></th>
861 <th id="username"><?php esc_html_e( 'Username', 'mainwp' ); ?></th>
862 <th id="email"><?php esc_html_e( 'E-mail', 'mainwp' ); ?></th>
863 <th id="last_password_change" class="right aligned"><?php esc_html_e( 'Last Password Change', 'mainwp' ); ?></th>
864 <th id="password_status" class="center aligned"><?php esc_html_e( 'Password Status', 'mainwp' ); ?></th>
865 <th id="role"><?php esc_html_e( 'Role', 'mainwp' ); ?></th>
866 <th id="posts"><?php esc_html_e( 'Posts', 'mainwp' ); ?></th>
867 <th id="website"><?php esc_html_e( 'Website', 'mainwp' ); ?></th>
868 <th id="mainwp-users-actions" class="no-sort collapsing"></th>
869 </tr>
870 </thead>
871 <tbody id="mainwp-users-list">
872 <?php
873 if ( $cached ) {
874 MainWP_Cache::echo_body( 'Users' );
875 } else {
876 MainWP_Cache::init_cache( 'Users' );
877 static::render_table_body( $role, $groups, $sites, $search, $clients );
878 }
879 ?>
880 </tbody>
881 </table>
882 <?php
883 } else {
884 MainWP_UI::render_empty_page_placeholder(
885 esc_html__( 'Find Users', 'mainwp' ),
886 esc_html__( 'Select the Child Sites you want, choose any filters, then click Show Users.', 'mainwp' ),
887 '<em data-emoji=":busts_in_silhouette:" class="big"></em>'
888 );
889 }
890 /**
891 * Action: mainwp_after_users_table
892 *
893 * Fires after the User table.
894 *
895 * @since 4.1
896 */
897 do_action( 'mainwp_after_users_table' );
898
899 /**
900 * Filter: mainwp_users_table_fatures
901 *
902 * Filters the Manage Users table features.
903 *
904 * @since 4.1
905 */
906 $table_features = array(
907 'searching' => 'true',
908 'paging' => 'true',
909 'info' => 'true',
910 'stateSave' => 'true',
911 'scrollX' => 'true',
912 'responsive' => 'true',
913 'colReorder' => '{columns:":not(.check-column):not(:last-child)"}',
914 'order' => '[]',
915 );
916 $table_features = apply_filters( 'mainwp_users_table_fatures', $table_features );
917 ?>
918 <script type="text/javascript">
919 if (typeof responsive === 'undefined') {
920 let responsive = false; // to fix redeclaration for ajax request.
921 }
922 responsive = <?php echo esc_html( $table_features['responsive'] ); ?>;
923 if( jQuery( window ).width() > 1140 ) {
924 responsive = false;
925 }
926 jQuery( document ).ready( function () {
927 try {
928 jQuery( "#mainwp-users-table" ).DataTable().destroy(); // to fix re-init database issue.
929 $manage_users_table = jQuery( "#mainwp-users-table" ).DataTable( {
930 "responsive" : responsive,
931 "searching" : <?php echo esc_html( $table_features['searching'] ); ?>,
932 "colReorder" : <?php echo $table_features['colReorder']; // phpcs:ignore -- specical chars. ?>,
933 "stateSave": <?php echo esc_html( $table_features['stateSave'] ); ?>,
934 "paging": <?php echo esc_html( $table_features['paging'] ); ?>,
935 "info": <?php echo esc_html( $table_features['info'] ); ?>,
936 "order": <?php echo esc_html( $table_features['order'] ); ?>,
937 "scrollX" : <?php echo esc_html( $table_features['scrollX'] ); ?>,
938 "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
939 "language" : { "emptyTable": "<?php esc_html_e( 'Please use the search options to find wanted users.', 'mainwp' ); ?>" },
940 "columnDefs": [
941 {
942 "targets": 'no-sort',
943 "orderable": false
944 },
945 {
946 "targets": '#last_password_change',
947 "type": 'string'
948 },
949 {
950 "targets": '#password_status',
951 "type": 'string'
952 }
953 ],
954 "drawCallback": function() {
955 setTimeout(() => {
956 jQuery('#mainwp-users-table .ui.dropdown').dropdown();
957 jQuery('#mainwp-users-table .ui.checkbox').checkbox();
958 mainwp_datatable_fix_menu_overflow('#mainwp-users-table');
959 mainwp_table_check_columns_init(); // ajax: to fix checkbox all.
960 updateUsersBulkActionsState();
961 }, 1000);
962 },
963 select: {
964 items: 'row',
965 style: 'multi+shift',
966 selector: 'tr>td:not(.not-selectable)'
967 }
968 } ).on('select', function (e, dt, type, indexes) {
969 if( 'row' == type ){
970 dt.rows(indexes)
971 .nodes()
972 .to$().find('td.check-column .ui.checkbox' ).checkbox('set checked');
973 updateUsersBulkActionsState();
974 }
975 }).on('deselect', function (e, dt, type, indexes) {
976 if( 'row' == type ){
977 dt.rows(indexes)
978 .nodes()
979 .to$().find('td.check-column .ui.checkbox' ).checkbox('set unchecked');
980 updateUsersBulkActionsState();
981 }
982 }).on( 'columns-reordered', function () {
983 setTimeout(() => {
984 jQuery( '#mainwp-users-table .ui.dropdown' ).dropdown();
985 jQuery( '#mainwp-users-table .ui.checkbox' ).checkbox();
986 mainwp_datatable_fix_menu_overflow('#mainwp-users-table');
987 mainwp_table_check_columns_init(); // ajax: to fix checkbox all.
988 }, 1000);
989 });
990 } catch ( err ) {
991 // to fix js error.
992 }
993
994 _init_manage_sites_screen = function() {
995 jQuery( '#mainwp-overview-screen-options-modal input[type=checkbox][id^="mainwp_show_column_"]' ).each( function() {
996 let col_id = jQuery( this ).attr( 'id' );
997 col_id = col_id.replace( "mainwp_show_column_", "" );
998 try {
999 $manage_users_table.column( '#' + col_id ).visible( jQuery(this).is( ':checked' ) );
1000 } catch(err) {
1001 // to fix js error.
1002 }
1003 } );
1004 };
1005 _init_manage_sites_screen();
1006
1007 updateUsersBulkActionsState();
1008
1009 jQuery(document).on('change', '#mainwp-users-table .check-column INPUT:checkbox', function() {
1010 updateUsersBulkActionsState();
1011 });
1012
1013 } );
1014 </script>
1015 <?php
1016 }
1017
1018 /**
1019 * Renders the table body.
1020 *
1021 * @param string $role User Role.
1022 * @param string $groups Usr Group.
1023 * @param string $sites Users Sites.
1024 * @param string $search Search field.
1025 * @param mixed $clients Current Clients's Sites the user is on.
1026 *
1027 * @uses \MainWP\Dashboard\MainWP_Cache::init_cache()
1028 * @uses \MainWP\Dashboard\MainWP_Cache::add_context()
1029 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
1030 * @uses \MainWP\Dashboard\MainWP_DB::query()
1031 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
1032 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_by_group_id()
1033 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
1034 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
1035 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
1036 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
1037 */
1038 public static function render_table_body( $role = '', $groups = '', $sites = '', $search = '', $clients = '' ) { // phpcs:ignore -- NOSONAR - current complexity required to achieve desired results. Pull request solutions appreciated.
1039 $output = new \stdClass();
1040 $output->errors = array();
1041 $output->users = 0;
1042
1043 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
1044 $data_fields[] = 'users';
1045
1046 if ( 1 === (int) get_option( 'mainwp_optimize', 1 ) || MainWP_Demo_Handle::is_demo_mode() ) {
1047
1048 $check_users_role = false;
1049
1050 if ( ! empty( $role ) ) {
1051 $roles = explode( ',', $role );
1052 if ( is_array( $roles ) ) {
1053 $check_users_role = true;
1054 }
1055 }
1056
1057 $dbwebsites = array();
1058 if ( ! empty( $sites ) ) {
1059 foreach ( $sites as $v ) {
1060 if ( MainWP_Utility::ctype_digit( $v ) ) {
1061 $website = MainWP_DB::instance()->get_website_by_id( $v );
1062 if ( empty( $website->sync_errors ) && ! MainWP_System_Utility::is_suspended_site( $website ) ) {
1063 $dbwebsites[ $website->id ] = $website;
1064 }
1065 }
1066 }
1067 }
1068 if ( ! empty( $groups ) ) {
1069 foreach ( $groups as $v ) {
1070 if ( MainWP_Utility::ctype_digit( $v ) ) {
1071 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $v ) );
1072 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
1073 if ( ! empty( $website->sync_errors ) || MainWP_System_Utility::is_suspended_site( $website ) ) {
1074 continue;
1075 }
1076 $dbwebsites[ $website->id ] = $website;
1077 }
1078 MainWP_DB::free_result( $websites );
1079 }
1080 }
1081 }
1082
1083 if ( ! empty( $clients ) && is_array( $clients ) ) {
1084 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
1085 $clients,
1086 array(
1087 'select_data' => $data_fields,
1088 )
1089 );
1090
1091 foreach ( $websites as $website ) {
1092 if ( ! empty( $website->sync_errors ) || MainWP_System_Utility::is_suspended_site( $website ) ) {
1093 continue;
1094 }
1095 $dbwebsites[ $website->id ] = $website;
1096 }
1097 }
1098
1099 if ( $dbwebsites ) {
1100 foreach ( $dbwebsites as $website ) {
1101 $allUsers = json_decode( $website->users, true );
1102 $allUsersCount = count( $allUsers );
1103 $search_user_role = array();
1104 if ( $check_users_role ) {
1105 for ( $i = 0; $i < $allUsersCount; $i++ ) {
1106 $user = $allUsers[ $i ];
1107 foreach ( $roles as $_role ) {
1108 if ( stristr( $user['role'], $_role ) ) {
1109 if ( ! in_array( $user['id'], $search_user_role ) ) {
1110 $search_user_role[] = $user['id'];
1111 }
1112 break;
1113 }
1114 }
1115 }
1116 }
1117 for ( $i = 0; $i < $allUsersCount; $i++ ) {
1118 $user = $allUsers[ $i ];
1119 if ( ! empty( $search ) && ! stristr( $user['login'], trim( $search ) ) && ! stristr( $user['display_name'], trim( $search ) ) && ! stristr( $user['email'], trim( $search ) ) ) {
1120 continue;
1121 }
1122
1123 if ( $check_users_role && ! in_array( $user['id'], $search_user_role ) ) {
1124 continue;
1125 }
1126
1127 $tmpUsers = array( $user );
1128 $output->users += static::users_search_handler_renderer( $tmpUsers, $website );
1129 }
1130 }
1131 }
1132 } else {
1133 $dbwebsites = array();
1134 if ( '' !== $sites ) {
1135 foreach ( $sites as $v ) {
1136 if ( MainWP_Utility::ctype_digit( $v ) ) {
1137 $website = MainWP_DB::instance()->get_website_by_id( $v );
1138 if ( empty( $website->sync_errors ) && ! MainWP_System_Utility::is_suspended_site( $website ) ) {
1139 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
1140 $website,
1141 $data_fields
1142 );
1143 }
1144 }
1145 }
1146 }
1147 if ( '' !== $groups ) {
1148 foreach ( $groups as $v ) {
1149 if ( MainWP_Utility::ctype_digit( $v ) ) {
1150 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $v ) );
1151 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
1152 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
1153 continue;
1154 }
1155 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
1156 $website,
1157 $data_fields
1158 );
1159 }
1160 MainWP_DB::free_result( $websites );
1161 }
1162 }
1163 }
1164
1165 if ( '' !== $clients && is_array( $clients ) ) {
1166 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
1167 $clients,
1168 array(
1169 'select_data' => $data_fields,
1170 )
1171 );
1172 if ( $websites ) {
1173 foreach ( $websites as $website ) {
1174 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
1175 continue;
1176 }
1177 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
1178 $website,
1179 $data_fields
1180 );
1181 }
1182 }
1183 }
1184
1185 $post_data = array(
1186 'role' => $role,
1187 'search' => '*' . trim( $search ) . '*',
1188 'search_columns' => 'user_login,display_name,user_email',
1189 );
1190
1191 MainWP_Connect::fetch_urls_authed(
1192 $dbwebsites,
1193 'search_users',
1194 $post_data,
1195 array(
1196 static::get_class_name(),
1197 'users_search_handler',
1198 ),
1199 $output
1200 );
1201 }
1202
1203 MainWP_Cache::add_context(
1204 'Users',
1205 array(
1206 'count' => $output->users,
1207 'keyword' => $search,
1208 'status' => $role,
1209 'sites' => '' !== $sites ? $sites : '',
1210 'groups' => '' !== $groups ? $groups : '',
1211 'clients' => ( '' !== $clients ) ? $clients : '',
1212 )
1213 );
1214
1215 // Sort if required.
1216
1217 if ( empty( $output->users ) ) {
1218 static::render_cache_not_found();
1219 }
1220 }
1221
1222 /**
1223 * Renders when cache is not found.
1224 *
1225 * @uses \MainWP\Dashboard\MainWP_Cache::add_body()
1226 */
1227 public static function render_cache_not_found() {
1228 ob_start();
1229 $newOutput = ob_get_clean();
1230 echo $newOutput; // phpcs:ignore WordPress.Security.EscapeOutput
1231 MainWP_Cache::add_body( 'Users', $newOutput );
1232 }
1233
1234 /**
1235 * Gets the selected users current role.
1236 *
1237 * @param string $role Selected Users Role.
1238 */
1239 private static function get_role( $role ) {
1240 if ( is_array( $role ) ) {
1241 $allowed_roles = array( 'subscriber', 'administrator', 'editor', 'author', 'contributor' );
1242 $ret = '';
1243 foreach ( $role as $ro ) {
1244 if ( in_array( $ro, $allowed_roles ) ) {
1245 $ret .= ucfirst( $ro ) . ', ';
1246 }
1247 }
1248 $ret = rtrim( $ret, ', ' );
1249 if ( '' === $ret ) {
1250 $ret = 'None';
1251 }
1252
1253 return $ret;
1254 }
1255
1256 return ucfirst( $role );
1257 }
1258
1259 /**
1260 * Renders Search results.
1261 *
1262 * @param array $users Users array.
1263 * @param object $website Object containing the child site info.
1264 *
1265 * @return mixed Search results table.
1266 *
1267 * @uses \MainWP\Dashboard\MainWP_Cache::add_body()
1268 */
1269 protected static function users_search_handler_renderer( $users, $website ) { // phpcs:ignore -- NOSONAR -complex.
1270 $return = 0;
1271 $is_demo = MainWP_Demo_Handle::is_demo_mode();
1272
1273 foreach ( $users as $user ) {
1274 if ( ! is_array( $user ) ) {
1275 continue;
1276 }
1277 ob_start();
1278 ?>
1279 <tr>
1280 <td class="check-column"><span class="ui checkbox"><input type="checkbox" name="user[]" value="1"></span></td>
1281 <?php do_action( 'mainwp_users_table_column', $user, $website ); ?>
1282 <td class="name column-name not-selectable">
1283 <?php echo ! empty( $user['display_name'] ) ? esc_html( $user['display_name'] ) : '&nbsp;'; ?>
1284 </td>
1285 <td class="username column-username not-selectable"><strong><abbr title="<?php echo esc_attr( $user['login'] ); ?>"><?php echo esc_html( $user['login'] ); ?></abbr></strong></td>
1286 <td class="email column-email not-selectable"><a href="mailto:<?php echo esc_attr( $user['email'] ); ?>"><?php echo esc_html( $user['email'] ); ?></a></td>
1287 <td class="last_password_change column-last_password_change not-selectable right aligned" data-order="<?php echo ! empty( $user['last_password_change'] ) ? intval( $user['last_password_change'] ) : 0; ?>">
1288 <?php
1289 if ( ! empty( $user['last_password_change'] ) ) {
1290 $timestamp = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $user['last_password_change'] );
1291 echo '<span data-tooltip="' . esc_attr( $timestamp ) . '" data-inverted="" data-position="left center">' . esc_html( MainWP_Utility::time_elapsed_string( $user['last_password_change'] ) ) . '</span>';
1292 } else {
1293 echo '<span class="ui grey text" data-tooltip="' . esc_attr__( 'Password change hasn\'t been tracked yet.', 'mainwp' ) . '" data-inverted="" data-position="left center">' . esc_html__( 'Unknown', 'mainwp' ) . '</span>';
1294 }
1295 ?>
1296 </td>
1297 <?php
1298 $status = isset( $user['password_status'] ) ? $user['password_status'] : '';
1299 $status_order = 0;
1300 if ( 'OVERDUE' === $status ) {
1301 $status_order = 3;
1302 } elseif ( 'DUE' === $status ) {
1303 $status_order = 2;
1304 } elseif ( 'OK' === $status ) {
1305 $status_order = 1;
1306 }
1307 ?>
1308 <td class="password_status column-password_status not-selectable center aligned" data-order="<?php echo intval( $status_order ); ?>">
1309 <?php
1310 if ( 'OK' === $status && empty( $user['last_password_change'] ) ) {
1311 echo '<span class="ui grey mini label" data-tooltip="' . esc_attr__( 'Password change hasn\'t been tracked yet.', 'mainwp' ) . '" data-inverted="" data-position="left center">' . esc_html__( 'Unknown', 'mainwp' ) . '</span>';
1312 } elseif ( 'OK' === $status ) {
1313 echo '<span class="ui green mini label">' . esc_html__( 'Fresh', 'mainwp' ) . '</span>';
1314 } elseif ( 'DUE' === $status ) {
1315 if ( ! empty( $user['password_due_time'] ) ) {
1316 $due_date = MainWP_Utility::format_timestamp( $user['password_due_time'] );
1317 echo '<span class="ui yellow mini label" data-tooltip="' . esc_attr__( 'Due: ', 'mainwp' ) . esc_attr( $due_date ) . '" data-inverted="" data-position="left center">' . esc_html__( 'Due Soon', 'mainwp' ) . '</span>';
1318 } else {
1319 echo '<span class="ui yellow mini label">' . esc_html__( 'Due Soon', 'mainwp' ) . '</span>';
1320 }
1321 } elseif ( 'OVERDUE' === $status ) {
1322 if ( ! empty( $user['password_due_time'] ) ) {
1323 $overdue_date = MainWP_Utility::format_timestamp( $user['password_due_time'] );
1324 echo '<span class="ui red mini label" data-tooltip="' . esc_attr__( 'Was due: ', 'mainwp' ) . esc_attr( $overdue_date ) . '" data-inverted="" data-position="left center">' . esc_html__( 'Overdue', 'mainwp' ) . '</span>';
1325 } else {
1326 echo '<span class="ui red mini label">' . esc_html__( 'Overdue', 'mainwp' ) . '</span>';
1327 }
1328 } elseif ( 'DISABLED' === $status || empty( $status ) ) {
1329 echo '<span class="ui grey mini label">' . esc_html__( 'Disabled', 'mainwp' ) . '</span>';
1330 } else {
1331 echo '<span class="ui grey text">' . esc_html( $status ) . '</span>';
1332 }
1333 ?>
1334 </td>
1335 <td class="role column-role not-selectable"><?php echo static::get_role( $user['role'] ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
1336 <td class="posts column-posts not-selectable"><a href="<?php echo esc_url( admin_url( 'admin.php?page=PostBulkManage&siteid=' . intval( $website->id ) ) . '&userid=' . $user['id'] ); ?>"><?php echo esc_html( $user['post_count'] ); ?></a></td>
1337 <td class="website column-website not-selectable"><a href="<?php echo esc_url( $website->url ); ?>" target="_blank"><?php echo esc_html( $website->url ); ?></a></td>
1338 <td class="right aligned not-selectable">
1339 <input class="userId" type="hidden" name="id" value="<?php echo esc_attr( $user['id'] ); ?>" />
1340 <input class="userName" type="hidden" name="name" value="<?php echo esc_attr( $user['login'] ); ?>" />
1341 <input class="websiteId" type="hidden" name="id" value="<?php echo intval( $website->id ); ?>" />
1342 <div class="ui right pointing dropdown" style="z-index: 999">
1343 <a href="javascript:void(0)"><i class="ellipsis vertical icon"></i></a>
1344 <div class="menu">
1345 <a class="item user_getedit" href="#"><?php esc_html_e( 'Edit', 'mainwp' ); ?></a>
1346 <?php if ( ( 1 !== (int) $user['id'] ) && ( $user['login'] !== $website->adminname ) ) { ?>
1347 <a class="item user_submitdelete" href="#"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
1348 <?php } elseif ( ( 1 === (int) $user['id'] ) || ( $user['login'] === $website->adminname ) ) { ?>
1349 <a href="javascript:void(0)" class="item" data-tooltip="This user is used for our secure link, it can not be deleted." data-inverted="" data-position="left center"><?php esc_html_e( 'Delete', 'mainwp' ); ?></a>
1350 <?php } ?>
1351 <?php if ( ! $is_demo ) : ?>
1352 <a class="item" href="<?php MainWP_Site_Open::get_open_site_admin_link( $website->id, true ); ?>" data-tooltip="<?php esc_attr_e( 'Jump to the site WP Admin', 'mainwp' ); ?>" data-position="bottom right" data-inverted="" class="open_newwindow_wpadmin ui green basic icon button" target="_blank"><?php esc_html_e( 'Go to WP Admin', 'mainwp' ); ?></a>
1353 <?php else : ?>
1354 <a class="item" href="<?php echo esc_url( $website->url ) . 'wp-admin.html'; ?>" data-tooltip="<?php esc_attr_e( 'Jump to the site WP Admin', 'mainwp' ); ?>" data-position="bottom right" data-inverted="" class="open_newwindow_wpadmin ui green basic icon button" target="_blank"><?php esc_html_e( 'Go to WP Admin', 'mainwp' ); ?></a>
1355 <?php endif; ?>
1356 <?php
1357 /**
1358 * Action: mainwp_users_table_action
1359 *
1360 * Adds a new item in the Actions menu in Manage Users table.
1361 *
1362 * Suggested HTML markup:
1363 * <a class="item" href="Your custom URL">Your custom label</a>
1364 *
1365 * @param array $user Array containing the user data.
1366 * @param array $website Object containing the website data.
1367 *
1368 * @since 4.1
1369 */
1370 do_action( 'mainwp_users_table_action', $user, $website );
1371 ?>
1372 </div>
1373 </div>
1374 </td>
1375 </tr>
1376 <?php
1377 $newOutput = ob_get_clean();
1378 echo $newOutput; // phpcs:ignore WordPress.Security.EscapeOutput
1379 MainWP_Cache::add_body( 'Users', $newOutput );
1380 ++$return;
1381 }
1382
1383 return $return;
1384 }
1385
1386 /**
1387 * Handles user search.
1388 *
1389 * @param mixed $data Search data.
1390 * @param mixed $website Child Site.
1391 * @param mixed $output Output to pass to static::users_search_handler_renderer().
1392 *
1393 * @uses \MainWP\Dashboard\MainWP_Error_Helper::get_error_message()
1394 * @uses \MainWP\Dashboard\MainWP_Exception
1395 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_child_response()
1396 */
1397 public static function users_search_handler( $data, $website, &$output ) {
1398 if ( MainWP_Demo_Handle::get_instance()->is_demo_website( $website ) ) {
1399 return;
1400 }
1401 if ( 0 < preg_match( '/<mainwp>(.*)<\/mainwp>/', $data, $results ) ) {
1402 $result = $results[1];
1403 $users = MainWP_System_Utility::get_child_response( base64_decode( $result ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1404 unset( $results );
1405 $output->users += static::users_search_handler_renderer( $users, $website );
1406 unset( $users );
1407 } else {
1408 $output->errors[ $website->id ] = MainWP_Error_Helper::get_error_message( new MainWP_Exception( 'NOMAINWP', $website->url ) );
1409 }
1410 }
1411
1412 /**
1413 * Deletes user.
1414 */
1415 public static function delete() {
1416 static::action( 'delete' );
1417 die( wp_json_encode( array( 'result' => esc_html__( 'User has been deleted', 'mainwp' ) ) ) );
1418 }
1419
1420 /**
1421 * Edits user.
1422 */
1423 public static function edit() {
1424 $information = static::action( 'edit' );
1425 wp_send_json( $information );
1426 }
1427
1428 /**
1429 * Updates user.
1430 */
1431 public static function update_user() {
1432 static::action( 'update_user' );
1433 die( wp_json_encode( array( 'result' => esc_html__( 'User has been updated', 'mainwp' ) ) ) );
1434 }
1435
1436 /**
1437 * Updates users password.
1438 */
1439 public static function update_password() {
1440 static::action( 'update_password' );
1441 die( wp_json_encode( array( 'result' => esc_html__( 'User password has been updated', 'mainwp' ) ) ) );
1442 }
1443
1444 /**
1445 * Users actions.
1446 *
1447 * @param mixed $pAction Action to perform delete|update_user|update_password.
1448 * @param string $extra Additional Roles to add if any.
1449 *
1450 * @return mixed $information User update info that is returned.
1451 * @throws \MainWP_Exception Error message.
1452 *
1453 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
1454 * @uses \MainWP\Dashboard\MainWP_DB::update_website_values()
1455 * @uses \MainWP\Dashboard\MainWP_Error_Helper::get_error_message()
1456 * @uses \MainWP\Dashboard\MainWP_Exception
1457 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
1458 * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
1459 */
1460 public static function action( $pAction, $extra = '' ) { // phpcs:ignore -- NOSONAR - current complexity required to achieve desired results. Pull request solutions appreciated.
1461
1462 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1463 $userId = isset( $_POST['userId'] ) ? sanitize_text_field( wp_unslash( $_POST['userId'] ) ) : false;
1464 $userName = isset( $_POST['userName'] ) ? sanitize_text_field( wp_unslash( $_POST['userName'] ) ) : '';
1465 $websiteId = isset( $_POST['websiteId'] ) ? sanitize_text_field( wp_unslash( $_POST['websiteId'] ) ) : false;
1466 $pass = isset( $_POST['update_password'] ) ? rawurldecode( wp_unslash( $_POST['update_password'] ) ) : '';
1467
1468 if ( function_exists( '\mb_convert_encoding' ) ) {
1469 $pass = \mb_convert_encoding( $pass, 'ISO-8859-1', 'UTF-8' );
1470 } else {
1471 $pass = utf8_decode( $pass ); // to compatible.
1472 }
1473
1474 if ( empty( $userId ) || empty( $websiteId ) ) {
1475 die( wp_json_encode( array( 'error' => esc_html__( 'Site ID or user ID not found. Please reload the page and try again.', 'mainwp' ) ) ) );
1476 }
1477
1478 $website = MainWP_DB::instance()->get_website_by_id( $websiteId );
1479
1480 if ( MainWP_System_Utility::is_suspended_site( $website ) ) {
1481 die(
1482 wp_json_encode(
1483 array(
1484 'error' => esc_html__( 'Suspended site.', 'mainwp' ),
1485 'errorCode' => 'SUSPENDED_SITE',
1486 )
1487 )
1488 );
1489 }
1490
1491 if ( ! MainWP_System_Utility::can_edit_website( $website ) ) {
1492 die( wp_json_encode( array( 'error' => esc_html__( 'You can not edit this website!', 'mainwp' ) ) ) );
1493 }
1494
1495 if ( ( 'delete' === $pAction ) && ( $website->adminname === $userName ) ) {
1496 die( wp_json_encode( array( 'error' => esc_html__( 'This user is used for our secure link, it can not be deleted.', 'mainwp' ) ) ) );
1497 }
1498
1499 if ( 'update_user' === $pAction ) {
1500 $user_data = isset( $_POST['user_data'] ) ? wp_unslash( $_POST['user_data'] ) : '';
1501 parse_str( $user_data, $extra );
1502 if ( $website->adminname === $userName && is_array( $extra ) && isset( $extra['role'] ) ) {
1503 unset( $extra['role'] );
1504 }
1505
1506 if ( ! empty( $pass ) ) {
1507 $extra['pass1'] = $pass;
1508 $extra['pass2'] = $pass;
1509 }
1510 }
1511 // phpcs:enable
1512
1513 $optimize = ( 1 === (int) get_option( 'mainwp_optimize', 1 ) ) ? 1 : 0;
1514
1515 /**
1516 * Action: mainwp_before_user_action
1517 *
1518 * Fires before user edit/delete/update_user/update_password actions.
1519 *
1520 * @since 4.1
1521 */
1522 do_action( 'mainwp_before_user_action', $pAction, $userId, $extra, $pass, $optimize, $website );
1523
1524 try {
1525 $information = MainWP_Connect::fetch_url_authed(
1526 $website,
1527 'user_action',
1528 array(
1529 'action' => $pAction,
1530 'id' => $userId,
1531 'extra' => $extra,
1532 'user_pass' => $pass,
1533 'optimize' => $optimize,
1534 )
1535 );
1536
1537 if ( is_array( $information ) && isset( $information['status'] ) && ( 'SUCCESS' === $information['status'] ) ) {
1538 $data = isset( $information['other_data']['users_data'] ) ? $information['other_data']['users_data'] : array(); // user actions data.
1539
1540 /**
1541 * Fires immediately after user action.
1542 *
1543 * @since 4.5.1.1
1544 */
1545 do_action( 'mainwp_user_action', $website, $pAction, $data, $extra, $optimize );
1546 }
1547 } catch ( MainWP_Exception $e ) {
1548 die( wp_json_encode( array( 'error' => MainWP_Error_Helper::get_error_message( $e ) ) ) );
1549 }
1550
1551 /**
1552 * Action: mainwp_after_user_action
1553 *
1554 * Fires after user edit/delete/update_user/update_password actions.
1555 *
1556 * @since 4.1
1557 */
1558 do_action( 'mainwp_after_user_action', $information, $pAction, $userId, $extra, $pass, $optimize, $website );
1559
1560 if ( is_array( $information ) && isset( $information['error'] ) ) {
1561 wp_send_json( array( 'error' => esc_html( $information['error'] ) ) );
1562 }
1563
1564 if ( ! isset( $information['status'] ) || ( 'SUCCESS' !== $information['status'] ) ) {
1565 die( wp_json_encode( array( 'error' => esc_html__( 'Unexpected error.', 'mainwp' ) ) ) );
1566 } elseif ( 'update_user' === $pAction ) {
1567 if ( $optimize && isset( $information['users'] ) ) {
1568 $websiteValues['users'] = wp_json_encode( $information['users'] );
1569 MainWP_DB::instance()->update_website_values( $websiteId, $websiteValues );
1570 }
1571 }
1572
1573 // This user is used for our secure link, you can not change the role.
1574 if ( 'edit' === $pAction && $website->adminname === $userName && is_array( $information ) && isset( $information['user_data'] ) ) {
1575 $information['is_secure_admin'] = 1;
1576 }
1577
1578 return $information;
1579 }
1580
1581 /**
1582 * Renders the Add New user form.
1583 */
1584 public static function render_bulk_add() {
1585
1586 /**
1587 * Filter: mainwp_new_user_password_complexity
1588 *
1589 * Filters the Password lenght for the Add New user, Password field.
1590 *
1591 * Since 4.1
1592 */
1593 $pass_complexity = apply_filters( 'mainwp_new_user_password_complexity', '24' );
1594 static::render_header( 'Add' );
1595 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1596 ?>
1597 <div id="mainwp-add-users">
1598 <?php
1599 /**
1600 * Action: mainwp_before_new_user_form
1601 *
1602 * Fires before the Add New user form.
1603 *
1604 * @since 4.1
1605 */
1606 do_action( 'mainwp_before_new_user_form' );
1607 ?>
1608 <form action="" method="post" name="createuser" id="createuser" class="add:users: validate">
1609 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
1610 <div class="mainwp-main-content ui padded segment">
1611 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-add-user-info-message' ) ) : ?>
1612 <div class="ui info message">
1613 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-add-user-info-message"></i>
1614 <div class="header"><?php esc_html_e( 'Create users on all selected Child Sites.', 'mainwp' ); ?></div>
1615 <?php esc_html_e( 'Select one or more sites, tags or clients before submitting.', 'mainwp' ); ?>
1616 </div>
1617 <?php endif; ?>
1618 <?php if ( isset( $_GET['success'] ) && 1 === (int) $_GET['success'] ) : ?>
1619 <div class="ui green message">
1620 <i class="close icon"></i>
1621 <?php esc_html_e( 'User created successfully. You can now manage this user from the Manage Users page, or create another one here.', 'mainwp' ); ?>
1622 </div>
1623 <?php endif; ?>
1624 <div class="ui message" id="mainwp-message-zone" style="display:none;"></div>
1625 <div id="mainwp-add-new-user-form" >
1626 <?php
1627 /**
1628 * Action: mainwp_before_new_user_form_fields
1629 *
1630 * Fires before the Add New user form fields.
1631 *
1632 * @since 4.1
1633 */
1634 do_action( 'mainwp_before_new_user_form_fields' );
1635 ?>
1636 <div class="ui form">
1637 <div class="ui grid field">
1638 <label class="six wide column middle aligned"><?php esc_html_e( 'Username', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
1639 <div class="ui six wide column">
1640 <div class="ui input">
1641 <input type="text" id="user_login" name="user_login" value="<?php echo ( isset( $_POST['user_login'] ) ) ? esc_html( sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) ) : ''; ?>">
1642 </div>
1643 </div>
1644 </div>
1645 <div class="ui grid field">
1646 <label class="six wide column middle aligned"><?php esc_html_e( 'E-mail', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
1647 <div class="ui six wide column">
1648 <div class="ui input">
1649 <input type="text" id="email" name="email" value="<?php echo ( isset( $_POST['email'] ) ) ? esc_html( sanitize_text_field( wp_unslash( $_POST['email'] ) ) ) : ''; ?>">
1650 </div>
1651 </div>
1652 </div>
1653 <div class="ui grid field">
1654 <label class="six wide column middle aligned"><?php esc_html_e( 'First Name', 'mainwp' ); ?></label>
1655 <div class="ui six wide column">
1656 <div class="ui input">
1657 <input type="text" id="first_name" name="first_name" value="<?php echo ( isset( $_POST['first_name'] ) ) ? esc_html( sanitize_text_field( wp_unslash( $_POST['first_name'] ) ) ) : ''; ?>">
1658 </div>
1659 </div>
1660 </div>
1661 <div class="ui grid field">
1662 <label class="six wide column middle aligned"><?php esc_html_e( 'Last Name', 'mainwp' ); ?></label>
1663 <div class="ui six wide column">
1664 <div class="ui input">
1665 <input type="text" id="last_name" name="last_name" value="<?php echo ( isset( $_POST['last_name'] ) ) ? esc_html( sanitize_text_field( wp_unslash( $_POST['last_name'] ) ) ) : ''; ?>">
1666 </div>
1667 </div>
1668 </div>
1669 <div class="ui grid field">
1670 <label class="six wide column middle aligned"><?php esc_html_e( 'Website', 'mainwp' ); ?></label>
1671 <div class="ui six wide column">
1672 <div class="ui input">
1673 <input type="text" id="url" name="url" value="<?php echo ( isset( $_POST['url'] ) ) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : ''; ?>">
1674 </div>
1675 </div>
1676 </div>
1677 <div class="ui grid field">
1678 <label class="six wide column middle aligned"><?php esc_html_e( 'Password', 'mainwp' ); ?> <span class="ui small red text"><?php esc_html_e( '(Required)', 'mainwp' ); ?></span></label>
1679 <div class="ui six wide column">
1680 <input class="hidden" value=" "/>
1681 <div class="ui icon input">
1682 <input type="text" id="password" name="password" autocomplete="off" value="<?php echo esc_attr( wp_generate_password( $pass_complexity ) ); ?>">
1683 <i class="sync alternate link icon mainwp-generate-password-button"></i>
1684 </div>
1685 </div>
1686 </div>
1687
1688 <div class="ui grid field">
1689 <label class="six wide column middle aligned"><?php esc_html_e( 'Send Password?', 'mainwp' ); ?></label>
1690 <div class="one wide column ui toggle checkbox">
1691 <input type="checkbox" name="send_password" id="send_password" <?php echo ( isset( $_POST['send_password'] ) ) ? esc_html( 'checked' ) : ''; ?> >
1692 </div>
1693 <div class="nine wide column">
1694 <span class="ui small text"><?php esc_html_e( 'If enabled, the new user will receive their login credentials via email.', 'mainwp' ); ?></span>
1695 </div>
1696 </div>
1697
1698 <?php
1699 $user_roles = array(
1700 'subscriber' => esc_html__( 'Subscriber', 'mainwp' ),
1701 'administrator' => esc_html__( 'Administrator', 'mainwp' ),
1702 'editor' => esc_html__( 'Editor', 'mainwp' ),
1703 'author' => esc_html__( 'Author', 'mainwp' ),
1704 'contributor' => esc_html__( 'Contributor', 'mainwp' ),
1705 );
1706 $user_roles = apply_filters_deprecated( 'mainwp-users-manage-roles', array( $user_roles ), '4.0.7.2', 'mainwp_users_manage_roles' ); // @deprecated Use 'mainwp_users_manage_roles' instead. NOSONAR - not IP.
1707 $user_roles = apply_filters( 'mainwp_users_manage_roles', $user_roles );
1708 ?>
1709
1710 <div class="ui grid field">
1711 <label class="six wide column middle aligned"><?php esc_html_e( 'Role', 'mainwp' ); ?></label>
1712 <div class="six wide column">
1713 <select class="ui dropdown" name="role" id="role">
1714 <?php
1715 foreach ( $user_roles as $r => $n ) {
1716 if ( empty( $r ) ) {
1717 continue;
1718 }
1719 ?>
1720 <option value="<?php echo esc_html( $r ); ?>" <?php echo ( isset( $_POST['role'] ) && $_POST['role'] === $r ) ? esc_html( 'selected' ) : ''; ?>><?php echo esc_html( $n ); ?></option>
1721 <?php
1722 }
1723 ?>
1724 </select>
1725 </div>
1726 </div>
1727
1728 </div>
1729 <?php
1730 /**
1731 * Action: mainwp_after_new_user_form_fields
1732 *
1733 * Fires after the Add New user form fields.
1734 *
1735 * @since 4.1
1736 */
1737 do_action( 'mainwp_after_new_user_form_fields' );
1738 ?>
1739 </div>
1740 </div>
1741 <div class="mainwp-side-content mainwp-no-padding">
1742 <?php
1743 /**
1744 * Action: mainwp_add_new_user_sidebar_top
1745 *
1746 * Fires at the top of the sidebar on Add New user page.
1747 *
1748 * @since 4.1
1749 */
1750 do_action( 'mainwp_add_new_user_sidebar_top' );
1751 ?>
1752 <div class="mainwp-select-sites ui accordion mainwp-sidebar-accordion">
1753 <?php
1754 /**
1755 * Action: mainwp_add_new_user_before_select_sites
1756 *
1757 * Fires before the Select Sites section on the Add New user page.
1758 *
1759 * @since 4.1
1760 */
1761 do_action( 'mainwp_add_new_user_before_select_sites' );
1762 ?>
1763 <div class="title active"><i class="dropdown icon"></i> <?php esc_html_e( 'Select Sites', 'mainwp' ); ?></div>
1764 <div class="content active">
1765 <?php
1766 $sel_params = array(
1767 'show_client' => true,
1768 );
1769 MainWP_UI_Select_Sites::select_sites_box( $sel_params );
1770 ?>
1771 </div>
1772 <?php
1773 /**
1774 * Action: mainwp_add_new_user_after_select_sites
1775 *
1776 * Fires after the Select Sites section on the Add New user page.
1777 *
1778 * @since 4.1
1779 */
1780 do_action( 'mainwp_add_new_user_after_select_sites' );
1781 ?>
1782 </div>
1783 <div class="ui fitted divider"></div>
1784 <div class="mainwp-search-submit">
1785 <?php
1786 /**
1787 * Action: mainwp_add_new_user_before_submit_button
1788 *
1789 * Fires before the Submit button on the Add New user page.
1790 *
1791 * @since 4.1
1792 */
1793 do_action( 'mainwp_add_new_user_before_submit_button' );
1794 ?>
1795 <input type="button" name="createuser" id="bulk_add_createuser" class="ui big green fluid button" value="<?php esc_attr_e( 'Add New User', 'mainwp' ); ?> "/>
1796 <?php
1797 /**
1798 * Action: mainwp_add_new_user_after_submit_button
1799 *
1800 * Fires after the Submit button on the Add New user page.
1801 *
1802 * @since 4.1
1803 */
1804 do_action( 'mainwp_add_new_user_after_submit_button' );
1805 ?>
1806 </div>
1807 <?php
1808 /**
1809 * Action: mainwp_add_new_user_sidebar_bottom
1810 *
1811 * Fires at the bottom of the sidebar on Add New user page.
1812 *
1813 * @since 4.1
1814 */
1815 do_action( 'mainwp_add_new_user_sidebar_bottom' );
1816 ?>
1817 </div>
1818 <div style="clear:both"></div>
1819 </form>
1820 <script type="text/javascript">
1821 jQuery( document ).ready( function () {
1822 // Initialize button state based on site selection
1823 mainwp_init_button_site_selection_dependency( 'bulk_add_createuser' );
1824 } );
1825 </script>
1826 <?php
1827 /**
1828 * Action: mainwp_after_new_user_form
1829 *
1830 * Fires after the Add New user form.
1831 *
1832 * @since 4.1
1833 */
1834 do_action( 'mainwp_after_new_user_form' );
1835 ?>
1836 </div>
1837 <?php
1838 // phpcs:enable
1839
1840 static::render_footer( 'Add' );
1841 }
1842
1843 /**
1844 * Renders bulk Import Users form.
1845 *
1846 * @return void
1847 */
1848 public static function render_bulk_import_users() {
1849 if ( isset( $_FILES['import_user_file_bulkupload'] ) && isset( $_FILES['import_user_file_bulkupload']['error'] ) && UPLOAD_ERR_OK === $_FILES['import_user_file_bulkupload']['error'] ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
1850 static::render_bulk_upload();
1851 return;
1852 }
1853 ?>
1854 <?php static::render_header( 'Import' ); ?>
1855 <div id="MainWP_Bulk_AddUser">
1856 <form action="" method="post" name="createuser" id="createuser" class="add:users: validate" enctype="multipart/form-data">
1857 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
1858 <?php static::render_import_users(); ?>
1859 </form>
1860 </div>
1861 <?php
1862 static::render_footer( 'Import' );
1863 }
1864
1865 /**
1866 * Method render_import_users()
1867 *
1868 * Render Import Users page.
1869 */
1870 public static function render_import_users() {
1871 ?>
1872 <div class="ui padded segment" id="mainwp-import-sites">
1873 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-import-users-info-message' ) ) : ?>
1874 <div class="ui info message">
1875 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-import-users-info-message"></i>
1876 <?php /* translators: 1: opening anchor tag, 2: closing anchor tag */ printf( esc_html__( 'Use the form to bulk import users. You can download the sample CSV file to see how to fomat the import file properly. For additional help, please check this %1$shelp documentation%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/sites/users/manage-users#import-users-via-csv/" target="_blank">', '</a>' ); ?>
1877 </div>
1878 <?php endif; ?>
1879
1880 <div id="mainwp-message-zone" class="ui message" style="display:none"></div>
1881 <?php
1882 /**
1883 * Action: mainwp_before_import_users
1884 *
1885 * Fires above the Import Users section.
1886 *
1887 * @since 4.1
1888 */
1889 do_action( 'mainwp_before_import_users' );
1890 ?>
1891 <div id="mainwp-message-zone" class="ui message" style="display:none"></div>
1892 <div class="ui form">
1893 <form method="POST" action="" enctype="multipart/form-data" id="mainwp_managesites_bulkadd_form">
1894 <?php MainWP_UI::generate_wp_nonce( 'mainwp-admin-nonce' ); ?>
1895 <div class="ui grid field">
1896 <label class="six wide column middle aligned"><?php esc_html_e( 'Upload the CSV file', 'mainwp' ); ?> (<a href="<?php echo esc_url( MAINWP_PLUGIN_URL . 'assets/csv/sample_users.csv' ); ?>" ><?php esc_html_e( 'Download Sample CSV file', 'mainwp' ); ?></a>)</label>
1897 <div class="ten wide column" data-tooltip="<?php esc_attr_e( 'Click to upload the import file.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
1898 <div class="ui file input">
1899 <input type="file" name="import_user_file_bulkupload" id="import_user_file_bulkupload" accept="text/comma-separated-values" />
1900 </div>
1901 </div>
1902 </div>
1903 <div class="ui grid field">
1904 <label class="six wide column middle aligned"><?php esc_html_e( 'CSV file contains a header', 'mainwp' ); ?></label>
1905 <div class="ui toggle checkbox" data-tooltip="<?php esc_attr_e( 'Enable if the import file contains a header.', 'mainwp' ); ?>" data-inverted="" data-position="left center">
1906 <input type="checkbox" name="import_user_chk_header_first" checked="checked" id="import_user_chk_header_first" value="1" />
1907 </div>
1908 </div>
1909 <div class="ui divider"></div>
1910 <input type="button" name="createuser" id="bulk_import_createuser" class="ui big green button" value="<?php esc_attr_e( 'Import Users', 'mainwp' ); ?>" />
1911 </form>
1912 </div>
1913 <?php
1914 /**
1915 * Action: mainwp_after_import_users
1916 *
1917 * Fires under the Import Users section.
1918 *
1919 * @since 4.1
1920 */
1921 do_action( 'mainwp_after_import_users' );
1922 ?>
1923 </div>
1924 <?php
1925 }
1926
1927 /**
1928 * Method do_bulk_add()
1929 *
1930 * Bulk User addition $_POST Handler.
1931 *
1932 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
1933 * @uses \MainWP\Dashboard\MainWP_DB::query()
1934 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
1935 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
1936 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
1937 * @uses \MainWP\Dashboard\MainWP_Bulk_Add::get_class_name()
1938 * @uses \MainWP\Dashboard\MainWP_Utility::ctype_digit()
1939 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
1940 */
1941 public static function do_bulk_add() { // phpcs:ignore -- NOSONAR -Current complexity is required to achieve desired results. Pull request solutions appreciated.
1942 $errors = array();
1943 $errorFields = array();
1944
1945 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1946 if ( isset( $_POST['select_by'] ) ) {
1947 $selected_sites = ( isset( $_POST['selected_sites'] ) && is_array( $_POST['selected_sites'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_sites'] ) ) : array();
1948 $selected_groups = ( isset( $_POST['selected_groups'] ) && is_array( $_POST['selected_groups'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_groups'] ) ) : array();
1949 $selected_clients = ( isset( $_POST['selected_clients'] ) && is_array( $_POST['selected_clients'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['selected_clients'] ) ) : array();
1950
1951 if ( ( 'group' === $_POST['select_by'] && empty( $selected_groups ) ) || ( 'site' === $_POST['select_by'] && empty( $selected_sites ) ) || ( 'client' === $_POST['select_by'] && empty( $selected_clients ) ) ) {
1952 $errors[] = esc_html__( 'Please select at least one website or group or client.', 'mainwp' );
1953 }
1954 } else {
1955 $errors[] = esc_html__( 'Please select at least one website or group or client.', 'mainwp' );
1956 }
1957
1958 if ( ! isset( $_POST['user_login'] ) || '' === $_POST['user_login'] ) {
1959 $errorFields[] = 'user_login';
1960 }
1961
1962 if ( ! isset( $_POST['email'] ) || '' === $_POST['email'] ) {
1963 $errorFields[] = 'email';
1964 }
1965
1966 $allowed_roles = array( 'subscriber', 'administrator', 'editor', 'author', 'contributor' );
1967 $cus_roles = array();
1968 $cus_roles = apply_filters_deprecated( 'mainwp-users-manage-roles', array( $cus_roles ), '4.0.7.2', 'mainwp_users_manage_roles' ); // @deprecated Use 'mainwp_users_manage_roles' instead. NOSONAR - not IP.
1969 $cus_roles = apply_filters( 'mainwp_users_manage_roles', $cus_roles );
1970
1971 if ( is_array( $cus_roles ) && ! empty( $cus_roles ) ) {
1972 $cus_roles = array_keys( $cus_roles );
1973 $allowed_roles = array_merge( $allowed_roles, $cus_roles );
1974 }
1975
1976 if ( ! isset( $_POST['role'] ) || ! in_array( $_POST['role'], $allowed_roles ) ) {
1977 $errorFields[] = 'role';
1978 }
1979
1980 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
1981
1982 if ( empty( $errors ) && empty( $errorFields ) ) {
1983 $user_to_add = array(
1984 'user_pass' => isset( $_POST['pass1'] ) ? wp_unslash( $_POST['pass1'] ) : '',
1985 'user_login' => isset( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : '',
1986 'user_url' => isset( $_POST['url'] ) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : '',
1987 'user_email' => isset( $_POST['email'] ) ? sanitize_text_field( wp_unslash( $_POST['email'] ) ) : '',
1988 'first_name' => isset( $_POST['first_name'] ) ? sanitize_text_field( wp_unslash( $_POST['first_name'] ) ) : '',
1989 'last_name' => isset( $_POST['last_name'] ) ? sanitize_text_field( wp_unslash( $_POST['last_name'] ) ) : '',
1990 'role' => isset( $_POST['role'] ) ? sanitize_text_field( wp_unslash( $_POST['role'] ) ) : '',
1991 );
1992
1993 $dbwebsites = array();
1994
1995 if ( isset( $_POST['select_by'] ) && 'site' === $_POST['select_by'] ) {
1996 foreach ( $selected_sites as $k ) {
1997 if ( MainWP_Utility::ctype_digit( $k ) ) {
1998 $website = MainWP_DB::instance()->get_website_by_id( $k );
1999 if ( empty( $website->sync_errors ) && ! MainWP_System_Utility::is_suspended_site( $website ) ) {
2000 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
2001 $website,
2002 $data_fields
2003 );
2004 }
2005 }
2006 }
2007 } elseif ( isset( $_POST['select_by'] ) && 'client' === $_POST['select_by'] ) {
2008 $websites = MainWP_DB_Client::instance()->get_websites_by_client_ids(
2009 $selected_clients,
2010 array(
2011 'select_data' => $data_fields,
2012 )
2013 );
2014
2015 if ( $websites ) {
2016 foreach ( $websites as $website ) {
2017 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
2018 continue;
2019 }
2020 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
2021 $website,
2022 $data_fields
2023 );
2024 }
2025 }
2026 } else {
2027 foreach ( $selected_groups as $k ) {
2028 if ( MainWP_Utility::ctype_digit( $k ) ) {
2029 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_id( $k ) );
2030 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2031 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
2032 continue;
2033 }
2034 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
2035 $website,
2036 $data_fields
2037 );
2038 }
2039 MainWP_DB::free_result( $websites );
2040 }
2041 }
2042 }
2043
2044 if ( ! empty( $dbwebsites ) ) {
2045 $post_data = array(
2046 'new_user' => base64_encode( wp_json_encode( $user_to_add ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
2047 'send_password' => ( isset( $_POST['send_password'] ) ? intval( $_POST['send_password'] ) : '' ),
2048 );
2049 $output = new \stdClass();
2050 $output->ok = array();
2051 $output->errors = array();
2052
2053 /**
2054 * Action: mainwp_before_user_create
2055 *
2056 * Fires before user create.
2057 *
2058 * @since 4.1
2059 */
2060 do_action( 'mainwp_before_user_create', $post_data, $dbwebsites );
2061
2062 MainWP_Connect::fetch_urls_authed(
2063 $dbwebsites,
2064 'newuser',
2065 $post_data,
2066 array(
2067 MainWP_Bulk_Add::get_class_name(),
2068 'posting_bulk_handler',
2069 ),
2070 $output
2071 );
2072
2073 /**
2074 * Action: mainwp_after_user_create
2075 *
2076 * Fires after user create.
2077 *
2078 * @since 4.1
2079 */
2080 do_action( 'mainwp_after_user_create', $output, $post_data, $dbwebsites );
2081 }
2082
2083 $countSites = 0;
2084 $countRealItems = 0;
2085 foreach ( $dbwebsites as $website ) {
2086 if ( isset( $output->ok[ $website->id ] ) && 1 === (int) $output->ok[ $website->id ] ) {
2087 ++$countSites;
2088 ++$countRealItems;
2089 }
2090 }
2091 static::render_bulk_add_modal( $dbwebsites, $output );
2092 } else {
2093 echo wp_json_encode( array( $errorFields, $errors ) );
2094 }
2095 // phpcs:enable
2096 }
2097
2098 /**
2099 * Renders Bulk User addition Modal window.
2100 *
2101 * @param mixed $dbwebsites Child sites list.
2102 * @param mixed $output Modal window content.
2103 */
2104 public static function render_bulk_add_modal( $dbwebsites, $output ) {
2105 // phpcs:disable WordPress.Security.EscapeOutput
2106 ?>
2107 <div id="mainwp-creating-new-user-modal" class="ui modal">
2108 <i class="close mainwp-reload icon"></i>
2109 <div class="header"><?php esc_html_e( 'New User', 'mainwp' ); ?></div>
2110 <div class="content">
2111 <div class="ui middle aligned divided list">
2112 <?php foreach ( $dbwebsites as $website ) : ?>
2113 <div class="item ui grid">
2114 <span class="content"><a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&dashboard=' . $website->id ) ); ?>"><?php echo esc_html( stripslashes( $website->name ) ); ?></a></span>
2115 <span class="right floated content"><?php echo isset( $output->ok[ $website->id ] ) && 1 === (int) $output->ok[ $website->id ] ? '<i class="check green icon"></i> ' : '<span data-tooltip="' . esc_attr( $output->errors[ $website->id ] ) . '" data-position="left center" data-inverted=""><i class="times red icon"></i></span>'; ?></span>
2116 </div>
2117 <?php endforeach; ?>
2118 </div>
2119 <script type="text/javascript">
2120 setTimeout(() => {
2121 // Check if all items have green check icons (no red times icons)
2122 let allSuccess = true;
2123 jQuery('#mainwp-creating-new-user-modal .ui.list .item').each(function() {
2124 // Check if this item has a red times icon
2125 if (jQuery(this).find('.times.red.icon').length > 0) {
2126 allSuccess = false;
2127 return false; // Break the loop
2128 }
2129 });
2130
2131 // If all items are successful, redirect to success page
2132 if (allSuccess) {
2133 jQuery('#createuser')[0].reset();
2134 location.href = 'admin.php?page=UserBulkAdd&success=1';
2135 }
2136 }, 3000);
2137 </script>
2138 </div>
2139 </div>
2140 <?php
2141 // phpcs:enable
2142 }
2143
2144 /**
2145 * Renders Import Users Modal window.
2146 *
2147 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_wp_file_system()
2148 * @uses \MainWP\Dashboard\MainWP_Utility::starts_with()
2149 */
2150 public static function render_bulk_upload() { //phpcs:ignore -- NOSONAR - complex.
2151 static::render_header( 'Import' );
2152 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2153 $errors = array();
2154 if ( isset( $_FILES['import_user_file_bulkupload']['error'] ) && UPLOAD_ERR_OK === $_FILES['import_user_file_bulkupload']['error'] ) {
2155 if ( isset( $_FILES['import_user_file_bulkupload']['tmp_name'] ) && is_uploaded_file( $_FILES['import_user_file_bulkupload']['tmp_name'] ) ) {
2156 $tmp_path = isset( $_FILES['import_user_file_bulkupload']['tmp_name'] ) ? sanitize_text_field( wp_unslash( $_FILES['import_user_file_bulkupload']['tmp_name'] ) ) : '';
2157 MainWP_System_Utility::get_wp_file_system();
2158 // phpcs:enable
2159 /**
2160 * WordPress files system object.
2161 *
2162 * @global object
2163 */
2164 global $wp_filesystem;
2165
2166 $content = $wp_filesystem->get_contents( $tmp_path );
2167 $lines = explode( "\r\n", $content );
2168
2169 if ( is_array( $lines ) && ! empty( $lines ) ) {
2170 $i = 0;
2171 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2172 if ( ! empty( $_POST['import_user_chk_header_first'] ) ) {
2173 $header_line = trim( $lines[0] ) . "\n";
2174 unset( $lines[0] );
2175 }
2176 // phpcs:enable
2177
2178 foreach ( $lines as $originalLine ) {
2179
2180 $line = trim( $originalLine );
2181
2182 if ( MainWP_Utility::starts_with( $line, '#' ) ) {
2183 continue;
2184 }
2185
2186 $items = str_getcsv( $line, ',' );
2187
2188 if ( 3 > count( $items ) ) {
2189 continue;
2190 }
2191
2192 $import_data = array(
2193 'user_login' => sanitize_text_field( wp_unslash( $items[0] ) ),
2194 'email' => sanitize_text_field( wp_unslash( $items[1] ) ),
2195 'first_name' => sanitize_text_field( wp_unslash( $items[2] ) ),
2196 'last_name' => sanitize_text_field( wp_unslash( $items[3] ) ),
2197 'url' => sanitize_text_field( wp_unslash( $items[4] ) ),
2198 'pass1' => sanitize_text_field( wp_unslash( $items[5] ) ),
2199 'send_password' => intval( $items[6] ),
2200 'role' => sanitize_text_field( wp_unslash( strtolower( $items[7] ) ) ),
2201 'select_sites' => sanitize_text_field( wp_unslash( $items[8] ) ),
2202 'select_groups' => sanitize_text_field( wp_unslash( $items[9] ) ),
2203 );
2204 $encoded = wp_json_encode( $import_data );
2205 ?>
2206 <input type="hidden" id="user_import_csv_line_<?php echo intval( $i + 1 ); ?>" original-line="<?php echo esc_attr( sanitize_text_field( $line ) ); ?>" encoded-data="<?php echo esc_html( $encoded ); ?>" />
2207 <?php
2208 ++$i;
2209 }
2210 $header_line = trim( $header_line );
2211 ?>
2212 <div class="ui modal" id="mainwp-import-users-modal">
2213 <i class="close icon"></i>
2214 <div class="header"><?php esc_html_e( 'Importing new users and add them to your sites.', 'mainwp' ); ?></div>
2215 <div class="scrolling content">
2216 <?php
2217 /**
2218 * Action: mainwp_import_users_modal_top
2219 *
2220 * Fires on the top of the Import Users modal.
2221 *
2222 * @since 4.1
2223 */
2224 do_action( 'mainwp_import_users_modal_top' );
2225 ?>
2226 <div id="MainWPBulkUploadUserLoading" style="display: none;"><i class="ui active inline loader tiny"></i> <?php esc_html_e( 'Importing Users', 'mainwp' ); ?></div>
2227 <input type="hidden" id="import_user_do_import" value="1"/>
2228 <input type="hidden" id="import_user_total_import" value="<?php echo esc_attr( $i ); ?>"/>
2229 <p>
2230 <div class="import_user_import_listing" id="import_user_import_logging">
2231 <pre class="log"><?php echo esc_html( $header_line ) . "\n"; ?></pre>
2232 </div>
2233 </p>
2234 <div id="import_user_import_failed_rows" style="display: none;">
2235 <span><?php echo esc_html( $header_line ); ?></span>
2236 </div>
2237 <?php
2238 /**
2239 * Action: mainwp_import_users_modal_bottom
2240 *
2241 * Fires on the bottom of the Import Users modal.
2242 *
2243 * @since 4.1
2244 */
2245 do_action( 'mainwp_import_users_modal_bottom' );
2246 ?>
2247 </div>
2248 <div class="actions">
2249 <input type="button" name="import_user_btn_import" id="import_user_btn_import" class="ui basic button" value="<?php esc_attr_e( 'Pause', 'mainwp' ); ?>"/>
2250 <input type="button" name="import_user_btn_save_csv" id="import_user_btn_save_csv" style="display:none;" class="ui basic green button" value="<?php esc_attr_e( 'Save failed', 'mainwp' ); ?>"/>
2251 </div>
2252 </div>
2253 <script type="text/javascript">
2254 jQuery( document ).ready( function () {
2255 jQuery( "#mainwp-import-users-modal" ).modal( {
2256 closable: false,
2257 onHide: function() {
2258 mainwp_forceReload('admin.php?page=BulkImportUsers');
2259 }
2260 } ).modal( 'show' );
2261 } );
2262 </script>
2263
2264 <?php
2265
2266 } else {
2267 $errors[] = esc_html__( 'Invalid data. Please make sure that the Import file has been formated properly.', 'mainwp' );
2268 }
2269 } else {
2270 $errors[] = esc_html__( 'File could not be uploaded. Temporary file cold not be created. Please make sure that the tmpfile() PHP function is enabled on your server.', 'mainwp' );
2271 }
2272 } else {
2273 $errors[] = esc_html__( 'File could not be uploaded. Please try again. If process keeps failing, please review MainWP Knowledgebase, and if you still have issues, please let us know in the MainWP Community.', 'mainwp' );
2274 }
2275
2276 if ( ! empty( $errors ) ) {
2277 ?>
2278 <?php foreach ( $errors as $error ) { ?>
2279 <div class="ui error message"><?php echo esc_html( $error ); ?></div>
2280 <?php } ?>
2281
2282 <a href="<?php echo esc_url( get_admin_url() ); ?>admin.php?page=UserBulkAdd" class="ui button"><?php esc_html_e( 'Add New', 'mainwp' ); ?></a>
2283 <a href="<?php echo esc_url( get_admin_url() ); ?>admin.php?page=mainwp_tab" class="ui button"><?php esc_html_e( 'Return to Overview', 'mainwp' ); ?></a>
2284 <?php
2285 }
2286
2287 static::render_footer( 'Import' );
2288 }
2289
2290 /**
2291 * User Import $_POST handler.
2292 *
2293 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
2294 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_group_by_name()
2295 * @uses \MainWP\Dashboard\MainWP_DB::query()
2296 * @uses \MainWP\Dashboard\MainWP_DB::get_websites_by_url()
2297 * @uses \MainWP\Dashboard\MainWP_DB::get_sql_websites_by_group_id()
2298 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
2299 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
2300 * @uses \MainWP\Dashboard\MainWP_Bulk_Add::get_class_name()
2301 * @uses \MainWP\Dashboard\MainWP_Utility::map_site()
2302 */
2303 public static function do_import() { // phpcs:ignore -- NOSONAR -Current complexity is required to achieve desired results. Pull request solutions appreciated.
2304
2305 // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2306 $selected_sites = ( isset( $_POST['select_sites'] ) && is_array( $_POST['select_sites'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['select_sites'] ) ) : array();
2307 $selected_groups = ( isset( $_POST['select_groups'] ) && is_array( $_POST['select_groups'] ) ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['select_groups'] ) ) : array();
2308
2309 $data_fields = MainWP_System_Utility::get_default_map_site_fields();
2310 $data_fields[] = 'users';
2311
2312 $user_to_add = array(
2313 'user_pass' => isset( $_POST['pass1'] ) ? wp_unslash( $_POST['pass1'] ) : '',
2314 'user_login' => isset( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : '',
2315 'user_url' => isset( $_POST['url'] ) ? wp_unslash( $_POST['url'] ) : '',
2316 'user_email' => isset( $_POST['email'] ) ? sanitize_text_field( wp_unslash( $_POST['email'] ) ) : '',
2317 'first_name' => isset( $_POST['first_name'] ) ? sanitize_text_field( wp_unslash( $_POST['first_name'] ) ) : '',
2318 'last_name' => isset( $_POST['last_name'] ) ? sanitize_text_field( wp_unslash( $_POST['last_name'] ) ) : '',
2319 'role' => isset( $_POST['role'] ) ? sanitize_text_field( wp_unslash( $_POST['role'] ) ) : '',
2320 );
2321
2322 $ret = array();
2323 $dbwebsites = array();
2324 $not_valid = array();
2325 $error_sites = '';
2326 if ( isset( $_POST['select_by'] ) && 'site' === $_POST['select_by'] ) {
2327 foreach ( $selected_sites as $url ) {
2328 if ( ! empty( $url ) ) {
2329 $website = MainWP_DB::instance()->get_websites_by_url( $url );
2330 if ( ! empty( $website ) ) {
2331 $website = current( $website );
2332 }
2333 if ( $website ) {
2334 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
2335 if ( '' !== $website->sync_errors ) {
2336 $err_imp = esc_html__( 'Site disconnected:', 'mainwp' );
2337 } else {
2338 $err_imp = esc_html__( 'Site suspended:', 'mainwp' );
2339 }
2340 $not_valid[] = $err_imp . ' ' . $website->url;
2341 $error_sites .= $website->url . ';';
2342 continue;
2343 }
2344 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
2345 $website,
2346 $data_fields
2347 );
2348 } else {
2349 $not_valid[] = esc_html__( 'Unexisting website. Please try again.', 'mainwp' ) . ' ' . $url;
2350 $error_sites .= $url . ';';
2351 }
2352 }
2353 }
2354 } else {
2355 foreach ( $selected_groups as $group ) {
2356 if ( MainWP_DB_Common::instance()->get_group_by_name( $group ) ) {
2357 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_websites_by_group_name( $group ) );
2358 if ( $websites ) {
2359 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
2360 if ( '' !== $website->sync_errors || MainWP_System_Utility::is_suspended_site( $website ) ) {
2361 if ( '' !== $website->sync_errors ) {
2362 $err_imp = esc_html__( 'Site disconnected:', 'mainwp' );
2363 } else {
2364 $err_imp = esc_html__( 'Site suspended:', 'mainwp' );
2365 }
2366 $not_valid[] = $err_imp . ' ' . $website->url;
2367 $error_sites .= $website->url . ';';
2368 continue;
2369 }
2370 $dbwebsites[ $website->id ] = MainWP_Utility::map_site(
2371 $website,
2372 $data_fields
2373 );
2374 }
2375 MainWP_DB::free_result( $websites );
2376 } else {
2377 $not_valid[] = esc_html__( 'No websites assigned to the selected group.', 'mainwp' ) . ' ' . $group;
2378 $error_sites .= $group . ';';
2379 }
2380 } else {
2381 $not_valid[] = esc_html__( 'Unexisting group selected. Please try again.', 'mainwp' ) . ' ' . $group;
2382 $error_sites .= $group . ';';
2383 }
2384 }
2385 }
2386
2387 if ( ! empty( $dbwebsites ) ) {
2388 $post_data = array(
2389 'new_user' => base64_encode( wp_json_encode( $user_to_add ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
2390 'send_password' => ( isset( $_POST['send_password'] ) ? intval( $_POST['send_password'] ) : '' ),
2391 );
2392 $output = new \stdClass();
2393 $output->ok = array();
2394 $output->errors = array();
2395
2396 /**
2397 * Action: mainwp_before_user_create
2398 *
2399 * Fires before user create.
2400 *
2401 * @since 4.1
2402 */
2403 do_action( 'mainwp_before_user_create', $post_data, $dbwebsites );
2404
2405 MainWP_Connect::fetch_urls_authed(
2406 $dbwebsites,
2407 'newuser',
2408 $post_data,
2409 array(
2410 MainWP_Bulk_Add::get_class_name(),
2411 'posting_bulk_handler',
2412 ),
2413 $output
2414 );
2415
2416 /**
2417 * Action: mainwp_after_user_create
2418 *
2419 * Fires after user create.
2420 *
2421 * @since 4.1
2422 */
2423 do_action( 'mainwp_after_user_create', $output, $post_data, $dbwebsites );
2424 }
2425
2426 $ret['ok_list'] = array();
2427 $ret['error_list'] = array();
2428 foreach ( $dbwebsites as $website ) {
2429 if ( isset( $output->ok[ $website->id ] ) && 1 === (int) $output->ok[ $website->id ] ) {
2430 $ret['ok_list'][] = 'New user(s) created: ' . esc_html( stripslashes( $website->name ) );
2431 } else {
2432 $ret['error_list'][] = esc_html( $output->errors[ $website->id ] . ' ' . stripslashes( $website->name ) );
2433 $error_sites .= $website->url . ';';
2434 }
2435 }
2436
2437 foreach ( $not_valid as $val ) {
2438 $ret['error_list'][] = $val;
2439 }
2440
2441 $ret['failed_logging'] = '';
2442 if ( ! empty( $error_sites ) ) {
2443 $error_sites = rtrim( $error_sites, ';' );
2444
2445 $user_login = isset( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : '';
2446 $email = isset( $_POST['email'] ) ? sanitize_text_field( wp_unslash( $_POST['email'] ) ) : '';
2447 $first_name = isset( $_POST['first_name'] ) ? sanitize_text_field( wp_unslash( $_POST['first_name'] ) ) : '';
2448 $last_name = isset( $_POST['last_name'] ) ? sanitize_text_field( wp_unslash( $_POST['last_name'] ) ) : '';
2449 $url = isset( $_POST['url'] ) ? sanitize_text_field( wp_unslash( $_POST['url'] ) ) : '';
2450 $pass1 = isset( $_POST['pass1'] ) ? wp_unslash( $_POST['pass1'] ) : '';
2451 $send_password = isset( $_POST['send_password'] ) ? intval( $_POST['send_password'] ) : 0;
2452 $role = isset( $_POST['role'] ) ? sanitize_text_field( wp_unslash( $_POST['role'] ) ) : '';
2453
2454 $ret['failed_logging'] = esc_html( $user_login . ',' . $email . ',' . $first_name . ',' . $last_name . ',' . $url . ',' . $pass1 . ',' . $send_password . ',' . $role . ',' . $error_sites . ',' );
2455 }
2456 $ret['line_number'] = isset( $_POST['line_number'] ) ? intval( $_POST['line_number'] ) : 0;
2457 // phpcs:enable
2458 die( wp_json_encode( $ret ) );
2459 }
2460
2461 /**
2462 * Method mainwp_help_content()
2463 *
2464 * Creates the MainWP Help Documentation List for the help component in the sidebar.
2465 */
2466 public static function mainwp_help_content() {
2467 if ( isset( $_GET['page'] ) && ( 'UserBulkManage' === $_GET['page'] || 'UserBulkAdd' === $_GET['page'] || 'UpdateAdminPasswords' === $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2468 ?>
2469 <p><?php esc_html_e( 'If you need help with managing users, please review following help documents', 'mainwp' ); ?></p>
2470 <div class="ui list">
2471 <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/sites/users/manage-users" target="_blank">Manage Users</a></div>
2472 <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/sites/users/manage-users#create-a-new-user" target="_blank">Create a New User</a></div>
2473 <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/sites/users/manage-users#edit-existing-users" target="_blank">Edit an Existing User</a></div>
2474 <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/sites/users/manage-users#bulk-update-admin-passwords" target="_blank">Bulk Update Administrator Passwords</a></div>
2475 <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/sites/users/manage-users#delete-users" target="_blank">Delete User(s)</a></div>
2476 <?php
2477 /**
2478 * Action: mainwp_users_help_item
2479 *
2480 * Fires at the bottom of the help articles list in the Help sidebar on the Users page.
2481 *
2482 * Suggested HTML markup:
2483 *
2484 * <div class="item"><a href="Your custom URL">Your custom text</a></div>
2485 *
2486 * @since 4.1
2487 */
2488 do_action( 'mainwp_users_help_item' );
2489 ?>
2490 </div>
2491 <?php
2492 }
2493 }
2494 }
2495