PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.2.1
WP 2FA – Two-factor authentication for WordPress v2.2.1
4.1.0 4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / class-settings-page.php
wp-2fa / includes / classes / Admin Last commit date
Controllers 4 years ago Helpers 4 years ago SettingsPages 4 years ago Views 4 years ago class-help-contact-us.php 4 years ago class-premium-features.php 4 years ago class-settings-page.php 4 years ago class-settingspage.php 4 years ago class-setup-wizard.php 4 years ago class-user-listing.php 4 years ago class-user-notices.php 4 years ago class-user-profile.php 4 years ago class-user-registered.php 4 years ago class-user.php 4 years ago index.php 5 years ago
class-settings-page.php
704 lines
1 <?php
2 /**
3 * Settings rendering class.
4 *
5 * @package wp2fa
6 * @subpackage settings
7 * @copyright 2021 WP White Security
8 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
9 * @link https://wordpress.org/plugins/wp-2fa/
10 */
11
12 namespace WP2FA\Admin;
13
14 use \WP2FA\WP2FA as WP2FA;
15 use WP2FA\Utils\User_Utils;
16 use WP2FA\Utils\Settings_Utils;
17 use WP2FA\Admin\Views\Settings_Page_Render;
18 use WP2FA\Admin\SettingsPages\{
19 Settings_Page_Policies,
20 Settings_Page_General,
21 Settings_Page_White_Label,
22 Settings_Page_Email
23 };
24 use WP2FA\Admin\Helpers\WP_Helper;
25 use WP2FA\Admin\Helpers\User_Helper;
26 use WP2FA\Admin\Controllers\Settings;
27
28 /**
29 * Class for handling settings
30 */
31 class Settings_Page {
32
33 const TOP_MENU_SLUG = 'wp-2fa-policies';
34
35 /**
36 * Holds the status of the backup codes functionality
37 *
38 * @var bool[]
39 */
40 private static $backup_codes_enabled = array();
41
42 /**
43 * Create admin menu entry and settings page
44 */
45 public function create_settings_admin_menu() {
46 // Create admin menu item.
47 add_menu_page(
48 esc_html__( 'WP 2FA', 'wp-2fa' ),
49 esc_html__( 'WP 2FA', 'wp-2fa' ),
50 'manage_options',
51 self::TOP_MENU_SLUG,
52 null,
53 'data:image/svg+xml;base64,' . base64_encode( file_get_contents( WP_2FA_PATH . 'dist/images/wp-2fa-white-icon20x28.svg' ) ), // phpcs:ignore
54 81
55 );
56
57 $settings_policies = new Settings_Page_Policies();
58 $settings_white_label = new Settings_Page_White_Label();
59 $settings_email = new Settings_Page_Email();
60 $settings_render = new Settings_Page_Render();
61
62 add_submenu_page(
63 self::TOP_MENU_SLUG,
64 esc_html__( '2FA Policies', 'wp-2fa' ),
65 esc_html__( '2FA Policies', 'wp-2fa' ),
66 'manage_options',
67 self::TOP_MENU_SLUG,
68 array( $settings_policies, 'render' ),
69 1
70 );
71
72 add_submenu_page(
73 self::TOP_MENU_SLUG,
74 esc_html__( 'WP 2FA Settings', 'wp-2fa' ),
75 esc_html__( 'Settings', 'wp-2fa' ),
76 'manage_options',
77 'wp-2fa-settings',
78 array( $settings_render, 'render' ),
79 2
80 );
81
82 // Register our policy settings.
83 register_setting(
84 WP_2FA_POLICY_SETTINGS_NAME,
85 WP_2FA_POLICY_SETTINGS_NAME,
86 array( $settings_policies, 'validate_and_sanitize' )
87 );
88
89 // Register our white label settings.
90 register_setting(
91 WP_2FA_WHITE_LABEL_SETTINGS_NAME,
92 WP_2FA_WHITE_LABEL_SETTINGS_NAME,
93 array( $settings_white_label, 'validate_and_sanitize' )
94 );
95
96 // Register our settings page.
97 register_setting(
98 WP_2FA_SETTINGS_NAME,
99 WP_2FA_SETTINGS_NAME,
100 array( \WP2FA\Admin\SettingsPages\Settings_Page_General::class, 'validate_and_sanitize' )
101 );
102
103 register_setting(
104 WP_2FA_EMAIL_SETTINGS_NAME,
105 WP_2FA_EMAIL_SETTINGS_NAME,
106 array( $settings_email, 'validate_and_sanitize' )
107 );
108
109 /**
110 * Fires after the main menu settings are registered.
111 *
112 * @param string - The menu slug.
113 * @param bool - Is that multisite install or not.
114 *
115 * @since 2.0.0
116 */
117 do_action( WP_2FA_PREFIX . 'after_admin_menu_created', self::TOP_MENU_SLUG, false );
118 }
119
120 /**
121 * Create admin menu entry and settings page
122 */
123 public function create_settings_admin_menu_multisite() {
124 // Create admin menu item.
125 add_menu_page(
126 esc_html__( 'WP 2FA Settings', 'wp-2fa' ),
127 esc_html__( 'WP 2FA', 'wp-2fa' ),
128 'manage_options',
129 self::TOP_MENU_SLUG,
130 null,
131 'data:image/svg+xml;base64,' . base64_encode( file_get_contents( WP_2FA_PATH . 'dist/images/wp-2fa-white-icon20x28.svg' ) ), // phpcs:ignore
132 81
133 );
134
135 $settings_policies = new Settings_Page_Policies();
136 add_submenu_page(
137 self::TOP_MENU_SLUG,
138 esc_html__( '2FA Policies', 'wp-2fa' ),
139 esc_html__( '2FA Policies', 'wp-2fa' ),
140 'manage_options',
141 self::TOP_MENU_SLUG,
142 array( $settings_policies, 'render' ),
143 1
144 );
145
146 $settings_render = new Settings_Page_Render();
147 add_submenu_page(
148 self::TOP_MENU_SLUG,
149 esc_html__( 'WP 2FA Settings', 'wp-2fa' ),
150 esc_html__( 'Settings', 'wp-2fa' ),
151 'manage_options',
152 'wp-2fa-settings',
153 array( $settings_render, 'render' ),
154 2
155 );
156
157 /**
158 * Fires after the main menu settings are registered.
159 *
160 * @param string - The menu slug.
161 * @param bool - Is that multisite install or not.
162 *
163 * @since 2.0.0
164 */
165 do_action( WP_2FA_PREFIX . 'after_admin_menu_created', self::TOP_MENU_SLUG, true );
166 }
167
168 /**
169 * Get all users
170 *
171 * @SuppressWarnings(PHPMD.ExitExpression)
172 */
173 public function get_all_users() {
174 // Die if user does not have permission to view.
175 if ( ! current_user_can( 'manage_options' ) ) {
176 die( 'Access Denied.' );
177 }
178 // Filter $_GET array for security.
179 $get_array = filter_input_array( INPUT_GET );
180
181 // Die if nonce verification failed.
182 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
183 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
184 }
185
186 $users_args = array(
187 'fields' => array( 'ID', 'user_login' ),
188 );
189 if ( WP_Helper::is_multisite() ) {
190 $users_args['blog_id'] = 0;
191 }
192 $users_data = User_Utils::get_all_user_ids_and_login_names( 'query', $users_args );
193
194 // Create final array which we will fill in below.
195 $users = array();
196
197 foreach ( $users_data as $user ) {
198 if ( strpos( $user['user_login'], $get_array['term'] ) !== false ) {
199 array_push(
200 $users,
201 array(
202 'value' => $user['user_login'],
203 'label' => $user['user_login'],
204 )
205 );
206 }
207 }
208
209 echo wp_json_encode( $users );
210 exit;
211 }
212
213 /**
214 * Get all network sites
215 *
216 * @SuppressWarnings(PHPMD.ExitExpression)
217 */
218 public function get_all_network_sites() {
219 // Die if user does not have permission to view.
220 if ( ! current_user_can( 'manage_options' ) ) {
221 die( 'Access Denied.' );
222 }
223 // Filter $_GET array for security.
224 $get_array = filter_input_array( INPUT_GET );
225 // Die if nonce verification failed.
226 if ( ! wp_verify_nonce( sanitize_text_field( $get_array['wp_2fa_nonce'] ), 'wp-2fa-settings-nonce' ) ) {
227 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
228 }
229 // Fetch sites.
230 $sites_found = array();
231
232 foreach ( get_sites() as $site ) {
233 $subsite_id = get_object_vars( $site )['blog_id'];
234 $subsite_name = get_blog_details( $subsite_id )->blogname;
235 $site_details = '';
236 $site_details[ $subsite_id ] = $subsite_name;
237 if ( false !== stripos( $subsite_name, $get_array['term'] ) ) {
238 array_push(
239 $sites_found,
240 array(
241 'label' => $subsite_id,
242 'value' => $subsite_name,
243 )
244 );
245 }
246 }
247 echo wp_json_encode( $sites_found );
248 exit;
249 }
250
251 /**
252 * Unlock users accounts if they have overrun grace period
253 *
254 * @param int $user_id User ID.
255 *
256 * @SuppressWarnings(PHPMD.ExitExpression)
257 */
258 public function unlock_account( $user_id ) {
259 // Die if user does not have permission to view.
260 if ( ! current_user_can( 'manage_options' ) ) {
261 die( 'Access Denied.' );
262 }
263
264 $grace_period = WP2FA::get_wp2fa_setting( 'grace-period' );
265 $grace_period_denominator = WP2FA::get_wp2fa_setting( 'grace-period-denominator' );
266 $create_a_string = $grace_period . ' ' . $grace_period_denominator;
267 // Turn that string into a time.
268 $grace_expiry = strtotime( $create_a_string );
269
270 // Filter $_GET array for security.
271 $get_array = filter_input_array( INPUT_GET );
272 $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] );
273
274 // Die if nonce verification failed.
275 if ( ! wp_verify_nonce( $nonce, 'wp-2fa-unlock-account-nonce' ) ) {
276 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
277 }
278
279 if ( isset( $get_array['user_id'] ) ) {
280 global $wpdb;
281 $wpdb->query( // phpcs:ignore
282 $wpdb->prepare(
283 "
284 DELETE FROM $wpdb->usermeta
285 WHERE user_id = %d
286 AND meta_key IN ( %s, %s )
287 ",
288 array(
289 intval( $get_array['user_id'] ),
290 User_Helper::USER_GRACE_KEY,
291 WP_2FA_PREFIX . 'locked_account_notification',
292 )
293 )
294 );
295 User_Helper::set_user_expiry_date( $grace_expiry, intval( $get_array['user_id'] ) );
296 $this->send_account_unlocked_email( intval( $get_array['user_id'] ) );
297 add_action( 'admin_notices', array( $this, 'user_unlocked_notice' ) );
298 }
299 }
300
301 /**
302 * Remove user 2fa config
303 *
304 * @param int $user_id User ID.
305 *
306 * @SuppressWarnings(PHPMD.ExitExpression)
307 */
308 public function remove_user_2fa( $user_id ) {
309 // Filter $_GET array for security.
310 $get_array = filter_input_array( INPUT_GET );
311 $nonce = sanitize_text_field( $get_array['wp_2fa_nonce'] );
312
313 if ( ! wp_verify_nonce( $nonce, 'wp-2fa-remove-user-2fa-nonce' ) ) {
314 die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
315 }
316
317 if ( isset( $get_array['user_id'] ) ) {
318 $user_id = intval( $get_array['user_id'] );
319
320 if ( ! current_user_can( 'manage_options' ) && get_current_user_id() !== $user_id ) {
321 return;
322 }
323
324 User_Helper::remove_all_2fa_meta_for_user( $user_id );
325
326 $is_needed = User::is_enforced( $user_id );
327
328 if ( $is_needed ) {
329 if ( 'do-not-enforce' !== WP2FA::get_wp2fa_setting( 'enforcement-policy' ) ) {
330 // Turn inputs into a useable string.
331 $create_a_string = WP2FA::get_wp2fa_setting( 'grace-period' ) . ' ' . WP2FA::get_wp2fa_setting( 'grace-period-denominator' );
332 // Turn that string into a time.
333 $grace_expiry = strtotime( $create_a_string );
334 User_Helper::set_user_expiry_date( $grace_expiry, $user_id );
335 update_user_meta( $user_id, WP_2FA_PREFIX . 'update_nag_dismissed', true );
336 }
337 $grace_policy = WP2FA::get_wp2fa_setting( 'grace-policy' );
338 if ( 'no-grace-period' === $grace_policy ) {
339 User_Helper::set_user_enforced_instantly( true, $user_id );
340 // Set this to a known older value so its already expired.
341 User_Helper::set_user_expiry_date( '1609502400', $user_id );
342 // Get sessions for user with ID $user_id.
343 $sessions = \WP_Session_Tokens::get_instance( $user_id );
344 // Log them out.
345 $sessions->destroy_all();
346 }
347 }
348 if ( isset( $get_array['admin_reset'] ) ) {
349 add_action( 'admin_notices', array( $this, 'admin_deleted_2fa_notice' ) );
350 } else {
351 add_action( 'admin_notices', array( $this, 'user_deleted_2fa_notice' ) );
352 }
353 }
354 }
355
356 /**
357 * Send account unlocked notification via email.
358 *
359 * @param int $user_id user ID.
360 *
361 * @return boolean
362 */
363 public static function send_account_unlocked_email( $user_id ) {
364 // Bail if the user has not enabled this email.
365 if ( 'enable_account_unlocked_email' !== WP2FA::get_wp2fa_email_templates( 'send_account_unlocked_email' ) ) {
366 return false;
367 }
368
369 // Grab user data.
370 $user = get_userdata( $user_id );
371 // Grab user email.
372 $email = $user->user_email;
373 // Setup the email contents.
374 $subject = wp_strip_all_tags( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_subject' ) ) );
375 $message = wpautop( WP2FA::replace_email_strings( WP2FA::get_wp2fa_email_templates( 'user_account_unlocked_email_body' ), $user_id ) );
376
377 return self::send_email( $email, $subject, $message );
378 }
379
380 /**
381 * Hide settings menu item
382 */
383 public function hide_settings() {
384 $user = wp_get_current_user();
385
386 // Check we have a user before doing anything else.
387 if ( is_a( $user, '\WP_User' ) ) {
388 if ( ! empty( WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ) ) ) {
389 $main_user = (int) WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' );
390 } else {
391 $main_user = get_current_user_id();
392 }
393 if ( ! empty( WP2FA::get_wp2fa_general_setting( 'limit_access' ) ) && $user->ID !== $main_user ) {
394 // Remove admin menu item.
395 remove_submenu_page( 'options-general.php', 'wp-2fa-policies' );
396 }
397 }
398 }
399
400 /**
401 * Add unlock user link to user actions.
402 *
403 * @param array $links Default row content.
404 *
405 * @return array
406 * @throws \Freemius_Exception - freemius exception.
407 */
408 public function add_plugin_action_links( $links ) {
409 // add link to the external free trial page in free version and also in premium version if license is not active.
410 if ( ! function_exists( 'wp2fa_freemius' ) || ! wp2fa_freemius()->has_active_valid_license() ) {
411 $trial_link = 'https://wp2fa.io/get-wp-2fa-premium-trial/?utm_source=plugin&utm_medium=referral&utm_campaign=WP2FA';
412 $links = array_merge(
413 array(
414 '<a style="font-weight:bold" href="' . $trial_link . '" target="_blank">' . __( 'Free 14-day Premium Trial', 'wp-2fa' ) . '</a>',
415 ),
416 $links
417 );
418 }
419
420 // add link to the plugin settings page.
421 $url = Settings::get_settings_page_link();
422 $links = array_merge(
423 array(
424 '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Configure 2FA Settings', 'wp-2fa' ) . '</a>',
425 ),
426 $links
427 );
428
429 return $links;
430 }
431
432 /**
433 * User unlocked notice.
434 */
435 public function user_unlocked_notice() {
436 ?>
437 <div class="notice notice-success is-dismissible">
438 <p><?php esc_html_e( 'User account successfully unlocked. User can login again.', 'wp-2fa' ); ?></p>
439 <button type="button" class="notice-dismiss">
440 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
441 </button>
442 </div>
443 <?php
444 }
445
446 /**
447 * User deleted 2FA settings notification
448 */
449 public function user_deleted_2fa_notice() {
450 ?>
451 <div class="notice notice-success is-dismissible">
452 <p><?php esc_html_e( 'Your 2FA settings have been removed.', 'wp-2fa' ); ?></p>
453 <button type="button" class="notice-dismiss">
454 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
455 </button>
456 </div>
457 <?php
458 }
459
460 /**
461 * Admin deleted user 2FA settings notification
462 */
463 public function admin_deleted_2fa_notice() {
464 ?>
465 <div class="notice notice-success is-dismissible">
466 <p><?php esc_html_e( 'User 2FA settings have been removed.', 'wp-2fa' ); ?></p>
467 <button type="button" class="notice-dismiss">
468 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
469 </button>
470 </div>
471 <?php
472 }
473
474 /**
475 * Updates options for multisite
476 *
477 * @return void
478 *
479 * @since 2.0.0
480 */
481 public function update_wp2fa_network_options() {
482
483 $settings_policies = new Settings_Page_Policies();
484
485 $settings_policies->update_wp2fa_network_options();
486
487 Settings_Page_General::update_wp2fa_network_options();
488
489 $settings_white_label = new Settings_Page_White_Label();
490
491 $settings_white_label->update_wp2fa_network_options();
492
493 /**
494 * Gives the ability for extensions to set their settings in the plugin.
495 *
496 * @since 2.2.0
497 */
498 do_action( WP_2FA_PREFIX . 'update_network_settings' );
499 }
500
501 /**
502 * Handle saving email options to the network main site options.
503 */
504 public function update_wp2fa_network_email_options() {
505 $settings_email = new Settings_Page_Email();
506
507 $settings_email->update_wp2fa_network_options();
508 }
509
510 /**
511 * These are used instead of add_settings_error which in a network site. Used to show if settings have been updated or failed.
512 */
513 public function settings_saved_network_admin_notice() {
514 if ( isset( $_GET['wp_2fa_network_settings_updated'] ) && 'true' === $_GET['wp_2fa_network_settings_updated'] ) { // phpcs:ignore
515 ?>
516 <div class="notice notice-success is-dismissible">
517 <p><?php esc_html_e( '2FA Settings Updated', 'wp-2fa' ); ?></p>
518 <button type="button" class="notice-dismiss">
519 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
520 </button>
521 </div>
522 <?php
523 }
524 if ( isset( $_GET['wp_2fa_network_settings_updated'] ) && 'false' === $_GET['wp_2fa_network_settings_updated'] ) { // phpcs:ignore
525 ?>
526 <div class="notice notice-error is-dismissible">
527 <p><?php esc_html_e( 'Please ensure both custom email address and display name are provided.', 'wp-2fa' ); ?></p>
528 <button type="button" class="notice-dismiss">
529 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
530 </button>
531 </div>
532 <?php
533 }
534 if ( isset( $_GET['wp_2fa_network_settings_error'] ) ) { // phpcs:ignore
535 ?>
536 <div class="notice notice-error is-dismissible">
537 <p><?php echo \esc_attr( \esc_url_raw( \urldecode_deep( \wp_unslash( $_GET['wp_2fa_network_settings_error'] ) ) ) ); // phpcs:ignore ?></p>
538 <button type="button" class="notice-dismiss">
539 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
540 </button>
541 </div>
542 <?php
543 }
544 }
545
546 /**
547 * These are used instead of add_settings_error which in a network site. Used to show if settings have been updated or failed.
548 *
549 * @return void
550 *
551 * @since 2.0.0
552 */
553 public function settings_saved_admin_notice() {
554 if ( isset( $_GET['settings-updated'] ) && 'true' === $_GET['settings-updated'] ) { // phpcs:ignore
555 $wp_settings_errors = get_settings_errors();
556
557 if ( count( $wp_settings_errors ) ) {
558 foreach ( $wp_settings_errors as $error ) {
559 ?>
560 <div class="notice notice-<?php echo \esc_attr( $error['type'] ); ?> is-dismissible">
561 <p><?php echo \esc_html( $error['message'] ); ?></p>
562 <button type="button" class="notice-dismiss">
563 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
564 </button>
565 </div>
566 <?php
567 }
568 } else {
569 ?>
570 <div class="notice notice-success is-dismissible">
571 <p><?php esc_html_e( '2FA Settings Updated', 'wp-2fa' ); ?></p>
572 <button type="button" class="notice-dismiss">
573 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
574 </button>
575 </div>
576 <?php
577 }
578 }
579 if ( isset( $_GET['settings-updated'] ) && 'false' === $_GET['settings-updated'] ) { // phpcs:ignore
580 ?>
581 <div class="notice notice-error is-dismissible">
582 <p><?php esc_html_e( 'Please ensure both custom email address and display name are provided.', 'wp-2fa' ); ?></p>
583 <button type="button" class="notice-dismiss">
584 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
585 </button>
586 </div>
587 <?php
588 }
589 if ( isset( $_GET['settings_error'] ) ) { // phpcs:ignore
590 ?>
591 <div class="notice notice-error is-dismissible">
592 <p><?php echo \esc_attr( \esc_url_raw( \urldecode_deep( \wp_unslash( $_GET['settings_error'] ) ) ) ); ?></p>
593 <button type="button" class="notice-dismiss">
594 <span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'wp-2fa' ); ?></span>
595 </button>
596 </div>
597 <?php
598 }
599 }
600
601 /**
602 * Add our custom state to our created page.
603 *
604 * @param array $post_states - array with the post states.
605 * @param WP_Post $post - the WP post.
606 *
607 * @return array
608 */
609 public function add_display_post_states( $post_states, $post ) {
610 if ( ! empty( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) ) ) {
611 if ( WP2FA::get_wp2fa_setting( 'custom-user-page-id' ) === $post->ID ) {
612 $post_states['wp_2fa_page_for_user'] = __( 'WP 2FA User Page', 'wp-2fa' );
613 }
614 }
615
616 return $post_states;
617 }
618
619 /**
620 * Handles sending of an email. It sets necessary header such as content type and custom from email address and name.
621 *
622 * @param string $recipient_email Email address to send message to.
623 * @param string $subject Email subject.
624 * @param string $message Message contents.
625 *
626 * @return bool Whether the email contents were sent successfully.
627 */
628 public static function send_email( $recipient_email, $subject, $message ) {
629
630 // Specify our desired headers.
631 $headers = 'Content-type: text/html;charset=utf-8' . "\r\n";
632
633 if ( 'use-custom-email' === WP2FA::get_wp2fa_email_templates( 'email_from_setting' ) ) {
634 $headers .= 'From: ' . WP2FA::get_wp2fa_email_templates( 'custom_from_display_name' ) . ' <' . WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' ) . '>' . "\r\n";
635 } else {
636 $headers .= 'From: ' . get_bloginfo( 'name' ) . ' <' . get_bloginfo( 'admin_email' ) . '>' . "\r\n";
637 }
638
639 // Fire our email.
640 return wp_mail( $recipient_email, $subject, $message, $headers );
641
642 }
643
644 /**
645 * Turns user roles data in any form and shape to an array of strings.
646 *
647 * @param mixed $value User role names (slugs) as raw value.
648 *
649 * @return string[] List of user role names (slugs).
650 */
651 public static function extract_roles_from_input( $value ) {
652 if ( is_array( $value ) ) {
653 return $value;
654 }
655
656 if ( is_string( $value ) && ! empty( $value ) ) {
657 return explode( ',', $value );
658 }
659
660 return array();
661 }
662
663 /**
664 * Determine if any BG processes are currently running.
665 *
666 * @return int|false Number of jobs.
667 */
668 public function get_current_number_of_active_bg_processes() {
669 global $wpdb;
670
671 $bg_jobs = $wpdb->get_results( // phpcs:ignore
672 "SELECT option_value FROM $wpdb->options
673 WHERE option_name LIKE '%_2fa_bg_%'"
674 );
675
676 return count( $bg_jobs );
677 }
678
679 /**
680 * Checks if the backup codes option is enabled for the role
681 *
682 * @param string $role - The role name.
683 *
684 * @return bool
685 */
686 public static function are_backup_codes_enabled( $role = 'global' ) {
687
688 $role = ( is_null( $role ) || empty( $role ) ) ? 'global' : $role;
689
690 if ( ! isset( self::$backup_codes_enabled[ $role ] ) ) {
691 self::$backup_codes_enabled[ $role ] = false;
692
693 if ( 'global' === $role ) {
694 $setting_value = Settings::get_role_or_default_setting( 'backup_codes_enabled' );
695 } else {
696 $setting_value = Settings::get_role_or_default_setting( 'backup_codes_enabled', 'current', $role );
697 }
698 self::$backup_codes_enabled[ $role ] = Settings_Utils::string_to_bool( $setting_value );
699 }
700
701 return self::$backup_codes_enabled[ $role ];
702 }
703 }
704