PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.9.2
WP 2FA – Two-factor authentication for WordPress v2.9.2
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-help-contact-us.php
wp-2fa / includes / classes / Admin Last commit date
Controllers 10 months ago Fly-Out 10 months ago Helpers 10 months ago Methods 10 months ago SettingsPages 10 months ago Views 10 months ago class-help-contact-us.php 10 months ago class-plugin-updated-notice.php 10 months ago class-premium-features.php 10 months ago class-settings-page.php 10 months ago class-setup-wizard.php 10 months ago class-user-listing.php 10 months ago class-user-notices.php 10 months ago class-user-profile.php 10 months ago class-user-registered.php 10 months ago index.php 10 months ago
class-help-contact-us.php
474 lines
1 <?php
2 /**
3 * Contact us and help rendering class.
4 *
5 * @package wp2fa
6 * @subpackage admin
7 * @copyright 2025 Melapress
8 * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
9 * @link https://wordpress.org/plugins/wp-2fa/
10 * @since 2.0.0
11 */
12
13 namespace WP2FA\Admin;
14
15 use WP2FA\Admin\Settings_Page;
16 use WP2FA\Admin\Helpers\WP_Helper;
17 use WP2FA\WP2FA;
18
19 if ( ! class_exists( '\WP2FA\Admin\Help_Contact_Us' ) ) {
20
21 /**
22 * Handles contact us tab and content.
23 */
24 class Help_Contact_Us {
25
26 const TOP_MENU_SLUG = 'wp-2fa-help-contact-us';
27
28 /**
29 * Create admin menu entry and settings page
30 *
31 * @since 3.0.0
32 */
33 public static function add_extra_menu_item() {
34 add_submenu_page(
35 Settings_Page::TOP_MENU_SLUG,
36 \esc_html__( 'Help & Contact Us', 'wp-2fa' ),
37 \esc_html__( 'Help & Contact Us', 'wp-2fa' ),
38 'manage_options',
39 self::TOP_MENU_SLUG,
40 array( __CLASS__, 'render' ),
41 100
42 );
43 }
44
45 /**
46 * Handles rendering the help tabs and their wrapping element.
47 *
48 * @return void
49 *
50 * @since 3.0.0
51 */
52 public static function render() {
53 $main_user = get_current_user_id();
54 $current_user_id = $main_user;
55
56 if ( ! empty( WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' ) ) ) {
57 $main_user = (int) WP2FA::get_wp2fa_setting( '2fa_settings_last_updated_by' );
58 }
59 ?>
60 <?php if ( ! empty( WP2FA::get_wp2fa_general_setting( 'limit_access' ) ) && $main_user !== $current_user_id ) { ?>
61 </br>
62 <?php
63 echo \esc_html__( 'These settings have been disabled by your site administrator, please contact them for further assistance.', 'wp-2fa' );
64 ?>
65 <?php } else { ?>
66 <div class="wrap help-wrap">
67 <h2><?php \esc_html_e( 'Help', 'wp-2fa' ); ?></h2>
68 <hr>
69 <br>
70 <div class="nav-tab-wrapper">
71 <?php
72 // Get current tab.
73 $current_tab = isset( $_GET['tab'] ) ? \sanitize_text_field( \wp_unslash( $_GET['tab'] ) ) : 'help';
74 ?>
75 <a href="<?php echo \esc_url( remove_query_arg( 'tab' ) ); ?>" class="nav-tab<?php echo 'help' === $current_tab ? ' nav-tab-active' : ''; ?>"><?php \esc_html_e( 'Help', 'wp-2fa' ); ?></a>
76 <a href="<?php echo \esc_url( add_query_arg( 'tab', 'system-info' ) ); ?>" class="nav-tab<?php echo 'system-info' === $current_tab ? ' nav-tab-active' : ''; ?>"><?php \esc_html_e( 'System info', 'wp-2fa' ); ?></a>
77 </div>
78 <div class="wp2fa-help-section nav-tabs">
79 <?php
80 self::sidebar();
81 if ( 'help' === $current_tab ) {
82 self::help();
83 } elseif ( 'system-info' === $current_tab ) {
84 self::system_info();
85 }
86 ?>
87 </div>
88 </div>
89 <?php } ?>
90 <?php
91 }
92
93 /**
94 * Help tab content.
95 *
96 * @return void
97 *
98 * @since 3.0.0
99 */
100 public static function help() {
101 ?>
102 <div class="wp2fa-help-main">
103 <!-- getting started -->
104 <div class="title">
105 <h2><?php \esc_html_e( 'Getting started', 'wp-2fa' ); ?></h2>
106 </div>
107 <p><?php \esc_html_e( 'Getting started with WP 2FA and making 2FA compulsory is as easy as 1 2 3 with WP 2FA. This can be easily done through the install wizard or the plugin settings. If you are stuck, no problem! Below are a few links of guides to help you get started:', 'wp-2fa' ); ?></p>
108 <ul>
109 <li><?php echo wp_sprintf( '<a href="%1$s" target="_blank">%2$s</a>', \esc_url( 'https://melapress.com/support/kb/wp-2fa-plugin-getting-started/?&utm_source=plugin&utm_medium=wp2fa&utm_campaign=getting_started_help' ), \esc_html__( 'Getting started with WP 2FA', 'wp-2fa' ) ); ?></li>
110 <li><?php echo wp_sprintf( '<a href="%1$s" target="_blank">%2$s</a>', \esc_url( 'https://melapress.com/support/kb/wp-2fa-configure-2fa-policies-enforce/?&utm_source=plugin&utm_medium=wp2fa&utm_campaign=configure_policies_help' ), \esc_html__( 'Configuring 2FA policies & making 2FA mandatory', 'wp-2fa' ) ); ?></li>
111 <li><?php echo wp_sprintf( '<a href="%1$s" target="_blank">%2$s</a>', \esc_url( 'https://melapress.com/support/kb/wp-2fa-configure-2fa-front-end-page-wordpress/?&utm_source=plugin&utm_medium=wp2fa&utm_campaign=no_dashboard_page_help' ), \esc_html__( 'Allowing users to configure 2FA from a website page (no dashboard access)', 'wp-2fa' ) ); ?></li>
112 </ul>
113 <!-- End -->
114 <br>
115 <p><iframe title="<?php \esc_html_e( 'Getting started', 'wp-2fa' ); ?>" class="wsal-youtube-embed" width="100%" height="315" src="https://www.youtube.com/embed/vRlX_NNGeFo" frameborder="0" allowfullscreen></iframe></p>
116
117 <!-- Plugin documentation -->
118 <div class="title">
119 <h2><?php \esc_html_e( 'Plugin documentation', 'wp-2fa' ); ?></h2>
120 </div>
121 <p><?php \esc_html_e( 'For more technical information about the WP 2FA plugin please visit the plugin\'s knowledge base.', 'wp-2fa' ); ?></p>
122 <div class="btn">
123 <a href="<?php echo \esc_url( 'https://melapress.com/support/kb/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=technical_help' ); ?>" class="button" target="_blank"><?php \esc_html_e( 'Knowledge base', 'wp-2fa' ); ?></a>
124 </div>
125 <!-- End -->
126
127 <!-- Plugin support -->
128 <div class="title">
129 <h2><?php \esc_html_e( 'Plugin support', 'wp-2fa' ); ?></h2>
130 </div>
131 <p><?php \esc_html_e( 'Do you need assistance with the plugin? Have you noticed or encountered an issue while using WP 2FA, or do you just want to report something to us?', 'wp-2fa' ); ?></p>
132 <div class="btn">
133 <a href="<?php echo \esc_url( 'https://melapress.com/support/submit-ticket/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=suppor_ticket' ); ?>" class="button" target="_blank"><?php \esc_html_e( 'Open support ticket', 'wp-2fa' ); ?></a>
134 <a href="<?php echo \esc_url( 'https://melapress.com/contact/?utm_source=plugin&utm_medium=link&utm_campaign=contact_us' ); ?>" class="button" target="_blank"><?php \esc_html_e( 'Contact us', 'wp-2fa' ); ?></a>
135 </div>
136 <!-- End -->
137 </div>
138 <?php
139 }
140
141 /**
142 * System info tab content.
143 *
144 * @return void
145 *
146 * @since 3.0.0
147 */
148 public static function system_info() {
149 ?>
150 <div class="wp2fa-help-main">
151 <!-- getting started -->
152 <div class="title">
153 <h2><?php \esc_html_e( 'System information', 'wp-2fa' ); ?></h2>
154 </div>
155 <form method="post" dir="ltr">
156 <textarea readonly="readonly" onclick="this.focus(); this.select()" id="system-info-textarea" name="wsal-sysinfo"><?php echo \esc_textarea( self::get_sysinfo() ); ?></textarea>
157 <p class="submit">
158 <input type="hidden" name="ppmwp-action" value="download_sysinfo" />
159 <?php submit_button( 'Download System Info File', 'primary', 'wp2fa-download-sysinfo', false ); ?>
160 </p>
161 </form>
162 <script>
163
164 function download(filename, text) {
165 // Create temporary element.
166 var element = document.createElement('a');
167 element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
168 element.setAttribute('download', filename);
169
170 // Set the element to not display.
171 element.style.display = 'none';
172 document.body.appendChild(element);
173
174 // Simulate click on the element.
175 element.click();
176
177 // Remove temporary element.
178 document.body.removeChild(element);
179 }
180 jQuery( document ).ready( function() {
181 var download_btn = jQuery( '#wp2fa-download-sysinfo' );
182 download_btn.click( function( event ) {
183 event.preventDefault();
184 download( 'wp2fa-system-info.txt', jQuery( '#system-info-textarea' ).val() );
185 } );
186 } );
187 </script>
188 </div>
189 <?php
190 }
191
192 /**
193 * Advertising sidebar.
194 *
195 * @return void
196 *
197 * @since 3.0.0
198 */
199 public static function sidebar() {
200 ?>
201 <div class="our-wordpress-plugins side-bar">
202 <h3><?php \esc_html_e( 'Our WordPress Plugins', 'wp-2fa' ); ?></h3>
203 <ul>
204 <li>
205 <div class="plugin-box">
206 <div class="plugin-img" style="padding:10px">
207 <img src="<?php echo \esc_url( WP_2FA_URL . 'dist/images/melapress-role-editor-logo-full-colour-horiz-rgb.svg' ); ?>" alt="">
208 </div>
209 <div class="plugin-desc">
210 <p><?php \esc_html_e( 'Create, edit, and delete and easily manage WordPress user roles like a pro.', 'wp-2fa' ); ?></p>
211 <div class="cta-btn">
212 <a href="
213 <?php
214 echo \esc_url(
215 add_query_arg(
216 array(
217 'utm_source' => 'plugin',
218 'utm_medium' => 'referral',
219 'utm_campaign' => 'wp2fa',
220 'utm_content' => 'role-editor-plugin-banner',
221 ),
222 'https://melapress.com/wordpress-user-roles-editor/'
223 )
224 );
225 ?>
226 " target="_blank"><?php \esc_html_e( 'LEARN MORE', 'wp-2fa' ); ?></a>
227 </div>
228 </div>
229 </div>
230 </li>
231 <li>
232 <div class="plugin-box">
233 <div class="plugin-img">
234 <img src="<?php echo \esc_url( WP_2FA_URL . 'dist/images/wp-activity-log.jpeg' ); ?>" alt="">
235 </div>
236 <div class="plugin-desc">
237 <p><?php \esc_html_e( 'Keep a log of users and under the hood site activity.', 'wp-2fa' ); ?></p>
238 <div class="cta-btn">
239 <a href="
240 <?php
241 echo \esc_url(
242 add_query_arg(
243 array(
244 'utm_source' => 'plugin',
245 'utm_medium' => 'referral',
246 'utm_campaign' => 'wp2fa',
247 'utm_content' => 'wsal-plugin-banner',
248 ),
249 'https://melapress.com/wordpress-activity-log/'
250 )
251 );
252 ?>
253 " target="_blank"><?php \esc_html_e( 'LEARN MORE', 'wp-2fa' ); ?></a>
254 </div>
255 </div>
256 </div>
257 </li>
258 <li>
259 <div class="plugin-box">
260 <div class="plugin-img">
261 <img src="<?php echo \esc_url( WP_2FA_URL . 'dist/images/login-security.jpeg' ); ?>" alt="">
262 </div>
263 <div class="plugin-desc">
264 <p><?php \esc_html_e( 'Enforce strong password policies on WordPress.', 'wp-2fa' ); ?></p>
265 <div class="cta-btn">
266 <a href="
267 <?php
268 echo \esc_url(
269 add_query_arg(
270 array(
271 'utm_source' => 'plugin',
272 'utm_medium' => 'referral',
273 'utm_campaign' => 'wp2fa',
274 'utm_content' => 'login-security-plugin-banner',
275 ),
276 'https://melapress.com/wordpress-login-security/?&utm_source=plugin&utm_medium=wp2fa&utm_campaign=wsal_link'
277 )
278 );
279 ?>
280 " target="_blank"><?php \esc_html_e( 'LEARN MORE', 'wp-2fa' ); ?></a>
281 </div>
282 </div>
283 </div>
284 </li>
285 <li>
286 <div class="plugin-box">
287 <div class="plugin-img">
288 <img src="<?php echo \esc_url( WP_2FA_URL . 'dist/images/website-file-changes-monitor.png
289 ' ); ?>" alt="">
290 </div>
291 <div class="plugin-desc">
292 <p><?php \esc_html_e( 'Automatically identify unauthorized file changes on your WordPress site.', 'wp-2fa' ); ?></p>
293 <div class="cta-btn">
294 <a href="
295 <?php
296 echo \esc_url(
297 add_query_arg(
298 array(
299 'utm_source' => 'plugin',
300 'utm_medium' => 'referral',
301 'utm_campaign' => 'wp2fa',
302 'utm_content' => 'file-changes-monitor-plugin-banner',
303 ),
304 'https://melapress.com/wordpress-plugins/website-file-changes-monitor/'
305 )
306 );
307 ?>
308 " target="_blank"><?php \esc_html_e( 'LEARN MORE', 'wp-2fa' ); ?></a>
309 </div>
310 </div>
311 </div>
312 </li>
313 </ul>
314 </div>
315 <?php
316 }
317
318 /**
319 * Gather basic settings and system information for use in the system info tab. Left untranslated (as is the case in all plugins)
320 * as its for our use only.
321 *
322 * @return string
323 */
324 public static function get_sysinfo() {
325 // System info.
326 global $wpdb;
327
328 $sysinfo = '### System Info → Begin ###' . "\n\n";
329
330 // Start with the basics...
331 $sysinfo .= '-- Site Info --' . "\n\n";
332 $sysinfo .= 'Site URL (WP Address): ' . site_url() . "\n";
333 $sysinfo .= 'Home URL (Site Address): ' . home_url() . "\n";
334 $sysinfo .= 'Multisite: ' . ( WP_Helper::is_multisite() ? 'Yes' : 'No' ) . "\n";
335
336 // Get theme info.
337 $theme_data = wp_get_theme();
338 $theme = $theme_data->name . ' ' . $theme_data->version;
339 $parent_theme = $theme_data->template;
340 if ( ! empty( $parent_theme ) ) {
341 $parent_theme_data = wp_get_theme( $parent_theme );
342 $parent_theme = $parent_theme_data->name . ' ' . $parent_theme_data->version;
343 }
344
345 // Language information.
346 $locale = get_locale();
347
348 // WordPress configuration.
349 $sysinfo .= "\n" . '-- WordPress Configuration --' . "\n\n";
350 $sysinfo .= 'Version: ' . get_bloginfo( 'version' ) . "\n";
351 $sysinfo .= 'Language: ' . ( ! empty( $locale ) ? $locale : 'en_US' ) . "\n";
352 $sysinfo .= 'Permalink Structure: ' . ( get_option( 'permalink_structure' ) ? get_option( 'permalink_structure' ) : 'Default' ) . "\n";
353 $sysinfo .= 'Active Theme: ' . $theme . "\n";
354 if ( $parent_theme !== $theme ) {
355 $sysinfo .= 'Parent Theme: ' . $parent_theme . "\n";
356 }
357 $sysinfo .= 'Show On Front: ' . get_option( 'show_on_front' ) . "\n";
358
359 // Only show page specs if frontpage is set to 'page'.
360 if ( 'page' === get_option( 'show_on_front' ) ) {
361 $front_page_id = (int) get_option( 'page_on_front' );
362 $blog_page_id = (int) get_option( 'page_for_posts' );
363
364 $sysinfo .= 'Page On Front: ' . ( 0 !== $front_page_id ? get_the_title( $front_page_id ) . ' (#' . $front_page_id . ')' : 'Unset' ) . "\n";
365 $sysinfo .= 'Page For Posts: ' . ( 0 !== $blog_page_id ? get_the_title( $blog_page_id ) . ' (#' . $blog_page_id . ')' : 'Unset' ) . "\n";
366 }
367
368 $sysinfo .= 'ABSPATH: ' . ABSPATH . "\n";
369 $sysinfo .= 'WP_DEBUG: ' . ( defined( 'WP_DEBUG' ) ? ( WP_DEBUG ? 'Enabled' : 'Disabled' ) : 'Not set' ) . "\n";
370 $sysinfo .= 'WP Memory Limit: ' . WP_MEMORY_LIMIT . "\n";
371
372 // Get plugins that have an update.
373 $updates = get_plugin_updates();
374
375 // Must-use plugins.
376 // NOTE: MU plugins can't show updates!
377 $muplugins = get_mu_plugins();
378 if ( count( $muplugins ) > 0 ) {
379 $sysinfo .= "\n" . '-- Must-Use Plugins --' . "\n\n";
380
381 foreach ( $muplugins as $plugin => $plugin_data ) {
382 $sysinfo .= $plugin_data['Name'] . ': ' . $plugin_data['Version'] . "\n";
383 }
384 }
385
386 // WordPress active plugins.
387 $sysinfo .= "\n" . '-- WordPress Active Plugins --' . "\n\n";
388
389 $plugins = get_plugins();
390 $active_plugins = get_option( 'active_plugins', array() );
391
392 foreach ( $plugins as $plugin_path => $plugin ) {
393 if ( ! in_array( $plugin_path, $active_plugins, true ) ) {
394 continue;
395 }
396
397 $update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[ $plugin_path ]->update->new_version . ')' : '';
398 $sysinfo .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n";
399 }
400
401 // WordPress inactive plugins.
402 $sysinfo .= "\n" . '-- WordPress Inactive Plugins --' . "\n\n";
403
404 foreach ( $plugins as $plugin_path => $plugin ) {
405 if ( in_array( $plugin_path, $active_plugins, true ) ) {
406 continue;
407 }
408
409 $update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[ $plugin_path ]->update->new_version . ')' : '';
410 $sysinfo .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n";
411 }
412
413 if ( WP_Helper::is_multisite() ) {
414 // WordPress Multisite active plugins.
415 $sysinfo .= "\n" . '-- Network Active Plugins --' . "\n\n";
416
417 $plugins = wp_get_active_network_plugins();
418 $active_plugins = get_site_option( 'active_sitewide_plugins', array() );
419
420 foreach ( $plugins as $plugin_path ) {
421 $plugin_base = plugin_basename( $plugin_path );
422
423 if ( ! array_key_exists( $plugin_base, $active_plugins ) ) {
424 continue;
425 }
426
427 $update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[ $plugin_path ]->update->new_version . ')' : '';
428 $plugin = get_plugin_data( $plugin_path );
429 $sysinfo .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n";
430 }
431 }
432
433 // Server configuration.
434 $server_software = ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) ? \sanitize_text_field( \wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '';
435 $sysinfo .= "\n" . '-- Webserver Configuration --' . "\n\n";
436 $sysinfo .= 'PHP Version: ' . PHP_VERSION . "\n";
437 $sysinfo .= 'MySQL Version: ' . $wpdb->db_version() . "\n";
438
439 if ( isset( $server_software ) ) {
440 $sysinfo .= 'Webserver Info: ' . $server_software . "\n";
441 } else {
442 $sysinfo .= 'Webserver Info: Global $_SERVER array is not set.' . "\n";
443 }
444
445 // PHP configs.
446 $sysinfo .= "\n" . '-- PHP Configuration --' . "\n\n";
447 $sysinfo .= 'Memory Limit: ' . ini_get( 'memory_limit' ) . "\n";
448 $sysinfo .= 'Upload Max Size: ' . ini_get( 'upload_max_filesize' ) . "\n";
449 $sysinfo .= 'Post Max Size: ' . ini_get( 'post_max_size' ) . "\n";
450 $sysinfo .= 'Upload Max Filesize: ' . ini_get( 'upload_max_filesize' ) . "\n";
451 $sysinfo .= 'Time Limit: ' . ini_get( 'max_execution_time' ) . "\n";
452 $sysinfo .= 'Max Input Vars: ' . ini_get( 'max_input_vars' ) . "\n";
453 $sysinfo .= 'Display Errors: ' . ( ini_get( 'display_errors' ) ? 'On (' . ini_get( 'display_errors' ) . ')' : 'N/A' ) . "\n";
454
455 $sysinfo .= "\n" . '-- WP 2FA Settings --' . "\n\n";
456
457 global $wpdb;
458
459 $wp2fa_options = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE 'wp_2fa_%'", ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
460
461 if ( ! empty( $wp2fa_options ) ) {
462 foreach ( $wp2fa_options as $option => $value ) {
463 $sysinfo .= 'Option: ' . $value['option_name'] . "\n";
464 $sysinfo .= 'Value: ' . print_r( $value['option_value'], true ) . "\n\n"; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
465 }
466 }
467
468 $sysinfo .= "\n" . '### System Info → End ###' . "\n\n";
469
470 return $sysinfo;
471 }
472 }
473 }
474