PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / trunk
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent vtrunk
3.5.3 3.5.2 3.5.1 3.4.9 3.5.0 3.4.8 3.4.7 trunk 2.3.1 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6
supportcandy / includes / admin / custom-fields / class-wpsc-cf-settings.php

class-wpsc-cf-settings.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent trunk, at includes/admin/custom-fields/class-wpsc-cf-settings.php

1,031 lines 30.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly!
4 }
5
6 if ( ! class_exists( 'WPSC_CF_Settings' ) ) :
7
8 final class WPSC_CF_Settings {
9
10 /**
11 * Set if current screen is settings page
12 *
13 * @var boolean
14 */
15 public static $is_current_page;
16
17 /**
18 * Sections for this view
19 *
20 * @var array
21 */
22 private static $sections = array();
23
24 /**
25 * Current section to load
26 *
27 * @var string
28 */
29 public static $current_section;
30
31 /**
32 * Custom field category (e.g. ticket, agentonly, customer, etc.)
33 *
34 * @var array
35 */
36 public static $fields = array();
37
38 /**
39 * Allowed modules for custom field categories
40 *
41 * @var array
42 */
43 public static $allowed_modules = array();
44
45 /**
46 * Initialize this class
47 */
48 public static function init() {
49
50 // Load sections for this screen.
51 add_action( 'admin_init', array( __CLASS__, 'load_sections' ), 1 );
52
53 // Humbargar modal.
54 add_action( 'admin_footer', array( __CLASS__, 'humbargar_menu' ) );
55
56 // Footer scripts.
57 add_action( 'admin_footer', array( __CLASS__, 'footer_scripts' ) );
58
59 // Add current section to admin localization data.
60 add_filter( 'wpsc_admin_localizations', array( __CLASS__, 'localizations' ) );
61
62 // Register ready function.
63 add_action( 'wpsc_js_ready', array( __CLASS__, 'register_js_ready_function' ) );
64
65 // Register fields.
66 add_action( 'init', array( __CLASS__, 'register_fields' ), 10 );
67
68 // Register allowed modules.
69 add_action( 'init', array( __CLASS__, 'register_allowed_modules' ), 11 );
70
71 // Add new custom field.
72 add_action( 'wp_ajax_wpsc_get_add_new_custom_field', array( __CLASS__, 'get_add_new_custom_field' ) );
73 add_action( 'wp_ajax_wpsc_get_add_new_custom_field_properties', array( __CLASS__, 'get_add_new_custom_field_properties' ) );
74 add_action( 'wp_ajax_wpsc_set_add_new_custom_field', array( __CLASS__, 'set_add_new_custom_field' ) );
75
76 // Edit custom field.
77 add_action( 'wp_ajax_wpsc_get_edit_custom_field', array( __CLASS__, 'get_edit_custom_field' ) );
78 add_action( 'wp_ajax_wpsc_set_edit_custom_field', array( __CLASS__, 'set_edit_custom_field' ) );
79
80 // Delete.
81 add_action( 'wp_ajax_wpsc_delete_custom_field', array( __CLASS__, 'delete_custom_field' ) );
82
83 // Sorting.
84 add_action( 'wp_ajax_wpsc_set_custom_field_load_order', array( __CLASS__, 'set_custom_field_load_order' ) );
85 }
86
87 /**
88 * Load section (nav elements) for this screen
89 *
90 * @return void
91 */
92 public static function load_sections() {
93
94 self::$is_current_page = isset( $_REQUEST['page'] ) && wp_unslash( $_REQUEST['page'] ) === 'wpsc-ticket-form' ? true : false; //phpcs:ignore
95
96 if ( ! self::$is_current_page ) {
97 return;
98 }
99
100 self::$sections = apply_filters(
101 'wpsc_ticket_form_page_sections',
102 array(
103 'ticket-form-fields' => array(
104 'slug' => 'ticket_form_fields',
105 'icon' => 'contact-form',
106 'label' => esc_attr__( 'Ticket Form Fields', 'supportcandy' ),
107 'callback' => 'wpsc_get_tff',
108 ),
109 'ticket-fields' => array(
110 'slug' => 'ticket_fields',
111 'icon' => 'ticket-alt',
112 'label' => esc_attr__( 'Ticket Fields', 'supportcandy' ),
113 'callback' => 'wpsc_get_ticket_fields',
114 ),
115 'customer-fields' => array(
116 'slug' => 'customer_fields',
117 'icon' => 'user-tie',
118 'label' => esc_attr__( 'Customer Fields', 'supportcandy' ),
119 'callback' => 'wpsc_get_customer_fields',
120 ),
121 'agent-only-fields' => array(
122 'slug' => 'agent_only_fields',
123 'icon' => 'headset',
124 'label' => esc_attr__( 'Agent Only Fields', 'supportcandy' ),
125 'callback' => 'wpsc_get_agent_only_fields',
126 ),
127 )
128 );
129
130 self::$current_section = isset( $_REQUEST['section'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['section'] ) ) : 'ticket-form-fields'; //phpcs:ignore
131 }
132
133 /**
134 * Add localizations to local JS
135 *
136 * @param array $localizations - localizations.
137 * @return array
138 */
139 public static function localizations( $localizations ) {
140
141 if ( ! self::$is_current_page ) {
142 return $localizations;
143 }
144
145 // Humbargar Titles.
146 $localizations['humbargar_titles'] = self::get_humbargar_titles();
147
148 // Current section.
149 $localizations['current_section'] = self::$current_section;
150
151 return $localizations;
152 }
153
154 /**
155 * UI foundation for this screen
156 *
157 * @return void
158 */
159 public static function layout() {
160 ?>
161
162 <div class="wrap">
163 <hr class="wp-header-end">
164 <div id="wpsc-container" style="display:none;">
165 <div class="wpsc-header wpsc-setting-header-xs wpsc-visible-xs">
166 <div class="wpsc-humbargar-title">
167 <?php WPSC_Icons::get( self::$sections[ self::$current_section ]['icon'] ); ?>
168 <label><?php echo esc_attr( self::$sections[ self::$current_section ]['label'] ); ?></label>
169 </div>
170 <div class="wpsc-humbargar" onclick="wpsc_toggle_humbargar();">
171 <?php WPSC_Icons::get( 'bars' ); ?>
172 </div>
173 </div>
174 <div class="wpsc-settings-page">
175 <div class="wpsc-setting-section-container wpsc-hidden-xs">
176 <h2><?php esc_attr_e( 'Custom Fields', 'supportcandy' ); ?></h2>
177 <?php
178 foreach ( self::$sections as $key => $section ) {
179
180 $active = self::$current_section === $key ? 'active' : '';
181 ?>
182 <div
183 class="wpsc-setting-nav <?php echo esc_attr( $key ) . ' ' . esc_attr( $active ); ?>"
184 onclick="<?php echo esc_attr( $section['callback'] ) . '();'; ?>">
185 <?php WPSC_Icons::get( $section['icon'] ); ?>
186 <label><?php echo esc_attr( $section['label'] ); ?></label>
187 </div>
188 <?php
189 }
190 ?>
191 </div>
192 <div class="wpsc-setting-body"></div>
193 </div>
194 </div>
195 </div>
196 <?php
197
198 self::print_snippets();
199 }
200
201 /**
202 * Print humbargar menu in footer
203 *
204 * @return void
205 */
206 public static function humbargar_menu() {
207
208 if ( ! self::$is_current_page ) {
209 return;
210 }
211 ?>
212
213 <div class="wpsc-humbargar-overlay" onclick="wpsc_toggle_humbargar();" style="display:none"></div>
214 <div class="wpsc-humbargar-menu" style="display:none">
215 <div class="box-inner">
216 <div class="wpsc-humbargar-close" onclick="wpsc_toggle_humbargar();">
217 <?php WPSC_Icons::get( 'times' ); ?>
218 </div>
219 <?php
220 foreach ( self::$sections as $key => $section ) :
221
222 $active = self::$current_section === $key ? 'active' : '';
223 ?>
224 <div
225 class="wpsc-humbargar-menu-item <?php echo esc_attr( $key ) . ' ' . esc_attr( $active ); ?>"
226 onclick="<?php echo esc_attr( $section['callback'] ) . '(true);'; ?>">
227 <?php WPSC_Icons::get( $section['icon'] ); ?>
228 <label><?php echo esc_attr( $section['label'] ); ?></label>
229 </div>
230 <?php
231 endforeach;
232 ?>
233 </div>
234 </div>
235 <?php
236 }
237
238 /**
239 * Humbargar mobile titles to be used in localizations
240 *
241 * @return array
242 */
243 private static function get_humbargar_titles() {
244
245 $titles = array();
246 foreach ( self::$sections as $section ) {
247
248 ob_start();
249 WPSC_Icons::get( $section['icon'] );
250 echo '<label>' . esc_attr( $section['label'] ) . '</label>';
251 $titles[ $section['slug'] ] = ob_get_clean();
252 }
253 return $titles;
254 }
255
256 /**
257 * Register JS functions to call on document ready
258 *
259 * @return void
260 */
261 public static function register_js_ready_function() {
262
263 if ( ! self::$is_current_page ) {
264 return;
265 }
266 echo esc_attr( self::$sections[ self::$current_section ]['callback'] ) . '();' . PHP_EOL;
267 }
268
269 /**
270 * Register fields (ticket, agentonly, customer, etc.)
271 *
272 * @return void
273 */
274 public static function register_fields() {
275
276 self::$fields = apply_filters( 'wpsc_custom_field_categories', array() );
277 }
278
279 /**
280 * Register allowed modules
281 *
282 * @return void
283 */
284 public static function register_allowed_modules() {
285
286 self::$allowed_modules = apply_filters(
287 'wpsc_cf_allowed_modules',
288 array(
289
290 'ticket-form' => array( 'ticket', 'customer' ),
291 'ticket-list' => array( 'ticket', 'customer', 'agentonly' ),
292 'ticket-filter' => array( 'ticket', 'customer', 'agentonly' ),
293 'ticket-macro' => array( 'ticket', 'customer', 'agentonly' ),
294 )
295 );
296 }
297
298 /**
299 * Add new custom field form
300 *
301 * String $field - custom field (ticket, agentonly, customer, etc.).
302 *
303 * @return void
304 */
305 public static function get_add_new_custom_field() {
306
307 if ( check_ajax_referer( 'wpsc_get_add_new_custom_field', '_ajax_nonce', false ) !== 1 ) {
308 wp_send_json_error( 'Unauthorized request!', 401 );
309 }
310
311 if ( ! WPSC_Functions::is_site_admin() ) {
312 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
313 }
314
315 $field = isset( $_POST['field'] ) ? sanitize_text_field( wp_unslash( $_POST['field'] ) ) : '';
316 if ( ! $field ) {
317 wp_send_json_error( 'Incorrect request!', 400 );
318 }
319 ?>
320
321 <form action="#" onsubmit="return false;" class="frm-add-new-custom-field">
322
323 <div data-type="textfield" data-required="true" class="wpsc-input-group label">
324 <div class="label-container">
325 <label for="">
326 <?php esc_attr_e( 'Label', 'supportcandy' ); ?>
327 <span class="required-char">*</span>
328 </label>
329 </div>
330 <input name="label" type="text" autocomplete="off"/>
331 </div>
332
333 <div data-type="" data-required="true" class="wpsc-input-group load-after">
334 <div class="label-container">
335 <label for="">
336 <?php esc_attr_e( 'Load after', 'supportcandy' ); ?>
337 </label>
338 </div>
339 <select name="load-after" class="load-after">
340 <option value="__TOP__">-- <?php esc_attr_e( 'TOP', 'supportcandy' ); ?> --</option>
341 <?php
342 foreach ( WPSC_Custom_Field::$custom_fields as $cf ) {
343 if ( $cf->field != $field ) {
344 continue;
345 }
346 ?>
347 <option value="<?php echo esc_attr( $cf->slug ); ?>"><?php echo esc_attr( $cf->name ); ?></option>
348 <?php
349 }
350 ?>
351 <option selected value="__END__">-- <?php esc_attr_e( 'END', 'supportcandy' ); ?> --</option>
352 </select>
353 <script>jQuery('select.load-after').selectWoo();</script>
354 </div>
355
356 <div data-type="single-select" data-required="true" class="wpsc-input-group field-type">
357 <div class="label-container">
358 <label for="">
359 <?php esc_attr_e( 'Select field type', 'supportcandy' ); ?>
360 <span class="required-char">*</span>
361 </label>
362 </div>
363 <select id="wpsc-select-ticket-field" name="type">
364 <option value=""></option>
365 <?php
366 $cf_types = apply_filters( 'wpsc_add_new_custom_field_cf_types', WPSC_Custom_Field::$cf_types, $field );
367 foreach ( $cf_types as $slug => $type ) :
368 ?>
369 <option value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_attr( $type['label'] ); ?></option>
370 <?php
371 endforeach;
372 ?>
373 </select>
374 <script>
375 jQuery('#wpsc-select-ticket-field').selectWoo({ allowClear: true, placeholder: "" });
376 jQuery('#wpsc-select-ticket-field').change(function(){
377 // validate custom field type.
378 jQuery('div.cft-properties').remove();
379 var curEl = jQuery(this);
380 var cft = curEl.val();
381 if (!cft) return;
382 // get custome field properties.
383 jQuery(this).prop('disabled', true);
384 var form = jQuery('.frm-add-new-custom-field');
385 form.append(supportcandy.loader_html);
386 var dataform = new FormData(form[0]);
387 var data = {
388 action: 'wpsc_get_add_new_custom_field_properties',
389 field: dataform.get('field'),
390 cft,
391 _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_add_new_custom_field_properties' ) ); ?>'
392 };
393 jQuery.post(supportcandy.ajax_url, data, function (response) {
394 form.children().last().remove();
395 form.append(response);
396 curEl.prop('disabled', false);
397 });
398 });
399 </script>
400 </div>
401
402 <input type="hidden" name="field" value="<?php echo esc_attr( $field ); ?>">
403 <input type="hidden" name="action" value="wpsc_set_add_new_custom_field">
404 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_add_new_custom_field' ) ); ?>">
405
406 </form>
407
408 <div class="setting-footer-actions">
409 <button
410 class="wpsc-button normal primary margin-right"
411 onclick="wpsc_set_add_new_custom_field(this);">
412 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
413 <button
414 class="wpsc-button normal secondary"
415 onclick="jQuery('.wpsc-setting-nav.active').trigger('click');">
416 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
417 </div>
418 <?php
419
420 wp_die();
421 }
422
423 /**
424 * Add new custom field properties like extra-info, char-limit, etc.
425 *
426 * @return void
427 */
428 public static function get_add_new_custom_field_properties() {
429
430 if ( check_ajax_referer( 'wpsc_get_add_new_custom_field_properties', '_ajax_nonce', false ) != 1 ) {
431 wp_send_json_error( 'Unauthorized request!', 401 );
432 }
433
434 if ( ! WPSC_Functions::is_site_admin() ) {
435 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
436 }
437
438 $field = isset( $_POST['field'] ) ? sanitize_text_field( wp_unslash( $_POST['field'] ) ) : '';
439 if ( ! $field ) {
440 wp_send_json_error( 'Incorrect request!', 400 );
441 }
442
443 $cft = isset( $_POST['cft'] ) ? sanitize_text_field( wp_unslash( $_POST['cft'] ) ) : '';
444 if ( ! $cft ) {
445 wp_send_json_error( 'Incorrect request!', 400 );
446 }
447
448 ?>
449 <div class="cft-properties">
450 <?php
451 WPSC_Custom_Field::$cf_types[ $cft ]['class']::get_add_new_custom_field_properties( self::$fields[ $field ] );
452 ?>
453 </div>
454 <?php
455
456 wp_die();
457 }
458
459 /**
460 * Set add new custom field
461 *
462 * @return void
463 */
464 public static function set_add_new_custom_field() {
465
466 if ( check_ajax_referer( 'wpsc_set_add_new_custom_field', '_ajax_nonce', false ) != 1 ) {
467 wp_send_json_error( 'Unauthorized request!', 401 );
468 }
469
470 if ( ! WPSC_Functions::is_site_admin() ) {
471 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
472 }
473
474 $field = isset( $_POST['field'] ) ? sanitize_text_field( wp_unslash( $_POST['field'] ) ) : '';
475 if ( ! $field || ! in_array( $field, array_keys( self::$fields ) ) ) {
476 wp_send_json_error( 'Incorrect request!', 400 );
477 }
478
479 $cf = new WPSC_Custom_Field();
480 $cf->field = $field;
481
482 $cf->name = isset( $_POST['label'] ) ? sanitize_text_field( wp_unslash( $_POST['label'] ) ) : '';
483 if ( ! $cf->name ) {
484 wp_send_json_error( 'Incorrect request!', 400 );
485 }
486
487 $cf->type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
488 if ( ! $cf->type ) {
489 wp_send_json_error( 'Incorrect request!', 400 );
490 }
491
492 $cf->type::set_cf_properties( $cf, self::$fields[ $field ] );
493
494 // set load after.
495 $load_after = isset( $_POST['load-after'] ) ? sanitize_text_field( wp_unslash( $_POST['load-after'] ) ) : '__END__';
496 if ( $load_after != '__END__' ) {
497
498 $count = 1;
499
500 if ( $load_after == '__TOP__' ) {
501 $cf->load_order = $count++;
502 $cf->save();
503 }
504
505 foreach ( WPSC_Custom_Field::$custom_fields as $cff ) {
506
507 if ( $cff->field != $cf->field || $cff->slug == $cf->slug ) {
508 continue;
509 }
510
511 $cff->load_order = $count++;
512 $cff->save();
513
514 if ( $cff->slug == $load_after ) {
515 $cf->load_order = $count++;
516 $cf->save();
517 }
518 }
519 }
520
521 wp_die();
522 }
523
524 /**
525 * Get edit custom field screen
526 *
527 * @return void
528 */
529 public static function get_edit_custom_field() {
530
531 global $wpdb;
532
533 if ( check_ajax_referer( 'wpsc_get_edit_custom_field', '_ajax_nonce', false ) != 1 ) {
534 wp_send_json_error( 'Unauthorized request!', 401 );
535 }
536
537 if ( ! WPSC_Functions::is_site_admin() ) {
538 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
539 }
540
541 $id = isset( $_POST['cf_id'] ) ? intval( $_POST['cf_id'] ) : 0;
542 if ( ! $id ) {
543 wp_send_json_error( 'Incorrect request!', 400 );
544 }
545
546 $cf = new WPSC_Custom_Field( $id );
547 if ( ! $cf->id ) {
548 wp_send_json_error( 'Incorrect request!', 400 );
549 }
550 ?>
551
552 <form action="#" onsubmit="return false;" class="frm-edit-custom-field">
553
554 <div data-type="textfield" data-required="true" class="wpsc-input-group label">
555 <div class="label-container">
556 <label for="">
557 <?php esc_attr_e( 'Label', 'supportcandy' ); ?>
558 <span class="required-char">*</span>
559 </label>
560 </div>
561 <input name="label" type="text" value="<?php echo esc_attr( $cf->name ); ?>" autocomplete="off"/>
562 </div>
563
564 <div data-type="" data-required="true" class="wpsc-input-group load-after">
565 <div class="label-container">
566 <label for="">
567 <?php esc_attr_e( 'Load after', 'supportcandy' ); ?>
568 </label>
569 </div>
570 <select name="load-after" class="load-after">
571 <option value="__TOP__">-- <?php esc_attr_e( 'TOP', 'supportcandy' ); ?> --</option>
572 <?php
573 $load_after = $wpdb->get_var( "SELECT slug FROM {$wpdb->prefix}psmsc_custom_fields WHERE field='{$cf->field}' AND load_order < {$cf->load_order} ORDER BY load_order DESC LIMIT 1" );
574 foreach ( WPSC_Custom_Field::$custom_fields as $cff ) {
575 if ( $cff->field != $cf->field || $cff == $cf ) {
576 continue;
577 }
578 ?>
579 <option <?php selected( $load_after, $cff->slug ); ?> value="<?php echo esc_attr( $cff->slug ); ?>"><?php echo esc_attr( $cff->name ); ?></option>
580 <?php
581 }
582 ?>
583 <option value="__END__">-- <?php esc_attr_e( 'END', 'supportcandy' ); ?> --</option>
584 </select>
585 <script>jQuery('select.load-after').selectWoo();</script>
586 </div>
587 <?php
588
589 if ( ! $cf->type::$is_default ) :
590 ?>
591 <div data-type="textfield" data-required="true" class="wpsc-input-group label">
592 <div class="label-container">
593 <label for="">
594 <?php esc_attr_e( 'Field Type', 'supportcandy' ); ?>
595 <span class="required-char">*</span>
596 </label>
597 </div>
598 <input disabled type="text" value="<?php echo esc_attr( WPSC_Custom_Field::$cf_types[ $cf->type::$slug ]['label'] ); ?>" autocomplete="off"/>
599 </div>
600 <?php
601 endif
602 ?>
603
604 <?php $cf->type::get_edit_custom_field_properties( $cf, self::$fields[ $cf->field ] ); ?>
605
606 <input type="hidden" name="action" value="wpsc_set_edit_custom_field">
607 <input type="hidden" name="cf_id" value="<?php echo esc_attr( $cf->id ); ?>">
608 <input type="hidden" name="type" value="<?php echo esc_attr( $cf->type::$slug ); ?>">
609 <input type="hidden" name="field" value="<?php echo esc_attr( $cf->field ); ?>">
610 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_edit_custom_field' ) ); ?>">
611
612 </form>
613
614 <div class="setting-footer-actions">
615 <button
616 class="wpsc-button normal primary margin-right"
617 onclick="wpsc_set_edit_custom_field(this);">
618 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
619 <button
620 class="wpsc-button normal secondary"
621 onclick="jQuery('.wpsc-setting-nav.active').trigger('click');">
622 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
623 </div>
624 <?php
625
626 wp_die();
627 }
628
629 /**
630 * Set edit custom field
631 *
632 * @return void
633 */
634 public static function set_edit_custom_field() {
635
636 global $wpdb;
637
638 if ( check_ajax_referer( 'wpsc_set_edit_custom_field', '_ajax_nonce', false ) != 1 ) {
639 wp_send_json_error( 'Unauthorized request!', 401 );
640 }
641
642 if ( ! WPSC_Functions::is_site_admin() ) {
643 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
644 }
645
646 $id = isset( $_POST['cf_id'] ) ? intval( $_POST['cf_id'] ) : 0;
647 if ( ! $id ) {
648 wp_send_json_error( 'Incorrect request!', 400 );
649 }
650
651 $cf = new WPSC_Custom_Field( $id );
652 if ( ! $cf->id ) {
653 wp_send_json_error( 'Incorrect request!', 400 );
654 }
655
656 $cf->name = isset( $_POST['label'] ) ? sanitize_text_field( wp_unslash( $_POST['label'] ) ) : '';
657 if ( ! $cf->name ) {
658 wp_send_json_error( 'Incorrect request!', 400 );
659 }
660
661 $cf->type::set_cf_properties( $cf, self::$fields[ $cf->field ] );
662
663 // set load after.
664 $load_after = isset( $_POST['load-after'] ) ? sanitize_text_field( wp_unslash( $_POST['load-after'] ) ) : '__END__';
665 if ( $load_after != '__END__' ) {
666
667 $count = 1;
668
669 if ( $load_after == '__TOP__' ) {
670 $cf->load_order = $count++;
671 $cf->save();
672 }
673
674 foreach ( WPSC_Custom_Field::$custom_fields as $cff ) {
675
676 if ( $cff->field != $cf->field || $cff->slug == $cf->slug ) {
677 continue;
678 }
679
680 $cff->load_order = $count++;
681 $cff->save();
682
683 if ( $cff->slug == $load_after ) {
684 $cf->load_order = $count++;
685 $cf->save();
686 }
687 }
688 } else {
689
690 $max_load_order = (int) $wpdb->get_var( "SELECT max(load_order) FROM {$wpdb->prefix}psmsc_custom_fields WHERE field='{$cf->field}'" );
691 $cf->load_order = ++$max_load_order;
692 $cf->save();
693 }
694
695 wp_die();
696 }
697
698 /**
699 * Delete custom feild
700 */
701 public static function delete_custom_field() {
702
703 if ( check_ajax_referer( 'wpsc_delete_custom_field', '_ajax_nonce', false ) != 1 ) {
704 wp_send_json_error( 'Unauthorized request!', 401 );
705 }
706
707 if ( ! WPSC_Functions::is_site_admin() ) {
708 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
709 }
710
711 $id = isset( $_POST['cf_id'] ) ? intval( $_POST['cf_id'] ) : 0;
712 if ( ! $id ) {
713 wp_send_json_error( 'Incorrect request!', 400 );
714 }
715
716 $cf = new WPSC_Custom_Field( $id );
717 if ( ! $cf->id ) {
718 wp_send_json_error( 'Incorrect request!', 400 );
719 }
720
721 do_action( 'wpsc_delete_custom_field', $cf );
722
723 WPSC_Custom_Field::destroy( $id );
724 wp_die();
725 }
726
727 /**
728 * Set load order for custom fields
729 *
730 * @return void
731 */
732 public static function set_custom_field_load_order() {
733
734 if ( check_ajax_referer( 'wpsc_set_custom_field_load_order', '_ajax_nonce', false ) != 1 ) {
735 wp_send_json_error( 'Unauthorized request!', 400 );
736 }
737
738 if ( ! WPSC_Functions::is_site_admin() ) {
739 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
740 }
741
742 $ids = isset( $_POST['ids'] ) ? array_map( 'intval', wp_unslash( $_POST['ids'] ) ) : array();
743 if ( ! $ids ) {
744 wp_send_json_error( 'Bad Request', 400 );
745 }
746
747 $count = 1;
748 foreach ( $ids as $id ) {
749
750 $cf = new WPSC_Custom_Field( $id );
751 if ( ! $cf->id ) {
752 continue;
753 }
754
755 $cf->load_order = $count++;
756 $cf->save();
757 }
758
759 wp_send_json( array( 'success' => true ), 200 );
760 }
761
762 /**
763 * Static snippets for this page
764 *
765 * @return void
766 */
767 public static function print_snippets() {
768 ?>
769
770 <div class="wpsc-snippets">
771 <div class="wpsc-add-option">
772 <div class="wpsc-option-item">
773 <div class="content">
774 <div class="wpsc-add-option-container">
775 <input type="text" value="" autocomplete="off"/>
776 <button onclick="wpsc_add_new_option(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_add_new_option' ) ); ?>');">
777 <?php WPSC_Icons::get( 'check' ); ?>
778 </button>
779 </div>
780 <div class="wpsc-edit-option-container" style="display: none;">
781 <input class="edit-option-text" type="text" value="" autocomplete="off" />
782 <button onclick="wpsc_set_edit_option(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_set_edit_option' ) ); ?>');">
783 <?php WPSC_Icons::get( 'check' ); ?>
784 </button>
785 <button class="cancel" onclick="wpsc_edit_option_cancel(this);">
786 <?php WPSC_Icons::get( 'times' ); ?>
787 </button>
788 </div>
789 <div class="wpsc-option-listing-container" style="display: none;">
790 <span class="sort wpsc-sort-handle"><?php WPSC_Icons::get( 'sort' ); ?></span>
791 <div class="text"></div>
792 <span class="edit" onclick="wpsc_edit_option(this);"><?php WPSC_Icons::get( 'edit' ); ?></span>
793 </div>
794 </div>
795 <div class="remove-container">
796 <span onclick="wpsc_remove_option_item(this)"><?php WPSC_Icons::get( 'times-circle' ); ?></span>
797 </div>
798 </div>
799 </div>
800 </div>
801 <?php
802 }
803
804 /**
805 * Footer scripts (dynamic)
806 *
807 * @return void
808 */
809 public static function footer_scripts() {
810 ?>
811
812 <script>
813
814 /**
815 * Set add new custom field
816 */
817 function wpsc_set_add_new_custom_field(el) {
818
819 var form = jQuery('.frm-add-new-custom-field');
820 var dataform = new FormData(form[0]);
821 var field = dataform.get('field');
822 var fieldType = dataform.get('type');
823
824 // general validations
825 if (!wpsc_cf_settings_general_validations(form)) return;
826
827 // check whether char-limit honored by default value
828 if (
829 (field == 'ticket' || field == 'agentonly') &&
830 (fieldType == 'cf_textfield' || fieldType == 'cf_textarea' || fieldType == 'cf_number' ||
831 fieldType == 'cf_email' || fieldType == 'cf_url')
832 ) {
833 var defaultVal = dataform.get('default_value').trim();
834 var char_limit = dataform.get('char_limit');
835 if ( defaultVal && char_limit && defaultVal.length > char_limit) {
836 alert('<?php esc_attr_e( 'Default value exceeds character limit!', 'supportcandy' ); ?>');
837 return;
838 }
839 }
840
841 var dateRange = dataform.get('date_range');
842 if(
843 (field == 'ticket' || field == 'agentonly') &&
844 (fieldType == 'cf_date' || fieldType == 'cf_datetime') && dateRange == 'range'){
845 var defaultVal = dataform.get('default_value').trim();
846 fromDate = new Date(jQuery('#from-date-range').val());
847 toDate = new Date(jQuery('#to-date-range').val());
848 defaultDate = new Date(defaultVal);
849 if(!(Date.parse(defaultDate) <= Date.parse(toDate) && Date.parse(defaultDate) >= Date.parse(fromDate)) ){
850 alert('<?php esc_attr_e( 'Default value is not in the range!', 'supportcandy' ); ?>');
851 return;
852 }
853 }
854
855 if (field == 'ticket' && fieldType == 'cf_html') {
856 var defaultVal = dataform.get('html_text').trim();
857 if(!defaultVal){
858 alert(supportcandy.translations.req_fields_missing);
859 return;
860 }
861 }
862
863 <?php do_action( 'wpsc_js_set_add_new_custom_field' ); ?>
864
865 jQuery(el).text(supportcandy.translations.please_wait);
866 jQuery.ajax({
867 url: supportcandy.ajax_url,
868 type: 'POST',
869 data: dataform,
870 processData: false,
871 contentType: false
872 }).done(function (res) {
873 jQuery('.wpsc-setting-nav.active').trigger('click');
874 });
875 }
876
877 /**
878 * Set edit custom field
879 */
880 function wpsc_set_edit_custom_field(el) {
881
882 var form = jQuery('.frm-edit-custom-field');
883 var dataform = new FormData(form[0]);
884 var field = dataform.get('field');
885 var fieldType = dataform.get('type');
886
887 if ( ( fieldType == 'df_status' || fieldType == 'df_priority' || fieldType == 'df_category' ) && dataform.get('default_value') == null ) {
888 alert( supportcandy.translations.req_fields_missing );
889 return;
890 }
891
892 // general validations
893 if (!wpsc_cf_settings_general_validations(form)) return;
894
895 // check whether char-limit honored by default value
896 if (
897 (field == 'ticket' || field == 'agentonly') &&
898 (fieldType == 'cf_textfield' || fieldType == 'cf_textarea' || fieldType == 'cf_number' ||
899 fieldType == 'cf_email' || fieldType == 'cf_url')
900 ) {
901 var defaultVal = dataform.get('default_value').trim();
902 var char_limit = parseInt(dataform.get('char_limit'));
903 if ( defaultVal && char_limit && defaultVal.length > char_limit) {
904 alert('<?php esc_attr_e( 'Default value exceeds character limit!', 'supportcandy' ); ?>');
905 return;
906 }
907 }
908
909 var dateRange = dataform.get('date_range');
910 if(
911 (field == 'ticket' || field == 'agentonly') &&
912 (fieldType == 'cf_date' || fieldType == 'cf_datetime') && dateRange == 'range'){
913 var defaultVal = dataform.get('default_value').trim();
914 fromDate = new Date(jQuery('#from-date-range').val());
915 toDate = new Date(jQuery('#to-date-range').val());
916 defaultDate = new Date(defaultVal);
917 if(!(Date.parse(defaultDate) <= Date.parse(toDate) && Date.parse(defaultDate) >= Date.parse(fromDate)) ){
918 alert('<?php esc_attr_e( 'Default value is not in the range!', 'supportcandy' ); ?>');
919 return;
920 }
921 }
922
923 if (field == 'ticket' && fieldType == 'cf_html') {
924 var defaultVal = dataform.get('html_text').trim();
925 if(!defaultVal){
926 alert(supportcandy.translations.req_fields_missing);
927 return;
928 }
929 }
930
931 <?php do_action( 'wpsc_js_set_edit_custom_field' ); ?>
932
933 jQuery(el).text(supportcandy.translations.please_wait);
934 jQuery.ajax({
935 url: supportcandy.ajax_url,
936 type: 'POST',
937 data: dataform,
938 processData: false,
939 contentType: false
940 }).done(function (res) {
941 jQuery('.wpsc-setting-nav.active').trigger('click');
942 });
943 }
944
945 /**
946 * General validations
947 */
948 function wpsc_cf_settings_general_validations(form) {
949
950 var flag = true;
951 form.find('.wpsc-input-group').each(function(index, element){
952
953 var inputData = jQuery(element).data();
954 switch(inputData.type) {
955
956 case 'textfield':
957 var fieldValue = jQuery(this).find('input').val().trim();
958 if (inputData.required && !fieldValue) {
959 alert(supportcandy.translations.req_fields_missing);
960 jQuery(this).find('input').focus();
961 return flag = false;
962 }
963 break;
964
965 case 'single-select':
966 var fieldValue = jQuery(this).find('select').val();
967 if (inputData.required && !fieldValue) {
968 alert(supportcandy.translations.req_fields_missing);
969 return flag = false;
970 }
971 break;
972
973 case 'select-options':
974 var fieldValue = jQuery(this).find('.wpsc-options-container .option_id').length;
975 if (inputData.required && !fieldValue) {
976 alert(supportcandy.translations.submit_option_error);
977 return flag = false;
978 }
979 break;
980
981 case 'number':
982 var fieldValue = jQuery(this).find('input').val().trim();
983 if (inputData.required && !fieldValue) {
984 alert(supportcandy.translations.req_fields_missing);
985 return flag = false;
986 }
987 if (fieldValue && isNaN(fieldValue)) {
988 alert('<?php esc_attr_e( 'Incorrect number value!', 'supportcandy' ); ?>');
989 jQuery(this).find('input').focus();
990 return flag = false;
991 }
992 break;
993
994 case 'email':
995 var fieldValue = jQuery(this).find('input').val().trim();
996 if (inputData.required && !fieldValue) {
997 alert(supportcandy.translations.req_fields_missing);
998 return flag = false;
999 }
1000 if (fieldValue && !validateEmail(fieldValue)) {
1001 alert('<?php esc_attr_e( 'Incorrect email!', 'supportcandy' ); ?>');
1002 jQuery(this).find('input').focus();
1003 return flag = false;
1004 }
1005 break;
1006
1007 case 'url':
1008 var fieldValue = jQuery(this).find('input').val().trim();
1009 if (inputData.required && !fieldValue) {
1010 alert(supportcandy.translations.req_fields_missing);
1011 return flag = false;
1012 }
1013 if (fieldValue && !validateURL(fieldValue)) {
1014 alert('<?php esc_attr_e( 'Incorrect url!', 'supportcandy' ); ?>');
1015 jQuery(this).find('input').focus();
1016 return flag = false;
1017 }
1018 break;
1019 }
1020 });
1021
1022 return flag;
1023 }
1024 </script>
1025 <?php
1026 }
1027 }
1028 endif;
1029
1030 WPSC_CF_Settings::init();
1031