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

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