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