PluginProbe ʕ •ᴥ•ʔ
Hustle – Email Marketing, Lead Generation, Optins, Popups / 7.8.14.1
Hustle – Email Marketing, Lead Generation, Optins, Popups v7.8.14.1
7.8.14 7.8.14.1 7.8.13 7.8.13.1 trunk 3.0 3.1 3.1.1 3.1.2 3.1.3 3.1.4 4.3.2 4.4.4 4.4.5 4.4.5.1 4.4.5.4 4.6 4.6.1.1 4.6.1.4 4.7.0.2 4.7.0.3 4.7.0.7 4.7.0.9 4.7.1.0 4.7.1.1 4.8.0.0 5.0.0 5.0.1 5.0.1.1 5.0.1.2 5.1 5.1.1 5.1.2 5.1.3 5.1.3.1 5.1.3.2 5.1.4 5.1.5 6.0 6.0.1 6.0.2 6.0.3 6.0.4.2 6.0.5 6.0.6.1 6.0.7 6.0.8.1 6.0.9 7.0.0.1 7.0.2 7.0.3 7.0.4 7.1.0 7.1.1 7.2.0 7.2.1 7.3.0 7.3.1 7.3.3 7.3.5 7.3.6 7.3.7 7.4.0 7.4.1 7.4.11 7.4.13 7.4.13.1 7.4.2 7.4.3 7.4.4 7.4.5 7.4.5.1 7.4.5.2 7.4.6 7.4.7 7.5.0 7.6.0 7.6.1 7.6.3 7.6.4 7.6.6 7.7.0 7.7.1 7.8.0 7.8.1 7.8.10 7.8.10.1 7.8.10.2 7.8.11 7.8.12 7.8.12.1 7.8.2 7.8.3 7.8.4 7.8.5 7.8.6 7.8.7 7.8.8 7.8.9 7.8.9.1 7.8.9.2 7.8.9.3
wordpress-popup / inc / hustle-settings-admin-ajax.php
wordpress-popup / inc Last commit date
display-conditions 5 months ago front 2 days ago helpers 1 month ago metas 3 months ago multisite 5 months ago palettes 3 years ago provider 1 month ago providers 2 days ago templates 3 years ago update 5 months ago class-hustle-admin-page-abstract.php 1 month ago class-hustle-auth-token.php 5 months ago class-hustle-condition-factory.php 6 years ago class-hustle-cross-sell.php 10 months ago class-hustle-dashboard-admin.php 1 month ago class-hustle-data.php 1 month ago class-hustle-db.php 2 years ago class-hustle-installer.php 4 years ago class-hustle-meta.php 3 years ago class-hustle-module-admin.php 1 month ago class-hustle-module-collection.php 5 months ago class-hustle-module-fields.php 3 months ago class-hustle-module-page-abstract.php 1 month ago class-hustle-module-validator.php 3 months ago class-hustle-notifications.php 2 days ago class-hustle-settings-admin.php 1 month ago class-hustle-wp-dashboard-page.php 5 months ago class-opt-in.php 2 days ago hustle-background-conversion-log.php 3 months ago hustle-deletion.php 3 months ago hustle-embedded-admin.php 3 years ago hustle-entries-admin.php 5 months ago hustle-entry-model.php 1 month ago hustle-general-data-protection.php 5 months ago hustle-init.php 1 month ago hustle-mail.php 5 months ago hustle-migration.php 5 months ago hustle-model.php 2 days ago hustle-module-model.php 1 month ago hustle-module-widget-legacy.php 5 months ago hustle-module-widget.php 5 months ago hustle-modules-common-admin-ajax.php 1 month ago hustle-popup-admin.php 3 years ago hustle-providers-admin.php 1 month ago hustle-providers.php 5 months ago hustle-settings-admin-ajax.php 1 month ago hustle-settings-page.php 3 years ago hustle-slidein-admin.php 3 years ago hustle-sshare-admin.php 2 days ago hustle-sshare-model.php 2 days ago hustle-tracking-model.php 3 months ago interface-hustle-auth-provider.php 5 months ago opt-in-geo.php 5 months ago opt-in-utils.php 2 days ago opt-in-wpmudev-api.php 5 months ago
hustle-settings-admin-ajax.php
857 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Hustle_Settings_Admin_Ajax
4 *
5 * @package Hustle
6 */
7
8 /**
9 * Class Hustle_Settings_Admin_Ajax
10 */
11 class Hustle_Settings_Admin_Ajax {
12
13 /**
14 * Constructor
15 */
16 public function __construct() {
17
18 add_action( 'wp_ajax_hustle_remove_ips', array( $this, 'remove_ips_from_tables' ) );
19 add_action( 'wp_ajax_hustle_reset_settings', array( $this, 'reset_settings' ) );
20
21 // Return the recaptcha script for preview.
22 add_action( 'wp_ajax_hustle_load_recaptcha_preview', array( $this, 'load_recaptcha_preview' ) );
23
24 // Return the turnstile script for preview.
25 add_action( 'wp_ajax_hustle_load_turnstile_preview', array( $this, 'load_turnstile_preview' ) );
26
27 // Color Palette tab actions.
28 add_action( 'wp_ajax_hustle_handle_palette_actions', array( $this, 'handle_palette_actions' ) );
29
30 // Handle saving settings.
31 add_action( 'wp_ajax_hustle_save_settings', array( $this, 'ajax_settings_save' ) );
32 }
33
34 /**
35 * Filter IPs
36 *
37 * @since 4.0
38 * @param string $ip_string IPs string.
39 * @return array valid IPs
40 */
41 private function filter_ips( $ip_string ) {
42
43 // Create an array with their values.
44 $ip_array = preg_split( '/[\s,]+/', $ip_string, -1, PREG_SPLIT_NO_EMPTY );
45
46 // Remove from the array the IPs that are not valid IPs.
47 foreach ( $ip_array as $key => $ip ) {
48 if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
49 unset( $ip_array[ $key ] );
50 continue;
51 }
52 }
53
54 return $ip_array;
55 }
56
57 /**
58 * Reset the plugin
59 *
60 * @since 4.0.3
61 */
62 public function reset_settings() {
63 Opt_In_Utils::validate_ajax_call( 'hustle_reset_settings' );
64 Opt_In_Utils::is_user_allowed_ajax( 'hustle_edit_settings' );
65
66 /**
67 * Fires before Settings reset
68 *
69 * @since 4.0.3
70 */
71 do_action( 'hustle_before_reset_settings' );
72
73 // Delete starts here.
74 Hustle_Deletion::hustle_delete_custom_options();
75 Hustle_Deletion::hustle_delete_addon_options();
76 Hustle_Deletion::hustle_clear_module_views();
77 Hustle_Deletion::hustle_clear_module_submissions();
78 Hustle_Deletion::hustle_clear_modules();
79
80 /**
81 * Fires after Settings reset
82 *
83 * @since 4.0.3
84 */
85 do_action( 'hustle_after_reset_settings' );
86 }
87
88 /**
89 * Remove the requested IPs from views and conversions on batches.
90 *
91 * @since 3.0.6
92 */
93 public function remove_ips_from_tables() {
94 Opt_In_Utils::validate_ajax_call( 'hustle_remove_ips' );
95 Opt_In_Utils::is_user_allowed_ajax( 'hustle_edit_settings' );
96
97 /**
98 * From Tracking
99 */
100 $range = filter_input( INPUT_POST, 'range', FILTER_SANITIZE_SPECIAL_CHARS );
101 $tracking = Hustle_Tracking_Model::get_instance();
102 $hustle_entries_admin = new Hustle_Entry_Model();
103
104 if ( 'all' === $range ) {
105 $tracking->set_null_on_all_ips();
106 $hustle_entries_admin->delete_all_ips();
107 $message = esc_html__( 'All IP addresses have been successfully deleted from the database.', 'hustle' );
108
109 } else {
110 $values = filter_input( INPUT_POST, 'ips', FILTER_SANITIZE_SPECIAL_CHARS );
111 if ( ! empty( $values ) ) {
112 $values = preg_replace( '/ /', '', $values );
113 $r = preg_split( '/[\r\n]/', $values );
114 $ips = array();
115 foreach ( $r as $one ) {
116 $is_valid = ( filter_var( $one, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) || filter_var( $one, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) );
117
118 if ( $is_valid ) {
119 $ips[] = $one;
120 continue;
121 }
122 $a = explode( '-', $one );
123 if ( 2 !== count( $a ) ) {
124 continue;
125 }
126 $is_valid = filter_var( $a[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );
127 if ( ! $is_valid ) {
128 continue;
129 }
130 $is_valid = filter_var( $a[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );
131 if ( ! $is_valid ) {
132 continue;
133 }
134 $ips[] = array_map( 'ip2long', $a );
135 }
136 $tracking->set_null_on_selected_ips( $ips );
137 $hustle_entries_admin->delete_selected_ips( $ips );
138 $message = esc_html__( 'All selected IP addresses have been successfully deleted from the database.', 'hustle' );
139
140 } else {
141 $message = esc_html__( 'No IPs were deleted. You must provide at least one IP.', 'hustle' );
142 }
143 }
144
145 wp_send_json_success( array( 'message' => $message ) );
146 }
147
148 /**
149 * Saves the global privacy settings.
150 *
151 * @since 4.0
152 */
153 public function save_privacy_settings() {
154
155 $filter_args = array(
156 'ip_tracking' => FILTER_SANITIZE_SPECIAL_CHARS,
157 // Account erasure request.
158 'retain_sub_on_erasure' => FILTER_SANITIZE_SPECIAL_CHARS,
159 // Submissions retention.
160 'retain_submission_forever' => FILTER_SANITIZE_SPECIAL_CHARS,
161 'submissions_retention_number' => FILTER_SANITIZE_NUMBER_INT,
162 'submissions_retention_number_unit' => FILTER_SANITIZE_SPECIAL_CHARS,
163 // IPs retention.
164 'retain_ip_forever' => FILTER_SANITIZE_SPECIAL_CHARS,
165 'ip_retention_number' => FILTER_SANITIZE_NUMBER_INT,
166 'ip_retention_number_unit' => FILTER_SANITIZE_SPECIAL_CHARS,
167 // Tracking retention.
168 'retain_tracking_forever' => FILTER_SANITIZE_SPECIAL_CHARS,
169 'tracking_retention_number' => FILTER_SANITIZE_NUMBER_INT,
170 'tracking_retention_number_unit' => FILTER_SANITIZE_SPECIAL_CHARS,
171 );
172 $data = filter_input_array( INPUT_POST, $filter_args, false );
173
174 $stored_settings = Hustle_Settings_Admin::get_privacy_settings();
175
176 $new_settings = array_merge( $stored_settings, $data );
177
178 Hustle_Settings_Admin::update_hustle_settings( $new_settings, 'privacy' );
179 wp_send_json_success();
180 }
181
182 /**
183 * Saves the global privacy settings.
184 *
185 * @since 4.0.2
186 */
187 public function save_data_settings() {
188
189 $reset_settings_uninstall = filter_input( INPUT_POST, 'reset_settings_uninstall', FILTER_SANITIZE_SPECIAL_CHARS );
190 $reset_all_sites = filter_input( INPUT_POST, 'reset_all_sites', FILTER_SANITIZE_SPECIAL_CHARS );
191
192 $value = array(
193 'reset_settings_uninstall' => '1' === $reset_settings_uninstall ? '1' : '0',
194 );
195 if ( $reset_all_sites ) {
196 $value['reset_all_sites'] = $reset_all_sites;
197 }
198
199 Hustle_Settings_Admin::update_hustle_settings( $value, 'data' );
200 wp_send_json_success();
201 }
202
203 /**
204 * Save the data under the Top Metric tab.
205 *
206 * @since 4.0.0
207 */
208 private function save_top_metrics_settings() {
209 $data = filter_input( INPUT_POST, 'metrics', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
210 $metrics = ! empty( $data ) ? array_filter( $data ) : array();
211
212 // Only 3 metrics can be selected. No more.
213 if ( 3 < count( $metrics ) ) {
214 wp_send_json_error(
215 array(
216 'notification' => array(
217 'status' => 'error',
218 'message' => esc_html__( "You can't select more than 3 metrics.", 'hustle' ),
219 ),
220 )
221 );
222 }
223
224 $allowed_metric_keys = array(
225 'average_conversion_rate',
226 'today_conversions',
227 'last_week_conversions',
228 'last_month_conversions',
229 'total_conversions',
230 'most_conversions',
231 'inactive_modules_count',
232 'total_modules_count',
233 );
234
235 $data_to_store = array();
236 foreach ( $metrics as $name ) {
237 if ( in_array( $name, $allowed_metric_keys, true ) ) {
238 $data_to_store[] = $name;
239 }
240 }
241
242 Hustle_Settings_Admin::update_hustle_settings( $data_to_store, 'top_metrics' );
243 wp_send_json_success();
244 }
245
246 /**
247 * Save the reCaptcha settings.
248 *
249 * @since 4.0
250 */
251 private function save_recaptcha_settings() {
252
253 $settings_to_save = array(
254 // V2 Checkbox.
255 'v2_checkbox_site_key' => '',
256 'v2_checkbox_secret_key' => '',
257 // V2 Invisible.
258 'v2_invisible_site_key' => '',
259 'v2_invisible_secret_key' => '',
260 // V3 Recaptcha.
261 'v3_recaptcha_site_key' => '',
262 'v3_recaptcha_secret_key' => '',
263 'language' => 'automatic',
264 );
265
266 foreach ( $settings_to_save as $key => $value ) {
267 $incoming_setting = filter_input( INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS );
268
269 if ( $incoming_setting ) {
270 $settings_to_save[ $key ] = trim( $incoming_setting );
271 }
272 }
273
274 // Keep these keys stored in case the user rolls back to before 4.0.3.
275 $settings_to_save['sitekey'] = $settings_to_save['v2_checkbox_site_key'];
276 $settings_to_save['secret'] = $settings_to_save['v2_checkbox_secret_key'];
277
278 Hustle_Settings_Admin::update_hustle_settings( $settings_to_save, 'recaptcha' );
279
280 wp_send_json_success(
281 array(
282 'notification' => array(
283 'status' => 'success',
284 'message' => esc_html__( 'reCAPTCHA configured successfully. You can now add reCAPTCHA field to your opt-in forms where you want the reCAPTCHA to appear.', 'hustle' ),
285 ),
286 'callback' => 'actionSaveRecaptcha',
287 )
288 );
289 }
290
291 /**
292 * Save the Cloudflare Turnstile settings.
293 *
294 * @since 4.0.0
295 */
296 private function save_turnstile_settings() {
297
298 $settings_to_save = array(
299 'turnstile_api_key' => '',
300 'turnstile_client_secret' => '',
301 'language' => 'auto',
302 );
303
304 foreach ( $settings_to_save as $key => $value ) {
305 $incoming_setting = filter_input( INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS );
306
307 if ( $incoming_setting ) {
308 $settings_to_save[ $key ] = trim( $incoming_setting );
309 }
310 }
311
312 Hustle_Settings_Admin::update_hustle_settings( $settings_to_save, 'turnstile' );
313
314 wp_send_json_success(
315 array(
316 'notification' => array(
317 'status' => 'success',
318 'message' => esc_html__( 'Cloudflare Turnstile configured successfully.', 'hustle' ),
319 ),
320 )
321 );
322 }
323
324 /**
325 * Save the Accessibility settings.
326 *
327 * @since 4.0.0
328 */
329 private function save_accessibility_settings() {
330
331 $accessibility_color = filter_input( INPUT_POST, 'hustle-accessibility-color', FILTER_VALIDATE_BOOLEAN );
332
333 if ( is_null( $accessibility_color ) ) {
334 wp_send_json_error();
335 }
336 $value = array(
337 'accessibility_color' => $accessibility_color,
338 );
339
340 Hustle_Settings_Admin::update_hustle_settings( $value, 'accessibility' );
341
342 wp_send_json_success( array( 'url' => true ) );
343 }
344
345 /**
346 * Save the Unsubscribe settings.
347 *
348 * @since 4.0.0
349 */
350 private function save_unsubscribe_settings() {
351
352 $data = $_POST;// phpcs:ignore WordPress.Security.NonceVerification.Missing
353 $email_body = wp_json_encode( wp_kses_post( $data['email_message'] ) );
354 $sanitized_data = Opt_In_Utils::validate_and_sanitize_fields( $data );
355
356 // Save the messages to be displayed in the unsubscription process.
357 $messages_data = array(
358 'enabled' => isset( $sanitized_data['messages_enabled'] ) ? $sanitized_data['messages_enabled'] : '0',
359 'get_lists_button_text' => $sanitized_data['get_lists_button_text'],
360 'submit_button_text' => $sanitized_data['submit_button_text'],
361 'invalid_email' => $sanitized_data['invalid_email'],
362 'email_not_found' => $sanitized_data['email_not_found'],
363 'invalid_data' => $sanitized_data['invalid_data'],
364 'email_submitted' => $sanitized_data['email_submitted'],
365 'successful_unsubscription' => $sanitized_data['successful_unsubscription'],
366 'email_not_processed' => $sanitized_data['email_not_processed'],
367 );
368
369 // Save the unsubscription email settings.
370 $email_data = array(
371 'enabled' => isset( $sanitized_data['email_enabled'] ) ? $sanitized_data['email_enabled'] : '0',
372 'email_subject' => $sanitized_data['email_subject'],
373 'email_body' => $email_body,
374 );
375
376 $value = array(
377 'messages' => $messages_data,
378 'email' => $email_data,
379 );
380 Hustle_Settings_Admin::update_hustle_settings( $value, 'unsubscribe' );
381
382 wp_send_json_success();
383 }
384
385 /**
386 * Return the Cloudflare Turnstile script to be added in the page.
387 *
388 * @since 7.13.0
389 */
390 public function load_turnstile_preview() {
391
392 $source = Hustle_Module_Front::add_turnstile_script( true, true );
393 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
394 $html = '<script src="' . esc_url( $source ) . '" async defer></script>';
395
396 wp_send_json_success( $html );
397 }
398
399 /**
400 * Return the recaptcha script to be added in the page.
401 * This script changes when the recaptcha's language changes,
402 * so it must be updated on language change when previewing.
403 *
404 * @since 4.0.3
405 */
406 public function load_recaptcha_preview() {
407
408 $source = Hustle_Module_Front::add_recaptcha_script( '', true, true );
409 // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
410 $html = '<script src="' . esc_url( $source ) . '" async defer></script>';
411
412 wp_send_json_success( $html );
413 }
414
415 /**
416 * Save Hustle settings
417 *
418 * @since 4.0
419 *
420 * @todo Handle error messages
421 */
422 public function ajax_settings_save() {
423 Opt_In_Utils::validate_ajax_call( 'hustle_settings_save' );
424 Opt_In_Utils::is_user_allowed_ajax( 'hustle_edit_settings' );
425
426 $tab = filter_input( INPUT_POST, 'target', FILTER_SANITIZE_SPECIAL_CHARS );
427
428 switch ( $tab ) {
429 case 'permissions':
430 $this->save_permissions_settings();
431 break;
432
433 case 'general':
434 $this->save_general_settings();
435 break;
436
437 case 'top_metrics':
438 $this->save_top_metrics_settings();
439 break;
440
441 case 'analytics':
442 $this->save_dashboard_analytics_settings();
443 break;
444
445 case 'recaptcha':
446 $this->save_recaptcha_settings();
447 break;
448
449 case 'turnstile':
450 $this->save_turnstile_settings();
451 break;
452
453 case 'accessibility':
454 $this->save_accessibility_settings();
455 break;
456
457 case 'unsubscribe':
458 $this->save_unsubscribe_settings();
459 break;
460
461 case 'privacy':
462 $this->save_privacy_settings();
463 break;
464
465 case 'data':
466 $this->save_data_settings();
467 break;
468
469 default:
470 break;
471 }
472
473 // The action is not listed. No one should land here if following the regular plugin's paths.
474 wp_send_json_error(
475 array(
476 'notification' => array(
477 'status' => 'error',
478 'message' => esc_html__( "The action you're trying to perform was not found.", 'hustle' ),
479 ),
480 )
481 );
482 }
483
484
485 /**
486 * Handles saving the "Permissions" settings.
487 *
488 * @since 4.1.0
489 */
490 private function save_permissions_settings() {
491
492 // Handle per module roles. We'll go with per permission next.
493 $current_modules_ids = filter_input( INPUT_POST, 'modules_ids', FILTER_SANITIZE_SPECIAL_CHARS );
494 $modules_ids = empty( $current_modules_ids ) ? array() : explode( ',', $current_modules_ids );
495
496 if ( ! empty( $modules_ids ) ) {
497 $modules_roles = filter_input( INPUT_POST, 'modules', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
498
499 foreach ( $modules_ids as $module_id ) {
500
501 $module = Hustle_Module_Model::new_instance( $module_id );
502 if ( ! is_wp_error( $module ) ) {
503
504 $selected_roles = isset( $modules_roles[ $module_id ] ) ? $modules_roles[ $module_id ] : array();
505 $module->update_edit_roles( $selected_roles );
506 }
507 }
508 }
509
510 // Handling per permissions roles here.
511 $filter = array(
512 'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
513 'flags' => FILTER_REQUIRE_ARRAY,
514 );
515 $filter_options = array(
516 'create' => $filter,
517 'edit_integrations' => $filter,
518 'access_emails' => $filter,
519 'edit_settings' => $filter,
520 );
521 $incoming = filter_input_array( INPUT_POST, $filter_options );
522
523 // If the role can create modules, it can also edit them.
524 $incoming['edit'] = $incoming['create'];
525
526 // Capability related to each incoming input.
527 $hustle_capabilities = array(
528 'create' => 'hustle_create',
529 'edit' => 'hustle_edit_module',
530 'edit_integrations' => 'hustle_edit_integrations',
531 'access_emails' => 'hustle_access_emails',
532 'edit_settings' => 'hustle_edit_settings',
533 );
534
535 $existing_roles = Opt_In_Utils::get_user_roles();
536
537 // Loop through the submitted capabilities.
538 foreach ( $incoming as $capability => $selected_roles ) {
539
540 if ( ! is_array( $selected_roles ) ) {
541 // The filter failed. No roles were selected.
542 $incoming[ $capability ] = array();
543 $selected_roles = array();
544
545 } else {
546
547 // Loop through the selected roles of this capability. Unset any invalid role.
548 foreach ( $selected_roles as $key => $role_slug ) {
549
550 if ( ! isset( $existing_roles[ $role_slug ] ) ) {
551 unset( $incoming[ $capability ][ $key ] );
552 }
553 }
554 }
555
556 // Update roles capabilities.
557 foreach ( $existing_roles as $role_slug => $role_name ) {
558 if ( Opt_In_Utils::is_admin_role( $role_slug ) ) {
559 continue;
560 }
561
562 $role = get_role( $role_slug );
563
564 $cap = $hustle_capabilities[ $capability ];
565 if ( in_array( $role_slug, $selected_roles, true ) ) {
566 // Add capability.
567 $role->add_cap( $cap );
568
569 } elseif ( 'edit' === $capability ) { // Check if this role can edit at least one module before removing the cap.
570 if ( ! Hustle_Module_Model::can_role_edit_one_module( $role_slug ) ) {
571 // Remove capability.
572 $role->remove_cap( $cap );
573 } else {
574 $role->add_cap( $cap );
575 }
576 } else {
577 // Remove capability.
578 $role->remove_cap( $cap );
579 }
580 }
581 }
582
583 // Store per permission roles.
584 Hustle_Settings_Admin::update_hustle_settings( $incoming, 'permissions' );
585
586 wp_send_json_success();
587 }
588
589 /**
590 * Handles saving the "General" settings.
591 *
592 * @since 4.1.0
593 */
594 private function save_general_settings() {
595
596 // Retrieve the stored data.
597 $stored_values = Hustle_Settings_Admin::get_general_settings();
598
599 // Sanitize the incoming data.
600 foreach ( $stored_values as $key => $value ) {
601 if ( 'sender_email_address' !== $key ) {
602 $new_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_SPECIAL_CHARS );
603 } else {
604 $new_value = filter_input( INPUT_POST, $key, FILTER_VALIDATE_EMAIL );
605 }
606
607 // Update it if valid.
608 if ( false !== $new_value && ! is_null( $new_value ) ) {
609 // Reload page if global_tracking_disabled is changed because there are dependent settings like Dashboard Analytics.
610 if ( 'global_tracking_disabled' === $key && $stored_values[ $key ] !== $new_value ) {
611 $reload = true;
612 }
613 $stored_values[ $key ] = $new_value;
614 }
615 }
616
617 Hustle_Settings_Admin::update_hustle_settings( $stored_values, 'general' );
618
619 if ( empty( $reload ) ) {
620 wp_send_json_success();
621 } else {
622 wp_send_json_success( array( 'url' => true ) );
623 }
624 }
625
626 /**
627 * Handles saving the "Dashboard Analytics" settings.
628 *
629 * @since 4.1.0
630 */
631 private function save_dashboard_analytics_settings() {
632
633 $reload = false;
634 $value = Hustle_Settings_Admin::get_hustle_settings( 'analytics' );
635
636 // Handle enable/disable action.
637 $enable_toggled = filter_input( INPUT_POST, 'enabled', FILTER_SANITIZE_SPECIAL_CHARS );
638 if ( false !== $enable_toggled && ! is_null( $enable_toggled ) ) {
639 $value['enabled'] = $enable_toggled;
640 $reload = true;
641
642 } else {
643
644 // Handle storing the actual settings.
645 $filter_args = array(
646 'modules' => array(
647 'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
648 'flags' => FILTER_REQUIRE_ARRAY,
649 ),
650 'role' => array(
651 'filter' => FILTER_SANITIZE_SPECIAL_CHARS,
652 'flags' => FILTER_REQUIRE_ARRAY,
653 ),
654 'title' => FILTER_SANITIZE_SPECIAL_CHARS,
655 );
656 $filtered_data = filter_input_array( INPUT_POST, $filter_args );
657
658 // Use defaults if the filter fails or the value isn't set.
659 $modules = ! empty( $filtered_data['modules'] ) ? array_filter( $filtered_data['modules'] ) : array();
660 $selected_roles = ! empty( $filtered_data['role'] ) ? $filtered_data['role'] : array();
661 $title = is_string( $filtered_data['title'] ) ? $filtered_data['title'] : '';
662
663 $value = array(
664 'enabled' => '1',
665 'title' => $title,
666 'modules' => $modules,
667 'role' => Opt_In_Utils::get_admin_roles(),
668 );
669
670 // Store the roles if they exist.
671 $roles = Opt_In_Utils::get_user_roles();
672 foreach ( $selected_roles as $role_slug ) {
673 if ( isset( $roles[ $role_slug ] ) ) {
674 $value['role'][ $role_slug ] = $roles[ $role_slug ];
675 }
676 }
677
678 // Update roles capability.
679 foreach ( $roles as $role_key => $role_name ) {
680 $role = get_role( $role_key );
681 if ( Opt_In_Utils::is_admin_role( $role_key ) || ! $role ) {
682 continue;
683 }
684 $cap = 'hustle_analytics';
685 if ( in_array( $role_key, $selected_roles, true ) ) {
686 // add capability.
687 $role->add_cap( $cap );
688 } else {
689 // remove capability.
690 $role->remove_cap( $cap );
691 }
692 }
693 }
694
695 // TODO: delete transient on uninstall.
696 // TODO: get these dynamically.
697 // Delete the transients set for retrieving this data in the WP Dashboard.
698 // These are the same values available in Hustle_Wp_Dashboard_Page::get_analytic_ranges().
699 delete_transient( 'hustle_wp_widget_daily_stats_7' );
700 delete_transient( 'hustle_wp_widget_daily_stats_30' );
701 delete_transient( 'hustle_wp_widget_daily_stats_90' );
702
703 Hustle_Settings_Admin::update_hustle_settings( $value, 'analytics' );
704
705 if ( ! $reload ) {
706 wp_send_json_success();
707 } else {
708 wp_send_json_success( array( 'url' => true ) );
709 }
710 }
711
712 /**
713 * Handle the palette's actions.
714 *
715 * @since 4.0.3
716 */
717 public function handle_palette_actions() {
718
719 Opt_In_Utils::validate_ajax_call( 'hustle_palette_action' );
720 Opt_In_Utils::is_user_allowed_ajax( 'hustle_edit_settings' );
721
722 $palette_id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_SPECIAL_CHARS );
723 $action = filter_input( INPUT_POST, 'hustleAction', FILTER_SANITIZE_SPECIAL_CHARS );
724
725 $args = array(
726 'page' => Hustle_Data::SETTINGS_PAGE,
727 'section' => 'palettes',
728 );
729
730 switch ( $action ) {
731
732 case 'delete':
733 $name = Hustle_Settings_Admin::delete_custom_palette( $palette_id );
734 $args['show-notice'] = 'success';
735 $args['notice'] = 'palette_deleted';
736 $args['deleted-name'] = rawurlencode( $name );
737 break;
738
739 case 'go-to-step':
740 $step = filter_input( INPUT_POST, 'step', FILTER_SANITIZE_SPECIAL_CHARS );
741
742 if ( '2' === $step ) {
743 $this->action_edit_palette_go_second_step();
744 } else {
745 $id = $this->action_edit_palette_save();
746 $args['show-notice'] = 'success';
747 $args['notice'] = 'palette_saved';
748 $args['saved-id'] = rawurlencode( $id );
749 }
750 break;
751
752 default:
753 break;
754 }
755
756 $url = add_query_arg( $args, 'admin.php' );
757 $response = array( 'url' => $url );
758
759 wp_send_json_success( $response );
760 }
761
762 /**
763 * Palettes -> Edit palette. Handle the action from when going to second step.
764 *
765 * @since 4.0.3
766 */
767 private function action_edit_palette_go_second_step() {
768
769 $palette_slug = filter_input( INPUT_POST, 'slug', FILTER_SANITIZE_SPECIAL_CHARS );
770
771 if ( $palette_slug ) { // Editing an existing palette.
772
773 $palette_name = filter_input( INPUT_POST, 'name', FILTER_SANITIZE_SPECIAL_CHARS );
774 $palette_array = Hustle_Palettes_Helper::get_palette_array( $palette_slug );
775 $palette_array['slug'] = $palette_slug;
776 $palette_array['name'] = $palette_name;
777
778 $callback = 'actionOpenEditPalette';
779
780 } else { // Creating a new palette.
781
782 $callback = 'actionGoToSecondStep';
783 $base_source = filter_input( INPUT_POST, 'base_source', FILTER_SANITIZE_SPECIAL_CHARS );
784
785 if ( 'palette' === $base_source ) {
786 // Use an existing palette as the base.
787 $palette = filter_input( INPUT_POST, 'base_palette', FILTER_SANITIZE_SPECIAL_CHARS );
788 $palette_array = Hustle_Palettes_Helper::get_palette_array( $palette );
789
790 } else {
791 // Use a module's palette as the base.
792
793 $fallback_palette_name = filter_input( INPUT_POST, 'fallback_palette', FILTER_SANITIZE_SPECIAL_CHARS );
794 $fallback_palette = Hustle_Palettes_Helper::get_palette_array( $fallback_palette_name );
795
796 $module_id = filter_input( INPUT_POST, 'module_id', FILTER_VALIDATE_INT );
797
798 $module = Hustle_Module_Model::new_instance( $module_id );
799
800 if ( is_wp_error( $module ) ) {
801 $palette_array = $fallback_palette;
802
803 } else {
804 $design = $module->get_design()->to_array();
805
806 // remove option color keys from info modules.
807 if ( 'informational' === $module->module_mode ) {
808 $info = Hustle_Palettes_Helper::get_palette_array( 'info-module' );
809 $design = array_diff_key( $design, $info );
810 }
811
812 $module_palette = array_intersect_key( $design, $fallback_palette );
813 $palette_array = array_merge( $fallback_palette, $module_palette );
814 }
815 }
816 }
817
818 wp_send_json_success(
819 array(
820 'callback' => $callback,
821 'palette_data' => $palette_array,
822 )
823 );
824 }
825
826 /**
827 * Handle action for when saving the palette.
828 *
829 * @since 4.0.3
830 */
831 private function action_edit_palette_save() {
832
833 $palette_slug = filter_input( INPUT_POST, 'slug', FILTER_SANITIZE_SPECIAL_CHARS );
834 $palette_name = filter_input( INPUT_POST, 'palette_name', FILTER_SANITIZE_SPECIAL_CHARS );
835
836 $post_data = Opt_In_Utils::validate_and_sanitize_fields( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
837
838 // Remove non-palette data.
839 $palette_colors = array_intersect_key( $post_data, Hustle_Palettes_Helper::get_palette_array( 'gray_slate' ) );
840
841 $palette_data = array( 'palette' => $palette_colors );
842
843 if ( $palette_slug ) {
844 // Updating an existing palette.
845 $palette_data['slug'] = $palette_slug;
846
847 } else {
848 // Creating a new one.
849 $palette_data['name'] = $palette_name ? $palette_name : wp_rand();
850 }
851
852 $id = Hustle_Settings_Admin::save_custom_palette( $palette_data );
853
854 return $id;
855 }
856 }
857