PluginProbe
WANotifier for Forms and Actions / 2.7.4
WANotifier for Forms and Actions v2.7.4
3.1.0 3.0.4 2.7.10 2.7.11 2.7.12 2.7.13 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 3.0.0 3.0.1 3.0.2 3.0.3 trunk 0.1.0 0.1.1 1.0.0 1.0.1 1.0.2 1.0.3 All 66 releases
notifier / includes / classes / class-notifier-settings.php

class-notifier-settings.php in WANotifier for Forms and Actions 2.7.4, at includes/classes/class-notifier-settings.php

637 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings page class
4 *
5 * @package Wa_Notifier
6 */
7 class Notifier_Settings {
8
9 /**
10 * Init
11 */
12 public static function init() {
13 add_action( 'admin_menu', array( __CLASS__ , 'setup_admin_page') );
14 add_action( 'admin_init', array( __CLASS__ , 'save_settings_fields' ) );
15 add_action( 'admin_init', array( __CLASS__ , 'disconnect_notifier' ) );
16 add_action( 'wp_ajax_notifier_preview_btn_style', array(__CLASS__, 'preview_btn_style'));
17 }
18
19 /**
20 * Add settings page to men
21 */
22 public static function setup_admin_page () {
23 if (!Notifier::is_api_active()){
24 return;
25 }
26
27 add_submenu_page( NOTIFIER_NAME, 'Settings', 'Settings', 'manage_options', NOTIFIER_NAME . '-settings', array( __CLASS__, 'output' ) );
28 }
29
30 /**
31 * Output
32 */
33 public static function output() {
34 include_once NOTIFIER_PATH . '/views/admin-settings.php';
35 }
36
37 /**
38 * Get settings tabs
39 */
40 private static function get_settings_tabs() {
41 $tabs = array(
42 'general' => 'General',
43 'woocommerce' => 'WooCommerce',
44 'click_to_chat' => 'Click to Chat',
45 'api' => 'API',
46 'advanced' => 'Advanced',
47 );
48
49 if ( ! class_exists( 'WooCommerce' ) ) {
50 unset($tabs['woocommerce']);
51 }
52
53 return $tabs;
54 }
55
56 /**
57 * Check if on settings page
58 */
59 public static function is_settings_page() {
60 $current_page = isset($_GET['page']) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
61 return strpos($current_page, NOTIFIER_NAME . '-settings') !== false;
62 }
63
64 /**
65 * Settings fields
66 */
67 private static function settings_fields($tab) {
68 $api_key = get_option(NOTIFIER_PREFIX . 'api_key');
69 if(Notifier::is_api_active() && '' != $api_key) {
70 $disabled = true;
71 $description = 'You are successfully connected to WANotifier.com. <a href="?notifier_disconnect=1">Disconnect</a>.';
72 }
73 else{
74 $disabled = false;
75 $description = 'You are not connected to WANotifier.com yet. Please enter valid API key and save the settings. You can get your WANotifier.com API Key from <a href="https://app.wanotifier.com/settings/api/" target="_blank">here</a>.';
76 }
77 $settings = array();
78 switch ($tab) {
79 case 'general':
80 $settings = array(
81 array(
82 'title' => 'General',
83 'type' => 'title',
84 'description' => ''
85 ),
86 array(
87 'id' => 'default_country_code',
88 'title' => 'Default Country Code (Optional)',
89 'type' => 'text',
90 'placeholder' => 'Eg. +91',
91 'description' => 'Enter default country code that will be added to all recipient phone number fields before sending to WANotifier that do not start with a + sign.',
92 'default' => ''
93 ),
94 );
95
96 if ( class_exists( 'WooCommerce' ) ) {
97 $settings = array_merge( $settings, array(
98 array(
99 'title' => 'WooCommerce',
100 'type' => 'title',
101 'description' => ''
102 ),
103 array(
104 'id' => 'enable_opt_in_checkbox_checkout',
105 'title' => 'Opt-in Consent on Checkout',
106 'type' => 'checkbox',
107 'default' => '',
108 'label' => 'Enable',
109 'name' => 'enable_opt_in_checkbox_checkout',
110 'description' => 'Add an opt-in checkbox to WooCommerce checkout form. Once enabled, WhatsApp notification will be sent only to customers who opt-in during checkout.'
111 ),
112 array(
113 'id' => 'checkout_opt_in_checkbox_text',
114 'title' => 'Opt-in Checkbox Text',
115 'type' => 'textarea',
116 'placeholder' => 'Enter text for the opt-in checkbox',
117 'default' => 'Receive updates on WhatsApp',
118 'name' => 'checkout_opt_in_checkbox_text',
119 )
120 ) );
121 }
122
123 break;
124 case 'click_to_chat':
125 $settings = array(
126 array(
127 'title' => 'Click to Chat',
128 'description' => 'Show click to chat button on your website to let your visitors start WhatsApp chat with you.',
129 'type' => 'title',
130 ),
131 array(
132 'id' => 'ctc_enable',
133 'title' => 'Enable',
134 'type' => 'checkbox',
135 'default' => '',
136 'name' => 'ctc_enable',
137 ),
138 array(
139 'id' => 'ctc_whatsapp_number',
140 'title' => 'Whatsapp Number',
141 'type' => 'text',
142 'placeholder' => 'Enter your WhatsApp number',
143 'name' => 'ctc_whatsapp_number',
144 'description' => 'Enter your WhatsApp number with country code. Eg. +919876543210',
145 ),
146 array(
147 'id' => 'ctc_greeting_text',
148 'title' => 'Greeting Message',
149 'type' => 'text',
150 'name' => 'ctc_greeting_text',
151 'placeholder' => 'Enter your greeting message here',
152 'description' => 'This text will be added to user\'s WhatsApp chat text field when they click on the button.' ,
153 ),
154 array(
155 'id' => 'ctc_button_style',
156 'title' => 'Button Style',
157 'name' => 'ctc_button_style',
158 'class' => 'chat-button-style',
159 'type' => 'select',
160 'default' => '',
161 'options' => self::get_button_styles(),
162 'description' => 'Select a button style. Preview will be shown on bottom right of this screen. You can update button style by writing custom CSS in your theme.',
163 ),
164 array(
165 'id' => 'ctc_custom_button_image_url',
166 'title' => 'Button image url',
167 'type' => 'text',
168 'placeholder' => 'https://',
169 'name' => 'ctc_custom_button_image_url',
170 'description' => 'Enter button image url here.',
171 'tr_class' => 'notifier-chat-btn-image-url',
172 ),
173 );
174 break;
175 case 'api':
176 $settings = array(
177 array(
178 'title' => 'API Configuration',
179 'description' => '',
180 'type' => 'title',
181 ),
182 array(
183 'id' => 'api_key',
184 'title' => 'WANotifier.com API key',
185 'type' => 'text',
186 'placeholder' => 'Enter your WANotifier.com API key here',
187 'default' => '',
188 'description' => $description,
189 'disabled' => $disabled
190 ),
191 );
192 break;
193 case 'advanced':
194 $settings = array(
195 array(
196 'title' => 'Advanced Settings',
197 'description' => '',
198 'type' => 'title',
199 ),
200 array(
201 'id' => 'hidden_custom_keys',
202 'title' => 'Hidden custom meta keys',
203 'type' => 'checkbox',
204 'label' => 'Enable',
205 'description' => 'Enable hidden custom meta keys that start with underscores (e.g. _field_name) to be avaialbe in Data and Recipient Fields. Note that enabling this might impact your website performance slightly.',
206 'default' => ''
207 ),
208 array(
209 'id' => 'enable_async_triggers',
210 'title' => 'Async triggers',
211 'type' => 'checkbox',
212 'default' => '',
213 'label' => 'Enable',
214 'name' => 'enable_async_triggers',
215 'description' => 'Plugin slowing down checkout or form submission? Enable this option to send triggers asynchronously using Action Scheduler. Note that if you have a site with strong caching, this might not work as expected.' ,
216 ),
217 array(
218 'id' => 'enable_activity_log',
219 'title' => 'Activity log',
220 'type' => 'checkbox',
221 'default' => '',
222 'label' => 'Enable',
223 'name' => 'enable_activity_log',
224 'description' => 'Enabling this option will activate the activity logging feature. You can view activity logs <a href="/wp-admin/admin.php?page=notifier-tools">here</a>.' ,
225 ),
226 );
227 break;
228 case 'woocommerce':
229 if ( class_exists( 'WooCommerce' ) ) {
230 $settings = array(
231 array(
232 'id' => 'enable_abandonment_cart_tracking',
233 'title' => 'Abandoned cart tracking',
234 'type' => 'checkbox',
235 'default' => '',
236 'label' => 'Start capturing abandoned carts',
237 'name' => 'enable_abandonment_cart_tracking',
238 'description' => 'Enable this to start capturing abandoned carts in database. Carts will be considered as abandoned if order is not placed by the user after adding items in the cart within cart abandoned cut-off time set below.'
239 ),
240 array(
241 'id' => 'abandonment_cart_cron_run_time',
242 'title' => 'Cart abandoned cut-off time',
243 'type' => 'number',
244 'placeholder' => 'Enter time in minutes. Eg. 20',
245 'description' => 'Enter time in minutes after which the cart will be considered as abandoned. This is the time from when items are added / updated in cart.',
246 'default' => '20',
247 'custom_attributes' => array('min' => 20),
248 ),
249 );
250 }
251 break;
252 }
253 $settings = apply_filters( 'notifier_$tab_settings_fields', $settings );
254 return $settings;
255 }
256
257 /**
258 * Generate HTML for displaying individual fields
259 */
260 public static function display_field( $field ) {
261 $field = wp_parse_args($field, array(
262 'title' => '',
263 'description' => '',
264 'label' => ''
265 ));
266
267 $html = '';
268
269 if (isset($field['id'])) {
270 $option_name = NOTIFIER_PREFIX . $field['id'];
271 $option = get_option( $option_name );
272 }
273
274 $data = isset($option) ? $option : '';
275 if ( isset( $field['default'] ) && empty($option) ) {
276 $data = $field['default'];
277 }
278
279 $custom_attributes = array();
280 if ( ! empty( $field['custom_attributes'] ) && is_array( $field['custom_attributes'] ) ) {
281 foreach ( $field['custom_attributes'] as $attribute => $value ) {
282 $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $value ) . '"';
283 }
284 }
285
286 if ( isset($field['required']) && $field['required'] ) {
287 $custom_attributes[] = 'required="required"';
288 }
289
290 if ( isset($field['disabled']) && $field['disabled'] ) {
291 $custom_attributes[] = 'disabled="disabled"';
292 }
293
294 if(isset($field['tr_class'])){
295 $tr_class = $field['tr_class'];
296 }else{
297 $tr_class = '';
298 }
299
300 $custom_attributes_string = implode( ' ', $custom_attributes );
301
302 if ( 'title' === $field['type']) {
303 $html .= '<tr class="'.esc_attr($tr_class).'"><th class="section-title" colspan="2"><h3>' . $field['title'] . '</h3>';
304 $html .= '<p class="description">' . $field['description'] . '</p></th></tr>';
305 } else {
306 $html .= '<tr class="'.esc_attr($tr_class).'">';
307 $html .= '<th>' . $field['title'] . '</th>';
308 $html .= '<td>';
309
310 switch ( $field['type'] ) {
311
312 case 'text':
313 case 'password':
314 case 'number':
315 $html .= '<input id="' . esc_attr( $option_name ) . '" type="' . $field['type'] . '" name="' . esc_attr( $option_name ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" value="' . esc_attr($data) . '" '.$custom_attributes_string.'/>';
316 break;
317
318 case 'textarea':
319 $html .= '<textarea id="' . esc_attr( $option_name ) . '" rows="5" name="' . esc_attr( $option_name ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" '.$custom_attributes_string.'>' . esc_textarea($data) . '</textarea><br/>';
320 break;
321
322 case 'checkbox':
323 $checked = '';
324 if ( $option && 'yes' == $option ) {
325 $checked = 'checked="checked"';
326 }
327 $html .= '<label><input id="' . esc_attr( $option_name ) . '" type="' . $field['type'] . '" name="' . esc_attr( $option_name ) . '" ' . $checked . ' '.$custom_attributes_string.' value="yes"/>' . $field['label'] . '</label>';
328 break;
329
330 case 'checkbox_multi':
331 foreach ( $field['options'] as $k => $v ) {
332 $checked = false;
333 if ( in_array( $k, $data ) ) {
334 $checked = true;
335 }
336 $html .= '<p><label for="' . esc_attr( $field['id'] . '_' . $k ) . '"><input type="checkbox" ' . checked( $checked, true, false ) . ' name="' . esc_attr( $option_name ) . '[]" value="' . esc_attr( $k ) . '" id="' . esc_attr( $option_name . '_' . $k ) . '" '.$custom_attributes_string.'/> ' . $v . '</label></p>';
337 }
338 break;
339
340 case 'radio':
341 foreach ( $field['options'] as $k => $v ) {
342 $checked = false;
343 if ( $k == $data ) {
344 $checked = true;
345 }
346 $html .= '<p><label for="' . esc_attr( $field['id'] . '_' . $k ) . '"><input type="radio" ' . checked( $checked, true, false ) . ' name="' . esc_attr( $option_name ) . '" value="' . esc_attr( $k ) . '" id="' . esc_attr( $option_name . '_' . $k ) . '" '.$custom_attributes_string.'/> ' . $v . '</label></p>';
347 }
348 break;
349
350 case 'select':
351 $html .= '<select name="' . esc_attr( $option_name ) . '" id="' . esc_attr( $field['id'] ) . '" '.$custom_attributes_string.'>';
352 foreach ( $field['options'] as $k => $v ) {
353 $selected = false;
354 if ( $k == $data ) {
355 $selected = true;
356 }
357 $html .= '<option ' . selected( $selected, true, false ) . ' value="' . esc_attr( $k ) . '">' . $v . '</option>';
358 }
359 $html .= '</select> ';
360 break;
361
362 case 'select_multi':
363 $html .= '<select name="' . esc_attr( $option_name ) . '[]" id="' . esc_attr( $field['id'] ) . '" multiple="multiple" '.$custom_attributes_string.'>';
364 foreach ( $field['options'] as $k => $v ) {
365 $selected = false;
366 if ( in_array( $k, $data ) ) {
367 $selected = true;
368 }
369 $html .= '<option ' . selected( $selected, true, false ) . ' value="' . esc_attr( $k ) . '" />' . $v . '</label> ';
370 }
371 $html .= '</select> ';
372 break;
373
374 case 'file':
375 $uploader_title = isset($field['uploader_title']) ? $field['uploader_title'] : 'Upload media';
376 $uploader_button_text = isset($field['uploader_button_text']) ? $field['uploader_button_text'] : 'Select';
377 $file_types = isset($field['uploader_supported_file_types']) ? $field['uploader_supported_file_types'] : array();
378
379 $image_thumb = '';
380 $video_url = '';
381 $show_image = 'hide';
382 $show_video = 'hide';
383
384 $html .= '<span class="notifier-media-preview">';
385 if ( '' != $data ) {
386 $file_type = $field['uploader_supported_file_types'];
387 switch ($file_type) {
388 case 'image':
389 case 'image/jpeg':
390 case 'image/png':
391 case 'application/pdf':
392 $image_thumb = wp_get_attachment_thumb_url( $data );
393 $show_image = '';
394 $show_video = 'hide';
395 break;
396
397 case 'video/mp4':
398 $video_url = wp_get_attachment_url( $data );
399 $show_image = 'hide';
400 $show_video = '';
401 break;
402
403 default:
404 $show_image = 'hide';
405 $show_video = 'hide';
406 }
407 }
408 $html .= '<img id="' . esc_attr( $option_name ) . '_preview_image" class="notifier-media-preview-item '. esc_attr($show_image) .'" src="' . esc_url($image_thumb) . '" />';
409 $html .= '<video id="' . esc_attr( $option_name ) . '_preview_video" class="notifier-media-preview-item '. esc_attr($show_video) .'" width="300" height="169" controls muted><source src="' . esc_url($video_url) . '" type="video/mp4"></video><br/>';
410 $html .= '</span>';
411
412 $html .= '<input id="' . esc_attr( $option_name ) . '_button" type="button" data-uploader_title="' . esc_attr($uploader_title) . '" data-uploader_button_text="' . esc_attr($uploader_button_text) . '" data-uploader_supported_file_types="' . esc_attr($file_types) . '" class="notifier-media-upload-button button" value="' . 'Upload' . '" /> ';
413 $html .= '<input id="' . esc_attr( $option_name ) . '_delete" type="button" class="notifier-media-delete-button button" value="' . 'Remove' . '" />';
414 $html .= '<input id="' . esc_attr( $option_name ) . '" class="notifier-media-attachment-id" type="hidden" name="' . esc_attr( $option_name ) . '" value="' . esc_attr( $data ) . '"/><br/>';
415 break;
416
417 case 'color':
418 ?>
419 <div class="color-picker" style="position:relative;">
420 <input type="text" name="<?php echo esc_attr( $option_name ); ?>" class="color" value="<?php echo esc_attr( $data ); ?>" />
421 <div style="position:absolute;background:#FFF;z-index:99;border-radius:100%;" class="colorpicker"></div>
422 </div>
423 <?php
424 break;
425
426 }
427
428 if ( '' != $field['description'] ) {
429 $html .= '<p class="description">' . wp_kses_post($field['description']) . '</p>';
430 }
431 }
432
433 //phpcs:ignore
434 echo $html;
435 }
436
437 /**
438 * Show the setting fields
439 */
440 public static function show_settings_fields ($tab) {
441 $setting_fields = self::settings_fields($tab);
442 echo "<table class='notifier-fields-table'>";
443 foreach ($setting_fields as $field) {
444 self::display_field( $field );
445 }
446 echo '</table>';
447 }
448
449 /**
450 * Save the settings.
451 *
452 * TODO - check fields other than text and textarea
453 */
454 public static function save_settings_fields() {
455 if ( ! self::is_settings_page() ) {
456 return;
457 }
458
459 if ( ! isset( $_POST['save'] ) ) {
460 return;
461 }
462
463 //phpcs:ignore
464 if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], NOTIFIER_NAME . '-settings' ) ) {
465 return;
466 }
467
468 $tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'general';
469
470 $settings_fields = self::settings_fields($tab);
471 $data = $_POST;
472 $update_options = array();
473
474 // Loop options and get values to save.
475 foreach ( $settings_fields as $option ) {
476 if ( ! isset( $option['id'] ) || ! isset( $option['type'] ) ) {
477 continue;
478 }
479
480 if ( isset( $option['disabled'] ) && $option['disabled'] ) {
481 continue;
482 }
483
484 $option_name = NOTIFIER_PREFIX . $option['id'];
485 $setting_name = '';
486 $raw_value = isset( $data[ $option_name ] ) ? wp_unslash( $data[ $option_name ] ) : null;
487
488 // Format the value based on option type.
489 switch ( $option['type'] ) {
490 case 'checkbox':
491 $value = '1' === $raw_value || 'yes' === $raw_value ? 'yes' : 'no';
492 break;
493 case 'textarea':
494 $value = wp_kses_post( trim( $raw_value ) );
495 break;
496 case 'select':
497 $allowed_values = empty( $option['options'] ) ? array() : array_map( 'strval', array_keys( $option['options'] ) );
498 if ( empty( $option['default'] ) && empty( $allowed_values ) ) {
499 $value = null;
500 break;
501 }
502 $default = ( empty( $option['default'] ) ? $allowed_values[0] : $option['default'] );
503 $value = in_array( $raw_value, $allowed_values, true ) ? $raw_value : $default;
504 break;
505 default:
506 $value = sanitize_text_field( $raw_value );
507 break;
508 }
509
510 // Check if option is an array and handle that differently to single values.
511 if ( $option_name && $setting_name ) {
512 if ( ! isset( $update_options[ $option_name ] ) ) {
513 $update_options[ $option_name ] = get_option( $option_name, array() );
514 }
515 if ( ! is_array( $update_options[ $option_name ] ) ) {
516 $update_options[ $option_name ] = array();
517 }
518 $update_options[ $option_name ][ $setting_name ] = $value;
519 } else {
520 $update_options[ $option_name ] = $value;
521 }
522 }
523
524 // Save all options in our array.
525 foreach ( $update_options as $name => $value ) {
526 if('notifier_api_key' == $name){
527 $current_api_key = get_option($name);
528 if($current_api_key == $value){
529 continue;
530 }
531
532 update_option( NOTIFIER_PREFIX . 'api_key', $value);
533 delete_option( NOTIFIER_PREFIX . 'enabled_triggers' );
534 delete_option( NOTIFIER_PREFIX . 'api_activated' );
535
536 $params = array(
537 'site_url' => site_url(),
538 'source' => 'wp'
539 );
540
541 $response = Notifier::send_api_request( 'verify_api', $params, 'POST' );
542
543 if($response->error){
544 $notices[] = array(
545 'message' => 'There was an error validating API key. Error: ' . $response->message,
546 'type' => 'error'
547 );
548 }
549 else{
550 update_option('notifier_api_activated', 'yes');
551 $notices[] = array(
552 'message' => 'API key validated and saved successfully. Your triggers have been reset. Please enable and save your triggers again from the <a href="'.admin_url('admin.php?page=notifier').'">WANotifier</a> page.',
553 'type' => 'success'
554 );
555 }
556 }
557 elseif('notifier_ctc_whatsapp_number' == $name && !notifier_validate_phone_number($value)){
558 $notices[] = array(
559 'message' => 'Please enter a valid WhatsApp phone number with country code.',
560 'type' => 'error'
561 );
562 }
563 else{
564 update_option( $name, $value, 'yes' );
565 }
566 }
567
568 if('advanced' == $tab){
569 delete_transient( '_notifier_custom_meta_keys' );
570 }
571
572 if(empty($notices)){
573 $notices[] = array(
574 'message' => 'Settings updated successfully.',
575 'type' => 'success'
576 );
577 }
578
579 new Notifier_Admin_Notices($notices);
580 }
581
582 /**
583 * Disconnect WANotifier.com connection
584 */
585 public static function disconnect_notifier(){
586 if(isset($_GET['notifier_disconnect']) && '1' == $_GET['notifier_disconnect']){
587 delete_option( NOTIFIER_PREFIX . 'api_key' );
588 delete_option( NOTIFIER_PREFIX . 'enabled_triggers' );
589 delete_option( NOTIFIER_PREFIX . 'api_activated' );
590 $notices[] = array(
591 'message' => 'Disconnected successfully. To re-connect with WANotifier.com, enter API key below and click on <b>Save and validate</b>.',
592 'type' => 'success'
593 );
594 new Notifier_Admin_Notices($notices, true);
595 wp_redirect(admin_url('admin.php?page=notifier'));
596 }
597 }
598
599 /**
600 * Get button styles
601 */
602 public static function get_button_styles(){
603 return array(
604 'default' => 'Select button style',
605 'btn-style-1' => 'Style 1' ,
606 'btn-style-2' => 'Style 2',
607 'btn-style-3' => 'Style 3',
608 'btn-style-4' => 'Style 4',
609 'btn-custom-image' => 'Add your own image'
610 );
611 }
612
613 /**
614 * Show Chat Button Preview
615 */
616 public static function preview_btn_style(){
617 $btn_style = isset($_POST['btn_style']) ? sanitize_text_field($_POST['btn_style']) : '';
618
619 $button_styles = self::get_button_styles();
620 $button_style_keys = array_keys($button_styles);
621
622 if(! in_array($btn_style, $button_style_keys)){
623 wp_send_json( array(
624 'preview' => 'Invalid request'
625 ) );
626 }
627
628 ob_start();
629 include_once NOTIFIER_PATH.'templates/buttons/'.$btn_style.'.php';
630 $btn_output = ob_get_clean();
631
632 wp_send_json( array(
633 'preview' => $btn_output
634 ) );
635 }
636 }
637