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

class-wpsc-ticket-priorities.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent 3.3.9, at includes/admin/settings/class-wpsc-ticket-priorities.php

618 lines 19.2 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_Priorities' ) ) :
7
8 final class WPSC_Ticket_Priorities {
9
10 /**
11 * Initialize this class
12 */
13 public static function init() {
14
15 // List.
16 add_action( 'wp_ajax_wpsc_get_ticket_priorities', array( __CLASS__, 'get_priorities' ) );
17
18 // Add new.
19 add_action( 'wp_ajax_wpsc_get_add_new_priority', array( __CLASS__, 'get_add_new_priority' ) );
20 add_action( 'wp_ajax_wpsc_set_add_priority', array( __CLASS__, 'set_add_priority' ) );
21
22 // Edit.
23 add_action( 'wp_ajax_wpsc_get_edit_priority', array( __CLASS__, 'get_edit_priority' ) );
24 add_action( 'wp_ajax_wpsc_set_edit_priority', array( __CLASS__, 'set_edit_priority' ) );
25
26 // Delete.
27 add_action( 'wp_ajax_wpsc_get_delete_priority', array( __CLASS__, 'get_delete_priority' ) );
28 add_action( 'wp_ajax_wpsc_set_delete_priority', array( __CLASS__, 'set_delete_priority' ) );
29 }
30
31 /**
32 * Get priority settings
33 *
34 * @return void
35 */
36 public static function get_priorities() {
37
38 if ( ! WPSC_Functions::is_site_admin() ) {
39 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
40 }
41
42 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
43 $cf = WPSC_Custom_Field::get_cf_by_slug( 'priority' );?>
44
45 <div class="wpsc-setting-header">
46 <h2><?php esc_attr_e( 'Ticket Priorities', 'supportcandy' ); ?></h2>
47 </div>
48 <div class="wpsc-setting-section-body">
49 <div class="wpsc-dock-container">
50 <?php
51 printf(
52 /* translators: Click here to see the documentation */
53 esc_attr__( '%s to see the documentation!', 'supportcandy' ),
54 '<a href="https://supportcandy.net/docs/ticket-priorities/" target="_blank">' . esc_attr__( 'Click here', 'supportcandy' ) . '</a>'
55 );
56 ?>
57 </div>
58 <table class="wpsc-ticket-priorities wpsc-setting-tbl">
59 <thead>
60 <tr>
61 <th><?php esc_attr_e( 'Name', 'supportcandy' ); ?></th>
62 <th><?php esc_attr_e( 'Actions', 'supportcandy' ); ?></th>
63 </tr>
64 </thead>
65 <tbody>
66 <?php
67 foreach ( $priorities as $priority ) {
68 ?>
69 <tr>
70 <td><span class="wpsc-tag" style="color: <?php echo esc_attr( $priority->color ); ?>; background-color: <?php echo esc_attr( $priority->bg_color ); ?>;" ><?php echo esc_attr( $priority->name ); ?></span></td>
71 <td>
72 <div class="actions">
73 <a class="wpsc-link" href="javascript:wpsc_get_edit_priority(<?php echo esc_attr( $priority->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_priority' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></a>
74 <?php
75 if ( $cf->default_value[0] != $priority->id ) :
76 ?>
77 | <a class="wpsc-link" href="javascript:wpsc_get_delete_priority(<?php echo esc_attr( $priority->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_priority' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></a>
78 <?php
79 endif;
80 ?>
81 </div>
82 </td>
83 </tr>
84 <?php
85 }
86 ?>
87 </tbody>
88 </table>
89 </div>
90 <script>
91 jQuery('table.wpsc-ticket-priorities').DataTable({
92 ordering: false,
93 pageLength: 20,
94 bLengthChange: false,
95 columnDefs: [
96 { targets: -1, searchable: false },
97 { targets: '_all', className: 'dt-left' }
98 ],
99 layout: {
100 topStart: {
101 buttons: [
102 {
103 text: '<?php esc_attr_e( 'Add new', 'supportcandy' ); ?>',
104 className: 'wpsc-button small primary',
105 action: function ( e, dt, node, config ) {
106 wpsc_show_modal();
107 var data = { action: 'wpsc_get_add_new_priority' };
108 jQuery.post(
109 supportcandy.ajax_url,
110 data,
111 function (response) {
112
113 // Set to modal.
114 jQuery( '.wpsc-modal-header' ).text( response.title );
115 jQuery( '.wpsc-modal-body' ).html( response.body );
116 jQuery( '.wpsc-modal-footer' ).html( response.footer );
117 // Display modal.
118 wpsc_show_modal_inner_container();
119 }
120 );
121 }
122 }
123 ],
124 },
125 },
126 language: supportcandy.translations.datatables
127 });
128
129 </script>
130 <?php
131 wp_die();
132 }
133
134 /**
135 * Get add new priority
136 */
137 public static function get_add_new_priority() {
138
139 if ( ! WPSC_Functions::is_site_admin() ) {
140 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
141 }
142 $title = esc_attr__( 'Add new', 'supportcandy' );
143
144 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
145 ob_start();
146 ?>
147 <form action="#" onsubmit="return false;" class="wpsc-frm-add-priority">
148 <div class="wpsc-input-group">
149 <div class="label-container">
150 <label for=""><?php esc_attr_e( 'Name', 'supportcandy' ); ?></label>
151 <span class="required-char">*</span>
152 </div>
153 <input name="name" type="text" autocomplete="off">
154 </div>
155 <div class="wpsc-input-group">
156 <div class="label-container">
157 <label for=""><?php esc_attr_e( 'Color', 'supportcandy' ); ?></label>
158 </div>
159 <input class="wpsc-color-picker" name="color" value="#ffffff" />
160 </div>
161 <div class="wpsc-input-group">
162 <div class="label-container">
163 <label for=""><?php esc_attr_e( 'Background color', 'supportcandy' ); ?></label>
164 </div>
165 <input class="wpsc-color-picker" name="bg-color" value="#1E90FF" />
166 </div>
167 <div data-type="" data-required="true" class="wpsc-input-group load-after">
168 <div class="label-container">
169 <label for="">
170 <?php esc_attr_e( 'Load after', 'supportcandy' ); ?>
171 </label>
172 </div>
173 <select name="load-after" class="load-after">
174 <option value="__TOP__">-- <?php esc_attr_e( 'TOP', 'supportcandy' ); ?> --</option>
175 <?php
176 foreach ( $priorities as $priority ) {
177 ?>
178 <option value="<?php echo esc_attr( $priority->id ); ?>"><?php echo esc_attr( $priority->name ); ?></option>
179 <?php
180 }
181 ?>
182 <option selected value="__END__">-- <?php esc_attr_e( 'END', 'supportcandy' ); ?> --</option>
183 </select>
184 <script>jQuery('select.load-after').selectWoo();</script>
185 </div>
186 <script>jQuery('.wpsc-color-picker').wpColorPicker();</script>
187 <?php do_action( 'wpsc_get_add_priority_body' ); ?>
188 <input type="hidden" name="action" value="wpsc_set_add_priority">
189 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_add_priority' ) ); ?>">
190 </form>
191 <?php
192 $body = ob_get_clean();
193
194 ob_start();
195 ?>
196 <button class="wpsc-button small primary" onclick="wpsc_set_add_priority(this);">
197 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
198 </button>
199 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
200 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
201 </button>
202 <?php
203 do_action( 'wpsc_get_add_priority' );
204 $footer = ob_get_clean();
205
206 $response = array(
207 'title' => $title,
208 'body' => $body,
209 'footer' => $footer,
210 );
211 wp_send_json( $response );
212 }
213
214 /**
215 * Set add priority
216 */
217 public static function set_add_priority() {
218
219 if ( check_ajax_referer( 'wpsc_set_add_priority', '_ajax_nonce', false ) != 1 ) {
220 wp_send_json_error( 'Unauthorised request!', 401 );
221 }
222
223 if ( ! WPSC_Functions::is_site_admin() ) {
224 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
225 }
226
227 $name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
228 if ( ! $name ) {
229 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
230 }
231
232 $color = isset( $_POST['color'] ) ? sanitize_text_field( wp_unslash( $_POST['color'] ) ) : '';
233 if ( ! $color ) {
234 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
235 }
236
237 $bgcolor = isset( $_POST['bg-color'] ) ? sanitize_text_field( wp_unslash( $_POST['bg-color'] ) ) : '';
238 if ( ! $bgcolor ) {
239 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
240 }
241
242 $data = array(
243 'name' => $name,
244 'color' => $color,
245 'bg_color' => $bgcolor,
246 );
247 $priority = WPSC_Priority::insert( $data );
248
249 // set laod order.
250 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
251 $load_after = isset( $_POST['load-after'] ) ? sanitize_text_field( wp_unslash( $_POST['load-after'] ) ) : '__END__';
252
253 if ( $load_after != '__END__' ) {
254
255 $count = 1;
256
257 if ( $load_after == '__TOP__' ) {
258 $priority->load_order = $count++;
259 $priority->save();
260 }
261
262 foreach ( $priorities as $prio ) {
263
264 if ( $prio->id == $priority->id ) {
265 continue;
266 }
267
268 $prio->load_order = $count++;
269 $prio->save();
270
271 if ( $prio->id == $load_after ) {
272 $priority->load_order = $count++;
273 $priority->save();
274 }
275 }
276 }
277
278 wp_die();
279 }
280
281 /**
282 * Get edit priority
283 */
284 public static function get_edit_priority() {
285
286 global $wpdb;
287
288 if ( check_ajax_referer( 'wpsc_get_edit_priority', '_ajax_nonce', false ) != 1 ) {
289 wp_send_json_error( 'Unauthorised request!', 401 );
290 }
291
292 if ( ! WPSC_Functions::is_site_admin() ) {
293 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
294 }
295
296 $id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
297 if ( ! $id ) {
298 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
299 }
300
301 $priority = new WPSC_Priority( $id );
302 if ( ! $priority->id ) {
303 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
304 }
305
306 $title = esc_attr( $priority->name );
307
308 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
309 ob_start();
310 ?>
311 <form action="#" onsubmit="return false;" class="wpsc-frm-edit-priority">
312 <div class="wpsc-input-group">
313 <div class="label-container">
314 <label for=""><?php esc_attr_e( 'Name', 'supportcandy' ); ?></label>
315 <span class="required-char">*</span>
316 </div>
317 <input name="name" type="text" value="<?php echo esc_attr( $priority->name ); ?>" autocomplete="off">
318 </div>
319 <div class="wpsc-input-group">
320 <div class="label-container">
321 <label for=""><?php esc_attr_e( 'Color', 'supportcandy' ); ?></label>
322 </div>
323 <input class="wpsc-color-picker" name="color" value="<?php echo esc_attr( $priority->color ); ?>" />
324 </div>
325 <div class="wpsc-input-group">
326 <div class="label-container">
327 <label for=""><?php esc_attr_e( 'Background color', 'supportcandy' ); ?></label>
328 </div>
329 <input class="wpsc-color-picker" name="bg-color" value="<?php echo esc_attr( $priority->bg_color ); ?>" />
330 </div>
331 <div data-type="" data-required="true" class="wpsc-input-group load-after">
332 <div class="label-container">
333 <label for="">
334 <?php esc_attr_e( 'Load after', 'supportcandy' ); ?>
335 </label>
336 </div>
337 <select name="load-after" class="load-after">
338 <option value="__TOP__">-- <?php esc_attr_e( 'TOP', 'supportcandy' ); ?> --</option>
339 <?php
340 $load_after = $wpdb->get_var( "SELECT id FROM {$wpdb->prefix}psmsc_priorities WHERE load_order < {$priority->load_order} ORDER BY load_order DESC LIMIT 1" );
341 foreach ( $priorities as $prio ) {
342 if ( $prio->id == $priority->id ) {
343 continue;
344 }
345 ?>
346 <option <?php selected( $load_after, $prio->id ); ?> value="<?php echo esc_attr( $prio->id ); ?>"><?php echo esc_attr( $prio->name ); ?></option>
347 <?php
348 }
349 ?>
350 <option value="__END__">-- <?php esc_attr_e( 'END', 'supportcandy' ); ?> --</option>
351 </select>
352 <script>jQuery('select.load-after').selectWoo();</script>
353 </div>
354 <script>jQuery('.wpsc-color-picker').wpColorPicker();</script>
355 <?php do_action( 'wpsc_get_edit_priority_body' ); ?>
356 <input type="hidden" name="action" value="wpsc_set_edit_priority">
357 <input type="hidden" name= "id" value="<?php echo esc_attr( $id ); ?>">
358 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_edit_priority' ) ); ?>">
359 </form>
360 <?php
361 $body = ob_get_clean();
362
363 ob_start();
364 ?>
365 <button class="wpsc-button small primary" onclick="wpsc_set_edit_priority(this);">
366 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
367 </button>
368 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
369 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
370 </button>
371 <?php
372 do_action( 'wpsc_get_edit_priority' );
373 $footer = ob_get_clean();
374
375 $response = array(
376 'title' => $title,
377 'body' => $body,
378 'footer' => $footer,
379 );
380 wp_send_json( $response );
381 }
382
383 /**
384 * Set edit priority
385 */
386 public static function set_edit_priority() {
387
388 global $wpdb;
389
390 if ( check_ajax_referer( 'wpsc_set_edit_priority', '_ajax_nonce', false ) != 1 ) {
391 wp_send_json_error( 'Unauthorised request!', 401 );
392 }
393
394 if ( ! WPSC_Functions::is_site_admin() ) {
395 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
396 }
397
398 $id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
399 if ( ! $id ) {
400 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
401 }
402
403 $name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
404 if ( ! $name ) {
405 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
406 }
407
408 $color = isset( $_POST['color'] ) ? sanitize_text_field( wp_unslash( $_POST['color'] ) ) : '';
409 if ( ! $color ) {
410 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
411 }
412
413 $bgcolor = isset( $_POST['bg-color'] ) ? sanitize_text_field( wp_unslash( $_POST['bg-color'] ) ) : '';
414 if ( ! $bgcolor ) {
415 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
416 }
417
418 $priority = new WPSC_Priority( $id );
419 if ( ! $priority->id ) {
420 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
421 }
422
423 $priority->name = $name;
424 $priority->color = $color;
425 $priority->bg_color = $bgcolor;
426 $priority->save();
427
428 // set laod order.
429 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
430 $load_after = isset( $_POST['load-after'] ) ? sanitize_text_field( wp_unslash( $_POST['load-after'] ) ) : '__END__';
431
432 if ( $load_after != '__END__' ) {
433
434 $count = 1;
435
436 if ( $load_after == '__TOP__' ) {
437 $priority->load_order = $count++;
438 $priority->save();
439 }
440
441 foreach ( $priorities as $cat ) {
442
443 if ( $cat->id == $priority->id ) {
444 continue;
445 }
446
447 $cat->load_order = $count++;
448 $cat->save();
449
450 if ( $cat->id == $load_after ) {
451 $priority->load_order = $count++;
452 $priority->save();
453 }
454 }
455 } else {
456
457 $max_load_order = (int) $wpdb->get_var( "SELECT max(load_order) FROM {$wpdb->prefix}psmsc_priorities" );
458 $priority->load_order = ++$max_load_order;
459 $priority->save();
460 }
461
462 wp_die();
463 }
464
465 /**
466 * Delete priority modal
467 *
468 * @return void
469 */
470 public static function get_delete_priority() {
471
472 if ( ! WPSC_Functions::is_site_admin() ) {
473 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
474 }
475
476 if ( check_ajax_referer( 'wpsc_get_delete_priority', '_ajax_nonce', false ) != 1 ) {
477 wp_send_json_error( 'Unauthorised request!', 401 );
478 }
479
480 $title = esc_attr__( 'Delete priority', 'supportcandy' );
481
482 $id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
483 if ( ! $id ) {
484 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
485 }
486
487 $priority = new WPSC_Priority( $id );
488 if ( ! $priority->id ) {
489 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
490 }
491
492 $priorities = WPSC_Priority::find( array( 'items_per_page' => 0 ) )['results'];
493 ob_start();
494 ?>
495 <form action="#" onsubmit="return false;" class="wpsc-frm-delete-priority">
496 <div class="wpsc-input-group">
497 <div class="label-container">
498 <label for=""><?php esc_attr_e( 'Replace with', 'supportcandy' ); ?></label>
499 </div>
500 <select name="replace_id">
501 <?php
502 foreach ( $priorities as $prt ) {
503 if ( $prt->id == $priority->id ) {
504 continue;
505 }
506 ?>
507 <option value="<?php echo esc_attr( $prt->id ); ?>"><?php echo esc_attr( $prt->name ); ?></option>
508 <?php
509 }
510 ?>
511 </select>
512 </div>
513 <input type="hidden" name="id" value="<?php echo esc_attr( $priority->id ); ?>">
514 <input type="hidden" name="action" value="wpsc_set_delete_priority">
515 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpsc_set_delete_priority' ) ); ?>">
516 </form>
517 <?php
518 $body = ob_get_clean();
519
520 ob_start();
521 ?>
522 <button class="wpsc-button small primary" onclick="wpsc_set_delete_priority(this);">
523 <?php esc_attr_e( 'Submit', 'supportcandy' ); ?>
524 </button>
525 <button class="wpsc-button small secondary" onclick="wpsc_close_modal();">
526 <?php esc_attr_e( 'Cancel', 'supportcandy' ); ?>
527 </button>
528 <?php
529 $footer = ob_get_clean();
530
531 $response = array(
532 'title' => $title,
533 'body' => $body,
534 'footer' => $footer,
535 );
536
537 wp_send_json( $response );
538 }
539
540 /**
541 * Delete priority
542 */
543 public static function set_delete_priority() {
544
545 global $wpdb;
546
547 if ( ! WPSC_Functions::is_site_admin() ) {
548 wp_send_json_error( __( 'Unauthorized access!', 'supportcandy' ), 401 );
549 }
550
551 if ( check_ajax_referer( 'wpsc_set_delete_priority', '_ajax_nonce', false ) != 1 ) {
552 wp_send_json_error( 'Unauthorised request!', 401 );
553 }
554
555 $id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : 0;
556 if ( ! $id ) {
557 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
558 }
559
560 $priority = new WPSC_Priority( $id );
561 if ( ! $priority->id ) {
562 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
563 }
564
565 $replace_id = isset( $_POST['replace_id'] ) ? intval( $_POST['replace_id'] ) : 0;
566 if ( ! $replace_id ) {
567 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
568 }
569
570 $replace = new WPSC_Priority( $replace_id );
571 if ( ! $replace->id ) {
572 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
573 }
574
575 $cf = WPSC_Custom_Field::get_cf_by_slug( 'priority' );
576 if ( $id == $cf->default_value[0] || $id == '1' ) {
577 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
578 }
579
580 // replace in ticket table.
581 $success = $wpdb->update(
582 $wpdb->prefix . 'psmsc_tickets',
583 array( 'priority' => $replace->id ),
584 array( 'priority' => $priority->id )
585 );
586
587 // replace in logs.
588 $results = $wpdb->get_results(
589 "SELECT * FROM {$wpdb->prefix}psmsc_threads WHERE
590 (type = 'log') AND
591 JSON_VALID(body) AND
592 JSON_EXTRACT(body, '$.slug') = 'priority' AND
593 (
594 JSON_UNQUOTE(JSON_EXTRACT(body, '$.new')) = '" . $priority->id . "' OR
595 JSON_UNQUOTE(JSON_EXTRACT(body, '$.prev')) = '" . $priority->id . "'
596 )"
597 );
598 foreach ( $results as $log ) {
599 $body = json_decode( $log->body );
600 $body->prev = $body->prev == $priority->id ? $replace->id : $body->prev;
601 $body->new = $body->new == $priority->id ? $replace->id : $body->new;
602 $body = wp_json_encode( $body );
603 $wpdb->update(
604 $wpdb->prefix . 'psmsc_threads',
605 array( 'body' => $body ),
606 array( 'id' => $log->id )
607 );
608 }
609
610 $priority->destroy( $priority );
611
612 wp_die();
613 }
614 }
615 endif;
616
617 WPSC_Ticket_Priorities::init();
618