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-tickets.php

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

478 lines 13.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly!
4 }
5
6 if ( ! class_exists( 'WPSC_Tickets' ) ) :
7
8 final class WPSC_Tickets {
9
10 /**
11 * Set if current screen is tickets page
12 *
13 * @var boolean
14 */
15 public static $is_current_page;
16
17 /**
18 * Sections for this view
19 *
20 * @var [type]
21 */
22 private static $sections = array();
23
24 /**
25 * Current section to load
26 *
27 * @var [type]
28 */
29 public static $current_section;
30
31 /**
32 * Initialize this class
33 */
34 public static function init() {
35
36 // Load sections for this screen.
37 add_action( 'admin_init', array( __CLASS__, 'load_sections' ) );
38
39 // Add current section to admin localization data.
40 add_filter( 'wpsc_admin_localizations', array( __CLASS__, 'localizations' ) );
41
42 // Humbargar modal.
43 add_action( 'admin_footer', array( __CLASS__, 'humbargar_menu' ) );
44
45 // JS dynamic fucntions.
46 add_action( 'wpsc_js_ready', array( __CLASS__, 'register_js_ready_function' ) );
47 add_action( 'wpsc_js_after_ticket_reply', array( __CLASS__, 'js_after_ticket_reply' ) );
48 add_action( 'wpsc_js_after_close_ticket', array( __CLASS__, 'js_after_close_ticket' ) );
49
50 // agent dashboard.
51 add_action( 'wp_ajax_wpsc_get_agent_dashboard', array( __CLASS__, 'get_agent_dashboard' ) );
52
53 // show sales banner.
54 add_action( 'wpsc_before_tickets_page', array( __CLASS__, 'show_sales_banner' ) );
55 add_action( 'wp_ajax_wpsc_dismiss_sale_banner', array( __CLASS__, 'dismiss_sale_banner' ) );
56 }
57
58 /**
59 * Load section (nav elements) for this screen
60 *
61 * @return void
62 */
63 public static function load_sections() {
64
65 self::$is_current_page = isset( $_REQUEST['page'] ) && $_REQUEST['page'] === 'wpsc-tickets' ? true : false; // phpcs:ignore
66
67 $current_user = WPSC_Current_User::$current_user;
68 if ( ! ( $current_user->is_agent && self::$is_current_page ) ) {
69 return;
70 }
71
72 // get default tab.
73 $tab = $current_user->agent->get_default_tab();
74
75 $gs = get_option( 'wpsc-gs-general' );
76 $ms = get_option( 'wpsc-ms-advanced-settings' );
77
78 // allow create ticket.
79 $allow_create_ticket = in_array( $current_user->agent->role, $gs['allow-create-ticket'] ) ? true : false;
80
81 $sections = array();
82 // Supportcandy dashboard.
83 if ( $current_user->is_agent && $current_user->agent->has_cap( 'dash-access' ) ) {
84 $sections['dashboard'] = array(
85 'slug' => 'dashboard',
86 'icon' => 'dashboard',
87 'label' => esc_attr__( 'Dashboard', 'supportcandy' ),
88 'callback' => 'wpsc_get_agent_dashboard',
89 );
90 }
91
92 // ticket list.
93 $sections['ticket-list'] = array(
94 'slug' => 'ticket_list',
95 'icon' => 'list-alt',
96 'label' => esc_attr__( 'Ticket List', 'supportcandy' ),
97 'callback' => 'wpsc_get_ticket_list',
98 );
99
100 // new ticket.
101 if ( $allow_create_ticket ) {
102 $sections['new-ticket'] = array(
103 'slug' => 'new_ticket',
104 'icon' => 'plus-square',
105 'label' => esc_attr__( 'New Ticket', 'supportcandy' ),
106 'callback' => 'wpsc_get_ticket_form',
107 );
108 }
109
110 // my profile.
111 if ( $ms['allow-my-profile'] ) {
112 $sections['my-profile'] = array(
113 'slug' => 'my_profile',
114 'icon' => 'id-card',
115 'label' => esc_attr__( 'My Profile', 'supportcandy' ),
116 'callback' => 'wpsc_get_user_profile',
117 );
118 }
119
120 // agent profile.
121 if ( $current_user->is_agent && $ms['allow-agent-profile'] ) {
122 $sections['agent-profile'] = array(
123 'slug' => 'agent_profile',
124 'icon' => 'headset',
125 'label' => esc_attr__( 'Agent Profile', 'supportcandy' ),
126 'callback' => 'wpsc_get_agent_profile',
127 );
128 }
129
130 self::$sections = apply_filters( 'wpsc_tickets_page_sections', $sections );
131 self::$current_section = isset( $_REQUEST['section'] ) ? sanitize_text_field( $_REQUEST['section'] ) : $tab; // phpcs:ignore
132 }
133
134 /**
135 * Add localizations to local JS
136 *
137 * @param array $localizations - localization list.
138 * @return array
139 */
140 public static function localizations( $localizations ) {
141
142 if ( ! self::$is_current_page ) {
143 return $localizations;
144 }
145
146 // Humbargar Titles.
147 $localizations['humbargar_titles'] = self::get_humbargar_titles();
148
149 // Current section.
150 $localizations['current_section'] = self::$current_section;
151
152 // Current ticket id.
153 if ( self::$current_section === 'ticket-list' && isset( $_REQUEST['id'] ) ) { // phpcs:ignore
154 $localizations['current_ticket_id'] = intval( $_REQUEST['id'] ); // phpcs:ignore
155 }
156
157 return $localizations;
158 }
159
160 /**
161 * UI foundation for this screen
162 *
163 * @return void
164 */
165 public static function layout() {
166
167 ?>
168 <div class="wrap">
169 <hr class="wp-header-end">
170 <div id="wpsc-container" style="display:none;">
171 <?php do_action( 'wpsc_before_tickets_page' ); ?>
172 <div class="wpsc-shortcode-container">
173 <div class="wpsc-header wpsc-hidden-xs">
174 <?php
175 foreach ( self::$sections as $key => $section ) :
176 $active = self::$current_section === $key ? 'active' : '';
177 ?>
178 <div class="wpsc-menu-list wpsc-tickets-nav <?php echo esc_attr( $key ) . ' ' . esc_attr( $active ); ?>" onclick="<?php echo esc_attr( $section['callback'] ) . '();'; ?>">
179 <?php WPSC_Icons::get( $section['icon'] ); ?>
180 <label><?php echo esc_attr( $section['label'] ); ?></label>
181 </div>
182 <?php
183 endforeach;
184 ?>
185 <div class="wpsc-menu-list wpsc-tickets-nav log-out" onclick="wpsc_user_logout(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_user_logout' ) ); ?>');">
186 <?php WPSC_Icons::get( 'log-out' ); ?>
187 <label><?php echo esc_attr__( 'Logout', 'supportcandy' ); ?></label>
188 </div>
189 </div>
190 <div class="wpsc-header wpsc-visible-xs">
191 <div class="wpsc-humbargar-title">
192 <?php WPSC_Icons::get( self::$sections[ self::$current_section ]['icon'] ); ?>
193 <label><?php echo esc_attr( self::$sections[ self::$current_section ]['label'] ); ?></label>
194 </div>
195 <div class="wpsc-humbargar" onclick="wpsc_toggle_humbargar();">
196 <?php WPSC_Icons::get( 'bars' ); ?>
197 </div>
198 </div>
199 <div class="wpsc-body"></div>
200 <?php
201 self::load_html_snippets();
202 ?>
203 </div>
204 </div>
205 </div>
206 <?php
207 }
208
209 /**
210 * Print humbargar menu in footer
211 *
212 * @return void
213 */
214 public static function humbargar_menu() {
215
216 if ( ! self::$is_current_page ) {
217 return;
218 }
219
220 ?>
221 <div class="wpsc-humbargar-overlay" onclick="wpsc_toggle_humbargar();" style="display:none"></div>
222 <div class="wpsc-humbargar-menu" style="display:none">
223 <div class="box-inner">
224 <div class="wpsc-humbargar-close" onclick="wpsc_toggle_humbargar();">
225 <?php WPSC_Icons::get( 'times' ); ?>
226 </div>
227 <?php
228 foreach ( self::$sections as $key => $section ) :
229
230 $active = self::$current_section === $key ? 'active' : '';
231 ?>
232 <div
233 class="wpsc-humbargar-menu-item <?php echo esc_attr( $key ) . ' ' . esc_attr( $active ); ?>"
234 onclick="<?php echo esc_attr( $section['callback'] ) . '(true);'; ?>">
235 <?php WPSC_Icons::get( $section['icon'] ); ?>
236 <label><?php echo esc_attr( $section['label'] ); ?></label>
237 </div>
238 <?php endforeach; ?>
239 <div class="wpsc-humbargar-menu-item log-out" onclick="wpsc_user_logout(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_user_logout' ) ); ?>');">
240 <?php WPSC_Icons::get( 'log-out' ); ?>
241 <label><?php echo esc_attr__( 'Logout', 'supportcandy' ); ?></label>
242 </div>
243 </div>
244 </div>
245 <?php
246 }
247
248 /**
249 * Humbargar mobile titles to be used in localizations
250 *
251 * @return array
252 */
253 private static function get_humbargar_titles() {
254
255 $titles = array();
256 foreach ( self::$sections as $section ) {
257
258 ob_start();
259 WPSC_Icons::get( $section['icon'] );
260 echo '<label>' . esc_attr( $section['label'] ) . '</label>';
261 $titles[ $section['slug'] ] = ob_get_clean();
262 }
263 return $titles;
264 }
265
266 /**
267 * Register JS functions to call on document ready
268 *
269 * @return void
270 */
271 public static function register_js_ready_function() {
272
273 if ( ! self::$is_current_page ) {
274 return;
275 }
276
277 echo esc_attr( self::$sections[ self::$current_section ]['callback'] ) . '();' . PHP_EOL;
278 }
279
280 /**
281 * After ticket reply
282 *
283 * @return void
284 */
285 public static function js_after_ticket_reply() {
286
287 if ( ! self::$is_current_page ) {
288 return;
289 }
290
291 $current_user = WPSC_Current_User::$current_user;
292 $agent_settings = get_option( 'wpsc-tl-ms-agent-view' );
293 $call_to_function = $agent_settings['ticket-reply-redirect'] == 'ticket-list' ? 'wpsc_get_ticket_list();' : 'wpsc_get_individual_ticket(ticket_id)';
294 echo esc_attr( $call_to_function ) . PHP_EOL;
295 }
296
297 /**
298 * JS after close ticket
299 *
300 * @return void
301 */
302 public static function js_after_close_ticket() {
303
304 if ( ! self::$is_current_page ) {
305 return;
306 }
307 echo 'wpsc_get_ticket_list();' . PHP_EOL;
308 }
309
310 /**
311 * Load HTML snippets that can be used by js to load dynamically
312 *
313 * @return void
314 */
315 public static function load_html_snippets() {
316 ?>
317
318 <div class="wpsc-page-snippets" style="display: none;">
319 <div class="wpsc-editor-attachment upload-waiting">
320 <div class="attachment-label"></div>
321 <div class="attachment-remove" onclick="wpsc_remove_attachment(this)">
322 <?php WPSC_Icons::get( 'times' ); ?>
323 </div>
324 <div class="attachment-waiting"></div>
325 </div>
326 </div>
327 <?php
328 }
329
330 /**
331 * Get current agent dashboard layout
332 *
333 * @return void
334 */
335 public static function get_agent_dashboard() {
336
337 $settings = get_option( 'wpsc-ap-dashboard' );
338 $db_gs = get_option( 'wpsc-db-gs-settings', array() );
339 ?>
340 <div class="wpsc-dashboard-view">
341 <div class="wpsc-dash-widgets-row">
342 <?php
343 $cards = get_option( 'wpsc-dashboard-cards', array() );
344 foreach ( $cards as $slug => $card ) {
345 if ( ! $card['is_enable'] ) {
346 continue;
347 }
348 if ( ! class_exists( $card['class'] ) ) {
349 continue;
350 }
351 $card['class']::print_dashboard_card( $slug, $card );
352 }
353 ?>
354 </div>
355 <div class="wpsc-dash-widgets-row wpsc-dashboard-widget-view">
356 <?php
357 $widgets = get_option( 'wpsc-dashboard-widgets', array() );
358 foreach ( $widgets as $slug => $widget ) {
359 if ( ! $widget['is_enable'] ) {
360 continue;
361 }
362 if ( ! class_exists( $widget['class'] ) ) {
363 continue;
364 }
365 $widget['class']::print_dashboard_widget( $slug, $widget );
366 }
367 ?>
368 </div>
369 </div>
370 <?php
371 if ( $db_gs['dash-auto-refresh'] ) {
372 ?>
373 <script>
374 jQuery(document).ready(function() {
375 refresh_dashboard();
376 });
377 var wpsc_db_refresh_timeout;
378 function refresh_dashboard() {
379
380 if( supportcandy.current_section !== "dashboard" ) {
381 supportcandy.db_auto_refresh_schedule = false;
382 return;
383 }
384
385 // Clear the previous timeout, if any.
386 clearTimeout( wpsc_db_refresh_timeout );
387
388 wpsc_db_refresh_timeout = setTimeout(function () {
389 supportcandy.db_auto_refresh_schedule = true;
390 refresh_dashboard();
391 }, 300000);
392
393 if (
394 typeof supportcandy.db_auto_refresh_schedule === "undefined" ||
395 supportcandy.db_auto_refresh_schedule === false
396 ) {
397 return;
398 }
399 supportcandy.db_auto_refresh_schedule = false;
400 wpsc_get_agent_dashboard();
401 }
402 </script>
403 <?php
404 }
405 ?>
406 <style>
407 .wpsc-dash-widget-small svg{
408 color: <?php echo esc_attr( $settings['card-body-svg-color'] ); ?>;
409 }
410 .wpsc-dash-widget-small{
411 background-color:<?php echo esc_attr( $settings['card-body-bg-color'] ); ?> !important;
412 }
413 .wpsc-dash-widget-small, .wpsc-dash-widget-small h2{
414 color:<?php echo esc_attr( $settings['card-body-text-color'] ); ?> !important;
415 }
416 .wpsc-dash-widget-mid, .wpsc-dash-widget-large{
417 background-color:<?php echo esc_attr( $settings['widget-body-bg-color'] ); ?> !important;
418 color:<?php echo esc_attr( $settings['widget-body-text-color'] ); ?> !important;
419 }
420 .wpsc-dash-widget-header svg {
421 color:<?php echo esc_attr( $settings['widget-body-svg-color'] ); ?>;
422 }
423 </style>
424 <?php
425 wp_die();
426 }
427
428 /**
429 * Show sales banner
430 *
431 * @return void
432 */
433 public static function show_sales_banner() {
434 if ( current_user_can( 'manage_options' ) &&
435 ! ( class_exists( 'WPSC_EP' ) || class_exists( 'WPSC_Workflows' ) || class_exists( 'WPSC_SLA' ) || class_exists( 'WPSC_SF' ) || class_exists( 'WPSC_WOO' ) ) &&
436 current_time( 'Y-m-d' ) < '2025-12-31' &&
437 ! get_transient( 'wpsc_sale_banner_timeout' ) ) {
438 ?>
439 <div class="wpsc-sale-banner" style="display: flex; justify-content: space-between; flex-wrap: wrap;background-color: #000;color: #fff;padding: 10px 15px; margin-bottom: 10px; border-radius: 5px;">
440 <p style="margin:0; font-size: 12px; font-weight: 500;">
441 Get 50% off on all SupportCandy plans, starting from $39.50 (USD).
442 </p>
443 <div style="display: flex; align-items: center; gap: 15px;">
444 <a href="https://supportcandy.net/pricing?utm_source=plugin&utm_medium=banner&utm_campaign=plugin_flash_sale" target="_blank" style="color: #fff; text-decoration: underline;">View Plans</a>
445 <a href="#" id="wpsc-sale-banner-dismiss" style="color: #fff; text-decoration: underline;">Dismiss</a>
446 </div>
447 </div>
448 <?php
449 }
450 ?>
451 <script>
452 jQuery(document).ready(function() {
453 jQuery('#wpsc-sale-banner-dismiss').on('click', function(e){
454 e.preventDefault();
455 jQuery.post(ajaxurl, { action: 'wpsc_dismiss_sale_banner' }, function(){
456 window.location.reload();
457 });
458 });
459 });
460 </script>
461 <?php
462 }
463
464 /**
465 * Dismiss the sales banner
466 *
467 * @return void
468 */
469 public static function dismiss_sale_banner() {
470 set_transient( 'wpsc_sale_banner_timeout', 1, DAY_IN_SECONDS );
471 wp_die();
472 }
473 }
474 endif;
475
476 WPSC_Tickets::init();
477
478