PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.4.1
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.4.1
3.5.4 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 / custom-field-types / class-wpsc-cf-date.php

class-wpsc-cf-date.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent 3.4.1, at includes/custom-field-types/class-wpsc-cf-date.php

1,686 lines 57.4 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_Date' ) ) :
7
8 final class WPSC_CF_Date {
9
10 /**
11 * Slug for this custom field type
12 *
13 * @var string
14 */
15 public static $slug = 'cf_date';
16
17 /**
18 * Set whether this custom field type is of type date
19 *
20 * @var boolean
21 */
22 public static $is_date = true;
23
24 /**
25 * Set whether this custom field type has applicable to date range
26 *
27 * @var boolean
28 */
29 public static $has_date_range = true;
30
31 /**
32 * Set whether this custom field type has multiple values
33 *
34 * @var boolean
35 */
36 public static $has_multiple_val = false;
37
38 /**
39 * Data type for column created in tickets table
40 *
41 * @var string
42 */
43 public static $data_type = 'DATETIME NULL DEFAULT NULL';
44
45 /**
46 * Set whether this custom field type has reference to other class
47 *
48 * @var boolean
49 */
50 public static $has_ref = true;
51
52 /**
53 * Reference class for this custom field type so that its value(s) return with object or array of objects automatically. Empty string indicate no reference.
54 *
55 * @var string
56 */
57 public static $ref_class = 'datetime';
58
59 /**
60 * Set whether this custom field field type is system default (no fields can be created from it).
61 *
62 * @var boolean
63 */
64 public static $is_default = false;
65
66 /**
67 * Set whether this field type has extra information that can be used in ticket form, edit custom fields, etc.
68 *
69 * @var boolean
70 */
71 public static $has_extra_info = true;
72
73 /**
74 * Set whether this custom field type can accept personal info.
75 *
76 * @var boolean
77 */
78 public static $has_personal_info = true;
79
80 /**
81 * Set whether fields created from this custom field type is allowed in create ticket form
82 *
83 * @var boolean
84 */
85 public static $is_ctf = true;
86
87 /**
88 * Set whether fields created from this custom field type is allowed in ticket list
89 *
90 * @var boolean
91 */
92 public static $is_list = true;
93
94 /**
95 * Set whether fields created from this custom field type is allowed in ticket filter
96 *
97 * @var boolean
98 */
99 public static $is_filter = true;
100
101 /**
102 * Set whether fields created from this custom field type can be given character limits
103 *
104 * @var boolean
105 */
106 public static $has_char_limit = false;
107
108 /**
109 * Set whether fields created from this custom field type has custom options set in options table
110 *
111 * @var boolean
112 */
113 public static $has_options = false;
114
115 /**
116 * Set whether fields created from this custom field type can be available for ticket list sorting
117 *
118 * @var boolean
119 */
120 public static $is_sort = true;
121
122 /**
123 * Set whether fields created from this custom field type can be auto-filled
124 *
125 * @var boolean
126 */
127 public static $is_auto_fill = true;
128
129 /**
130 * Set whether fields created from this custom field type can have placeholder
131 *
132 * @var boolean
133 */
134 public static $is_placeholder = true;
135
136 /**
137 * Set whether fields created from this custom field type is applicable for visibility conditions in create ticket form
138 *
139 * @var boolean
140 */
141 public static $is_visibility_conditions = true;
142
143 /**
144 * Set whether fields created from this custom field type is applicable for macros
145 *
146 * @var boolean
147 */
148 public static $has_macro = true;
149
150 /**
151 * Set whether fields of this custom field type is applicalbe for search on ticket list page.
152 *
153 * @var boolean
154 */
155 public static $is_search = false;
156
157 /**
158 * Initialize the class
159 *
160 * @return void
161 */
162 public static function init() {
163
164 // Get object of this class.
165 add_filter( 'wpsc_load_ref_classes', array( __CLASS__, 'load_ref_class' ) );
166
167 // Set custom field type.
168 add_filter( 'wpsc_cf_types', array( __CLASS__, 'add_cf_type' ), 6 );
169
170 // ticket form.
171 add_action( 'wpsc_js_validate_ticket_form', array( __CLASS__, 'js_validate_ticket_form' ) );
172 add_filter( 'wpsc_create_ticket_data', array( __CLASS__, 'set_create_ticket_data' ), 10, 3 );
173 add_action( 'wpsc_js_clear_value_hidden_fields', array( __CLASS__, 'js_clear_value_hidden_fields' ) );
174
175 // create ticket data for rest api.
176 add_filter( 'wpsc_rest_create_ticket', array( __CLASS__, 'set_rest_ticket_data' ), 10, 3 );
177 }
178
179 /**
180 * Load current class to reference classes
181 *
182 * @param array $classes - Associative array of class names indexed by its slug.
183 * @return array
184 */
185 public static function load_ref_class( $classes ) {
186
187 $classes[ self::$slug ] = array(
188 'class' => __CLASS__,
189 'save-key' => 'id',
190 );
191 return $classes;
192 }
193
194 /**
195 * Add custom field type to list
196 *
197 * @param array $cf_types - custom field types array.
198 * @return array
199 */
200 public static function add_cf_type( $cf_types ) {
201
202 $cf_types[ self::$slug ] = array(
203 'label' => esc_attr__( 'Date', 'supportcandy' ),
204 'class' => __CLASS__,
205 );
206 return $cf_types;
207 }
208
209 /**
210 * Print operators for ticket form filter
211 *
212 * @param WPSC_Custom_Field $cf - custom field object.
213 * @param array $filter - Existing filters (if any).
214 * @return void
215 */
216 public static function get_operators( $cf, $filter = array() ) {
217 ?>
218
219 <div class="item conditional">
220 <select class="operator" onchange="wpsc_tc_get_operand(this, '<?php echo esc_attr( $cf->slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_tc_get_operand' ) ); ?>');">
221 <option value=""><?php esc_attr_e( 'Compare As', 'supportcandy' ); ?></option>
222 <option <?php isset( $filter['operator'] ) && selected( $filter['operator'], '=' ); ?> value="="><?php esc_attr_e( 'Equals', 'supportcandy' ); ?></option>
223 <option <?php isset( $filter['operator'] ) && selected( $filter['operator'], '<' ); ?> value="<"><?php esc_attr_e( 'Less than', 'supportcandy' ); ?></option>
224 <option <?php isset( $filter['operator'] ) && selected( $filter['operator'], '<=' ); ?> value="<="><?php esc_attr_e( 'Less than or equals', 'supportcandy' ); ?></option>
225 <option <?php isset( $filter['operator'] ) && selected( $filter['operator'], '>' ); ?> value=">"><?php esc_attr_e( 'Greater than', 'supportcandy' ); ?></option>
226 <option <?php isset( $filter['operator'] ) && selected( $filter['operator'], '>=' ); ?> value=">="><?php esc_attr_e( 'Greater than or equals', 'supportcandy' ); ?></option>
227 <option <?php isset( $filter['operator'] ) && selected( $filter['operator'], 'BETWEEN' ); ?> value="BETWEEN"><?php esc_attr_e( 'Between', 'supportcandy' ); ?></option>
228 </select>
229 </div>
230 <?php
231 }
232
233 /**
234 * Print operators for ticket form filter
235 *
236 * @param string $operator - condition operator on which operands should be returned.
237 * @param WPSC_Custom_Field $cf - custom field object.
238 * @param array $filter - Exising functions (if any).
239 * @return void
240 */
241 public static function get_operands( $operator, $cf, $filter = array() ) {
242
243 $unique_id = uniqid( 'wpsc_' );
244 $is_between = $operator == 'BETWEEN' ? true : false;
245 $operand_val_1 = isset( $filter['operand_val_1'] ) ? $filter['operand_val_1'] : '';
246 $operand_val_2 = isset( $filter['operand_val_2'] ) ? $filter['operand_val_2'] : '';
247 ?>
248
249 <div class="item conditional operand <?php echo ! $is_between ? 'single' : ''; ?>">
250 <input type="text" class="operand_val_1 <?php echo esc_attr( $unique_id ); ?>" placeholder="<?php echo $is_between ? esc_attr__( 'From date', 'supportcandy' ) : ''; ?>" value="<?php echo esc_attr( $operand_val_1 ); ?>">
251 </div>
252 <script>
253 jQuery('.operand_val_1.<?php echo esc_attr( $unique_id ); ?>').flatpickr({
254 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
255 });
256 </script>
257 <?php
258
259 if ( $is_between ) {
260 ?>
261 <div class="item conditional operand">
262 <input type="text" class="operand_val_2 <?php echo esc_attr( $unique_id ); ?>" placeholder="<?php esc_attr_e( 'To date', 'supportcandy' ); ?>" value="<?php echo esc_attr( $operand_val_2 ); ?>">
263 </div>
264 <script>
265 jQuery('.operand_val_1.<?php echo esc_attr( $unique_id ); ?>').change(function() {
266 var fromDate = jQuery(this).val().trim();
267 jQuery('.operand_val_2.<?php echo esc_attr( $unique_id ); ?>').flatpickr({
268 minDate: fromDate,
269 defaultDate: fromDate,
270 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
271 });
272 });
273 <?php
274 if ( $operand_val_2 ) {
275 ?>
276 jQuery('.operand_val_2.<?php echo esc_attr( $unique_id ); ?>').flatpickr({
277 minDate: '<?php echo esc_attr( $operand_val_1 ); ?>',
278 defaultDate: '<?php echo esc_attr( $operand_val_2 ); ?>',
279 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
280 });
281 <?php
282 }
283 ?>
284 </script>
285 <?php
286 }
287 }
288
289 /**
290 * Check condition for this type
291 *
292 * @param array $condition - condition data.
293 * @param WPSC_Custom_Field $cf - custom field object.
294 * @param mixed $value - value to compare.
295 * @return boolean
296 */
297 public static function is_valid( $condition, $cf, $value ) {
298
299 $response = false;
300 if ( ! $value ) {
301 return false;
302 }
303 $operand_1 = new DateTime( $condition['operand_val_1'] . ' 00:00:00' );
304
305 switch ( $condition['operator'] ) {
306
307 case '=':
308 $response = $operand_1 == $value ? true : false;
309 break;
310
311 case '<':
312 $response = $operand_1 > $value ? true : false;
313 break;
314
315 case '>':
316 $response = $operand_1 < $value ? true : false;
317 break;
318
319 case '<=':
320 $response = $operand_1 >= $value ? true : false;
321 break;
322
323 case '>=':
324 $response = $operand_1 <= $value ? true : false;
325 break;
326
327 case 'BETWEEN':
328 $operand_2 = new DateTime( $condition['operand_val_2'] . ' 00:00:00' );
329 $response = $operand_1 <= $value && $operand_2 >= $value ? true : false;
330 break;
331 }
332 return $response;
333 }
334
335 /**
336 * Parse filter and return sql query to be merged in ticket model query builder
337 *
338 * @param WPSC_Custom_Field $cf - custom field of this type.
339 * @param mixed $compare - comparison operator.
340 * @param mixed $val - value to compare.
341 * @return string
342 */
343 public static function parse_filter( $cf, $compare, $val ) {
344
345 $str = '';
346
347 switch ( $compare ) {
348
349 case '=':
350 $from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
351 $to = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
352 $str = self::get_sql_slug( $cf ) . ' BETWEEN \'' . esc_sql( $from ) . '\' AND \'' . esc_sql( $to ) . '\'';
353 break;
354
355 case '<':
356 $from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
357 $arr = array(
358 self::get_sql_slug( $cf ) . esc_sql( $compare ) . '\'' . esc_sql( $from ) . '\'',
359 self::get_sql_slug( $cf ) . ' != \'0000-00-00 00:00:00\'',
360 );
361 $str = '(' . implode( ' AND ', $arr ) . ')';
362 break;
363
364 case '>':
365 $to = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
366 $str = self::get_sql_slug( $cf ) . esc_sql( $compare ) . '\'' . esc_sql( $to ) . '\'';
367 break;
368
369 case '<=':
370 $from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
371 $to = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
372 $arr = array(
373 self::get_sql_slug( $cf ) . esc_sql( $compare ) . '\'' . esc_sql( $from ) . '\'',
374 self::get_sql_slug( $cf ) . ' BETWEEN \'' . esc_sql( $from ) . '\' AND \'' . esc_sql( $to ) . '\'',
375 );
376 $str = '((' . implode( ' OR ', $arr ) . ') AND ' . self::get_sql_slug( $cf ) . ' != \'0000-00-00 00:00:00\')';
377 break;
378
379 case '>=':
380 $from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
381 $to = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
382 $arr = array(
383 self::get_sql_slug( $cf ) . esc_sql( $compare ) . '\'' . esc_sql( $to ) . '\'',
384 self::get_sql_slug( $cf ) . ' BETWEEN \'' . esc_sql( $from ) . '\' AND \'' . esc_sql( $to ) . '\'',
385 );
386 $str = '(' . implode( ' OR ', $arr ) . ')';
387 break;
388
389 case 'BETWEEN':
390 $from = WPSC_Functions::get_utc_date_str( $val['operand_val_1'] . ' 00:00:00' );
391 $to = WPSC_Functions::get_utc_date_str( $val['operand_val_2'] . ' 23:59:59' );
392 $str = self::get_sql_slug( $cf ) . ' BETWEEN \'' . esc_sql( $from ) . '\' AND \'' . esc_sql( $to ) . '\'';
393 break;
394
395 default:
396 $str = '1=1';
397 }
398
399 return $str;
400 }
401
402 /**
403 * Return orderby string
404 *
405 * @param WPSC_Custom_Field $cf - custom field object.
406 * @return string
407 */
408 public static function get_orderby_string( $cf ) {
409
410 return self::get_sql_slug( $cf );
411 }
412
413 /**
414 * Check ticket condition
415 *
416 * @param array $condition - array with condition data.
417 * @param WPSC_Custom_Field $cf - custom field object.
418 * @param WPSC_Ticket $ticket - ticket object.
419 * @return boolean
420 */
421 public static function is_valid_ticket_condition( $condition, $cf, $ticket ) {
422
423 $flag = true;
424 $date = $ticket->{$cf->slug};
425 if ( ! is_object( $date ) ) {
426 return false;
427 }
428
429 $date->setTimezone( wp_timezone() );
430
431 switch ( $condition['operator'] ) {
432
433 case '=':
434 $flag = $date->format( 'Y-m-d' ) == $condition['operand_val_1'] ? true : false;
435 break;
436
437 case '<':
438 $operand = new DateTime( $condition['operand_val_1'] );
439 $flag = $date < $operand ? true : false;
440 break;
441
442 case '>':
443 $operand = new DateTime( $condition['operand_val_1'] );
444 $flag = $date > $operand ? true : false;
445 break;
446
447 case '<=':
448 $operand = new DateTime( $condition['operand_val_1'] );
449 $flag = $date <= $operand ? true : false;
450 break;
451
452 case '>=':
453 $operand = new DateTime( $condition['operand_val_1'] );
454 $flag = $date >= $operand ? true : false;
455 break;
456
457 case 'BETWEEN':
458 $operand1 = new DateTime( $condition['operand_val_1'] );
459 $operand2 = new DateTime( $condition['operand_val_2'] );
460 $flag = $operand1 <= $date && $operand2 >= $date ? true : false;
461 break;
462
463 default:
464 $flag = true;
465 }
466
467 return $flag;
468 }
469
470 /**
471 * Check customer condition
472 *
473 * @param array $condition - array with condition data.
474 * @param WPSC_Custom_Field $cf - custom field object.
475 * @param WPSC_Customer $customer - customer object.
476 * @return boolean
477 */
478 public static function is_valid_customer_condition( $condition, $cf, $customer ) {
479
480 $flag = true;
481 $date = $customer->{$cf->slug};
482 if ( ! is_object( $date ) ) {
483 return false;
484 }
485
486 switch ( $condition['operator'] ) {
487
488 case '=':
489 $flag = $date->format( 'Y-m-d' ) == $condition['operand_val_1'] ? true : false;
490 break;
491
492 case '<':
493 $operand = new DateTime( $condition['operand_val_1'] );
494 $flag = $date < $operand ? true : false;
495 break;
496
497 case '>':
498 $operand = new DateTime( $condition['operand_val_1'] );
499 $flag = $date > $operand ? true : false;
500 break;
501
502 case '<=':
503 $operand = new DateTime( $condition['operand_val_1'] );
504 $flag = $date <= $operand ? true : false;
505 break;
506
507 case '>=':
508 $operand = new DateTime( $condition['operand_val_1'] );
509 $flag = $date >= $operand ? true : false;
510 break;
511
512 case 'BETWEEN':
513 $operand1 = new DateTime( $condition['operand_val_1'] );
514 $operand2 = new DateTime( $condition['operand_val_2'] );
515 $flag = $operand1 <= $date && $operand2 >= $date ? true : false;
516 break;
517
518 default:
519 $flag = true;
520 }
521
522 return $flag;
523 }
524
525 /**
526 * Print ticket form field
527 *
528 * @param WPSC_Custom_Field $cf - Custom field object.
529 * @param array $tff - Array of ticket form field settings for this field.
530 * @return string
531 */
532 public static function print_tff( $cf, $tff ) {
533
534 $unique_id = uniqid( 'wpsc_' );
535 $val = '';
536 if ( $cf->field == 'ticket' ) {
537 $val = $cf->is_auto_fill && $cf->default_value ? $cf->default_value[0] : '';
538 $val = $val ? new DateTime( $val . ' 00:00:00' ) : '';
539 } else {
540 $current_user = WPSC_Current_User::$current_user;
541 $val = $current_user->is_customer && $current_user->customer->{$cf->slug} ? $current_user->customer->{$cf->slug} : '';
542 }
543
544 ob_start();
545 ?>
546 <div class="<?php echo esc_attr( WPSC_Functions::get_tff_classes( $cf, $tff ) ); ?>" data-cft="<?php echo esc_attr( self::$slug ); ?>" data-slug="<?php echo esc_attr( $cf->slug ); ?>">
547 <div class="wpsc-tff-label">
548 <span class="name"><?php echo esc_attr( $cf->name ); ?></span>
549 <?php
550 if ( $tff['is-required'] ) {
551 ?>
552 <span class="required-indicator">*</span>
553 <?php
554 }
555 ?>
556 </div>
557 <span class="extra-info"><?php echo esc_attr( $cf->extra_info ); ?></span>
558 <div class="wpsc-input-close-group">
559 <input
560 id="<?php echo esc_attr( $unique_id ); ?>"
561 type="text"
562 name="<?php echo esc_attr( $cf->slug ); ?>"
563 onchange="wpsc_check_tff_visibility()"
564 placeholder="<?php echo esc_attr( $cf->placeholder_text ); ?>"
565 maxlength="<?php echo $cf->char_limit ? intval( $cf->char_limit ) : ''; ?>"
566 value="<?php echo $val && is_object( $val ) ? esc_attr( $val->format( 'Y-m-d' ) ) : ''; ?>"
567 autocomplete="off"/>
568 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
569 </div>
570 <script>
571 jQuery('#<?php echo esc_attr( $unique_id ); ?>').flatpickr({
572 <?php echo $cf->date_range == 'future' ? 'minDate: new Date(),' : ''; ?>
573 <?php echo $cf->date_range == 'past' ? 'maxDate: new Date(),' : ''; ?>
574 disableMobile: true,
575 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
576 <?php echo $cf->date_range == 'range' ? "minDate:'" . esc_attr( $cf->start_range->format( 'Y-m-d' ) ) . "', maxDate:'" . esc_attr( $cf->end_range->format( 'Y-m-d' ) ) . "'" : ''; ?>
577 });
578 </script>
579 </div>
580 <?php
581 return ob_get_clean();
582 }
583
584 /**
585 * Validate this type field in create ticket
586 *
587 * @return void
588 */
589 public static function js_validate_ticket_form() {
590 ?>
591
592 case '<?php echo esc_attr( self::$slug ); ?>':
593 var val = customField.find('input').first().val().trim();
594 if (customField.hasClass('required') && !val) {
595 isValid = false;
596 alert(supportcandy.translations.req_fields_missing);
597 }
598 break;
599 <?php
600 echo PHP_EOL;
601 }
602
603 /**
604 * Return custom field value in $_POST
605 * Ignore phpcs nonce issue as we already checked where it is called from.
606 *
607 * @param string $slug - Custom field slug.
608 * @param mixed $cf - Custom field object or false.
609 * @return mixed
610 */
611 public static function get_tff_value( $slug, $cf = false ) {
612
613 $date = isset( $_POST[ $slug ] ) ? sanitize_text_field( wp_unslash( $_POST[ $slug ] ) ) : ''; // phpcs:ignore
614 $date = $date && preg_match( '/\d{4}-\d{2}-\d{2}/', $date ) ? $date : '';
615 return $date ? new DateTime( $date . ' 00:00:00' ) : false;
616 }
617
618 /**
619 * Return default value for custom field of this type
620 *
621 * @param WPSC_Custom_Field $cf - custom field object.
622 * @return mixed
623 */
624 public static function get_default_value( $cf ) {
625
626 return $cf->default_value ? $cf->default_value[0] . ' 00:00:00' : '';
627 }
628
629 /**
630 * Check and return custom field value for new ticket to be created.
631 * This function is used by filter for set create ticket form and called directly by my-profile for each applicable custom fields.
632 * Ignore phpcs nonce issue as we already checked where it is called from.
633 *
634 * @param array $data - Array of values to to stored in ticket in an insert function.
635 * @param array $custom_fields - Array containing all applicable custom fields indexed by unique custom field types.
636 * @param boolean $is_my_profile - Whether it or not it is created from my-profile. This function is used by create ticket as well as my-profile. Due to customer fields handling is done same way, this flag gives apportunity to identify where it being called.
637 * @return array
638 */
639 public static function set_create_ticket_data( $data, $custom_fields, $is_my_profile ) {
640
641 if ( isset( $custom_fields[ self::$slug ] ) ) {
642 foreach ( $custom_fields[ self::$slug ] as $cf ) {
643 $value = self::get_tff_value( $cf->slug );
644 if ( $cf->field == 'ticket' ) {
645
646 $default_val = self::get_default_value( $cf );
647 $data[ $cf->slug ] = $value ? $value->format( 'Y-m-d H:i:s' ) : $default_val;
648
649 } elseif ( $cf->field == 'agentonly' ) {
650
651 $data[ $cf->slug ] = self::get_default_value( $cf );
652
653 } elseif ( $cf->field == 'customer' && $data['customer'] != 0 ) {
654
655 $tff = get_option( 'wpsc-tff' );
656 if ( ! $is_my_profile && ! isset( $tff[ $cf->slug ] ) ) {
657 continue;
658 }
659 $customer = new WPSC_Customer( $data['customer'] );
660 $prev_val = $customer->{$cf->slug} && is_object( $customer->{$cf->slug} ) ? $customer->{$cf->slug}->format( 'Y-m-d' ) : '';
661 $value = $value ? $value : '0000-00-00 00:00:00';
662 if ( $customer->{$cf->slug} != $value ) {
663 $customer->{$cf->slug} = $value;
664 $customer->save();
665
666 $new_val = $value && is_object( $value ) ? $value->format( 'Y-m-d H:i:s' ) : '';
667
668 // Set log for this change.
669 WPSC_Log::insert(
670 array(
671 'type' => 'customer',
672 'ref_id' => $customer->id,
673 'modified_by' => WPSC_Current_User::$current_user->customer->id,
674 'body' => wp_json_encode(
675 array(
676 'slug' => $cf->slug,
677 'prev' => $prev_val,
678 'new' => $new_val,
679 )
680 ),
681 'date_created' => ( new DateTime() )->format( 'Y-m-d H:i:s' ),
682 )
683 );
684 }
685 }
686 }
687 }
688 return $data;
689 }
690
691 /**
692 * Set create ticket data for rest api request
693 *
694 * @param array $data - create ticket data array.
695 * @param WP_REST_Request $request - rest request object.
696 * @param array $custom_fields - custom field objects indexed by unique custom field types.
697 * @return array
698 */
699 public static function set_rest_ticket_data( $data, $request, $custom_fields ) {
700
701 $current_user = WPSC_Current_User::$current_user;
702 $tff = get_option( 'wpsc-tff' );
703
704 if ( isset( $custom_fields[ self::$slug ] ) ) {
705 foreach ( $custom_fields[ self::$slug ] as $cf ) {
706
707 if (
708 ! in_array( $cf->field, array( 'ticket', 'agentonly', 'customer' ) ) ||
709 ( $cf->field == 'customer' && ! isset( $tff[ $cf->slug ] ) )
710 ) {
711 continue;
712 }
713
714 $date = WPSC_Functions::sanitize_date( sanitize_text_field( $request->get_param( $cf->slug ) ) );
715
716 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ) {
717
718 $data[ $cf->slug ] = $cf->field == 'ticket' && $date ? $date : self::get_default_value( $cf );
719
720 } else {
721
722 $customer = new WPSC_Customer( $data['customer'] );
723 $format = 'Y-m-d H:i:s';
724 $date = $date ? DateTime::createFromFormat( $format, $date ) : '';
725 $existing_val = $customer->{$cf->slug};
726 $existing_val = $existing_val && is_object( $existing_val ) ? $existing_val->format( $format ) : '';
727
728 if ( $date && $date->format( $format ) != $existing_val ) {
729
730 $customer->{$cf->slug} = $date;
731 $customer->save();
732
733 // Set log for this change.
734 WPSC_Log::insert(
735 array(
736 'type' => 'customer',
737 'ref_id' => $customer->id,
738 'modified_by' => $current_user->customer->id,
739 'body' => wp_json_encode(
740 array(
741 'slug' => $cf->slug,
742 'prev' => $existing_val,
743 'new' => $date->format( $format ),
744 )
745 ),
746 'date_created' => ( new DateTime() )->format( 'Y-m-d H:i:s' ),
747 )
748 );
749 }
750 }
751 }
752 }
753
754 return $data;
755 }
756
757 /**
758 * Return slug string to be used in where condition of ticket model for this type of field
759 *
760 * @param WPSC_Custom_Field $cf - custom field object.
761 * @return string
762 */
763 public static function get_sql_slug( $cf ) {
764
765 $join_char = in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ? 't.' : 'c.';
766 return $join_char . $cf->slug;
767 }
768
769 /**
770 * Return val field for meta query of this type of custom field
771 *
772 * @param array $condition - condition data.
773 * @return mixed
774 */
775 public static function get_meta_value( $condition ) {
776
777 $operator = $condition['operator'];
778 switch ( $operator ) {
779
780 case '=':
781 case '<':
782 case '<=':
783 case '>':
784 case '>=':
785 return $condition['operand_val_1'];
786
787 case 'BETWEEN':
788 if (
789 ! ( isset( $condition['operand_val_1'] ) && preg_match( '/^(\d{4})-\d{2}-(\d{2})$/', $condition['operand_val_1'] ) ) ||
790 ! ( isset( $condition['operand_val_2'] ) && preg_match( '/^(\d{4})-\d{2}-(\d{2})$/', $condition['operand_val_2'] ) )
791 ) {
792 return false;
793 }
794
795 return array(
796 'operand_val_1' => $condition['operand_val_1'],
797 'operand_val_2' => $condition['operand_val_2'],
798 );
799 }
800 return false;
801 }
802
803 /**
804 * Print generic input field for this type.
805 *
806 * @param WPSC_Custom_Field $cf - custom field object.
807 * @param DateTime $date - optional. Input field will be printed with given value (if given).
808 * @return void
809 */
810 public static function print_cf_input( $cf, $date = '' ) {
811
812 if ( $date && ! is_object( $date ) && $date != '0000-00-00 00:00:00' ) {
813 $date = new DateTime( $date );
814 }
815
816 $unique_id = uniqid( 'wpsc_' );
817 ?>
818 <div class="wpsc-tff wpsc-sm-12 wpsc-md-12 wpsc-lg-12 wpsc-visible wpsc-xs-12" data-cft="<?php echo esc_attr( self::$slug ); ?>">
819 <div class="wpsc-tff-label">
820 <span class="name"><?php echo esc_attr( $cf->name ); ?></span>
821 </div>
822 <?php
823 $extra_info = stripslashes( $cf->extra_info );
824 if ( $extra_info ) :
825 ?>
826 <span class="extra-info"><?php echo esc_attr( $cf->extra_info ); ?></span>
827 <?php
828 endif
829 ?>
830 <div class="wpsc-input-close-group">
831 <input
832 id="<?php echo esc_attr( $unique_id ); ?>"
833 type="text"
834 name="<?php echo esc_attr( $cf->slug ); ?>"
835 placeholder="<?php echo esc_attr( $cf->placeholder_text ); ?>"
836 maxlength="<?php echo $cf->char_limit ? intval( $cf->char_limit ) : ''; ?>"
837 value="<?php echo $date && is_object( $date ) ? esc_attr( $date->format( 'Y-m-d' ) ) : ''; ?>"
838 autocomplete="off"/>
839 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
840 </div>
841 <script>
842 jQuery('#<?php echo esc_attr( $unique_id ); ?>').flatpickr({
843 <?php echo $cf->date_range == 'future' ? 'minDate: new Date(),' : ''; ?>
844 <?php echo $cf->date_range == 'past' ? 'maxDate: new Date(),' : ''; ?>
845 disableMobile: true,
846 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
847 <?php echo $cf->date_range == 'range' ? "minDate:'" . esc_attr( $cf->start_range->format( 'Y-m-d' ) ) . "', maxDate:'" . esc_attr( $cf->end_range->format( 'Y-m-d' ) ) . "'" : ''; ?>
848 });
849 </script>
850 </div>
851 <?php
852 }
853
854 /**
855 * Get value for generic field from post.
856 * Ignore phpcs nonce issue as we already checked where it is called from.
857 *
858 * @param WPSC_Custom_Field $cf - custom field object.
859 * @return string
860 */
861 public static function get_cf_input_val( $cf ) {
862
863 $date = isset( $_POST[ $cf->slug ] ) ? sanitize_text_field( wp_unslash( $_POST[ $cf->slug ] ) ) : ''; // phpcs:ignore
864 return $date && preg_match( '/\d{4}-\d{2}-\d{2}/', $date ) ? $date . ' 00:00:00' : '';
865 }
866
867 /**
868 * Print edit ticket custom field in individual ticket
869 *
870 * @param WPSC_Custom_Field $cf - custom field object.
871 * @param WPSC_Ticket $ticket - ticket object.
872 * @return void
873 */
874 public static function print_edit_ticket_cf( $cf, $ticket ) {
875
876 $unique_id = uniqid( 'wpsc_' );
877 ?>
878 <div class="wpsc-tff wpsc-sm-12 wpsc-md-12 wpsc-lg-12 wpsc-visible wpsc-xs-12" data-cft="<?php echo esc_attr( self::$slug ); ?>">
879 <div class="wpsc-tff-label">
880 <span class="name"><?php echo esc_attr( $cf->name ); ?></span>
881 </div>
882 <?php
883 $extra_info = stripslashes( $cf->extra_info );
884 if ( $extra_info ) :
885 ?>
886 <span class="extra-info"><?php echo esc_attr( $cf->extra_info ); ?></span>
887 <?php
888 endif
889 ?>
890 <div class="wpsc-input-close-group">
891 <input
892 id="<?php echo esc_attr( $unique_id ); ?>"
893 type="text"
894 name="<?php echo esc_attr( $cf->slug ); ?>"
895 placeholder="<?php echo esc_attr( $cf->placeholder_text ); ?>"
896 maxlength="<?php echo $cf->char_limit ? intval( $cf->char_limit ) : ''; ?>"
897 value="<?php echo $ticket->{$cf->slug} && is_object( $ticket->{$cf->slug} ) ? esc_attr( $ticket->{$cf->slug}->format( 'Y-m-d' ) ) : ''; ?>"
898 autocomplete="off"/>
899 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
900 </div>
901 <script>
902 jQuery('#<?php echo esc_attr( $unique_id ); ?>').flatpickr({
903 <?php echo $cf->date_range == 'future' ? 'minDate: new Date(),' : ''; ?>
904 <?php echo $cf->date_range == 'past' ? 'maxDate: new Date(),' : ''; ?>
905 disableMobile: true,
906 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
907 <?php echo $cf->date_range == 'range' ? "minDate:'" . esc_attr( $cf->start_range->format( 'Y-m-d' ) ) . "', maxDate:'" . esc_attr( $cf->end_range->format( 'Y-m-d' ) ) . "'" : ''; ?>
908 });
909 </script>
910 </div>
911 <?php
912 }
913
914 /**
915 * Set edit individual ticket for this custom field type.
916 * Ignore phpcs nonce issue as we already checked where it is called from.
917 *
918 * @param WPSC_Custom_Field $cf - custom field object.
919 * @param WPSC_Ticket $ticket - ticket object.
920 * @return WPSC_Ticket
921 */
922 public static function set_edit_ticket_cf( $cf, $ticket ) {
923
924 $prev = $ticket->{$cf->slug} && is_object( $ticket->{$cf->slug} ) ? $ticket->{$cf->slug}->format( 'Y-m-d' ) : '';
925 $new = isset( $_POST[ $cf->slug ] ) ? sanitize_text_field( wp_unslash( $_POST[ $cf->slug ] ) ) : ''; // phpcs:ignore
926
927 // Exit if there is no change.
928 if ( $prev == $new ) {
929 return $ticket;
930 }
931
932 // Change value.
933 $ticket->{$cf->slug} = $new ? new DateTime( $new ) : '';
934 $ticket->save();
935
936 return $ticket;
937 }
938
939 /**
940 * Modify ticket field value of this custom field type using rest api
941 *
942 * @param WPSC_Ticket $ticket - ticket object.
943 * @param WPSC_Custom_Field $cf - custom field.
944 * @param mixed $value - value to be set.
945 * @return void
946 */
947 public static function set_rest_edit_ticket_cf( $ticket, $cf, $value ) {
948
949 $date = WPSC_Functions::sanitize_date( sanitize_text_field( $value ) );
950 $new = $date ? $date : '';
951 $prev = is_object( $ticket->{$cf->slug} ) ? $ticket->{$cf->slug}->format( 'Y-m-d H:i:s' ) : '';
952 if ( $prev != $new ) {
953 $ticket->{$cf->slug} = $new;
954 }
955 }
956
957 /**
958 * Insert log thread for this custom field type change
959 *
960 * @param WPSC_Custom_Field $cf - current custom field of this type.
961 * @param WPSC_Ticket $prev - ticket object before making any changes.
962 * @param WPSC_Ticket $new - ticket object after making changes.
963 * @param string $current_date - date string to be stored as create time.
964 * @param int $customer_id - current user customer id for blame.
965 * @return void
966 */
967 public static function insert_ticket_log( $cf, $prev, $new, $current_date, $customer_id ) {
968
969 // Exit if there is no change.
970 if ( $prev->{$cf->slug} == $new->{$cf->slug} ) {
971 return;
972 }
973
974 $prev_val = $prev->{$cf->slug} && is_object( $prev->{$cf->slug} ) ? $prev->{$cf->slug}->format( 'Y-m-d H:i:s' ) : '';
975 $new_val = $new->{$cf->slug} && is_object( $new->{$cf->slug} ) ? $new->{$cf->slug}->format( 'Y-m-d H:i:s' ) : '';
976
977 $thread = WPSC_Thread::insert(
978 array(
979 'ticket' => $prev->id,
980 'customer' => $customer_id,
981 'type' => 'log',
982 'body' => wp_json_encode(
983 array(
984 'slug' => $cf->slug,
985 'prev' => $prev_val,
986 'new' => $new_val,
987 )
988 ),
989 'date_created' => $current_date,
990 'date_updated' => $current_date,
991 )
992 );
993 }
994
995 /**
996 * Return data for this custom field while creating duplicate ticket
997 *
998 * @param WPSC_Custom_Field $cf - custom field object.
999 * @param WPSC_Ticket $ticket - ticket object.
1000 * @return mixed
1001 */
1002 public static function get_duplicate_ticket_data( $cf, $ticket ) {
1003
1004 return $ticket->{$cf->slug} && is_object( $ticket->{$cf->slug} ) ? $ticket->{$cf->slug}->format( 'Y-m-d H:i:s' ) : '';
1005 }
1006
1007 /**
1008 * Print edit field for this type in edit customer info
1009 *
1010 * @param WPSC_Custom_field $cf - custom field object.
1011 * @param WPSC_Customer $customer - customer object.
1012 * @param array $tff - ticket form field data.
1013 * @return string
1014 */
1015 public static function print_edit_customer_info( $cf, $customer, $tff ) {
1016
1017 $unique_id = uniqid( 'wpsc_' );
1018 $val = $customer->id && $customer->{$cf->slug} ? $customer->{$cf->slug} : '';
1019
1020 ob_start();
1021 ?>
1022 <div class="<?php echo esc_attr( WPSC_Functions::get_tff_classes( $cf, $tff ) ); ?>" data-cft="<?php echo esc_attr( self::$slug ); ?>">
1023 <div class="wpsc-tff-label">
1024 <span class="name"><?php echo esc_attr( $cf->name ); ?></span>
1025 </div>
1026 <span class="extra-info"><?php echo esc_attr( $cf->extra_info ); ?></span>
1027 <div class="wpsc-input-close-group">
1028 <input
1029 id="<?php echo esc_attr( $unique_id ); ?>"
1030 type="text"
1031 name="<?php echo esc_attr( $cf->slug ); ?>"
1032 placeholder="<?php echo esc_attr( $cf->placeholder_text ); ?>"
1033 maxlength="<?php echo $cf->char_limit ? intval( $cf->char_limit ) : ''; ?>"
1034 value="<?php echo $val && is_object( $val ) ? esc_attr( $val->format( 'Y-m-d' ) ) : ''; ?>"
1035 autocomplete="off"/>
1036 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1037 </div>
1038 <script>
1039 jQuery('#<?php echo esc_attr( $unique_id ); ?>').flatpickr({
1040 <?php echo $cf->date_range == 'future' ? 'minDate: new Date(),' : ''; ?>
1041 <?php echo $cf->date_range == 'past' ? 'maxDate: new Date(),' : ''; ?>
1042 disableMobile: true,
1043 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1044 <?php echo $cf->date_range == 'range' ? "minDate:'" . esc_attr( $cf->start_range->format( 'Y-m-d' ) ) . "', maxDate:'" . esc_attr( $cf->end_range->format( 'Y-m-d' ) ) . "'" : ''; ?>
1045 });
1046 </script>
1047 </div>
1048 <?php
1049 return ob_get_clean();
1050 }
1051
1052 /**
1053 * Print add new custom field setting properties
1054 *
1055 * @param string $field_class - Class name of the field.
1056 * @return void
1057 */
1058 public static function get_add_new_custom_field_properties( $field_class ) {
1059
1060 if ( in_array( 'extra_info', $field_class::$allowed_properties ) ) :
1061 ?>
1062 <div data-type="textfield" data-required="false" class="wpsc-input-group extra-info">
1063 <div class="label-container">
1064 <label for=""><?php esc_attr_e( 'Extra info', 'supportcandy' ); ?></label>
1065 </div>
1066 <input name="extra_info" type="text" autocomplete="off" />
1067 </div>
1068 <?php
1069 endif;
1070
1071 if ( in_array( 'default_value', $field_class::$allowed_properties ) ) :
1072 ?>
1073 <div data-type="textfield" data-required="false" class="wpsc-input-group default_value">
1074 <div class="label-container">
1075 <label for="">
1076 <?php esc_attr_e( 'Default value', 'supportcandy' ); ?>
1077 </label>
1078 </div>
1079 <div class="wpsc-input-close-group">
1080 <input type="text" id="wpsc-default-val-date" name="default_value" />
1081 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1082 </div>
1083 <script>jQuery("#wpsc-default-val-date").flatpickr({
1084 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1085 });</script>
1086 </div>
1087 <?php
1088 endif;
1089
1090 if ( in_array( 'is_auto_fill', $field_class::$allowed_properties ) ) :
1091 ?>
1092 <div data-type="single-select" data-required="false" class="wpsc-input-group is_auto_fill">
1093 <div class="label-container">
1094 <label for="">
1095 <?php esc_attr_e( 'Auto-fill in ticket form', 'supportcandy' ); ?>
1096 </label>
1097 </div>
1098 <select name="is_auto_fill">
1099 <option value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1100 <option value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1101 </select>
1102 </div>
1103 <?php
1104 endif;
1105
1106 if ( in_array( 'placeholder_text', $field_class::$allowed_properties ) ) :
1107 ?>
1108 <div data-type="textfield" data-required="false" class="wpsc-input-group placeholder_text">
1109 <div class="label-container">
1110 <label for="">
1111 <?php esc_attr_e( 'Placeholder', 'supportcandy' ); ?>
1112 </label>
1113 </div>
1114 <input type="text" name="placeholder_text" autocomplete="off">
1115 </div>
1116 <?php
1117 endif;
1118 ?>
1119
1120 <div data-type="single-select" data-required="false" class="wpsc-input-group date_range">
1121 <div class="label-container">
1122 <label for=""><?php esc_attr_e( 'Date range', 'supportcandy' ); ?></label>
1123 </div>
1124 <select id="wpsc-date-range" name="date_range">
1125 <option value="all"><?php esc_attr_e( 'All', 'supportcandy' ); ?></option>
1126 <option value="future"><?php esc_attr_e( 'Future', 'supportcandy' ); ?></option>
1127 <option value="past"><?php esc_attr_e( 'Past', 'supportcandy' ); ?></option>
1128 <option value="range"><?php esc_attr_e( 'Between', 'supportcandy' ); ?></option>
1129 </select>
1130 <script>
1131 jQuery('#wpsc-date-range').change(function() {
1132 if (jQuery(this).val() == 'range') {
1133 jQuery('.wpsc-date-range-option').show();
1134 } else {
1135 jQuery('.wpsc-date-range-option').hide();
1136 }
1137 });
1138 </script>
1139 </div>
1140
1141 <div data-type="date-select" data-required="false" class="wpsc-input-group wpsc-date-range-option" style="display:none;">
1142 <div class="label-container">
1143 <label for=""><?php esc_attr_e( 'Date in between', 'supportcandy' ); ?></label>
1144 </div>
1145 <div class="wpsc-date-range">
1146 <div class="wpsc-input-close-group">
1147 <input type="text" id="from-date-range" name="from-date-range" value="" autocomplete="off"/>
1148 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1149 </div>
1150 <div style="margin:5px;"></div>
1151 <div class="wpsc-input-close-group">
1152 <input type="text" id="to-date-range" name="to-date-range" value="" autocomplete="off"/>
1153 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1154 </div>
1155 </div>
1156 <script>
1157 jQuery('#from-date-range').flatpickr({
1158 disableMobile: true,
1159 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1160 });
1161 jQuery('#from-date-range').change(function() {
1162 var fromDate = jQuery(this).val().trim();
1163 jQuery('#to-date-range').flatpickr( {
1164 minDate: fromDate,
1165 defaultDate: fromDate,
1166 disableMobile: true,
1167 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1168 });
1169 });
1170 </script>
1171 </div>
1172
1173 <div data-type="date-format" data-required="false" class="wpsc-input-group date-format">
1174 <div class="label-container">
1175 <label for=""><?php esc_attr_e( 'Date format', 'supportcandy' ); ?></label>
1176 </div>
1177 <input type="text" name="date_format" autocomplete="off" />
1178 </div>
1179 <?php
1180
1181 if ( in_array( 'tl_width', $field_class::$allowed_properties ) ) :
1182 ?>
1183 <div data-type="number" data-required="false" class="wpsc-input-group tl_width">
1184 <div class="label-container">
1185 <label for="">
1186 <?php esc_attr_e( 'Ticket list width (pixels)', 'supportcandy' ); ?>
1187 </label>
1188 </div>
1189 <input type="number" name="tl_width" autocomplete="off">
1190 </div>
1191 <?php
1192 endif;
1193
1194 if ( in_array( 'is_personal_info', $field_class::$allowed_properties ) ) :
1195 ?>
1196 <div data-type="single-select" data-required="false" class="wpsc-input-group is_personal_info">
1197 <div class="label-container">
1198 <label for="">
1199 <?php esc_attr_e( 'Has personal info', 'supportcandy' ); ?>
1200 </label>
1201 </div>
1202 <select name="is_personal_info">
1203 <option value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1204 <option value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1205 </select>
1206 </div>
1207 <?php
1208 endif;
1209
1210 if ( in_array( 'allow_my_profile', $field_class::$allowed_properties ) ) :
1211 ?>
1212 <div data-type="single-select" data-required="false" class="wpsc-input-group allow_my_profile">
1213 <div class="label-container">
1214 <label for="">
1215 <?php esc_attr_e( 'Allow in my profile?', 'supportcandy' ); ?>
1216 </label>
1217 </div>
1218 <select name="allow_my_profile">
1219 <option value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1220 <option value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1221 </select>
1222 </div>
1223 <?php
1224 endif;
1225
1226 if ( in_array( 'allow_ticket_form', $field_class::$allowed_properties ) ) :
1227 ?>
1228 <div data-type="single-select" data-required="false" class="wpsc-input-group allow_ticket_form">
1229 <div class="label-container">
1230 <label for="">
1231 <?php esc_attr_e( 'Allow in ticket form?', 'supportcandy' ); ?>
1232 </label>
1233 </div>
1234 <select name="allow_ticket_form">
1235 <option value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1236 <option value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1237 </select>
1238 </div>
1239 <?php
1240 endif;
1241 }
1242
1243 /**
1244 * Print edit custom field properties
1245 *
1246 * @param WPSC_Custom_Fields $cf - custom field object.
1247 * @param string $field_class - class name of field category.
1248 * @return void
1249 */
1250 public static function get_edit_custom_field_properties( $cf, $field_class ) {
1251
1252 if ( in_array( 'extra_info', $field_class::$allowed_properties ) ) :
1253 ?>
1254 <div data-type="textfield" data-required="false" class="wpsc-input-group extra-info">
1255 <div class="label-container">
1256 <label for=""><?php esc_attr_e( 'Extra info', 'supportcandy' ); ?></label>
1257 </div>
1258 <input name="extra_info" type="text" value="<?php echo esc_attr( $cf->extra_info ); ?>" autocomplete="off" />
1259 </div>
1260 <?php
1261 endif;
1262
1263 if ( in_array( 'default_value', $field_class::$allowed_properties ) ) :
1264 $default_val = $cf->default_value ? $cf->default_value[0] : '';
1265 ?>
1266 <div data-type="textfield" data-required="false" class="wpsc-input-group default_value">
1267 <div class="label-container">
1268 <label for="">
1269 <?php esc_attr_e( 'Default value', 'supportcandy' ); ?>
1270 </label>
1271 </div>
1272 <div class="wpsc-input-close-group">
1273 <input type="text" id="wpsc-default-val-date" name="default_value" value="<?php echo esc_attr( $default_val ); ?>" autocomplete="off"/>
1274 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1275 </div>
1276 <script>
1277 jQuery("#wpsc-default-val-date").flatpickr({
1278 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1279 });
1280 </script>
1281 </div>
1282 <?php
1283 endif;
1284
1285 if ( in_array( 'is_auto_fill', $field_class::$allowed_properties ) ) :
1286 ?>
1287 <div data-type="single-select" data-required="false" class="wpsc-input-group is_auto_fill">
1288 <div class="label-container">
1289 <label for="">
1290 <?php esc_attr_e( 'Auto-fill in ticket form', 'supportcandy' ); ?>
1291 </label>
1292 </div>
1293 <select name="is_auto_fill">
1294 <option <?php selected( $cf->is_auto_fill, '0' ); ?> value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1295 <option <?php selected( $cf->is_auto_fill, '1' ); ?> value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1296 </select>
1297 </div>
1298 <?php
1299 endif;
1300
1301 if ( in_array( 'placeholder_text', $field_class::$allowed_properties ) ) :
1302 ?>
1303 <div data-type="textfield" data-required="false" class="wpsc-input-group placeholder_text">
1304 <div class="label-container">
1305 <label for="">
1306 <?php esc_attr_e( 'Placeholder', 'supportcandy' ); ?>
1307 </label>
1308 </div>
1309 <input type="text" name="placeholder_text" value="<?php echo esc_attr( $cf->placeholder_text ); ?>" autocomplete="off">
1310 </div>
1311 <?php
1312 endif;
1313 ?>
1314
1315 <div data-type="single-select" data-required="false" class="wpsc-input-group date-range">
1316 <div class="label-container">
1317 <label for=""><?php esc_attr_e( 'Date range', 'supportcandy' ); ?></label>
1318 </div>
1319 <select id="wpsc-date-range" name="date_range">
1320 <option <?php selected( $cf->date_range, 'all' ); ?> value="all"><?php esc_attr_e( 'All', 'supportcandy' ); ?></option>
1321 <option <?php selected( $cf->date_range, 'future' ); ?> value="future"><?php esc_attr_e( 'Future', 'supportcandy' ); ?></option>
1322 <option <?php selected( $cf->date_range, 'past' ); ?> value="past"><?php esc_attr_e( 'Past', 'supportcandy' ); ?></option>
1323 <option <?php selected( $cf->date_range, 'range' ); ?> value="range"><?php esc_attr_e( 'Between', 'supportcandy' ); ?></option>
1324 </select>
1325 <script>
1326 jQuery('#wpsc-date-range').change(function() {
1327 if (jQuery(this).val() == 'range') {
1328 jQuery('.wpsc-date-range-option').show();
1329 } else {
1330 jQuery('.wpsc-date-range-option').hide();
1331 }
1332 });
1333 </script>
1334 </div>
1335
1336 <div data-type="date-select" data-required="false" class="wpsc-input-group wpsc-date-range-option" style="<?php echo $cf->date_range != 'range' ? 'display:none;' : ''; ?>">
1337 <div class="label-container">
1338 <label for=""><?php esc_attr_e( 'Date in between', 'supportcandy' ); ?></label>
1339 </div>
1340 <div class="wpsc-date-range">
1341 <div class="wpsc-input-close-group">
1342 <input type="text" id="from-date-range" name="from-date-range" value="<?php echo $cf->start_range && is_object( $cf->start_range ) ? esc_attr( $cf->start_range->format( 'Y-m-d' ) ) : ''; ?>" autocomplete="off"/>
1343 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1344 </div>
1345 <div style="margin:5px;"></div>
1346 <div class="wpsc-input-close-group">
1347 <input type="text" id="to-date-range" name="to-date-range" value="<?php echo $cf->end_range && is_object( $cf->end_range ) ? esc_attr( $cf->end_range->format( 'Y-m-d' ) ) : ''; ?>" autocomplete="off"/>
1348 <span onclick="wpsc_clear_date(this);"><?php WPSC_Icons::get( 'times' ); ?></span>
1349 </div>
1350 </div>
1351 <script>
1352 jQuery('#from-date-range').flatpickr({
1353 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1354 });
1355 jQuery('#to-date-range').flatpickr({
1356 locale: "<?php echo esc_attr( WPSC_Functions::get_locale_iso() ); ?>",
1357 });
1358 jQuery('#from-date-range').change(function() {
1359 var fromDate = jQuery(this).val().trim();
1360 jQuery('#to-date-range').flatpickr( {
1361 minDate: fromDate,
1362 defaultDate: fromDate,
1363 });
1364 });
1365 </script>
1366 </div>
1367
1368 <div data-type="date-format" data-required="false" class="wpsc-input-group date-format">
1369 <div class="label-container">
1370 <label for=""><?php esc_attr_e( 'Date format', 'supportcandy' ); ?></label>
1371 </div>
1372 <input type="text" name="date_format" value="<?php echo esc_attr( $cf->date_format ); ?>" autocomplete="off" />
1373 </div>
1374 <?php
1375
1376 if ( in_array( 'tl_width', $field_class::$allowed_properties ) ) :
1377 ?>
1378 <div data-type="number" data-required="false" class="wpsc-input-group tl_width">
1379 <div class="label-container">
1380 <label for="">
1381 <?php esc_attr_e( 'Ticket list width (pixels)', 'supportcandy' ); ?>
1382 </label>
1383 </div>
1384 <input type="number" name="tl_width" value="<?php echo intval( $cf->tl_width ); ?>" autocomplete="off">
1385 </div>
1386 <?php
1387 endif;
1388
1389 if ( in_array( 'is_personal_info', $field_class::$allowed_properties ) ) :
1390 ?>
1391 <div data-type="single-select" data-required="false" class="wpsc-input-group is_personal_info">
1392 <div class="label-container">
1393 <label for="">
1394 <?php esc_attr_e( 'Has personal info', 'supportcandy' ); ?>
1395 </label>
1396 </div>
1397 <select name="is_personal_info">
1398 <option <?php selected( $cf->is_personal_info, '0' ); ?> value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1399 <option <?php selected( $cf->is_personal_info, '1' ); ?> value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1400 </select>
1401 </div>
1402 <?php
1403 endif;
1404
1405 if ( in_array( 'allow_my_profile', $field_class::$allowed_properties ) ) :
1406 ?>
1407 <div data-type="single-select" data-required="false" class="wpsc-input-group allow_my_profile">
1408 <div class="label-container">
1409 <label for="">
1410 <?php esc_attr_e( 'Allow in my profile?', 'supportcandy' ); ?>
1411 </label>
1412 </div>
1413 <select name="allow_my_profile">
1414 <option <?php selected( $cf->allow_my_profile, 0 ); ?> value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1415 <option <?php selected( $cf->allow_my_profile, 1 ); ?> value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1416 </select>
1417 </div>
1418 <?php
1419 endif;
1420
1421 if ( in_array( 'allow_ticket_form', $field_class::$allowed_properties ) ) :
1422 ?>
1423 <div data-type="single-select" data-required="false" class="wpsc-input-group allow_ticket_form">
1424 <div class="label-container">
1425 <label for="">
1426 <?php esc_attr_e( 'Allow in ticket form?', 'supportcandy' ); ?>
1427 </label>
1428 </div>
1429 <select name="allow_ticket_form">
1430 <option <?php selected( $cf->allow_ticket_form, 0 ); ?> value="0"><?php esc_attr_e( 'No', 'supportcandy' ); ?></option>
1431 <option <?php selected( $cf->allow_ticket_form, 1 ); ?> value="1"><?php esc_attr_e( 'Yes', 'supportcandy' ); ?></option>
1432 </select>
1433 </div>
1434 <?php
1435 endif;
1436 }
1437
1438 /**
1439 * Set custom field properties. Can be used by add/edit custom field.
1440 * Ignore phpcs nonce issue as we already checked where it is called from.
1441 *
1442 * @param WPSC_Custom_Field $cf - custom field object.
1443 * @param string $field_class - class of field category.
1444 * @return void
1445 */
1446 public static function set_cf_properties( $cf, $field_class ) {
1447
1448 // extra info.
1449 if ( in_array( 'extra_info', $field_class::$allowed_properties ) ) {
1450 $cf->extra_info = isset( $_POST['extra_info'] ) ? sanitize_text_field( wp_unslash( $_POST['extra_info'] ) ) : ''; // phpcs:ignore
1451 }
1452
1453 // default value.
1454 if ( in_array( 'default_value', $field_class::$allowed_properties ) ) {
1455 $default_value = isset( $_POST['default_value'] ) ? sanitize_text_field( wp_unslash( $_POST['default_value'] ) ) : ''; // phpcs:ignore
1456 $cf->default_value = $default_value ? array( $default_value ) : array();
1457 }
1458
1459 // auto fill.
1460 if ( in_array( 'is_auto_fill', $field_class::$allowed_properties ) ) {
1461 $cf->is_auto_fill = isset( $_POST['is_auto_fill'] ) ? sanitize_text_field( wp_unslash( $_POST['is_auto_fill'] ) ) : ''; // phpcs:ignore
1462 }
1463
1464 // placeholder!
1465 if ( in_array( 'placeholder_text', $field_class::$allowed_properties ) ) {
1466 $cf->placeholder_text = isset( $_POST['placeholder_text'] ) ? sanitize_text_field( wp_unslash( $_POST['placeholder_text'] ) ) : ''; // phpcs:ignore
1467 }
1468
1469 // date range.
1470 $cf->date_range = isset( $_POST['date_range'] ) ? sanitize_text_field( wp_unslash( $_POST['date_range'] ) ) : 'all'; // phpcs:ignore
1471
1472 // date range in between.
1473 $cf->start_range = isset( $_POST['from-date-range'] ) ? new DateTime( sanitize_text_field( wp_unslash( $_POST['from-date-range'] ) ) ) : ''; // phpcs:ignore
1474 $cf->end_range = isset( $_POST['to-date-range'] ) && $cf->start_range ? new DateTime( sanitize_text_field( wp_unslash( $_POST['to-date-range'] ) ) ) : ''; //phpcs:ignore
1475
1476 // date format.
1477 $cf->date_format = isset( $_POST['date_format'] ) ? sanitize_text_field( wp_unslash( $_POST['date_format'] ) ) : ''; // phpcs:ignore
1478
1479 // personal info.
1480 if ( in_array( 'is_personal_info', $field_class::$allowed_properties ) ) {
1481 $cf->is_personal_info = isset( $_POST['is_personal_info'] ) ? intval( $_POST['is_personal_info'] ) : 0; // phpcs:ignore
1482 }
1483
1484 // my-profile..
1485 if ( in_array( 'allow_my_profile', $field_class::$allowed_properties ) ) {
1486 $cf->allow_my_profile = isset( $_POST['allow_my_profile'] ) ? intval( $_POST['allow_my_profile'] ) : 0; // phpcs:ignore
1487 }
1488
1489 // ticket form..
1490 if ( in_array( 'allow_ticket_form', $field_class::$allowed_properties ) ) {
1491 $cf->allow_ticket_form = isset( $_POST['allow_ticket_form'] ) ? intval( $_POST['allow_ticket_form'] ) : 0; // phpcs:ignore
1492 }
1493
1494 // tl_width!
1495 if ( in_array( 'tl_width', $field_class::$allowed_properties ) ) {
1496 $tl_width = isset( $_POST['tl_width'] ) ? intval( $_POST['tl_width'] ) : 0; // phpcs:ignore
1497 $cf->tl_width = $tl_width ? $tl_width : 100;
1498 }
1499
1500 // save!
1501 $cf->save();
1502 }
1503
1504 /**
1505 * Returns printable ticket value for custom field. Can be used in export tickets, replace macros etc.
1506 *
1507 * @param WPSC_Custom_Field $cf - custom field object.
1508 * @param WPSC_Ticket $ticket - ticket object.
1509 * @param string $module - module name.
1510 * @return string
1511 */
1512 public static function get_ticket_field_val( $cf, $ticket, $module = '' ) {
1513
1514 if ( ! is_object( $ticket->{$cf->slug} ) ) {
1515 return '';
1516 }
1517
1518 $gs = get_option( 'wpsc-gs-general' );
1519 $format = $cf->date_format ? $cf->date_format : $gs['default-date-format'];
1520 $value = date_i18n( $format, $ticket->{$cf->slug}->getTimestamp(), false );
1521
1522 return apply_filters( 'wpsc_ticket_field_val_date', $value, $cf, $ticket, $module );
1523 }
1524
1525 /**
1526 * Print ticket value for given custom field on ticket list
1527 *
1528 * @param WPSC_Custom_Field $cf - custom field object.
1529 * @param WPSC_Ticket $ticket - ticket object.
1530 * @return void
1531 */
1532 public static function print_tl_ticket_field_val( $cf, $ticket ) {
1533
1534 echo esc_attr( self::get_ticket_field_val( $cf, $ticket ) );
1535 }
1536
1537 /**
1538 * Print ticket value for given custom field on widget
1539 *
1540 * @param WPSC_Custom_Field $cf - custom field object.
1541 * @param WPSC_Ticket $ticket - ticket object.
1542 * @return void
1543 */
1544 public static function print_widget_ticket_field_val( $cf, $ticket ) {
1545
1546 echo esc_attr( self::get_ticket_field_val( $cf, $ticket ) );
1547 }
1548
1549 /**
1550 * Returns printable customer value for custom field. Can be used in export tickets, replace macros etc.
1551 *
1552 * @param WPSC_Custom_Field $cf - custom field object.
1553 * @param WPSC_Customer $customer - customer object.
1554 * @return string
1555 */
1556 public static function get_customer_field_val( $cf, $customer ) {
1557
1558 if ( ! is_object( $customer->{$cf->slug} ) ) {
1559 return '';
1560 }
1561
1562 $gs = get_option( 'wpsc-gs-general' );
1563 $format = $cf->date_format ? $cf->date_format : $gs['default-date-format'];
1564 return date_i18n( $format, $customer->{$cf->slug}->getTimestamp(), false );
1565 }
1566
1567 /**
1568 * Print customer value for given custom field on ticket list
1569 *
1570 * @param WPSC_Custom_Field $cf - custom field object.
1571 * @param WPSC_Customer $customer - customer object.
1572 * @return void
1573 */
1574 public static function print_tl_customer_field_val( $cf, $customer ) {
1575
1576 echo esc_attr( self::get_customer_field_val( $cf, $customer ) );
1577 }
1578
1579 /**
1580 * Print customer value for given custom field on widget
1581 *
1582 * @param WPSC_Custom_Field $cf - custom field object.
1583 * @param WPSC_Customer $customer - customer object.
1584 * @return void
1585 */
1586 public static function print_widget_customer_field_val( $cf, $customer ) {
1587
1588 echo esc_attr( self::get_customer_field_val( $cf, $customer ) );
1589 }
1590
1591 /**
1592 * Print given value for custom field
1593 *
1594 * @param WPSC_Custom_Field $cf - custom field object.
1595 * @param mixed $val - value to convert and print.
1596 * @return void
1597 */
1598 public static function print_val( $cf, $val ) {
1599
1600 if ( ! $val || $val == '0000-00-00 00:00:00' ) {
1601 esc_attr_e( 'None', 'supportcandy' );
1602 return;
1603 }
1604
1605 $gs = get_option( 'wpsc-gs-general' );
1606 $format = $cf->date_format ? $cf->date_format : $gs['default-date-format'];
1607 $val = is_object( $val ) ? $val : new DateTime( $val );
1608 echo esc_attr( date_i18n( $format, $val->getTimestamp(), false ) );
1609 }
1610
1611 /**
1612 * Return printable value for history log macro
1613 *
1614 * @param WPSC_Custom_Field $cf - custom field object.
1615 * @param mixed $val - value to convert and return.
1616 * @return string
1617 */
1618 public static function get_history_log_val( $cf, $val ) {
1619
1620 ob_start();
1621 self::print_val( $cf, $val );
1622 return ob_get_clean();
1623 }
1624
1625 /**
1626 * Print dashboard activity function
1627 *
1628 * @param WPSC_Custom_Field $cf - custom field object.
1629 * @param array $recent_logs - recent_logs object.
1630 * @param array $body - body object.
1631 * @param int $view - check if frontend.
1632 * @return string
1633 */
1634 public static function print_activity( $cf, $recent_logs, $body, $view ) {
1635
1636 $url = WPSC_Functions::get_ticket_url( $recent_logs->ticket->id, $view );
1637 $gs = get_option( 'wpsc-gs-general' );
1638 $format = $cf->date_format ? $cf->date_format : $gs['default-date-format'];
1639
1640 $new_val = new DateTime( $body->new );
1641 if ( $body->new ) {
1642 $log = date_i18n( $format, $new_val->getTimestamp() );
1643 } else {
1644 $log = 'None';
1645 }
1646 return esc_attr( $recent_logs->customer->name ) . ' updated the ' . esc_attr( $cf->name ) . ' value of <a href="' . esc_attr( $url ) . '" target="_blank">#' . esc_attr( $recent_logs->ticket->id ) . '</a> to ' . esc_attr( $log );
1647 }
1648
1649 /**
1650 * Return given value for custom field
1651 *
1652 * @param WPSC_Custom_Field $cf - custom field object.
1653 * @param mixed $val - value to convert and print.
1654 * @return void
1655 */
1656 public static function get_field_value( $cf, $val ) {
1657
1658 if ( ! $val || $val == '0000-00-00 00:00:00' ) {
1659 esc_attr_e( 'None', 'supportcandy' );
1660 return;
1661 }
1662
1663 $gs = get_option( 'wpsc-gs-general' );
1664 $format = $cf->date_format ? $cf->date_format : $gs['default-date-format'];
1665 $val = is_object( $val ) ? $val : new DateTime( $val );
1666 return esc_attr( date_i18n( $format, $val->getTimestamp(), false ) );
1667 }
1668
1669 /**
1670 * Clear value of hidden fields
1671 *
1672 * @return void
1673 */
1674 public static function js_clear_value_hidden_fields() {
1675 ?>
1676 case '<?php echo esc_attr( self::$slug ); ?>':
1677 customField.find('input').first().val('');
1678 break;
1679 <?php
1680 echo PHP_EOL;
1681 }
1682 }
1683 endif;
1684
1685 WPSC_CF_Date::init();
1686