| @@ -6,11 +6,13 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | namespace WP_Defender\Controller; |
| 9 | 9 | |
| 10 | +use Countable; | |
| 10 | 11 | use WP_Defender\Event; |
| 11 | 12 | use Calotes\Component\Request; |
| 12 | 13 | use Calotes\Component\Response; |
| 14 | +use WP_Defender\Integrations\Woocommerce; | |
| 13 | 15 | use WP_Defender\Component\Config\Config_Hub_Helper; |
| 14 | 16 | use WP_Defender\Component\Strong_Password as Service; |
| 15 | 17 | use WP_Defender\Model\Setting\Strong_Password as Settings; |
| 16 | 18 | |
| @@ -40,8 +42,15 @@ | ||
| 40 | 42 | */ |
| 41 | 43 | private ?Password_Protection $helper; |
| 42 | 44 | |
| 43 | 45 | /** |
| 46 | + * WooCommerce integration instance. | |
| 47 | + * | |
| 48 | + * @var Woocommerce|null | |
| 49 | + */ | |
| 50 | + private ?Woocommerce $woo; | |
| 51 | + | |
| 52 | + /** | |
| 44 | 53 | * Initializes the model and service, registers routes, and sets up scheduled events if the model is active. |
| 45 | 54 | */ |
| 46 | 55 | public function __construct() { |
| 47 | 56 | $this->model = wd_di()->get( Settings::class ); |
| @@ -46,42 +55,78 @@ | ||
| 46 | 55 | public function __construct() { |
| 47 | 56 | $this->model = wd_di()->get( Settings::class ); |
| 48 | 57 | $this->service = wd_di()->get( Service::class ); |
| 49 | 58 | $this->helper = wd_di()->get( Password_Protection::class ); |
| 50 | - add_filter( 'wp_defender_advanced_tools_data', array( $this, 'script_data' ) ); | |
| 59 | + $this->woo = wd_di()->get( Woocommerce::class ); | |
| 51 | 60 | $this->register_routes(); |
| 52 | 61 | if ( $this->model->is_active() ) { |
| 53 | - // Update site url on sub-site when MaskLogin is disabled. | |
| 54 | - if ( | |
| 55 | - is_multisite() && ! is_main_site() | |
| 56 | - && ! wd_di()->get( \WP_Defender\Model\Setting\Mask_Login::class )->is_active() | |
| 57 | - ) { | |
| 58 | - add_filter( 'network_site_url', array( $this->helper, 'filter_site_url' ), 100, 2 ); | |
| 59 | - } | |
| 60 | - remove_action( 'user_profile_update_errors', 'slt_fsp_validate_profile_update', 0 ); | |
| 61 | - remove_action( 'resetpass_form', 'slt_fsp_validate_resetpass_form', 10 ); | |
| 62 | - if ( is_admin() ) { | |
| 63 | - add_action( 'admin_enqueue_scripts', array( $this->service, 'scripts' ) ); | |
| 64 | - add_action( 'user_profile_update_errors', array( $this->service, 'on_profile_update' ), 100, 3 ); | |
| 65 | - } | |
| 66 | - add_action( 'login_enqueue_scripts', array( $this->service, 'scripts' ) ); | |
| 67 | - add_action( 'validate_password_reset', array( $this->service, 'on_password_reset' ), 100, 2 ); | |
| 68 | - add_action( 'wp_authenticate_user', array( $this->service, 'during_authentication' ), 100, 2 ); | |
| 69 | - add_filter( 'random_password', array( $this->service, 'generate_password' ), 10, 2 ); | |
| 62 | + $this->setup_hooks(); | |
| 70 | 63 | } |
| 71 | 64 | } |
| 72 | 65 | |
| 73 | 66 | /** |
| 74 | - * Provide data to the frontend via localized script. | |
| 75 | - * | |
| 76 | - * @param array $data Data collection is ready to passed. | |
| 77 | - * | |
| 78 | - * @return array Modified data array with added this controller data. | |
| 67 | + * Set up core WordPress hooks for strong password functionality. | |
| 68 | + * These hooks work independently of WooCommerce settings. | |
| 79 | 69 | */ |
| 80 | - public function script_data( array $data ): array { | |
| 81 | - $data['strong_password'] = $this->data_frontend(); | |
| 70 | + private function setup_hooks() { | |
| 71 | + // Remove conflicting plugins. | |
| 72 | + remove_action( 'user_profile_update_errors', 'slt_fsp_validate_profile_update', 0 ); | |
| 73 | + remove_action( 'resetpass_form', 'slt_fsp_validate_resetpass_form', 10 ); | |
| 82 | 74 | |
| 83 | - return $data; | |
| 75 | + // Admin hooks. | |
| 76 | + if ( is_admin() ) { | |
| 77 | + add_action( 'admin_enqueue_scripts', array( $this->service, 'scripts' ) ); | |
| 78 | + add_action( 'user_profile_update_errors', array( $this->service, 'on_profile_update' ), 100, 3 ); | |
| 79 | + } | |
| 80 | + | |
| 81 | + // Core WordPress authentication and password hooks. | |
| 82 | + add_action( 'login_enqueue_scripts', array( $this->service, 'scripts' ) ); | |
| 83 | + add_action( 'validate_password_reset', array( $this->service, 'on_password_reset' ), 100, 2 ); | |
| 84 | + add_action( 'wp_authenticate_user', array( $this->service, 'during_core_authentication' ), 100, 2 ); | |
| 85 | + add_filter( 'random_password', array( $this->service, 'generate_password' ), 10, 2 ); | |
| 86 | + | |
| 87 | + // WooCommerce-specific hooks — each gated on its own form setting. | |
| 88 | + if ( | |
| 89 | + $this->woo->is_activated() && | |
| 90 | + isset( $this->model->plugins['woocommerce'] ) && | |
| 91 | + $this->model->plugins['woocommerce'] | |
| 92 | + ) { | |
| 93 | + $woo_forms = $this->model->forms['woocommerce'] ?? array(); | |
| 94 | + | |
| 95 | + if ( array() !== $woo_forms ) { | |
| 96 | + add_action( 'wp_enqueue_scripts', array( $this->service, 'scripts' ) ); | |
| 97 | + add_action( | |
| 98 | + 'woocommerce_save_account_details_errors', | |
| 99 | + array( $this->service, 'on_woo_account_update' ), | |
| 100 | + 100, | |
| 101 | + 2 | |
| 102 | + ); | |
| 103 | + } | |
| 104 | + | |
| 105 | + if ( in_array( Woocommerce::WOO_REGISTER_FORM, $woo_forms, true ) ) { | |
| 106 | + add_filter( | |
| 107 | + 'woocommerce_process_registration_errors', | |
| 108 | + array( $this->service, 'during_woo_registration' ), | |
| 109 | + 100 | |
| 110 | + ); | |
| 111 | + } | |
| 112 | + | |
| 113 | + if ( in_array( Woocommerce::WOO_LOGIN_FORM, $woo_forms, true ) || in_array( Woocommerce::WOO_CHECKOUT_FORM, $woo_forms, true ) ) { | |
| 114 | + add_filter( | |
| 115 | + 'woocommerce_process_login_errors', | |
| 116 | + array( $this->service, 'during_woo_authentication' ), | |
| 117 | + 100, | |
| 118 | + 3 | |
| 119 | + ); | |
| 120 | + } | |
| 121 | + | |
| 122 | + if ( in_array( Woocommerce::WOO_LOST_PASSWORD_FORM, $woo_forms, true ) ) { | |
| 123 | + add_filter( | |
| 124 | + 'woocommerce_reset_password_message', | |
| 125 | + array( $this->service, 'add_woocommerce_error_message' ) | |
| 126 | + ); | |
| 127 | + } | |
| 128 | + } | |
| 84 | 129 | } |
| 85 | 130 | |
| 86 | 131 | /** |
| 87 | 132 | * All the variables that we will show on frontend, both in the main page, or dashboard widget. |
| @@ -90,11 +135,13 @@ | ||
| 90 | 135 | */ |
| 91 | 136 | public function data_frontend(): array { |
| 92 | 137 | return array_merge( |
| 93 | 138 | array( |
| 94 | - 'is_active' => $this->model->is_active(), | |
| 95 | - 'model' => $this->model->export(), | |
| 96 | - 'all_roles' => wp_list_pluck( get_editable_roles(), 'name' ), | |
| 139 | + 'is_active' => $this->model->is_active(), | |
| 140 | + 'model' => $this->model->export(), | |
| 141 | + 'all_roles' => wp_list_pluck( get_editable_roles(), 'name' ), | |
| 142 | + 'woo_forms' => Woocommerce::get_forms(), | |
| 143 | + 'is_woo_active' => wd_di()->get( Woocommerce::class )->is_activated(), | |
| 97 | 144 | ), |
| 98 | 145 | $this->dump_routes_and_nonces() |
| 99 | 146 | ); |
| 100 | 147 | } |
| @@ -116,9 +163,9 @@ | ||
| 116 | 163 | |
| 117 | 164 | $response = array( |
| 118 | 165 | 'auto_close' => true, |
| 119 | 166 | ); |
| 120 | - if ( $this->model->enabled && empty( $this->model->user_roles ) ) { | |
| 167 | + if ( $this->model->enabled && array() === $this->model->user_roles ) { | |
| 121 | 168 | // we need to control this message in front. |
| 122 | 169 | $response['warning'] = sprintf( |
| 123 | 170 | /* translators: 1. Open tag. 2. Close tag. */ |
| 124 | 171 | esc_html__( 'You need to check at least one of the %1$sStrong Passwords checks preferences below%2$s and save your settings to enable Strong Password Protection.', 'defender-security' ), |
| @@ -130,9 +177,9 @@ | ||
| 130 | 177 | } |
| 131 | 178 | |
| 132 | 179 | if ( $this->maybe_track() ) { |
| 133 | 180 | $prev_data = $this->model->get_old_settings(); |
| 134 | - if ( ! empty( $prev_data ) ) { | |
| 181 | + if ( array() !== $prev_data ) { | |
| 135 | 182 | if ( $this->model->enabled && ! $prev_data['enabled'] ) { |
| 136 | 183 | $need_track = true; |
| 137 | 184 | $event = 'def_feature_activated'; |
| 138 | 185 | } elseif ( ! $this->model->enabled && $prev_data['enabled'] ) { |
| @@ -175,10 +222,8 @@ | ||
| 175 | 222 | /** |
| 176 | 223 | * Import the data of other source into this, it can be when HUB trigger the import, or user apply a preset. |
| 177 | 224 | * |
| 178 | 225 | * @param array $data Data from other source. |
| 179 | - * | |
| 180 | - * @return null|void | |
| 181 | 226 | */ |
| 182 | 227 | public function import_data( array $data ) { |
| 183 | 228 | $this->model->import( $data ); |
| 184 | 229 | if ( $this->model->validate() ) { |
| @@ -187,10 +232,8 @@ | ||
| 187 | 232 | } |
| 188 | 233 | |
| 189 | 234 | /** |
| 190 | 235 | * Remove all settings, configs generated in this container runtime. |
| 191 | - * | |
| 192 | - * @return mixed | |
| 193 | 236 | */ |
| 194 | 237 | public function remove_settings() { |
| 195 | 238 | } |
| 196 | 239 | |
| @@ -196,11 +239,9 @@ | ||
| 196 | 239 | |
| 197 | 240 | /** |
| 198 | 241 | * Remove all data. |
| 199 | 242 | */ |
| 200 | - public function remove_data() { | |
| 201 | - $this->delete_visited_meta(); | |
| 202 | - } | |
| 243 | + public function remove_data() {} | |
| 203 | 244 | |
| 204 | 245 | /** |
| 205 | 246 | * Export strings. |
| 206 | 247 | * |
| @@ -212,24 +253,37 @@ | ||
| 212 | 253 | ); |
| 213 | 254 | } |
| 214 | 255 | |
| 215 | 256 | /** |
| 216 | - * Provides data for the dashboard widget. | |
| 257 | + * Generates configuration strings based on the provided configuration. | |
| 217 | 258 | * |
| 218 | - * @return array An array of dashboard widget data. | |
| 259 | + * @param mixed $config The configuration data. | |
| 260 | + * | |
| 261 | + * @return array Returns an array of configuration strings. | |
| 219 | 262 | */ |
| 220 | - public function dashboard_widget(): array { | |
| 221 | - return array( 'model' => $this->model->export() ); | |
| 263 | + public function config_strings( $config ): array { | |
| 264 | + $is_enabled = isset( $config['enabled'] ) ? (bool) $config['enabled'] : false; | |
| 265 | + if ( | |
| 266 | + ! $is_enabled || | |
| 267 | + ! isset( $config['user_roles'] ) || | |
| 268 | + ! is_array( $config['user_roles'] ) || | |
| 269 | + array() === $config['user_roles'] | |
| 270 | + ) { | |
| 271 | + return array( esc_html__( 'Inactive', 'defender-security' ) ); | |
| 272 | + } | |
| 273 | + | |
| 274 | + return array( | |
| 275 | + $is_enabled && ( is_array( $config['user_roles'] ) || $config['user_roles'] instanceof Countable ? count( $config['user_roles'] ) : 0 ) > 0 | |
| 276 | + ? esc_html__( 'Active', 'defender-security' ) | |
| 277 | + : esc_html__( 'Inactive', 'defender-security' ), | |
| 278 | + ); | |
| 222 | 279 | } |
| 223 | 280 | |
| 224 | 281 | /** |
| 225 | - * Delete the 'wd_password_rules_visited' meta key. | |
| 226 | - * We can remove it in the future releases and use delete_meta_key() of Breadcrumbs class. | |
| 282 | + * Provides data for the dashboard widget. | |
| 227 | 283 | * |
| 228 | - * @return void | |
| 284 | + * @return array An array of dashboard widget data. | |
| 229 | 285 | */ |
| 230 | - private function delete_visited_meta() { | |
| 231 | - global $wpdb; | |
| 232 | - | |
| 233 | - $wpdb->delete( $wpdb->usermeta, array( 'meta_key' => 'wd_password_rules_visited' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.SlowDBQuery | |
| 286 | + public function dashboard_widget(): array { | |
| 287 | + return array( 'model' => $this->model->export() ); | |
| 234 | 288 | } |
| 235 | 289 | } |