PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.4.2
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.4.2
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 / models / class-wpsc-custom-field.php

class-wpsc-custom-field.php in SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent 3.4.2, at includes/models/class-wpsc-custom-field.php

764 lines 20.4 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_Custom_Field' ) ) :
7
8 final class WPSC_Custom_Field {
9
10 /**
11 * Object data in key => val pair.
12 *
13 * @var array
14 */
15 private $data = array();
16
17 /**
18 * Set whether or not current object properties modified
19 *
20 * @var boolean
21 */
22 private $is_modified = false;
23
24 /**
25 * Schema for this model
26 *
27 * @var array
28 */
29 public static $schema = array();
30
31 /**
32 * Prevent fields to modify
33 *
34 * @var array
35 */
36 public static $prevent_modify = array();
37
38 /**
39 * Custom field type
40 *
41 * @var array
42 */
43 public static $cf_types;
44
45 /**
46 * Custom fields with slug indexing.
47 *
48 * @var array
49 */
50 public static $custom_fields = array();
51
52 /**
53 * DB object caching
54 *
55 * @var array
56 */
57 private static $cache = array();
58
59 /**
60 * Initialize this class
61 *
62 * @return void
63 */
64 public static function init() {
65
66 // Apply schema for this model.
67 add_action( 'init', array( __CLASS__, 'apply_schema' ), 2 );
68
69 // Get object of this class.
70 add_filter( 'wpsc_load_ref_classes', array( __CLASS__, 'load_ref_class' ) );
71
72 // Set custom field types.
73 add_action( 'init', array( __CLASS__, 'set_cf_types' ) );
74 }
75
76 /**
77 * Apply schema for this model
78 *
79 * @return void
80 */
81 public static function apply_schema() {
82
83 $schema = array(
84 'id' => array(
85 'has_ref' => false,
86 'ref_class' => '',
87 'has_multiple_val' => false,
88 ),
89 'name' => array(
90 'has_ref' => false,
91 'ref_class' => '',
92 'has_multiple_val' => false,
93 ),
94 'extra_info' => array(
95 'has_ref' => false,
96 'ref_class' => '',
97 'has_multiple_val' => false,
98 ),
99 'slug' => array(
100 'has_ref' => false,
101 'ref_class' => '',
102 'has_multiple_val' => false,
103 ),
104 'field' => array( // Set whether this field is ticket field, customer field or agentonly field.
105 'has_ref' => false,
106 'ref_class' => '',
107 'has_multiple_val' => false,
108 ),
109 'type' => array( // Set custom field type.. e.g. TextFeld, Dropdown, or any default types.
110 'has_ref' => true,
111 'ref_class' => 'wpsc_cft',
112 'has_multiple_val' => false,
113 ),
114 'default_value' => array( // If set, this value will be used if not provided for ticket or customer field types.
115 'has_ref' => false,
116 'ref_class' => '',
117 'has_multiple_val' => true,
118 ),
119 'placeholder_text' => array( // Placeholder on create ticket or edit ticket, customer or agentonly fields where applicable.
120 'has_ref' => false,
121 'ref_class' => '',
122 'has_multiple_val' => false,
123 ),
124 'char_limit' => array( // Number of charaters to accept where applicable.
125 'has_ref' => false,
126 'ref_class' => '',
127 'has_multiple_val' => false,
128 ),
129 'date_display_as' => array( // Used in Date Created, Date Updated and Date Closed to define whether you want to display date string or date difference on ticket list.
130 'has_ref' => false,
131 'ref_class' => '',
132 'has_multiple_val' => false,
133 ),
134 'date_range' => array( // Used in "Date" custom field whether to accept past, future or any dates.
135 'has_ref' => false,
136 'ref_class' => '',
137 'has_multiple_val' => false,
138 ),
139 'date_format' => array( // Used in "Date" custom field to display date in given format.
140 'has_ref' => false,
141 'ref_class' => '',
142 'has_multiple_val' => false,
143 ),
144 'start_range' => array( // Used in "Date Datetime and Time" custom field for start date or start time.
145 'has_ref' => true,
146 'ref_class' => 'datetime',
147 'has_multiple_val' => false,
148 ),
149 'end_range' => array( // Used in "Date Datetime and Time" custom field for end date or end time.
150 'has_ref' => true,
151 'ref_class' => 'datetime',
152 'has_multiple_val' => false,
153 ),
154 'time_format' => array( // Used in "Time" custom field to display time in 12 or 24 hrs.
155 'has_ref' => false,
156 'ref_class' => '',
157 'has_multiple_val' => false,
158 ),
159 'is_personal_info' => array( // Used for GDPR compatibility.
160 'has_ref' => false,
161 'ref_class' => '',
162 'has_multiple_val' => false,
163 ),
164 'load_order' => array(
165 'has_ref' => false,
166 'ref_class' => '',
167 'has_multiple_val' => false,
168 ),
169 'is_auto_fill' => array( // Used for fill value automatically.
170 'has_ref' => false,
171 'ref_class' => '',
172 'has_multiple_val' => false,
173 ),
174 'allow_ticket_form' => array( // Used for customer field are add or not in create ticket form.
175 'has_ref' => false,
176 'ref_class' => '',
177 'has_multiple_val' => false,
178 ),
179 'allow_my_profile' => array( // Used for customer field are show/hide in my profile.
180 'has_ref' => false,
181 'ref_class' => '',
182 'has_multiple_val' => false,
183 ),
184 'tl_width' => array( // Used in ticket list for column width.
185 'has_ref' => false,
186 'ref_class' => '',
187 'has_multiple_val' => false,
188 ),
189 'number_type' => array( // Used to set whether current field is integer or float.
190 'has_ref' => false,
191 'ref_class' => '',
192 'has_multiple_val' => false,
193 ),
194 );
195 self::$schema = apply_filters( 'wpsc_cf_schema', $schema );
196
197 // Prevent modify.
198 $prevent_modify = array( 'id', 'slug' );
199 self::$prevent_modify = apply_filters( 'wpsc_cf_prevent_modify', $prevent_modify );
200
201 // Set custom fields.
202 $custom_fields = self::find( array( 'items_per_page' => 0 ) )['results'];
203 foreach ( $custom_fields as $cf ) {
204 if ( ! class_exists( $cf->type ) ) {
205 continue;
206 }
207 self::$custom_fields[ $cf->slug ] = $cf;
208 self::$cache[ $cf->id ] = $cf;
209 }
210 }
211
212 /**
213 * Model constructor
214 *
215 * @param int $id - Optional. Data record id to retrive object for.
216 */
217 public function __construct( $id = 0 ) {
218
219 global $wpdb;
220
221 $id = intval( $id );
222
223 if ( $id && isset( self::$cache[ $id ] ) ) {
224 $this->data = self::$cache[ $id ]->data;
225 }
226
227 if ( $id > 0 ) {
228 $cf = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}psmsc_custom_fields WHERE id = " . $id, ARRAY_A );
229 if ( ! is_array( $cf ) ) {
230 return;
231 }
232
233 foreach ( $cf as $key => $val ) {
234
235 if ( $key == 'name' ) {
236
237 $this->data[ $key ] = $val !== null ? WPSC_Translations::get( 'wpsc-cf-name-' . $cf['id'], stripslashes( $val ) ) : '';
238
239 } elseif ( $key == 'extra_info' ) {
240
241 $this->data[ $key ] = $val !== null ? WPSC_Translations::get( 'wpsc-cf-exi-' . $cf['id'], stripslashes( $val ) ) : '';
242
243 } elseif ( $key == 'placeholder_text' ) {
244 $this->data[ $key ] = $val !== null ? WPSC_Translations::get( 'wpsc-cf-pl-txt-' . $cf['id'], stripslashes( $val ) ) : '';
245
246 } else {
247
248 $this->data[ $key ] = $val !== null ? $val : '';
249 }
250 }
251 }
252 }
253
254 /**
255 * Convert object into an array
256 *
257 * @return array
258 */
259 public function to_array() {
260
261 return $this->data;
262 }
263
264 /**
265 * Magic get function to use with object arrow function
266 *
267 * @param string $var_name - variable name.
268 * @return mixed
269 */
270 public function __get( $var_name ) {
271
272 if ( ! isset( $this->data[ $var_name ] ) ||
273 $this->data[ $var_name ] == null ||
274 $this->data[ $var_name ] == ''
275 ) {
276 return self::$schema[ $var_name ]['has_multiple_val'] ? array() : '';
277 }
278
279 if ( self::$schema[ $var_name ]['has_multiple_val'] ) {
280
281 $response = array();
282 $values = $this->data[ $var_name ] ? explode( '|', $this->data[ $var_name ] ) : array();
283 foreach ( $values as $val ) {
284 $response[] = self::$schema[ $var_name ]['has_ref'] ?
285 WPSC_Functions::get_object( self::$schema[ $var_name ]['ref_class'], $val ) :
286 $val;
287 }
288 return $response;
289
290 } else {
291
292 return self::$schema[ $var_name ]['has_ref'] && $this->data[ $var_name ] ?
293 WPSC_Functions::get_object( self::$schema[ $var_name ]['ref_class'], $this->data[ $var_name ] ) :
294 $this->data[ $var_name ];
295 }
296 }
297
298 /**
299 * Magic function to use setting object field with arrow function
300 *
301 * @param string $var_name - (Required) property slug.
302 * @param mixed $value - (Required) value to set for a property.
303 * @return void
304 */
305 public function __set( $var_name, $value ) {
306
307 if ( in_array( $var_name, self::$prevent_modify ) ) {
308 return;
309 }
310
311 $data_val = '';
312 if ( self::$schema[ $var_name ]['has_multiple_val'] ) {
313
314 $data_vals = array_map(
315 fn( $val ) => is_object( $val ) ? WPSC_Functions::set_object( self::$schema[ $var_name ]['ref_class'], $val ) : $val,
316 $value
317 );
318
319 $data_val = $data_vals ? implode( '|', $data_vals ) : '';
320
321 } else {
322
323 $data_val = is_object( $value ) ? WPSC_Functions::set_object( self::$schema[ $var_name ]['ref_class'], $value ) : $value;
324 }
325
326 if ( isset( $this->data[ $var_name ] ) && $this->data[ $var_name ] == $data_val ) {
327 return;
328 }
329
330 $this->data[ $var_name ] = $data_val;
331 $this->is_modified = true;
332 }
333
334 /**
335 * Save changes made
336 *
337 * @return boolean
338 */
339 public function save() {
340
341 global $wpdb;
342
343 if ( ! $this->is_modified ) {
344 return true;
345 }
346
347 $data = $this->data;
348 $success = true;
349
350 if ( ! isset( $data['id'] ) ) {
351
352 $cf = self::insert( $data );
353 if ( $cf ) {
354 $this->data = $cf->data;
355 $success = true;
356 } else {
357 $success = false;
358 }
359 } else {
360
361 unset( $data['id'] );
362 $success = $wpdb->update(
363 $wpdb->prefix . 'psmsc_custom_fields',
364 $data,
365 array( 'id' => $this->id )
366 );
367
368 WPSC_Translations::add( 'wpsc-cf-name-' . $this->id, $data['name'] );
369 $data['extra_info'] ? WPSC_Translations::add( 'wpsc-cf-exi-' . $this->id, $data['extra_info'] ) : WPSC_Translations::remove( 'wpsc-cf-exi-' . $this->id );
370 $data['placeholder_text'] ? WPSC_Translations::add( 'wpsc-cf-pl-txt-' . $this->id, $data['placeholder_text'] ) : WPSC_Translations::remove( 'wpsc-cf-pl-txt-' . $this->id );
371
372 if ( $success ) {
373 self::$custom_fields[ $this->slug ] = $this;
374 self::$cache[ $this->id ] = $this;
375 }
376 }
377 $this->is_modified = false;
378 return $success ? true : false;
379 }
380
381 /**
382 * Insert new record
383 *
384 * @param array $data - insert data.
385 * @return WPSC_Custom_Field
386 */
387 public static function insert( $data ) {
388
389 global $wpdb;
390
391 if ( ! isset( $data['load_order'] ) ) {
392 $max_order = $wpdb->get_var( "SELECT MAX(load_order) FROM {$wpdb->prefix}psmsc_custom_fields" );
393 $data['load_order'] = intval( $max_order ) + 1;
394 }
395
396 $success = $wpdb->insert(
397 $wpdb->prefix . 'psmsc_custom_fields',
398 $data
399 );
400
401 if ( ! $success ) {
402 return false;
403 }
404
405 $id = $wpdb->insert_id;
406
407 // string translation.
408 WPSC_Translations::add( 'wpsc-cf-name-' . $id, $data['name'] );
409 if ( isset( $data['extra_info'] ) ) {
410 WPSC_Translations::add( 'wpsc-cf-exi-' . $id, $data['extra_info'] );
411 }
412 if ( isset( $data['placeholder_text'] ) ) {
413 WPSC_Translations::add( 'wpsc-cf-pl-txt-' . $id, $data['placeholder_text'] );
414 }
415
416 $cf = new WPSC_Custom_Field( $id );
417
418 // Save slug if not already set. Reasone we have to do it here because slug is in $prevent_modify.
419 if ( ! $cf->slug ) {
420 $slug = 'cust_' . $cf->id;
421 $wpdb->update(
422 $wpdb->prefix . 'psmsc_custom_fields',
423 array( 'slug' => $slug ),
424 array( 'id' => $cf->id )
425 );
426 $cf->data['slug'] = $slug;
427 }
428
429 // Check if user has privileges to change innodb_strict_mode.
430 $has_privileges = $wpdb->get_var( 'SELECT @@innodb_strict_mode' ) !== null;
431 if ( $has_privileges ) {
432 // Disable InnoDB strict mode if enabled to avoid limit of number of columns in tables.
433 $strict_mode = $wpdb->get_var( "SHOW VARIABLES LIKE 'innodb_strict_mode'", 1 );
434 if ( $strict_mode == 'ON' ) {
435 $wpdb->query( "SET innodb_strict_mode = 'OFF'" );
436 }
437 }
438
439 // Add column to tickets table if field is either ticket or agentonly.
440 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) && $cf->type::$slug != 'cf_html' ) {
441 $success = $cf->create_ticket_tbl_col();
442 }
443
444 // Add column to customer table if field is customer.
445 if ( $cf->field === 'customer' ) {
446 $success = $cf->create_customer_tbl_col();
447 }
448
449 $success = apply_filters( 'wpsc_add_cf_table_column', $success, $cf );
450
451 self::$custom_fields[ $cf->slug ] = $cf;
452 self::$cache[ $cf->id ] = $cf;
453
454 if ( ! $success ) {
455 return false;
456 }
457 return $cf;
458 }
459
460 /**
461 * Delete record of given ID
462 *
463 * @param int $id - category id.
464 * @return boolean
465 */
466 public static function destroy( $id ) {
467
468 global $wpdb;
469
470 $cf = new WPSC_Custom_Field( $id );
471 if ( $cf->type::$is_default ) {
472 return false;
473 }
474
475 if ( in_array( $cf->field, array( 'ticket', 'agentonly' ) ) && $cf->type::$slug != 'cf_html' ) {
476 $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_tickets DROP {$cf->slug}" );
477 $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_archived_tickets DROP {$cf->slug}" );
478 }
479
480 if ( $cf->field === 'customer' ) {
481 $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_customers DROP {$cf->slug}" );
482 }
483
484 do_action( 'wpsc_custom_field_before_destroy', $cf );
485
486 // Remove from DB.
487 $success = $wpdb->delete(
488 $wpdb->prefix . 'psmsc_custom_fields',
489 array( 'id' => $cf->id )
490 );
491 if ( ! $success ) {
492 return false;
493 }
494
495 // Remove options if any.
496 if ( $cf->type::$has_options ) {
497 $cf->delete_options();
498 }
499
500 unset( self::$custom_fields[ $cf->slug ] );
501 unset( self::$cache[ $cf->id ] );
502
503 // remove string translations.
504 WPSC_Translations::remove( 'wpsc-cf-name-' . $cf->id );
505 WPSC_Translations::remove( 'wpsc-cf-exi-' . $cf->id );
506 WPSC_Translations::remove( 'wpsc-cf-pl-txt-' . $cf->id );
507
508 return true;
509 }
510
511 /**
512 * Set data to create new object using direct data. Used in find method
513 *
514 * @param array $data - data to set for object.
515 * @return void
516 */
517 private function set_data( $data ) {
518
519 foreach ( $data as $var_name => $val ) {
520
521 if ( $var_name == 'name' ) {
522
523 $this->data[ $var_name ] = $val !== null ? WPSC_Translations::get( 'wpsc-cf-name-' . $data['id'], stripslashes( $val ) ) : '';
524
525 } elseif ( $var_name == 'extra_info' ) {
526
527 $this->data[ $var_name ] = $val !== null ? WPSC_Translations::get( 'wpsc-cf-exi-' . $data['id'], stripslashes( $val ) ) : '';
528
529 } elseif ( $var_name == 'placeholder_text' ) {
530
531 $this->data[ $var_name ] = $val !== null ? WPSC_Translations::get( 'wpsc-cf-pl-txt-' . $data['id'], stripslashes( $val ) ) : '';
532
533 } else {
534
535 $this->data[ $var_name ] = $val !== null ? $val : '';
536 }
537 }
538 }
539
540 /**
541 * Find records based on given filters
542 *
543 * @param array $filter - array containing array items like search, where, orderby, order, page_no, items_per_page, etc.
544 * @param boolean $is_object - return data as array or object. Default object.
545 * @return mixed
546 */
547 public static function find( $filter = array(), $is_object = true ) {
548
549 global $wpdb;
550
551 $sql = 'SELECT * FROM ' . $wpdb->prefix . 'psmsc_custom_fields ';
552 $where = self::get_where( $filter );
553
554 $filter['items_per_page'] = isset( $filter['items_per_page'] ) ? $filter['items_per_page'] : 0;
555 $filter['page_no'] = isset( $filter['page_no'] ) ? $filter['page_no'] : 1;
556 $filter['orderby'] = isset( $filter['orderby'] ) ? $filter['orderby'] : 'load_order';
557 $filter['order'] = isset( $filter['order'] ) ? $filter['order'] : 'ASC';
558
559 $order = WPSC_Functions::parse_order( $filter );
560 $limit = WPSC_Functions::parse_limit( $filter );
561 $sql = $sql . $where . $order . $limit;
562 $results = $wpdb->get_results( $sql, ARRAY_A );
563
564 // total results.
565 $sql = 'SELECT count(id) FROM ' . $wpdb->prefix . 'psmsc_custom_fields ';
566 $total_items = $wpdb->get_var( $sql . $where );
567
568 $response = WPSC_Functions::parse_response( $results, $total_items, $filter );
569
570 // Return array.
571 if ( ! $is_object ) {
572 return $response;
573 }
574
575 // create and return array of objects.
576 $temp_results = array();
577 foreach ( $response['results'] as $cf ) {
578
579 $ob = new WPSC_Custom_Field();
580 $data = array();
581 foreach ( $cf as $key => $val ) {
582 $data[ $key ] = $val;
583 }
584 $ob->set_data( $data );
585 $temp_results[] = $ob;
586 }
587 $response['results'] = $temp_results;
588
589 return $response;
590 }
591
592 /**
593 * Get where for find method
594 *
595 * @param array $filter - user filter.
596 * @return array
597 */
598 private static function get_where( $filter ) {
599
600 $where = '';
601
602 // Set user defined filters.
603 $meta_query = isset( $filter['meta_query'] ) && $filter['meta_query'] ? $filter['meta_query'] : array();
604 $meta_query = apply_filters( 'wpsc_cf_meta_query', $meta_query, $filter );
605 if ( $meta_query ) {
606
607 $meta_query = WPSC_Functions::parse_user_filters( __CLASS__, $meta_query );
608 $where = $meta_query . ' ';
609 }
610
611 return $where ? 'WHERE ' . $where : '';
612 }
613
614 /**
615 * Load current class to reference classes
616 *
617 * @param array $classes - Associative array of class names indexed by its slug.
618 * @return array
619 */
620 public static function load_ref_class( $classes ) {
621
622 $classes['wpsc_cf'] = array(
623 'class' => __CLASS__,
624 'save-key' => 'id',
625 );
626 return $classes;
627 }
628
629 /**
630 * Create column for custom field in ticket table
631 *
632 * @return boolean
633 */
634 public function create_ticket_tbl_col() {
635
636 global $wpdb;
637 $result_archived = $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_archived_tickets ADD {$this->slug} {$this->type::$data_type}" );
638 $result_tickets = $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_tickets ADD {$this->slug} {$this->type::$data_type}" );
639
640 // Both queries must succeed.
641 if ( $result_archived === false || $result_tickets === false ) {
642 // Optionally, you could log or handle the error here.
643 return false;
644 }
645 return true;
646 }
647
648 /**
649 * Create column for custom field in customer table
650 *
651 * @return boolean
652 */
653 public function create_customer_tbl_col() {
654
655 global $wpdb;
656 return $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_customers ADD {$this->slug} {$this->type::$data_type}" );
657 }
658
659 /**
660 * Set custom field types
661 */
662 public static function set_cf_types() {
663
664 self::$cf_types = apply_filters( 'wpsc_cf_types', array() );
665 }
666
667 /**
668 * Reset options for the field
669 *
670 * @param array $options - option ids.
671 * @param boolean $is_edit - set whether it is called from edit custom field.
672 * @return void
673 */
674 public function set_options( $options, $is_edit = false ) {
675
676 global $wpdb;
677
678 if ( $is_edit ) {
679 $wpdb->update(
680 $wpdb->prefix . 'psmsc_options',
681 array( 'custom_field' => 0 ),
682 array( 'custom_field' => $this->id )
683 );
684 }
685
686 if ( $this->type::$has_options ) {
687 $count = 1;
688 foreach ( $options as $option_id ) {
689 $option = new WPSC_Option( $option_id );
690 if ( ! $option->id ) {
691 continue;
692 }
693 $option->custom_field = $this->id;
694 $option->load_order = $count++;
695 $option->save();
696 }
697 }
698 }
699
700 /**
701 * Get options for this field
702 */
703 public function get_options() {
704
705 $filter = array(
706 'meta_query' => array(
707 'relation' => 'AND',
708 array(
709 'slug' => 'custom_field',
710 'compare' => '=',
711 'val' => $this->id,
712 ),
713 ),
714 );
715 return WPSC_Option::find( $filter )['results'];
716 }
717
718 /**
719 * Delete all options for this custom field
720 */
721 public function delete_options() {
722
723 global $wpdb;
724 $wpdb->delete(
725 $wpdb->prefix . 'psmsc_options',
726 array( 'custom_field' => $this->id )
727 );
728 }
729
730 /**
731 * Return CF object by slug
732 *
733 * @param string $slug - custom field slug.
734 * @return WPSC_Custom_Field
735 */
736 public static function get_cf_by_slug( $slug ) {
737
738 $cf = isset( self::$custom_fields[ $slug ] ) ? self::$custom_fields[ $slug ] : false;
739 return $cf;
740 }
741
742 /**
743 * Set load order for ids given
744 *
745 * @param array $ids - custom field ids.
746 * @return void
747 */
748 public static function set_load_order( $ids ) {
749
750 $count = 1;
751 foreach ( $ids as $id ) {
752 $cf = new WPSC_Custom_Field( $id );
753 if ( ! $cf ) {
754 wp_send_json_error( __( 'Bad request!', 'supportcandy' ), 400 );
755 }
756 $cf->load_order = $count++;
757 $cf->save();
758 }
759 }
760 }
761 endif;
762
763 WPSC_Custom_Field::init();
764