PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.2.4
Defender Security – Malware Scanner, Login Security & Firewall v6.2.4
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / controller / class-strong-password.php

class-strong-password.php in Defender Security – Malware Scanner, Login Security & Firewall 6.2.4, at src/controller/class-strong-password.php

290 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handle strong password module.
4 *
5 * @package WP_Defender\Controller
6 */
7
8 namespace WP_Defender\Controller;
9
10 use Countable;
11 use WP_Defender\Event;
12 use Calotes\Component\Request;
13 use Calotes\Component\Response;
14 use WP_Defender\Integrations\Woocommerce;
15 use WP_Defender\Component\Config\Config_Hub_Helper;
16 use WP_Defender\Component\Strong_Password as Service;
17 use WP_Defender\Model\Setting\Strong_Password as Settings;
18
19 /**
20 * Handle strong password module.
21 */
22 class Strong_Password extends Event {
23
24 /**
25 * The model for the strong password module.
26 *
27 * @var Settings|null
28 */
29 protected ?Settings $model = null;
30
31 /**
32 * The service for the strong password module.
33 *
34 * @var Service|null
35 */
36 protected ?Service $service = null;
37
38 /**
39 * Helper instance for reuse methods from pwned password protection.
40 *
41 * @var Password_Protection|null
42 */
43 private ?Password_Protection $helper;
44
45 /**
46 * WooCommerce integration instance.
47 *
48 * @var Woocommerce|null
49 */
50 private ?Woocommerce $woo;
51
52 /**
53 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
54 */
55 public function __construct() {
56 $this->model = wd_di()->get( Settings::class );
57 $this->service = wd_di()->get( Service::class );
58 $this->helper = wd_di()->get( Password_Protection::class );
59 $this->woo = wd_di()->get( Woocommerce::class );
60 $this->register_routes();
61 if ( $this->model->is_active() ) {
62 $this->setup_hooks();
63 }
64 }
65
66 /**
67 * Set up core WordPress hooks for strong password functionality.
68 * These hooks work independently of WooCommerce settings.
69 */
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 );
74
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 }
129 }
130
131 /**
132 * All the variables that we will show on frontend, both in the main page, or dashboard widget.
133 *
134 * @return array
135 */
136 public function data_frontend(): array {
137 return array_merge(
138 array(
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(),
144 ),
145 $this->dump_routes_and_nonces()
146 );
147 }
148
149 /**
150 * Save settings.
151 *
152 * @param Request $request The request object containing new settings data.
153 *
154 * @return Response
155 * @defender_route
156 */
157 public function save_settings( Request $request ): Response {
158 $model_data = $request->get_data_by_model( $this->model );
159 $this->model->import( $model_data );
160 if ( $this->model->validate() ) {
161 $this->model->save();
162 Config_Hub_Helper::set_clear_active_flag();
163
164 $response = array(
165 'auto_close' => true,
166 );
167 if ( $this->model->enabled && array() === $this->model->user_roles ) {
168 // we need to control this message in front.
169 $response['warning'] = sprintf(
170 /* translators: 1. Open tag. 2. Close tag. */
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' ),
172 '<b>',
173 '</b>'
174 );
175
176 return new Response( true, array_merge( $response, $this->data_frontend() ) );
177 }
178
179 if ( $this->maybe_track() ) {
180 $prev_data = $this->model->get_old_settings();
181 if ( array() !== $prev_data ) {
182 if ( $this->model->enabled && ! $prev_data['enabled'] ) {
183 $need_track = true;
184 $event = 'def_feature_activated';
185 } elseif ( ! $this->model->enabled && $prev_data['enabled'] ) {
186 $need_track = true;
187 $event = 'def_feature_deactivated';
188 } else {
189 $need_track = false;
190 }
191
192 if ( $need_track ) {
193 $data = array(
194 'Feature' => 'Strong Password',
195 'Triggered From' => 'Feature page',
196 );
197 $this->track_feature( $event, $data );
198 }
199 }
200 }
201
202 return new Response( true, array_merge( $response, $this->data_frontend() ) );
203 }
204
205 return new Response(
206 false,
207 array(
208 'message' => $this->model->get_formatted_errors(),
209 )
210 );
211 }
212
213 /**
214 * Export the data of this module, we will use this for export to HUB, create a preset etc.
215 *
216 * @return array
217 */
218 public function to_array() {
219 return array();
220 }
221
222 /**
223 * Import the data of other source into this, it can be when HUB trigger the import, or user apply a preset.
224 *
225 * @param array $data Data from other source.
226 */
227 public function import_data( array $data ) {
228 $this->model->import( $data );
229 if ( $this->model->validate() ) {
230 $this->model->save();
231 }
232 }
233
234 /**
235 * Remove all settings, configs generated in this container runtime.
236 */
237 public function remove_settings() {
238 }
239
240 /**
241 * Remove all data.
242 */
243 public function remove_data() {}
244
245 /**
246 * Export strings.
247 *
248 * @return array
249 */
250 public function export_strings(): array {
251 return array(
252 $this->model->is_active() ? esc_html__( 'Active', 'defender-security' ) : esc_html__( 'Inactive', 'defender-security' ),
253 );
254 }
255
256 /**
257 * Generates configuration strings based on the provided configuration.
258 *
259 * @param mixed $config The configuration data.
260 *
261 * @return array Returns an array of configuration strings.
262 */
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 );
279 }
280
281 /**
282 * Provides data for the dashboard widget.
283 *
284 * @return array An array of dashboard widget data.
285 */
286 public function dashboard_widget(): array {
287 return array( 'model' => $this->model->export() );
288 }
289 }
290