PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.4.5
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.4.5
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 / models / class-wpsc-agent.php

class-wpsc-agent.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent 3.4.5, at includes/models/class-wpsc-agent.php

1,153 lines 28.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly!
4 }
5
6 if ( ! class_exists( 'WPSC_Agent' ) ) :
7
8 final class WPSC_Agent {
9
10 /**
11 * Object data in key => val pair.
12 *
13 * @var array
14 */
15 private $data = array();
16
17 /**
18 * Set whether or not current object properties modified
19 *
20 * @var boolean
21 */
22 private $is_modified = false;
23
24 /**
25 * Schema for this model
26 *
27 * @var array
28 */
29 public static $schema = array();
30
31 /**
32 * Prevent fields to modify
33 *
34 * @var array
35 */
36 public static $prevent_modify = array();
37
38 /**
39 * DB object caching
40 *
41 * @var array
42 */
43 private static $cache = array();
44
45 /**
46 * Initialize this class
47 *
48 * @return void
49 */
50 public static function init() {
51
52 // Apply schema for this model.
53 add_action( 'init', array( __CLASS__, 'apply_schema' ), 2 );
54
55 // Get object of this class.
56 add_filter( 'wpsc_load_ref_classes', array( __CLASS__, 'load_ref_class' ) );
57
58 // after profile update.
59 add_action( 'profile_update', array( __CLASS__, 'agent_profile_update' ), 10, 2 );
60
61 // reset missing count.
62 add_action( 'init', array( __CLASS__, 'reset_count_check' ), 200 );
63 add_action( 'wpsc_reset_missing_counts', array( __CLASS__, 'reset_missing_counts' ) );
64
65 // create ticket event to reset unresolved and workload counts of related agents to the ticket.
66 add_action( 'wpsc_create_new_ticket', array( __CLASS__, 'create_new_ticket' ), 500 );
67
68 // change status event to reset unresolved and workload counts of related agents to the ticket.
69 add_action( 'wpsc_change_ticket_status', array( __CLASS__, 'change_status' ), 200, 4 );
70
71 // assigned agent event to reset unresolved and workload counts of related agents to the ticket.
72 add_action( 'wpsc_change_assignee', array( __CLASS__, 'change_assignee' ), 200, 4 );
73
74 // change raised by event to reset unresolved and workload counts of related agents to the ticket.
75 add_action( 'wpsc_change_raised_by', array( __CLASS__, 'change_raised_by' ), 200, 4 );
76
77 // archive/restore/delete ticket event to reset unresolved and workload counts of related agents to the ticket.
78 add_action( 'wpsc_ticket_archive', array( __CLASS__, 'reset_agent_unresolved_count' ), 200 );
79 add_action( 'wpsc_delete_ticket', array( __CLASS__, 'reset_agent_unresolved_count' ), 200 );
80 add_action( 'wpsc_ticket_restore', array( __CLASS__, 'reset_agent_unresolved_count' ), 200 );
81 add_action( 'wpsc_ticket_delete_permanently', array( __CLASS__, 'reset_agent_unresolved_count' ), 200 );
82
83 // agent autocomplete admin access only.
84 add_action( 'wp_ajax_wpsc_agent_autocomplete_admin_access', array( __CLASS__, 'agent_autocomplete_admin_access' ) );
85
86 // reset unresolved count after agent role update.
87 add_action( 'wpsc_agent_role_update', array( __CLASS__, 'agent_role_update' ) );
88 }
89
90 /**
91 * Apply schema for this model
92 *
93 * @return void
94 */
95 public static function apply_schema() {
96
97 $schema = array(
98 'id' => array(
99 'has_ref' => false,
100 'ref_class' => '',
101 'has_multiple_val' => false,
102 ),
103 'user' => array(
104 'has_ref' => true,
105 'ref_class' => 'wp_user',
106 'has_multiple_val' => false,
107 ),
108 'customer' => array(
109 'has_ref' => true,
110 'ref_class' => 'wpsc_customer',
111 'has_multiple_val' => false,
112 ),
113 'role' => array(
114 'has_ref' => false,
115 'ref_class' => '',
116 'has_multiple_val' => false,
117 ),
118 'name' => array(
119 'has_ref' => false,
120 'ref_class' => '',
121 'has_multiple_val' => false,
122 ),
123 'workload' => array(
124 'has_ref' => false,
125 'ref_class' => '',
126 'has_multiple_val' => false,
127 ),
128 'unresolved_count' => array(
129 'has_ref' => false,
130 'ref_class' => '',
131 'has_multiple_val' => false,
132 ),
133 'is_agentgroup' => array(
134 'has_ref' => false,
135 'ref_class' => '',
136 'has_multiple_val' => false,
137 ),
138 'is_active' => array(
139 'has_ref' => false,
140 'ref_class' => '',
141 'has_multiple_val' => false,
142 ),
143 );
144 self::$schema = apply_filters( 'wpsc_agent_schema', $schema );
145
146 // Prevent modify.
147 $prevent_modify = array( 'id' );
148 self::$prevent_modify = apply_filters( 'wpsc_agent_prevent_modify', $prevent_modify );
149 }
150
151 /**
152 * Model constructor
153 *
154 * @param int $id - Optional. Data record id to retrive object for.
155 */
156 public function __construct( $id = 0 ) {
157
158 global $wpdb;
159
160 $id = intval( $id );
161
162 if ( isset( self::$cache[ $id ] ) ) {
163 $this->data = self::$cache[ $id ]->data;
164 return;
165 }
166
167 if ( $id > 0 ) {
168
169 $agent = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}psmsc_agents WHERE id = " . $id, ARRAY_A );
170 if ( ! is_array( $agent ) ) {
171 return;
172 }
173
174 foreach ( $agent as $key => $val ) {
175 $this->data[ $key ] = $val !== null ? $val : '';
176 }
177
178 self::$cache[ $id ] = $this;
179 }
180 }
181
182 /**
183 * Convert object into an array
184 *
185 * @return array
186 */
187 public function to_array() {
188
189 return $this->data;
190 }
191
192 /**
193 * Magic get function to use with object arrow function
194 *
195 * @param string $var_name - variable name.
196 * @return mixed
197 */
198 public function __get( $var_name ) {
199
200 if ( ! isset( $this->data[ $var_name ] ) ||
201 $this->data[ $var_name ] == null ||
202 $this->data[ $var_name ] == ''
203 ) {
204 return self::$schema[ $var_name ]['has_multiple_val'] ? array() : '';
205 }
206
207 if ( self::$schema[ $var_name ]['has_multiple_val'] ) {
208
209 $response = array();
210 $values = $this->data[ $var_name ] ? explode( '|', $this->data[ $var_name ] ) : array();
211 foreach ( $values as $val ) {
212 $response[] = self::$schema[ $var_name ]['has_ref'] ?
213 WPSC_Functions::get_object( self::$schema[ $var_name ]['ref_class'], $val ) :
214 $val;
215 }
216 return $response;
217
218 } else {
219
220 return self::$schema[ $var_name ]['has_ref'] && $this->data[ $var_name ] ?
221 WPSC_Functions::get_object( self::$schema[ $var_name ]['ref_class'], $this->data[ $var_name ] ) :
222 $this->data[ $var_name ];
223 }
224 }
225
226 /**
227 * Magic function to use setting object field with arrow function
228 *
229 * @param string $var_name - (Required) property slug.
230 * @param mixed $value - (Required) value to set for a property.
231 * @return void
232 */
233 public function __set( $var_name, $value ) {
234
235 if ( ! isset( $this->data[ $var_name ] ) ) {
236 return;
237 }
238
239 if ( in_array( $var_name, self::$prevent_modify ) ) {
240 return;
241 }
242
243 $data_val = '';
244 if ( self::$schema[ $var_name ]['has_multiple_val'] ) {
245
246 $data_vals = array_map(
247 fn( $val ) => is_object( $val ) ? WPSC_Functions::set_object( self::$schema[ $var_name ]['ref_class'], $val ) : $val,
248 $value
249 );
250
251 $data_val = $data_vals ? implode( '|', $data_vals ) : '';
252
253 } else {
254
255 $data_val = is_object( $value ) ? WPSC_Functions::set_object( self::$schema[ $var_name ]['ref_class'], $value ) : $value;
256 }
257
258 if ( isset( $this->data[ $var_name ] ) && $this->data[ $var_name ] == $data_val ) {
259 return;
260 }
261
262 $this->data[ $var_name ] = $data_val;
263 $this->is_modified = true;
264 }
265
266 /**
267 * Save changes made
268 *
269 * @return boolean
270 */
271 public function save() {
272
273 global $wpdb;
274
275 if ( ! $this->is_modified ) {
276 return true;
277 }
278
279 $data = $this->data;
280 $data['is_active'] = intval( $data['is_active'] );
281
282 $success = true;
283
284 unset( $data['id'] );
285 $success = $wpdb->update(
286 $wpdb->prefix . 'psmsc_agents',
287 $data,
288 array( 'id' => $this->data['id'] )
289 );
290
291 $this->is_modified = false;
292 self::$cache[ $this->id ] = $this;
293 return $success ? true : false;
294 }
295
296 /**
297 * Insert new record
298 *
299 * @param array $data - record data.
300 * @return WPSC_Agent
301 */
302 public static function insert( $data ) {
303
304 global $wpdb;
305
306 $success = $wpdb->insert(
307 $wpdb->prefix . 'psmsc_agents',
308 $data
309 );
310
311 if ( ! $success ) {
312 return false;
313 }
314
315 $agent = new WPSC_Agent( $wpdb->insert_id );
316 self::$cache[ $agent->id ] = $agent;
317 return $agent;
318 }
319
320 /**
321 * Make it inactive so that garbage collector will delete files associated in
322 * background and then delete the record. This will improve its performance.
323 *
324 * @param WPSC_Agent $agent - agent model.
325 * @return boolean
326 */
327 public static function destroy( $agent ) {
328
329 global $wpdb;
330 $agent->is_active = 0;
331 $agent->save();
332 return true;
333 }
334
335 /**
336 * Set data to create new object using direct data. Used in find method
337 *
338 * @param array $data - data to set for object.
339 * @return void
340 */
341 private function set_data( $data ) {
342
343 foreach ( $data as $var_name => $val ) {
344 $this->data[ $var_name ] = $val !== null ? $val : '';
345 }
346 self::$cache[ $this->id ] = $this;
347 }
348
349 /**
350 * Find records based on given filters
351 *
352 * @param array $filter - array containing array items like search, where, orderby, order, page_no, items_per_page, etc.
353 * @param boolean $is_object - return data as array or object. Default object.
354 * @return mixed
355 */
356 public static function find( $filter = array(), $is_object = true ) {
357
358 global $wpdb;
359
360 $filter['items_per_page'] = isset( $filter['items_per_page'] ) ? $filter['items_per_page'] : 20;
361 $filter['page_no'] = isset( $filter['page_no'] ) ? $filter['page_no'] : 1;
362 $filter['orderby'] = isset( $filter['orderby'] ) ? $filter['orderby'] : 'name';
363 $filter['order'] = isset( $filter['order'] ) ? $filter['order'] : 'ASC';
364
365 // orderby.
366 $filter['orderby'] = apply_filters( 'wpsc_agent_orderby_string', $filter['orderby'] );
367
368 // Add table alice to orderby.
369 $filter['orderby'] = 'a.' . $filter['orderby'];
370
371 $sql = 'SELECT a.* FROM ' . $wpdb->prefix . 'psmsc_agents a ';
372 $order = WPSC_Functions::parse_order( $filter );
373 $limit = WPSC_Functions::parse_limit( $filter );
374 $join = self::get_joins( $filter );
375 $where = self::get_where( $filter );
376
377 $group_by = 'GROUP BY a.id ';
378
379 $sql = $sql . $join . $where . $group_by . $order . $limit;
380 $results = $wpdb->get_results( $sql, ARRAY_A );
381
382 // total results.
383 $sql = 'SELECT count(a.id) FROM ' . $wpdb->prefix . 'psmsc_agents a ';
384 $total_items = $wpdb->get_var( $sql . $join . $where );
385
386 $response = WPSC_Functions::parse_response( $results, $total_items, $filter );
387
388 // Return array.
389 if ( ! $is_object ) {
390 return $response;
391 }
392
393 // create and return array of objects.
394 $temp_results = array();
395 foreach ( $response['results'] as $agent ) {
396
397 $ob = new WPSC_Agent();
398 $data = array();
399 foreach ( $agent as $key => $val ) {
400 $data[ $key ] = $val;
401 }
402 $ob->set_data( $data );
403 $temp_results[] = $ob;
404
405 // set cache.
406 self::$cache[ $ob->id ] = $ob;
407 }
408 $response['results'] = $temp_results;
409
410 return $response;
411 }
412
413 /**
414 * Apply joins to the query if search is needed
415 *
416 * @param array $filter - user filter.
417 * @return array
418 */
419 private static function get_joins( $filter ) {
420
421 global $wpdb;
422
423 $joins = array();
424 $search = WPSC_Functions::get_filter_search_str( $filter );
425 if ( $search ) {
426 $joins = array( 'LEFT JOIN ' . $wpdb->users . ' u ON a.user = u.ID' );
427 }
428
429 return $joins ? implode( ' ', $joins ) . ' ' : '';
430 }
431
432 /**
433 * Get where for find method
434 *
435 * @param array $filter - user filter.
436 * @return array
437 */
438 private static function get_where( $filter ) {
439
440 $where = array( '1=1' );
441
442 // Load meta filters.
443 $meta_query = isset( $filter['meta_query'] ) ? $filter['meta_query'] : array();
444 if ( $meta_query ) {
445 $where[] = WPSC_Functions::parse_user_filters( __CLASS__, $meta_query );
446 }
447
448 // Search.
449 $search = WPSC_Functions::get_filter_search_str( $filter );
450 if ( $search ) {
451 $search_query = array(
452 'CONVERT(a.name USING utf8) LIKE \'%' . $search . '%\'',
453 'CONVERT(u.user_login USING utf8) LIKE \'%' . $search . '%\'',
454 'CONVERT(u.user_nicename USING utf8) LIKE \'%' . $search . '%\'',
455 'CONVERT(u.user_email USING utf8) LIKE \'%' . $search . '%\'',
456 'CONVERT(u.display_name USING utf8) LIKE \'%' . $search . '%\'',
457 );
458 $where[] = implode( ' OR ', $search_query );
459 }
460
461 return 'WHERE (' . implode( ') AND (', $where ) . ') ';
462 }
463
464 /**
465 * Load current class to reference classes
466 *
467 * @param array $classes - Associative array of class names indexed by its slug.
468 * @return array
469 */
470 public static function load_ref_class( $classes ) {
471
472 $classes['wpsc_agent'] = array(
473 'class' => __CLASS__,
474 'save-key' => 'id',
475 );
476 return $classes;
477 }
478
479 /**
480 * Check whether wp user of given id is an agent or not
481 *
482 * @param int $user_id - wp user id.
483 * @return boolean
484 */
485 public static function get_by_user_id( $user_id ) {
486
487 if ( ! $user_id ) {
488 return new WPSC_Agent();
489 }
490
491 $response = self::find(
492 array(
493 'meta_query' => array(
494 'relation' => 'AND',
495 array(
496 'slug' => 'user',
497 'compare' => '=',
498 'val' => $user_id,
499 ),
500 ),
501 )
502 );
503
504 return $response['results'] ? $response['results'][0] : new WPSC_Agent();
505 }
506
507 /**
508 * Get agents by role.
509 *
510 * @param int $role_id - role id.
511 * @return array.
512 */
513 public static function get_by_role( $role_id ) {
514
515 $agents = self::find(
516 array(
517 'items_per_page' => 0,
518 'meta_query' => array(
519 'relation' => 'AND',
520 array(
521 'slug' => 'role',
522 'compare' => '=',
523 'val' => $role_id,
524 ),
525 array(
526 'slug' => 'is_active',
527 'compare' => '=',
528 'val' => 1,
529 ),
530 ),
531 )
532 )['results'];
533
534 return $agents;
535 }
536
537 /**
538 * Get an agent by customer
539 *
540 * @param WPSC_Customer $customer - customer object.
541 * @return WPSC_Agent
542 */
543 public static function get_by_customer( $customer ) {
544
545 $results = self::find(
546 array(
547 'meta_query' => array(
548 'relation' => 'AND',
549 array(
550 'slug' => 'customer',
551 'compare' => '=',
552 'val' => $customer->id,
553 ),
554 array(
555 'slug' => 'is_active',
556 'compare' => '=',
557 'val' => 1,
558 ),
559 ),
560 )
561 )['results'];
562
563 return $results ? $results[0] : new WPSC_Agent();
564 }
565
566 /**
567 * Agent autocomplete callback
568 *
569 * @param array $filters - autocomplete filter.
570 * @return array
571 */
572 public static function agent_autocomplete( $filters ) {
573
574 $args = array(
575 'search' => $filters['term'],
576 'items_per_page' => 25,
577 'orderby' => $filters['sort_by'],
578 'order' => 'ASC',
579 'meta_query' => array(
580 'relation' => 'AND',
581 array(
582 'slug' => 'is_active',
583 'compare' => '=',
584 'val' => 1,
585 ),
586 ),
587 );
588
589 if ( is_numeric( $filters['isAgentgroup'] ) ) {
590 $args['meta_query'][] = array(
591 'slug' => 'is_agentgroup',
592 'compare' => '=',
593 'val' => $filters['isAgentgroup'],
594 );
595 }
596
597 $args = apply_filters( 'wpsc_agent_autocomplete_filters', $args, $filters['filter_by'] );
598 $agents = self::find( $args )['results'];
599
600 $response = array();
601
602 if ( ! $filters['isMultiple'] ) {
603 $response[] = array(
604 'id' => 0,
605 'title' => esc_attr__( 'None', 'supportcandy' ),
606 );
607 }
608
609 foreach ( $agents as $agent ) {
610 $response[] = array(
611 'id' => $agent->id,
612 'title' => $agent->name,
613 );
614 }
615
616 return $response;
617 }
618
619 /**
620 * Return whether or not agent has given capability
621 *
622 * @param string $cap - capability slug.
623 * @return boolean
624 */
625 public function has_cap( $cap ) {
626
627 $roles = get_option( 'wpsc-agent-roles', array() );
628 if ( ! isset( $roles[ $this->role ] ) ) {
629 return false;
630 }
631 $role = $roles[ $this->role ];
632 return isset( $role['caps'][ $cap ] ) && $role['caps'][ $cap ] ? true : false;
633 }
634
635 /**
636 * Get signature of the agent
637 *
638 * @return string
639 */
640 public function get_signature() {
641
642 $signature = get_user_meta( $this->user->ID, get_current_blog_id() . '_wpsc_email_signature', true );
643 return $signature ? $signature : '';
644 }
645
646 /**
647 * Set signature for the agent
648 *
649 * @param string $signature - signature string.
650 * @return void
651 */
652 public function set_signature( $signature ) {
653
654 update_user_meta( $this->user->ID, get_current_blog_id() . '_wpsc_email_signature', $signature );
655 }
656
657 /**
658 * Get default filter for the agent
659 *
660 * @return string
661 */
662 public function get_default_filter() {
663
664 $current_user = WPSC_Current_User::$current_user;
665 $default_filters = get_option( 'wpsc-atl-default-filters' );
666 $saved_filters = $current_user->get_saved_filters();
667 $agent_view = get_option( 'wpsc-tl-ms-agent-view', array() );
668
669 $default_filter = get_user_meta( $this->user->ID, get_current_blog_id() . '_wpsc_tl_default_filter', true );
670 if ( ! $default_filter ) {
671 $this->set_default_filter( $agent_view['default-filter'] );
672 return $agent_view['default-filter'];
673 }
674
675 $default_flag = preg_match( '/default-(\d*)$/', $default_filter, $default_matches );
676 $saved_flag = preg_match( '/saved-(\d*)$/', $default_filter, $saved_matches );
677
678 if (
679 ! (
680 isset( $default_filters[ $default_filter ] ) ||
681 ( $default_flag && isset( $default_filters[ $default_matches[1] ] ) ) ||
682 ( $saved_flag && isset( $saved_filters[ $saved_matches[1] ] ) )
683 ) ||
684 ( isset( $default_filters[ $default_filter ] ) && ! $default_filters[ $default_filter ]['is_enable'] ) ||
685 ( $default_flag && isset( $default_filters[ $default_matches[1] ] ) && ! $default_filters[ $default_matches[1] ]['is_enable'] )
686 ) {
687 $this->set_default_filter( $agent_view['default-filter'] );
688 return $agent_view['default-filter'];
689 }
690
691 return $default_filter;
692 }
693
694 /**
695 * Set default filter for the agent
696 *
697 * @param string $filter - filter slug.
698 * @return void
699 */
700 public function set_default_filter( $filter ) {
701
702 update_user_meta( $this->user->ID, get_current_blog_id() . '_wpsc_tl_default_filter', $filter );
703 }
704
705 /**
706 * Get default tab for the agent
707 *
708 * @return string
709 */
710 public function get_default_tab() {
711 $tab = get_user_meta( $this->user->ID, get_current_blog_id() . '_wpsc_tl_default_tab', true );
712 return $tab ? $tab : 'ticket-list';
713 }
714
715 /**
716 * Set default tab for the agent
717 *
718 * @param string $filter - filter slug.
719 * @return void
720 */
721 public function set_default_tab( $filter ) {
722
723 update_user_meta( $this->user->ID, get_current_blog_id() . '_wpsc_tl_default_tab', $filter );
724 }
725
726 /**
727 * Update name of agent if there is change in wp user meta.
728 *
729 * @param int $user_id - wp user id.
730 * @param WP_User $old_user_data - updated user object.
731 * @return void
732 */
733 public static function agent_profile_update( $user_id, $old_user_data ) {
734
735 $agent = self::get_by_user_id( $user_id );
736 if ( $agent ) {
737 $user = get_userdata( $user_id );
738 $agent->name = $user->display_name;
739 $agent->save();
740 }
741 }
742
743 /**
744 * Get working hrs of current agent
745 *
746 * @return array
747 */
748 public function get_working_hrs() {
749
750 return WPSC_Working_Hour::get( $this->id );
751 }
752
753 /**
754 * Get exceptions of current agent
755 *
756 * @return array
757 */
758 public function get_wh_exceptions() {
759
760 return WPSC_Wh_Exception::get( $this->id );
761 }
762
763 /**
764 * Reset count check
765 *
766 * @return void
767 */
768 public static function reset_count_check() {
769
770 if ( ! wp_next_scheduled( 'wpsc_reset_missing_counts' ) ) {
771 wp_schedule_event(
772 time(),
773 'wpsc_5min',
774 'wpsc_reset_missing_counts'
775 );
776 }
777 }
778
779 /**
780 * Calculate agent workloads
781 *
782 * @return void
783 */
784 public static function reset_missing_counts() {
785
786 $agents = self::find(
787 array(
788 'items_per_page' => 10,
789 'meta_query' => array(
790 'relation' => 'AND',
791 array(
792 'slug' => 'is_active',
793 'compare' => '=',
794 'val' => 1,
795 ),
796 array(
797 'slug' => 'is_agentgroup',
798 'compare' => '=',
799 'val' => 0,
800 ),
801 array(
802 'relation' => 'OR',
803 array(
804 'slug' => 'workload',
805 'compare' => 'IS',
806 'val' => null,
807 ),
808 array(
809 'slug' => 'unresolved_count',
810 'compare' => 'IS',
811 'val' => null,
812 ),
813 ),
814 ),
815 )
816 )['results'];
817
818 foreach ( $agents as $agent ) {
819 $agent->reset_unresolved_count();
820 $agent->reset_workload();
821 }
822 }
823
824 /**
825 * Reset unresolved count for the agent
826 */
827 public function reset_unresolved_count() {
828
829 // tickets filter.
830 $filters = array( 'items_per_page' => 1 );
831
832 // system query.
833 $system_query = array(
834 'relation' => 'OR',
835 array(
836 'slug' => 'customer',
837 'compare' => '=',
838 'val' => $this->customer->id,
839 ),
840 );
841 if ( $this->has_cap( 'view-assigned-me' ) ) {
842 $system_query[] = array(
843 'slug' => 'assigned_agent',
844 'compare' => '=',
845 'val' => $this->id,
846 );
847 }
848 if ( $this->has_cap( 'view-unassigned' ) ) {
849 $system_query[] = array(
850 'slug' => 'assigned_agent',
851 'compare' => '=',
852 'val' => '',
853 );
854 }
855 if ( $this->has_cap( 'view-assigned-others' ) ) {
856 $system_query[] = array(
857 'slug' => 'assigned_agent',
858 'compare' => 'NOT IN',
859 'val' => array( $this->id, '' ),
860 );
861 }
862 $filters['system_query'] = apply_filters( 'wpsc_reset_agent_unresolved_system_query', $system_query, $this );
863
864 // meta query.
865 $more_settings = get_option( 'wpsc-tl-ms-agent-view' );
866 $filters['meta_query'] = array(
867 'relation' => 'OR',
868 array(
869 'slug' => 'status',
870 'compare' => 'IN',
871 'val' => $more_settings['unresolved-ticket-statuses'],
872 ),
873 );
874
875 // get tickets.
876 $response = WPSC_Ticket::find( $filters );
877
878 // save unresolved count.
879 $this->unresolved_count = $response['total_items'];
880 $this->save();
881 }
882
883 /**
884 * Reset workload count for the agent
885 */
886 public function reset_workload() {
887
888 if ( $this->is_agentgroup ) {
889 return;
890 }
891
892 $more_settings = get_option( 'wpsc-tl-ms-agent-view' );
893 $response = WPSC_Ticket::find(
894 array(
895 'items_per_page' => 1,
896 'meta_query' => array(
897 'relation' => 'AND',
898 array(
899 'slug' => 'status',
900 'compare' => 'IN',
901 'val' => $more_settings['unresolved-ticket-statuses'],
902 ),
903 array(
904 'slug' => 'assigned_agent',
905 'compare' => '=',
906 'val' => $this->id,
907 ),
908 ),
909 )
910 );
911
912 // save workload.
913 $this->workload = $response['total_items'];
914 $this->save();
915 }
916
917 /**
918 * Reset unresolved count and workload after create new ticket.
919 *
920 * @param WPSC_Ticket $ticket - ticket object.
921 * @return void
922 */
923 public static function create_new_ticket( $ticket ) {
924
925 // reset workload for applicable agents.
926 foreach ( $ticket->assigned_agent as $agent ) {
927 $agent->reset_workload();
928 }
929
930 // reset unresolved count for applicable agents.
931 $agents = $ticket->get_current_read_permission_agents();
932 foreach ( $agents as $agent ) {
933 $agent->reset_unresolved_count();
934 }
935 }
936
937
938 /**
939 * Reset unresolved count and workload after change status.
940 *
941 * @param WPSC_Ticket $ticket - ticket object.
942 * @param int $prev - previous value.
943 * @param int $new - new value.
944 * @param int $customer_id - customer object id who made this change.
945 * @return void
946 */
947 public static function change_status( $ticket, $prev, $new, $customer_id ) {
948
949 // reset workload for applicable agents.
950 foreach ( $ticket->assigned_agent as $agent ) {
951 $agent->reset_workload();
952 }
953
954 // reset unresolved for applicable agents.
955 $agents = $ticket->get_current_read_permission_agents();
956 foreach ( $agents as $agent ) {
957 $agent->reset_unresolved_count();
958 }
959 }
960
961 /**
962 * Reset unresolved count and workload after change assignee
963 *
964 * @param WPSC_Ticket $ticket - ticket object.
965 * @param int $prev - previous value.
966 * @param int $new - new value.
967 * @param int $customer_id - customer object id who made this change.
968 * @return void
969 */
970 public static function change_assignee( $ticket, $prev, $new, $customer_id ) {
971
972 // reset workload for applicable agents.
973 $agents = array_merge( $prev, $new );
974 $temp_agents = array();
975 foreach ( $agents as $agent ) {
976 if ( ! isset( $temp_agents[ $agent->id ] ) ) {
977 $temp_agents[ $agent->id ] = $agent;
978 }
979 }
980 foreach ( $temp_agents as $agent ) {
981 $agent->reset_workload();
982 }
983
984 // reset unresolved for applicable agents.
985 $agents = $ticket->get_current_read_permission_agents();
986 $agents = array_merge( $agents, $ticket->get_prev_read_permission_agents( $prev ) );
987 $temp_agents = array();
988 foreach ( $agents as $agent ) {
989 if ( ! isset( $temp_agents[ $agent->id ] ) ) {
990 $temp_agents[ $agent->id ] = $agent;
991 }
992 }
993 foreach ( $temp_agents as $agent ) {
994 $agent->reset_unresolved_count();
995 }
996 }
997
998 /**
999 * Reset unresolved count and workload after change raised by
1000 *
1001 * @param WPSC_Ticket $ticket - ticket object.
1002 * @param int $prev - previous value.
1003 * @param int $new - new value.
1004 * @param int $customer_id - customer object id who made this change.
1005 * @return void
1006 */
1007 public static function change_raised_by( $ticket, $prev, $new, $customer_id ) {
1008
1009 $agents = array();
1010
1011 $prev_user = $prev->user;
1012 if ( $prev_user ) {
1013 $prev_agent = self::get_by_user_id( $prev_user->ID );
1014 if ( $prev_agent->id && $prev_agent->is_active ) {
1015 $agents[] = $prev_agent;
1016 }
1017 }
1018
1019 $new_user = $new->user;
1020 if ( $new_user ) {
1021 $new_agent = self::get_by_user_id( $new_user->ID );
1022 if ( $new_agent->id && $new_agent->is_active ) {
1023 $agents[] = $new_agent;
1024 }
1025 }
1026
1027 if ( $agents ) {
1028 foreach ( $agents as $agent ) {
1029 $agent->reset_unresolved_count();
1030 }
1031 }
1032 }
1033
1034 /**
1035 * Reset unresolved count and workload after archive/restore/delete ticket
1036 *
1037 * @param WPSC_Ticket $ticket - ticket object.
1038 * @return void
1039 */
1040 public static function reset_agent_unresolved_count( $ticket ) {
1041
1042 $tl_advanced = get_option( 'wpsc-tl-ms-advanced' );
1043 if ( in_array( $ticket->status->id, $tl_advanced['closed-ticket-statuses'] ) ) {
1044 return;
1045 }
1046
1047 // reset workload for applicable agents.
1048 foreach ( $ticket->assigned_agent as $agent ) {
1049 if ( ! $agent->is_active ) {
1050 continue;
1051 }
1052 $agent->reset_workload();
1053 }
1054
1055 // reset unresolved for applicable agents.
1056 $agents = $ticket->get_current_read_permission_agents();
1057 foreach ( $agents as $agent ) {
1058 if ( ! $agent->is_active ) {
1059 continue;
1060 }
1061 $agent->reset_unresolved_count();
1062 }
1063 }
1064
1065 /**
1066 * Get editor of the agent
1067 *
1068 * @return string
1069 */
1070 public function get_signature_editor() {
1071
1072 return get_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc_agent_signature_editor', true );
1073 }
1074
1075 /**
1076 * Set editor for current user
1077 *
1078 * @param string $editor - text/html editor for signature.
1079 * @return void
1080 */
1081 public function set_signature_editor( $editor ) {
1082
1083 update_user_meta( $this->user->ID, get_current_blog_id() . '-wpsc_agent_signature_editor', $editor );
1084 }
1085
1086 /**
1087 * Agent autocomplete for admin access only
1088 */
1089 public static function agent_autocomplete_admin_access() {
1090
1091 if ( check_ajax_referer( 'wpsc_agent_autocomplete_admin_access', '_ajax_nonce', false ) !== 1 ) {
1092 wp_send_json_error( 'Unauthorized request!', 401 );
1093 }
1094
1095 if ( ! WPSC_Functions::is_site_admin() ) {
1096 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
1097 }
1098
1099 $filters = array();
1100
1101 $filters['term'] = isset( $_GET['q'] ) ? sanitize_text_field( wp_unslash( $_GET['q'] ) ) : '';
1102 $filters['filter_by'] = isset( $_GET['filter_by'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_by'] ) ) : 'all';
1103 $filters['sort_by'] = isset( $_GET['sort_by'] ) ? sanitize_text_field( wp_unslash( $_GET['sort_by'] ) ) : 'name';
1104 $filters['isMultiple'] = isset( $_GET['isMultiple'] ) ? intval( wp_unslash( $_GET['isMultiple'] ) ) : 0;
1105
1106 $filters['isAgentgroup'] = 0;
1107 if ( class_exists( 'WPSC_Agentgroups' ) ) {
1108 $filters['isAgentgroup'] = isset( $_GET['isAgentgroup'] ) ? intval( $_GET['isAgentgroup'] ) : null;
1109 }
1110
1111 $response = self::agent_autocomplete( $filters );
1112 wp_send_json( $response );
1113 }
1114
1115 /**
1116 * Update unresolved count after agent role capabilities are updated
1117 *
1118 * @param integer $role_id - agent role id.
1119 * @return void
1120 */
1121 public static function agent_role_update( $role_id ) {
1122
1123 if ( ! WPSC_Functions::is_site_admin() ) {
1124 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
1125 }
1126
1127 $args = array(
1128 'meta_query' => array(
1129 'relation' => 'AND',
1130 array(
1131 'slug' => 'role',
1132 'compare' => '=',
1133 'val' => $role_id,
1134 ),
1135 array(
1136 'slug' => 'is_active',
1137 'compare' => '=',
1138 'val' => 1,
1139 ),
1140 ),
1141 );
1142 $agents = self::find( $args )['results'];
1143
1144 foreach ( $agents as $agent ) {
1145
1146 $agent->reset_unresolved_count();
1147 }
1148 }
1149 }
1150 endif;
1151
1152 WPSC_Agent::init();
1153