PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.3.9
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.3.9
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.3.9, at includes/admin/tickets/class-wpsc-ticket-list.php

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