PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.5.4
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.5.4
3.5.4 3.5.3 3.5.2 3.5.1 3.4.9 3.5.0 3.4.8 3.4.7 trunk 2.3.1 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6
supportcandy / includes / admin / tickets / class-wpsc-ticket-list.php

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

2,623 lines 83.5 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_Ticket_List' ) ) :
7
8 final class WPSC_Ticket_List {
9
10 /**
11 * All default and saved filters for logged-in user
12 *
13 * @var array
14 */
15 private static $filters;
16
17 /**
18 * Cookie filters to be sent to JS with tickets
19 *
20 * @var array
21 */
22 private static $cookie_filters;
23
24 /**
25 * Ticket found for the filter
26 *
27 * @var array
28 */
29 private static $tickets = array();
30
31 /**
32 * Set if there is next page is available
33 *
34 * @var integer
35 */
36 private static $has_next_page = false;
37
38 /**
39 * Total number of pages
40 *
41 * @var integer
42 */
43 private static $total_pages = 0;
44
45 /**
46 * Total number of tickets found for $filters
47 *
48 * @var integer
49 */
50 private static $total_items = 0;
51
52 /**
53 * Set whether tickets to be queried is active or deleted
54 *
55 * @var integer
56 */
57 public static $is_active = 1;
58
59 /**
60 * Default filters based on logged-in user
61 *
62 * @var array
63 */
64 public static $default_filters;
65
66 /**
67 * Saved filters of logged-in user
68 *
69 * @var array
70 */
71 private static $saved_filters;
72
73 /**
74 * More settings for agent/customer view based on logged-in user
75 *
76 * @var array
77 */
78 public static $more_settings;
79
80 /**
81 * Flag to check whether current filter is numeric default filter or not
82 *
83 * @var integer
84 */
85 private static $default_flag;
86
87 /**
88 * Flag to check whether current filter is saved filter or not
89 *
90 * @var integer
91 */
92 private static $saved_flag;
93
94 /**
95 * Numeric type flag ID for current filter
96 *
97 * @var integer
98 */
99 private static $filter_id = 0;
100
101 /**
102 * Ticket list bulk actions
103 *
104 * @var array
105 */
106 private static $bulk_actions = array();
107
108 /**
109 * Flag for current view
110 *
111 * @var integer
112 */
113 private static $is_frontend = 0;
114
115 /**
116 * Initialize this class
117 *
118 * @return void
119 */
120 public static function init() {
121
122 // Get ticket list ajax request.
123 add_action( 'wp_ajax_wpsc_get_ticket_list', array( __CLASS__, 'layout' ) );
124 add_action( 'wp_ajax_nopriv_wpsc_get_ticket_list', array( __CLASS__, 'layout' ) );
125
126 // Conditions allowed for custom ticket filters.
127 add_filter( 'wpsc_custom_filter_conditions', array( __CLASS__, 'custom_filter_conditions' ) );
128
129 // Get tickets ajax request.
130 add_action( 'wp_ajax_wpsc_get_tickets', array( __CLASS__, 'get_tickets' ) );
131 add_action( 'wp_ajax_nopriv_wpsc_get_tickets', array( __CLASS__, 'get_tickets' ) );
132 add_action( 'wp_ajax_wpsc_get_tl_custom_filter', array( __CLASS__, 'get_tl_custom_filter_ui' ) );
133 add_action( 'wp_ajax_nopriv_wpsc_get_tl_custom_filter', array( __CLASS__, 'get_tl_custom_filter_ui' ) );
134
135 // Saved filters.
136 add_action( 'wp_ajax_wpsc_tl_get_add_saved_filter', array( __CLASS__, 'get_add_saved_filter_ui' ) );
137 add_action( 'wp_ajax_nopriv_wpsc_tl_get_add_saved_filter', array( __CLASS__, 'get_add_saved_filter_ui' ) );
138 add_action( 'wp_ajax_wpsc_tl_set_add_saved_filter', array( __CLASS__, 'set_add_saved_filter' ) );
139 add_action( 'wp_ajax_nopriv_wpsc_tl_set_add_saved_filter', array( __CLASS__, 'set_add_saved_filter' ) );
140 add_action( 'wp_ajax_wpsc_tl_get_edit_saved_filter', array( __CLASS__, 'get_edit_saved_filter_ui' ) );
141 add_action( 'wp_ajax_nopriv_wpsc_tl_get_edit_saved_filter', array( __CLASS__, 'get_edit_saved_filter_ui' ) );
142 add_action( 'wp_ajax_wpsc_tl_set_edit_saved_filter', array( __CLASS__, 'set_edit_saved_filter' ) );
143 add_action( 'wp_ajax_nopriv_wpsc_tl_set_edit_saved_filter', array( __CLASS__, 'set_edit_saved_filter' ) );
144 add_action( 'wp_ajax_wpsc_tl_delete_saved_filter', array( __CLASS__, 'delete_saved_filter' ) );
145 add_action( 'wp_ajax_nopriv_wpsc_tl_delete_saved_filter', array( __CLASS__, 'delete_saved_filter' ) );
146
147 // Bulk actions.
148 add_action( 'wp_ajax_wpsc_bulk_change_status', array( __CLASS__, 'bulk_change_status' ) );
149 add_action( 'wp_ajax_nopriv_wpsc_bulk_change_status', array( __CLASS__, 'bulk_change_status' ) );
150 add_action( 'wp_ajax_wpsc_set_bulk_change_status', array( __CLASS__, 'set_bulk_change_status' ) );
151 add_action( 'wp_ajax_nopriv_wpsc_set_bulk_change_status', array( __CLASS__, 'set_bulk_change_status' ) );
152 add_action( 'wp_ajax_wpsc_bulk_assign_agents', array( __CLASS__, 'bulk_assign_agents' ) );
153 add_action( 'wp_ajax_nopriv_wpsc_bulk_assign_agents', array( __CLASS__, 'bulk_assign_agents' ) );
154 add_action( 'wp_ajax_wpsc_set_bulk_assign_agent', array( __CLASS__, 'set_bulk_assign_agent' ) );
155 add_action( 'wp_ajax_nopriv_wpsc_set_bulk_assign_agent', array( __CLASS__, 'set_bulk_assign_agent' ) );
156
157 add_action( 'wp_ajax_wpsc_bulk_assign_tags', array( __CLASS__, 'bulk_assign_tags' ) );
158 add_action( 'wp_ajax_nopriv_wpsc_bulk_assign_tags', array( __CLASS__, 'bulk_assign_tags' ) );
159 add_action( 'wp_ajax_wpsc_set_bulk_assign_tag', array( __CLASS__, 'set_bulk_assign_tag' ) );
160 add_action( 'wp_ajax_nopriv_wpsc_set_bulk_assign_tag', array( __CLASS__, 'set_bulk_assign_tag' ) );
161
162 add_action( 'wp_ajax_wpsc_bulk_delete_tickets', array( __CLASS__, 'bulk_delete_tickets' ) );
163 add_action( 'wp_ajax_nopriv_wpsc_bulk_delete_tickets', array( __CLASS__, 'bulk_delete_tickets' ) );
164 add_action( 'wp_ajax_wpsc_bulk_restore_tickets', array( __CLASS__, 'bulk_restore_tickets' ) );
165 add_action( 'wp_ajax_nopriv_wpsc_bulk_restore_tickets', array( __CLASS__, 'bulk_restore_tickets' ) );
166 add_action( 'wp_ajax_wpsc_bulk_delete_tickets_permanently', array( __CLASS__, 'bulk_delete_tickets_permanently' ) );
167 add_action( 'wp_ajax_nopriv_wpsc_bulk_delete_tickets_permanently', array( __CLASS__, 'bulk_delete_tickets_permanently' ) );
168
169 add_action( 'wp_ajax_wpsc_bulk_archive_tickets', array( __CLASS__, 'bulk_archive_tickets' ) );
170 add_action( 'wp_ajax_nopriv_wpsc_bulk_archive_tickets', array( __CLASS__, 'bulk_archive_tickets' ) );
171
172 add_action( 'wp_ajax_wpsc_bulk_permanently_delete_tickets', array( __CLASS__, 'bulk_permanently_delete_tickets' ) );
173 add_action( 'wp_ajax_nopriv_wpsc_bulk_permanently_delete_tickets', array( __CLASS__, 'bulk_permanently_delete_tickets' ) );
174
175 // agent autocomplete assign cap access check.
176 add_action( 'wp_ajax_wpsc_agent_autocomplete_bulk_assign', array( __CLASS__, 'agent_autocomplete_bulk_assign' ) );
177 add_action( 'wp_ajax_nopriv_wpsc_agent_autocomplete_bulk_assign', array( __CLASS__, 'agent_autocomplete_bulk_assign' ) );
178
179 // get updated nonce for frontend.
180 add_action( 'wp_ajax_wpsc_get_nonce', array( __CLASS__, 'get_nonce' ) );
181
182 // filter ticket list by tags.
183 add_action( 'init', array( __CLASS__, 'apply_tag_custom_filter' ), 100 );
184
185 // get updated nonce for backend.
186 add_filter( 'heartbeat_received', array( __CLASS__, 'get_nonce_heartbeat' ), 10, 2 );
187 }
188
189 /**
190 * Ajax callback for Ticket list section
191 *
192 * @return void
193 */
194 public static function layout() {
195
196 self::load_tickets();
197 self::set_bulk_actions();
198 self::get_filters();
199 self::get_ticket_list();
200 self::print_tl_snippets();
201 wp_die();
202 }
203
204 /**
205 * Ajax callback for get_tickets on ticket list with filters and page
206 *
207 * @return void
208 */
209 public static function get_tickets() {
210
211 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
212 wp_send_json_error( 'Unauthorized request!', 401 );
213 }
214
215 self::$is_frontend = isset( $_POST['is_frontend'] ) ? sanitize_text_field( wp_unslash( $_POST['is_frontend'] ) ) : '0';
216
217 self::load_tickets();
218 self::set_bulk_actions();
219 $filters = self::$cookie_filters;
220 $filters['filters'] = isset( $filters['filters'] ) ? $filters['filters'] : '[]';
221
222 $response = array(
223 'tickets' => self::print_tickets(),
224 'filter_actions' => self::get_filter_actions(),
225 'bulk_actions' => self::get_bulk_actions(),
226 'pagination_str' => self::get_pagination_str(),
227 'pagination' => array(
228 'current_page' => self::$filters['page_no'],
229 'has_next_page' => self::$has_next_page,
230 'total_pages' => self::$total_pages,
231 'total_items' => self::$total_items,
232 ),
233 'filters' => $filters,
234 );
235 wp_send_json( $response );
236 }
237
238 /**
239 * Load tickets based on current filter
240 *
241 * @return void
242 */
243 private static function load_tickets() {
244
245 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
246 wp_send_json_error( 'Unauthorized request!', 401 );
247 }
248
249 $current_user = WPSC_Current_User::$current_user;
250 if ( ! $current_user->is_customer ) {
251 wp_send_json_error( new WP_Error( '001', 'Unauthorized!' ), 400 );
252 }
253
254 self::$is_frontend = isset( $_POST['is_frontend'] ) ? sanitize_text_field( wp_unslash( $_POST['is_frontend'] ) ) : '0';
255
256 $filters = null;
257
258 // check whether filters are given in post.
259 $filters = isset( $_POST['filters'] ) ? map_deep( wp_unslash( $_POST['filters'] ), 'sanitize_text_field' ) : array();
260
261 // get filters from cookies.
262 $tl_filters = isset( $_COOKIE['wpsc-tl-filters'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wpsc-tl-filters'] ) ) : '';
263
264 // use cookie filter if filters are not given.
265 $filters = $filters == null && $tl_filters ? json_decode( $tl_filters, true ) : $filters;
266
267 $customer_view = get_option( 'wpsc-tl-ms-customer-view', array() );
268 self::$more_settings = get_option( $current_user->is_agent ? 'wpsc-tl-ms-agent-view' : 'wpsc-tl-ms-customer-view' );
269
270 $current_user_filters = $current_user->get_tl_filters();
271 self::$default_filters = $current_user_filters['default'];
272 self::$saved_filters = $current_user_filters['saved'];
273
274 if ( ! $filters || ! self::has_filter_access( $filters ) ) {
275 $filters = array(
276 'filterSlug' => $current_user->is_agent ? $current_user->agent->get_default_filter() : $customer_view['default-filter'],
277 );
278 if ( isset( self::$default_filters[ $filters['filterSlug'] ] ) ) {
279 $filters['orderby'] = self::$more_settings['default-sort-by'];
280 $filters['order'] = self::$more_settings['default-sort-order'];
281 }
282 }
283
284 self::$default_flag = preg_match( '/default-(\d*)$/', $filters['filterSlug'], $default_matches );
285 if ( self::$default_flag ) {
286 self::$filter_id = $default_matches[1];
287 }
288
289 self::$saved_flag = preg_match( '/saved-(\d*)$/', $filters['filterSlug'], $saved_matches );
290 if ( self::$saved_flag ) {
291 self::$filter_id = $saved_matches[1];
292 }
293
294 // Order by.
295 if ( ! isset( $filters['orderby'] ) && ! self::$default_flag && isset( self::$default_filters[ $filters['filterSlug'] ] ) ) {
296 $filters['orderby'] = self::$more_settings['default-sort-by'];
297 }
298 if ( ! isset( $filters['orderby'] ) && self::$default_flag ) {
299 $filters['orderby'] = self::$default_filters[ self::$filter_id ]['sort-by'];
300 }
301 if ( ! isset( $filters['orderby'] ) && self::$saved_flag ) {
302 $filters['orderby'] = self::$saved_filters[ self::$filter_id ]['sort-by'];
303 }
304
305 // Order.
306 if ( ! isset( $filters['order'] ) && ! self::$default_flag && isset( self::$default_filters[ $filters['filterSlug'] ] ) ) {
307 $filters['order'] = self::$more_settings['default-sort-order'];
308 }
309 if ( ! isset( $filters['order'] ) && self::$default_flag ) {
310 $filters['order'] = self::$default_filters[ self::$filter_id ]['sort-order'];
311 }
312 if ( ! isset( $filters['order'] ) && self::$saved_flag ) {
313 $filters['order'] = self::$saved_filters[ self::$filter_id ]['sort-order'];
314 }
315
316 // Search.
317 $filters['search'] = isset( $filters['search'] ) ? sanitize_text_field( $filters['search'] ) : '';
318
319 // Current page number.
320 $filters['page_no'] = isset( $filters['page_no'] ) ? intval( $filters['page_no'] ) : 1;
321
322 // Set cookie here so that front-end should have access to filters until here only.
323 setcookie( 'wpsc-tl-filters', wp_json_encode( $filters ), time() + 3600 );
324 self::$cookie_filters = $filters;
325
326 $filters['items_per_page'] = self::$more_settings['number-of-tickets'];
327
328 // System query.
329 $filters['system_query'] = $current_user->get_tl_system_query( $filters );
330
331 // Meta query.
332 $meta_query = array( 'relation' => 'AND' );
333
334 if (
335 isset( self::$default_filters[ $filters['filterSlug'] ] ) ||
336 ( self::$default_flag && isset( self::$default_filters[ self::$filter_id ] ) ) ||
337 ( self::$saved_flag && isset( self::$saved_filters[ self::$filter_id ] ) ) ||
338 $filters['filterSlug'] == 'custom'
339 ) {
340
341 $slug = self::$default_flag || self::$saved_flag ? self::$filter_id : '';
342 if ( ! $slug ) {
343 $slug = $filters['filterSlug'];
344 }
345
346 $parent_slug = is_numeric( $slug ) && self::$default_flag ? self::$default_filters[ $slug ]['parent-filter'] : '';
347 if ( ! $parent_slug && is_numeric( $slug ) && self::$saved_flag ) {
348 $parent_slug = self::$saved_filters[ $slug ]['parent-filter'];
349 }
350 if ( ! $parent_slug && $slug == 'custom' ) {
351 $parent_slug = $filters['parent-filter'];
352 }
353 if ( ! $parent_slug ) {
354 $parent_slug = $slug;
355 }
356
357 // Get parent meta queries.
358 $meta_query = array_merge( $meta_query, self::get_parent_meta_query( $parent_slug ) );
359
360 if ( self::$default_flag ) {
361 $meta_query = array_merge( $meta_query, WPSC_Ticket_Conditions::get_meta_query( self::$default_filters[ $slug ]['filters'] ) );
362 }
363
364 if ( self::$saved_flag ) {
365 $json_str = str_replace( PHP_EOL, '\n', self::$saved_filters[ $slug ]['filters'] );
366 $meta_query = array_merge( $meta_query, WPSC_Ticket_Conditions::get_meta_query( $json_str, true ) );
367 }
368
369 if ( $filters['filterSlug'] == 'custom' ) {
370 $meta_query = array_merge( $meta_query, WPSC_Ticket_Conditions::get_meta_query( $filters['filters'], true ) );
371 }
372 }
373
374 $filters['meta_query'] = $meta_query;
375 $filters['is_active'] = self::$is_active;
376 self::$filters = apply_filters( 'wpsc_ticket_list_filters', $filters );
377
378 $response = WPSC_Ticket::find( self::$filters );
379 self::$tickets = $response['results'];
380 self::$total_items = intval( $response['total_items'] );
381 self::$total_pages = intval( $response['total_pages'] );
382 self::$has_next_page = $response['has_next_page'];
383 }
384
385 /**
386 * Print ticket filters layout
387 *
388 * @return void
389 */
390 private static function get_filters() {
391
392 $current_user = WPSC_Current_User::$current_user;
393 $custom_fields = WPSC_Custom_Field::$custom_fields;
394 $list_items = $current_user->get_tl_list_items();
395
396 ?>
397 <div class="wpsc-filter">
398 <div class="wpsc-search">
399 <div class="search-field">
400 <?php WPSC_Icons::get( 'search' ); ?>
401 <input class="wpsc-search-input" type="text" placeholder="<?php esc_attr_e( 'Search...', 'supportcandy' ); ?>" spellcheck="false" value="<?php echo esc_attr( stripslashes( self::$filters['search'] ) ); ?>" onkeyup="wpsc_tl_search_keyup(event, this, 'ticket_list');"/>
402 </div>
403 </div>
404 <div class="wpsc-filter-container">
405 <div class="wpsc-filter-item">
406 <label for="wpsc-input-filter"><?php esc_attr_e( 'Filter', 'supportcandy' ); ?></label>
407 <select id="wpsc-input-filter" class="wpsc-input-filter" name="filter" onchange="wpsc_tl_filter_change(this, 'ticket_list');">
408
409 <optgroup label="<?php esc_attr_e( 'Default filters', 'supportcandy' ); ?>">
410 <?php
411 foreach ( self::$default_filters as $index => $filter ) :
412 $selected = '';
413 if ( self::$filters['filterSlug'] == $index ) {
414 $selected = 'selected="selected"';
415 }
416 if ( ! $selected && self::$default_flag && self::$filters['filterSlug'] == 'default-' . $index ) {
417 $selected = 'selected="selected"';
418 }
419 ?>
420 <option <?php echo esc_attr( $selected ); ?> value="<?php echo is_numeric( $index ) ? 'default-' . esc_attr( $index ) : esc_attr( $index ); ?>">
421 <?php
422 $filter_label = $filter['label'] ? WPSC_Translations::get( 'wpsc-atl-' . $index, stripslashes( $filter['label'] ) ) : stripslashes( $filter['label'] );
423 echo esc_attr( $filter_label )
424 ?>
425 </option>
426 <?php
427 endforeach;
428 ?>
429 </optgroup>
430 <?php
431
432 if ( ! $current_user->is_guest ) :
433 ?>
434 <optgroup label="<?php esc_attr_e( 'Saved filters', 'supportcandy' ); ?>">
435 <?php
436 foreach ( self::$saved_filters as $index => $filter ) :
437 $selected = '';
438 if ( self::$saved_flag && self::$filters['filterSlug'] == 'saved-' . $index ) {
439 $selected = 'selected="selected"';
440 }
441 ?>
442 <option <?php echo esc_attr( $selected ); ?> value="saved-<?php echo esc_attr( $index ); ?>"><?php echo esc_attr( $filter['label'] ); ?></option>
443 <?php
444 endforeach;
445 ?>
446 </optgroup>
447 <?php
448 endif;
449 ?>
450
451 <optgroup label="<?php esc_attr_e( 'Custom filters', 'supportcandy' ); ?>">
452 <option <?php selected( self::$filters['filterSlug'], 'custom' ); ?> value="custom"><?php esc_attr_e( 'Custom...', 'supportcandy' ); ?></option>
453 </optgroup>
454
455 </select>
456 </div>
457 <div class="wpsc-filter-item">
458 <label for="wpsc-input-sort-by"><?php esc_attr_e( 'Sort By', 'supportcandy' ); ?></label>
459 <select id="wpsc-input-sort-by" class="wpsc-input-sort-by" name="sort-by">
460 <?php
461 foreach ( $list_items as $slug ) :
462 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
463 if ( ! $cf || ! $cf->type::$is_sort ) {
464 continue;
465 }
466 ?>
467 <option <?php selected( $cf->slug, self::$filters['orderby'] ); ?> value="<?php echo esc_attr( $cf->slug ); ?>"><?php echo esc_attr( $cf->name ); ?></option>
468 <?php
469 endforeach;
470 ?>
471 </select>
472 </div>
473 <div class="wpsc-filter-item">
474 <select id="wpsc-input-sort-order" class="wpsc-input-sort-order" name="sort-order">
475 <option <?php selected( self::$filters['order'], 'ASC' ); ?> value="ASC"><?php esc_attr_e( 'ASC', 'supportcandy' ); ?></option>
476 <option <?php selected( self::$filters['order'], 'DESC' ); ?> value="DESC"><?php esc_attr_e( 'DESC', 'supportcandy' ); ?></option>
477 </select>
478 </div>
479 <div class="wpsc-filter-submit">
480 <button class="wpsc-button normal primary margin-right" onclick="wpsc_tl_apply_filter_btn_click( 'ticket_list' );"><?php esc_attr_e( 'Apply', 'supportcandy' ); ?></button>
481 <div class="wpsc-filter-actions">
482 <?php echo self::get_filter_actions(); // phpcs:ignore?>
483 </div>
484 </div>
485 </div>
486 </div>
487 <?php
488 }
489
490 /**
491 * Get filter actions based on current filter applied
492 *
493 * @return string
494 */
495 private static function get_filter_actions() {
496
497 $actions = array(
498 'reset' => array(
499 'label' => esc_attr__( 'Reset', 'supportcandy' ),
500 'callback' => 'wpsc_tl_reset_filter',
501 ),
502 );
503
504 if ( self::$saved_flag || self::$filters['filterSlug'] == 'custom' ) {
505 $actions['edit'] = array(
506 'label' => esc_attr__( 'Edit', 'supportcandy' ),
507 'callback' => 'wpsc_tl_edit_filter',
508 );
509 }
510
511 if ( self::$saved_flag ) {
512 $actions['delete'] = array(
513 'label' => esc_attr__( 'Delete', 'supportcandy' ),
514 'callback' => 'wpsc_tl_delete_saved_filter',
515 );
516 }
517
518 $actions_arr = array();
519 foreach ( $actions as $key => $action ) :
520 ob_start();
521 ?>
522 <span
523 class="wpsc-link"
524 onclick="<?php echo esc_attr( $action['callback'] ) . '( \'ticket_list\' );'; ?>">
525 <?php echo esc_attr( $action['label'] ); ?>
526 </span>
527 <?php
528 $actions_arr[] = ob_get_clean();
529 endforeach;
530
531 return implode( '<div class="action-devider"></div>', $actions_arr );
532 }
533
534 /**
535 * Print ticket list layout along with first page tickets
536 *
537 * @return void
538 */
539 private static function get_ticket_list() {
540
541 $current_user = WPSC_Current_User::$current_user;
542 $pagination_html = self::get_pagination_html();
543 ?>
544
545 <div class="wpsc-tickets-container">
546 <div class="wpsc-bulk-actions">
547 <?php
548 if ( $current_user->is_agent && self::$bulk_actions ) :
549 ?>
550 <button
551 id="wpsc-bulk-actions-btn"
552 class="wpsc-button small secondary"
553 type="button"
554 data-popover="wpsc-bulk-actions">
555 <?php esc_attr_e( 'Bulk Actions', 'supportcandy' ); ?>
556 <?php WPSC_Icons::get( 'chevron-down' ); ?>
557 </button>
558 <div id="wpsc-bulk-actions" class="gpopover wpsc-popover-menu wpsc-ticket-bulk-actions" >
559 <?php
560 echo self::get_bulk_actions(); // phpcs:ignore
561 ?>
562 </div>
563 <?php
564 endif;
565 ?>
566 <button
567 id="wpsc-more-actions-btn"
568 class="wpsc-button small secondary"
569 type="button"
570 data-popover="wpsc-more-actions">
571 <?php esc_attr_e( 'List Actions', 'supportcandy' ); ?>
572 <?php WPSC_Icons::get( 'chevron-down' ); ?>
573 </button>
574 <div id="wpsc-more-actions" class="gpopover wpsc-popover-menu">
575 <?php
576 $more_actions = apply_filters(
577 'wpsc_admin_tl_more_actions',
578 array(
579 'refresh' => array(
580 'icon' => 'sync',
581 'label' => esc_attr__( 'Refresh', 'supportcandy' ),
582 'callback' => 'wpsc_get_tickets',
583 ),
584 'auto-refresh' => array(
585 'icon' => 'history',
586 'label' => esc_attr__( 'Auto-Refresh', 'supportcandy' ),
587 'callback' => 'wpsc_get_tl_auto_refresh',
588 ),
589 )
590 );
591 foreach ( $more_actions as $action ) :
592 ?>
593 <div class="wpsc-popover-menu-item" onclick="<?php echo esc_attr( $action['callback'] ) . '(\'' . esc_attr( wp_create_nonce( $action['callback'] ) ) . '\');'; ?>">
594 <?php WPSC_Icons::get( $action['icon'] ); ?>
595 <span><?php echo esc_attr( $action['label'] ); ?></span>
596 </div>
597 <?php
598 endforeach;
599 ?>
600 </div>
601 <script>
602 jQuery('#wpsc-more-actions-btn, #wpsc-bulk-actions-btn').gpopover({width: 200});
603 </script>
604 <div class="wpsc-ticket-pagination-header wpsc-hidden-xs">
605 <?php echo $pagination_html; // phpcs:ignore?>
606 </div>
607 </div>
608
609 <div class="wpsc-ticket-list">
610 <?php echo self::print_tickets(); // phpcs:ignore?>
611 </div>
612
613 <div class="wpsc-ticket-pagination-footer">
614 <?php echo $pagination_html; // phpcs:ignore?>
615 </div>
616 <script>
617 jQuery( document ).ready(function() {
618 wpsc_check_nonce();
619 });
620 function wpsc_check_nonce(){
621
622 if( supportcandy.current_section != 'ticket-list' || supportcandy.is_frontend === '0' ){
623 return;
624 }
625
626 var data = { action: 'wpsc_get_nonce' };
627 jQuery.post(
628 supportcandy.ajax_url,
629 data,
630 function (response) {
631 supportcandy.nonce = response.general;
632 setTimeout(() => {
633 wpsc_check_nonce();
634 }, 60000);
635 }
636 );
637 }
638
639 jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
640 data.wpsc_heartbeat = 'get_nonce';
641 });
642
643 jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
644 if ( ! data.general ) {
645 return;
646 }
647 supportcandy.nonce = data.general;
648 });
649 </script>
650 </div>
651 <?php
652 }
653
654 /**
655 * Return HTML content of pagination section
656 */
657 private static function get_pagination_html() {
658
659 $pagination_str = self::get_pagination_str();
660 $btn_style = self::$total_items <= self::$more_settings['number-of-tickets'] ? 'display:none;' : '';
661 ob_start();
662 ?>
663
664 <span
665 class="wpsc-pagination-btn wpsc-pagination-first wpsc-link"
666 style="<?php echo esc_attr( $btn_style ); ?>"
667 onclick="wpsc_tl_set_page('first', 'ticket_list');">
668 <?php esc_attr_e( 'First Page', 'supportcandy' ); ?>
669 </span>
670 <?php
671 if ( is_rtl() ) {
672 ?>
673 <span
674 class="wpsc-pagination-btn wpsc-pagination-next wpsc-link"
675 style="<?php echo esc_attr( $btn_style ); ?>"
676 onclick="wpsc_tl_set_page('next', 'ticket_list');">
677 <?php WPSC_Icons::get( 'chevron-right' ); ?>
678 </span>
679 <?php
680 } else {
681 ?>
682 <span
683 class="wpsc-pagination-btn wpsc-pagination-prev wpsc-link"
684 style="<?php echo esc_attr( $btn_style ); ?>"
685 onclick="wpsc_tl_set_page('prev', 'ticket_list');">
686 <?php WPSC_Icons::get( 'chevron-left' ); ?>
687 </span>
688 <?php
689 }
690 ?>
691 <span class="wpsc-pagination-txt"><?php echo esc_attr( $pagination_str ); ?></span>
692 <?php
693 if ( is_rtl() ) {
694 ?>
695 <span
696 class="wpsc-pagination-btn wpsc-pagination-prev wpsc-link"
697 style="<?php echo esc_attr( $btn_style ); ?>"
698 onclick="wpsc_tl_set_page('prev', 'ticket_list');">
699 <?php WPSC_Icons::get( 'chevron-left' ); ?>
700 </span>
701 <?php
702 } else {
703 ?>
704 <span
705 class="wpsc-pagination-btn wpsc-pagination-next wpsc-link"
706 style="<?php echo esc_attr( $btn_style ); ?>"
707 onclick="wpsc_tl_set_page('next', 'ticket_list');">
708 <?php WPSC_Icons::get( 'chevron-right' ); ?>
709 </span>
710 <?php
711 }
712 ?>
713 <span
714 class="wpsc-pagination-btn wpsc-pagination-last wpsc-link"
715 style="<?php echo esc_attr( $btn_style ); ?>"
716 onclick="wpsc_tl_set_page('last', 'ticket_list');">
717 <?php esc_attr_e( 'Last Page', 'supportcandy' ); ?>
718 </span>
719 <?php
720
721 return ob_get_clean();
722 }
723
724 /**
725 * Pagination string
726 *
727 * @return string
728 */
729 private static function get_pagination_str() {
730
731 if ( self::$total_items < 1 ) {
732 return '';
733 }
734
735 if ( self::$total_items == 1 ) {
736 return esc_attr__( '1 Ticket', 'supportcandy' );
737 }
738
739 if ( self::$total_items <= self::$more_settings['number-of-tickets'] ) {
740 /* translators: %1$s: total tickets */
741 return sprintf( esc_attr__( '%1$d Tickets', 'supportcandy' ), self::$total_items );
742 }
743
744 $from = ( self::$more_settings['number-of-tickets'] * ( self::$filters['page_no'] - 1 ) ) + 1;
745 $to = self::$filters['page_no'] == self::$total_pages ?
746 self::$total_items :
747 self::$more_settings['number-of-tickets'] * self::$filters['page_no'];
748
749 /* translators: e.g. 1-20 of 100 Tickets */
750 return sprintf( esc_attr__( '%1$d-%2$d of %3$d Tickets', 'supportcandy' ), $from, $to, self::$total_items );
751 }
752
753 /**
754 * Get tickets based on current filter
755 *
756 * @return string
757 */
758 private static function print_tickets() {
759
760 ob_start();
761 $current_user = WPSC_Current_User::$current_user;
762 $list_items = $current_user->get_tl_list_items();
763 ?>
764
765 <div style="overflow-x:auto;">
766 <table class="wpsc-ticket-list-tbl">
767
768 <thead>
769 <tr>
770 <?php
771
772 if ( $current_user->is_agent && self::$bulk_actions ) :
773 ?>
774 <th style="width: 45px;">
775 <div class="checkbox-container">
776 <?php $unique_id = uniqid( 'wpsc_' ); ?>
777 <input id="<?php echo esc_attr( $unique_id ); ?>" class="wpsc-bulk-selector" type="checkbox" onchange="wpsc_bulk_select_change();"/>
778 <label for="<?php echo esc_attr( $unique_id ); ?>"></label>
779 </div>
780 </th>
781 <?php
782 endif;
783 do_action( 'wpsc_print_ticket_list_th' );
784 foreach ( $list_items as $slug ) :
785 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
786 if ( ! $cf ) {
787 continue;
788 }
789 $is_sortable = $cf->type::$is_sort;
790 $is_active = $is_sortable && self::$filters['orderby'] === $slug;
791 $order = $is_active ? self::$filters['order'] : '';
792 ?>
793 <th
794 style="min-width: <?php echo esc_attr( $cf->tl_width ); ?>px;"
795 <?php if ( $is_sortable ) : ?>
796 class="wpsc-tl-sortable-th<?php echo $is_active ? ' wpsc-tl-sorted-' . esc_attr( strtolower( $order ) ) : ''; ?>"
797 onclick="wpsc_tl_sort_column('<?php echo esc_attr( $slug ); ?>', 'ticket_list');"
798 <?php endif; ?>
799 >
800 <?php if ( $is_sortable ) : ?>
801 <div class="wpsc-tl-th-inner">
802 <span class="wpsc-tl-th-label"><?php echo esc_attr( $cf->name ); ?></span>
803 <span class="wpsc-tl-sort-icon">
804 <?php WPSC_Icons::get( 'ASC' === $order ? 'chevron-up' : ( 'DESC' === $order ? 'chevron-down' : 'sort' ) ); ?>
805 </span>
806 </div>
807 <?php else : ?>
808 <span class="wpsc-tl-th-label"><?php echo esc_attr( $cf->name ); ?></span>
809 <?php endif; ?>
810 </th>
811 <?php
812 endforeach;
813 ?>
814
815 </tr>
816 </thead>
817
818 <tbody>
819 <?php
820
821 if ( self::$tickets ) {
822
823 foreach ( self::$tickets as $ticket ) :
824 $class = apply_filters( 'wpsc_ticket_list_tr_classes', array( 'wpsc_tl_tr' ), $ticket );
825 $url = WPSC_Functions::get_ticket_url( $ticket->id, self::$is_frontend );
826 ?>
827 <tr class="<?php echo esc_attr( implode( ' ', $class ) ); ?>" onclick="if(link)wpsc_tl_handle_click(event, <?php echo esc_attr( $ticket->id ); ?>, '<?php echo esc_url( $url ); ?>')">
828 <?php
829 if ( $current_user->is_agent && self::$bulk_actions ) :
830 ?>
831 <td class="bulk-selector" onmouseover="link=false;" onmouseout="link=true;">
832 <div class="wpsc-tl-item-selector">
833 <div class="checkbox-container">
834 <?php $unique_id = uniqid( 'wpsc_' ); ?>
835 <input id="<?php echo esc_attr( $unique_id ); ?>" class="wpsc-bulk-select" type="checkbox" onchange="wpsc_bulk_item_select_change();" value="<?php echo esc_attr( $ticket->id ); ?>"/>
836 <label for="<?php echo esc_attr( $unique_id ); ?>"></label>
837 </div>
838 </div>
839 </td>
840 <?php
841 endif;
842 do_action( 'wpsc_print_ticket_list_td', $ticket );
843 foreach ( $list_items as $slug ) :
844 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
845 if ( ! $cf ) {
846 continue;
847 }
848 ?>
849 <td onmouseover="link=true;">
850 <?php
851 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ) {
852 $cf->type::print_tl_ticket_field_val( $cf, $ticket );
853 } else {
854 $cf->type::print_tl_customer_field_val( $cf, $ticket->customer );
855 }
856 ?>
857 </td>
858 <?php
859 endforeach;
860 ?>
861 </tr>
862 <?php
863 endforeach;
864
865 } else {
866
867 $col_span = count( $list_items );
868 if ( $current_user->is_agent && self::$bulk_actions ) {
869 ++$col_span;
870 }
871 ?>
872 <tr><td colspan="<?php echo esc_attr( $col_span ); ?>" style="text-align:left;"><?php esc_attr_e( 'No tickets found!', 'supportcandy' ); ?></td></tr>
873 <?php
874
875 }
876 ?>
877
878 </tbody>
879
880 </table>
881 </div>
882 <script>
883 function wpsc_tl_handle_click(event, id, url) {
884 if ( ( event.ctrlKey || event.metaKey ) && url ) {
885 window.open(url, '_blank');
886 } else {
887 wpsc_get_individual_ticket(id);
888 }
889 }
890 </script>
891 <?php
892
893 return ob_get_clean();
894 }
895
896 /**
897 * Ticket list snippets. It may include static modal screens, JS initializers, etc.
898 *
899 * @return void
900 */
901 public static function print_tl_snippets() {
902
903 $filters = self::$cookie_filters;
904 $filter_json = isset( $filters['filters'] ) && $filters['filters'] ? $filters['filters'] : '[]';
905 $filters['filters'] = $filter_json;
906
907 $ticket_list_js_vars = array(
908 'pagination' => array(
909 'current_page' => self::$filters['page_no'],
910 'has_next_page' => self::$has_next_page,
911 'total_pages' => self::$total_pages,
912 'total_items' => self::$total_items,
913 ),
914 'filters' => $filters,
915 );
916
917 $advanced_settings = get_option( 'wpsc-tl-ms-advanced', array() );
918 ?>
919
920 <div class="wpsc-tl_snippets" style="display:none;">
921 <div class="auto-refresh">
922 <div class="modal-header">
923 <?php esc_attr_e( 'Auto-Refresh', 'supportcandy' ); ?>
924 </div>
925 <div class="modal-body">
926 <div class="wpsc-toggle-btn">
927 <div class="toggle-off" onclick="wpsc_toggle_off(this);">
928 <?php esc_attr_e( 'OFF', 'supportcandy' ); ?>
929 </div>
930 <div class="toggle-on" onclick="wpsc_toggle_on(this);">
931 <?php esc_attr_e( 'ON', 'supportcandy' ); ?>
932 </div>
933 <input type="hidden" value="0">
934 </div>
935 </div>
936 <div class="modal-footer">
937 <button class="wpsc-button small primary" onclick="wpsc_set_tl_auto_refresh(this);">
938 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
939 </button>
940 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
941 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
942 </button>
943 </div>
944 </div>
945 <script>
946 supportcandy.ticketList = <?php echo wp_json_encode( $ticket_list_js_vars ); ?>;
947 supportcandy.tl_auto_refresh = <?php echo esc_attr( $advanced_settings['auto-refresh-list-status'] ); ?>;
948 if(supportcandy.tl_auto_refresh) { wpsc_tl_auto_refresh(); }
949 </script>
950 <?php do_action( 'wpsc_tl_snippets' ); ?>
951 </div>
952 <?php
953 }
954
955 /**
956 * Check whether current user has access to given filter
957 *
958 * @param array $filters - ticket filters.
959 * @return boolean
960 */
961 public static function has_filter_access( $filters ) {
962
963 $current_user = WPSC_Current_User::$current_user;
964
965 $filter_slug = isset( $filters['filterSlug'] ) ? $filters['filterSlug'] : '';
966
967 if ( ! $filter_slug ) {
968 return false;
969 }
970
971 if ( isset( self::$default_filters[ $filter_slug ] ) ) {
972 return true;
973 }
974
975 $flag = preg_match( '/default-(\d*)$/', $filter_slug, $matches );
976 if ( $flag && isset( self::$default_filters[ $matches[1] ] ) ) {
977 return true;
978 }
979
980 $flag = preg_match( '/saved-(\d*)$/', $filter_slug, $matches );
981 if ( $flag && isset( self::$saved_filters[ $matches[1] ] ) ) {
982 return true;
983 }
984
985 if ( $filter_slug == 'custom' && WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters['filters'] ) ) {
986 return true;
987 }
988
989 return false;
990 }
991
992 /**
993 * Convert UI filters in json format to meta query
994 *
995 * @param array $filters - ticket filters.
996 * @return array
997 */
998 public static function get_meta_query( $filters ) {
999
1000 $meta_query = array();
1001 foreach ( $filters as $slug => $condition ) {
1002
1003 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1004 if ( ! $cf ) {
1005 continue;
1006 }
1007
1008 $val = $cf->type::get_meta_value( $condition );
1009 if ( $val === false ) {
1010 continue;
1011 }
1012
1013 $meta_query[] = array(
1014 'slug' => $slug,
1015 'compare' => $condition['operator'],
1016 'val' => $val,
1017 );
1018 }
1019 return $meta_query;
1020 }
1021
1022 /**
1023 * Return parent meta query
1024 *
1025 * @param string $parent_slug - filter type.
1026 * @return array
1027 */
1028 public static function get_parent_meta_query( $parent_slug ) {
1029
1030 $current_user = WPSC_Current_User::$current_user;
1031 $meta_query = array();
1032 switch ( $parent_slug ) {
1033
1034 case 'all':
1035 break;
1036
1037 case 'unresolved':
1038 if ( ! isset( self::$default_filters['unresolved'] ) ) {
1039 break;
1040 }
1041 $meta_query[] = array(
1042 'slug' => 'status',
1043 'compare' => 'IN',
1044 'val' => self::$more_settings['unresolved-ticket-statuses'],
1045 );
1046 break;
1047
1048 case 'unassigned':
1049 if ( ! isset( self::$default_filters['unassigned'] ) ) {
1050 break;
1051 }
1052 $meta_query[] = array(
1053 'slug' => 'assigned_agent',
1054 'compare' => '=',
1055 'val' => '',
1056 );
1057 break;
1058
1059 case 'mine':
1060 if ( ! isset( self::$default_filters['mine'] ) ) {
1061 break;
1062 }
1063 $meta_query[] = array(
1064 'slug' => 'assigned_agent',
1065 'compare' => '=',
1066 'val' => $current_user->agent->id,
1067 );
1068 $meta_query[] = array(
1069 'slug' => 'status',
1070 'compare' => 'IN',
1071 'val' => self::$more_settings['unresolved-ticket-statuses'],
1072 );
1073 break;
1074
1075 case 'closed':
1076 if ( ! isset( self::$default_filters['closed'] ) ) {
1077 break;
1078 }
1079 $ms_advanced = get_option( 'wpsc-tl-ms-advanced' );
1080 $gs = get_option( 'wpsc-gs-general' );
1081 $closed_statuses = array( $gs['close-ticket-status'] );
1082 $closed_statuses = array_merge( $closed_statuses, $ms_advanced['closed-ticket-statuses'] );
1083 $closed_statuses = array_unique( $closed_statuses );
1084 $meta_query[] = array(
1085 'slug' => 'status',
1086 'compare' => 'IN',
1087 'val' => $closed_statuses,
1088 );
1089 break;
1090
1091 case 'deleted':
1092 if ( isset( self::$default_filters['deleted'] ) && self::$is_active !== 0 ) {
1093 self::$is_active = 0;
1094 }
1095 break;
1096
1097 default:
1098 // Break if not exists.
1099 if ( ! is_numeric( $parent_slug ) || ! isset( self::$default_filters[ $parent_slug ] ) ) {
1100 break;
1101 }
1102
1103 $meta_query = array_merge( $meta_query, self::get_parent_meta_query( self::$default_filters[ $parent_slug ]['parent-filter'] ) );
1104 $meta_query = array_merge( $meta_query, WPSC_Ticket_Conditions::get_meta_query( self::$default_filters[ $parent_slug ]['filters'] ) );
1105 }
1106
1107 return $meta_query;
1108 }
1109
1110 /**
1111 * Custom filter modal pop-up
1112 *
1113 * @return void
1114 */
1115 public static function get_tl_custom_filter_ui() {
1116
1117 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1118 wp_send_json_error( 'Unauthorized request!', 401 );
1119 }
1120
1121 $current_user = WPSC_Current_User::$current_user;
1122 if ( ! ( $current_user->is_agent || $current_user->is_customer ) ) {
1123 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1124 }
1125
1126 $title = esc_attr__( 'Custom filter', 'supportcandy' );
1127 $default_filters = get_option( $current_user->is_agent ? 'wpsc-atl-default-filters' : 'wpsc-ctl-default-filters' );
1128 $list_items = $current_user->get_tl_list_items();
1129 $more_settings = get_option( $current_user->is_agent ? 'wpsc-tl-ms-agent-view' : 'wpsc-tl-ms-customer-view' );
1130
1131 // check whether filters are passed.
1132 $filters = isset( $_POST['filters'] ) ? map_deep( wp_unslash( $_POST['filters'] ), 'sanitize_text_field' ) : array();
1133 $custom_filters = isset( $filters['filters'] ) && WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters['filters'] ) ? $filters['filters'] : '';
1134
1135 ob_start();
1136 ?>
1137 <form action="#" onsubmit="return false;" class="wpsc-tl-custom-filter">
1138 <div class="wpsc-input-group">
1139 <div class="label-container">
1140 <label for="">
1141 <?php esc_attr_e( 'Parent filter', 'supportcandy' ); ?>
1142 <span class="required-char">*</span>
1143 </label>
1144 </div>
1145 <select name="parent-filter">
1146 <?php
1147 foreach ( $default_filters as $slug => $filter ) :
1148 if ( $slug === 'deleted' && $current_user->is_agent && ! $current_user->agent->has_cap( 'dtt-access' ) ) {
1149 continue;
1150 }
1151 $selected = isset( $filters['parent-filter'] ) && $filters['parent-filter'] == $slug ? 'selected="selected"' : ''
1152 ?>
1153 <option <?php echo esc_attr( $selected ); ?> value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_attr( $filter['label'] ); ?></option>
1154 <?php
1155 endforeach;
1156 ?>
1157 </select>
1158 </div>
1159 <?php WPSC_Ticket_Conditions::print( 'custom_filters', 'wpsc_custom_filter_conditions', $custom_filters, true, __( 'Filters', 'supportcandy' ) ); ?>
1160 <div class="wpsc-input-group">
1161 <div class="label-container">
1162 <label for="">
1163 <?php esc_attr_e( 'Sort by', 'supportcandy' ); ?>
1164 <span class="required-char">*</span>
1165 </label>
1166 </div>
1167 <select name="sort-by">
1168 <?php
1169 $orderby = isset( $filters['orderby'] ) ? $filters['orderby'] : $more_settings['default-sort-by'];
1170 foreach ( $list_items as $slug ) :
1171 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1172 if ( ! $cf ) {
1173 continue;
1174 }
1175 if ( $cf->type::$is_sort ) :
1176 ?>
1177 <option <?php selected( $orderby, $cf->slug ); ?> value="<?php echo esc_attr( $cf->slug ); ?>"><?php echo esc_attr( $cf->name ); ?></option>
1178 <?php
1179 endif;
1180 endforeach;
1181 ?>
1182 </select>
1183 </div>
1184 <div class="wpsc-input-group">
1185 <div class="label-container">
1186 <label for="">
1187 <?php esc_attr_e( 'Sort order', 'supportcandy' ); ?>
1188 <span class="required-char">*</span>
1189 </label>
1190 </div>
1191 <select name="sort-order">
1192 <?php
1193 $order = isset( $filters['order'] ) ? $filters['order'] : $more_settings['default-sort-order'];
1194 ?>
1195 <option <?php selected( $order, 'ASC' ); ?> value="ASC"><?php esc_attr_e( 'ASC', 'supportcandy' ); ?></option>
1196 <option <?php selected( $order, 'DESC' ); ?> value="DESC"><?php esc_attr_e( 'DESC', 'supportcandy' ); ?></option>
1197 </select>
1198 </div>
1199 </form>
1200 <?php
1201 $body = ob_get_clean();
1202
1203 ob_start();
1204 ?>
1205 <button class="wpsc-button small primary" onclick="wpsc_tl_apply_custom_filter(this, 'ticket_list');">
1206 <?php esc_attr_e( 'Apply', 'supportcandy' ); ?>
1207 </button>
1208 <?php
1209
1210 if ( ! $current_user->is_guest ) :
1211 ?>
1212 <button class="wpsc-button small secondary" onclick="wpsc_tl_add_saved_filter(this);">
1213 <?php esc_attr_e( 'Save & Apply', 'supportcandy' ); ?>
1214 </button>
1215 <?php
1216 endif;
1217 ?>
1218
1219 <button class="wpsc-button small secondary" onclick="<?php echo $filters ? 'wpsc_close_modal()' : 'wpsc_tl_close_custom_filter_modal()'; ?>;">
1220 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1221 </button>
1222 <?php
1223 $footer = ob_get_clean();
1224
1225 $response = array(
1226 'title' => $title,
1227 'body' => $body,
1228 'footer' => $footer,
1229 );
1230 wp_send_json( $response );
1231 }
1232
1233 /**
1234 * Add saved filter UI
1235 *
1236 * @return void
1237 */
1238 public static function get_add_saved_filter_ui() {
1239
1240 $current_user = WPSC_Current_User::$current_user;
1241 if ( ! $current_user->customer->user->ID ) {
1242 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1243 }
1244
1245 $title = esc_attr__( 'Custom filter', 'supportcandy' );
1246
1247 ob_start();
1248 ?>
1249 <form action="#" onsubmit="return false;" class="wpsc-tl-add-saved-filter">
1250 <div class="wpsc-input-group">
1251 <div class="label-container">
1252 <label for="">
1253 <?php esc_attr_e( 'Label', 'supportcandy' ); ?>
1254 <span class="required-char">*</span>
1255 </label>
1256 </div>
1257 <input class="wpsc-cf-label" type="text" name="label" autocomplete="off"/>
1258 </div>
1259 </form>
1260 <?php
1261 $body = ob_get_clean();
1262
1263 ob_start();
1264 ?>
1265 <button class="wpsc-button small primary" onclick="wpsc_tl_set_add_saved_filter(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_tl_set_add_saved_filter' ) ); ?>');">
1266 <?php esc_attr_e( 'Save & Apply', 'supportcandy' ); ?>
1267 </button>
1268 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1269 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1270 </button>
1271 <?php
1272 $footer = ob_get_clean();
1273
1274 $response = array(
1275 'title' => $title,
1276 'body' => $body,
1277 'footer' => $footer,
1278 );
1279 wp_send_json( $response );
1280 }
1281
1282 /**
1283 * Set add saved filter
1284 */
1285 public static function set_add_saved_filter() {
1286
1287 if ( check_ajax_referer( 'wpsc_tl_set_add_saved_filter', '_ajax_nonce', false ) != 1 ) {
1288 wp_send_json_error( 'Unauthorized request!', 401 );
1289 }
1290
1291 $current_user = WPSC_Current_User::$current_user;
1292 if ( ! $current_user->customer->user->ID || ! isset( $_POST['filters'] ) ) {
1293 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1294 }
1295
1296 $default_filters = $current_user->is_agent ? get_option( 'wpsc-atl-default-filters' ) : get_option( 'wpsc-atl-default-filters' );
1297
1298 $label = isset( $_POST['filters']['label'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['label'] ) ) : '';
1299 if ( ! $label ) {
1300 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1301 }
1302
1303 $parent_filter = isset( $_POST['filters']['parent-filter'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['parent-filter'] ) ) : '';
1304 if ( ! $parent_filter || ! isset( $default_filters[ $parent_filter ] ) ) {
1305 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1306 }
1307
1308 $filters = isset( $_POST['filters']['filters'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['filters'] ) ) : '';
1309 if ( ! $filters || $filters == '[]' || ! WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters ) ) {
1310 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1311 }
1312
1313 $filters = str_replace( '\n', PHP_EOL, $filters );
1314
1315 $sort_by = isset( $_POST['filters']['orderby'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['orderby'] ) ) : '';
1316 if ( ! $sort_by ) {
1317 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1318 }
1319
1320 $sort_order = isset( $_POST['filters']['order'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['order'] ) ) : '';
1321 if ( ! $sort_order ) {
1322 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1323 }
1324
1325 $saved_filters = $current_user->get_saved_filters();
1326 $index = WPSC_Functions::get_tl_cf_auto_increament();
1327 $saved_filters[ $index ] = array(
1328 'label' => $label,
1329 'parent-filter' => $parent_filter,
1330 'filters' => $filters,
1331 'sort-by' => $sort_by,
1332 'sort-order' => $sort_order,
1333 );
1334 update_user_meta( $current_user->customer->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', $saved_filters );
1335
1336 $response = array( 'slug' => 'saved-' . $index );
1337 wp_send_json( $response );
1338 }
1339
1340 /**
1341 * Edit saved filter UI
1342 *
1343 * @return void
1344 */
1345 public static function get_edit_saved_filter_ui() {
1346
1347 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1348 wp_send_json_error( 'Unauthorized request!', 401 );
1349 }
1350
1351 $current_user = WPSC_Current_User::$current_user;
1352 if ( ! $current_user->customer->user->ID ) {
1353 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1354 }
1355
1356 $filter_slug = isset( $_POST['filterSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['filterSlug'] ) ) : '';
1357 if ( ! $filter_slug ) {
1358 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1359 }
1360
1361 $flag = preg_match( '/saved-(\d*)$/', $filter_slug, $matches );
1362 if ( ! $flag ) {
1363 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1364 }
1365
1366 $saved_filters = $current_user->get_saved_filters();
1367 $filters = $saved_filters[ $matches[1] ];
1368
1369 $title = $filters['label'];
1370 $default_filters = $current_user->is_agent ? get_option( 'wpsc-atl-default-filters' ) : get_option( 'wpsc-atl-default-filters' );
1371 $list_items = $current_user->get_tl_list_items();
1372 $more_settings = $current_user->is_agent ? get_option( 'wpsc-tl-ms-agent-view' ) : get_option( 'wpsc-tl-ms-customer-view' );
1373 $custom_filters = str_replace( PHP_EOL, '\n', $filters['filters'] );
1374
1375 ob_start();
1376 ?>
1377 <form action="#" onsubmit="return false;" class="wpsc-tl-custom-filter">
1378 <div class="wpsc-input-group">
1379 <div class="label-container">
1380 <label for="">
1381 <?php esc_attr_e( 'Label', 'supportcandy' ); ?>
1382 <span class="required-char">*</span>
1383 </label>
1384 </div>
1385 <input class="wpsc-cf-label" type="text" name="label" value="<?php echo esc_attr( $filters['label'] ); ?>" autocomplete="off"/>
1386 </div>
1387 <div class="wpsc-input-group">
1388 <div class="label-container">
1389 <label for="">
1390 <?php esc_attr_e( 'Parent filter', 'supportcandy' ); ?>
1391 <span class="required-char">*</span>
1392 </label>
1393 </div>
1394 <select name="parent-filter">
1395 <?php
1396 foreach ( $default_filters as $slug => $filter ) :
1397 $selected = isset( $filters['parent-filter'] ) && $filters['parent-filter'] == $slug ? 'selected="selected"' : ''
1398 ?>
1399 <option <?php echo esc_attr( $selected ); ?> value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_attr( $filter['label'] ); ?></option>
1400 <?php
1401 endforeach;
1402 ?>
1403 </select>
1404 </div>
1405 <?php WPSC_Ticket_Conditions::print( 'custom_filters', 'wpsc_custom_filter_conditions', $custom_filters, true, __( 'Filters', 'supportcandy' ) ); ?>
1406 <div class="wpsc-input-group">
1407 <div class="label-container">
1408 <label for="">
1409 <?php esc_attr_e( 'Sort by', 'supportcandy' ); ?>
1410 <span class="required-char">*</span>
1411 </label>
1412 </div>
1413 <select name="sort-by">
1414 <?php
1415 $orderby = isset( $filters['sort-by'] ) ? $filters['sort-by'] : $more_settings['default-sort-by'];
1416 foreach ( $list_items as $slug ) :
1417 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1418 if ( ! $cf ) {
1419 continue;
1420 }
1421 if ( $cf->type::$is_sort ) :
1422 ?>
1423 <option <?php selected( $orderby, $cf->slug ); ?> value="<?php echo esc_attr( $cf->slug ); ?>"><?php echo esc_attr( $cf->name ); ?></option>
1424 <?php
1425 endif;
1426 endforeach;
1427 ?>
1428 </select>
1429 </div>
1430 <div class="wpsc-input-group">
1431 <div class="label-container">
1432 <label for="">
1433 <?php esc_attr_e( 'Sort order', 'supportcandy' ); ?>
1434 <span class="required-char">*</span>
1435 </label>
1436 </div>
1437 <select name="sort-order">
1438 <?php
1439 $order = isset( $filters['sort-order'] ) ? $filters['sort-order'] : $more_settings['default-sort-order'];
1440 ?>
1441 <option <?php selected( $order, 'ASC' ); ?> value="ASC"><?php esc_attr_e( 'ASC', 'supportcandy' ); ?></option>
1442 <option <?php selected( $order, 'DESC' ); ?> value="DESC"><?php esc_attr_e( 'DESC', 'supportcandy' ); ?></option>
1443 </select>
1444 </div>
1445 <input type="hidden" name="action" value="wpsc_tl_set_edit_saved_filter"/>
1446 <input type="hidden" name="slug" value="<?php echo esc_attr( $matches[1] ); ?>"/>
1447 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_tl_set_edit_saved_filter' ) ); ?>">
1448 </form>
1449 <?php
1450 $body = ob_get_clean();
1451
1452 ob_start();
1453 ?>
1454 <button class="wpsc-button small primary" onclick="wpsc_tl_set_edit_saved_filter(this);">
1455 <?php esc_attr_e( 'Save & Apply', 'supportcandy' ); ?>
1456 </button>
1457 <button class="wpsc-button small secondary" onclick="wpsc_tl_add_saved_filter();">
1458 <?php esc_attr_e( 'Save As', 'supportcandy' ); ?>
1459 </button>
1460 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1461 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1462 </button>
1463 <?php
1464 $footer = ob_get_clean();
1465
1466 $response = array(
1467 'title' => $title,
1468 'body' => $body,
1469 'footer' => $footer,
1470 );
1471 wp_send_json( $response );
1472 }
1473
1474 /**
1475 * Set edit saved filter
1476 */
1477 public static function set_edit_saved_filter() {
1478
1479 if ( check_ajax_referer( 'wpsc_tl_set_edit_saved_filter', '_ajax_nonce', false ) != 1 ) {
1480 wp_send_json_error( 'Unauthorized request!', 401 );
1481 }
1482
1483 $current_user = WPSC_Current_User::$current_user;
1484 if ( ! $current_user->customer->user->ID ) {
1485 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1486 }
1487
1488 $slug = isset( $_POST['slug'] ) ? intval( $_POST['slug'] ) : 0;
1489 if ( ! $slug ) {
1490 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1491 }
1492
1493 $saved_filters = $current_user->get_saved_filters();
1494 if ( ! isset( $saved_filters[ $slug ] ) ) {
1495 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1496 }
1497
1498 $label = isset( $_POST['label'] ) ? sanitize_text_field( wp_unslash( $_POST['label'] ) ) : '';
1499 if ( ! $label ) {
1500 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1501 }
1502
1503 $parent_filter = isset( $_POST['parent-filter'] ) ? sanitize_text_field( wp_unslash( $_POST['parent-filter'] ) ) : '';
1504 if ( ! $parent_filter ) {
1505 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1506 }
1507
1508 $filters = isset( $_POST['filters'] ) ? sanitize_text_field( wp_unslash( $_POST['filters'] ) ) : '';
1509 if ( ! $filters || $filters == '[]' || ! WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters ) ) {
1510 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1511 }
1512
1513 $filters = str_replace( '\n', PHP_EOL, $filters );
1514
1515 $sort_by = isset( $_POST['sort-by'] ) ? sanitize_text_field( wp_unslash( $_POST['sort-by'] ) ) : '';
1516 if ( ! $sort_by ) {
1517 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1518 }
1519
1520 $sort_order = isset( $_POST['sort-order'] ) ? sanitize_text_field( wp_unslash( $_POST['sort-order'] ) ) : '';
1521 if ( ! $sort_order ) {
1522 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1523 }
1524
1525 $saved_filters[ $slug ] = array(
1526 'label' => $label,
1527 'parent-filter' => $parent_filter,
1528 'filters' => $filters,
1529 'sort-by' => $sort_by,
1530 'sort-order' => $sort_order,
1531 );
1532 update_user_meta( $current_user->customer->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', $saved_filters );
1533 wp_die();
1534 }
1535
1536 /**
1537 * Delete saved filter
1538 *
1539 * @return void
1540 */
1541 public static function delete_saved_filter() {
1542
1543 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1544 wp_send_json_error( 'Unauthorized request!', 401 );
1545 }
1546
1547 $current_user = WPSC_Current_User::$current_user;
1548 if ( ! $current_user->customer->user->ID ) {
1549 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1550 }
1551
1552 $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : '';
1553 if ( ! $slug ) {
1554 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1555 }
1556
1557 $flag = preg_match( '/saved-(\d*)$/', $slug, $matches );
1558 if ( ! $flag ) {
1559 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1560 }
1561
1562 $slug = $matches[1];
1563
1564 $saved_filters = $current_user->get_saved_filters();
1565 if ( ! isset( $saved_filters[ $slug ] ) ) {
1566 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1567 }
1568
1569 unset( $saved_filters[ $slug ] );
1570
1571 update_user_meta( $current_user->customer->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', $saved_filters );
1572 wp_die();
1573 }
1574
1575 /**
1576 * Get change bult ticket status/categoty/priority
1577 *
1578 * @return void
1579 */
1580 public static function bulk_change_status() {
1581
1582 if ( check_ajax_referer( 'wpsc_bulk_change_status', '_ajax_nonce', false ) != 1 ) {
1583 wp_send_json_error( 'Unauthorized request!', 401 );
1584 }
1585
1586 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
1587 if ( ! $ticket_ids ) {
1588 wp_send_json_error( 'Something went wrong!', 400 );
1589 }
1590
1591 $widgets = get_option( 'wpsc-ticket-widget' );
1592 $title = $widgets['change-status']['title'];
1593
1594 $current_user = WPSC_Current_User::$current_user;
1595
1596 $gs = get_option( 'wpsc-gs-general' );
1597 $tl_advanced = get_option( 'wpsc-tl-ms-advanced' );
1598 $close_flag = in_array( $current_user->agent->role, $gs['allow-close-ticket'] ) ? true : false;
1599
1600 $statuses = WPSC_Status::find( array( 'items_per_page' => 0 ) )['results'];
1601 $categories = WPSC_Category::find( array( 'items_per_page' => 0 ) )['results'];
1602 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
1603
1604 ob_start();
1605 ?>
1606 <form action="#" onsubmit="return false;" class="frm-edit-bulk-status">
1607 <div class="wpsc-input-group">
1608 <?php $cf = WPSC_Custom_Field::get_cf_by_slug( 'status' ); ?>
1609 <div class="label-container">
1610 <label for=""><?php echo esc_attr( $cf->name ); ?></label>
1611 </div>
1612 <select id="wpsc-select-bulk-ticket-status" name="status_id">
1613 <option value=""></option>
1614 <?php
1615 foreach ( $statuses as $status ) :
1616 if (
1617 ( $status->id == $gs['close-ticket-status'] || in_array( $status->id, $tl_advanced['closed-ticket-statuses'] ) ) &&
1618 ! $close_flag
1619 ) {
1620 continue;
1621 }
1622 ?>
1623 <option value="<?php echo esc_attr( $status->id ); ?>"><?php echo esc_attr( $status->name ); ?></option>
1624 <?php
1625 endforeach;
1626 ?>
1627 </select>
1628 <script>
1629 jQuery('#wpsc-select-bulk-ticket-status').selectWoo({
1630 allowClear: true,
1631 placeholder: ""
1632 });
1633 </script>
1634 </div>
1635 <div class="wpsc-input-group">
1636 <?php $cf = WPSC_Custom_Field::get_cf_by_slug( 'category' ); ?>
1637 <div class="label-container">
1638 <label for=""><?php echo esc_attr( $cf->name ); ?></label>
1639 </div>
1640 <select id="wpsc-select-bulk-ticket-category" name="cat_id">
1641 <option value=""></option>
1642 <?php
1643 foreach ( $categories as $category ) :
1644 ?>
1645 <option value="<?php echo esc_attr( $category->id ); ?>"><?php echo esc_attr( $category->name ); ?></option>
1646 <?php
1647 endforeach;
1648 ?>
1649 </select>
1650 <script>
1651 jQuery('#wpsc-select-bulk-ticket-category').selectWoo({
1652 allowClear: true,
1653 placeholder: ""
1654 });
1655 </script>
1656 </div>
1657 <div class="wpsc-input-group">
1658 <?php $cf = WPSC_Custom_Field::get_cf_by_slug( 'priority' ); ?>
1659 <div class="label-container">
1660 <label for=""><?php echo esc_attr( $cf->name ); ?></label>
1661 </div>
1662 <select id="wpsc-select-bulk-ticket-priority" name="priority_id">
1663 <option value=""></option>
1664 <?php
1665 foreach ( $priorities as $priority ) :
1666 ?>
1667 <option value="<?php echo esc_attr( $priority->id ); ?>"><?php echo esc_attr( $priority->name ); ?></option>
1668 <?php
1669 endforeach;
1670 ?>
1671 </select>
1672 <script>
1673 jQuery('#wpsc-select-bulk-ticket-priority').selectWoo({
1674 allowClear: true,
1675 placeholder: ""
1676 });
1677 </script>
1678 </div>
1679 <?php do_action( 'wpsc_get_bulk_ticket_status_body', $ticket_ids ); ?>
1680 <input type="hidden" name="action" value="wpsc_set_bulk_change_status">
1681 <input type="hidden" name="ticket_ids" value="<?php echo esc_attr( implode( ',', $ticket_ids ) ); ?>">
1682 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_bulk_change_status' ) ); ?>">
1683 </form>
1684 <?php
1685 do_action( 'wpsc_get_bulk_ticket_status_footer', $ticket_ids );
1686 $body = ob_get_clean();
1687
1688 ob_start();
1689 ?>
1690 <button class="wpsc-button small primary" onclick="wpsc_set_bulk_change_status(this);">
1691 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
1692 </button>
1693 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1694 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1695 </button>
1696 <?php
1697 $footer = ob_get_clean();
1698
1699 $response = array(
1700 'title' => $title,
1701 'body' => $body,
1702 'footer' => $footer,
1703 );
1704 wp_send_json( $response );
1705 }
1706
1707 /**
1708 * Set change bulk statuses/category/priority
1709 *
1710 * @return void
1711 */
1712 public static function set_bulk_change_status() {
1713
1714 if ( check_ajax_referer( 'wpsc_set_bulk_change_status', '_ajax_nonce', false ) != 1 ) {
1715 wp_send_json_error( 'Unauthorized request!', 401 );
1716 }
1717
1718 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_POST['ticket_ids'] ) ) ) ) ) : array();
1719 if ( ! $ticket_ids ) {
1720 wp_send_json_error( 'Missing ticket ids', 400 );
1721 }
1722
1723 $current_user = WPSC_Current_User::$current_user;
1724
1725 $status_id = isset( $_POST['status_id'] ) ? intval( $_POST['status_id'] ) : 0;
1726 $cat_id = isset( $_POST['cat_id'] ) ? intval( $_POST['cat_id'] ) : 0;
1727 $priority_id = isset( $_POST['priority_id'] ) ? intval( $_POST['priority_id'] ) : 0;
1728
1729 $gs = get_option( 'wpsc-gs-general' );
1730 $tl_advanced = get_option( 'wpsc-tl-ms-advanced' );
1731 $close_flag = in_array( $current_user->agent->role, $gs['allow-close-ticket'] ) ? true : false;
1732
1733 foreach ( $ticket_ids as $ticket_id ) {
1734
1735 $ticket = new WPSC_Ticket( $ticket_id );
1736 if ( ! $ticket->id ) {
1737 continue;
1738 }
1739
1740 WPSC_Individual_Ticket::$ticket = $ticket;
1741
1742 if (
1743 ( $status_id == $gs['close-ticket-status'] || in_array( $status_id, $tl_advanced['closed-ticket-statuses'] ) ) &&
1744 ! $close_flag
1745 ) {
1746 continue;
1747 }
1748
1749 if ( $ticket->is_active && ! ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'cs' ) ) ) {
1750 continue;
1751 }
1752
1753 // Check status.
1754 if ( $status_id && $ticket->status->id != $status_id ) {
1755 WPSC_Individual_Ticket::change_status( $ticket->status->id, $status_id, $current_user->customer->id );
1756 }
1757
1758 // Check category.
1759 if ( $cat_id && $ticket->category->id != $cat_id ) {
1760 WPSC_Individual_Ticket::change_category( $ticket->category->id, $cat_id, $current_user->customer->id );
1761 }
1762
1763 // Check priority.
1764 if ( $priority_id && $ticket->priority->id != $priority_id ) {
1765 WPSC_Individual_Ticket::change_priority( $ticket->priority->id, $priority_id, $current_user->customer->id );
1766 }
1767 }
1768 wp_die();
1769 }
1770
1771 /**
1772 * Get edit assign agents
1773 *
1774 * @return void
1775 */
1776 public static function bulk_assign_agents() {
1777
1778 if ( check_ajax_referer( 'wpsc_bulk_assign_agents', '_ajax_nonce', false ) != 1 ) {
1779 wp_send_json_error( 'Unauthorized request!', 401 );
1780 }
1781
1782 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
1783 if ( ! $ticket_ids ) {
1784 wp_send_json_error( 'Something went wrong!', 400 );
1785 }
1786
1787 $widgets = get_option( 'wpsc-ticket-widget' );
1788 $title = $widgets['assignee']['title'];
1789
1790 ob_start();
1791 ?>
1792 <form action="#" onsubmit="return false;" class="frm-bulk-assign-agent">
1793 <div class="wpsc-input-group" style="flex-direction:row; flex-wrap:nowrap;">
1794 <div class="wpsc-input-group">
1795 <div class="label-container">
1796 <label for=""><?php esc_attr_e( 'Filter by', 'supportcandy' ); ?></label>
1797 </div>
1798 <select class="agent-filter-by">
1799 <?php
1800 $filter_by = apply_filters(
1801 'wpsc_assignee_filter_by',
1802 array(
1803 'all' => esc_attr__( 'All', 'supportcandy' ),
1804 )
1805 );
1806 foreach ( $filter_by as $key => $label ) :
1807 ?>
1808 <option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_attr( $label ); ?></option>
1809 <?php
1810 endforeach
1811 ?>
1812 </select>
1813 </div>
1814 <div style="margin:5px;"></div>
1815 <div class="wpsc-input-group">
1816 <div class="label-container">
1817 <label for=""><?php esc_attr_e( 'Sort by', 'supportcandy' ); ?></label>
1818 </div>
1819 <select class="agent-sort-by">
1820 <option value="workload"><?php esc_attr_e( 'Workload', 'supportcandy' ); ?></option>
1821 <option value="name"><?php esc_attr_e( 'Name', 'supportcandy' ); ?></option>
1822 </select>
1823 </div>
1824 </div>
1825 <div class="wpsc-input-group">
1826 <div class="label-container">
1827 <label for=""><?php esc_attr_e( 'Select agent(s)', 'supportcandy' ); ?></label>
1828 </div>
1829 <select id="wpsc-select-bulk-assign-agent" multiple name="assignee[]"></select>
1830 <script>
1831 jQuery('#wpsc-select-bulk-assign-agent').selectWoo({
1832 ajax: {
1833 url: supportcandy.ajax_url,
1834 dataType: 'json',
1835 delay: 250,
1836 data: function (params) {
1837 return {
1838 q: params.term, // search term.
1839 action: 'wpsc_agent_autocomplete_bulk_assign',
1840 _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_agent_autocomplete_bulk_assign' ) ); ?>',
1841 filter_by: jQuery('select.agent-filter-by').val(),
1842 sort_by: jQuery('select.agent-sort-by').val(),
1843 isMultiple: 1,
1844 };
1845 },
1846 processResults: function (data, params) {
1847 var terms = [];
1848 if ( data ) {
1849 jQuery.each( data, function( id, text ) {
1850 terms.push( { id: text.id, text: text.title } );
1851 });
1852 }
1853 return {
1854 results: terms
1855 };
1856 },
1857 cache: true
1858 },
1859 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work.
1860 minimumInputLength: 0,
1861 allowClear: false,
1862 placeholder: ""
1863 });
1864 </script>
1865 </div>
1866 <?php do_action( 'wpsc_get_bulk_assigned_agent_body', $ticket_ids ); ?>
1867 <input type="hidden" name="action" value="wpsc_set_bulk_assign_agent">
1868 <input type="hidden" name="ticket_ids" value="<?php echo esc_attr( implode( ',', $ticket_ids ) ); ?>">
1869 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_bulk_assign_agent' ) ); ?>">
1870 </form>
1871 <?php
1872 do_action( 'wpsc_get_bulk_assigned_agent_footer' );
1873 $body = ob_get_clean();
1874
1875 ob_start();
1876 ?>
1877 <button class="wpsc-button small primary" onclick="wpsc_set_bulk_assign_agent(this);">
1878 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
1879 </button>
1880 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1881 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1882 </button>
1883 <?php
1884 $footer = ob_get_clean();
1885
1886 $response = array(
1887 'title' => $title,
1888 'body' => $body,
1889 'footer' => $footer,
1890 );
1891
1892 wp_send_json( $response );
1893 }
1894
1895 /**
1896 * Change assigned agent
1897 *
1898 * @return void
1899 */
1900 public static function set_bulk_assign_agent() {
1901
1902 if ( check_ajax_referer( 'wpsc_set_bulk_assign_agent', '_ajax_nonce', false ) != 1 ) {
1903 wp_send_json_error( 'Unauthorized request!', 401 );
1904 }
1905
1906 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_POST['ticket_ids'] ) ) ) ) ) : array();
1907 if ( ! $ticket_ids ) {
1908 wp_send_json_error( 'Missing ticket ids', 400 );
1909 }
1910
1911 $new_ids = isset( $_POST['assignee'] ) ? array_filter( array_map( 'intval', $_POST['assignee'] ) ) : array();
1912 if ( ! $new_ids ) {
1913 wp_send_json_error( 'Something went wrong!', 400 );
1914 }
1915
1916 foreach ( $ticket_ids as $ticket_id ) {
1917
1918 $ticket = new WPSC_Ticket( $ticket_id );
1919 if ( ! $ticket->id ) {
1920 continue;
1921 }
1922
1923 WPSC_Individual_Ticket::$ticket = $ticket;
1924
1925 $current_user = WPSC_Current_User::$current_user;
1926 if ( $ticket->is_active && ! ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'aa' ) ) ) {
1927 continue;
1928 }
1929
1930 $prev = $ticket->assigned_agent;
1931
1932 // Check whether all new agets exists.
1933 $new = array();
1934 foreach ( $new_ids as $id ) {
1935 $agent = new WPSC_Agent( $id );
1936 $new[] = $agent;
1937 if ( ! $agent->id ) {
1938 wp_send_json_error( 'Something went wrong!', 400 );
1939 }
1940 }
1941
1942 $prev_ids = array();
1943 foreach ( $prev as $agent ) {
1944 $prev_ids[] = $agent->id;
1945 }
1946
1947 // Exit if there is no change.
1948 if (
1949 count( array_diff( $new_ids, $prev_ids ) ) === 0 &&
1950 count( array_diff( $prev_ids, $new_ids ) ) === 0
1951 ) {
1952 continue;
1953 }
1954
1955 // Change assignee.
1956 WPSC_Individual_Ticket::change_assignee( $prev, $new, $current_user->customer->id );
1957 }
1958 wp_die();
1959 }
1960
1961 /**
1962 * Get change bulk ticket tags
1963 *
1964 * @return void
1965 */
1966 public static function bulk_assign_tags() {
1967
1968 if ( check_ajax_referer( 'wpsc_bulk_assign_tags', '_ajax_nonce', false ) != 1 ) {
1969 wp_send_json_error( 'Unauthorized request!', 401 );
1970 }
1971
1972 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
1973 if ( ! $ticket_ids ) {
1974 wp_send_json_error( 'Something went wrong!', 400 );
1975 }
1976
1977 $ticket_widgets = get_option( 'wpsc-ticket-widget', array() );
1978 $title = $ticket_widgets['tags']['title'];
1979
1980 $tags = WPSC_Ticket_Tags::find( array( 'items_per_page' => 0 ) )['results'];
1981 $unique_id = uniqid();
1982 ob_start();
1983 ?>
1984
1985 <form action="#" onsubmit="return false;" class="frm-bulk-assign-tags">
1986 <div class="wpsc-input-group">
1987 <div class="label-container">
1988 <label for=""><?php esc_attr_e( 'Select tag(s)', 'supportcandy' ); ?></label>
1989 </div>
1990 <select id="wpsc-tags" class="wpsc-tags" multiple name="tags[]"></select>
1991 </div>
1992 <script>
1993 jQuery(document).ready(function(){
1994 if (!jQuery('select.wpsc-tags').hasClass("select2-hidden-accessible")) {
1995 jQuery('select.wpsc-tags').selectWoo({
1996 tags: true,
1997 ajax: {
1998 url: supportcandy.ajax_url,
1999 dataType: 'json',
2000 delay: 250,
2001 data: function (params) {
2002 return {
2003 q: params.term, // search term
2004 page: params.page,
2005 action: 'wpsc_tag_autocomplete',
2006 tags: jQuery( this ).val(),
2007 _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_tag_autocomplete' ) ); ?>'
2008 };
2009 },
2010 processResults: function (data, params) {
2011 var terms = [];
2012 if ( data ) {
2013 jQuery.each( data, function( id, text ) {
2014 terms.push( { id: text.id, text: text.title } );
2015 });
2016 }
2017 return {
2018 results: terms
2019 };
2020 },
2021 cache: true
2022 },
2023 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
2024 minimumInputLength: 0,
2025 placeholder: ""
2026 });
2027 }
2028 });
2029 </script>
2030 <?php do_action( 'wpsc_get_bulk_assigned_tag_body', $ticket_ids ); ?>
2031 <input type="hidden" name="action" value="wpsc_set_bulk_assign_tag">
2032 <input type="hidden" name="ticket_ids" value="<?php echo esc_attr( implode( ',', $ticket_ids ) ); ?>">
2033 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_bulk_assign_tag' ) ); ?>">
2034 </form>
2035 <?php
2036 do_action( 'wpsc_get_bulk_assigned_tag_footer', $ticket_ids );
2037 $body = ob_get_clean();
2038
2039 ob_start();
2040 ?>
2041 <button class="wpsc-button small primary" onclick="wpsc_set_bulk_assign_tag(this);">
2042 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
2043 </button>
2044 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
2045 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
2046 </button>
2047 <?php
2048 $footer = ob_get_clean();
2049
2050 $response = array(
2051 'title' => $title,
2052 'body' => $body,
2053 'footer' => $footer,
2054 );
2055 wp_send_json( $response );
2056 }
2057
2058 /**
2059 * Change assigned tag
2060 *
2061 * @return void
2062 */
2063 public static function set_bulk_assign_tag() {
2064
2065 if ( check_ajax_referer( 'wpsc_set_bulk_assign_tag', '_ajax_nonce', false ) != 1 ) {
2066 wp_send_json_error( 'Unauthorized request!', 401 );
2067 }
2068
2069 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_POST['ticket_ids'] ) ) ) ) ) : array();
2070 if ( ! $ticket_ids ) {
2071 wp_send_json_error( 'Missing ticket ids', 400 );
2072 }
2073
2074 $tags = isset( $_POST['tags'] ) ? array_filter( array_map( 'sanitize_text_field', wp_unslash( $_POST['tags'] ) ) ) : array();
2075 if ( ! $tags ) {
2076 wp_send_json_error( 'Something went wrong!', 400 );
2077 }
2078 $general = get_option( 'wpsc-ticket-tags-general-settings' );
2079
2080 foreach ( $ticket_ids as $ticket_id ) {
2081
2082 $ticket = new WPSC_Ticket( $ticket_id );
2083 if ( ! $ticket->id ) {
2084 continue;
2085 }
2086
2087 WPSC_Individual_Ticket::$ticket = $ticket;
2088
2089 $current_user = WPSC_Current_User::$current_user;
2090 if ( ! ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'tt' ) ) ) {
2091 continue;
2092 }
2093
2094 $prev_tags = array();
2095 foreach ( $ticket->tags as $tag ) {
2096 $prev_tags[] = $tag->id;
2097 }
2098
2099 $ticket_tags = array();
2100 foreach ( $tags as $key => $tag_id ) {
2101
2102 $tag = new WPSC_Ticket_Tags( $tag_id );
2103 if ( ! $tag->id ) {
2104
2105 $data = array(
2106 'name' => $tag_id,
2107 'description' => '',
2108 'color' => $general['color'],
2109 'bg_color' => $general['bg-color'],
2110 );
2111 $new_tag = WPSC_Ticket_Tags::insert( $data );
2112 $tags[ $key ] = $new_tag->id;
2113 }
2114 $ticket_tags[] = $tags[ $key ];
2115 }
2116
2117 $new_tags = array_unique( array_merge( $prev_tags, $ticket_tags ) );
2118 // Change tag.
2119 WPSC_Individual_Ticket::change_tag( $prev_tags, $new_tags, $current_user->customer->id );
2120 }
2121
2122 wp_die();
2123 }
2124
2125 /**
2126 * Archive ticket ajax request
2127 */
2128 public static function bulk_archive_tickets() {
2129
2130 if ( check_ajax_referer( 'wpsc_bulk_archive_tickets', '_ajax_nonce', false ) != 1 ) {
2131 wp_send_json_error( 'Unauthorized request!', 401 );
2132 }
2133
2134 $current_user = WPSC_Current_User::$current_user;
2135 if ( ! $current_user->is_agent ) {
2136 wp_send_json_error( 'Unauthorized request!', 401 );
2137 }
2138
2139 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2140 if ( ! $ticket_ids ) {
2141 wp_send_json_error( 'Something went wrong!', 400 );
2142 }
2143
2144 foreach ( $ticket_ids as $ticket_id ) {
2145
2146 $ticket = new WPSC_Ticket( $ticket_id );
2147 WPSC_Individual_Ticket::$ticket = $ticket;
2148 if ( ! $ticket->id || ! WPSC_Individual_Ticket::has_ticket_cap( 'at' ) ) {
2149 continue;
2150 }
2151
2152 WPSC_Individual_Ticket::archive_ticket();
2153 }
2154 wp_die();
2155 }
2156
2157 /**
2158 * Permanently delete ticket ajax request
2159 */
2160 public static function bulk_permanently_delete_tickets() {
2161
2162 if ( check_ajax_referer( 'wpsc_bulk_permanently_delete_tickets', '_ajax_nonce', false ) != 1 ) {
2163 wp_send_json_error( 'Unauthorised request!', 401 );
2164 }
2165
2166 $current_user = WPSC_Current_User::$current_user;
2167 if ( ! $current_user->is_agent ) {
2168 wp_send_json_error( 'Unauthorised request!', 401 );
2169 }
2170
2171 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2172 if ( ! $ticket_ids ) {
2173 wp_send_json_error( 'Something went wrong!', 400 );
2174 }
2175
2176 foreach ( $ticket_ids as $ticket_id ) {
2177
2178 $ticket = new WPSC_Ticket( $ticket_id );
2179 WPSC_Individual_Ticket::$ticket = $ticket;
2180 if ( ! $ticket->id || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2181 continue;
2182 }
2183 WPSC_Ticket::destroy( $ticket );
2184 }
2185 wp_die();
2186 }
2187
2188 /**
2189 * Check parent filter is deleted or not
2190 *
2191 * @param string $slug - filter type.
2192 * @return boolean
2193 */
2194 public static function has_delete_parent_filter( $slug ) {
2195
2196 // phpcs:disable
2197 switch ( $slug ) {
2198
2199 case 'all':
2200 return false;
2201 break;
2202
2203 case 'unresolved':
2204 return false;
2205 break;
2206
2207 case 'mine':
2208 return false;
2209 break;
2210
2211 case 'closed':
2212 return false;
2213 break;
2214
2215 case 'deleted':
2216 return true;
2217 break;
2218
2219 default:
2220 if ( ! is_numeric( $slug ) || ! isset( self::$default_filters[ $slug ] ) ) {
2221 return false;
2222 }
2223 $slug = self::$default_filters[ $slug ]['parent-filter'];
2224 self::has_delete_parent_filter( $slug );
2225 }
2226 // phpcs:enable
2227 }
2228
2229 /**
2230 * Set bulk actions for current user
2231 */
2232 public static function set_bulk_actions() {
2233
2234 $current_user = WPSC_Current_User::$current_user;
2235 $is_deleted = self::is_current_filter_deleted();
2236 $bulk_actions = array();
2237
2238 if ( ! $is_deleted ) {
2239 if ( $current_user->is_agent && self::has_ticket_cap( 'cs' ) ) {
2240 $bulk_actions['change-status'] = array(
2241 'icon' => 'gps-navigation',
2242 'label' => esc_attr__( 'Change Status', 'supportcandy' ),
2243 'callback' => 'wpsc_bulk_change_status',
2244 );
2245 }
2246
2247 if ( $current_user->is_agent && self::has_ticket_cap( 'aa' ) ) {
2248 $bulk_actions['assign-agents'] = array(
2249 'icon' => 'headset',
2250 'label' => esc_attr__( 'Assign Agents', 'supportcandy' ),
2251 'callback' => 'wpsc_bulk_assign_agents',
2252 );
2253 }
2254
2255 if ( $current_user->is_agent && self::has_ticket_cap( 'tt' ) ) {
2256 $bulk_actions['assign-tags'] = array(
2257 'icon' => 'tags',
2258 'label' => esc_attr__( 'Assign Tags', 'supportcandy' ),
2259 'callback' => 'wpsc_bulk_assign_tags',
2260 );
2261 }
2262
2263 if ( $current_user->is_agent && self::has_ticket_cap( 'dtt' ) ) {
2264 $bulk_actions['delete'] = array(
2265 'icon' => 'trash-alt',
2266 'label' => esc_attr__( 'Delete', 'supportcandy' ),
2267 'callback' => 'wpsc_bulk_delete_tickets',
2268 );
2269 }
2270 $bulk_actions = apply_filters( 'wpsc_tl_bulk_actions', $bulk_actions );
2271 } else {
2272
2273 if ( $current_user->is_agent && self::has_ticket_cap( 'dtt' ) ) {
2274 $bulk_actions['restore'] = array(
2275 'icon' => 'trash-restore',
2276 'label' => esc_attr__( 'Restore', 'supportcandy' ),
2277 'callback' => 'wpsc_bulk_restore_tickets',
2278 );
2279 }
2280
2281 if ( $current_user->is_agent && self::has_ticket_cap( 'dtt' ) ) {
2282 $bulk_actions['permanently_delete'] = array(
2283 'icon' => 'trash-alt',
2284 'label' => esc_attr__( 'Delete Permanently', 'supportcandy' ),
2285 'callback' => 'wpsc_bulk_permanently_delete_tickets',
2286 );
2287 }
2288 }
2289
2290 if ( $current_user->is_agent && self::has_ticket_cap( 'at' ) ) {
2291 $bulk_actions['archive'] = array(
2292 'icon' => 'archive',
2293 'label' => esc_attr__( 'Archive', 'supportcandy' ),
2294 'callback' => 'wpsc_bulk_archive_tickets',
2295 );
2296 }
2297
2298 $bulk_actions = apply_filters( 'wpsc_tl_bulk_actions', $bulk_actions );
2299
2300 self::$bulk_actions = $bulk_actions;
2301 }
2302
2303 /**
2304 * Get Bulk actions
2305 *
2306 * @return string
2307 */
2308 public static function get_bulk_actions() {
2309
2310 $current_user = WPSC_Current_User::$current_user;
2311 $actions_arr = array();
2312 foreach ( self::$bulk_actions as $action ) :
2313 ob_start();
2314 ?>
2315 <div class="wpsc-popover-menu-item" onclick="<?php echo esc_attr( $action['callback'] ) . '(\'' . esc_attr( wp_create_nonce( $action['callback'] ) ) . '\');'; ?>">
2316 <?php WPSC_Icons::get( $action['icon'] ); ?>
2317 <span><?php echo esc_attr( $action['label'] ); ?></span>
2318 </div>
2319 <?php
2320 $actions_arr[] = ob_get_clean();
2321 endforeach;
2322
2323 return implode( '', $actions_arr );
2324 }
2325
2326 /**
2327 * Agent ticket access for cap
2328 *
2329 * @param string $cap - capability type.
2330 * @return boolean
2331 */
2332 public static function has_ticket_cap( $cap ) {
2333
2334 $current_user = WPSC_Current_User::$current_user;
2335 $flag = false;
2336 if (
2337 $current_user->agent->has_cap( $cap . '-unassigned' ) ||
2338 $current_user->agent->has_cap( $cap . '-assigned-me' ) ||
2339 $current_user->agent->has_cap( $cap . '-assigned-others' )
2340 ) {
2341 $flag = true;
2342 }
2343
2344 return apply_filters( 'wpsc_bulk_has_ticket_cap', $flag );
2345 }
2346
2347 /**
2348 * Agent autocomplete bulk assign agents
2349 *
2350 * @return void
2351 */
2352 public static function agent_autocomplete_bulk_assign() {
2353
2354 if ( check_ajax_referer( 'wpsc_agent_autocomplete_bulk_assign', '_ajax_nonce', false ) !== 1 ) {
2355 wp_send_json_error( 'Unauthorized request!', 401 );
2356 }
2357
2358 $current_user = WPSC_Current_User::$current_user;
2359 if ( ! ( $current_user->is_agent && self::has_ticket_cap( 'aa' ) ) ) {
2360 wp_send_json_error( 'Unauthorized request!', 401 );
2361 }
2362
2363 $filters = array();
2364
2365 $filters['term'] = isset( $_GET['q'] ) ? sanitize_text_field( wp_unslash( $_GET['q'] ) ) : '';
2366 $filters['filter_by'] = isset( $_GET['filter_by'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_by'] ) ) : 'all';
2367 $filters['sort_by'] = isset( $_GET['sort_by'] ) ? sanitize_text_field( wp_unslash( $_GET['sort_by'] ) ) : 'name';
2368 $filters['isMultiple'] = isset( $_GET['isMultiple'] ) ? intval( wp_unslash( $_GET['isMultiple'] ) ) : 0;
2369
2370 $filters['isAgentgroup'] = 0;
2371 if ( class_exists( 'WPSC_Agentgroups' ) ) {
2372 $filters['isAgentgroup'] = isset( $_GET['isAgentgroup'] ) ? intval( $_GET['isAgentgroup'] ) : null;
2373 }
2374
2375 $response = WPSC_Agent::agent_autocomplete( $filters );
2376 wp_send_json( $response );
2377 }
2378
2379 /**
2380 * Check whether current filter is deleted type or not
2381 *
2382 * @return boolean
2383 */
2384 public static function is_current_filter_deleted() {
2385
2386 $filters = self::$filters;
2387
2388 $slug = self::$default_flag ? self::$filter_id : '';
2389 if ( ! $slug && self::$saved_flag ) {
2390 $slug = self::$filter_id;
2391 }
2392 if ( ! $slug ) {
2393 $slug = $filters['filterSlug'];
2394 }
2395
2396 $parent_slug = is_numeric( $slug ) && self::$default_flag ? self::$default_filters[ $slug ]['parent-filter'] : '';
2397
2398 if ( ! $parent_slug && is_numeric( $slug ) && self::$saved_flag ) {
2399
2400 $parent_slug = self::$saved_filters[ $slug ]['parent-filter'];
2401
2402 } elseif ( ! $parent_slug && $slug == 'custom' ) {
2403
2404 $parent_slug = $filters['parent-filter'];
2405
2406 } else {
2407
2408 $parent_slug = $slug;
2409 }
2410
2411 return self::has_delete_parent_filter( $parent_slug );
2412 }
2413
2414 /**
2415 * Get updated nonce.
2416 *
2417 * @return void
2418 */
2419 public static function get_nonce() {
2420
2421 $response = array(
2422 'general' => wp_create_nonce( 'general' ),
2423 );
2424 wp_send_json( $response );
2425 }
2426
2427 /**
2428 * Allow only allowed conditions for current user for custom ticket filter
2429 *
2430 * @param array $conditions - conditions to filter.
2431 * @return array
2432 */
2433 public static function custom_filter_conditions( $conditions ) {
2434
2435 $current_user = WPSC_Current_User::$current_user;
2436 $level = $current_user->level == 'admin' ? 'agent' : $current_user->level;
2437
2438 foreach ( $conditions as $slug => $item ) {
2439
2440 if ( $item['type'] == 'cf' ) {
2441
2442 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
2443 if (
2444 ! $cf->type::$is_filter ||
2445 ! in_array( $cf->field, array( 'ticket', 'customer', 'agentonly' ) ) ||
2446 ! in_array( $level, $item['levels'] )
2447 ) {
2448 unset( $conditions[ $slug ] );
2449 }
2450 } else { // not custom field type.
2451
2452 unset( $conditions[ $slug ] );
2453 }
2454 }
2455
2456 return $conditions;
2457 }
2458
2459 /**
2460 * Filter tickets by tag
2461 *
2462 * @return void
2463 */
2464 public static function apply_tag_custom_filter() {
2465
2466 if ( isset( $_REQUEST['wpsc_tag'] ) && ( isset($_REQUEST['section']) && $_REQUEST['section'] == 'ticket-list' ) ) { // phpcs:ignore
2467
2468 $tag = intval( $_REQUEST['wpsc_tag'] ); // phpcs:ignore
2469 if ( ! $tag ) {
2470 return;
2471 }
2472
2473 if ( ! WPSC_Functions::is_site_admin() ) {
2474 return;
2475 }
2476
2477 $custom_filters = array();
2478
2479 $obj = new stdClass();
2480 $obj->slug = 'tags';
2481 $obj->operator = '=';
2482 $obj->operand_val_1 = $_REQUEST['wpsc_tag']; // phpcs:ignore
2483
2484 $custom_filters[] = array( $obj );
2485
2486 $filters = array(
2487 'filterSlug' => 'custom',
2488 'parent-filter' => 'all',
2489 'filters' => wp_json_encode( $custom_filters ),
2490 'orderby' => 'date_updated',
2491 'order' => 'DESC',
2492 'page_no' => 1,
2493 'search' => '',
2494 );
2495
2496 setcookie( 'wpsc-tl-filters', wp_json_encode( $filters ), time() + 3600 );
2497 }
2498 }
2499
2500 /**
2501 * Receive Heartbeat data and respond.
2502 *
2503 * Processes data received via a Heartbeat request, and returns additional data to pass back to the front end.
2504 *
2505 * @param array $response Heartbeat response data to pass back to front end.
2506 * @param array $data Data received from the front end (unslashed).
2507 *
2508 * @return array
2509 */
2510 public static function get_nonce_heartbeat( array $response, array $data ) {
2511
2512 if ( empty( $data['wpsc_heartbeat'] ) ) {
2513 return $response;
2514 }
2515
2516 $response['general'] = wp_create_nonce( 'general' );
2517 return $response;
2518 }
2519
2520 /**
2521 * Delete ticket ajax request
2522 */
2523 public static function bulk_delete_tickets() {
2524
2525 if ( check_ajax_referer( 'wpsc_bulk_delete_tickets', '_ajax_nonce', false ) != 1 ) {
2526 wp_send_json_error( 'Unauthorised request!', 401 );
2527 }
2528
2529 $current_user = WPSC_Current_User::$current_user;
2530 if ( ! $current_user->is_agent ) {
2531 wp_send_json_error( 'Unauthorised request!', 401 );
2532 }
2533
2534 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2535 if ( ! $ticket_ids ) {
2536 wp_send_json_error( 'Something went wrong!', 400 );
2537 }
2538
2539 foreach ( $ticket_ids as $ticket_id ) {
2540
2541 $ticket = new WPSC_Ticket( $ticket_id );
2542 WPSC_Individual_Ticket::$ticket = $ticket;
2543 if ( ! $ticket->id || ! $ticket->is_active || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2544 continue;
2545 }
2546
2547 WPSC_Individual_Ticket::delete_ticket();
2548 }
2549 wp_die();
2550 }
2551
2552 /**
2553 * Restore bulk tickets
2554 *
2555 * @return void
2556 */
2557 public static function bulk_restore_tickets() {
2558
2559 if ( check_ajax_referer( 'wpsc_bulk_restore_tickets', '_ajax_nonce', false ) != 1 ) {
2560 wp_send_json_error( 'Unauthorised request!', 401 );
2561 }
2562
2563 $current_user = WPSC_Current_User::$current_user;
2564 if ( ! $current_user->is_agent ) {
2565 wp_send_json_error( 'Unauthorised request!', 401 );
2566 }
2567
2568 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2569 if ( ! $ticket_ids ) {
2570 wp_send_json_error( 'Something went wrong!', 400 );
2571 }
2572
2573 foreach ( $ticket_ids as $ticket_id ) {
2574
2575 $ticket = new WPSC_Ticket( $ticket_id );
2576 WPSC_Individual_Ticket::$ticket = $ticket;
2577 if ( ! $ticket->id || $ticket->is_active || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2578 continue;
2579 }
2580
2581 WPSC_Individual_Ticket::restore_ticket();
2582 }
2583 wp_die();
2584 }
2585
2586 /**
2587 * Delete bulk tickets permanently
2588 *
2589 * @return void
2590 */
2591 public static function bulk_delete_tickets_permanently() {
2592
2593 if ( check_ajax_referer( 'wpsc_bulk_delete_tickets_permanently', '_ajax_nonce', false ) != 1 ) {
2594 wp_send_json_error( 'Unauthorised request!', 401 );
2595 }
2596
2597 $current_user = WPSC_Current_User::$current_user;
2598 if ( ! $current_user->is_agent ) {
2599 wp_send_json_error( 'Unauthorised request!', 401 );
2600 }
2601
2602 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2603 if ( ! $ticket_ids ) {
2604 wp_send_json_error( 'Something went wrong!', 400 );
2605 }
2606
2607 foreach ( $ticket_ids as $ticket_id ) {
2608
2609 $ticket = new WPSC_Ticket( $ticket_id );
2610 WPSC_Individual_Ticket::$ticket = $ticket;
2611 if ( ! $ticket->id || $ticket->is_active || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2612 continue;
2613 }
2614
2615 WPSC_Individual_Ticket::delete_permanently();
2616 }
2617 wp_die();
2618 }
2619 }
2620 endif;
2621
2622 WPSC_Ticket_List::init();
2623