| @@ -1,9 +1,19 @@ | ||
| 1 | 1 | <?php |
| 2 | +/** | |
| 3 | + * Handles WordPress admin page related tasks. | |
| 4 | + * | |
| 5 | + * @package WP_Defender | |
| 6 | + */ | |
| 2 | 7 | |
| 3 | 8 | namespace WP_Defender; |
| 4 | 9 | |
| 10 | +use WP_Defender\Component\Rate; | |
| 5 | 11 | use WP_Defender\Behavior\WPMUDEV; |
| 12 | +use WP_Defender\Component\Firewall; | |
| 13 | +use WP_Defender\Integrations\Dashboard_Whitelabel; | |
| 14 | +use WP_Defender\Component\Config\Config_Hub_Helper; | |
| 15 | +use WP_Defender\Helper\Analytics\Deactivation_Survey; | |
| 6 | 16 | |
| 7 | 17 | if ( ! defined( 'ABSPATH' ) ) { |
| 8 | 18 | die(); |
| 9 | 19 | } |
| @@ -8,9 +18,9 @@ | ||
| 8 | 18 | die(); |
| 9 | 19 | } |
| 10 | 20 | |
| 11 | 21 | /** |
| 12 | - * Class Admin | |
| 22 | + * Handles WordPress admin page related tasks. | |
| 13 | 23 | * |
| 14 | 24 | * @since 2.4 |
| 15 | 25 | */ |
| 16 | 26 | class Admin { |
| @@ -15,66 +25,251 @@ | ||
| 15 | 25 | */ |
| 16 | 26 | class Admin { |
| 17 | 27 | |
| 18 | 28 | /** |
| 29 | + * Is the Free version? | |
| 30 | + * | |
| 19 | 31 | * @var bool |
| 20 | 32 | */ |
| 21 | - public $is_pro; | |
| 33 | + public $is_wp_org_version; | |
| 22 | 34 | |
| 23 | 35 | /** |
| 36 | + * Constructor for the Admin class. | |
| 37 | + */ | |
| 38 | + public function __construct() { | |
| 39 | + $this->is_wp_org_version = defender_is_wp_org_version(); | |
| 40 | + add_action( 'wp_ajax_defender_ip_detection_notice_dismiss', array( $this, 'dismiss_notice' ) ); | |
| 41 | + add_action( 'wp_ajax_defender_ip_detection_switch_to_xff', array( $this, 'switch_to_xff' ) ); | |
| 42 | + add_action( 'wp_ajax_defender_track_deactivate', array( $this, 'track_deactivate' ) ); | |
| 43 | + add_action( 'admin_head', array( $this, 'add_global_styles' ) ); | |
| 44 | + | |
| 45 | + // Deactivation survey. | |
| 46 | + add_action( 'admin_footer-plugins.php', array( $this, 'load_deactivation_survey_modal' ) ); | |
| 47 | + } | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * Add global styles. | |
| 51 | + */ | |
| 52 | + public function add_global_styles() { | |
| 53 | + echo '<style> | |
| 54 | + #toplevel_page_wp-defender ul.wp-submenu li a[href="admin.php?page=wdf-ip-lockout"] { display: flex; justify-content: space-between; align-items: center; } | |
| 55 | + #adminmenu li.wp-has-current-submenu a.wp-has-current-submenu { background-color: #4763E4 !important; } | |
| 56 | + #adminmenu .toplevel_page_wp-defender div.wp-menu-image.svg { width: 16px; height: 16px; margin-top: 10px; margin-left: 10px; background-size: 16px auto; } | |
| 57 | + </style>'; | |
| 58 | + if ( ! $this->is_wp_org_version ) { | |
| 59 | + echo '<style> | |
| 60 | + #adminmenu .defender-admin-menu-pro-tag { | |
| 61 | + display: inline-block; | |
| 62 | + padding: 0; | |
| 63 | + color: inherit; | |
| 64 | + border: 1px solid currentColor; | |
| 65 | + border-radius: 9px; | |
| 66 | + line-height: 16px; | |
| 67 | + font-size: 11px; | |
| 68 | + height: 16px; | |
| 69 | + width: 28px; | |
| 70 | + text-align: center; | |
| 71 | + margin-left: 5px; | |
| 72 | + } | |
| 73 | + </style>'; | |
| 74 | + } | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 24 | 78 | * Init admin actions. |
| 25 | 79 | */ |
| 26 | 80 | public function init() { |
| 27 | - $this->is_pro = ( new WPMUDEV() )->is_pro(); | |
| 28 | - $is_def_page = defender_current_page(); | |
| 29 | 81 | // Display plugin links. |
| 30 | 82 | add_filter( 'network_admin_plugin_action_links_' . DEFENDER_PLUGIN_BASENAME, array( $this, 'settings_link' ) ); |
| 31 | 83 | add_filter( 'plugin_action_links_' . DEFENDER_PLUGIN_BASENAME, array( $this, 'settings_link' ) ); |
| 32 | 84 | add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 3 ); |
| 33 | - // Only for wordpress.org members. | |
| 34 | - if ( ! $this->is_pro ) { | |
| 35 | - // Add plugin upgrade notification. | |
| 36 | - add_action( 'in_plugin_update_message-' . DEFENDER_PLUGIN_BASENAME, array( $this, 'show_upgrade_notice' ), 10, 2 ); | |
| 37 | - if ( $is_def_page && ! is_multisite() ) { | |
| 38 | - add_action( 'admin_notices', array( $this, 'show_rating_notice' ) ); | |
| 39 | - } elseif ( $is_def_page && is_multisite() && is_main_site() ) { | |
| 40 | - add_action( 'network_admin_notices', array( $this, 'show_rating_notice' ) ); | |
| 85 | + // Only for plugin pages and actions are only for wp.org members. | |
| 86 | + if ( $this->is_wp_org_version ) { | |
| 87 | + /** | |
| 88 | + * Action hook that fires after a scan issue is fixed. | |
| 89 | + * | |
| 90 | + * @since 4.4.0 | |
| 91 | + */ | |
| 92 | + add_action( | |
| 93 | + 'wpdef_fixed_scan_issue', | |
| 94 | + array( $this, 'after_scan_fix' ), | |
| 95 | + 10 | |
| 96 | + ); | |
| 97 | + // For submenu callout. | |
| 98 | + add_action( 'admin_head', array( $this, 'retarget_submenu_callout' ) ); | |
| 99 | + if ( ! wd_di()->get( WPMUDEV::class )->is_wpmu_hosting() ) { | |
| 100 | + $upsell_menu_title = sprintf( | |
| 101 | + '<span class="defender-upsell-label">%1$s<span class="defender-upsell-pro-tag">%2$s</span></span><svg class="defender-upsell-arrow" width="9" height="9" viewBox="0 0 9 9" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.225625 8.7625C0.0881251 8.62917 0.013125 8.47083 0.000624999 8.2875C-0.00770833 8.10417 0.0672918 7.93125 0.225625 7.76875L5.86313 2.125L7.16313 0.93125C7.31313 0.789584 7.47146 0.722917 7.63812 0.73125C7.80479 0.739583 7.94854 0.804167 8.06938 0.925C8.19021 1.04583 8.25062 1.18958 8.25062 1.35625C8.25479 1.52292 8.18812 1.67708 8.05062 1.81875L6.85063 3.11875L1.21313 8.75C1.05896 8.90417 0.890209 8.97917 0.706875 8.975C0.527709 8.975 0.367292 8.90417 0.225625 8.7625ZM7.61938 4.4625L7.76312 1.24375L4.43188 1.3625H2.30687C2.11521 1.3625 1.94854 1.29792 1.80688 1.16875C1.66521 1.03542 1.59438 0.875 1.59438 0.6875C1.59438 0.5 1.66104 0.339584 1.79438 0.20625C1.93188 0.0687502 2.10688 0 2.31938 0H8.25688C8.48188 0 8.66104 0.0687502 8.79437 0.20625C8.92771 0.34375 8.99438 0.520834 8.99438 0.7375V6.66875C8.99438 6.87292 8.92563 7.04583 8.78813 7.1875C8.65063 7.325 8.48812 7.39375 8.30062 7.39375C8.10896 7.39375 7.94646 7.325 7.81313 7.1875C7.68396 7.04583 7.61938 6.87708 7.61938 6.68125V4.4625Z" fill="white"/></svg>', | |
| 102 | + esc_html__( 'Upgrade', 'defender-security' ), | |
| 103 | + esc_html__( 'Pro', 'defender-security' ) | |
| 104 | + ); | |
| 105 | + add_submenu_page( | |
| 106 | + 'wp-defender', | |
| 107 | + esc_html__( 'Upgrade to Pro', 'defender-security' ), | |
| 108 | + $upsell_menu_title, | |
| 109 | + is_multisite() ? 'manage_network_options' : 'manage_options', | |
| 110 | + $this->get_link( 'upsell', 'defender_new-submenu_upsell' ) | |
| 111 | + ); | |
| 112 | + global $submenu; | |
| 113 | + if ( isset( $submenu['wp-defender'] ) && is_array( $submenu['wp-defender'] ) && array() !== $submenu['wp-defender'] ) { | |
| 114 | + $last = array_key_last( $submenu['wp-defender'] ); | |
| 115 | + $submenu['wp-defender'][ $last ][4] = 'defender-menu-upsell'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited | |
| 116 | + } | |
| 41 | 117 | } |
| 42 | - add_action( 'wp_ajax_defender_dismiss_notification', array( $this, 'dismiss_notice' ) ); | |
| 43 | - add_action( 'admin_init', array( $this, 'register_free_modules' ), 20 ); | |
| 118 | + } | |
| 119 | + | |
| 120 | + // Display IP detection notice. | |
| 121 | + if ( is_multisite() ) { | |
| 122 | + add_action( 'network_admin_notices', array( $this, 'admin_notices' ) ); | |
| 44 | 123 | } else { |
| 45 | - // For Pro version. | |
| 46 | - add_action( | |
| 47 | - 'load-plugins.php', | |
| 48 | - function () { | |
| 49 | - add_action( 'after_plugin_row_' . DEFENDER_PLUGIN_BASENAME, array( | |
| 50 | - $this, | |
| 51 | - 'show_upgrade_notice' | |
| 52 | - ), 10, 2 ); | |
| 53 | - }, | |
| 54 | - 22 | |
| 55 | - ); | |
| 124 | + add_action( 'admin_notices', array( $this, 'admin_notices' ) ); | |
| 56 | 125 | } |
| 57 | 126 | } |
| 58 | 127 | |
| 59 | 128 | /** |
| 129 | + * Initialize the deactivation survey modal. | |
| 130 | + */ | |
| 131 | + public function init_deactivation_survey() { | |
| 132 | + global $pagenow; | |
| 133 | + | |
| 134 | + if ( 'plugins.php' !== $pagenow ) { | |
| 135 | + return; | |
| 136 | + } | |
| 137 | + | |
| 138 | + wp_enqueue_style( 'def-sui' ); | |
| 139 | + wp_enqueue_style( 'def-admin' ); | |
| 140 | + | |
| 141 | + if ( ! wp_script_is( 'clipboard', 'enqueued' ) ) { | |
| 142 | + wp_enqueue_script( 'clipboard' ); | |
| 143 | + } | |
| 144 | + | |
| 145 | + wp_enqueue_script( 'wpmudev-sui' ); | |
| 146 | + wp_enqueue_script( 'def-deactivation-survey' ); | |
| 147 | + wp_enqueue_script( 'def-admin' ); | |
| 148 | + } | |
| 149 | + | |
| 150 | + /** | |
| 151 | + * Retrieves the display name of the plugin. | |
| 152 | + * | |
| 153 | + * @return string The display name of the plugin with a trailing hyphen. | |
| 154 | + */ | |
| 155 | + public function get_plugin_display_name(): string { | |
| 156 | + // Check if the plugin is the WordPress.org version (i.e., the free version) and set the label accordingly. | |
| 157 | + $plugin_label = $this->is_wp_org_version | |
| 158 | + ? esc_html__( 'Defender', 'defender-security' ) | |
| 159 | + : esc_html__( 'Defender Pro', 'defender-security' ); | |
| 160 | + | |
| 161 | + // Instantiate the Dashboard_Whitelabel class only if necessary. | |
| 162 | + $whitelabel = new Dashboard_Whitelabel(); | |
| 163 | + | |
| 164 | + // If whitelabeling is enabled and a custom name is provided, use it. | |
| 165 | + if ( $whitelabel->can_whitelabel() ) { | |
| 166 | + $custom_label = $whitelabel->get_plugin_name( Config_Hub_Helper::WDP_ID ); | |
| 167 | + if ( is_string( $custom_label ) && '' !== trim( $custom_label ) ) { | |
| 168 | + $plugin_label = $custom_label; | |
| 169 | + } | |
| 170 | + } | |
| 171 | + | |
| 172 | + // Return the final plugin label with the appended dash. | |
| 173 | + return $plugin_label . ' - '; | |
| 174 | + } | |
| 175 | + | |
| 176 | + /** | |
| 177 | + * Generates the submenu callout for the WP Defender plugin. | |
| 178 | + * | |
| 179 | + * @return void | |
| 180 | + */ | |
| 181 | + public function retarget_submenu_callout(): void { | |
| 182 | + ?> | |
| 183 | + <style> | |
| 184 | + #adminmenu .wp-submenu li.defender-menu-upsell > a, | |
| 185 | + #adminmenu .wp-submenu li.defender-menu-upsell > a:hover, | |
| 186 | + #adminmenu .wp-submenu li.defender-menu-upsell > a:active, | |
| 187 | + #adminmenu .wp-submenu li.defender-menu-upsell > a:focus { | |
| 188 | + display: flex; | |
| 189 | + align-items: center; | |
| 190 | + justify-content: space-between; | |
| 191 | + height: 32px; | |
| 192 | + padding: 7px 12px; | |
| 193 | + box-sizing: border-box; | |
| 194 | + background: #571EE7; | |
| 195 | + color: #ffffff; | |
| 196 | + font-size: 14px; | |
| 197 | + font-weight: 400; | |
| 198 | + line-height: 18px; | |
| 199 | + } | |
| 200 | + | |
| 201 | + #adminmenu .wp-submenu li.defender-menu-upsell > a .defender-upsell-label { | |
| 202 | + display: inline-flex; | |
| 203 | + align-items: center; | |
| 204 | + } | |
| 205 | + | |
| 206 | + #adminmenu .wp-submenu li.defender-menu-upsell > a .defender-upsell-pro-tag { | |
| 207 | + display: inline-flex; | |
| 208 | + align-items: center; | |
| 209 | + justify-content: center; | |
| 210 | + margin-left: 6px; | |
| 211 | + padding: 0 5px; | |
| 212 | + border: 1px solid #ffffff; | |
| 213 | + border-radius: 9px; | |
| 214 | + width: 30px; | |
| 215 | + height: 18px; | |
| 216 | + box-sizing: border-box; | |
| 217 | + font-family: 'Roboto', Arial, sans-serif; | |
| 218 | + font-size: 12px; | |
| 219 | + font-weight: 400; | |
| 220 | + line-height: 20px; | |
| 221 | + letter-spacing: 0.1px; | |
| 222 | + } | |
| 223 | + | |
| 224 | + #adminmenu .wp-submenu li.defender-menu-upsell > a .defender-upsell-arrow { | |
| 225 | + margin-right: 4px; | |
| 226 | + } | |
| 227 | + | |
| 228 | + #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a, | |
| 229 | + #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:hover, | |
| 230 | + #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:active, | |
| 231 | + #toplevel_page_wp-defender.wp-not-current-submenu .wp-submenu li.defender-menu-upsell > a:focus { | |
| 232 | + margin-left: -4px; | |
| 233 | + } | |
| 234 | + </style> | |
| 235 | + <script type='text/javascript'> | |
| 236 | + jQuery(function ($) { | |
| 237 | + $('#adminmenu li.defender-menu-upsell > a').attr("target", "_blank"); | |
| 238 | + }); | |
| 239 | + </script> | |
| 240 | + <?php | |
| 241 | + } | |
| 242 | + | |
| 243 | + /** | |
| 244 | + * Fired when the scan issue is fixed. | |
| 245 | + * | |
| 246 | + * @return void | |
| 247 | + */ | |
| 248 | + public function after_scan_fix(): void { | |
| 249 | + Rate::run_counter_of_fixed_scans(); | |
| 250 | + } | |
| 251 | + | |
| 252 | + /** | |
| 60 | 253 | * Return URL link. |
| 61 | 254 | * |
| 62 | - * @param string $link_for Accepts: 'docs', 'plugin', 'rate', 'support', 'roadmap'. | |
| 63 | - * @param string $campaign Utm campaign tag to be used in link. Default: ''. | |
| 64 | - * @param string $adv_path Advanced path. Default: ''. | |
| 255 | + * @param string $link_for Accepts: 'docs', 'plugin', 'rate' and etc. | |
| 256 | + * @param string $campaign Utm campaign tag to be used in link. Default: ''. | |
| 257 | + * @param string $adv_path Advanced path. Default: ''. | |
| 258 | + * @param string $source UTM source. Default: 'defender'. | |
| 65 | 259 | * |
| 66 | 260 | * @return string |
| 67 | 261 | */ |
| 68 | - public function get_link( $link_for, $campaign = '', $adv_path = '' ) { | |
| 69 | - $domain = 'https://wpmudev.com'; | |
| 262 | + public function get_link( $link_for, $campaign = '', $adv_path = '', $source = 'defender' ): string { | |
| 263 | + $domain = 'https://wpmudev.com'; | |
| 70 | 264 | $wp_org = 'https://wordpress.org'; |
| 71 | - $utm_tags = "?utm_source=defender&utm_medium=plugin&utm_campaign={$campaign}"; | |
| 265 | + $utm_tags = "?utm_source={$source}&utm_medium=plugin&utm_campaign={$campaign}"; | |
| 72 | 266 | switch ( $link_for ) { |
| 73 | 267 | case 'docs': |
| 74 | 268 | $link = "{$domain}/docs/wpmu-dev-plugins/defender/{$utm_tags}"; |
| 75 | 269 | break; |
| 76 | 270 | case 'plugin': |
| 271 | + case 'upsell': | |
| 77 | 272 | $link = "{$domain}/project/wp-defender/{$utm_tags}"; |
| 78 | 273 | break; |
| 79 | 274 | case 'rate': |
| 80 | 275 | $link = "{$wp_org}/support/plugin/defender-security/reviews/#new-post"; |
| @@ -79,10 +274,15 @@ | ||
| 79 | 274 | case 'rate': |
| 80 | 275 | $link = "{$wp_org}/support/plugin/defender-security/reviews/#new-post"; |
| 81 | 276 | break; |
| 82 | 277 | case 'support': |
| 83 | - $link = $this->is_pro ? "{$domain}/get-support/" : "{$wp_org}/support/plugin/defender-security/"; | |
| 278 | + $link = $this->is_wp_org_version | |
| 279 | + ? "{$wp_org}/support/plugin/defender-security/" | |
| 280 | + : "{$domain}/get-support/"; | |
| 84 | 281 | break; |
| 282 | + case 'support_with_utm': | |
| 283 | + $link = "{$domain}/hub2/support/{$utm_tags}"; | |
| 284 | + break; | |
| 85 | 285 | case 'roadmap': |
| 86 | 286 | $link = "{$domain}/roadmap/"; |
| 87 | 287 | break; |
| 88 | 288 | case 'pro_link': |
| @@ -95,28 +295,58 @@ | ||
| 95 | 295 | |
| 96 | 296 | return $link; |
| 97 | 297 | } |
| 98 | 298 | |
| 99 | - | |
| 100 | 299 | /** |
| 101 | 300 | * Adds a settings link on plugin page. |
| 102 | 301 | * |
| 103 | - * @param array $links Current links. | |
| 302 | + * @param array $links Current links. | |
| 104 | 303 | * |
| 105 | 304 | * @return array |
| 106 | 305 | */ |
| 107 | 306 | public function settings_link( $links ) { |
| 108 | - $action_links = []; | |
| 109 | - $wpmu_dev = new WPMUDEV(); | |
| 110 | - // Settings link. | |
| 111 | - $action_links['dashboard'] = '<a href="' . network_admin_url( 'admin.php?page=wdf-setting' ) . '" aria-label="' . esc_attr( __( 'Go to Defender Settings', 'wpdef' ) ) . '">' . esc_html__( 'Settings', 'wpdef' ) . '</a>'; | |
| 112 | - // Documentation link. | |
| 113 | - $action_links['docs'] = '<a target="_blank" href="' . $this->get_link('docs', 'defender_pluginlist_docs') . '" aria-label="' . esc_attr(__('Docs', 'wpdef')) . '">' . esc_html__('Docs', 'wpdef') . '</a>'; | |
| 307 | + $action_links = array(); | |
| 308 | + $wpmu_dev = new WPMUDEV(); | |
| 309 | + // Dashboard-link. | |
| 310 | + $action_links['dashboard'] = '<a href="' . network_admin_url( 'admin.php?page=wp-defender' ) . '" aria-label="' . esc_attr( | |
| 311 | + esc_html__( | |
| 312 | + 'Go to Defender Dashboard', | |
| 313 | + 'defender-security' | |
| 314 | + ) | |
| 315 | + ) . '">' . esc_html__( 'Dashboard', 'defender-security' ) . '</a>'; | |
| 316 | + // Documentation-link. | |
| 317 | + $action_links['docs'] = '<a target="_blank" href="' . $this->get_link( | |
| 318 | + 'docs', | |
| 319 | + 'defender_pluginlist_docs' | |
| 320 | + ) . '" aria-label="' . esc_attr( | |
| 321 | + esc_html__( | |
| 322 | + 'Docs', | |
| 323 | + 'defender-security' | |
| 324 | + ) | |
| 325 | + ) . '">' . esc_html__( 'Docs', 'defender-security' ) . '</a>'; | |
| 114 | 326 | if ( ! $wpmu_dev->is_member() ) { |
| 115 | 327 | if ( WP_DEFENDER_PRO_PATH !== DEFENDER_PLUGIN_BASENAME ) { |
| 116 | - $action_links['upgrade'] = '<a style="color: #8D00B1;" target="_blank" href="' . $this->get_link( 'plugin', 'defender_pluginlist_upgrade' ) . '" aria-label="' . esc_attr( __( 'Upgrade to Defender Pro', 'wpdef' ) ) . '">' . esc_html__( 'Upgrade', 'wpdef' ) . '</a>'; | |
| 117 | - } else { | |
| 118 | - $action_links['renew'] = '<a style="color: #8D00B1;" target="_blank" href="' . $this->get_link( 'plugin', 'defender_pluginlist_renew' ) . '" aria-label="' . esc_attr( __( 'Renew Your Membership', 'wpdef' ) ) . '">' . esc_html__( 'Renew Membership', 'wpdef' ) . '</a>'; | |
| 328 | + if ( ! wd_di()->get( WPMUDEV::class )->is_wpmu_hosting() ) { | |
| 329 | + $action_links['upgrade'] = '<a style="color: #8D00B1;" target="_blank" href="' . $this->get_link( | |
| 330 | + 'plugin', | |
| 331 | + 'defender_pluginlist_upgrade' | |
| 332 | + ) . '" aria-label="' . esc_attr( | |
| 333 | + esc_html__( | |
| 334 | + 'Upgrade to Defender Pro', | |
| 335 | + 'defender-security' | |
| 336 | + ) | |
| 337 | + ) . '">' . esc_html__( 'Get Defender Pro', 'defender-security' ) . '</a>'; | |
| 338 | + } | |
| 339 | + } elseif ( ! $wpmu_dev->is_hosted_site_connected_to_tfh() ) { | |
| 340 | + $action_links['renew'] = '<a style="color: #8D00B1;" target="_blank" href="' . $this->get_link( | |
| 341 | + 'plugin', | |
| 342 | + 'defender_pluginlist_renew' | |
| 343 | + ) . '" aria-label="' . esc_attr( | |
| 344 | + esc_html__( | |
| 345 | + 'Renew Your Membership', | |
| 346 | + 'defender-security' | |
| 347 | + ) | |
| 348 | + ) . '">' . esc_html__( 'Renew Membership', 'defender-security' ) . '</a>'; | |
| 119 | 349 | } |
| 120 | 350 | } |
| 121 | 351 | |
| 122 | 352 | return array_merge( $action_links, $links ); |
| @@ -124,16 +354,16 @@ | ||
| 124 | 354 | |
| 125 | 355 | /** |
| 126 | 356 | * Show row meta on the plugin screen. |
| 127 | 357 | * |
| 128 | - * @param mixed $links Plugin Row Meta. | |
| 129 | - * @param mixed $file Plugin Base file. | |
| 130 | - * @param array $plugin_data Plugin data. | |
| 358 | + * @param string[] $links Plugin Row Meta. | |
| 359 | + * @param string $file Plugin Base file. | |
| 360 | + * @param array $plugin_data Plugin data. | |
| 131 | 361 | * |
| 132 | 362 | * @return array |
| 133 | 363 | */ |
| 134 | 364 | public function plugin_row_meta( $links, $file, $plugin_data ) { |
| 135 | - $row_meta = []; | |
| 365 | + $row_meta = array(); | |
| 136 | 366 | if ( ! defined( 'DEFENDER_PLUGIN_BASENAME' ) || DEFENDER_PLUGIN_BASENAME !== $file ) { |
| 137 | 367 | return $links; |
| 138 | 368 | } |
| 139 | 369 | |
| @@ -138,18 +368,22 @@ | ||
| 138 | 368 | } |
| 139 | 369 | |
| 140 | 370 | // Change AuthorURI link. |
| 141 | 371 | if ( isset( $links[1] ) ) { |
| 142 | - $author_uri = $this->is_pro ? 'https://wpmudev.com/' : 'https://profiles.wordpress.org/wpmudev/'; | |
| 372 | + $author_uri = $this->is_wp_org_version ? 'https://profiles.wordpress.org/wpmudev/' : 'https://wpmudev.com/'; | |
| 143 | 373 | $author_uri = sprintf( |
| 144 | 374 | '<a href="%s" target="_blank">%s</a>', |
| 145 | 375 | $author_uri, |
| 146 | - __( 'WPMU DEV' ) | |
| 376 | + esc_html__( 'WPMU DEV', 'defender-security' ) | |
| 147 | 377 | ); |
| 148 | - $links[1] = sprintf( /* translators: ... */ __( 'By %s' ), $author_uri ); | |
| 378 | + $links[1] = sprintf( | |
| 379 | + /* translators: %s: Author URI. */ | |
| 380 | + esc_html__( 'By %s', 'defender-security' ), | |
| 381 | + $author_uri | |
| 382 | + ); | |
| 149 | 383 | } |
| 150 | 384 | |
| 151 | - if ( ! $this->is_pro ) { | |
| 385 | + if ( $this->is_wp_org_version ) { | |
| 152 | 386 | // Change AuthorURI link. |
| 153 | 387 | if ( isset( $links[2] ) && false === strpos( $links[2], 'target="_blank"' ) ) { |
| 154 | 388 | if ( ! isset( $plugin_data['slug'] ) && $plugin_data['Name'] ) { |
| 155 | 389 | $links[2] = sprintf( |
| @@ -155,23 +389,28 @@ | ||
| 155 | 389 | $links[2] = sprintf( |
| 156 | 390 | '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>', |
| 157 | 391 | esc_url( |
| 158 | 392 | network_admin_url( |
| 159 | - 'plugin-install.php?tab=plugin-information&plugin=defender-security' . | |
| 160 | - '&TB_iframe=true&width=600&height=550' | |
| 393 | + 'plugin-install.php?tab=plugin-information&plugin=defender-security&TB_iframe=true&width=600&height=550' | |
| 161 | 394 | ) |
| 162 | 395 | ), |
| 163 | 396 | /* translators: %s: Plugin name. */ |
| 164 | - esc_attr( sprintf( __( 'More information about %s' ), $plugin_data['Name'] ) ), | |
| 397 | + esc_attr( sprintf( esc_html__( 'More information about %s', 'defender-security' ), $plugin_data['Name'] ) ), | |
| 165 | 398 | esc_attr( $plugin_data['Name'] ), |
| 166 | - __( 'View details' ) | |
| 399 | + esc_html__( 'View details', 'defender-security' ) | |
| 167 | 400 | ); |
| 168 | 401 | } else { |
| 169 | 402 | $links[2] = str_replace( 'href=', 'target="_blank" href=', $links[2] ); |
| 170 | 403 | } |
| 171 | 404 | } |
| 172 | - $row_meta['rate'] = '<a href="' . esc_url( $this->get_link( 'rate' ) ) . '" aria-label="' . esc_attr__( 'Rate Defender', 'wpdef' ) . '" target="_blank">' . esc_html__( 'Rate Defender', 'wpdef' ) . '</a>'; | |
| 173 | - $row_meta['support'] = '<a href="' . esc_url( $this->get_link( 'support' ) ) . '" aria-label="' . esc_attr__( 'Support', 'wpdef' ) . '" target="_blank">' . esc_html__( 'Support', 'wpdef' ) . '</a>'; | |
| 405 | + $row_meta['rate'] = '<a href="' . esc_url( $this->get_link( 'rate' ) ) . '" aria-label="' . esc_attr__( | |
| 406 | + 'Rate Defender', | |
| 407 | + 'defender-security' | |
| 408 | + ) . '" target="_blank">' . Rate::get_rate_button_title() . '</a>'; | |
| 409 | + $row_meta['support'] = '<a href="' . esc_url( $this->get_link( 'support' ) ) . '" aria-label="' . esc_attr__( | |
| 410 | + 'Support', | |
| 411 | + 'defender-security' | |
| 412 | + ) . '" target="_blank">' . esc_html__( 'Support', 'defender-security' ) . '</a>'; | |
| 174 | 413 | } else { |
| 175 | 414 | // Change 'Visit plugins' link to 'View details'. |
| 176 | 415 | if ( isset( $links[2] ) && false !== strpos( $links[2], 'project/wp-defender' ) ) { |
| 177 | 416 | $links[2] = sprintf( |
| @@ -176,185 +415,287 @@ | ||
| 176 | 415 | if ( isset( $links[2] ) && false !== strpos( $links[2], 'project/wp-defender' ) ) { |
| 177 | 416 | $links[2] = sprintf( |
| 178 | 417 | '<a href="%s" target="_blank">%s</a>', |
| 179 | 418 | esc_url( $this->get_link( 'pro_link', '', 'project/wp-defender/' ) ), |
| 180 | - __( 'View details' ) | |
| 419 | + esc_html__( 'View details', 'defender-security' ) | |
| 181 | 420 | ); |
| 182 | 421 | } |
| 183 | - $row_meta['support'] = '<a href="' . esc_url( $this->get_link( 'support' ) ) . '" aria-label="' . esc_attr__( 'Premium Support', 'wpdef' ) . '" target="_blank">' . esc_html__( 'Premium Support', 'wpdef' ) . '</a>'; | |
| 422 | + $row_meta['support'] = '<a href="' . esc_url( $this->get_link( 'support' ) ) . '" aria-label="' . esc_attr__( | |
| 423 | + 'Premium Support', | |
| 424 | + 'defender-security' | |
| 425 | + ) . '" target="_blank">' . esc_html__( 'Premium Support', 'defender-security' ) . '</a>'; | |
| 184 | 426 | } |
| 185 | - $row_meta['roadmap'] = '<a href="' . esc_url( $this->get_link( 'roadmap' ) ) . '" aria-label="' . esc_attr__( 'Roadmap', 'wpdef' ) . '" target="_blank">' . esc_html__( 'Roadmap', 'wpdef' ) . '</a>'; | |
| 427 | + $row_meta['roadmap'] = '<a href="' . esc_url( $this->get_link( 'roadmap' ) ) . '" aria-label="' . esc_attr__( | |
| 428 | + 'Roadmap', | |
| 429 | + 'defender-security' | |
| 430 | + ) . '" target="_blank">' . esc_html__( 'Roadmap', 'defender-security' ) . '</a>'; | |
| 186 | 431 | |
| 187 | 432 | return array_merge( $links, $row_meta ); |
| 188 | 433 | } |
| 189 | 434 | |
| 190 | 435 | /** |
| 436 | + * Display IP detection notices: | |
| 437 | + * - if user site is behind proxy, e.g. Cloudflare or something else, and only for admins, | |
| 438 | + * - only on the plugin's pages. | |
| 439 | + * | |
| 440 | + * @return void | |
| 441 | + */ | |
| 442 | + public function admin_notices(): void { | |
| 443 | + if ( ! current_user_can( 'manage_options' ) || ! is_defender_page() ) { | |
| 444 | + return; | |
| 445 | + } | |
| 446 | + $header = $this->get_plugin_display_name(); | |
| 447 | + if ( Firewall::is_cf_notice_ready() ) { | |
| 448 | + $is_show = 'cf'; | |
| 449 | + $class_notice = 'notice-info'; | |
| 450 | + $header .= esc_html__( | |
| 451 | + 'Cloudflare Usage Detected: Switched to CF-Connecting-IP for Better Compatibility', | |
| 452 | + 'defender-security' | |
| 453 | + ); | |
| 454 | + } elseif ( Firewall::is_xff_notice_ready() ) { | |
| 455 | + $is_show = 'xff'; | |
| 456 | + $class_notice = 'notice-warning'; | |
| 457 | + $header .= esc_html__( | |
| 458 | + 'Improve IP Detection: We suggest Switching to X-Forward-For IP Detection Method', | |
| 459 | + 'defender-security' | |
| 460 | + ); | |
| 461 | + } else { | |
| 462 | + return; | |
| 463 | + } | |
| 464 | + ?> | |
| 465 | + <div class="defender_ip_detection_notice notice <?php echo esc_attr( $class_notice ); ?> is-dismissible" | |
| 466 | + data-nonce="<?php echo esc_attr( wp_create_nonce( 'defender_ip_detection_notice_dismiss' ) ); ?>" | |
| 467 | + data-prop="notice-for-<?php echo esc_attr( $is_show ); ?>"> | |
| 468 | + <h3 style="margin-bottom:0;"> | |
| 469 | + <?php echo esc_html( $header ); ?> | |
| 470 | + </h3> | |
| 471 | + <?php if ( 'cf' === $is_show ) { ?> | |
| 472 | + <p style="color: #72777C; line-height: 22px;"> | |
| 473 | + <?php | |
| 474 | + printf( | |
| 475 | + /* translators: %s: Link. */ | |
| 476 | + esc_html__( | |
| 477 | + 'We have switched to using the CF-Connecting-IP HTTP header for IP detection, offering enhanced compatibility for users behind Cloudflare Proxy. If you wish to change this setting, you can do so from %s.', | |
| 478 | + 'defender-security' | |
| 479 | + ), | |
| 480 | + '<a style="font-weight:bold;" href="' . esc_url_raw( network_admin_url( 'admin.php?page=wdf-ip-lockout&view=settings#detect-ip-addresses' ) ) . '">' . esc_html__( 'here', 'defender-security' ) . '</a>' | |
| 481 | + ); | |
| 482 | + ?> | |
| 483 | + </p> | |
| 484 | + <p> | |
| 485 | + <button type="button" class="button button-primary button-large defender_ip_detection_action_hide" | |
| 486 | + data-prop="defender_ip_detection_notice_success"> | |
| 487 | + <?php | |
| 488 | + esc_html_e( | |
| 489 | + 'Ok, I understand', | |
| 490 | + 'defender-security' | |
| 491 | + ); | |
| 492 | + ?> | |
| 493 | + </button> | |
| 494 | + </p> | |
| 495 | + <?php } elseif ( 'xff' === $is_show ) { ?> | |
| 496 | + <p style="color: #72777C; line-height: 22px;"> | |
| 497 | + <?php | |
| 498 | + printf( | |
| 499 | + /* translators: %s: Link. */ | |
| 500 | + esc_html__( | |
| 501 | + 'Based on your server configuration, we recommend switching to the X-Forwarded-For method for accurate IP detection and to prevent firewall blocks. Easily modify your settings %s.', | |
| 502 | + 'defender-security' | |
| 503 | + ), | |
| 504 | + '<a style="font-weight:bold;" href="' . esc_url_raw( network_admin_url( 'admin.php?page=wdf-ip-lockout&view=settings#detect-ip-addresses' ) ) . '">' . esc_html__( 'here', 'defender-security' ) . '</a>' | |
| 505 | + ); | |
| 506 | + ?> | |
| 507 | + </p> | |
| 508 | + <p> | |
| 509 | + <button type="button" class="button button-primary button-large" | |
| 510 | + id="defender_ip_detection_action_switch" | |
| 511 | + data-prop="defender_ip_detection_notice_success"> | |
| 512 | + <?php esc_html_e( 'Switch to X-Forwarded-For', 'defender-security' ); ?> | |
| 513 | + </button> | |
| 514 | + <a href="#" class="defender_ip_detection_action_hide" | |
| 515 | + style="margin-left: 11px; line-height: 16px; text-decoration: none; font-weight: bold;" | |
| 516 | + data-prop="defender_ip_detection_notice_dismiss"><?php esc_html_e( 'Dismiss', 'defender-security' ); ?></a> | |
| 517 | + </p> | |
| 518 | + <?php } ?> | |
| 519 | + </div> | |
| 520 | + <script type="text/javascript"> | |
| 521 | + //Switch. | |
| 522 | + jQuery('#defender_ip_detection_action_switch').on('click', function (e) { | |
| 523 | + e.preventDefault(); | |
| 524 | + var $notice = jQuery(e.currentTarget).closest('.defender_ip_detection_notice'), | |
| 525 | + ajaxUrl = '<?php echo esc_url_raw( admin_url( 'admin-ajax.php' ) ); ?>'; | |
| 526 | + | |
| 527 | + jQuery.post( | |
| 528 | + ajaxUrl, | |
| 529 | + { | |
| 530 | + action: 'defender_ip_detection_switch_to_xff', | |
| 531 | + _ajax_nonce: $notice.data('nonce') | |
| 532 | + } | |
| 533 | + ).always(function () { | |
| 534 | + $notice.hide(); | |
| 535 | + }); | |
| 536 | + }); | |
| 537 | + //Hide. | |
| 538 | + jQuery('body').on('click', '.defender_ip_detection_notice .notice-dismiss, .defender_ip_detection_action_hide', function (e) { | |
| 539 | + e.preventDefault(); | |
| 540 | + var $notice = jQuery(e.currentTarget).closest('.defender_ip_detection_notice'), | |
| 541 | + ajaxUrl = '<?php echo esc_url_raw( admin_url( 'admin-ajax.php' ) ); ?>'; | |
| 542 | + | |
| 543 | + jQuery.post( | |
| 544 | + ajaxUrl, | |
| 545 | + { | |
| 546 | + action: 'defender_ip_detection_notice_dismiss', | |
| 547 | + prop: $notice.data('prop'), | |
| 548 | + _ajax_nonce: $notice.data('nonce') | |
| 549 | + } | |
| 550 | + ).always(function () { | |
| 551 | + $notice.hide(); | |
| 552 | + }); | |
| 553 | + }); | |
| 554 | + </script> | |
| 555 | + <?php | |
| 556 | + } | |
| 557 | + | |
| 558 | + /** | |
| 191 | 559 | * Dismiss notice. |
| 560 | + * | |
| 561 | + * @return void | |
| 192 | 562 | */ |
| 193 | - public function dismiss_notice() { | |
| 194 | - if ( ! current_user_can( 'manage_options' ) || ! check_ajax_referer( 'defender_dismiss_notification' ) ) { | |
| 563 | + public function dismiss_notice(): void { | |
| 564 | + if ( | |
| 565 | + ! current_user_can( 'manage_options' ) || | |
| 566 | + ! check_ajax_referer( 'defender_ip_detection_notice_dismiss' ) | |
| 567 | + ) { | |
| 195 | 568 | wp_send_json_error( |
| 196 | - array( | |
| 197 | - 'message' => __( 'Invalid request, you are not allowed to do that action.', 'wpdef' ), | |
| 198 | - ) | |
| 569 | + array( 'message' => esc_html__( 'Invalid request, you are not allowed to do that action.', 'defender-security' ) ) | |
| 199 | 570 | ); |
| 200 | 571 | } |
| 201 | 572 | |
| 202 | - $notification_name = ! empty( $_POST['prop'] ) ? sanitize_text_field( $_POST['prop'] ) : false; | |
| 203 | - if ( false === $notification_name ) { | |
| 573 | + $prop = defender_get_data_from_request( 'prop', 'p' ); | |
| 574 | + $notice_type = '' !== trim( $prop ) ? $prop : false; | |
| 575 | + if ( 'notice-for-cf' === $notice_type ) { | |
| 576 | + update_site_option( Firewall::IP_DETECTION_CF_DISMISS_SLUG, true ); | |
| 577 | + wp_send_json_success(); | |
| 578 | + } elseif ( 'notice-for-xff' === $notice_type ) { | |
| 579 | + update_site_option( Firewall::IP_DETECTION_XFF_DISMISS_SLUG, true ); | |
| 580 | + wp_send_json_success(); | |
| 581 | + } else { | |
| 204 | 582 | wp_send_json_error( |
| 205 | - array( | |
| 206 | - 'message' => __( 'Invalid request, allowed data not provided.', 'wpdef' ), | |
| 207 | - ) | |
| 583 | + array( 'message' => esc_html__( 'Invalid request, allowed data not provided.', 'defender-security' ) ) | |
| 208 | 584 | ); |
| 209 | 585 | } |
| 210 | - update_site_option( $notification_name, true ); | |
| 211 | - | |
| 212 | - wp_send_json_success(); | |
| 213 | 586 | } |
| 214 | 587 | |
| 215 | 588 | /** |
| 216 | - * Register sub-modules. | |
| 589 | + * Switch to XFF option. | |
| 590 | + * | |
| 591 | + * @return void | |
| 217 | 592 | */ |
| 218 | - public function register_free_modules() { | |
| 593 | + public function switch_to_xff(): void { | |
| 219 | 594 | if ( |
| 220 | - ! file_exists( defender_path( 'extra/free-dashboard/module.php' ) ) | |
| 221 | - || ! file_exists( defender_path( 'extra/recommended-plugins-notice/notice.php' ) ) | |
| 595 | + ! current_user_can( 'manage_options' ) || | |
| 596 | + ! check_ajax_referer( 'defender_ip_detection_notice_dismiss' ) | |
| 222 | 597 | ) { |
| 223 | - return; | |
| 598 | + wp_send_json_error( | |
| 599 | + array( 'message' => esc_html__( 'Invalid request, you are not allowed to do that action.', 'defender-security' ) ) | |
| 600 | + ); | |
| 224 | 601 | } |
| 225 | - /* @noinspection PhpIncludeInspection */ | |
| 226 | - require_once( defender_path( 'extra/free-dashboard/module.php' ) ); | |
| 227 | - /* @noinspection PhpIncludeInspection */ | |
| 228 | - require_once( defender_path( 'extra/recommended-plugins-notice/notice.php' ) ); | |
| 229 | - | |
| 230 | - // Register the current plugin. | |
| 231 | - do_action( | |
| 232 | - 'wdev_register_plugin', | |
| 233 | - /* 1 Plugin ID */ DEFENDER_PLUGIN_BASENAME, | |
| 234 | - /* 2 Plugin Title */ 'Defender', | |
| 235 | - /* 3 https://wordpress.org */ '/plugins/defender-security/', | |
| 236 | - /* 4 Email Button CTA */ __( 'Get Fast!', 'wpdef' ) | |
| 237 | - /* 5 Mailchimp List id for the plugin - No */ | |
| 602 | + // Change model's data. | |
| 603 | + $model_firewall = wd_di()->get( Model\Setting\Firewall::class ); | |
| 604 | + $model_firewall->http_ip_header = 'HTTP_X_FORWARDED_FOR'; | |
| 605 | + $xff_ip = defender_get_data_from_request( 'HTTP_X_FORWARDED_FOR', 's' ); | |
| 606 | + $xff_parts = preg_split( '/\s*,\s*/', $xff_ip ); | |
| 607 | + $xff_parts = is_array( $xff_parts ) ? $xff_parts : array(); | |
| 608 | + $xff_parts = array_map( 'trim', $xff_parts ); | |
| 609 | + $xff_parts = array_filter( | |
| 610 | + $xff_parts, | |
| 611 | + static function ( $ip ) { | |
| 612 | + return false !== filter_var( $ip, FILTER_VALIDATE_IP ); | |
| 613 | + } | |
| 238 | 614 | ); |
| 239 | - | |
| 240 | - // Recommended plugin notice. | |
| 241 | - do_action( | |
| 242 | - 'wpmudev-recommended-plugins-register-notice', | |
| 243 | - DEFENDER_PLUGIN_BASENAME, // Plugin basename | |
| 244 | - 'Defender', // Plugin Name | |
| 245 | - array( | |
| 246 | - 'toplevel_page_wp-defender', | |
| 247 | - 'toplevel_page_wp-defender-network', | |
| 248 | - ), | |
| 249 | - array( 'after', '.sui-wrap .sui-header' ) | |
| 250 | - ); | |
| 615 | + $separator = "\r\n"; | |
| 616 | + $xff_parts = array_unique( $xff_parts ); | |
| 617 | + $xff_ip = implode( $separator, $xff_parts ); | |
| 618 | + if ( '' === $xff_ip ) { | |
| 619 | + wp_send_json_error( | |
| 620 | + array( 'message' => esc_html__( 'Invalid trusted proxy IP(s) detected in X-Forwarded-For header.', 'defender-security' ) ) | |
| 621 | + ); | |
| 622 | + } | |
| 623 | + if ( '' === $model_firewall->trusted_proxies_ip ) { | |
| 624 | + $model_firewall->trusted_proxies_ip = $xff_ip; | |
| 625 | + } else { | |
| 626 | + // Todo: improve the code using a separate method. This will be useful when the user switches between different proxy headeres (IP detection options). | |
| 627 | + $model_firewall->trusted_proxies_ip = $model_firewall->trusted_proxies_ip . $separator . $xff_ip; | |
| 628 | + } | |
| 629 | + $model_firewall->save(); | |
| 630 | + // Save Dismiss slug. | |
| 631 | + update_site_option( Firewall::IP_DETECTION_XFF_DISMISS_SLUG, true ); | |
| 632 | + wp_send_json_success(); | |
| 251 | 633 | } |
| 252 | 634 | |
| 253 | 635 | /** |
| 254 | - * Show the rating notice. | |
| 636 | + * Load deactivation survey modal. | |
| 255 | 637 | */ |
| 256 | - public function show_rating_notice() { | |
| 257 | - // @since 2.6.1 | |
| 258 | - if ( get_site_option( 'defender_rating_success', apply_filters( 'wd_display_rating', false ) ) ) { | |
| 638 | + public function load_deactivation_survey_modal() { | |
| 639 | + $deactivation_survey_template_file = WP_DEFENDER_DIR . | |
| 640 | + 'src' . DIRECTORY_SEPARATOR . | |
| 641 | + 'view' . DIRECTORY_SEPARATOR . | |
| 642 | + 'modal' . DIRECTORY_SEPARATOR . | |
| 643 | + 'deactivation-survey.php'; | |
| 644 | + | |
| 645 | + if ( ! file_exists( $deactivation_survey_template_file ) ) { | |
| 259 | 646 | return; |
| 260 | 647 | } |
| 261 | 648 | |
| 262 | - $install_date = get_site_option( 'defender_free_install_date', false ); | |
| 263 | - // @since 2.6.1 | |
| 264 | - $days_later_dismiss = get_site_option( 'defender_days_rating_later_dismiss', | |
| 265 | - apply_filters( 'wd_dismiss_rating', false ) | |
| 649 | + // Data to be passed to the template file. | |
| 650 | + $is_pro = wd_di()->get( WPMUDEV::class )->is_pro(); | |
| 651 | + $docs_link = $this->get_link( | |
| 652 | + 'support_with_utm', | |
| 653 | + 'defender_deactivation_survey_help', | |
| 654 | + '', | |
| 655 | + $is_pro ? 'defender-pro' : 'defender' | |
| 266 | 656 | ); |
| 267 | 657 | |
| 268 | - if ( | |
| 269 | - $install_date && ! $days_later_dismiss | |
| 270 | - && current_time( 'timestamp' ) > strtotime( '+7 days', $install_date ) | |
| 271 | - ) { ?> | |
| 272 | - <div id="defender-free-usage-notice" | |
| 273 | - class="defender-rating-notice notice notice-info" | |
| 274 | - data-nonce="<?php echo esc_attr( wp_create_nonce( 'defender_dismiss_notification' ) ); ?>"> | |
| 275 | - | |
| 276 | - <p style="color: #72777C; line-height: 22px;"><?php esc_html_e( 'We\'ve spent countless hours developing Defender and making it free for you to use. We would really appreciate it if you dropped us a quick rating!', 'wpdef' ); ?></p> | |
| 277 | - | |
| 278 | - <p> | |
| 279 | - <button type="button" class="button button-primary button-large" | |
| 280 | - data-prop="defender_rating_success"><?php esc_html_e( 'Rate Defender', 'wpdef' ); ?></button> | |
| 281 | - <a href="#" class="dismiss" | |
| 282 | - style="margin-left: 11px; color: #555; line-height: 16px; font-weight: 500; text-decoration: none;" | |
| 283 | - data-prop="defender_days_rating_later_dismiss"><?php esc_html_e( 'Maybe later', 'wpdef' ); ?></a> | |
| 284 | - </p> | |
| 285 | - </div> | |
| 286 | - <?php | |
| 287 | - } | |
| 288 | - ?> | |
| 289 | - | |
| 290 | - <script type="text/javascript"> | |
| 291 | - jQuery('.defender-rating-notice a, .defender-rating-notice button').on('click', function (e) { | |
| 292 | - e.preventDefault(); | |
| 293 | - | |
| 294 | - var $notice = jQuery(e.currentTarget).closest('.defender-rating-notice'), | |
| 295 | - prop = jQuery(this).data('prop'), | |
| 296 | - ajaxUrl = '<?php echo admin_url( 'admin-ajax.php' ); ?>'; | |
| 297 | - | |
| 298 | - if ('defender_rating_success' === prop) { | |
| 299 | - window.open('https://wordpress.org/support/plugin/defender-security/reviews/#new-post', '_blank'); | |
| 300 | - } | |
| 301 | - | |
| 302 | - jQuery.post( | |
| 303 | - ajaxUrl, | |
| 304 | - { | |
| 305 | - action: 'defender_dismiss_notification', | |
| 306 | - prop: prop, | |
| 307 | - _ajax_nonce: $notice.data('nonce') | |
| 308 | - } | |
| 309 | - ).always(function () { | |
| 310 | - $notice.hide(); | |
| 311 | - }); | |
| 312 | - }); | |
| 313 | - </script> | |
| 314 | - | |
| 315 | - <?php | |
| 658 | + ob_start(); | |
| 659 | + require_once $deactivation_survey_template_file; | |
| 660 | + // Everything escaped in all template files. | |
| 661 | + echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 316 | 662 | } |
| 317 | 663 | |
| 318 | 664 | /** |
| 319 | - * Show plugin update notice. | |
| 320 | - * | |
| 321 | - * @param string $plugin_file | |
| 322 | - * @param array $response | |
| 323 | - * | |
| 324 | - * @since 2.8.3 | |
| 665 | + * Track deactivation. | |
| 325 | 666 | */ |
| 326 | - public function show_upgrade_notice( $plugin_file, $response ) { | |
| 327 | - if ( version_compare( PHP_VERSION, '7.2', '>=' ) ) { | |
| 328 | - return; | |
| 667 | + public function track_deactivate() { | |
| 668 | + if ( | |
| 669 | + ! current_user_can( 'manage_options' ) || | |
| 670 | + ! check_ajax_referer( 'defender_deactivation_survey_modal' ) | |
| 671 | + ) { | |
| 672 | + wp_send_json_error( | |
| 673 | + array( 'message' => esc_html__( 'Invalid request, you are not allowed to do that action.', 'defender-security' ) ) | |
| 674 | + ); | |
| 329 | 675 | } |
| 330 | - $plugin_data = (object) $response; | |
| 331 | - // Preparing for the next major plugin v3.0.0 and subsequent versions. | |
| 332 | - if ( isset( $plugin_data->new_version ) | |
| 333 | - && '3' === substr( trim( $plugin_data->new_version ), 0, 1 ) | |
| 334 | - && version_compare( DEFENDER_VERSION, '3', '<' ) | |
| 335 | - ){ | |
| 336 | - // Major plugin version or subsequent versions. | |
| 337 | - $new_version = ( '3' === $plugin_data->new_version ) ? '3.0.0' : $plugin_data->new_version; | |
| 338 | - // Collect notice. | |
| 339 | - $notice = '<p>' . esc_html__( 'There is a new version of Defender available - Deprecating PHP version 7.1. and lower.', 'wpdef' ) . '</p>'; | |
| 340 | - $notice .= '<span style="display: inherit;background: #D63638;color: #FFFFFF;margin-top: 12px;padding: 10px 12px;border-radius: 2px;">'; | |
| 341 | - $notice .= '<strong>'; | |
| 342 | - $notice .= esc_html__( 'Important Upgrade Notice:', 'wpdef' ); | |
| 343 | - $notice .= '</strong> '; | |
| 344 | - $notice .= sprintf( | |
| 345 | - /* translators: %s: Version number. */ | |
| 346 | - esc_html__( 'The upcoming version %s is compatible only with PHP 7.2.0 and higher. Please make sure to upgrade your PHP version.', 'wpdef' ), | |
| 347 | - $new_version | |
| 676 | + $posted_data = defender_get_data_from_request( null, 'p' ); | |
| 677 | + if ( ! is_array( $posted_data['properties'] ) ) { | |
| 678 | + wp_send_json_error( | |
| 679 | + array( 'message' => esc_html__( 'Invalid request, allowed data not provided.', 'defender-security' ) ) | |
| 348 | 680 | ); |
| 349 | - $notice .= '</span>'; | |
| 681 | + } | |
| 682 | + $properties = $posted_data['properties']; | |
| 683 | + if ( | |
| 684 | + ! isset( | |
| 685 | + $properties['Reason'], | |
| 686 | + $properties['Message'], | |
| 687 | + $properties['Modal Action'], | |
| 688 | + $properties['Requested Assistance'], | |
| 689 | + $properties['Tracking Status'] | |
| 690 | + ) | |
| 691 | + ) { | |
| 692 | + wp_send_json_error( | |
| 693 | + array( 'message' => esc_html__( 'Missing field(s).', 'defender-security' ) ) | |
| 694 | + ); | |
| 695 | + } | |
| 350 | 696 | |
| 351 | - echo "<script type='text/javascript'> | |
| 352 | - (function ($) { | |
| 353 | - $(document).ready(function () { | |
| 354 | - $( '.wp-list-table tr[data-plugin=\"" . esc_attr( $plugin_data->plugin ) . "\"] .notice-warning' ).html( '" . addslashes( $notice ) . "' ).css('padding-bottom', '10px'); | |
| 355 | - }); | |
| 356 | - })(jQuery); | |
| 357 | - </script>"; | |
| 358 | - } | |
| 697 | + wd_di()->get( Deactivation_Survey::class )->track_deactivation_survey( $properties ); | |
| 698 | + | |
| 699 | + wp_send_json_success(); | |
| 359 | 700 | } |
| 360 | 701 | } |