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 / frontend / class-wpsc-shortcode-three.php

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

471 lines 13.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly!
4 }
5
6 if ( ! class_exists( 'WPSC_Shortcode_Three' ) ) :
7
8 final class WPSC_Shortcode_Three {
9
10 /**
11 * Set whether ticket url is authenticated or not.
12 *
13 * @var boolean
14 */
15 public static $url_auth = false;
16
17 /**
18 * Initialize this class
19 */
20 public static function init() {
21
22 // register shortcode.
23 add_shortcode( 'wpsc_open_ticket', array( __CLASS__, 'layout' ) );
24
25 // Authenticate.
26 add_action( 'wp_ajax_wpsc_authenticate_open_ticket', array( __CLASS__, 'get_authenticate_open_ticket' ) );
27 add_action( 'wp_ajax_nopriv_wpsc_authenticate_open_ticket', array( __CLASS__, 'get_authenticate_open_ticket' ) );
28 add_action( 'wp_ajax_nopriv_wpsc_confirm_open_ticket_auth', array( __CLASS__, 'confirm_open_ticket_auth' ) );
29 }
30
31 /**
32 * Layout for this shortcode
33 *
34 * @param array $attrs - Shortcode attributes.
35 * @return string
36 */
37 public static function layout( $attrs ) {
38
39 $current_user = WPSC_Current_User::$current_user;
40 $ticket_id = isset( $_REQUEST['ticket-id'] ) ? intval( $_REQUEST['ticket-id'] ) : 0; // phpcs:ignore
41 if ( ! $ticket_id ) {
42 $ticket_id = isset( $_REQUEST['ticket_id'] ) ? intval( $_REQUEST['ticket_id'] ) : 0; // phpcs:ignore
43 }
44
45 // ticket URL authentication.
46 $advanced = get_option( 'wpsc-ms-advanced-settings' );
47 if ( ! $advanced['ticket-url-auth'] ) {
48
49 $auth_code = isset( $_REQUEST['auth-code'] ) ? sanitize_text_field( $_REQUEST['auth-code'] ) : ''; // phpcs:ignore
50 if ( ! $auth_code ) {
51 $auth_code = isset( $_REQUEST['auth_code'] ) ? sanitize_text_field( $_REQUEST['auth_code'] ) : ''; // phpcs:ignore
52 }
53
54 if ( $ticket_id && $auth_code ) {
55 $ticket = new WPSC_Ticket( $ticket_id );
56 self::$url_auth = $ticket->auth_code == $auth_code ? true : false;
57 }
58 }
59
60 ob_start();?>
61 <div id="wpsc-container" style="display:none;">
62 <div class="wpsc-shortcode-container" style="border: none !important;">
63 <?php
64
65 // logged in.
66 if ( $current_user->is_customer ) {
67
68 if ( $ticket_id ) {
69
70 // js events.
71 add_action( 'wpsc_js_ready', array( __CLASS__, 'register_js_ready_function' ) );
72 add_action( 'wpsc_js_after_ticket_reply', array( __CLASS__, 'js_after_ticket_reply' ) );
73 add_action( 'wpsc_js_after_close_ticket', array( __CLASS__, 'js_after_close_ticket' ) );
74 ?>
75 <div class="wpsc-body"></div>
76 <?php
77
78 } else {
79
80 self::load_otp_form();
81 }
82 } elseif ( $ticket_id && ! self::$url_auth ) {
83 // not logged in.
84
85 WPSC_Frontend::load_authentication_screen( false, false );
86 ?>
87 <div class="wpsc-form-devider">
88 <span>----</span>
89 <span class="label"><?php esc_attr_e( 'OR', 'supportcandy' ); ?></span>
90 <span>----</span>
91 </div>
92 <?php
93 self::load_otp_form( $ticket_id );
94
95 } elseif ( $ticket_id && self::$url_auth ) {
96
97 ?>
98 <div class="wpsc-body"></div>
99 <script>
100 jQuery(document).ready(function(){
101 wpsc_get_individual_ticket(<?php echo intval( $ticket_id ); ?>);
102 });
103 </script>
104 <?php
105
106 } else {
107
108 self::load_otp_form();
109 }
110 ?>
111
112 </div>
113 <style>
114 .wpsc-it-container {
115 margin: 0 !important;
116 }
117 .wpsc-it-reply-section-container {
118 padding-left: 3px;
119 }
120 </style>
121 </div>
122 <?php
123 WPSC_Frontend::load_html_snippets();
124 self::load_js_functions( $ticket_id );
125 return ob_get_clean();
126 }
127
128 /**
129 * Load OTP form
130 *
131 * @param integer $ticket_id - ticket id.
132 * @return void
133 */
134 public static function load_otp_form( $ticket_id = 0 ) {
135
136 $current_user = WPSC_Current_User::$current_user;
137 $ticket_id = $ticket_id ? $ticket_id : '';
138 ?>
139 <div class="wpsc-auth-container">
140 <div class="auth-inner-container">
141 <h2><?php esc_attr_e( 'Open existing ticket', 'supportcandy' ); ?></h2>
142 <form onsubmit="return false;" class="wpsc-login wpsc-authenticate-open-ticket">
143
144 <input type="text" name="ticket_id" placeholder="<?php esc_attr_e( 'Ticket ID', 'supportcandy' ); ?>" value="<?php echo esc_attr( $ticket_id ); ?>" autocomplete="off"/>
145 <?php
146
147 if ( ! $current_user->is_customer ) {
148 ?>
149 <input type="text" name="email_address" placeholder="<?php esc_attr_e( 'Email Address', 'supportcandy' ); ?>" autocomplete="off"/>
150 <?php
151 } else {
152 ?>
153 <input type="hidden" name="email_address" value="<?php echo esc_attr( $current_user->customer->email ); ?>"/>
154 <?php
155 }
156 ?>
157
158 <button class="wpsc-button normal primary" onclick="wpsc_authenticate_open_ticket(this)"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
159 <button class="wpsc-button normal secondary" onclick="window.location.reload();"><?php esc_attr_e( 'Cancel', 'supportcandy' ); ?></button>
160 <input type="hidden" name="action" value="wpsc_authenticate_open_ticket"/>
161 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_authenticate_open_ticket' ) ); ?>">
162 </form>
163 <script>
164 /**
165 * Load OTP verification
166 */
167 function wpsc_authenticate_open_ticket(el) {
168
169 const form = jQuery(el).closest('form')[0];
170 const dataform = new FormData(form);
171
172 if (!dataform.get('ticket_id').trim() || !dataform.get('email_address').trim()) {
173 alert(supportcandy.translations.req_fields_missing);
174 return;
175 }
176
177 var authContainer = jQuery(el).closest('.wpsc-auth-container');
178 authContainer.html(supportcandy.loader_html);
179 jQuery.ajax({
180 url: supportcandy.ajax_url,
181 type: 'POST',
182 data: dataform,
183 processData: false,
184 contentType: false
185 }).done(function (res) {
186 if (typeof(res) == "object") {
187 if (res.ticket_url) {
188 window.location.href = res.ticket_url;
189 } else {
190 alert(supportcandy.translations.something_wrong);
191 window.location.reload();
192 }
193 } else {
194 authContainer.html(res);
195 }
196 }).fail(function (data) {
197 alert(supportcandy.translations.something_wrong);
198 window.location.reload();
199 });
200 }
201 </script>
202 <?php
203 if ( $current_user->is_customer ) :
204 ?>
205 <div style="display:flex;flex-direction:column;margin: 10px 0 0;font-size: 12px;">
206 <span>
207 <?php
208 /* translators: %1$s: customer name */
209 printf( esc_attr__( 'Logged-in as %1$s', 'supportcandy' ), '<strong>' . esc_attr( $current_user->customer->name ) . '</strong>' );
210 ?>
211 </span>
212 <span class="wpsc-link" onclick="wpsc_user_logout(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_user_logout' ) ); ?>');"><?php esc_attr_e( 'Log out', 'supportcandy' ); ?></span>
213 </div>
214 <?php
215 endif
216 ?>
217 </div>
218 </div>
219 <?php
220 }
221
222 /**
223 * Load js functions for this shortcode
224 *
225 * @param integer $ticket_id - ticket id.
226 * @return void
227 */
228 public static function load_js_functions( $ticket_id ) {
229 ?>
230
231 <script type="text/javascript">
232 /**
233 * Get create ticket form
234 */
235 function wpsc_get_individual_ticket() {
236
237 jQuery('.wpsc-body').html(supportcandy.loader_html);
238
239 if (supportcandy.is_reload != 1) {
240 wpsc_scroll_top();
241 } else { supportcandy.is_reload = 0 }
242
243 var url = new URL(window.location.href);
244 var search_params = url.searchParams;
245
246 var data = { action: 'wpsc_get_individual_ticket', ticket_id: <?php echo esc_attr( $ticket_id ); ?> };
247 search_params.forEach(function(value, key) {
248 data[key] = value;
249 });
250 jQuery.post(supportcandy.ajax_url, data).done(function (response) {
251 jQuery('.wpsc-body').html(response);
252 wpsc_reset_responsive_style();
253 }).fail(function(response){
254 jQuery('.wpsc-body').html('<div style="display:flex; justify-content:center; margin:0 15px 15px; width:100%;"><?php esc_attr_e( 'Unauthorized access!', 'supportcandy' ); ?></div>');
255 });
256 }
257 </script>
258 <?php
259 }
260
261 /**
262 * JS ready function
263 *
264 * @return void
265 */
266 public static function register_js_ready_function() {
267
268 echo 'wpsc_get_individual_ticket();' . PHP_EOL;
269 }
270
271 /**
272 * Get authentication OTP screen for open ticket
273 *
274 * @return void
275 */
276 public static function get_authenticate_open_ticket() {
277
278 if ( check_ajax_referer( 'wpsc_authenticate_open_ticket', '_ajax_nonce', false ) != 1 ) {
279 wp_send_json_error( 'Unauthorized request!', 401 );
280 }
281
282 $ticket_id = isset( $_POST['ticket_id'] ) ? intval( $_POST['ticket_id'] ) : 0;
283 $email_address = isset( $_POST['email_address'] ) ? sanitize_text_field( wp_unslash( $_POST['email_address'] ) ) : '';
284 if ( ! $ticket_id || ! $email_address || ! filter_var( $email_address, FILTER_VALIDATE_EMAIL ) ) {
285 wp_send_json_error( 'Bad request', 400 );
286 }
287
288 $ticket = new WPSC_Ticket( $ticket_id );
289 if ( ! $ticket->id ) {
290 wp_send_json_error( 'Unauthorized request!', 401 );
291 }
292
293 WPSC_Individual_Ticket::$ticket = $ticket;
294
295 $current_user = WPSC_Current_User::$current_user;
296 if ( WPSC_Individual_Ticket::is_customer() || ( $current_user->is_agent && WPSC_Individual_Ticket::has_ticket_cap( 'view' ) ) ) {
297
298 // ticket url.
299 $page_settings = get_option( 'wpsc-gs-page-settings' );
300 $url = $page_settings['open-ticket-page'] ? get_permalink( $page_settings['open-ticket-page'] ) : get_permalink( $page_settings['support-page'] );
301 if ( ! $url ) {
302 wp_send_json_error( 'Open ticket page not selected!', 400 );
303 }
304 $ticket_url = add_query_arg(
305 array(
306 'ticket-id' => $ticket_id,
307 ),
308 $url
309 );
310
311 header( 'Content-Type: application/json' );
312 echo wp_json_encode(
313 array(
314 'ticket_url' => $ticket_url,
315 )
316 );
317 wp_die();
318 }
319
320 $otp = WPSC_Email_OTP::insert(
321 array(
322 'email' => $email_address,
323 'date_expiry' => ( new DateTime() )->add( new DateInterval( 'P1D' ) )->format( 'Y-m-d H:i:s' ),
324 'data' => wp_json_encode(
325 array(
326 'email' => $email_address,
327 'name' => $ticket->customer->name,
328 'ticket_id' => $ticket_id,
329 )
330 ),
331 )
332 );
333
334 // Send OTP for login.
335 WPSC_EN_Guest_Login_OTP::send_otp( $otp );
336 ?>
337
338 <div class="auth-inner-container">
339 <h2><?php esc_attr_e( 'Open existing ticket', 'supportcandy' ); ?></h2>
340 <small style="margin: 0 0 5px;"><?php esc_attr_e( 'We have sent a one-time verification code to your email address. Please insert it below and submit to open ticket!', 'supportcandy' ); ?></small>
341 <form onsubmit="return false;" class="wpsc-login wpsc-confirm-open-ticket-auth">
342 <input type="text" name="otp" autocomplete="off"/>
343 <button class="wpsc-button normal primary" onclick="wpsc_confirm_open_ticket_auth(this, '<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_open_ticket_auth' ) ); ?>')"><?php esc_attr_e( 'Submit', 'supportcandy' ); ?></button>
344 <input type="hidden" name="action" value="wpsc_confirm_open_ticket_auth"/>
345 <input type="hidden" name="otp_id" value="<?php echo esc_attr( $otp->id ); ?>">
346 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_confirm_open_ticket_auth' ) ); ?>">
347 </form>
348 <script>
349 /**
350 * Confirm OTP
351 *
352 * @return void
353 */
354 function wpsc_confirm_open_ticket_auth(el, nonce) {
355
356 const form = jQuery(el).closest('form')[0];
357 const dataform = new FormData(form);
358
359 if (!dataform.get('otp').trim()) {
360 alert(supportcandy.translations.req_fields_missing);
361 return;
362 }
363
364 jQuery(el).closest('.wpsc-auth-container').html(supportcandy.loader_html);
365 jQuery.ajax({
366 url: supportcandy.ajax_url,
367 type: 'POST',
368 data: dataform,
369 processData: false,
370 contentType: false
371 }).done(function (res) {
372 if (res.isSuccess == 1) {
373 window.location.href = res.ticket_url;
374 } else {
375 alert(supportcandy.translations.something_wrong);
376 window.location.reload();
377 }
378 });
379 }
380 </script>
381 </div>
382 <?php
383 wp_die();
384 }
385
386 /**
387 * Confirm guest login
388 *
389 * @return void
390 */
391 public static function confirm_open_ticket_auth() {
392
393 if ( check_ajax_referer( 'wpsc_confirm_open_ticket_auth', '_ajax_nonce', false ) != 1 ) {
394 wp_send_json_error( 'Unauthorized request!', 401 );
395 }
396
397 $page_settings = get_option( 'wpsc-gs-page-settings' );
398
399 $verification_otp = isset( $_POST['otp'] ) ? sanitize_text_field( wp_unslash( $_POST['otp'] ) ) : '';
400 if ( ! $verification_otp ) {
401 wp_send_json_error( 'Bad request', 400 );
402 }
403
404 $id = isset( $_POST['otp_id'] ) ? intval( $_POST['otp_id'] ) : '';
405 if ( ! $id ) {
406 wp_send_json_error( 'Bad request', 400 );
407 }
408
409 $otp = new WPSC_Email_OTP( $id );
410 if ( ! $otp->id ) {
411 wp_send_json_error( 'Bad request', 400 );
412 }
413
414 if ( ! $otp->is_valid( $verification_otp ) ) {
415 echo wp_json_encode( array( 'isSuccess' => 0 ) );
416 wp_die();
417 }
418
419 $data = json_decode( $otp->data, true );
420 $data['auth_token'] = WPSC_Functions::get_random_string( 100 );
421 $data['auth_type'] = 'open-ticket';
422 $otp->data = wp_json_encode( $data );
423 $otp->save();
424
425 $auth = array(
426 'email' => $otp->email,
427 'token' => $data['auth_token'],
428 );
429
430 setcookie( 'wpsc_guest_login_auth', wp_json_encode( $auth ), $otp->date_expiry->getTimestamp(), '/' );
431
432 $url = get_permalink( $page_settings['open-ticket-page'] );
433 $ticket_url = add_query_arg(
434 array(
435 'ticket-id' => $data['ticket_id'],
436 ),
437 $url
438 );
439
440 wp_send_json(
441 array(
442 'isSuccess' => 1,
443 'ticket_url' => $ticket_url,
444 )
445 );
446 }
447
448 /**
449 * After ticket reply
450 *
451 * @return void
452 */
453 public static function js_after_ticket_reply() {
454
455 echo 'wpsc_get_individual_ticket(ticket_id)' . PHP_EOL;
456 }
457
458 /**
459 * JS after close ticket
460 *
461 * @return void
462 */
463 public static function js_after_close_ticket() {
464
465 echo 'wpsc_get_individual_ticket(ticket_id)' . PHP_EOL;
466 }
467 }
468 endif;
469
470 WPSC_Shortcode_Three::init();
471