@@ -76,15 +76,15 @@ public function fetch_messages() {
7676 public function quit_wizard () {
7777 $ request_data = $ this ->clean ( $ _REQUEST );
7878
79- if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ request_data [ '_nonce ' ], 'plausible_analytics_quit_wizard ' ) < 1 ) {
79+ if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ request_data ['_nonce ' ], 'plausible_analytics_quit_wizard ' ) < 1 ) {
8080 Messages::set_error ( __ ( 'Not allowed ' , 'plausible-analytics ' ) );
8181
8282 wp_send_json_error ( null , 403 );
8383 }
8484
8585 update_option ( 'plausible_analytics_wizard_done ' , true );
8686
87- $ this ->maybe_handle_redirect ( $ request_data [ 'redirect ' ] );
87+ $ this ->maybe_handle_redirect ( $ request_data ['redirect ' ] );
8888
8989 wp_send_json_success ();
9090 }
@@ -93,26 +93,41 @@ public function quit_wizard() {
9393 * Clean variables using `sanitize_text_field`.
9494 * Arrays are cleaned recursively. Non-scalar values are ignored.
9595 *
96- * @since 1.3.0
97- * @access public
98- *
9996 * @param string|array $var Sanitize the variable.
10097 *
10198 * @return string|array
99+ * @since 1.3.0
100+ * @access public
101+ *
102102 */
103- private function clean ( $ var ) {
103+ private function clean ( $ var, $ key = '' ) {
104104 // If the variable is an array, recursively apply the function to each element of the array.
105105 if ( is_array ( $ var ) ) {
106- return array_map ( [ $ this , 'clean ' ], $ var );
106+ $ cleaned = [];
107+
108+ foreach ( $ var as $ k => $ v ) {
109+ $ cleaned [ $ k ] = $ this ->clean ( $ v , $ k );
110+ }
111+
112+ return $ cleaned ;
107113 }
108114
109115 // If the variable is a scalar value (string, integer, float, boolean).
110116 if ( is_scalar ( $ var ) ) {
117+ /**
118+ * If the variable is the options object, we only unslash it, but don't sanitize it yet.
119+ * Sanitization will happen after json_decode.
120+ */
121+ if ( $ key === 'options ' ) {
122+ return wp_unslash ( $ var );
123+ }
124+
111125 // Parse the variable using the wp_parse_url function.
112126 $ parsed = wp_parse_url ( $ var );
127+
113128 // If the variable has a scheme (e.g. http:// or https://), sanitize the variable using the esc_url_raw function.
114- if ( isset ( $ parsed [ 'scheme ' ] ) ) {
115- return esc_url_raw ( wp_unslash ( $ var ), [ $ parsed [ ' scheme ' ] ] );
129+ if ( isset ( $ parsed ['scheme ' ] ) ) {
130+ return esc_url_raw ( wp_unslash ( $ var ) );
116131 }
117132
118133 // If the variable does not have a scheme, sanitize the variable using the sanitize_text_field function.
@@ -157,54 +172,54 @@ private function maybe_handle_redirect( $direction ) {
157172 public function show_wizard () {
158173 $ request_data = $ this ->clean ( $ _REQUEST );
159174
160- if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ request_data [ '_nonce ' ], 'plausible_analytics_show_wizard ' ) < 1 ) {
175+ if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ request_data ['_nonce ' ], 'plausible_analytics_show_wizard ' ) < 1 ) {
161176 Messages::set_error ( __ ( 'Not allowed. ' , 'plausible-analytics ' ) );
162177
163178 wp_send_json_error ( null , 403 );
164179 }
165180
166181 delete_option ( 'plausible_analytics_wizard_done ' );
167182
168- $ this ->maybe_handle_redirect ( $ request_data [ 'redirect ' ] );
183+ $ this ->maybe_handle_redirect ( $ request_data ['redirect ' ] );
169184
170185 wp_send_json_success ();
171186 }
172187
173188 /**
174189 * Save Admin Settings
175190 *
176- * @since 1.0.0
177191 * @return void
192+ * @since 1.0.0
178193 */
179194 public function toggle_option () {
180195 // Sanitize all the post data before using.
181196 $ post_data = $ this ->clean ( $ _POST );
182197 $ settings = Helpers::get_settings ();
183198
184- if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ post_data [ '_nonce ' ], 'plausible_analytics_toggle_option ' ) < 1 ) {
199+ if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ post_data ['_nonce ' ], 'plausible_analytics_toggle_option ' ) < 1 ) {
185200 wp_send_json_error ( __ ( 'Not allowed. ' , 'plausible-analytics ' ), 403 );
186201 }
187202
188- if ( $ post_data [ 'is_list ' ] ) {
203+ if ( $ post_data ['is_list ' ] ) {
189204 /**
190205 * Toggle lists.
191206 */
192- if ( $ post_data [ 'toggle_status ' ] === 'on ' ) {
207+ if ( $ post_data ['toggle_status ' ] === 'on ' ) {
193208 // If toggle is on, store the value under a new key.
194- if ( ! in_array ( $ post_data [ 'option_value ' ], $ settings [ $ post_data [ 'option_name ' ] ] ) ) {
195- $ settings [ $ post_data [ 'option_name ' ] ][] = $ post_data [ 'option_value ' ];
209+ if ( ! in_array ( $ post_data ['option_value ' ], $ settings [ $ post_data ['option_name ' ] ] ) ) {
210+ $ settings [ $ post_data ['option_name ' ] ][] = $ post_data ['option_value ' ];
196211 }
197212 } else {
198213 // If toggle is off, find the key by its value and unset it.
199- if ( ( $ key = array_search ( $ post_data [ 'option_value ' ], $ settings [ $ post_data [ 'option_name ' ] ] ) ) !== false ) {
200- unset( $ settings [ $ post_data [ 'option_name ' ] ][ $ key ] );
214+ if ( ( $ key = array_search ( $ post_data ['option_value ' ], $ settings [ $ post_data ['option_name ' ] ] ) ) !== false ) {
215+ unset( $ settings [ $ post_data ['option_name ' ] ][ $ key ] );
201216 }
202217 }
203218 } else {
204219 /**
205220 * Single toggles.
206221 */
207- $ settings [ $ post_data [ 'option_name ' ] ] = $ post_data [ 'toggle_status ' ];
222+ $ settings [ $ post_data ['option_name ' ] ] = $ post_data ['toggle_status ' ];
208223 }
209224
210225 // Update all the options to plausible settings.
@@ -213,22 +228,22 @@ public function toggle_option() {
213228 /**
214229 * Allow devs to perform additional actions.
215230 */
216- do_action ( 'plausible_analytics_settings_saved ' , $ settings , $ post_data [ 'option_name ' ], $ post_data [ 'toggle_status ' ] );
231+ do_action ( 'plausible_analytics_settings_saved ' , $ settings , $ post_data ['option_name ' ], $ post_data ['toggle_status ' ] );
217232
218- $ option_label = $ post_data [ 'option_label ' ];
219- $ toggle_status = $ post_data [ 'toggle_status ' ] === 'on ' ? __ ( 'enabled ' , 'plausible-analytics ' ) : __ ( 'disabled ' , 'plausible-analytics ' );
233+ $ option_label = $ post_data ['option_label ' ];
234+ $ toggle_status = $ post_data ['toggle_status ' ] === 'on ' ? __ ( 'enabled ' , 'plausible-analytics ' ) : __ ( 'disabled ' , 'plausible-analytics ' );
220235 $ message = apply_filters (
221236 'plausible_analytics_toggle_option_success_message ' ,
222237 sprintf ( '%s %s. ' , $ option_label , $ toggle_status ),
223- $ post_data [ 'option_name ' ],
224- $ post_data [ 'toggle_status ' ]
238+ $ post_data ['option_name ' ],
239+ $ post_data ['toggle_status ' ]
225240 );
226241
227242 Messages::set_success ( $ message );
228243
229- $ additional = $ this ->maybe_render_additional_message ( $ post_data [ 'option_name ' ], $ post_data [ 'toggle_status ' ] );
244+ $ additional = $ this ->maybe_render_additional_message ( $ post_data ['option_name ' ], $ post_data ['toggle_status ' ] );
230245
231- Messages::set_additional ( $ additional , $ post_data [ 'option_name ' ] );
246+ Messages::set_additional ( $ additional , $ post_data ['option_name ' ] );
232247
233248 wp_send_json_success ( null , 200 );
234249 }
@@ -271,17 +286,21 @@ public function save_options() {
271286 $ post_data = $ this ->clean ( $ _POST );
272287 $ settings = Helpers::get_settings ();
273288
274- if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ post_data [ '_nonce ' ], 'plausible_analytics_toggle_option ' ) < 1 ) {
289+ if ( ! current_user_can ( 'manage_options ' ) || wp_verify_nonce ( $ post_data ['_nonce ' ], 'plausible_analytics_toggle_option ' ) < 1 ) {
275290 Messages::set_error ( __ ( 'Not allowed. ' , 'plausible-analytics ' ) );
276291
277292 wp_send_json_error ( null , 403 );
278293 }
279294
280- $ options = json_decode ( $ post_data [ 'options ' ] );
295+ $ options = json_decode ( $ post_data ['options ' ] );
281296
282297 if ( empty ( $ options ) ) {
283298 Messages::set_error ( __ ( 'No options found to save. ' , 'plausible-analytics ' ) );
284299
300+ if ( defined ( 'PLAUSIBLE_CI ' ) ) {
301+ return ;
302+ }
303+
285304 wp_send_json_error ( null , 400 );
286305 }
287306
@@ -298,46 +317,52 @@ function ( $option ) {
298317 );
299318
300319 if ( count ( $ input_array_elements ) > 0 ) {
301- $ options = [];
302- $ array_name = preg_replace ( '/\[[0-9]+]/ ' , '' , $ input_array_elements [ 0 ]->name );
303- $ options [ 0 ] = (object ) [];
304- $ options [ 0 ]->name = $ array_name ;
320+ $ options = [];
321+ $ array_name = preg_replace ( '/\[[0-9]+]/ ' , '' , $ input_array_elements [0 ]->name );
322+ $ options [0 ] = (object ) [];
323+ $ options [0 ]->name = $ array_name ;
324+ $ options [0 ]->value = [];
305325
306326 foreach ( $ input_array_elements as $ input_array_element ) {
307327 if ( $ input_array_element ->value ) {
308- $ options [ 0 ]->value [] = $ input_array_element ->value ;
328+ $ options [0 ]->value [] = $ input_array_element ->value ;
309329 }
310330 }
311331 }
312332
313333 foreach ( $ options as $ option ) {
334+ $ name = sanitize_text_field ( $ option ->name );
335+ $ value = $ this ->clean ( $ option ->value );
336+
314337 // Clean spaces
315- if ( is_string ( $ option -> value ) ) {
316- $ settings [ $ option -> name ] = trim ( $ option -> value );
338+ if ( is_string ( $ value ) ) {
339+ $ settings [ $ name ] = trim ( $ value );
317340 } else {
318- $ settings [ $ option -> name ] = $ option -> value ;
341+ $ settings [ $ name ] = $ value ;
319342 }
320343
321344 // Validate Plugin Token if this is the Plugin Token field.
322- if ( $ option -> name === 'api_token ' ) {
323- $ this ->validate_api_token ( $ option -> value );
345+ if ( $ name === 'api_token ' ) {
346+ $ this ->validate_api_token ( $ value );
324347
325- $ additional = $ this ->maybe_render_additional_message ( $ option -> name , $ option -> value );
348+ $ additional = $ this ->maybe_render_additional_message ( $ name , $ value );
326349
327- Messages::set_additional ( $ additional , $ option -> name );
350+ Messages::set_additional ( $ additional , $ name );
328351 }
329352
330353 // Refresh Tracker ID if Domain Name has changed (e.g. after migration from staging to production)
331- if ($ option -> name === 'domain_name ' ) {
332- delete_option ('plausible_analytics_tracker_id ' );
354+ if ( $ name === 'domain_name ' ) {
355+ delete_option ( 'plausible_analytics_tracker_id ' );
333356 }
334357 }
335358
336359 update_option ( 'plausible_analytics_settings ' , $ settings );
337360
338361 Messages::set_success ( __ ( 'Settings saved. ' , 'plausible-analytics ' ) );
339362
340- wp_send_json_success ( null , 200 );
363+ if ( ! defined ( 'PLAUSIBLE_CI ' ) ) {
364+ wp_send_json_success ( null , 200 );
365+ }
341366 }
342367
343368 /**
0 commit comments