PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 4.0.0
WP 2FA – Two-factor authentication for WordPress v4.0.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 / functions / core.php
wp-2fa / includes / functions Last commit date
core.php 13 hours ago index.php 13 hours ago login-header.php 13 hours ago
core.php
1283 lines
1 <?php
2 /**
3 * Core plugin functionality.
4 *
5 * @package WP2FA
6 */
7
8 namespace WP2FA\Core;
9
10 use WP2FA\WP2FA;
11 use WP2FA\Utils\Settings_Utils;
12 use WP2FA\Admin\Helpers\WP_Helper;
13 use WP2FA\Admin\Views\Re_Login_2FA;
14 use WP2FA\Admin\Helpers\User_Helper;
15 use WP2FA\Licensing\Licensing_Factory;
16
17 /**
18 * Default setup routine
19 *
20 * @return void
21 */
22 function setup() {
23 $n = function ( $function ) {
24 return __NAMESPACE__ . "\\$function";
25 };
26
27 add_action( 'init', $n( 'i18n' ) );
28 add_action( 'init', $n( 'init' ) );
29 add_action( 'admin_enqueue_scripts', $n( 'register_dialog_assets' ), 5 );
30 add_action( 'wp_enqueue_scripts', $n( 'register_dialog_assets' ), 5 );
31 add_action( 'login_enqueue_scripts', $n( 'register_dialog_assets' ), 5 );
32 add_action( 'admin_enqueue_scripts', $n( 'admin_scripts' ) );
33 add_action( 'admin_enqueue_scripts', $n( 'admin_styles' ) );
34 add_action( 'admin_head', $n( 'admin_menu_icon_css' ) );
35
36 // Hook to allow async or defer on asset loading.
37 add_filter( 'script_loader_tag', $n( 'script_loader_tag' ), 10, 2 );
38
39 /**
40 * Fires after the plugin is loaded.
41 *
42 * @since 2.0.0
43 */
44 do_action( WP_2FA_PREFIX . 'loaded' );
45 }
46
47 /**
48 * Register the unified dialog JS and CSS so extensions can depend on them.
49 *
50 * @return void
51 *
52 * @since 4.0.0
53 */
54 function register_dialog_assets() {
55 \wp_register_script(
56 'wp2fa-dialog',
57 WP_2FA_URL . 'js/wp2fa-dialog.js',
58 array(),
59 WP_2FA_VERSION,
60 true
61 );
62
63 \wp_register_style(
64 'wp2fa-dialog',
65 WP_2FA_URL . 'css/wp2fa-dialog.css',
66 array(),
67 WP_2FA_VERSION
68 );
69 }
70
71 /**
72 * Registers the default textdomain.
73 *
74 * @return void
75 */
76 function i18n() {
77 $locale = apply_filters( 'plugin_locale', determine_locale(), 'wp-2fa' );
78 load_textdomain( 'wp-2fa', WP_LANG_DIR . '/wp-2fa/wp-2fa-' . $locale . '.mo' );
79 load_plugin_textdomain( 'wp-2fa', false, plugin_basename( WP_2FA_PATH ) . '/languages/' );
80 }
81
82 /**
83 * Initializes the plugin and fires an action other plugins can hook into.
84 *
85 * @return void
86 */
87 function init() {
88
89 /**
90 * Fires when plugin is initiated.
91 *
92 * @since 2.0.0
93 */
94 do_action( WP_2FA_PREFIX . 'init' );
95 }
96
97 /**
98 * Activate the plugin
99 *
100 * @return void
101 */
102 function activate() {
103 // First load the init scripts in case any rewrite functionality is being loaded.
104 init();
105 flush_rewrite_rules();
106
107 // Check if the user is allowed to manage options for the site.
108 if ( current_user_can( 'manage_options' ) ) {
109 // Add an option to let our plugin know this user has not been through the setup wizard.
110 Settings_Utils::update_option( 'redirect_on_activate', true );
111 }
112
113 // Add plugin version to wp_options.
114 Settings_Utils::update_option( 'plugin_version', WP_2FA_VERSION );
115 }
116
117 /**
118 * Deactivate the plugin
119 *
120 * Uninstall routines should be in uninstall.php
121 *
122 * @return void
123 */
124 function deactivate() {
125 }
126
127 /**
128 * Uninstall the plugin
129 *
130 * @return void
131 */
132 function uninstall() {
133 WP2FA::init();
134 if ( ! empty( WP2FA::get_wp2fa_general_setting( 'delete_data_upon_uninstall' ) ) ) {
135 // Delete settings from wp_options.
136 global $wpdb;
137 if ( WP_Helper::is_multisite() ) {
138 $network_id = get_current_network_id();
139 $wpdb->query(
140 $wpdb->prepare(
141 "
142 DELETE FROM $wpdb->sitemeta
143 WHERE meta_key LIKE %s
144 AND site_id = %d
145 ",
146 '%wp_2fa_%',
147 $network_id
148 )
149 );
150 } else {
151 $wpdb->query(
152 $wpdb->prepare(
153 "
154 DELETE FROM $wpdb->options
155 WHERE option_name LIKE %s
156 ",
157 '%wp_2fa_%'
158 )
159 );
160 }
161
162 $wpdb->query(
163 $wpdb->prepare(
164 "
165 DELETE FROM $wpdb->usermeta
166 WHERE meta_key LIKE %s
167 ",
168 WP_2FA_PREFIX . 'wp_2fa_%'
169 )
170 );
171 }
172 }
173
174 /**
175 * The list of known contexts for enqueuing scripts/styles.
176 *
177 * @return array
178 */
179 function get_enqueue_contexts() {
180 return array( 'admin', 'frontend', 'shared' );
181 }
182
183 /**
184 * Generate an URL to a script, taking into account whether SCRIPT_DEBUG is enabled.
185 *
186 * @param string $script Script file name (no .js extension).
187 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
188 *
189 * @return string|\WP_Error URL
190 */
191 function script_url( $script, $context ) {
192
193 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
194 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA script loader.' );
195 }
196
197 return WP_2FA_URL . 'dist/js/' . sanitize_file_name( $script ) . '.js';
198 }
199
200 /**
201 * Generate an URL to a stylesheet, taking into account whether SCRIPT_DEBUG is enabled.
202 *
203 * @param string $stylesheet Stylesheet file name (no .css extension).
204 * @param string $context Context for the script ('admin', 'frontend', or 'shared').
205 *
206 * @return string|\WP_Error URL
207 */
208 function style_url( $stylesheet, $context ) {
209
210 if ( ! in_array( $context, get_enqueue_contexts(), true ) ) {
211 return new \WP_Error( 'invalid_enqueue_context', 'Invalid $context specified in WP2FA stylesheet loader.' );
212 }
213
214 return WP_2FA_URL . 'dist/css/' . sanitize_file_name( $stylesheet ) . '.css';
215 }
216
217 /**
218 * Enqueue scripts for admin.
219 *
220 * @return void
221 */
222 function admin_scripts() {
223
224 global $pagenow;
225
226 // Get page argument from $_GET array.
227 $page = ( isset( $_GET['page'] ) ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
228 if ( ( empty( $page ) || false === strpos( $page, 'wp-2fa' ) ) && 'profile.php' !== $pagenow ) {
229 return;
230 }
231
232 \wp_enqueue_script(
233 'wp_2fa_admin',
234 script_url( 'admin', 'admin' ),
235 array( 'jquery-ui-widget', 'jquery-ui-core', 'jquery-ui-autocomplete', 'wp_2fa_micro_modals', 'select2', 'wp-i18n' ),
236 WP_2FA_VERSION,
237 true
238 );
239
240 \wp_enqueue_script(
241 'wp_2fa_micro_modals',
242 script_url( 'micromodal', 'admin', 'wp-i18n' ),
243 array(),
244 WP_2FA_VERSION,
245 true
246 );
247
248 enqueue_select2_scripts();
249
250 // Data array.
251 $data_array = array(
252 'ajaxURL' => \admin_url( 'admin-ajax.php' ),
253 'roles' => WP_Helper::get_roles_wp(),
254 'nonce' => wp_create_nonce( 'wp-2fa-settings-nonce' ),
255 'dismissNonce' => wp_create_nonce( 'wp-2fa-dismiss-nag' ),
256 'codeValidatedHeading' => esc_html__( 'Congratulations', 'wp-2fa' ),
257 'codeValidatedText' => esc_html__( 'Your account just got more secure', 'wp-2fa' ),
258 'codeValidatedButton' => __( 'Close Wizard & Refresh', 'wp-2fa' ),
259 'processingText' => esc_html__( 'Processing Update', 'wp-2fa' ),
260 'email_sent_success' => esc_html__( 'Email successfully sent', 'wp-2fa' ),
261 'email_sent_failure' => esc_html__( 'Email delivery failed', 'wp-2fa' ),
262 'invalidEmail' => esc_html__( 'Please use a valid email address', 'wp-2fa' ),
263 'license_validation_in_progress' => esc_html__( 'Validating your license, please wait...', 'wp-2fa' ),
264 );
265 wp_localize_script( 'wp_2fa_admin', 'wp2faData', $data_array );
266
267 $re_login = Settings_Utils::get_setting_role( User_Helper::get_user_role(), Re_Login_2FA::RE_LOGIN_SETTINGS_NAME );
268
269 $role = User_Helper::get_user_role();
270
271 $redirect_page = \sanitize_text_field( Settings_Utils::get_setting_role( $role, 'redirect-user-custom-page' ) );
272 $redirect_page_global = \sanitize_text_field( Settings_Utils::get_setting_role( null, 'redirect-user-custom-page' ) );
273 $redirect_page_global_setting = \sanitize_text_field( Settings_Utils::get_setting_role( $role, 'redirect-user-custom-page-global' ) );
274
275 // Priority: role-specific redirect-user-custom-page > global redirect-user-custom-page > redirect-user-custom-page-global > empty.
276 if ( '' !== trim( (string) $redirect_page ) ) {
277 $redirect_to_url = \trailingslashit( get_site_url() ) . $redirect_page;
278 } elseif ( '' !== trim( (string) $redirect_page_global ) ) {
279 $redirect_to_url = \trailingslashit( get_site_url() ) . $redirect_page_global;
280 } elseif ( '' !== trim( (string) $redirect_page_global_setting ) ) {
281 $redirect_to_url = \trailingslashit( get_site_url() ) . $redirect_page_global_setting;
282 } else {
283 $redirect_to_url = '';
284 }
285
286 $data_array = array(
287 'ajaxURL' => \admin_url( 'admin-ajax.php' ),
288 'nonce' => wp_create_nonce( 'wp2fa-verify-wizard-page' ),
289 'codesPreamble' => esc_html__( 'These are the 2FA backup codes for the user', 'wp-2fa' ),
290 'readyText' => esc_html__( 'I\'m ready', 'wp-2fa' ),
291 'codeReSentText' => esc_html__( 'New code sent', 'wp-2fa' ),
292 'backupCodesSent' => esc_html__( 'Backup codes sent', 'wp-2fa' ),
293 'reLoginEnabled' => Re_Login_2FA::ENABLED_SETTING_VALUE,
294 'reLogin' => $re_login,
295 'loginUrl' => \wp_login_url(),
296 'redirectToUrl' => $redirect_to_url,
297 );
298 wp_localize_script( 'wp_2fa_admin', 'wp2faWizardData', $data_array );
299
300 // Secret field visibility toggle (eye icon).
301 \wp_add_inline_script(
302 'wp_2fa_admin',
303 '(function(){document.addEventListener("click",function(e){var btn=e.target.closest(".wp2fa-secret-toggle");if(!btn)return;e.preventDefault();var wrap=btn.closest(".wp2fa-secret-field-wrap");if(!wrap)return;var input=wrap.querySelector(".wp2fa-secret-field");if(!input)return;var isVisible=input.classList.toggle("wp2fa-secret-visible");btn.setAttribute("aria-label",isVisible?"Hide":"Show");var use=btn.querySelector("use");if(use){use.setAttribute("href",isVisible?"#wp2fa-icon-eye-off":"#wp2fa-icon-eye");}});})();'
304 );
305
306 \wp_enqueue_script( 'wp2fa-dialog' );
307 \wp_enqueue_style( 'wp2fa-dialog' );
308
309 \wp_enqueue_script(
310 'wp2fa-premium-badge-dialog',
311 WP_2FA_URL . 'js/wp2fa-premium-badge-dialog.js',
312 array( 'wp2fa-dialog' ),
313 file_exists( WP_2FA_PATH . 'js/wp2fa-premium-badge-dialog.js' ) ? (string) filemtime( WP_2FA_PATH . 'js/wp2fa-premium-badge-dialog.js' ) : WP_2FA_VERSION,
314 true
315 );
316
317 $tab = ( isset( $_GET['tab'] ) ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
318 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
319
320 wp_localize_script(
321 'wp2fa-premium-badge-dialog',
322 'wp2faPremiumBadgeDialog',
323 array(
324 'enabled' => ! Licensing_Factory::has_active_valid_license(),
325 'currentPage' => $page,
326 'currentTab' => $tab,
327 'currentScreen' => $screen ? $screen->id : '',
328 'dismissLabel' => esc_html__( 'Close', 'wp-2fa' ),
329 'pages' => get_premium_badge_dialog_pages(),
330 )
331 );
332 }
333
334 /**
335 * Returns the content map for premium badge dialogs.
336 *
337 * Keys should match admin page slugs (e.g. wp-2fa-policies) or use:
338 * - "slug:tab" for tab-specific content (e.g. wp-2fa-policies:passkeys)
339 * - "tab:<tab>" for any page tab match
340 * - "screen:<screen-id>" for WP screen id matches
341 * - "default" as fallback
342 *
343 * @return array
344 */
345 function get_premium_badge_dialog_pages() {
346 $hl = '<span class="wp2fa-dialog-title-highlight">';
347
348 $default_page = array(
349 'title' => esc_html__( 'Unlock', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium Features', 'wp-2fa' ) . '</span>',
350 'intro' => esc_html__( 'Upgrade to WP 2FA Premium to unlock advanced authentication options and stronger security controls.', 'wp-2fa' ),
351 'description' => esc_html__( 'Use this dialog content map to define page-specific upsell messaging.', 'wp-2fa' ),
352 'screenshotUrl' => esc_url_raw( WP_2FA_URL . 'includes/assets/images/reports-teaser-preview.png' ),
353 'bullets' => array(
354 array(
355 'title' => esc_html__( 'Upsell point', 'wp-2fa' ),
356 'description' => esc_html__( 'Optional description', 'wp-2fa' ),
357 ),
358 array(
359 'title' => esc_html__( 'Upsell point', 'wp-2fa' ),
360 'description' => esc_html__( 'Optional description', 'wp-2fa' ),
361 ),
362 ),
363 'cta' => array(
364 'text' => esc_html__( 'View Premium Plans', 'wp-2fa' ),
365 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-badge-dialog' ),
366 ),
367 );
368
369 $pages = array(
370 'default' => $default_page,
371 'wp-2fa-policies' => array(
372 'title' => esc_html__( 'Unlock 2FA policies per user role with the', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium edition', 'wp-2fa' ) . '</span>',
373 'intro' => esc_html__( 'Apply different 2FA requirements to administrators, editors, customers, members, and other user roles to balance security and user experience.', 'wp-2fa' ),
374 'description' => '',
375 'screenshotUrl' => '',
376 'bullets' => array(),
377 'cta' => array(
378 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
379 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-custom-policies-per-role' ),
380 ),
381 ),
382 'policies-banner' => array(
383 'title' => esc_html__( 'Set different 2FA policies for each user role', 'wp-2fa' ),
384 'intro' => esc_html__( 'Apply different two-factor authentication requirements to each user role on your website.', 'wp-2fa' ),
385 'description' => '',
386 'screenshotUrl' => '',
387 'bullets' => array(
388 array(
389 'title' => esc_html__( 'Protect high-risk users with stronger authentication', 'wp-2fa' ),
390 'description' => '',
391 ),
392 array(
393 'title' => esc_html__( 'Balance security and usability for every team', 'wp-2fa' ),
394 'description' => '',
395 ),
396 array(
397 'title' => esc_html__( 'Reduce support requests with a smoother rollout', 'wp-2fa' ),
398 'description' => '',
399 ),
400 ),
401 'cta' => array(
402 'text' => esc_html__( 'Unlock role-based policies', 'wp-2fa' ),
403 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=policies-banner-badge' ),
404 ),
405 ),
406 'settings-banner' => array(
407 'title' => esc_html__( 'Unlock advanced settings', 'wp-2fa' ),
408 'intro' => esc_html__( 'Customize authentication, integrate with more WordPress plugins, and manage security settings across multiple websites.', 'wp-2fa' ),
409 'description' => '',
410 'screenshotUrl' => '',
411 'bullets' => array(
412 array(
413 'title' => esc_html__( 'Offer users more ways to authenticate', 'wp-2fa' ),
414 'description' => '',
415 ),
416 array(
417 'title' => esc_html__( 'Extend 2FA to more login workflows', 'wp-2fa' ),
418 'description' => '',
419 ),
420 array(
421 'title' => esc_html__( 'Export and import settings between websites', 'wp-2fa' ),
422 'description' => '',
423 ),
424 ),
425 'cta' => array(
426 'text' => esc_html__( 'Unlock advanced settings', 'wp-2fa' ),
427 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=settings-banner-badge' ),
428 ),
429 ),
430 'wp-2fa-policies-methods' => array(
431 'title' => esc_html__( 'Unlock more 2FA methods with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
432 'intro' => esc_html__( 'Give every user a secure authentication method that works for them, whether they prefer passkeys, SMS, security keys, email verification, or authenticator apps.', 'wp-2fa' ),
433 'description' => '',
434 'screenshotUrl' => '',
435 'bullets' => array(
436 array(
437 'title' => esc_html__( 'Improve user adoption', 'wp-2fa' ),
438 'description' => esc_html__( 'Let users choose the authentication method they prefer', 'wp-2fa' ),
439 ),
440 array(
441 'title' => esc_html__( 'Reduce account lockouts', 'wp-2fa' ),
442 'description' => esc_html__( 'Allow users to verify their identity with backup authentication methods', 'wp-2fa' ),
443 ),
444 array(
445 'title' => esc_html__( 'Lower support overhead', 'wp-2fa' ),
446 'description' => esc_html__( 'Help users regain access without administrator intervention', 'wp-2fa' ),
447 ),
448 ),
449 'cta' => array(
450 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
451 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-2fa-method' ),
452 ),
453 ),
454 'screen:toplevel_page_wp-2fa-policies' => array(
455 'title' => esc_html__( 'Unlock 2FA policies per user role with the', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium edition', 'wp-2fa' ) . '</span>',
456 'intro' => esc_html__( 'Apply different 2FA requirements to administrators, editors, customers, members, and other user roles to balance security and user experience.', 'wp-2fa' ),
457 'description' => '',
458 'screenshotUrl' => '',
459 'bullets' => array(),
460 'cta' => array(
461 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
462 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-custom-policies-per-role' ),
463 ),
464 ),
465 'screen:toplevel_page_wp-2fa-policies-network' => array(
466 'title' => esc_html__( 'Unlock 2FA policies per user role with the', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium edition', 'wp-2fa' ) . '</span>',
467 'intro' => esc_html__( 'Apply different 2FA requirements to administrators, editors, customers, members, and other user roles to balance security and user experience.', 'wp-2fa' ),
468 'description' => '',
469 'screenshotUrl' => '',
470 'bullets' => array(),
471 'cta' => array(
472 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
473 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-custom-policies-per-role' ),
474 ),
475 ),
476 'wp-2fa-passkeys' => array(
477 'title' => esc_html__( 'Unlock Advanced Passkey Management with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
478 'intro' => '', //esc_html__( 'Give your users a faster, phishing-resistant way to log in and keep full control over how passkeys are used across your website.', 'wp-2fa' ),
479 'description' => esc_html__( 'Give your users a faster, phishing-resistant way to log in and keep full control over how passkeys are used across your website.', 'wp-2fa' ),
480 'screenshotUrl' => '',
481 'bullets' => array(
482 array(
483 'title' => esc_html__( 'Allow users to register multiple passkeys per account', 'wp-2fa' ),
484 'description' => '',
485 ),
486 array(
487 'title' => esc_html__( 'Enable or restrict passkeys for specific user roles', 'wp-2fa' ),
488 'description' => '',
489 ),
490 array(
491 'title' => esc_html__( 'Require an additional 2FA verification step for sensitive accounts', 'wp-2fa' ),
492 'description' => '',
493 ),
494 array(
495 'title' => esc_html__( 'Give users a secure, passwordless login experience', 'wp-2fa' ),
496 'description' => '',
497 ),
498 ),
499 'cta' => array(
500 'text' => esc_html__( 'Upgrade to Premium', 'wp-2fa' ),
501 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-passkeys' ),
502 ),
503 ),
504 'screen:wp-2fa_page_wp-2fa-passkeys' => array(
505 'title' => esc_html__( 'Unlock Advanced Passkey Management with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
506 'intro' => '', //esc_html__( 'Give your users a faster, phishing-resistant way to log in and keep full control over how passkeys are used across your website.', 'wp-2fa' ),
507 'description' => esc_html__( 'Give your users a faster, phishing-resistant way to log in and keep full control over how passkeys are used across your website.', 'wp-2fa' ),
508 'screenshotUrl' => '',
509 'bullets' => array(
510 array(
511 'title' => esc_html__( 'Allow users to register multiple passkeys per account', 'wp-2fa' ),
512 'description' => '',
513 ),
514 array(
515 'title' => esc_html__( 'Enable or restrict passkeys for specific user roles', 'wp-2fa' ),
516 'description' => '',
517 ),
518 array(
519 'title' => esc_html__( 'Require an additional 2FA verification step for sensitive accounts', 'wp-2fa' ),
520 'description' => '',
521 ),
522 array(
523 'title' => esc_html__( 'Give users a secure, passwordless login experience', 'wp-2fa' ),
524 'description' => '',
525 ),
526 ),
527 'cta' => array(
528 'text' => esc_html__( 'Upgrade to Premium', 'wp-2fa' ),
529 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-passkeys' ),
530 ),
531 ),
532 'screen:wp-2fa_page_wp-2fa-passkeys-network' => array(
533 'title' => esc_html__( 'Unlock Advanced Passkey Management with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
534 'intro' => '', //esc_html__( 'Give your users a faster, phishing-resistant way to log in and keep full control over how passkeys are used across your website.', 'wp-2fa' ),
535 'description' => esc_html__( 'Give your users a faster, phishing-resistant way to log in and keep full control over how passkeys are used across your website.', 'wp-2fa' ),
536 'screenshotUrl' => '',
537 'bullets' => array(
538 array(
539 'title' => esc_html__( 'Allow users to register multiple passkeys per account', 'wp-2fa' ),
540 'description' => '',
541 ),
542 array(
543 'title' => esc_html__( 'Enable or restrict passkeys for specific user roles', 'wp-2fa' ),
544 'description' => '',
545 ),
546 array(
547 'title' => esc_html__( 'Require an additional 2FA verification step for sensitive accounts', 'wp-2fa' ),
548 'description' => '',
549 ),
550 array(
551 'title' => esc_html__( 'Give users a secure, passwordless login experience', 'wp-2fa' ),
552 'description' => '',
553 ),
554 ),
555 'cta' => array(
556 'text' => esc_html__( 'Upgrade to Premium', 'wp-2fa' ),
557 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-passkeys' ),
558 ),
559 ),
560 'wp-2fa-policies:method-oob' => array(
561 'title' => esc_html__( 'Authenticate with a one-time email login link', 'wp-2fa' ),
562 'intro' => esc_html__( 'Let users skip the code entirely. Once they enter their username and password, send a secure one-time link straight to their inbox.', 'wp-2fa' ),
563 'description' => '',
564 'screenshotUrl' => '',
565 'bullets' => array(
566 array(
567 'title' => esc_html__( 'Removes the step of typing in a verification code', 'wp-2fa' ),
568 'description' => '',
569 ),
570 array(
571 'title' => esc_html__( 'Familiar and frictionless, most users already trust email links', 'wp-2fa' ),
572 'description' => '',
573 ),
574 array(
575 'title' => esc_html__( 'Works on any device with access to their inbox, no extra app required', 'wp-2fa' ),
576 'description' => '',
577 ),
578 array(
579 'title' => esc_html__( 'Flexible authentication option alongside other methods', 'wp-2fa' ),
580 'description' => '',
581 ),
582 ),
583 'cta' => array(
584 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
585 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/#utm_source=plugin&utm_medium=wp2fa&utm_campaign=2fa-premium-method-oob' ),
586 ),
587 ),
588 'wp-2fa-policies:method-yubikey' => array(
589 'title' => esc_html__( 'Add hardware-backed account protection', 'wp-2fa' ),
590 'intro' => esc_html__( 'Allow users to authenticate using YubiKey security keys for stronger protection against phishing and account compromise.', 'wp-2fa' ),
591 'description' => '',
592 'screenshotUrl' => '',
593 'bullets' => array(
594 array(
595 'title' => esc_html__( 'Hardware-based authentication', 'wp-2fa' ),
596 'description' => '',
597 ),
598 array(
599 'title' => esc_html__( 'Resistant to phishing attacks', 'wp-2fa' ),
600 'description' => '',
601 ),
602 array(
603 'title' => esc_html__( 'Trusted by security-conscious organizations', 'wp-2fa' ),
604 'description' => '',
605 ),
606 array(
607 'title' => esc_html__( 'Ideal for administrators and privileged users', 'wp-2fa' ),
608 'description' => '',
609 ),
610 ),
611 'cta' => array(
612 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
613 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/#utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-2fa-method-yubikey' ),
614 ),
615 ),
616 'wp-2fa-policies:method-0setup' => array(
617 'title' => esc_html__( 'Enable two-factor authentication instantly, with zero setup', 'wp-2fa' ),
618 'intro' => esc_html__( 'Users receive one-time verification codes via email, making it easy to roll out 2FA across your website.', 'wp-2fa' ),
619 'description' => '',
620 'screenshotUrl' => '',
621 'bullets' => array(
622 array(
623 'title' => esc_html__( 'No apps or hardware required', 'wp-2fa' ),
624 'description' => '',
625 ),
626 array(
627 'title' => esc_html__( 'Fast and simple user onboarding', 'wp-2fa' ),
628 'description' => '',
629 ),
630 array(
631 'title' => esc_html__( 'Works with every email-enabled website', 'wp-2fa' ),
632 'description' => '',
633 ),
634 array(
635 'title' => esc_html__( 'Helps improve 2FA adoption rates', 'wp-2fa' ),
636 'description' => '',
637 ),
638 ),
639 'cta' => array(
640 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
641 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa#utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-2fa-method-0setup' ),
642 ),
643 ),
644 'wp-2fa-policies:method-sms' => array(
645 'title' => esc_html__( 'Authenticate with SMS verification codes', 'wp-2fa' ),
646 'intro' => esc_html__( 'Send one-time authentication codes via SMS to provide users with a familiar login verification method.', 'wp-2fa' ),
647 'description' => '',
648 'screenshotUrl' => '',
649 'bullets' => array(
650 array(
651 'title' => esc_html__( 'Deliver codes directly to users\' phones', 'wp-2fa' ),
652 'description' => '',
653 ),
654 array(
655 'title' => esc_html__( 'Easy for users to understand and adopt', 'wp-2fa' ),
656 'description' => '',
657 ),
658 array(
659 'title' => esc_html__( 'Supports a wide range of devices', 'wp-2fa' ),
660 'description' => '',
661 ),
662 array(
663 'title' => esc_html__( 'Flexible authentication option alongside other methods', 'wp-2fa' ),
664 'description' => '',
665 ),
666 ),
667 'cta' => array(
668 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
669 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa#utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-2fa-method-sms' ),
670 ),
671 ),
672 'wp-2fa-policies:backup-email' => array(
673 'title' => esc_html__( 'Help users recover access safely', 'wp-2fa' ),
674 'intro' => esc_html__( 'Allow users to fall back to email-based verification if they lose access to their primary authentication method.', 'wp-2fa' ),
675 'description' => '',
676 'screenshotUrl' => '',
677 'bullets' => array(
678 array(
679 'title' => esc_html__( 'Reduce account lockouts', 'wp-2fa' ),
680 'description' => '',
681 ),
682 array(
683 'title' => esc_html__( 'Provide a secure recovery option', 'wp-2fa' ),
684 'description' => '',
685 ),
686 array(
687 'title' => esc_html__( 'Improve user experience', 'wp-2fa' ),
688 'description' => '',
689 ),
690 array(
691 'title' => esc_html__( 'Maintain access without compromising security', 'wp-2fa' ),
692 'description' => '',
693 ),
694 ),
695 'cta' => array(
696 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
697 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa#utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-2fa-method-backup-email' ),
698 ),
699 ),
700 'wp-2fa-passkeys:bypass-2fa' => array(
701 'title' => esc_html__( 'Choose whether passkey login requires additional 2FA', 'wp-2fa' ),
702 'intro' => esc_html__( 'Control how passkeys and two-factor authentication work together. Let users bypass the extra 2FA step after a successful passkey login for a faster experience, or require both for an added layer of protection on accounts that need it.', 'wp-2fa' ),
703 'description' => '',
704 'screenshotUrl' => '',
705 'bullets' => array(
706 array(
707 'title' => esc_html__( 'Stack passkey + 2FA for maximum protection', 'wp-2fa' ),
708 'description' => '',
709 ),
710 array(
711 'title' => esc_html__( 'Faster login for trusted users', 'wp-2fa' ),
712 'description' => '',
713 ),
714 array(
715 'title' => esc_html__( 'Balance convenience and security', 'wp-2fa' ),
716 'description' => '',
717 ),
718 ),
719 'cta' => array(
720 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
721 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/#utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-passkeys-bypass-feature' ),
722 ),
723 ),
724 'wp-2fa-passkeys:enforce-roles' => array(
725 'title' => esc_html__( 'Require passkeys for selected user roles', 'wp-2fa' ),
726 'intro' => esc_html__( 'Control which users can authenticate with passkeys by enabling or requiring them for specific roles on your website.', 'wp-2fa' ),
727 'description' => '',
728 'screenshotUrl' => '',
729 'bullets' => array(
730 array(
731 'title' => esc_html__( 'Apply passkey policies per user role', 'wp-2fa' ),
732 'description' => '',
733 ),
734 array(
735 'title' => esc_html__( 'Secure administrator and privileged accounts', 'wp-2fa' ),
736 'description' => '',
737 ),
738 array(
739 'title' => esc_html__( 'Roll out passkeys gradually across your site', 'wp-2fa' ),
740 'description' => '',
741 ),
742 array(
743 'title' => esc_html__( 'Maintain flexibility for different user groups', 'wp-2fa' ),
744 'description' => '',
745 ),
746 ),
747 'cta' => array(
748 'text' => esc_html__( 'Unlock with Premium', 'wp-2fa' ),
749 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/#utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-passkeys' ),
750 ),
751 ),
752 'wp-2fa-settings' => array(
753 'title' => esc_html__( 'Unlock advanced integrations & management tools with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
754 'intro' => esc_html__( 'Integrate WP 2FA with more authentication providers, connect it with popular WordPress plugins, and quickly migrate settings between websites.', 'wp-2fa' ),
755 'description' => '',
756 'screenshotUrl' => '',
757 'bullets' => array(
758 array(
759 'title' => esc_html__( 'More authentication options', 'wp-2fa' ),
760 'description' => esc_html__( 'Integrate with additional 2FA providers such as SMS, passkeys and hardware security keys including YubiKey', 'wp-2fa' ),
761 ),
762 array(
763 'title' => esc_html__( 'WooCommerce integration', 'wp-2fa' ),
764 'description' => esc_html__( 'Add 2FA settings to the WooCommerce customer portal with one click. No custom code required.', 'wp-2fa' ),
765 ),
766 array(
767 'title' => esc_html__( 'Save time managing websites', 'wp-2fa' ),
768 'description' => esc_html__( 'Export and import settings between sites in just a few clicks', 'wp-2fa' ),
769 ),
770 ),
771 'cta' => array(
772 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
773 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page' ),
774 ),
775 ),
776 'export-import' => array(
777 'title' => esc_html__( 'Move settings between websites', 'wp-2fa' ),
778 'intro' => '',
779 'description' => esc_html__( 'Export and import WP 2FA configurations to quickly deploy consistent security policies across multiple websites.', 'wp-2fa' ),
780 'screenshotUrl' => '',
781 'bullets' => array(
782 array(
783 'title' => esc_html__( 'Save time during setup and deployment', 'wp-2fa' ),
784 'description' => '',
785 ),
786 array(
787 'title' => esc_html__( 'Standardize security settings', 'wp-2fa' ),
788 'description' => '',
789 ),
790 array(
791 'title' => esc_html__( 'Simplify multi-site management', 'wp-2fa' ),
792 'description' => '',
793 ),
794 array(
795 'title' => esc_html__( 'Ideal for agencies and administrators', 'wp-2fa' ),
796 'description' => '',
797 ),
798 ),
799 'cta' => array(
800 'text' => esc_html__( 'Unlock Advanced Management', 'wp-2fa' ),
801 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page-export-import' ),
802 ),
803 ),
804 'provider-integrations' => array(
805 'title' => esc_html__( 'Offer more ways to authenticate', 'wp-2fa' ),
806 'intro' => '',
807 'description' => esc_html__( 'Give users the flexibility to choose the authentication method that best fits their workflow and security requirements.', 'wp-2fa' ),
808 'screenshotUrl' => '',
809 'bullets' => array(
810 array(
811 'title' => esc_html__( 'Passkeys for passwordless authentication', 'wp-2fa' ),
812 'description' => '',
813 ),
814 array(
815 'title' => esc_html__( 'YubiKey hardware security key support', 'wp-2fa' ),
816 'description' => '',
817 ),
818 array(
819 'title' => esc_html__( 'SMS verification codes via Twilio', 'wp-2fa' ),
820 'description' => '',
821 ),
822 array(
823 'title' => esc_html__( 'Email login links and zero-setup email 2FA', 'wp-2fa' ),
824 'description' => '',
825 ),
826 ),
827 'cta' => array(
828 'text' => esc_html__( 'Unlock More Authentication Methods', 'wp-2fa' ),
829 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page-provider-integrations' ),
830 ),
831 ),
832 'plugin-integrations' => array(
833 'title' => esc_html__( 'Seamlessly integrate with WordPress plugins', 'wp-2fa' ),
834 'intro' => '',
835 'description' => esc_html__( 'Add two-factor authentication to popular WordPress plugins and custom login workflows with minimal configuration.', 'wp-2fa' ),
836 'screenshotUrl' => '',
837 'bullets' => array(
838 array(
839 'title' => esc_html__( 'One-click WooCommerce integration', 'wp-2fa' ),
840 'description' => '',
841 ),
842 array(
843 'title' => esc_html__( 'Support custom login pages and workflows', 'wp-2fa' ),
844 'description' => '',
845 ),
846 array(
847 'title' => esc_html__( 'Protect more user journeys across your website', 'wp-2fa' ),
848 'description' => '',
849 ),
850 array(
851 'title' => esc_html__( 'Extend 2FA beyond the standard WordPress login', 'wp-2fa' ),
852 'description' => '',
853 ),
854 ),
855 'cta' => array(
856 'text' => esc_html__( 'Upgrade to Premium', 'wp-2fa' ),
857 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page-plugin-integrations' ),
858 ),
859 ),
860 'wp-2fa-settings-new' => array(
861 'title' => esc_html__( 'Unlock advanced integrations & management tools with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
862 'intro' => esc_html__( 'Integrate WP 2FA with more authentication providers, connect it with popular WordPress plugins, and quickly migrate settings between websites.', 'wp-2fa' ),
863 'description' => '',
864 'screenshotUrl' => '',
865 'bullets' => array(
866 array(
867 'title' => esc_html__( 'More authentication options', 'wp-2fa' ),
868 'description' => esc_html__( 'Integrate with additional 2FA providers such as SMS, passkeys and hardware security keys including YubiKey', 'wp-2fa' ),
869 ),
870 array(
871 'title' => esc_html__( 'WooCommerce integration', 'wp-2fa' ),
872 'description' => esc_html__( 'Add 2FA settings to the WooCommerce customer portal with one click. No custom code required.', 'wp-2fa' ),
873 ),
874 array(
875 'title' => esc_html__( 'Save time managing websites', 'wp-2fa' ),
876 'description' => esc_html__( 'Export and import settings between sites in just a few clicks', 'wp-2fa' ),
877 ),
878 ),
879 'cta' => array(
880 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
881 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page' ),
882 ),
883 ),
884 'screen:wp-2fa_page_wp-2fa-settings' => array(
885 'title' => esc_html__( 'Unlock advanced integrations & management tools with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
886 'intro' => esc_html__( 'Integrate WP 2FA with more authentication providers, connect it with popular WordPress plugins, and quickly migrate settings between websites.', 'wp-2fa' ),
887 'description' => '',
888 'screenshotUrl' => '',
889 'bullets' => array(
890 array(
891 'title' => esc_html__( 'More authentication options', 'wp-2fa' ),
892 'description' => esc_html__( 'Integrate with additional 2FA providers such as SMS, passkeys and hardware security keys including YubiKey', 'wp-2fa' ),
893 ),
894 array(
895 'title' => esc_html__( 'WooCommerce integration', 'wp-2fa' ),
896 'description' => esc_html__( 'Add 2FA settings to the WooCommerce customer portal with one click. No custom code required.', 'wp-2fa' ),
897 ),
898 array(
899 'title' => esc_html__( 'Save time managing websites', 'wp-2fa' ),
900 'description' => esc_html__( 'Export and import settings between sites in just a few clicks', 'wp-2fa' ),
901 ),
902 ),
903 'cta' => array(
904 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
905 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page' ),
906 ),
907 ),
908 'screen:wp-2fa_page_wp-2fa-settings-new' => array(
909 'title' => esc_html__( 'Unlock advanced integrations & management tools with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium', 'wp-2fa' ) . '</span>',
910 'intro' => esc_html__( 'Integrate WP 2FA with more authentication providers, connect it with popular WordPress plugins, and quickly migrate settings between websites.', 'wp-2fa' ),
911 'description' => '',
912 'screenshotUrl' => '',
913 'bullets' => array(
914 array(
915 'title' => esc_html__( 'More authentication options', 'wp-2fa' ),
916 'description' => esc_html__( 'Integrate with additional 2FA providers such as SMS, passkeys and hardware security keys including YubiKey', 'wp-2fa' ),
917 ),
918 array(
919 'title' => esc_html__( 'WooCommerce integration', 'wp-2fa' ),
920 'description' => esc_html__( 'Add 2FA settings to the WooCommerce customer portal with one click. No custom code required.', 'wp-2fa' ),
921 ),
922 array(
923 'title' => esc_html__( 'Save time managing websites', 'wp-2fa' ),
924 'description' => esc_html__( 'Export and import settings between sites in just a few clicks', 'wp-2fa' ),
925 ),
926 ),
927 'cta' => array(
928 'text' => esc_html__( 'upgrade now', 'wp-2fa' ),
929 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-settings-page' ),
930 ),
931 ),
932 'wl-setup-wizard' => array(
933 'title' => esc_html__( 'Brand the onboarding experience', 'wp-2fa' ),
934 'intro' => '',
935 'description' => esc_html__( 'Customize the setup wizard to match your organization\'s branding and provide users with a seamless authentication setup experience.', 'wp-2fa' ),
936 'screenshotUrl' => '',
937 'bullets' => array(
938 array(
939 'title' => esc_html__( 'Add your own branding and messaging', 'wp-2fa' ),
940 'description' => '',
941 ),
942 array(
943 'title' => esc_html__( 'Create a more professional user experience', 'wp-2fa' ),
944 'description' => '',
945 ),
946 array(
947 'title' => esc_html__( 'Improve user trust and adoption', 'wp-2fa' ),
948 'description' => '',
949 ),
950 array(
951 'title' => esc_html__( 'Deliver a consistent experience across your website', 'wp-2fa' ),
952 'description' => '',
953 ),
954 ),
955 'cta' => array(
956 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
957 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-white-labeling-tabs' ),
958 ),
959 ),
960 'wl-prompts' => array(
961 'title' => esc_html__( 'Personalize authentication messages', 'wp-2fa' ),
962 'intro' => '',
963 'description' => esc_html__( 'Customize user-facing prompts, emails, and notifications to better reflect your brand and communication style.', 'wp-2fa' ),
964 'screenshotUrl' => '',
965 'bullets' => array(
966 array(
967 'title' => esc_html__( 'Use your own wording and tone of voice', 'wp-2fa' ),
968 'description' => '',
969 ),
970 array(
971 'title' => esc_html__( 'Create a consistent branded experience', 'wp-2fa' ),
972 'description' => '',
973 ),
974 array(
975 'title' => esc_html__( 'Improve clarity for your users', 'wp-2fa' ),
976 'description' => '',
977 ),
978 array(
979 'title' => esc_html__( 'Reinforce trust during authentication', 'wp-2fa' ),
980 'description' => '',
981 ),
982 ),
983 'cta' => array(
984 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
985 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-white-labeling-tabs' ),
986 ),
987 ),
988 'wl-profile' => array(
989 'title' => esc_html__( 'Tailor the user account experience', 'wp-2fa' ),
990 'intro' => '',
991 'description' => esc_html__( 'Customize the 2FA settings area in user profiles to better match your website, brand, and user requirements.', 'wp-2fa' ),
992 'screenshotUrl' => '',
993 'bullets' => array(
994 array(
995 'title' => esc_html__( 'Create a seamless branded experience', 'wp-2fa' ),
996 'description' => '',
997 ),
998 array(
999 'title' => esc_html__( 'Display only the information users need', 'wp-2fa' ),
1000 'description' => '',
1001 ),
1002 array(
1003 'title' => esc_html__( 'Improve usability and clarity', 'wp-2fa' ),
1004 'description' => '',
1005 ),
1006 array(
1007 'title' => esc_html__( 'Better align authentication with your website', 'wp-2fa' ),
1008 'description' => '',
1009 ),
1010 ),
1011 'cta' => array(
1012 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
1013 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-white-labeling-tabs' ),
1014 ),
1015 ),
1016 'wp-2fa-white-labeling' => array(
1017 'title' => esc_html__( 'Unlock full white labelling with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Enterprise', 'wp-2fa' ) . '</span>',
1018 'intro' => esc_html__( 'Deliver a seamless branded experience by customizing the look, feel, and messaging of all WP 2FA pages, setup wizards, and emails.', 'wp-2fa' ),
1019 'description' => '',
1020 'screenshotUrl' => '',
1021 'bullets' => array(
1022 array(
1023 'title' => esc_html__( 'Strengthen your brand', 'wp-2fa' ),
1024 'description' => esc_html__( 'Replace WP 2FA branding with your own logo, colours, and styling', 'wp-2fa' ),
1025 ),
1026 array(
1027 'title' => esc_html__( 'Customize user communications', 'wp-2fa' ),
1028 'description' => esc_html__( 'Tailor setup instructions, messaging, and email templates to your audience', 'wp-2fa' ),
1029 ),
1030 array(
1031 'title' => esc_html__( 'Provide a seamless experience', 'wp-2fa' ),
1032 'description' => esc_html__( 'Keep users within your brand throughout the entire 2FA journey', 'wp-2fa' ),
1033 ),
1034 ),
1035 'cta' => array(
1036 'text' => esc_html__( 'Unlock Full White Labelling', 'wp-2fa' ),
1037 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-white-labeling-tabs' ),
1038 ),
1039 'ctaPremium' => array(
1040 'text' => esc_html__( 'Unlock Full White Labelling', 'wp-2fa' ),
1041 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-white-labeling-tabs' ),
1042 ),
1043 ),
1044 'screen:wp-2fa_page_wp-2fa-white-labeling' => array(
1045 'title' => esc_html__( 'Unlock full white labelling with', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Enterprise', 'wp-2fa' ) . '</span>',
1046 'intro' => esc_html__( 'Deliver a seamless branded experience by customizing the look, feel, and messaging of all WP 2FA pages, setup wizards, and emails.', 'wp-2fa' ),
1047 'description' => '',
1048 'screenshotUrl' => '',
1049 'bullets' => array(
1050 array(
1051 'title' => esc_html__( 'Strengthen your brand', 'wp-2fa' ),
1052 'description' => esc_html__( 'Replace WP 2FA branding with your own logo, colours, and styling', 'wp-2fa' ),
1053 ),
1054 array(
1055 'title' => esc_html__( 'Customize user communications', 'wp-2fa' ),
1056 'description' => esc_html__( 'Tailor setup instructions, messaging, and email templates to your audience', 'wp-2fa' ),
1057 ),
1058 array(
1059 'title' => esc_html__( 'Provide a seamless experience', 'wp-2fa' ),
1060 'description' => esc_html__( 'Keep users within your brand throughout the entire 2FA journey', 'wp-2fa' ),
1061 ),
1062 ),
1063 'cta' => array(
1064 'text' => esc_html__( 'Unlock Full White Labelling', 'wp-2fa' ),
1065 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-white-labeling-tabs' ),
1066 ),
1067 'ctaPremium' => array(
1068 'text' => esc_html__( 'Unlock Full White Labelling', 'wp-2fa' ),
1069 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-white-labeling-tabs' ),
1070 ),
1071 ),
1072 'wp-2fa-white-labeling:email-templates' => array(
1073 'title' => esc_html__( 'Customize authentication emails', 'wp-2fa' ),
1074 'intro' => esc_html__( 'Personalize the emails sent by WP 2FA to match your branding, messaging, and user experience requirements.', 'wp-2fa' ),
1075 'description' => '',
1076 'screenshotUrl' => '',
1077 'bullets' => array(
1078 array(
1079 'title' => esc_html__( 'Customize email content and wording', 'wp-2fa' ),
1080 'description' => '',
1081 ),
1082 array(
1083 'title' => esc_html__( 'Align communications with your brand', 'wp-2fa' ),
1084 'description' => '',
1085 ),
1086 array(
1087 'title' => esc_html__( 'Improve clarity for your users', 'wp-2fa' ),
1088 'description' => '',
1089 ),
1090 array(
1091 'title' => esc_html__( 'Create a more professional experience', 'wp-2fa' ),
1092 'description' => '',
1093 ),
1094 ),
1095 'cta' => array(
1096 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
1097 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-email-sms-templates-tabs' ),
1098 ),
1099 'ctaPremium' => array(
1100 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
1101 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-email-sms-templates-tabs' ),
1102 ),
1103 ),
1104 'wp-2fa-white-labeling:sms-templates' => array(
1105 'title' => esc_html__( 'Customize authentication SMS messages', 'wp-2fa' ),
1106 'intro' => esc_html__( 'Tailor SMS messages sent during authentication and account recovery workflows to better suit your organization and users.', 'wp-2fa' ),
1107 'description' => '',
1108 'screenshotUrl' => '',
1109 'bullets' => array(
1110 array(
1111 'title' => esc_html__( 'Customize SMS content and messaging', 'wp-2fa' ),
1112 'description' => '',
1113 ),
1114 array(
1115 'title' => esc_html__( 'Provide clearer instructions to users', 'wp-2fa' ),
1116 'description' => '',
1117 ),
1118 array(
1119 'title' => esc_html__( 'Maintain a consistent brand experience', 'wp-2fa' ),
1120 'description' => '',
1121 ),
1122 array(
1123 'title' => esc_html__( 'Improve communication during login and recovery', 'wp-2fa' ),
1124 'description' => '',
1125 ),
1126 ),
1127 'cta' => array(
1128 'text' => esc_html__( 'Unlock Full White Labelling', 'wp-2fa' ),
1129 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-email-sms-templates-tabs' ),
1130 ),
1131 'ctaPremium' => array(
1132 'text' => esc_html__( 'Unlock Full White Labelling', 'wp-2fa' ),
1133 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-email-sms-templates-tabs' ),
1134 ),
1135 ),
1136 'wp-2fa-white-labeling:customize-code-page-design' => array(
1137 'title' => esc_html__( 'Customize the 2FA code page design', 'wp-2fa' ),
1138 'intro' => esc_html__( 'Modify the appearance of the 2FA code page to better match your website\'s branding and user experience.', 'wp-2fa' ),
1139 'description' => '',
1140 'screenshotUrl' => '',
1141 'bullets' => array(
1142 array(
1143 'title' => esc_html__( 'Align the page with your brand identity', 'wp-2fa' ),
1144 'description' => '',
1145 ),
1146 array(
1147 'title' => esc_html__( 'Create a more professional login experience', 'wp-2fa' ),
1148 'description' => '',
1149 ),
1150 array(
1151 'title' => esc_html__( 'Build user trust with consistent styling', 'wp-2fa' ),
1152 'description' => '',
1153 ),
1154 array(
1155 'title' => esc_html__( 'Deliver a seamless authentication journey', 'wp-2fa' ),
1156 'description' => '',
1157 ),
1158 ),
1159 'cta' => array(
1160 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
1161 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=free-white-labeling-tabs' ),
1162 ),
1163 'ctaPremium' => array(
1164 'text' => esc_html__( 'Unlock White Labelling', 'wp-2fa' ),
1165 'url' => esc_url_raw( 'https://melapress.com/wordpress-2fa/pricing/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=premium-white-labeling-tabs' ),
1166 ),
1167 ),
1168 'wp-2fa-reports-locked' => array(
1169 'title' => esc_html__( 'Unlock Activity Log Reports with the', 'wp-2fa' ) . ' ' . $hl . esc_html__( 'Premium Edition', 'wp-2fa' ) . '</span>',
1170 'description' => esc_html__( 'An upsell message related to this page. Add screenshot and bullet points based on final copy.', 'wp-2fa' ),
1171 ),
1172 );
1173
1174 $pages = apply_filters( WP_2FA_PREFIX . 'premium_badge_dialog_pages', $pages );
1175
1176 if ( ! is_array( $pages ) ) {
1177 return array( 'default' => $default_page );
1178 }
1179
1180 if ( empty( $pages['default'] ) || ! is_array( $pages['default'] ) ) {
1181 $pages['default'] = $default_page;
1182 }
1183
1184 return $pages;
1185 }
1186
1187 /**
1188 * Enqueue Select2 jQuery library
1189 *
1190 * @return void
1191 */
1192 function enqueue_select2_scripts() {
1193 \wp_enqueue_style( 'select2', style_url( 'select2.min', 'admin' ), array(), WP_2FA_VERSION );
1194 \wp_enqueue_script( 'select2', script_url( 'select2.min', 'admin' ), array( 'jquery' ), WP_2FA_VERSION, false );
1195 }
1196
1197 /**
1198 * Output a tiny global CSS rule to fix the menu icon size on all admin pages.
1199 *
1200 * WordPress expects square SVG icons but ours has a non-square viewBox (13.31×20).
1201 * Without this, the icon renders oversized when NOT on the plugin's own pages.
1202 *
1203 * @return void
1204 */
1205 function admin_menu_icon_css() {
1206 echo '<style>#toplevel_page_wp-2fa-policies .wp-menu-image.svg{background-size:20px 20px!important}</style>' . "\n";
1207 }
1208
1209 /**
1210 * Enqueue styles for admin.
1211 *
1212 * @return void
1213 */
1214 function admin_styles() {
1215
1216 global $pagenow;
1217
1218 // Only load legacy admin styles on WP 2FA settings pages — not profile pages.
1219 // Profile pages use the new wizard CSS (wp2fa-wizard.css + wp2fa-profile.css).
1220 $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1221 if ( ( empty( $page ) || false === strpos( $page, 'wp-2fa' ) ) && 'profile.php' !== $pagenow && 'user-edit.php' !== $pagenow ) {
1222 return;
1223 }
1224
1225 // On profile/user-edit pages, only enqueue if NOT using the new wizard
1226 // (the new Wizard_Integration handles its own CSS).
1227 if ( in_array( $pagenow, array( 'profile.php', 'user-edit.php' ), true ) ) {
1228 return;
1229 }
1230
1231 wp_enqueue_style(
1232 'wp_2fa_admin',
1233 WP_2FA_URL . 'css/admin/wp2fa-admin-styles.css',
1234 array(),
1235 WP_2FA_VERSION
1236 );
1237 }
1238
1239 /**
1240 * Add async/defer attributes to enqueued scripts that have the specified script_execution flag.
1241 *
1242 * @link https://core.trac.wordpress.org/ticket/12009
1243 * @param string $tag The script tag.
1244 * @param string $handle The script handle.
1245 * @return string
1246 */
1247 function script_loader_tag( $tag, $handle ) {
1248 $script_execution = wp_scripts()->get_data( $handle, 'script_execution' );
1249
1250 if ( ! $script_execution ) {
1251 return $tag;
1252 }
1253
1254 if ( 'async' !== $script_execution && 'defer' !== $script_execution ) {
1255 return $tag;
1256 }
1257
1258 // Abort adding async/defer for scripts that have this script as a dependency. _doing_it_wrong()?
1259 foreach ( wp_scripts()->registered as $script ) {
1260 if ( in_array( $handle, $script->deps, true ) ) {
1261 return $tag;
1262 }
1263 }
1264
1265 // Add the attribute if it hasn't already been added.
1266 if ( ! preg_match( ":\s$script_execution(=|>|\s):", $tag ) ) {
1267 $tag = preg_replace( ':(?=></script>):', " $script_execution", $tag, 1 );
1268 }
1269
1270 return $tag;
1271 }
1272
1273 /**
1274 * Generates random string used to salt the key
1275 *
1276 * @return string
1277 *
1278 * @since 2.3.0
1279 */
1280 function wp_salt(): string {
1281 return WP2FA::get_secret_key();
1282 }
1283