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

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

2,603 lines 82.6 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 ?>
790 <th style="min-width: <?php echo esc_attr( $cf->tl_width ); ?>px;"><?php echo esc_attr( $cf->name ); ?></th>
791 <?php
792 endforeach;
793 ?>
794
795 </tr>
796 </thead>
797
798 <tbody>
799 <?php
800
801 if ( self::$tickets ) {
802
803 foreach ( self::$tickets as $ticket ) :
804 $class = apply_filters( 'wpsc_ticket_list_tr_classes', array( 'wpsc_tl_tr' ), $ticket );
805 $url = WPSC_Functions::get_ticket_url( $ticket->id, self::$is_frontend );
806 ?>
807 <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 ); ?>')">
808 <?php
809 if ( $current_user->is_agent && self::$bulk_actions ) :
810 ?>
811 <td class="bulk-selector" onmouseover="link=false;" onmouseout="link=true;">
812 <div class="wpsc-tl-item-selector">
813 <div class="checkbox-container">
814 <?php $unique_id = uniqid( 'wpsc_' ); ?>
815 <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 ); ?>"/>
816 <label for="<?php echo esc_attr( $unique_id ); ?>"></label>
817 </div>
818 </div>
819 </td>
820 <?php
821 endif;
822 do_action( 'wpsc_print_ticket_list_td', $ticket );
823 foreach ( $list_items as $slug ) :
824 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
825 if ( ! $cf ) {
826 continue;
827 }
828 ?>
829 <td onmouseover="link=true;">
830 <?php
831 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) ) {
832 $cf->type::print_tl_ticket_field_val( $cf, $ticket );
833 } else {
834 $cf->type::print_tl_customer_field_val( $cf, $ticket->customer );
835 }
836 ?>
837 </td>
838 <?php
839 endforeach;
840 ?>
841 </tr>
842 <?php
843 endforeach;
844
845 } else {
846
847 $col_span = count( $list_items );
848 if ( $current_user->is_agent && self::$bulk_actions ) {
849 ++$col_span;
850 }
851 ?>
852 <tr><td colspan="<?php echo esc_attr( $col_span ); ?>" style="text-align:left;"><?php esc_attr_e( 'No tickets found!', 'supportcandy' ); ?></td></tr>
853 <?php
854
855 }
856 ?>
857
858 </tbody>
859
860 </table>
861 </div>
862 <script>
863 function wpsc_tl_handle_click(event, id, url) {
864 if ( ( event.ctrlKey || event.metaKey ) && url ) {
865 window.open(url, '_blank');
866 } else {
867 wpsc_get_individual_ticket(id);
868 }
869 }
870 </script>
871 <?php
872
873 return ob_get_clean();
874 }
875
876 /**
877 * Ticket list snippets. It may include static modal screens, JS initializers, etc.
878 *
879 * @return void
880 */
881 public static function print_tl_snippets() {
882
883 $filters = self::$cookie_filters;
884 $filter_json = isset( $filters['filters'] ) && $filters['filters'] ? $filters['filters'] : '[]';
885 $filters['filters'] = $filter_json;
886
887 $ticket_list_js_vars = array(
888 'pagination' => array(
889 'current_page' => self::$filters['page_no'],
890 'has_next_page' => self::$has_next_page,
891 'total_pages' => self::$total_pages,
892 'total_items' => self::$total_items,
893 ),
894 'filters' => $filters,
895 );
896
897 $advanced_settings = get_option( 'wpsc-tl-ms-advanced', array() );
898 ?>
899
900 <div class="wpsc-tl_snippets" style="display:none;">
901 <div class="auto-refresh">
902 <div class="modal-header">
903 <?php esc_attr_e( 'Auto-Refresh', 'supportcandy' ); ?>
904 </div>
905 <div class="modal-body">
906 <div class="wpsc-toggle-btn">
907 <div class="toggle-off" onclick="wpsc_toggle_off(this);">
908 <?php esc_attr_e( 'OFF', 'supportcandy' ); ?>
909 </div>
910 <div class="toggle-on" onclick="wpsc_toggle_on(this);">
911 <?php esc_attr_e( 'ON', 'supportcandy' ); ?>
912 </div>
913 <input type="hidden" value="0">
914 </div>
915 </div>
916 <div class="modal-footer">
917 <button class="wpsc-button small primary" onclick="wpsc_set_tl_auto_refresh(this);">
918 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
919 </button>
920 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
921 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
922 </button>
923 </div>
924 </div>
925 <script>
926 supportcandy.ticketList = <?php echo wp_json_encode( $ticket_list_js_vars ); ?>;
927 supportcandy.tl_auto_refresh = <?php echo esc_attr( $advanced_settings['auto-refresh-list-status'] ); ?>;
928 if(supportcandy.tl_auto_refresh) { wpsc_tl_auto_refresh(); }
929 </script>
930 <?php do_action( 'wpsc_tl_snippets' ); ?>
931 </div>
932 <?php
933 }
934
935 /**
936 * Check whether current user has access to given filter
937 *
938 * @param array $filters - ticket filters.
939 * @return boolean
940 */
941 public static function has_filter_access( $filters ) {
942
943 $current_user = WPSC_Current_User::$current_user;
944
945 $filter_slug = isset( $filters['filterSlug'] ) ? $filters['filterSlug'] : '';
946
947 if ( ! $filter_slug ) {
948 return false;
949 }
950
951 if ( isset( self::$default_filters[ $filter_slug ] ) ) {
952 return true;
953 }
954
955 $flag = preg_match( '/default-(\d*)$/', $filter_slug, $matches );
956 if ( $flag && isset( self::$default_filters[ $matches[1] ] ) ) {
957 return true;
958 }
959
960 $flag = preg_match( '/saved-(\d*)$/', $filter_slug, $matches );
961 if ( $flag && isset( self::$saved_filters[ $matches[1] ] ) ) {
962 return true;
963 }
964
965 if ( $filter_slug == 'custom' && WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters['filters'] ) ) {
966 return true;
967 }
968
969 return false;
970 }
971
972 /**
973 * Convert UI filters in json format to meta query
974 *
975 * @param array $filters - ticket filters.
976 * @return array
977 */
978 public static function get_meta_query( $filters ) {
979
980 $meta_query = array();
981 foreach ( $filters as $slug => $condition ) {
982
983 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
984 if ( ! $cf ) {
985 continue;
986 }
987
988 $val = $cf->type::get_meta_value( $condition );
989 if ( $val === false ) {
990 continue;
991 }
992
993 $meta_query[] = array(
994 'slug' => $slug,
995 'compare' => $condition['operator'],
996 'val' => $val,
997 );
998 }
999 return $meta_query;
1000 }
1001
1002 /**
1003 * Return parent meta query
1004 *
1005 * @param string $parent_slug - filter type.
1006 * @return array
1007 */
1008 public static function get_parent_meta_query( $parent_slug ) {
1009
1010 $current_user = WPSC_Current_User::$current_user;
1011 $meta_query = array();
1012 switch ( $parent_slug ) {
1013
1014 case 'all':
1015 break;
1016
1017 case 'unresolved':
1018 if ( ! isset( self::$default_filters['unresolved'] ) ) {
1019 break;
1020 }
1021 $meta_query[] = array(
1022 'slug' => 'status',
1023 'compare' => 'IN',
1024 'val' => self::$more_settings['unresolved-ticket-statuses'],
1025 );
1026 break;
1027
1028 case 'unassigned':
1029 if ( ! isset( self::$default_filters['unassigned'] ) ) {
1030 break;
1031 }
1032 $meta_query[] = array(
1033 'slug' => 'assigned_agent',
1034 'compare' => '=',
1035 'val' => '',
1036 );
1037 break;
1038
1039 case 'mine':
1040 if ( ! isset( self::$default_filters['mine'] ) ) {
1041 break;
1042 }
1043 $meta_query[] = array(
1044 'slug' => 'assigned_agent',
1045 'compare' => '=',
1046 'val' => $current_user->agent->id,
1047 );
1048 $meta_query[] = array(
1049 'slug' => 'status',
1050 'compare' => 'IN',
1051 'val' => self::$more_settings['unresolved-ticket-statuses'],
1052 );
1053 break;
1054
1055 case 'closed':
1056 if ( ! isset( self::$default_filters['closed'] ) ) {
1057 break;
1058 }
1059 $ms_advanced = get_option( 'wpsc-tl-ms-advanced' );
1060 $gs = get_option( 'wpsc-gs-general' );
1061 $closed_statuses = array( $gs['close-ticket-status'] );
1062 $closed_statuses = array_merge( $closed_statuses, $ms_advanced['closed-ticket-statuses'] );
1063 $closed_statuses = array_unique( $closed_statuses );
1064 $meta_query[] = array(
1065 'slug' => 'status',
1066 'compare' => 'IN',
1067 'val' => $closed_statuses,
1068 );
1069 break;
1070
1071 case 'deleted':
1072 if ( isset( self::$default_filters['deleted'] ) && self::$is_active !== 0 ) {
1073 self::$is_active = 0;
1074 }
1075 break;
1076
1077 default:
1078 // Break if not exists.
1079 if ( ! is_numeric( $parent_slug ) || ! isset( self::$default_filters[ $parent_slug ] ) ) {
1080 break;
1081 }
1082
1083 $meta_query = array_merge( $meta_query, self::get_parent_meta_query( self::$default_filters[ $parent_slug ]['parent-filter'] ) );
1084 $meta_query = array_merge( $meta_query, WPSC_Ticket_Conditions::get_meta_query( self::$default_filters[ $parent_slug ]['filters'] ) );
1085 }
1086
1087 return $meta_query;
1088 }
1089
1090 /**
1091 * Custom filter modal pop-up
1092 *
1093 * @return void
1094 */
1095 public static function get_tl_custom_filter_ui() {
1096
1097 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1098 wp_send_json_error( 'Unauthorized request!', 401 );
1099 }
1100
1101 $current_user = WPSC_Current_User::$current_user;
1102 if ( ! ( $current_user->is_agent || $current_user->is_customer ) ) {
1103 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1104 }
1105
1106 $title = esc_attr__( 'Custom filter', 'supportcandy' );
1107 $default_filters = get_option( $current_user->is_agent ? 'wpsc-atl-default-filters' : 'wpsc-ctl-default-filters' );
1108 $list_items = $current_user->get_tl_list_items();
1109 $more_settings = get_option( $current_user->is_agent ? 'wpsc-tl-ms-agent-view' : 'wpsc-tl-ms-customer-view' );
1110
1111 // check whether filters are passed.
1112 $filters = isset( $_POST['filters'] ) ? map_deep( wp_unslash( $_POST['filters'] ), 'sanitize_text_field' ) : array();
1113 $custom_filters = isset( $filters['filters'] ) && WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters['filters'] ) ? $filters['filters'] : '';
1114
1115 ob_start();
1116 ?>
1117 <form action="#" onsubmit="return false;" class="wpsc-tl-custom-filter">
1118 <div class="wpsc-input-group">
1119 <div class="label-container">
1120 <label for="">
1121 <?php esc_attr_e( 'Parent filter', 'supportcandy' ); ?>
1122 <span class="required-char">*</span>
1123 </label>
1124 </div>
1125 <select name="parent-filter">
1126 <?php
1127 foreach ( $default_filters as $slug => $filter ) :
1128 if ( $slug === 'deleted' && $current_user->is_agent && ! $current_user->agent->has_cap( 'dtt-access' ) ) {
1129 continue;
1130 }
1131 $selected = isset( $filters['parent-filter'] ) && $filters['parent-filter'] == $slug ? 'selected="selected"' : ''
1132 ?>
1133 <option <?php echo esc_attr( $selected ); ?> value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_attr( $filter['label'] ); ?></option>
1134 <?php
1135 endforeach;
1136 ?>
1137 </select>
1138 </div>
1139 <?php WPSC_Ticket_Conditions::print( 'custom_filters', 'wpsc_custom_filter_conditions', $custom_filters, true, __( 'Filters', 'supportcandy' ) ); ?>
1140 <div class="wpsc-input-group">
1141 <div class="label-container">
1142 <label for="">
1143 <?php esc_attr_e( 'Sort by', 'supportcandy' ); ?>
1144 <span class="required-char">*</span>
1145 </label>
1146 </div>
1147 <select name="sort-by">
1148 <?php
1149 $orderby = isset( $filters['orderby'] ) ? $filters['orderby'] : $more_settings['default-sort-by'];
1150 foreach ( $list_items as $slug ) :
1151 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1152 if ( ! $cf ) {
1153 continue;
1154 }
1155 if ( $cf->type::$is_sort ) :
1156 ?>
1157 <option <?php selected( $orderby, $cf->slug ); ?> value="<?php echo esc_attr( $cf->slug ); ?>"><?php echo esc_attr( $cf->name ); ?></option>
1158 <?php
1159 endif;
1160 endforeach;
1161 ?>
1162 </select>
1163 </div>
1164 <div class="wpsc-input-group">
1165 <div class="label-container">
1166 <label for="">
1167 <?php esc_attr_e( 'Sort order', 'supportcandy' ); ?>
1168 <span class="required-char">*</span>
1169 </label>
1170 </div>
1171 <select name="sort-order">
1172 <?php
1173 $order = isset( $filters['order'] ) ? $filters['order'] : $more_settings['default-sort-order'];
1174 ?>
1175 <option <?php selected( $order, 'ASC' ); ?> value="ASC"><?php esc_attr_e( 'ASC', 'supportcandy' ); ?></option>
1176 <option <?php selected( $order, 'DESC' ); ?> value="DESC"><?php esc_attr_e( 'DESC', 'supportcandy' ); ?></option>
1177 </select>
1178 </div>
1179 </form>
1180 <?php
1181 $body = ob_get_clean();
1182
1183 ob_start();
1184 ?>
1185 <button class="wpsc-button small primary" onclick="wpsc_tl_apply_custom_filter(this, 'ticket_list');">
1186 <?php esc_attr_e( 'Apply', 'supportcandy' ); ?>
1187 </button>
1188 <?php
1189
1190 if ( ! $current_user->is_guest ) :
1191 ?>
1192 <button class="wpsc-button small secondary" onclick="wpsc_tl_add_saved_filter(this);">
1193 <?php esc_attr_e( 'Save & Apply', 'supportcandy' ); ?>
1194 </button>
1195 <?php
1196 endif;
1197 ?>
1198
1199 <button class="wpsc-button small secondary" onclick="<?php echo $filters ? 'wpsc_close_modal()' : 'wpsc_tl_close_custom_filter_modal()'; ?>;">
1200 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1201 </button>
1202 <?php
1203 $footer = ob_get_clean();
1204
1205 $response = array(
1206 'title' => $title,
1207 'body' => $body,
1208 'footer' => $footer,
1209 );
1210 wp_send_json( $response );
1211 }
1212
1213 /**
1214 * Add saved filter UI
1215 *
1216 * @return void
1217 */
1218 public static function get_add_saved_filter_ui() {
1219
1220 $current_user = WPSC_Current_User::$current_user;
1221 if ( ! $current_user->customer->user->ID ) {
1222 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1223 }
1224
1225 $title = esc_attr__( 'Custom filter', 'supportcandy' );
1226
1227 ob_start();
1228 ?>
1229 <form action="#" onsubmit="return false;" class="wpsc-tl-add-saved-filter">
1230 <div class="wpsc-input-group">
1231 <div class="label-container">
1232 <label for="">
1233 <?php esc_attr_e( 'Label', 'supportcandy' ); ?>
1234 <span class="required-char">*</span>
1235 </label>
1236 </div>
1237 <input class="wpsc-cf-label" type="text" name="label" autocomplete="off"/>
1238 </div>
1239 </form>
1240 <?php
1241 $body = ob_get_clean();
1242
1243 ob_start();
1244 ?>
1245 <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' ) ); ?>');">
1246 <?php esc_attr_e( 'Save & Apply', 'supportcandy' ); ?>
1247 </button>
1248 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1249 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1250 </button>
1251 <?php
1252 $footer = ob_get_clean();
1253
1254 $response = array(
1255 'title' => $title,
1256 'body' => $body,
1257 'footer' => $footer,
1258 );
1259 wp_send_json( $response );
1260 }
1261
1262 /**
1263 * Set add saved filter
1264 */
1265 public static function set_add_saved_filter() {
1266
1267 if ( check_ajax_referer( 'wpsc_tl_set_add_saved_filter', '_ajax_nonce', false ) != 1 ) {
1268 wp_send_json_error( 'Unauthorized request!', 401 );
1269 }
1270
1271 $current_user = WPSC_Current_User::$current_user;
1272 if ( ! $current_user->customer->user->ID || ! isset( $_POST['filters'] ) ) {
1273 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1274 }
1275
1276 $default_filters = $current_user->is_agent ? get_option( 'wpsc-atl-default-filters' ) : get_option( 'wpsc-atl-default-filters' );
1277
1278 $label = isset( $_POST['filters']['label'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['label'] ) ) : '';
1279 if ( ! $label ) {
1280 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1281 }
1282
1283 $parent_filter = isset( $_POST['filters']['parent-filter'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['parent-filter'] ) ) : '';
1284 if ( ! $parent_filter || ! isset( $default_filters[ $parent_filter ] ) ) {
1285 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1286 }
1287
1288 $filters = isset( $_POST['filters']['filters'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['filters'] ) ) : '';
1289 if ( ! $filters || $filters == '[]' || ! WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters ) ) {
1290 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1291 }
1292
1293 $filters = str_replace( '\n', PHP_EOL, $filters );
1294
1295 $sort_by = isset( $_POST['filters']['orderby'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['orderby'] ) ) : '';
1296 if ( ! $sort_by ) {
1297 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1298 }
1299
1300 $sort_order = isset( $_POST['filters']['order'] ) ? sanitize_text_field( wp_unslash( $_POST['filters']['order'] ) ) : '';
1301 if ( ! $sort_order ) {
1302 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1303 }
1304
1305 $saved_filters = $current_user->get_saved_filters();
1306 $index = WPSC_Functions::get_tl_cf_auto_increament();
1307 $saved_filters[ $index ] = array(
1308 'label' => $label,
1309 'parent-filter' => $parent_filter,
1310 'filters' => $filters,
1311 'sort-by' => $sort_by,
1312 'sort-order' => $sort_order,
1313 );
1314 update_user_meta( $current_user->customer->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', $saved_filters );
1315
1316 $response = array( 'slug' => 'saved-' . $index );
1317 wp_send_json( $response );
1318 }
1319
1320 /**
1321 * Edit saved filter UI
1322 *
1323 * @return void
1324 */
1325 public static function get_edit_saved_filter_ui() {
1326
1327 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1328 wp_send_json_error( 'Unauthorized request!', 401 );
1329 }
1330
1331 $current_user = WPSC_Current_User::$current_user;
1332 if ( ! $current_user->customer->user->ID ) {
1333 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1334 }
1335
1336 $filter_slug = isset( $_POST['filterSlug'] ) ? sanitize_text_field( wp_unslash( $_POST['filterSlug'] ) ) : '';
1337 if ( ! $filter_slug ) {
1338 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1339 }
1340
1341 $flag = preg_match( '/saved-(\d*)$/', $filter_slug, $matches );
1342 if ( ! $flag ) {
1343 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1344 }
1345
1346 $saved_filters = $current_user->get_saved_filters();
1347 $filters = $saved_filters[ $matches[1] ];
1348
1349 $title = $filters['label'];
1350 $default_filters = $current_user->is_agent ? get_option( 'wpsc-atl-default-filters' ) : get_option( 'wpsc-atl-default-filters' );
1351 $list_items = $current_user->get_tl_list_items();
1352 $more_settings = $current_user->is_agent ? get_option( 'wpsc-tl-ms-agent-view' ) : get_option( 'wpsc-tl-ms-customer-view' );
1353 $custom_filters = str_replace( PHP_EOL, '\n', $filters['filters'] );
1354
1355 ob_start();
1356 ?>
1357 <form action="#" onsubmit="return false;" class="wpsc-tl-custom-filter">
1358 <div class="wpsc-input-group">
1359 <div class="label-container">
1360 <label for="">
1361 <?php esc_attr_e( 'Label', 'supportcandy' ); ?>
1362 <span class="required-char">*</span>
1363 </label>
1364 </div>
1365 <input class="wpsc-cf-label" type="text" name="label" value="<?php echo esc_attr( $filters['label'] ); ?>" autocomplete="off"/>
1366 </div>
1367 <div class="wpsc-input-group">
1368 <div class="label-container">
1369 <label for="">
1370 <?php esc_attr_e( 'Parent filter', 'supportcandy' ); ?>
1371 <span class="required-char">*</span>
1372 </label>
1373 </div>
1374 <select name="parent-filter">
1375 <?php
1376 foreach ( $default_filters as $slug => $filter ) :
1377 $selected = isset( $filters['parent-filter'] ) && $filters['parent-filter'] == $slug ? 'selected="selected"' : ''
1378 ?>
1379 <option <?php echo esc_attr( $selected ); ?> value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_attr( $filter['label'] ); ?></option>
1380 <?php
1381 endforeach;
1382 ?>
1383 </select>
1384 </div>
1385 <?php WPSC_Ticket_Conditions::print( 'custom_filters', 'wpsc_custom_filter_conditions', $custom_filters, true, __( 'Filters', 'supportcandy' ) ); ?>
1386 <div class="wpsc-input-group">
1387 <div class="label-container">
1388 <label for="">
1389 <?php esc_attr_e( 'Sort by', 'supportcandy' ); ?>
1390 <span class="required-char">*</span>
1391 </label>
1392 </div>
1393 <select name="sort-by">
1394 <?php
1395 $orderby = isset( $filters['sort-by'] ) ? $filters['sort-by'] : $more_settings['default-sort-by'];
1396 foreach ( $list_items as $slug ) :
1397 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
1398 if ( ! $cf ) {
1399 continue;
1400 }
1401 if ( $cf->type::$is_sort ) :
1402 ?>
1403 <option <?php selected( $orderby, $cf->slug ); ?> value="<?php echo esc_attr( $cf->slug ); ?>"><?php echo esc_attr( $cf->name ); ?></option>
1404 <?php
1405 endif;
1406 endforeach;
1407 ?>
1408 </select>
1409 </div>
1410 <div class="wpsc-input-group">
1411 <div class="label-container">
1412 <label for="">
1413 <?php esc_attr_e( 'Sort order', 'supportcandy' ); ?>
1414 <span class="required-char">*</span>
1415 </label>
1416 </div>
1417 <select name="sort-order">
1418 <?php
1419 $order = isset( $filters['sort-order'] ) ? $filters['sort-order'] : $more_settings['default-sort-order'];
1420 ?>
1421 <option <?php selected( $order, 'ASC' ); ?> value="ASC"><?php esc_attr_e( 'ASC', 'supportcandy' ); ?></option>
1422 <option <?php selected( $order, 'DESC' ); ?> value="DESC"><?php esc_attr_e( 'DESC', 'supportcandy' ); ?></option>
1423 </select>
1424 </div>
1425 <input type="hidden" name="action" value="wpsc_tl_set_edit_saved_filter"/>
1426 <input type="hidden" name="slug" value="<?php echo esc_attr( $matches[1] ); ?>"/>
1427 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_tl_set_edit_saved_filter' ) ); ?>">
1428 </form>
1429 <?php
1430 $body = ob_get_clean();
1431
1432 ob_start();
1433 ?>
1434 <button class="wpsc-button small primary" onclick="wpsc_tl_set_edit_saved_filter(this);">
1435 <?php esc_attr_e( 'Save & Apply', 'supportcandy' ); ?>
1436 </button>
1437 <button class="wpsc-button small secondary" onclick="wpsc_tl_add_saved_filter();">
1438 <?php esc_attr_e( 'Save As', 'supportcandy' ); ?>
1439 </button>
1440 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1441 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1442 </button>
1443 <?php
1444 $footer = ob_get_clean();
1445
1446 $response = array(
1447 'title' => $title,
1448 'body' => $body,
1449 'footer' => $footer,
1450 );
1451 wp_send_json( $response );
1452 }
1453
1454 /**
1455 * Set edit saved filter
1456 */
1457 public static function set_edit_saved_filter() {
1458
1459 if ( check_ajax_referer( 'wpsc_tl_set_edit_saved_filter', '_ajax_nonce', false ) != 1 ) {
1460 wp_send_json_error( 'Unauthorized request!', 401 );
1461 }
1462
1463 $current_user = WPSC_Current_User::$current_user;
1464 if ( ! $current_user->customer->user->ID ) {
1465 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1466 }
1467
1468 $slug = isset( $_POST['slug'] ) ? intval( $_POST['slug'] ) : 0;
1469 if ( ! $slug ) {
1470 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1471 }
1472
1473 $saved_filters = $current_user->get_saved_filters();
1474 if ( ! isset( $saved_filters[ $slug ] ) ) {
1475 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1476 }
1477
1478 $label = isset( $_POST['label'] ) ? sanitize_text_field( wp_unslash( $_POST['label'] ) ) : '';
1479 if ( ! $label ) {
1480 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1481 }
1482
1483 $parent_filter = isset( $_POST['parent-filter'] ) ? sanitize_text_field( wp_unslash( $_POST['parent-filter'] ) ) : '';
1484 if ( ! $parent_filter ) {
1485 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1486 }
1487
1488 $filters = isset( $_POST['filters'] ) ? sanitize_text_field( wp_unslash( $_POST['filters'] ) ) : '';
1489 if ( ! $filters || $filters == '[]' || ! WPSC_Ticket_Conditions::is_valid_input_conditions( 'wpsc_custom_filter_conditions', $filters ) ) {
1490 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1491 }
1492
1493 $filters = str_replace( '\n', PHP_EOL, $filters );
1494
1495 $sort_by = isset( $_POST['sort-by'] ) ? sanitize_text_field( wp_unslash( $_POST['sort-by'] ) ) : '';
1496 if ( ! $sort_by ) {
1497 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1498 }
1499
1500 $sort_order = isset( $_POST['sort-order'] ) ? sanitize_text_field( wp_unslash( $_POST['sort-order'] ) ) : '';
1501 if ( ! $sort_order ) {
1502 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1503 }
1504
1505 $saved_filters[ $slug ] = array(
1506 'label' => $label,
1507 'parent-filter' => $parent_filter,
1508 'filters' => $filters,
1509 'sort-by' => $sort_by,
1510 'sort-order' => $sort_order,
1511 );
1512 update_user_meta( $current_user->customer->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', $saved_filters );
1513 wp_die();
1514 }
1515
1516 /**
1517 * Delete saved filter
1518 *
1519 * @return void
1520 */
1521 public static function delete_saved_filter() {
1522
1523 if ( check_ajax_referer( 'general', '_ajax_nonce', false ) != 1 ) {
1524 wp_send_json_error( 'Unauthorized request!', 401 );
1525 }
1526
1527 $current_user = WPSC_Current_User::$current_user;
1528 if ( ! $current_user->customer->user->ID ) {
1529 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1530 }
1531
1532 $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : '';
1533 if ( ! $slug ) {
1534 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1535 }
1536
1537 $flag = preg_match( '/saved-(\d*)$/', $slug, $matches );
1538 if ( ! $flag ) {
1539 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1540 }
1541
1542 $slug = $matches[1];
1543
1544 $saved_filters = $current_user->get_saved_filters();
1545 if ( ! isset( $saved_filters[ $slug ] ) ) {
1546 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
1547 }
1548
1549 unset( $saved_filters[ $slug ] );
1550
1551 update_user_meta( $current_user->customer->user->ID, get_current_blog_id() . '-wpsc-tl-saved-filters', $saved_filters );
1552 wp_die();
1553 }
1554
1555 /**
1556 * Get change bult ticket status/categoty/priority
1557 *
1558 * @return void
1559 */
1560 public static function bulk_change_status() {
1561
1562 if ( check_ajax_referer( 'wpsc_bulk_change_status', '_ajax_nonce', false ) != 1 ) {
1563 wp_send_json_error( 'Unauthorized request!', 401 );
1564 }
1565
1566 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
1567 if ( ! $ticket_ids ) {
1568 wp_send_json_error( 'Something went wrong!', 400 );
1569 }
1570
1571 $widgets = get_option( 'wpsc-ticket-widget' );
1572 $title = $widgets['change-status']['title'];
1573
1574 $current_user = WPSC_Current_User::$current_user;
1575
1576 $gs = get_option( 'wpsc-gs-general' );
1577 $tl_advanced = get_option( 'wpsc-tl-ms-advanced' );
1578 $close_flag = in_array( $current_user->agent->role, $gs['allow-close-ticket'] ) ? true : false;
1579
1580 $statuses = WPSC_Status::find( array( 'items_per_page' => 0 ) )['results'];
1581 $categories = WPSC_Category::find( array( 'items_per_page' => 0 ) )['results'];
1582 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
1583
1584 ob_start();
1585 ?>
1586 <form action="#" onsubmit="return false;" class="frm-edit-bulk-status">
1587 <div class="wpsc-input-group">
1588 <?php $cf = WPSC_Custom_Field::get_cf_by_slug( 'status' ); ?>
1589 <div class="label-container">
1590 <label for=""><?php echo esc_attr( $cf->name ); ?></label>
1591 </div>
1592 <select id="wpsc-select-bulk-ticket-status" name="status_id">
1593 <option value=""></option>
1594 <?php
1595 foreach ( $statuses as $status ) :
1596 if (
1597 ( $status->id == $gs['close-ticket-status'] || in_array( $status->id, $tl_advanced['closed-ticket-statuses'] ) ) &&
1598 ! $close_flag
1599 ) {
1600 continue;
1601 }
1602 ?>
1603 <option value="<?php echo esc_attr( $status->id ); ?>"><?php echo esc_attr( $status->name ); ?></option>
1604 <?php
1605 endforeach;
1606 ?>
1607 </select>
1608 <script>
1609 jQuery('#wpsc-select-bulk-ticket-status').selectWoo({
1610 allowClear: true,
1611 placeholder: ""
1612 });
1613 </script>
1614 </div>
1615 <div class="wpsc-input-group">
1616 <?php $cf = WPSC_Custom_Field::get_cf_by_slug( 'category' ); ?>
1617 <div class="label-container">
1618 <label for=""><?php echo esc_attr( $cf->name ); ?></label>
1619 </div>
1620 <select id="wpsc-select-bulk-ticket-category" name="cat_id">
1621 <option value=""></option>
1622 <?php
1623 foreach ( $categories as $category ) :
1624 ?>
1625 <option value="<?php echo esc_attr( $category->id ); ?>"><?php echo esc_attr( $category->name ); ?></option>
1626 <?php
1627 endforeach;
1628 ?>
1629 </select>
1630 <script>
1631 jQuery('#wpsc-select-bulk-ticket-category').selectWoo({
1632 allowClear: true,
1633 placeholder: ""
1634 });
1635 </script>
1636 </div>
1637 <div class="wpsc-input-group">
1638 <?php $cf = WPSC_Custom_Field::get_cf_by_slug( 'priority' ); ?>
1639 <div class="label-container">
1640 <label for=""><?php echo esc_attr( $cf->name ); ?></label>
1641 </div>
1642 <select id="wpsc-select-bulk-ticket-priority" name="priority_id">
1643 <option value=""></option>
1644 <?php
1645 foreach ( $priorities as $priority ) :
1646 ?>
1647 <option value="<?php echo esc_attr( $priority->id ); ?>"><?php echo esc_attr( $priority->name ); ?></option>
1648 <?php
1649 endforeach;
1650 ?>
1651 </select>
1652 <script>
1653 jQuery('#wpsc-select-bulk-ticket-priority').selectWoo({
1654 allowClear: true,
1655 placeholder: ""
1656 });
1657 </script>
1658 </div>
1659 <?php do_action( 'wpsc_get_bulk_ticket_status_body', $ticket_ids ); ?>
1660 <input type="hidden" name="action" value="wpsc_set_bulk_change_status">
1661 <input type="hidden" name="ticket_ids" value="<?php echo esc_attr( implode( ',', $ticket_ids ) ); ?>">
1662 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_bulk_change_status' ) ); ?>">
1663 </form>
1664 <?php
1665 do_action( 'wpsc_get_bulk_ticket_status_footer', $ticket_ids );
1666 $body = ob_get_clean();
1667
1668 ob_start();
1669 ?>
1670 <button class="wpsc-button small primary" onclick="wpsc_set_bulk_change_status(this);">
1671 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
1672 </button>
1673 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1674 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1675 </button>
1676 <?php
1677 $footer = ob_get_clean();
1678
1679 $response = array(
1680 'title' => $title,
1681 'body' => $body,
1682 'footer' => $footer,
1683 );
1684 wp_send_json( $response );
1685 }
1686
1687 /**
1688 * Set change bulk statuses/category/priority
1689 *
1690 * @return void
1691 */
1692 public static function set_bulk_change_status() {
1693
1694 if ( check_ajax_referer( 'wpsc_set_bulk_change_status', '_ajax_nonce', false ) != 1 ) {
1695 wp_send_json_error( 'Unauthorized request!', 401 );
1696 }
1697
1698 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_POST['ticket_ids'] ) ) ) ) ) : array();
1699 if ( ! $ticket_ids ) {
1700 wp_send_json_error( 'Missing ticket ids', 400 );
1701 }
1702
1703 $current_user = WPSC_Current_User::$current_user;
1704
1705 $status_id = isset( $_POST['status_id'] ) ? intval( $_POST['status_id'] ) : 0;
1706 $cat_id = isset( $_POST['cat_id'] ) ? intval( $_POST['cat_id'] ) : 0;
1707 $priority_id = isset( $_POST['priority_id'] ) ? intval( $_POST['priority_id'] ) : 0;
1708
1709 $gs = get_option( 'wpsc-gs-general' );
1710 $tl_advanced = get_option( 'wpsc-tl-ms-advanced' );
1711 $close_flag = in_array( $current_user->agent->role, $gs['allow-close-ticket'] ) ? true : false;
1712
1713 foreach ( $ticket_ids as $ticket_id ) {
1714
1715 $ticket = new WPSC_Ticket( $ticket_id );
1716 if ( ! $ticket->id ) {
1717 continue;
1718 }
1719
1720 WPSC_Individual_Ticket::$ticket = $ticket;
1721
1722 if (
1723 ( $status_id == $gs['close-ticket-status'] || in_array( $status_id, $tl_advanced['closed-ticket-statuses'] ) ) &&
1724 ! $close_flag
1725 ) {
1726 continue;
1727 }
1728
1729 if ( $ticket->is_active && ! ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'cs' ) ) ) {
1730 continue;
1731 }
1732
1733 // Check status.
1734 if ( $status_id && $ticket->status->id != $status_id ) {
1735 WPSC_Individual_Ticket::change_status( $ticket->status->id, $status_id, $current_user->customer->id );
1736 }
1737
1738 // Check category.
1739 if ( $cat_id && $ticket->category->id != $cat_id ) {
1740 WPSC_Individual_Ticket::change_category( $ticket->category->id, $cat_id, $current_user->customer->id );
1741 }
1742
1743 // Check priority.
1744 if ( $priority_id && $ticket->priority->id != $priority_id ) {
1745 WPSC_Individual_Ticket::change_priority( $ticket->priority->id, $priority_id, $current_user->customer->id );
1746 }
1747 }
1748 wp_die();
1749 }
1750
1751 /**
1752 * Get edit assign agents
1753 *
1754 * @return void
1755 */
1756 public static function bulk_assign_agents() {
1757
1758 if ( check_ajax_referer( 'wpsc_bulk_assign_agents', '_ajax_nonce', false ) != 1 ) {
1759 wp_send_json_error( 'Unauthorized request!', 401 );
1760 }
1761
1762 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
1763 if ( ! $ticket_ids ) {
1764 wp_send_json_error( 'Something went wrong!', 400 );
1765 }
1766
1767 $widgets = get_option( 'wpsc-ticket-widget' );
1768 $title = $widgets['assignee']['title'];
1769
1770 ob_start();
1771 ?>
1772 <form action="#" onsubmit="return false;" class="frm-bulk-assign-agent">
1773 <div class="wpsc-input-group" style="flex-direction:row; flex-wrap:nowrap;">
1774 <div class="wpsc-input-group">
1775 <div class="label-container">
1776 <label for=""><?php esc_attr_e( 'Filter by', 'supportcandy' ); ?></label>
1777 </div>
1778 <select class="agent-filter-by">
1779 <?php
1780 $filter_by = apply_filters(
1781 'wpsc_assignee_filter_by',
1782 array(
1783 'all' => esc_attr__( 'All', 'supportcandy' ),
1784 )
1785 );
1786 foreach ( $filter_by as $key => $label ) :
1787 ?>
1788 <option value="<?php echo esc_attr( $key ); ?>"><?php echo esc_attr( $label ); ?></option>
1789 <?php
1790 endforeach
1791 ?>
1792 </select>
1793 </div>
1794 <div style="margin:5px;"></div>
1795 <div class="wpsc-input-group">
1796 <div class="label-container">
1797 <label for=""><?php esc_attr_e( 'Sort by', 'supportcandy' ); ?></label>
1798 </div>
1799 <select class="agent-sort-by">
1800 <option value="workload"><?php esc_attr_e( 'Workload', 'supportcandy' ); ?></option>
1801 <option value="name"><?php esc_attr_e( 'Name', 'supportcandy' ); ?></option>
1802 </select>
1803 </div>
1804 </div>
1805 <div class="wpsc-input-group">
1806 <div class="label-container">
1807 <label for=""><?php esc_attr_e( 'Select agent(s)', 'supportcandy' ); ?></label>
1808 </div>
1809 <select id="wpsc-select-bulk-assign-agent" multiple name="assignee[]"></select>
1810 <script>
1811 jQuery('#wpsc-select-bulk-assign-agent').selectWoo({
1812 ajax: {
1813 url: supportcandy.ajax_url,
1814 dataType: 'json',
1815 delay: 250,
1816 data: function (params) {
1817 return {
1818 q: params.term, // search term.
1819 action: 'wpsc_agent_autocomplete_bulk_assign',
1820 _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_agent_autocomplete_bulk_assign' ) ); ?>',
1821 filter_by: jQuery('select.agent-filter-by').val(),
1822 sort_by: jQuery('select.agent-sort-by').val(),
1823 isMultiple: 1,
1824 };
1825 },
1826 processResults: function (data, params) {
1827 var terms = [];
1828 if ( data ) {
1829 jQuery.each( data, function( id, text ) {
1830 terms.push( { id: text.id, text: text.title } );
1831 });
1832 }
1833 return {
1834 results: terms
1835 };
1836 },
1837 cache: true
1838 },
1839 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work.
1840 minimumInputLength: 0,
1841 allowClear: false,
1842 placeholder: ""
1843 });
1844 </script>
1845 </div>
1846 <?php do_action( 'wpsc_get_bulk_assigned_agent_body', $ticket_ids ); ?>
1847 <input type="hidden" name="action" value="wpsc_set_bulk_assign_agent">
1848 <input type="hidden" name="ticket_ids" value="<?php echo esc_attr( implode( ',', $ticket_ids ) ); ?>">
1849 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_bulk_assign_agent' ) ); ?>">
1850 </form>
1851 <?php
1852 do_action( 'wpsc_get_bulk_assigned_agent_footer' );
1853 $body = ob_get_clean();
1854
1855 ob_start();
1856 ?>
1857 <button class="wpsc-button small primary" onclick="wpsc_set_bulk_assign_agent(this);">
1858 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
1859 </button>
1860 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
1861 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
1862 </button>
1863 <?php
1864 $footer = ob_get_clean();
1865
1866 $response = array(
1867 'title' => $title,
1868 'body' => $body,
1869 'footer' => $footer,
1870 );
1871
1872 wp_send_json( $response );
1873 }
1874
1875 /**
1876 * Change assigned agent
1877 *
1878 * @return void
1879 */
1880 public static function set_bulk_assign_agent() {
1881
1882 if ( check_ajax_referer( 'wpsc_set_bulk_assign_agent', '_ajax_nonce', false ) != 1 ) {
1883 wp_send_json_error( 'Unauthorized request!', 401 );
1884 }
1885
1886 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_POST['ticket_ids'] ) ) ) ) ) : array();
1887 if ( ! $ticket_ids ) {
1888 wp_send_json_error( 'Missing ticket ids', 400 );
1889 }
1890
1891 $new_ids = isset( $_POST['assignee'] ) ? array_filter( array_map( 'intval', $_POST['assignee'] ) ) : array();
1892 if ( ! $new_ids ) {
1893 wp_send_json_error( 'Something went wrong!', 400 );
1894 }
1895
1896 foreach ( $ticket_ids as $ticket_id ) {
1897
1898 $ticket = new WPSC_Ticket( $ticket_id );
1899 if ( ! $ticket->id ) {
1900 continue;
1901 }
1902
1903 WPSC_Individual_Ticket::$ticket = $ticket;
1904
1905 $current_user = WPSC_Current_User::$current_user;
1906 if ( $ticket->is_active && ! ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'aa' ) ) ) {
1907 continue;
1908 }
1909
1910 $prev = $ticket->assigned_agent;
1911
1912 // Check whether all new agets exists.
1913 $new = array();
1914 foreach ( $new_ids as $id ) {
1915 $agent = new WPSC_Agent( $id );
1916 $new[] = $agent;
1917 if ( ! $agent->id ) {
1918 wp_send_json_error( 'Something went wrong!', 400 );
1919 }
1920 }
1921
1922 $prev_ids = array();
1923 foreach ( $prev as $agent ) {
1924 $prev_ids[] = $agent->id;
1925 }
1926
1927 // Exit if there is no change.
1928 if (
1929 count( array_diff( $new_ids, $prev_ids ) ) === 0 &&
1930 count( array_diff( $prev_ids, $new_ids ) ) === 0
1931 ) {
1932 continue;
1933 }
1934
1935 // Change assignee.
1936 WPSC_Individual_Ticket::change_assignee( $prev, $new, $current_user->customer->id );
1937 }
1938 wp_die();
1939 }
1940
1941 /**
1942 * Get change bulk ticket tags
1943 *
1944 * @return void
1945 */
1946 public static function bulk_assign_tags() {
1947
1948 if ( check_ajax_referer( 'wpsc_bulk_assign_tags', '_ajax_nonce', false ) != 1 ) {
1949 wp_send_json_error( 'Unauthorized request!', 401 );
1950 }
1951
1952 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
1953 if ( ! $ticket_ids ) {
1954 wp_send_json_error( 'Something went wrong!', 400 );
1955 }
1956
1957 $ticket_widgets = get_option( 'wpsc-ticket-widget', array() );
1958 $title = $ticket_widgets['tags']['title'];
1959
1960 $tags = WPSC_Ticket_Tags::find( array( 'items_per_page' => 0 ) )['results'];
1961 $unique_id = uniqid();
1962 ob_start();
1963 ?>
1964
1965 <form action="#" onsubmit="return false;" class="frm-bulk-assign-tags">
1966 <div class="wpsc-input-group">
1967 <div class="label-container">
1968 <label for=""><?php esc_attr_e( 'Select tag(s)', 'supportcandy' ); ?></label>
1969 </div>
1970 <select id="wpsc-tags" class="wpsc-tags" multiple name="tags[]"></select>
1971 </div>
1972 <script>
1973 jQuery(document).ready(function(){
1974 if (!jQuery('select.wpsc-tags').hasClass("select2-hidden-accessible")) {
1975 jQuery('select.wpsc-tags').selectWoo({
1976 tags: true,
1977 ajax: {
1978 url: supportcandy.ajax_url,
1979 dataType: 'json',
1980 delay: 250,
1981 data: function (params) {
1982 return {
1983 q: params.term, // search term
1984 page: params.page,
1985 action: 'wpsc_tag_autocomplete',
1986 tags: jQuery( this ).val(),
1987 _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wpsc_tag_autocomplete' ) ); ?>'
1988 };
1989 },
1990 processResults: function (data, params) {
1991 var terms = [];
1992 if ( data ) {
1993 jQuery.each( data, function( id, text ) {
1994 terms.push( { id: text.id, text: text.title } );
1995 });
1996 }
1997 return {
1998 results: terms
1999 };
2000 },
2001 cache: true
2002 },
2003 escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
2004 minimumInputLength: 0,
2005 placeholder: ""
2006 });
2007 }
2008 });
2009 </script>
2010 <?php do_action( 'wpsc_get_bulk_assigned_tag_body', $ticket_ids ); ?>
2011 <input type="hidden" name="action" value="wpsc_set_bulk_assign_tag">
2012 <input type="hidden" name="ticket_ids" value="<?php echo esc_attr( implode( ',', $ticket_ids ) ); ?>">
2013 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_bulk_assign_tag' ) ); ?>">
2014 </form>
2015 <?php
2016 do_action( 'wpsc_get_bulk_assigned_tag_footer', $ticket_ids );
2017 $body = ob_get_clean();
2018
2019 ob_start();
2020 ?>
2021 <button class="wpsc-button small primary" onclick="wpsc_set_bulk_assign_tag(this);">
2022 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
2023 </button>
2024 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
2025 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
2026 </button>
2027 <?php
2028 $footer = ob_get_clean();
2029
2030 $response = array(
2031 'title' => $title,
2032 'body' => $body,
2033 'footer' => $footer,
2034 );
2035 wp_send_json( $response );
2036 }
2037
2038 /**
2039 * Change assigned tag
2040 *
2041 * @return void
2042 */
2043 public static function set_bulk_assign_tag() {
2044
2045 if ( check_ajax_referer( 'wpsc_set_bulk_assign_tag', '_ajax_nonce', false ) != 1 ) {
2046 wp_send_json_error( 'Unauthorized request!', 401 );
2047 }
2048
2049 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_POST['ticket_ids'] ) ) ) ) ) : array();
2050 if ( ! $ticket_ids ) {
2051 wp_send_json_error( 'Missing ticket ids', 400 );
2052 }
2053
2054 $tags = isset( $_POST['tags'] ) ? array_filter( array_map( 'sanitize_text_field', wp_unslash( $_POST['tags'] ) ) ) : array();
2055 if ( ! $tags ) {
2056 wp_send_json_error( 'Something went wrong!', 400 );
2057 }
2058 $general = get_option( 'wpsc-ticket-tags-general-settings' );
2059
2060 foreach ( $ticket_ids as $ticket_id ) {
2061
2062 $ticket = new WPSC_Ticket( $ticket_id );
2063 if ( ! $ticket->id ) {
2064 continue;
2065 }
2066
2067 WPSC_Individual_Ticket::$ticket = $ticket;
2068
2069 $current_user = WPSC_Current_User::$current_user;
2070 if ( ! ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'tt' ) ) ) {
2071 continue;
2072 }
2073
2074 $prev_tags = array();
2075 foreach ( $ticket->tags as $tag ) {
2076 $prev_tags[] = $tag->id;
2077 }
2078
2079 $ticket_tags = array();
2080 foreach ( $tags as $key => $tag_id ) {
2081
2082 $tag = new WPSC_Ticket_Tags( $tag_id );
2083 if ( ! $tag->id ) {
2084
2085 $data = array(
2086 'name' => $tag_id,
2087 'description' => '',
2088 'color' => $general['color'],
2089 'bg_color' => $general['bg-color'],
2090 );
2091 $new_tag = WPSC_Ticket_Tags::insert( $data );
2092 $tags[ $key ] = $new_tag->id;
2093 }
2094 $ticket_tags[] = $tags[ $key ];
2095 }
2096
2097 $new_tags = array_unique( array_merge( $prev_tags, $ticket_tags ) );
2098 // Change tag.
2099 WPSC_Individual_Ticket::change_tag( $prev_tags, $new_tags, $current_user->customer->id );
2100 }
2101
2102 wp_die();
2103 }
2104
2105 /**
2106 * Archive ticket ajax request
2107 */
2108 public static function bulk_archive_tickets() {
2109
2110 if ( check_ajax_referer( 'wpsc_bulk_archive_tickets', '_ajax_nonce', false ) != 1 ) {
2111 wp_send_json_error( 'Unauthorized request!', 401 );
2112 }
2113
2114 $current_user = WPSC_Current_User::$current_user;
2115 if ( ! $current_user->is_agent ) {
2116 wp_send_json_error( 'Unauthorized request!', 401 );
2117 }
2118
2119 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2120 if ( ! $ticket_ids ) {
2121 wp_send_json_error( 'Something went wrong!', 400 );
2122 }
2123
2124 foreach ( $ticket_ids as $ticket_id ) {
2125
2126 $ticket = new WPSC_Ticket( $ticket_id );
2127 WPSC_Individual_Ticket::$ticket = $ticket;
2128 if ( ! $ticket->id || ! WPSC_Individual_Ticket::has_ticket_cap( 'at' ) ) {
2129 continue;
2130 }
2131
2132 WPSC_Individual_Ticket::archive_ticket();
2133 }
2134 wp_die();
2135 }
2136
2137 /**
2138 * Permanently delete ticket ajax request
2139 */
2140 public static function bulk_permanently_delete_tickets() {
2141
2142 if ( check_ajax_referer( 'wpsc_bulk_permanently_delete_tickets', '_ajax_nonce', false ) != 1 ) {
2143 wp_send_json_error( 'Unauthorised request!', 401 );
2144 }
2145
2146 $current_user = WPSC_Current_User::$current_user;
2147 if ( ! $current_user->is_agent ) {
2148 wp_send_json_error( 'Unauthorised request!', 401 );
2149 }
2150
2151 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2152 if ( ! $ticket_ids ) {
2153 wp_send_json_error( 'Something went wrong!', 400 );
2154 }
2155
2156 foreach ( $ticket_ids as $ticket_id ) {
2157
2158 $ticket = new WPSC_Ticket( $ticket_id );
2159 WPSC_Individual_Ticket::$ticket = $ticket;
2160 if ( ! $ticket->id || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2161 continue;
2162 }
2163 WPSC_Ticket::destroy( $ticket );
2164 }
2165 wp_die();
2166 }
2167
2168 /**
2169 * Check parent filter is deleted or not
2170 *
2171 * @param string $slug - filter type.
2172 * @return boolean
2173 */
2174 public static function has_delete_parent_filter( $slug ) {
2175
2176 // phpcs:disable
2177 switch ( $slug ) {
2178
2179 case 'all':
2180 return false;
2181 break;
2182
2183 case 'unresolved':
2184 return false;
2185 break;
2186
2187 case 'mine':
2188 return false;
2189 break;
2190
2191 case 'closed':
2192 return false;
2193 break;
2194
2195 case 'deleted':
2196 return true;
2197 break;
2198
2199 default:
2200 if ( ! is_numeric( $slug ) || ! isset( self::$default_filters[ $slug ] ) ) {
2201 return false;
2202 }
2203 $slug = self::$default_filters[ $slug ]['parent-filter'];
2204 self::has_delete_parent_filter( $slug );
2205 }
2206 // phpcs:enable
2207 }
2208
2209 /**
2210 * Set bulk actions for current user
2211 */
2212 public static function set_bulk_actions() {
2213
2214 $current_user = WPSC_Current_User::$current_user;
2215 $is_deleted = self::is_current_filter_deleted();
2216 $bulk_actions = array();
2217
2218 if ( ! $is_deleted ) {
2219 if ( $current_user->is_agent && self::has_ticket_cap( 'cs' ) ) {
2220 $bulk_actions['change-status'] = array(
2221 'icon' => 'gps-navigation',
2222 'label' => esc_attr__( 'Change Status', 'supportcandy' ),
2223 'callback' => 'wpsc_bulk_change_status',
2224 );
2225 }
2226
2227 if ( $current_user->is_agent && self::has_ticket_cap( 'aa' ) ) {
2228 $bulk_actions['assign-agents'] = array(
2229 'icon' => 'headset',
2230 'label' => esc_attr__( 'Assign Agents', 'supportcandy' ),
2231 'callback' => 'wpsc_bulk_assign_agents',
2232 );
2233 }
2234
2235 if ( $current_user->is_agent && self::has_ticket_cap( 'tt' ) ) {
2236 $bulk_actions['assign-tags'] = array(
2237 'icon' => 'tags',
2238 'label' => esc_attr__( 'Assign Tags', 'supportcandy' ),
2239 'callback' => 'wpsc_bulk_assign_tags',
2240 );
2241 }
2242
2243 if ( $current_user->is_agent && self::has_ticket_cap( 'dtt' ) ) {
2244 $bulk_actions['delete'] = array(
2245 'icon' => 'trash-alt',
2246 'label' => esc_attr__( 'Delete', 'supportcandy' ),
2247 'callback' => 'wpsc_bulk_delete_tickets',
2248 );
2249 }
2250 $bulk_actions = apply_filters( 'wpsc_tl_bulk_actions', $bulk_actions );
2251 } else {
2252
2253 if ( $current_user->is_agent && self::has_ticket_cap( 'dtt' ) ) {
2254 $bulk_actions['restore'] = array(
2255 'icon' => 'trash-restore',
2256 'label' => esc_attr__( 'Restore', 'supportcandy' ),
2257 'callback' => 'wpsc_bulk_restore_tickets',
2258 );
2259 }
2260
2261 if ( $current_user->is_agent && self::has_ticket_cap( 'dtt' ) ) {
2262 $bulk_actions['permanently_delete'] = array(
2263 'icon' => 'trash-alt',
2264 'label' => esc_attr__( 'Delete Permanently', 'supportcandy' ),
2265 'callback' => 'wpsc_bulk_permanently_delete_tickets',
2266 );
2267 }
2268 }
2269
2270 if ( $current_user->is_agent && self::has_ticket_cap( 'at' ) ) {
2271 $bulk_actions['archive'] = array(
2272 'icon' => 'archive',
2273 'label' => esc_attr__( 'Archive', 'supportcandy' ),
2274 'callback' => 'wpsc_bulk_archive_tickets',
2275 );
2276 }
2277
2278 $bulk_actions = apply_filters( 'wpsc_tl_bulk_actions', $bulk_actions );
2279
2280 self::$bulk_actions = $bulk_actions;
2281 }
2282
2283 /**
2284 * Get Bulk actions
2285 *
2286 * @return string
2287 */
2288 public static function get_bulk_actions() {
2289
2290 $current_user = WPSC_Current_User::$current_user;
2291 $actions_arr = array();
2292 foreach ( self::$bulk_actions as $action ) :
2293 ob_start();
2294 ?>
2295 <div class="wpsc-popover-menu-item" onclick="<?php echo esc_attr( $action['callback'] ) . '(\'' . esc_attr( wp_create_nonce( $action['callback'] ) ) . '\');'; ?>">
2296 <?php WPSC_Icons::get( $action['icon'] ); ?>
2297 <span><?php echo esc_attr( $action['label'] ); ?></span>
2298 </div>
2299 <?php
2300 $actions_arr[] = ob_get_clean();
2301 endforeach;
2302
2303 return implode( '', $actions_arr );
2304 }
2305
2306 /**
2307 * Agent ticket access for cap
2308 *
2309 * @param string $cap - capability type.
2310 * @return boolean
2311 */
2312 public static function has_ticket_cap( $cap ) {
2313
2314 $current_user = WPSC_Current_User::$current_user;
2315 $flag = false;
2316 if (
2317 $current_user->agent->has_cap( $cap . '-unassigned' ) ||
2318 $current_user->agent->has_cap( $cap . '-assigned-me' ) ||
2319 $current_user->agent->has_cap( $cap . '-assigned-others' )
2320 ) {
2321 $flag = true;
2322 }
2323
2324 return apply_filters( 'wpsc_bulk_has_ticket_cap', $flag );
2325 }
2326
2327 /**
2328 * Agent autocomplete bulk assign agents
2329 *
2330 * @return void
2331 */
2332 public static function agent_autocomplete_bulk_assign() {
2333
2334 if ( check_ajax_referer( 'wpsc_agent_autocomplete_bulk_assign', '_ajax_nonce', false ) !== 1 ) {
2335 wp_send_json_error( 'Unauthorized request!', 401 );
2336 }
2337
2338 $current_user = WPSC_Current_User::$current_user;
2339 if ( ! ( $current_user->is_agent && self::has_ticket_cap( 'aa' ) ) ) {
2340 wp_send_json_error( 'Unauthorized request!', 401 );
2341 }
2342
2343 $filters = array();
2344
2345 $filters['term'] = isset( $_GET['q'] ) ? sanitize_text_field( wp_unslash( $_GET['q'] ) ) : '';
2346 $filters['filter_by'] = isset( $_GET['filter_by'] ) ? sanitize_text_field( wp_unslash( $_GET['filter_by'] ) ) : 'all';
2347 $filters['sort_by'] = isset( $_GET['sort_by'] ) ? sanitize_text_field( wp_unslash( $_GET['sort_by'] ) ) : 'name';
2348 $filters['isMultiple'] = isset( $_GET['isMultiple'] ) ? intval( wp_unslash( $_GET['isMultiple'] ) ) : 0;
2349
2350 $filters['isAgentgroup'] = 0;
2351 if ( class_exists( 'WPSC_Agentgroups' ) ) {
2352 $filters['isAgentgroup'] = isset( $_GET['isAgentgroup'] ) ? intval( $_GET['isAgentgroup'] ) : null;
2353 }
2354
2355 $response = WPSC_Agent::agent_autocomplete( $filters );
2356 wp_send_json( $response );
2357 }
2358
2359 /**
2360 * Check whether current filter is deleted type or not
2361 *
2362 * @return boolean
2363 */
2364 public static function is_current_filter_deleted() {
2365
2366 $filters = self::$filters;
2367
2368 $slug = self::$default_flag ? self::$filter_id : '';
2369 if ( ! $slug && self::$saved_flag ) {
2370 $slug = self::$filter_id;
2371 }
2372 if ( ! $slug ) {
2373 $slug = $filters['filterSlug'];
2374 }
2375
2376 $parent_slug = is_numeric( $slug ) && self::$default_flag ? self::$default_filters[ $slug ]['parent-filter'] : '';
2377
2378 if ( ! $parent_slug && is_numeric( $slug ) && self::$saved_flag ) {
2379
2380 $parent_slug = self::$saved_filters[ $slug ]['parent-filter'];
2381
2382 } elseif ( ! $parent_slug && $slug == 'custom' ) {
2383
2384 $parent_slug = $filters['parent-filter'];
2385
2386 } else {
2387
2388 $parent_slug = $slug;
2389 }
2390
2391 return self::has_delete_parent_filter( $parent_slug );
2392 }
2393
2394 /**
2395 * Get updated nonce.
2396 *
2397 * @return void
2398 */
2399 public static function get_nonce() {
2400
2401 $response = array(
2402 'general' => wp_create_nonce( 'general' ),
2403 );
2404 wp_send_json( $response );
2405 }
2406
2407 /**
2408 * Allow only allowed conditions for current user for custom ticket filter
2409 *
2410 * @param array $conditions - conditions to filter.
2411 * @return array
2412 */
2413 public static function custom_filter_conditions( $conditions ) {
2414
2415 $current_user = WPSC_Current_User::$current_user;
2416 $level = $current_user->level == 'admin' ? 'agent' : $current_user->level;
2417
2418 foreach ( $conditions as $slug => $item ) {
2419
2420 if ( $item['type'] == 'cf' ) {
2421
2422 $cf = WPSC_Custom_Field::get_cf_by_slug( $slug );
2423 if (
2424 ! $cf->type::$is_filter ||
2425 ! in_array( $cf->field, array( 'ticket', 'customer', 'agentonly' ) ) ||
2426 ! in_array( $level, $item['levels'] )
2427 ) {
2428 unset( $conditions[ $slug ] );
2429 }
2430 } else { // not custom field type.
2431
2432 unset( $conditions[ $slug ] );
2433 }
2434 }
2435
2436 return $conditions;
2437 }
2438
2439 /**
2440 * Filter tickets by tag
2441 *
2442 * @return void
2443 */
2444 public static function apply_tag_custom_filter() {
2445
2446 if ( isset( $_REQUEST['wpsc_tag'] ) && ( isset($_REQUEST['section']) && $_REQUEST['section'] == 'ticket-list' ) ) { // phpcs:ignore
2447
2448 $tag = intval( $_REQUEST['wpsc_tag'] ); // phpcs:ignore
2449 if ( ! $tag ) {
2450 return;
2451 }
2452
2453 if ( ! WPSC_Functions::is_site_admin() ) {
2454 return;
2455 }
2456
2457 $custom_filters = array();
2458
2459 $obj = new stdClass();
2460 $obj->slug = 'tags';
2461 $obj->operator = '=';
2462 $obj->operand_val_1 = $_REQUEST['wpsc_tag']; // phpcs:ignore
2463
2464 $custom_filters[] = array( $obj );
2465
2466 $filters = array(
2467 'filterSlug' => 'custom',
2468 'parent-filter' => 'all',
2469 'filters' => wp_json_encode( $custom_filters ),
2470 'orderby' => 'date_updated',
2471 'order' => 'DESC',
2472 'page_no' => 1,
2473 'search' => '',
2474 );
2475
2476 setcookie( 'wpsc-tl-filters', wp_json_encode( $filters ), time() + 3600 );
2477 }
2478 }
2479
2480 /**
2481 * Receive Heartbeat data and respond.
2482 *
2483 * Processes data received via a Heartbeat request, and returns additional data to pass back to the front end.
2484 *
2485 * @param array $response Heartbeat response data to pass back to front end.
2486 * @param array $data Data received from the front end (unslashed).
2487 *
2488 * @return array
2489 */
2490 public static function get_nonce_heartbeat( array $response, array $data ) {
2491
2492 if ( empty( $data['wpsc_heartbeat'] ) ) {
2493 return $response;
2494 }
2495
2496 $response['general'] = wp_create_nonce( 'general' );
2497 return $response;
2498 }
2499
2500 /**
2501 * Delete ticket ajax request
2502 */
2503 public static function bulk_delete_tickets() {
2504
2505 if ( check_ajax_referer( 'wpsc_bulk_delete_tickets', '_ajax_nonce', false ) != 1 ) {
2506 wp_send_json_error( 'Unauthorised request!', 401 );
2507 }
2508
2509 $current_user = WPSC_Current_User::$current_user;
2510 if ( ! $current_user->is_agent ) {
2511 wp_send_json_error( 'Unauthorised request!', 401 );
2512 }
2513
2514 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2515 if ( ! $ticket_ids ) {
2516 wp_send_json_error( 'Something went wrong!', 400 );
2517 }
2518
2519 foreach ( $ticket_ids as $ticket_id ) {
2520
2521 $ticket = new WPSC_Ticket( $ticket_id );
2522 WPSC_Individual_Ticket::$ticket = $ticket;
2523 if ( ! $ticket->id || ! $ticket->is_active || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2524 continue;
2525 }
2526
2527 WPSC_Individual_Ticket::delete_ticket();
2528 }
2529 wp_die();
2530 }
2531
2532 /**
2533 * Restore bulk tickets
2534 *
2535 * @return void
2536 */
2537 public static function bulk_restore_tickets() {
2538
2539 if ( check_ajax_referer( 'wpsc_bulk_restore_tickets', '_ajax_nonce', false ) != 1 ) {
2540 wp_send_json_error( 'Unauthorised request!', 401 );
2541 }
2542
2543 $current_user = WPSC_Current_User::$current_user;
2544 if ( ! $current_user->is_agent ) {
2545 wp_send_json_error( 'Unauthorised request!', 401 );
2546 }
2547
2548 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2549 if ( ! $ticket_ids ) {
2550 wp_send_json_error( 'Something went wrong!', 400 );
2551 }
2552
2553 foreach ( $ticket_ids as $ticket_id ) {
2554
2555 $ticket = new WPSC_Ticket( $ticket_id );
2556 WPSC_Individual_Ticket::$ticket = $ticket;
2557 if ( ! $ticket->id || $ticket->is_active || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2558 continue;
2559 }
2560
2561 WPSC_Individual_Ticket::restore_ticket();
2562 }
2563 wp_die();
2564 }
2565
2566 /**
2567 * Delete bulk tickets permanently
2568 *
2569 * @return void
2570 */
2571 public static function bulk_delete_tickets_permanently() {
2572
2573 if ( check_ajax_referer( 'wpsc_bulk_delete_tickets_permanently', '_ajax_nonce', false ) != 1 ) {
2574 wp_send_json_error( 'Unauthorised request!', 401 );
2575 }
2576
2577 $current_user = WPSC_Current_User::$current_user;
2578 if ( ! $current_user->is_agent ) {
2579 wp_send_json_error( 'Unauthorised request!', 401 );
2580 }
2581
2582 $ticket_ids = isset( $_POST['ticket_ids'] ) ? array_filter( array_map( 'intval', $_POST['ticket_ids'] ) ) : array();
2583 if ( ! $ticket_ids ) {
2584 wp_send_json_error( 'Something went wrong!', 400 );
2585 }
2586
2587 foreach ( $ticket_ids as $ticket_id ) {
2588
2589 $ticket = new WPSC_Ticket( $ticket_id );
2590 WPSC_Individual_Ticket::$ticket = $ticket;
2591 if ( ! $ticket->id || $ticket->is_active || ! WPSC_Individual_Ticket::has_ticket_cap( 'dtt' ) ) {
2592 continue;
2593 }
2594
2595 WPSC_Individual_Ticket::delete_permanently();
2596 }
2597 wp_die();
2598 }
2599 }
2600 endif;
2601
2602 WPSC_Ticket_List::init();
2603