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

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

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