PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.5.4
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.5.4
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 / admin / customers / class-wpsc-customers.php

class-wpsc-customers.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent 3.5.4, at includes/admin/customers/class-wpsc-customers.php

1,292 lines 41.0 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_Customers' ) ) :
7
8 final class WPSC_Customers {
9
10 /**
11 * Initialize the class
12 *
13 * @return void
14 */
15 public static function init() {
16
17 // get customer list.
18 add_action( 'wp_ajax_wpsc_get_customer_list', array( __CLASS__, 'get_customer_list' ) );
19
20 // view customer info.
21 add_action( 'wp_ajax_wpsc_view_customer_info', array( __CLASS__, 'view_customer_info' ) );
22
23 // edit customer info.
24 add_action( 'wp_ajax_wpsc_get_edit_customer_info', array( __CLASS__, 'get_edit_customer_info' ) );
25 add_action( 'wp_ajax_wpsc_set_edit_customer_info', array( __CLASS__, 'set_edit_customer_info' ) );
26
27 // view customer logs.
28 add_action( 'wp_ajax_wpsc_view_customer_logs', array( __CLASS__, 'view_customer_logs' ) );
29
30 // delete customer logs.
31 add_action( 'wp_ajax_wpsc_delete_customer', array( __CLASS__, 'delete_customer_info' ) );
32
33 // calculate customer ticket count.
34 add_action( 'wpsc_create_new_ticket', array( __CLASS__, 'customer_ticket_count' ), 500 );
35 add_action( 'wpsc_delete_ticket', array( __CLASS__, 'customer_ticket_count' ), 500 );
36 add_action( 'wpsc_ticket_restore', array( __CLASS__, 'customer_ticket_count' ), 500 );
37 add_action( 'wpsc_ticket_delete_permanently', array( __CLASS__, 'customer_ticket_count' ), 500 );
38 add_action( 'wpsc_change_raised_by', array( __CLASS__, 'customer_ticket_count_after_change_raised_by' ), 500, 4 );
39 add_action( 'wpsc_ticket_archive', array( __CLASS__, 'reset_customer_ticket_count' ), 500, 2 );
40 add_action( 'wpsc_archive_ticket_restore', array( __CLASS__, 'reset_customer_ticket_count' ), 500, 2 );
41 add_action( 'wpsc_after_ticket_merge', array( __CLASS__, 'customer_ticket_count_after_ticket_merge' ), 500, 2 );
42
43 // view customer profile info.
44 add_action( 'wp_ajax_wpsc_view_customer_detailed_info', array( __CLASS__, 'view_customer_detailed_info' ) );
45
46 // Get customer recent activities.
47 add_action( 'wp_ajax_wpsc_upw_get_recent_activities', array( __CLASS__, 'get_upw_recent_activities' ) );
48 add_action( 'wp_ajax_nopriv_wpsc_upw_get_recent_activities', array( __CLASS__, 'get_upw_recent_activities' ) );
49 }
50
51 /**
52 * Admin submenu layout
53 *
54 * @return void
55 */
56 public static function layout() {
57
58 $types = apply_filters(
59 'wpsc_customer_type_filter',
60 array(
61 'all' => esc_attr__( 'All Users', 'supportcandy' ),
62 'customer_with_tickets' => esc_attr__( 'Users has tickets', 'supportcandy' ),
63 )
64 );
65
66 ?>
67 <div class="wrap">
68 <hr class="wp-header-end">
69 <div id="wpsc-container">
70 <div class="wpsc-setting-header">
71 <h2><?php esc_attr_e( 'Customers', 'supportcandy' ); ?></h2>
72 </div>
73 <div class="wpsc-setting-section-body">
74 <div class="wpsc-customers-toolbar">
75
76 <div class="wpsc-customers-toolbar-item">
77 <label><?php esc_attr_e( 'Users', 'supportcandy' ); ?></label>
78 <select name="wpsc-cust-list-filter" id="wpsc-cust-list-filter">
79 <?php foreach ( $types as $key => $type ) : ?>
80 <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $key, 'customer_with_tickets' ); ?>><?php echo esc_attr( $type ); ?></option>
81 <?php endforeach; ?>
82 </select>
83 </div>
84
85 <div class="wpsc-customers-toolbar-item">
86 <label><?php esc_attr_e( 'User Type', 'supportcandy' ); ?></label>
87 <select id="wpsc-cust-type-filter">
88 <option value="all"><?php esc_attr_e( 'All types', 'supportcandy' ); ?></option>
89 <option value="registered"><?php esc_attr_e( 'Registered', 'supportcandy' ); ?></option>
90 <option value="guest"><?php esc_attr_e( 'Guest', 'supportcandy' ); ?></option>
91 </select>
92 </div>
93
94 <div class="wpsc-customers-toolbar-item wpsc-customers-toolbar-search">
95 <label><?php esc_attr_e( 'Search', 'supportcandy' ); ?></label>
96 <input type="text" id="wpsc-cust-filter-search" autocomplete="off" placeholder="<?php esc_attr_e( 'Search...', 'supportcandy' ); ?>">
97 </div>
98
99 <div class="wpsc-customers-toolbar-item wpsc-customers-toolbar-reset">
100 <button type="button" class="wpsc-button normal secondary" id="wpsc-cust-reset-filter">
101 <?php esc_attr_e( 'Reset', 'supportcandy' ); ?>
102 </button>
103 </div>
104
105 </div>
106 <?php
107 self::load_customer_list();
108 WPSC_Tickets::load_html_snippets();
109 ?>
110 </div>
111 </div>
112 </div>
113 <?php
114 }
115
116 /**
117 * List customer list
118 *
119 * @return void
120 */
121 public static function load_customer_list() {
122
123 ?>
124 <div id="wpsc-customer-list">
125 <table class="wpsc_customer_list wpsc-setting-tbl">
126 <thead>
127 <tr>
128 <th><?php esc_attr_e( 'Name', 'supportcandy' ); ?></th>
129 <th><?php esc_attr_e( 'Email address', 'supportcandy' ); ?></th>
130 <th><?php esc_attr_e( 'User Type', 'supportcandy' ); ?></th>
131 <th><?php esc_attr_e( 'Number of tickets', 'supportcandy' ); ?></th>
132 <th><?php esc_attr_e( 'Actions', 'supportcandy' ); ?></th>
133 </tr>
134 </thead>
135 </table>
136 </div>
137 <script>
138 function load_customer_list(custType, userType) {
139
140 jQuery('.wpsc_customer_list').dataTable({
141 processing: true,
142 serverSide: true,
143 serverMethod: 'post',
144 ajax: {
145 url: supportcandy.ajax_url,
146 data: {
147 'action': 'wpsc_get_customer_list',
148 'cust_type': custType,
149 'user_type': userType,
150 '_ajax_nonce': '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_customer_list' ) ); ?>'
151 }
152 },
153 'columns': [
154 { data: 'name' },
155 { data: 'email' },
156 { data: 'type' },
157 { data: 'tickets' },
158 { data: 'actions' },
159 ],
160 'bDestroy': true,
161 'searching': true,
162 'ordering': true,
163 order: [[ 3, 'desc' ]],
164 'bLengthChange': false,
165 pageLength: 20,
166 columnDefs: [
167 { targets: '_all', className: 'dt-left' },
168 { targets: [ 0, 1, 2, 4 ], orderable: false },
169 ],
170 language: supportcandy.translations.datatables
171 });
172 }
173
174 jQuery(document).ready(function() {
175
176 jQuery('#wpsc-cust-list-filter').selectWoo({ minimumResultsForSearch: 0, width: '100%' });
177 jQuery('#wpsc-cust-type-filter').selectWoo({ minimumResultsForSearch: 0, width: '100%' });
178
179 load_customer_list('customer_with_tickets', 'all');
180
181 jQuery('#wpsc-cust-filter-search').on('keyup', function() {
182 var searchTerm = jQuery(this).val();
183 jQuery('table.wpsc_customer_list').DataTable().search(searchTerm).draw();
184 });
185
186 jQuery('#wpsc-cust-list-filter, #wpsc-cust-type-filter').on('change', function(){
187 load_customer_list( jQuery('#wpsc-cust-list-filter').val(), jQuery('#wpsc-cust-type-filter').val() );
188 });
189
190 jQuery('#wpsc-cust-reset-filter').on('click', function() {
191 jQuery('#wpsc-cust-list-filter').val('customer_with_tickets').trigger('change.select2');
192 jQuery('#wpsc-cust-type-filter').val('all').trigger('change.select2');
193 jQuery('#wpsc-cust-filter-search').val('');
194 load_customer_list('customer_with_tickets', 'all');
195 });
196 });
197
198 <?php do_action( 'wpsc_js_customer_list_functions' ); ?>
199 </script>
200 <?php
201 }
202
203 /**
204 * Get list of all customers
205 *
206 * @return void
207 */
208 public static function get_customer_list() {
209
210 if ( check_ajax_referer( 'wpsc_get_customer_list', '_ajax_nonce', false ) != 1 ) {
211 wp_send_json_error( 'Unauthorized request!', 401 );
212 }
213
214 if ( ! WPSC_Functions::is_site_admin() ) {
215 wp_send_json_error( 'Unauthorized request!', 401 );
216 }
217
218 $search = isset( $_POST['search'] ) && isset( $_POST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_POST['search']['value'] ) ) : '';
219 $draw = isset( $_POST['draw'] ) ? intval( $_POST['draw'] ) : 1;
220 $start = isset( $_POST['start'] ) ? intval( $_POST['start'] ) : 1;
221 $rowperpage = isset( $_POST['length'] ) ? intval( $_POST['length'] ) : 20;
222 $page_no = ( $start / $rowperpage ) + 1;
223 $cust_type = isset( $_POST['cust_type'] ) ? sanitize_text_field( wp_unslash( $_POST['cust_type'] ) ) : 'customer_with_tickets';
224
225 $user_type = isset( $_POST['user_type'] ) ? sanitize_text_field( wp_unslash( $_POST['user_type'] ) ) : 'all';
226 if ( ! in_array( $user_type, array( 'all', 'guest', 'registered' ), true ) ) {
227 $user_type = 'all';
228 }
229
230 // Whitelisted map of sortable DataTables column index to actual DB column - only
231 // "Number of tickets" is backed by a real, sortable query column.
232 $sortable_columns = array(
233 3 => 'ticket_count',
234 );
235
236 $orderby = 'ticket_count';
237 $order = 'DESC';
238
239 if ( isset( $_POST['order'][0]['column'] ) ) {
240 $order_column = intval( $_POST['order'][0]['column'] );
241 if ( isset( $sortable_columns[ $order_column ] ) ) {
242 $orderby = $sortable_columns[ $order_column ];
243 }
244 }
245
246 if ( isset( $_POST['order'][0]['dir'] ) && 'asc' === strtolower( sanitize_text_field( wp_unslash( $_POST['order'][0]['dir'] ) ) ) ) {
247 $order = 'ASC';
248 }
249
250 $args = array(
251 'search' => $search,
252 'items_per_page' => $rowperpage,
253 'page_no' => $page_no,
254 'orderby' => $orderby,
255 'order' => $order,
256 'meta_query' => array(
257 'relation' => 'AND',
258 ),
259 );
260
261 if ( $cust_type == 'customer_with_tickets' ) {
262
263 $args['meta_query'][] = array(
264 'slug' => 'ticket_count',
265 'compare' => '>',
266 'val' => 0,
267 );
268 }
269
270 if ( $cust_type == 'all' ) {
271
272 $args['meta_query'][] = array();
273 }
274
275 if ( 'guest' === $user_type ) {
276 $args['meta_query'][] = array(
277 'slug' => 'user',
278 'compare' => '=',
279 'val' => 0,
280 );
281 } elseif ( 'registered' === $user_type ) {
282 $args['meta_query'][] = array(
283 'slug' => 'user',
284 'compare' => '>',
285 'val' => 0,
286 );
287 }
288
289 $args = apply_filters( 'wpsc_get_customer_list_filters', $args, $cust_type );
290 $response = WPSC_Customer::find( $args );
291
292 $customers = $response['results'];
293
294 $data = array();
295 foreach ( $customers as $customer ) {
296
297 $agent = WPSC_Agent::get_by_customer( $customer );
298 ob_start();
299 ?>
300 <span class="wpsc-link" onclick="wpsc_view_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_info' ) ); ?>')">
301 <?php esc_attr_e( 'View', 'supportcandy' ); ?>
302 </span> |
303 <span class="wpsc-link" onclick="wpsc_get_edit_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_customer_info' ) ); ?>')">
304 <?php esc_attr_e( 'Edit', 'supportcandy' ); ?>
305 </span> |
306 <span class="wpsc-link" onclick="wpsc_view_customer_logs(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_logs' ) ); ?>')">
307 <?php esc_attr_e( 'Logs', 'supportcandy' ); ?>
308 </span>
309 <?php
310 if ( ! $agent->id || ( $agent->role != 1 ) ) {
311 ?>
312 | <span class="wpsc-link" onclick="wpsc_delete_customer(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer' ) ); ?>')">
313 <?php esc_attr_e( 'Delete', 'supportcandy' ); ?>
314 </span>
315 <?php
316 }
317 ?>
318 <?php
319 $actions = ob_get_clean();
320
321 $name_cell = '<div class="wpsc-cust-name-cell">
322 <div class="wpsc-cust-avatar">' . get_avatar( $customer->email, 28 ) . '</div>
323 <span class="wpsc-link" onclick="wpsc_view_customer_detailed_info( ' . $customer->id . ', \'' . wp_create_nonce( 'wpsc_view_customer_detailed_info' ) . '\' )">' . esc_html( $customer->name ) . '</span>
324 </div>';
325
326 $data[] = array(
327 'name' => $name_cell,
328 'email' => $customer->email,
329 'type' => ! is_object( $customer->user ) ? esc_attr__( 'Guest', 'supportcandy' ) : esc_attr__( 'Registered', 'supportcandy' ),
330 'tickets' => $customer->ticket_count,
331 'actions' => $actions,
332 );
333 }
334
335 $response = array(
336 'draw' => intval( $draw ),
337 'iTotalRecords' => $response['total_items'],
338 'iTotalDisplayRecords' => $response['total_items'],
339 'data' => $data,
340 );
341
342 wp_send_json( $response );
343 }
344
345 /**
346 * View customer info
347 *
348 * @return void
349 */
350 public static function view_customer_info() {
351
352 if ( check_ajax_referer( 'wpsc_view_customer_info', '_ajax_nonce', false ) != 1 ) {
353 wp_send_json_error( 'Unauthorized request!', 401 );
354 }
355
356 if ( ! WPSC_Functions::is_site_admin() ) {
357 wp_send_json_error( 'Unauthorized request!', 401 );
358 }
359
360 $customer_id = isset( $_POST['customer_id'] ) ? intval( $_POST['customer_id'] ) : 0;
361 if ( ! $customer_id ) {
362 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
363 }
364
365 $customer = new WPSC_Customer( $customer_id );
366 if ( ! $customer->id ) {
367 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
368 }
369
370 $title = esc_attr__( 'Customer info', 'supportcandy' );
371 $unique_id = uniqid();
372
373 ob_start();
374 ?>
375 <div class="wpsc-thread-info">
376
377 <div style="width: 100%;">
378 <table class="wpsc-setting-tbl <?php echo esc_attr( $unique_id ); ?>" style="margin-bottom: 15px;">
379 <thead>
380 <tr>
381 <th><?php esc_attr_e( 'Field', 'supportcandy' ); ?></th>
382 <th><?php esc_attr_e( 'Value', 'supportcandy' ); ?></th>
383 </tr>
384 </thead>
385 <tbody>
386 <tr>
387 <td><?php esc_attr_e( 'Name', 'supportcandy' ); ?>:</td>
388 <td><?php echo esc_attr( $customer->name ); ?></td>
389 </tr>
390 <tr>
391 <td><?php esc_attr_e( 'Email Address', 'supportcandy' ); ?>:</td>
392 <td><?php echo esc_attr( $customer->email ); ?></td>
393 </tr>
394 <?php
395 foreach ( WPSC_Custom_Field::$custom_fields as $cf ) :
396 if ( $cf->field !== 'customer' || in_array( $cf->slug, WPSC_DF_Customer::$ignore_customer_info_cft ) ) {
397 continue;
398 }
399 ?>
400 <tr>
401 <td><?php echo esc_attr( $cf->name ); ?>:</td>
402 <td><?php $cf->type::print_widget_customer_field_val( $cf, $customer ); ?></td>
403 </tr>
404 <?php
405 endforeach;
406 ?>
407 </tbody>
408 </table>
409 <script>
410 jQuery('.<?php echo esc_attr( $unique_id ); ?>').DataTable({
411 searching: false,
412 paging: false,
413 ordering: false,
414 info: false
415 });
416 </script>
417 </div>
418 <?php do_action( 'wpsc_view_customer_info', $customer ); ?>
419 </div>
420 <?php
421 $body = ob_get_clean();
422
423 ob_start();
424
425 ?>
426 <button class="wpsc-button small primary" onclick="wpsc_get_edit_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_customer_info' ) ); ?>');">
427 <?php esc_attr_e( 'Edit Info', 'supportcandy' ); ?>
428 </button>
429 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
430 <?php esc_attr_e( 'Close', 'supportcandy' ); ?>
431 </button>
432 <?php
433 do_action( 'wpsc_view_customer_info_footer', $customer );
434 $footer = ob_get_clean();
435
436 $response = array(
437 'title' => $title,
438 'body' => $body,
439 'footer' => $footer,
440 );
441 wp_send_json( $response );
442 }
443
444 /**
445 * Get edit customer info
446 *
447 * @return void
448 */
449 public static function get_edit_customer_info() {
450
451 if ( check_ajax_referer( 'wpsc_get_edit_customer_info', '_ajax_nonce', false ) != 1 ) {
452 wp_send_json_error( 'Unauthorized request!', 401 );
453 }
454
455 if ( ! WPSC_Functions::is_site_admin() ) {
456 wp_send_json_error( 'Unauthorized request!', 401 );
457 }
458
459 $customer_id = isset( $_POST['customer_id'] ) ? intval( $_POST['customer_id'] ) : 0;
460 if ( ! $customer_id ) {
461 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
462 }
463
464 $customer = new WPSC_Customer( $customer_id );
465 if ( ! $customer->id ) {
466 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
467 }
468
469 $title = esc_attr__( 'Edit customer info', 'supportcandy' );
470 ob_start();
471 ?>
472 <form action="#" onsubmit="return false;" class="frm-edit-customer-info">
473 <?php
474
475 $cf = WPSC_Custom_Field::get_cf_by_slug( 'name' )
476 ?>
477 <div class="wpsc-tff">
478 <div class="wpsc-tff-label">
479 <span class="name"><?php echo esc_attr( $cf->name ); ?></span>
480 </div>
481 <span class="extra-info"><?php echo esc_attr( $cf->extra_info ); ?></span>
482 <input
483 type="text"
484 name="<?php echo esc_attr( $cf->slug ); ?>"
485 value="<?php echo esc_attr( $customer->name ); ?>"
486 placeholder="<?php echo esc_attr( $cf->placeholder_text ); ?>"
487 autocomplete="off"/>
488 </div>
489 <?php
490 foreach ( WPSC_Custom_Field::$custom_fields as $cf ) {
491 if ( $cf->field !== 'customer' || in_array( $cf->slug, WPSC_DF_Customer::$ignore_customer_info_cft ) ) {
492 continue;
493 }
494 $properties = array(
495 'is-required' => 0,
496 'width' => 'full',
497 'visibility' => '',
498 );
499 echo $cf->type::print_edit_customer_info( $cf, $customer, $properties ); // phpcs:ignore
500 }
501 do_action( 'wpsc_get_edit_customer_info_body', $customer );
502 ?>
503 <input type="hidden" name="action" value="wpsc_set_edit_customer_info"/>
504 <input type="hidden" name="id" value="<?php echo esc_attr( $customer->id ); ?>">
505 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_edit_customer_info' ) ); ?>">
506 </form>
507 <?php
508 do_action( 'wpsc_get_edit_customer_info_footer', $customer );
509 $body = ob_get_clean();
510
511 ob_start();
512 ?>
513 <button class="wpsc-button small primary" onclick="wpsc_set_edit_customer_info(this, <?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_info' ) ); ?>');">
514 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
515 </button>
516 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
517 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
518 </button>
519 <?php
520 $footer = ob_get_clean();
521
522 $response = array(
523 'title' => $title,
524 'body' => $body,
525 'footer' => $footer,
526 );
527 wp_send_json( $response );
528 }
529
530 /**
531 * Save customer info
532 *
533 * @return void
534 */
535 public static function set_edit_customer_info() {
536
537 if ( check_ajax_referer( 'wpsc_set_edit_customer_info', '_ajax_nonce', false ) != 1 ) {
538 wp_send_json_error( 'Unauthorized request!', 401 );
539 }
540
541 if ( ! WPSC_Functions::is_site_admin() ) {
542 wp_send_json_error( 'Unauthorized request!', 401 );
543 }
544
545 $customer_id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
546 if ( ! $customer_id ) {
547 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
548 }
549
550 $customer = new WPSC_Customer( $customer_id );
551 if ( ! $customer->id ) {
552 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
553 }
554
555 $name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
556 if ( ! $name ) {
557 wp_send_json_error( new WP_Error( '002', 'Bad request!' ), 400 );
558 }
559
560 if ( $customer->name != $name ) {
561 $customer->name = $name;
562 $customer->save();
563 // Update WP User if available.
564 if ( $customer->user ) {
565 wp_update_user(
566 array(
567 'ID' => $customer->user->ID,
568 'display_name' => $name,
569 )
570 );
571 }
572 }
573
574 $cfs = array();
575 foreach ( WPSC_Custom_Field::$custom_fields as $cf ) {
576
577 if ( $cf->field !== 'customer' || $cf->type::$is_default ) {
578 continue;
579 }
580 $cfs[ $cf->type::$slug ][] = $cf;
581 }
582
583 foreach ( $cfs as $slug => $fields ) {
584 WPSC_Functions::$ref_classes[ $slug ]['class']::set_create_ticket_data( array( 'customer' => $customer->id ), $cfs, true );
585 }
586 $response = array(
587 'customer_id' => $customer->id,
588 'nonce' => wp_create_nonce( 'wpsc_view_customer_detailed_info' ),
589 );
590 wp_send_json( $response );
591 }
592
593 /**
594 * View customer logs
595 *
596 * @return void
597 */
598 public static function view_customer_logs() {
599
600 if ( check_ajax_referer( 'wpsc_view_customer_logs', '_ajax_nonce', false ) != 1 ) {
601 wp_send_json_error( 'Unauthorized request!', 401 );
602 }
603
604 if ( ! WPSC_Functions::is_site_admin() ) {
605 wp_send_json_error( 'Unauthorized request!', 401 );
606 }
607
608 $customer_id = isset( $_POST['customer_id'] ) ? intval( $_POST['customer_id'] ) : 0;
609 if ( ! $customer_id ) {
610 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
611 }
612
613 $customer = new WPSC_Customer( $customer_id );
614 if ( ! $customer->id ) {
615 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
616 }
617
618 $title = esc_attr__( 'Customer logs', 'supportcandy' );
619 $unique_id = uniqid();
620
621 ob_start();
622 $logs = WPSC_Log::find(
623 array(
624 'meta_query' => array(
625 'relation' => 'AND',
626 array(
627 'slug' => 'type',
628 'compare' => '=',
629 'val' => 'customer',
630 ),
631 array(
632 'slug' => 'ref_id',
633 'compare' => '=',
634 'val' => $customer->id,
635 ),
636 ),
637 )
638 )['results'];
639 ?>
640 <div style="width: 100%;">
641 <?php
642 foreach ( $logs as $log ) {
643 self::print_log( $log );
644 }
645 ?>
646 </div>
647 <?php
648
649 do_action( 'wpsc_view_customer_info', $customer );
650
651 $body = ob_get_clean();
652
653 ob_start();
654 ?>
655 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
656 <?php esc_attr_e( 'Close', 'supportcandy' ); ?>
657 </button>
658 <?php
659 do_action( 'wpsc_view_customer_logs_footer', $customer );
660 $footer = ob_get_clean();
661
662 $response = array(
663 'title' => $title,
664 'body' => $body,
665 'footer' => $footer,
666 );
667 wp_send_json( $response );
668 }
669
670 /**
671 * Print customer log
672 *
673 * @param WPSC_Log $log - log object.
674 * @return void
675 */
676 public static function print_log( $log ) {
677
678 $advanced = get_option( 'wpsc-ms-advanced-settings', array() );
679 $now = new DateTime();
680 $date = $log->date_created->setTimezone( wp_timezone() );
681 $time_date_str = $date->format( $advanced['thread-date-format'] );
682 $time_diff_str = WPSC_Functions::date_interval_highest_unit_ago( $date->diff( $now ) );
683 $title = $advanced['thread-date-display-as'] == 'date' ? $time_diff_str : $time_date_str;
684 $time_str = $advanced['thread-date-display-as'] == 'date' ? $time_date_str : $time_diff_str;
685
686 $body = json_decode( $log->body );
687 $customer = new WPSC_Customer( $log->modified_by );
688
689 $cf = WPSC_Custom_Field::get_cf_by_slug( $body->slug );
690 if ( ! $cf ) {
691 return;
692 }
693 ?>
694 <div class="wpsc-thread log">
695 <div class="thread-avatar">
696 <?php
697 if ( $log->modified_by ) {
698 echo get_avatar( $customer->email, 32 );
699 } else {
700 WPSC_Icons::get( 'system' );
701 }
702 ?>
703 </div>
704 <div class="thread-body">
705 <div class="thread-header">
706 <div class="user-info">
707 <div>
708 <?php
709 if ( $log->modified_by ) {
710 printf(
711 /* translators: %1$s: User Name, %2$s: Field Name */
712 esc_attr__( '%1$s changed the %2$s', 'supportcandy' ),
713 '<strong>' . esc_attr( $customer->name ) . '</strong>',
714 '<strong>' . esc_attr( $cf->name ) . '</strong>'
715 );
716 } else {
717 printf(
718 /* translators: %1$s: Field Name */
719 esc_attr__( 'The %1$s has been changed', 'supportcandy' ),
720 '<strong>' . esc_attr( $cf->name ) . '</strong>'
721 );
722 }
723
724 ?>
725 </div>
726 <span class="thread-time" title="<?php echo esc_attr( $title ); ?>"><?php echo esc_attr( $time_str ); ?></span>
727 </div>
728 </div>
729 <div class="wpsc-log-diff">
730 <div class="lhs"><?php $cf->type::print_val( $cf, $body->prev ); ?></div>
731 <div class="transform-icon">
732 <?php
733 if ( is_rtl() ) {
734 WPSC_Icons::get( 'arrow-left' );
735 } else {
736 WPSC_Icons::get( 'arrow-right' );
737 }
738 ?>
739 </div>
740 <div class="rhs"><?php $cf->type::print_val( $cf, $body->new ); ?></div>
741 </div>
742 </div>
743 </div>
744 <?php
745 }
746
747 /**
748 * Count customer tickets after merge ticket
749 *
750 * @param WPSC_Ticket $prev_ticket - previous ticket object.
751 * @param WPSC_Ticket $new_ticket - new ticket object.
752 * @return void
753 */
754 public static function customer_ticket_count_after_ticket_merge( $prev_ticket, $new_ticket ) {
755
756 if ( ! $prev_ticket->customer ) {
757 return;
758 }
759
760 $customer = $prev_ticket->customer;
761
762 if ( ! is_object( $customer ) ) {
763 $customer = new WPSC_Customer( $customer );
764 }
765
766 if ( $customer->id ) {
767 $customer->update_ticket_count();
768 }
769 }
770
771 /**
772 * Count customer tickets after create/delete/restore ticket
773 *
774 * @param WPSC_Ticket $ticket - ticket object.
775 * @param int $prev - previous customer id.
776 * @param int $new - new customer id.
777 * @param int $customer_id - current customer id.
778 * @return void
779 */
780 public static function customer_ticket_count_after_change_raised_by( $ticket, $prev, $new, $customer_id ) {
781
782 if ( ! $ticket->customer ) {
783 return;
784 }
785
786 $customer = $ticket->customer;
787
788 if ( ! is_object( $customer ) ) {
789 $customer = new WPSC_Customer( $customer );
790 }
791
792 if ( $customer->id ) {
793 $customer->update_ticket_count();
794 }
795 }
796
797 /**
798 * Count customer archive tickets after restore ticket
799 *
800 * @param WPSC_Ticket $ticket - ticket object.
801 * @param WPSC_Archive_Ticket $ar_ticket - archive ticket object.
802 * @return void
803 */
804 public static function reset_customer_ticket_count( $ticket, $ar_ticket ) {
805 if ( ! $ticket->customer ) {
806 return;
807 }
808
809 $customer = $ticket->customer;
810
811 if ( ! is_object( $customer ) ) {
812 $customer = new WPSC_Customer( $customer );
813 }
814
815 if ( $customer->id ) {
816 $customer->update_ticket_count();
817 }
818 }
819
820 /**
821 * Count customer tickets after create/delete/restore ticket
822 *
823 * @param WPSC_Ticket $ticket - ticket object.
824 * @return void
825 */
826 public static function customer_ticket_count( $ticket ) {
827 if ( ! $ticket->customer ) {
828 return;
829 }
830
831 $customer = $ticket->customer;
832
833 if ( ! is_object( $customer ) ) {
834 $customer = new WPSC_Customer( $customer );
835 }
836
837 if ( $customer->id ) {
838 $customer->update_ticket_count();
839 }
840 }
841
842 /**
843 * Delete customer from.
844 *
845 * @return void
846 */
847 public static function delete_customer_info() {
848
849 if ( check_ajax_referer( 'wpsc_delete_customer', '_ajax_nonce', false ) != 1 ) {
850 wp_send_json_error( 'Unauthorized request!', 401 );
851 }
852
853 if ( ! WPSC_Functions::is_site_admin() ) {
854 wp_send_json_error( 'Unauthorized request!', 401 );
855 }
856
857 $customer_id = isset( $_POST['customer_id'] ) ? intval( $_POST['customer_id'] ) : 0;
858 if ( ! $customer_id ) {
859 wp_send_json_error( 'Bad Request', 400 );
860 }
861
862 $customer = new WPSC_Customer( $customer_id );
863 if ( ! $customer->id ) {
864 wp_send_json_error( 'Bad request', 400 );
865 }
866
867 // Make agent as a anonymous customer.
868 $agent = WPSC_Agent::get_by_customer( $customer );
869 if ( $agent->id ) {
870
871 if ( $agent->role == 1 ) {
872 wp_send_json_error( 'Unauthorized request!', 401 );
873 }
874
875 $agent->customer = WPSC_Functions::anonymous_customer();
876 $agent->is_active = 0;
877 $agent->save();
878
879 // Remove agent capability.
880 if ( $agent->has_cap( 'backend-access' ) ) {
881 $agent->user->remove_cap( 'wpsc_agent' );
882 }
883
884 do_action( 'wpsc_delete_agent', $agent );
885 }
886
887 self::delete_customer_tickets( $customer_id );
888
889 WPSC_Customer::destroy( $customer );
890 do_action( 'wpsc_delete_customer', $customer );
891 wp_die();
892 }
893
894 /**
895 * Delete customer tickets
896 *
897 * @param int $customer_id - customer_id.
898 * @return void
899 */
900 public static function delete_customer_tickets( $customer_id ) {
901
902 global $wpdb;
903
904 // Delete threads if records is exists.
905 $td_sql = "DELETE thrd FROM {$wpdb->prefix}psmsc_threads AS thrd LEFT JOIN {$wpdb->prefix}psmsc_tickets AS t ON thrd.ticket = t.id WHERE t.customer = $customer_id";
906 $wpdb->query( $td_sql );
907
908 // is active 0 attachment if records is exists.
909 $td_sql = "UPDATE {$wpdb->prefix}psmsc_attachments AS att LEFT JOIN {$wpdb->prefix}psmsc_tickets AS t ON att.ticket_id = t.id SET att.is_active = 0 WHERE t.customer = $customer_id";
910 $wpdb->query( $td_sql );
911
912 // Delete sla log records if log records is exists.
913 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}psmsc_sla_logs'" ) ) {
914 $sl_sql = "DELETE sl FROM {$wpdb->prefix}psmsc_sla_logs AS sl LEFT JOIN {$wpdb->prefix}psmsc_tickets AS t ON sl.ticket = t.id WHERE t.customer = $customer_id";
915 $wpdb->query( $sl_sql );
916 }
917
918 // Delete timer log records if log records is exists.
919 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}psmsc_timer_logs'" ) ) {
920 $tl_sql = "DELETE tl FROM {$wpdb->prefix}psmsc_timer_logs AS tl LEFT JOIN {$wpdb->prefix}psmsc_tickets AS t ON tl.ticket = t.id WHERE t.customer = $customer_id";
921 $wpdb->query( $tl_sql );
922 }
923
924 // Delete tickets if ticket records is exists.
925 $td_sql = "DELETE FROM {$wpdb->prefix}psmsc_tickets WHERE customer = $customer_id";
926 $wpdb->query( $td_sql );
927 }
928
929 /**
930 * Get customer profile details
931 *
932 * @return void
933 */
934 public static function view_customer_detailed_info() {
935
936 if ( check_ajax_referer( 'wpsc_view_customer_detailed_info', '_ajax_nonce', false ) != 1 ) {
937 wp_send_json_error( 'Unauthorized request!', 401 );
938 }
939
940 $customer_id = isset( $_POST['customer_id'] ) ? intval( $_POST['customer_id'] ) : 0;
941 if ( ! $customer_id ) {
942 wp_send_json_error( 'Bad Request', 400 );
943 }
944
945 $customer = new WPSC_Customer( $customer_id );
946 if ( ! $customer->id ) {
947 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
948 }
949 $agent = WPSC_Agent::get_by_customer( $customer );
950 ?>
951 <!-- User profile starts -->
952 <div class="wpsc-back-button">
953 <a class="wpsc-link" onclick="location.reload()"><?php esc_attr_e( 'Back', 'supportcandy' ); ?></a>
954 <?php
955 if ( ! $agent->id || ( $agent->role != 1 ) ) {
956 ?>
957 | <span class="wpsc-link" onclick="wpsc_delete_customer(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer' ) ); ?>')">
958 <?php esc_attr_e( 'Delete', 'supportcandy' ); ?>
959 </span>
960 <?php
961 }
962 ?>
963 </div>
964 <div class="wpsc-up-section">
965 <main>
966 <div class="wpsc-up-container">
967 <div class="wpsc-up-picture img">
968 <?php echo get_avatar( $customer->email, 50 ); ?>
969 </div>
970 <div class="wpsc-up-info">
971 <div class="wpsc-up-name"><?php echo esc_attr( $customer->name ); ?></div>
972 <div class="wpsc-up-email"><?php echo esc_attr( $customer->email ); ?></div>
973 </div>
974 </div>
975 <!-- Tabs -->
976 <div class="wpsc-up-tab">
977 <?php do_action( 'wpsc_add_before_up_tab' ); ?>
978 <label class="wpsc-profile-tab active" data-toggle-target="wpsc-up-tickets"><?php esc_attr_e( 'Tickets', 'supportcandy' ); ?></label>
979 <label class="wpsc-profile-tab" data-toggle-target="wpsc-up-cf"><?php esc_attr_e( 'Custom fields', 'supportcandy' ); ?></label>
980 <label class="wpsc-profile-tab" data-toggle-target="wpsc-up-other"><?php esc_attr_e( 'Other', 'supportcandy' ); ?></label>
981 <?php do_action( 'wpsc_add_after_up_tab' ); ?>
982 </div>
983
984 <!-- Tab Content -->
985 <section>
986 <?php do_action( 'wpsc_add_before_up_tab_content' ); ?>
987 <div class="wpsc-up-content wpsc-up-tickets active">
988 <?php self::get_customers_ticket_list( $customer ); ?>
989 </div>
990 <div class="wpsc-up-content wpsc-up-cf">
991 <?php self::get_customers_customer_fields( $customer ); ?>
992 </div>
993 <div class="wpsc-up-content wpsc-up-other">
994 <?php self::get_customers_other_info( $customer ); ?>
995 </div>
996 <?php do_action( 'wpsc_add_after_up_tab_content' ); ?>
997 </section>
998 </main>
999 </div>
1000 <!-- User profile ends -->
1001
1002 <script>
1003 jQuery('.wpsc-profile-tab').on('click', function(event) {
1004
1005 event.preventDefault();
1006 if ( jQuery(this).hasClass('active') ) return;
1007
1008 jQuery(this).toggleClass('active');
1009 var temp = jQuery(this).data('toggle-target');
1010 jQuery('.wpsc-up-content').removeClass('active').filter('.'+temp).addClass('active');
1011 jQuery('.wpsc-profile-tab').not(this).removeClass('active');
1012 });
1013 </script>
1014 <?php
1015 wp_die();
1016 }
1017
1018 /**
1019 * Get customer's individual tickets
1020 *
1021 * @param int $customer - customer id.
1022 * @return void
1023 */
1024 public static function get_customers_ticket_list( $customer ) {
1025
1026 $list_items = get_option( 'wpsc-ctl-list-items' );
1027 ?>
1028 <table class="my-profile-ticket-list wpsc-setting-tbl">
1029 <thead>
1030 <tr>
1031 <?php
1032 foreach ( $list_items as $slug ) :
1033 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1034 if ( ! $cf ) {
1035 continue;
1036 }
1037 ?>
1038 <th style="min-width: <?php echo esc_attr( $cf->tl_width ); ?>px;"><?php echo esc_attr( $cf->name ); ?></th>
1039 <?php
1040 endforeach;
1041 ?>
1042 </tr>
1043 </thead>
1044 <tbody>
1045 <?php
1046 $filters = array(
1047 'items_per_page' => 0,
1048 'orderby' => 'id',
1049 'order' => 'DESC',
1050 'meta_query' => array(
1051 'relation' => 'AND',
1052 array(
1053 'slug' => 'customer',
1054 'compare' => '=',
1055 'val' => $customer->id,
1056 ),
1057 ),
1058 );
1059 $tickets = WPSC_Ticket::find( $filters )['results'];
1060 if ( $tickets ) {
1061 foreach ( $tickets as $ticket ) {
1062 // Backend link (view = 0) so it opens the ticket in wp-admin, regardless
1063 // of how the frontend "open ticket page" is configured.
1064 $ticket_url = WPSC_Functions::get_ticket_url( $ticket->id, 0 );
1065 ?>
1066 <tr class="wpsc-cust-ticket-row" onclick="window.open('<?php echo esc_url( $ticket_url ); ?>', '_blank');" title="<?php esc_attr_e( 'Open ticket', 'supportcandy' ); ?>">
1067 <?php
1068 foreach ( $list_items as $slug ) {
1069 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1070 if ( ! $cf ) {
1071 continue;
1072 }
1073 ?>
1074 <td>
1075 <?php
1076 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ) {
1077 $cf->type::print_tl_ticket_field_val( $cf, $ticket );
1078 } else {
1079 $cf->type::print_tl_customer_field_val( $cf, $ticket->customer );
1080 }
1081 ?>
1082 </td>
1083 <?php
1084 }
1085 ?>
1086 </tr>
1087 <?php
1088 }
1089 }
1090 ?>
1091 </tbody>
1092 </table>
1093 <script>
1094 jQuery(document).ready(function() {
1095
1096 jQuery('.my-profile-ticket-list').dataTable({
1097 'bDestroy': true,
1098 'searching': false,
1099 'ordering': false,
1100 'bLengthChange': false,
1101 pageLength: 10,
1102 columnDefs: [
1103 { targets: '_all', className: 'dt-left' },
1104 ],
1105 language: supportcandy.translations.datatables
1106 });
1107 });
1108 </script>
1109 <?php
1110 }
1111
1112 /**
1113 * Get customer's custom fields
1114 *
1115 * @param int $customer - customer id.
1116 * @return void
1117 */
1118 public static function get_customers_customer_fields( $customer ) {
1119
1120 $properties = array(
1121 'is-required' => 0,
1122 'width' => 'full',
1123 'visibility' => '',
1124 );
1125
1126 // Render into a buffer first so we can tell whether there is anything to show at all
1127 // (no applicable customer fields, and nothing added via the body hook either) before
1128 // committing to the form + action buttons.
1129 ob_start();
1130 foreach ( WPSC_Custom_Field::$custom_fields as $cf ) {
1131 if ( $cf->field !== 'customer' || in_array( $cf->slug, WPSC_DF_Customer::$ignore_customer_info_cft ) ) {
1132 continue;
1133 }
1134 echo $cf->type::print_edit_customer_info( $cf, $customer, $properties ); // phpcs:ignore
1135 }
1136 do_action( 'wpsc_get_edit_customer_info_body', $customer );
1137 $fields_html = ob_get_clean();
1138
1139 if ( '' === trim( $fields_html ) ) {
1140 ?>
1141 <p class="wpsc-cust-cf-empty"><?php esc_attr_e( 'No custom fields found for this customer.', 'supportcandy' ); ?></p>
1142 <?php
1143 return;
1144 }
1145 ?>
1146 <form action="#" onsubmit="return false;" class="frm-edit-customer-info">
1147 <?php echo $fields_html; // phpcs:ignore ?>
1148 <input type="hidden" name="action" value="wpsc_set_edit_customer_info"/>
1149 <input type="hidden" name="id" value="<?php echo esc_attr( $customer->id ); ?>">
1150 <input type="hidden" name="name" value="<?php echo esc_attr( $customer->name ); ?>">
1151 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_edit_customer_info' ) ); ?>">
1152 </form>
1153 <button class="wpsc-button small primary" onclick="wpsc_set_edit_customer_info(this, <?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_info' ) ); ?>');">
1154 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
1155 </button>
1156 <button class="wpsc-button small secondary" onclick="wpsc_view_customer_logs(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_logs' ) ); ?>')">
1157 <?php esc_attr_e( 'View logs', 'supportcandy' ); ?>
1158 </button>
1159 <?php
1160 }
1161
1162 /**
1163 * Get customer's other info
1164 *
1165 * @param int $customer - customer id.
1166 * @return void
1167 */
1168 public static function get_customers_other_info( $customer ) {
1169
1170 do_action( 'wpsc_user_profile_widgets_before', $customer );
1171 ?>
1172 <div class="wpsc-xs-6 wpsc-sm-6 wpsc-md-6 wpsc-lg-6">
1173 <div class="wpsc-it-widget wpsc-itw-add-rec">
1174 <div class="wpsc-widget-header">
1175 <h2><?php echo esc_attr__( 'Recent Activities', 'supportcandy' ); ?></h2>
1176 <span>
1177 <div class="info-list-item">
1178 <div class="info-label">
1179 <a href="<?php echo esc_url_raw( admin_url( 'admin.php?page=wpsc-recent-activities&cid=' . $customer->id ) ); ?>" target="__blank"><?php echo esc_attr__( 'View All', 'supportcandy' ); ?></a>
1180 </div>
1181 </div>
1182 </span>
1183 </div>
1184 <div class="wpsc-widget-body wpsc-widget-scroller">
1185 <div class="info-list-item">
1186 <div class="info-val fullwidth">
1187 <div id="wpsc-upw-recent-activities"></div>
1188 </div>
1189 </div>
1190 </div>
1191 </div>
1192 </div>
1193 <script>
1194 wpsc_upw_get_recent_activities();
1195 function wpsc_upw_get_recent_activities() {
1196 jQuery('#wpsc-upw-recent-activities').html( supportcandy.loader_html );
1197 var data = { action: 'wpsc_upw_get_recent_activities', view: supportcandy.is_frontend, _ajax_nonce: supportcandy.nonce, customer_id: <?php echo esc_attr( $customer->id ); ?> };
1198 jQuery.post(
1199 supportcandy.ajax_url,
1200 data,
1201 function (response) {
1202 jQuery('#wpsc-upw-recent-activities').html(response.html);
1203 }
1204 );
1205 }
1206 </script>
1207 <?php
1208 do_action( 'wpsc_user_profile_widgets_after', $customer );
1209 }
1210
1211 /**
1212 * Get customer recent activities
1213 *
1214 * @return void
1215 */
1216 public static function get_upw_recent_activities() {
1217
1218 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1219 wp_send_json_error( 'Unauthorized request!', 401 );
1220 }
1221
1222 if ( ! WPSC_Functions::is_site_admin() ) {
1223 wp_send_json_error( new WP_Error( '004', 'Unauthorized!' ), 401 );
1224 }
1225
1226 $view = isset( $_POST['view'] ) ? sanitize_text_field( wp_unslash( $_POST['view'] ) ) : '0';
1227
1228 $customer_id = isset( $_POST['customer_id'] ) ? intval( $_POST['customer_id'] ) : 0;
1229 if ( ! $customer_id ) {
1230 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1231 }
1232
1233 $customer = new WPSC_Customer( $customer_id );
1234 if ( ! $customer->id ) {
1235 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1236 }
1237
1238 $logs = WPSC_RA_Logs::get_activity_logs( 10, 1, $customer_id );
1239 $now = new DateTime();
1240 ob_start();
1241 ?>
1242 <div class="wpsc-widget-list-section">
1243 <?php
1244 if ( $logs['total_items'] ) {
1245 foreach ( $logs['results'] as $log ) {
1246
1247 $url = WPSC_Functions::get_ticket_url( $log->ticket->id, $view );
1248 $time_ago = WPSC_Functions::date_interval_highest_unit_ago( $log->date_created->diff( $now ) );
1249
1250 if ( $log->type == 'report' ) {
1251 ?>
1252 <div class="wpsc-widget-list"><?php echo esc_attr( $log->customer->name ) . ' ' . esc_attr__( 'created a ticket', 'supportcandy' ); ?> <a href="<?php echo esc_attr( $url ); ?>" target="_blank">#<?php echo esc_attr( $log->ticket->id ) . ' ' . esc_attr( $log->ticket->subject ); ?></a><?php echo esc_attr( ' (' . $time_ago . ')' ); ?></div>
1253 <?php
1254 } elseif ( $log->type == 'reply' ) {
1255 ?>
1256 <div class="wpsc-widget-list"><?php echo esc_attr( $log->customer->name ) . ' ' . esc_attr__( 'replied to ticket', 'supportcandy' ); ?> <a href="<?php echo esc_attr( $url ); ?>" target="_blank">#<?php echo esc_attr( $log->ticket->id ); ?></a><?php echo esc_attr( ' (' . $time_ago . ')' ); ?></div>
1257 <?php
1258 } elseif ( $log->type == 'note' ) {
1259 ?>
1260 <div class="wpsc-widget-list"><?php echo esc_attr( $log->customer->name ) . ' ' . esc_attr__( 'added a note to ticket', 'supportcandy' ); ?> <a href="<?php echo esc_attr( $url ); ?>" target="_blank">#<?php echo esc_attr( $log->ticket->id ); ?></a><?php echo esc_attr( ' (' . $time_ago . ')' ); ?></div>
1261 <?php
1262 } elseif ( $log->type == 'log' ) {
1263 if ( ! $log->customer ) {
1264 continue;
1265 }
1266 $body = json_decode( $log->body );
1267 $is_json = ( json_last_error() == JSON_ERROR_NONE ) ? true : false;
1268 if ( $is_json ) {
1269 $cf = WPSC_Custom_Field::get_cf_by_slug( $body->slug );
1270 if ( ! $cf ) {
1271 continue;
1272 }
1273 ?>
1274 <div class="wpsc-widget-list"><?php echo wp_kses_post( $cf->type::print_activity( $cf, $log, $body, '0' ) ); ?><?php echo esc_attr( ' (' . $time_ago . ')' ); ?></div>
1275 <?php
1276 }
1277 }
1278 }
1279 } else {
1280 echo esc_attr__( 'Record not found!', 'supportcandy' );
1281 }
1282 ?>
1283 </div>
1284 <?php
1285 $table = ob_get_clean();
1286 wp_send_json( array( 'html' => $table ) );
1287 }
1288 }
1289 endif;
1290
1291 WPSC_Customers::init();
1292