Completed
Push — milestone/2_0/react-ui ( 73b2ee...16415b )
by
unknown
27:57 queued 10:59
created

Field::set_default_value()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
3
namespace Carbon_Fields\Field;
4
5
use Carbon_Fields\App;
6
use Carbon_Fields\Datastore\Datastore_Interface;
7
use Carbon_Fields\Datastore\Datastore_Holder_Interface;
8
use Carbon_Fields\Value_Set\Value_Set;
9
use Carbon_Fields\Helper\Helper;
10
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
11
12
/**
13
 * Base field class.
14
 * Defines the key container methods and their default implementations.
15
 * Implements factory design pattern.
16
 **/
17
class Field implements Datastore_Holder_Interface {
18
	
19
	/**
20
	 * Globally unique field identificator. Generated randomly
21
	 *
22
	 * @var string
23
	 */
24
	protected $id;
25
26
	/**
27
	 * Stores the initial <kbd>$type</kbd> variable passed to the <code>factory()</code> method
28
	 *
29
	 * @see factory
30
	 * @var string
31
	 */
32
	public $type;
33
34
	/**
35
	 * Array of ancestor field names
36
	 *
37
	 * @var array
38
	 **/
39
	protected $hierarchy = array();
40
41
	/**
42
	 * Array of complex entry ids
43
	 *
44
	 * @var array
45
	 **/
46
	protected $hierarchy_index = array();
47
48
	/**
49
	 * Field value
50
	 *
51
	 * @var Value_Set
52
	 */
53
	protected $value_set;
54
55
	/**
56
	 * Default field value
57
	 *
58
	 * @var mixed
59
	 */
60
	protected $default_value = '';
61
62
	/**
63
	 * Sanitized field name used as input name attribute during field render
64
	 *
65
	 * @see factory()
66
	 * @see set_name()
67
	 * @var string
68
	 */
69
	protected $name;
70
71
	/**
72
	 * Field name prefix
73
	 *
74
	 * @see set_name()
75
	 * @var string
76
	 */
77
	protected $name_prefix = '_';
78
79
	/**
80
	 * The base field name which is used in the container.
81
	 *
82
	 * @see set_base_name()
83
	 * @var string
84
	 */
85
	protected $base_name;
86
87
	/**
88
	 * Field name used as label during field render
89
	 *
90
	 * @see factory()
91
	 * @see set_label()
92
	 * @var string
93
	 */
94
	protected $label;
95
96
	/**
97
	 * Additional text containing information and guidance for the user
98
	 *
99
	 * @see help_text()
100
	 * @var string
101
	 */
102
	protected $help_text;
103
104
	/**
105
	 * Field DataStore instance to which save, load and delete calls are delegated
106
	 *
107
	 * @see set_datastore()
108
	 * @see get_datastore()
109
	 * @var Datastore_Interface
110
	 */
111
	protected $datastore;
112
113
	/**
114
	 * Flag whether the datastore is the default one or replaced with a custom one
115
	 *
116
	 * @see set_datastore()
117
	 * @see get_datastore()
118
	 * @var boolean
119
	 */
120
	protected $has_default_datastore = true;
121
122
	/**
123
	 * The type of the container this field is in
124
	 *
125
	 * @see get_context()
126
	 * @var string
127
	 */
128
	protected $context;
129
130
	/**
131
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
132
	 *
133
	 * @see set_autoload()
134
	 * @var bool
135
	 **/
136
	protected $autoload = false;
137
138
	/**
139
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
140
	 *
141
	 * @see set_lazyload()
142
	 * @var bool
143
	 **/
144
	protected $lazyload = false;
145
146
	/**
147
	 * The width of the field.
148
	 *
149
	 * @see set_width()
150
	 * @var int
151
	 **/
152
	protected $width = 0;
153
154
	/**
155
	 * Custom CSS classes.
156
	 *
157
	 * @see add_class()
158
	 * @var array
159
	 **/
160
	protected $classes = array();
161
162
	/**
163
	 * Whether or not this field is required.
164
	 *
165
	 * @see set_required()
166
	 * @var bool
167
	 **/
168
	protected $required = false;
169
170
	/**
171
	 * Stores the field conditional logic rules.
172
	 *
173
	 * @var array
174
	 **/
175
	protected $conditional_logic = array();
176
177
	/**
178
	 * Whether the field should be included in the response of the requests to the REST API
179
	 *
180
	 * @see  set_visible_in_rest_api
181
	 * @see  get_visible_in_rest_api
182
	 * @var boolean
183
	 */
184
	protected $visible_in_rest_api = false;
185
186
	/**
187
	 * Clone the Value_Set object as well
188
	 *
189
	 * @var array
190
	 **/
191
	public function __clone() {
192
		$this->set_value_set( clone $this->get_value_set() );
193
	}
194
195
	/**
196
	 * Create a new field of type $type and name $name and label $label.
197
	 *
198
	 * @param string $type
199
	 * @param string $name lower case and underscore-delimited
200
	 * @param string $label (optional) Automatically generated from $name if not present
201
	 * @return Field
202
	 **/
203 12
	public static function factory( $type, $name, $label = null ) {
204
		$type = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $type ) ) );
205
206 12
		$class = __NAMESPACE__ . '\\' . $type . '_Field';
207
208
		if ( ! class_exists( $class ) && class_exists( $type ) ) {
209
			$reflection = new \ReflectionClass( $type );
210
			if ( $reflection->isSubclassOf( get_class() ) ) {
211
				$class = $type;
212
			} else {
213
				Incorrect_Syntax_Exception::raise( 'Field must be of type Carbon_Fields\\Field\\Field' );
214
			}
215
		}
216
217 View Code Duplication
		if ( ! class_exists( $class ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218 3
			Incorrect_Syntax_Exception::raise( 'Unknown field "' . $type . '".' );
219 1
			$class = __NAMESPACE__ . '\\Broken_Field';
220
		}
221
222 4
		$field = new $class( $type, $name, $label );
223
224 5
		return $field;
225
	}
226
227
	/**
228
	 * An alias of factory().
229
	 *
230
	 * @see Field::factory()
231
	 * @return Field
232
	 **/
233 13
	public static function make( $type, $name, $label = null ) {
234 7
		return static::factory( $type, $name, $label );
235 13
	}
236
237
	/**
238
	 * Create a field from a certain type with the specified label.
239
	 * 
240
	 * @param string $type  Field type
241
	 * @param string $name  Field name
242
	 * @param string $label Field label
243
	 */
244 9
	protected function __construct( $type, $name, $label ) {
245
		App::verify_boot();
246
		
247 9
		$this->type = $type;
248
		$this->set_base_name( $name );
249 4
		$this->set_name( $name );
250
		$this->set_label( $label );
251
252
		// Pick random ID
253
		$random_string = md5( mt_rand() . $this->get_name() . $this->get_label() );
254
		$random_string = substr( $random_string, 0, 5 ); // 5 chars should be enough
255 5
		$this->id = 'carbon-' . $random_string;
256
257
		$this->init();
258 5
	}
259
260
	/**
261
	 * Returns the type of the field based on the class.
262
	 * The class is stripped by the "CarbonFields" prefix.
263
	 * Also the "Field" suffix is removed.
264
	 * Then underscores and backslashes are removed.
265
	 *
266
	 * @return string
267
	 */
268
	public function get_type() {
269
		$class = get_class( $this );
270
		return Helper::class_to_type( $class, '_Field' );
271
	}
272
273
	/**
274
	 * Activate the field once the container is attached.
275
	 */
276
	public function activate() {
277
		$this->admin_init();
278
279
		add_action( 'admin_footer', array( get_class(), 'admin_hook_scripts' ), 5 );
280
		add_action( 'admin_footer', array( get_class(), 'admin_hook_styles' ), 5 );
281
		add_action( 'admin_footer', array( get_class( $this ), 'admin_enqueue_scripts' ), 5 );
282
283
		do_action( 'crb_field_activated', $this );
284
	}
285
286
	/**
287
	 * Get array of hierarchy field names
288
	 *
289
	 * @return array
290
	 **/
291
	public function get_hierarchy() {
292
		return $this->hierarchy;
293
	}
294
295
	/**
296
	 * Set array of hierarchy field names
297
	 **/
298
	public function set_hierarchy( $hierarchy ) {
299
		$this->hierarchy = $hierarchy;
300
	}
301
302
	/**
303
	 * Get array of hierarchy indexes
304
	 *
305
	 * @return array
306
	 **/
307
	public function get_hierarchy_index() {
308
		return $this->hierarchy_index;
309
	}
310
311
	/**
312
	 * Set array of hierarchy indexes
313
	 **/
314
	public function set_hierarchy_index( $hierarchy_index ) {
315
		$hierarchy_index = ( ! empty( $hierarchy_index ) ) ? $hierarchy_index : array( 0 );
316
		$this->hierarchy_index = $hierarchy_index;
317
	}
318
319
	/**
320
	 * Return whether the field is a root field and holds a single value
321
	 *
322
	 * @return bool
323
	 **/
324
	public function is_simple_root_field() {
325
		$hierarchy = $this->get_hierarchy();
326
		return (
327
			empty( $hierarchy )
328
			&&
329
			(
330
				$this->get_value_set()->get_type() === Value_Set::TYPE_SINGLE_VALUE
331
				||
332
				$this->get_value_set()->get_type() === Value_Set::TYPE_MULTIPLE_PROPERTIES
333
			)
334
		);
335
	}
336
337
	/**
338
	 * Perform instance initialization
339
	 **/
340
	public function init() {}
341
342
	/**
343
	 * Instance initialization when in the admin area.
344
	 * Called during field boot.
345
	 **/
346
	public function admin_init() {}
347
348
	/**
349
	 * Enqueue admin scripts.
350
	 * Called once per field type.
351
	 **/
352
	public static function admin_enqueue_scripts() {}
353
354
	/**
355
	 * Get value from datastore
356
	 *
357
	 * @param bool $fallback_to_default
358
	 * @return mixed
359
	 **/
360
	protected function get_value_from_datastore( $fallback_to_default = true ) {
361
		$value_tree = $this->get_datastore()->load( $this );
362
		
363
		$value = null;
364
		if ( isset( $value_tree['value_set'] ) ) {
365
			$value = $value_tree['value_set'];
366
		}
367
368
		if ( $value === null && $fallback_to_default ) {
369
			$value = $this->get_default_value();
370
		}
371
372
		return $value;
373
	}
374
375
	/**
376
	 * Load value from datastore
377
	 **/
378 2
	public function load() {
379
		$value = $this->get_value_from_datastore();
380
		$this->set_value( $value );
381 2
	}
382
383
	/**
384
	 * Save value to storage
385
	 **/
386 5
	public function save() {
387
		$delete_on_save = ! in_array( $this->get_value_set()->get_type(), array( Value_Set::TYPE_SINGLE_VALUE, Value_Set::TYPE_MULTIPLE_PROPERTIES ) );
388
		$delete_on_save = apply_filters( 'carbon_fields_should_delete_field_value_on_save', $delete_on_save, $this );
389 5
		if ( $delete_on_save ) {
390
			$this->delete();
391
		}
392
393
		$save = apply_filters( 'carbon_fields_should_save_field_value', true, $this->get_value(), $this );
394 5
		if ( $save ) {
395
			$this->get_datastore()->save( $this );
396
		}
397
	}
398
399
	/**
400
	 * Delete value from storage
401
	 */
402
	public function delete() {
403
		$this->get_datastore()->delete( $this );
404
	}
405
406
	/**
407
	 * Load the field value from an input array based on it's name
408
	 *
409
	 * @param array $input Array of field names and values.
410
	 **/
411 2
	public function set_value_from_input( $input ) {
412
		if ( isset( $input[ $this->get_name() ] ) ) {
413
			$this->set_value( $input[ $this->get_name() ] );
414
		} else {
415
			$this->clear_value();
416 1
		}
417 2
	}
418
419
	/**
420
	 * Return whether the datastore instance is the default one or has been overriden
421
	 *
422
	 * @return boolean
423
	 **/
424
	public function has_default_datastore() {
425
		return $this->has_default_datastore;
426
	}
427
428
	/**
429
	 * Get the DataStore instance
430
	 *
431
	 * @return Datastore_Interface $datastore
432
	 **/
433 1
	public function get_datastore() {
434 1
		return $this->datastore;
435
	}
436
437
	/**
438
	 * Set datastore instance
439
	 *
440
	 * @param Datastore_Interface $datastore
441
	 * @return object $this
442
	 **/
443 1
	public function set_datastore( Datastore_Interface $datastore, $set_as_default = false ) {
444 1
		if ( $set_as_default && ! $this->has_default_datastore() ) {
445
			return $this; // datastore has been overriden with a custom one - abort changing to a default one
446
		}
447 1
		$this->datastore = $datastore;
448 1
		$this->has_default_datastore = $set_as_default;
449 1
		return $this;
450 1
	}
451
452
	/**
453
	 * Return the type of the container this field is in
454
	 *
455
	 * @return string
456
	 **/
457
	public function get_context() {
458
		return $this->context;
459
	}
460
461
	/**
462
	 * Assign the type of the container this field is in
463
	 *
464
	 * @param string
465
	 * @return object $this
466
	 **/
467
	public function set_context( $context ) {
468
		$this->context = $context;
469
		return $this;
470
	}
471
472
	/**
473
	 * Get the Value_Set object
474
	 *
475
	 * @return Value_Set
476
	 **/
477 2
	public function get_value_set() {
478 2
		if ( $this->value_set === null ) {
479
			$this->set_value_set( new Value_Set() );
480
		}
481 2
		return $this->value_set;
482
	}
483
484
	/**
485
	 * Set the Value_Set object
486
	 *
487
	 * @param Value_Set $value_set
488
	 **/
489
	public function set_value_set( $value_set ) {
490
		$this->value_set = $value_set;
491
	}
492
493
	/**
494
	 * Alias for $this->get_value_set()->get(); with fallback to default value
495
	 *
496
	 * @return mixed
497
	 **/
498
	public function get_value() {
499
		if ( $this->get_value_set()->get() === null ) {
500
			$this->set_value( $this->get_default_value() );
501
		}
502
		return $this->get_value_set()->get();
503
	}
504
505
	/**
506
	 * Alias for $this->get_value_set()->get_set(); with fallback to default value
507
	 *
508
	 * @return array<array>
509
	 **/
510
	public function get_full_value() {
511
		if ( $this->get_value_set()->get_set() === null ) {
512
			$this->set_value( $this->get_default_value() );
513
		}
514
		return $this->get_value_set()->get_set();
515
	}
516
517
	/**
518
	 * Return a differently formatted value for end-users
519
	 *
520
	 * @return mixed
521
	 **/
522
	public function get_formatted_value() {
523
		return $this->get_value();
524
	}
525
526
	/**
527
	 * Alias for $this->get_value_set()->set( $value );
528
	 **/
529 1
	public function set_value( $value ) {
530
		$this->get_value_set()->set( $value );
531 1
	}
532
533
	/**
534
	 * Clear the field value to a blank one (but not the default one)
535
	 */
536
	public function clear_value() {
537
		$this->get_value_set()->set( array() );
538
	}
539
540
	/**
541
	 * Get default field value
542
	 *
543
	 * @return mixed
544
	 **/
545 1
	public function get_default_value() {
546 1
		return $this->default_value;
547
	}
548
549
	/**
550
	 * Set default field value
551
	 *
552
	 * @param mixed $default_value
553
	 **/
554 1
	public function set_default_value( $default_value ) {
555 1
		$this->default_value = $default_value;
556 1
		return $this;
557
	}
558
559
	/**
560
	 * Return the field base name.
561
	 *
562
	 * @return string
563
	 **/
564
	public function get_base_name() {
565
		return $this->base_name;
566
	}
567
568
	/**
569
	 * Set field base name as defined in the container.
570
	 **/
571
	public function set_base_name( $name ) {
572
		$this->base_name = $name;
573
	}
574
575
	/**
576
	 * Return the field name
577
	 *
578
	 * @return string
579
	 **/
580
	public function get_name() {
581
		return $this->name;
582
	}
583
584
	/**
585
	 * Set field name.
586
	 * Use only if you are completely aware of what you are doing.
587
	 *
588
	 * @param string $name Field name, either sanitized or not
589
	 **/
590 6
	public function set_name( $name ) {
591 6
		if ( empty( $name ) ) {
592 1
			Incorrect_Syntax_Exception::raise( 'Field name can\'t be empty' );
593
		}
594
595 5
		$regex = '/\A[a-z0-9_\-\[\]]+\z/'; // symbols ]-[ are supported in a hidden way - required for widgets to work (WP imposes dashes and square brackets on field names)
596
		if ( ! preg_match( $regex, $name ) ) {
597 3
			Incorrect_Syntax_Exception::raise( 'Field name can only contain lowercase alphanumeric characters and underscores.' );
598
		}
599
600
		$name_prefix = $this->get_name_prefix();
601
		$name = ( substr( $name, 0, strlen( $name_prefix ) ) !== $name_prefix ? $name_prefix . $name : $name );
602
603 2
		$this->name = $name;
604 2
	}
605
606
	/**
607
	 * Return the field name prefix
608
	 *
609
	 * @return string
610
	 **/
611
	public function get_name_prefix() {
612
		return $this->name_prefix;
613
	}
614
615
	/**
616
	 * Set field name prefix
617
	 * Use only if you are completely aware of what you are doing.
618
	 *
619
	 * @param string $name_prefix
620
	 **/
621 2
	public function set_name_prefix( $name_prefix ) {
622
		$name_prefix = strval( $name_prefix );
623
		$old_prefix_length = strlen( $this->name_prefix );
624 2
		$this->name_prefix = '';
625
		$this->set_name( substr( $this->get_name(), $old_prefix_length ) );
626
627 2
		$this->name_prefix = $name_prefix;
628
		$this->set_name( $this->name_prefix . $this->get_name() );
629 2
	}
630
631
	/**
632
	 * Return field label.
633
	 *
634
	 * @return string
635
	 **/
636
	public function get_label() {
637
		return $this->label;
638
	}
639
640
	/**
641
	 * Set field label.
642
	 *
643
	 * @param string $label If null, the label will be generated from the field name
644
	 **/
645 View Code Duplication
	public function set_label( $label ) {
646
		// Try to guess field label from it's name
647
		if ( is_null( $label ) ) {
648
			// remove the leading underscore(if it's there)
649
			$label = preg_replace( '~^_~', '', $this->name );
650
651
			// remove the leading "crb_"(if it's there)
652
			$label = preg_replace( '~^crb_~', '', $label );
653
654
			// split the name into words and make them capitalized
655
			$label = mb_convert_case( str_replace( '_', ' ', $label ), MB_CASE_TITLE );
656
		}
657
658
		$this->label = $label;
659
	}
660
661
	/**
662
	 * Return the field help text
663
	 *
664
	 * @return object $this
665
	 **/
666
	public function get_help_text() {
667
		return $this->help_text;
668
	}
669
670
	/**
671
	 * Set additional text to be displayed during field render,
672
	 * containing information and guidance for the user
673
	 *
674
	 * @return object $this
675
	 **/
676
	public function set_help_text( $help_text ) {
677
		$this->help_text = $help_text;
678
		return $this;
679
	}
680
681
	/**
682
	 * Alias for set_help_text()
683
	 *
684
	 * @see set_help_text()
685
	 * @return object $this
686
	 **/
687
	public function help_text( $help_text ) {
688
		return $this->set_help_text( $help_text );
689
	}
690
691
	/**
692
	 * Return whether or not this value should be auto loaded.
693
	 *
694
	 * @return bool
695
	 **/
696
	public function get_autoload() {
697
		return $this->autoload;
698
	}
699
700
	/**
701
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
702
	 *
703
	 * @param bool $autoload
704
	 * @return object $this
705
	 **/
706
	public function set_autoload( $autoload ) {
707
		$this->autoload = $autoload;
708
		return $this;
709
	}
710
711
	/**
712
	 * Return whether or not this field should be lazyloaded.
713
	 *
714
	 * @return bool
715
	 **/
716
	public function get_lazyload() {
717
		return $this->lazyload;
718
	}
719
720
	/**
721
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
722
	 *
723
	 * @param bool $lazyload
724
	 * @return object $this
725
	 **/
726
	public function set_lazyload( $lazyload ) {
727
		$this->lazyload = $lazyload;
728
		return $this;
729
	}
730
731
	/**
732
	 * Get the field width.
733
	 *
734
	 * @return int $width
735
	 **/
736
	public function get_width() {
737
		return $this->width;
738
	}
739
740
	/**
741
	 * Set the field width.
742
	 *
743
	 * @param int $width
744
	 * @return object $this
745
	 **/
746
	public function set_width( $width ) {
747
		$this->width = (int) $width;
748
		return $this;
749
	}
750
751
	/**
752
	 * Get custom CSS classes.
753
	 *
754
	 * @return array<string>
755
	 */
756
	public function get_classes() {
757
		return $this->classes;
758
	}
759
760
	/**
761
	 * Set CSS classes that the container should use.
762
	 *
763
	 * @param string|array<string> $classes
764
	 * @return object $this
765
	 */
766
	public function set_classes( $classes ) {
767
		$this->classes = Helper::sanitize_classes( $classes );
768
		return $this;
769
	}
770
771
	/**
772
	 * Whether this field is mandatory for the user
773
	 *
774
	 * @param bool $required
775
	 * @return object $this
776
	 **/
777
	public function set_required( $required = true ) {
778
		$this->required = $required;
779
		return $this;
780
	}
781
782
	/**
783
	 * Return whether this field is mandatory for the user
784
	 *
785
	 * @return bool
786
	 **/
787
	public function is_required() {
788
		return $this->required;
789
	}
790
791
	/**
792
	 * HTML id attribute getter.
793
	 * @return string
794
	 */
795 1
	public function get_id() {
796 1
		return $this->id;
797
	}
798
799
	/**
800
	 * HTML id attribute setter
801
	 * @param string $id
802
	 */
803 1
	public function set_id( $id ) {
804 1
		$this->id = $id;
805 1
	}
806
807
	/**
808
	 * Set the field visibility conditional logic.
809
	 *
810
	 * @param array
811
	 */
812 5
	public function set_conditional_logic( $rules ) {
813 5
		$this->conditional_logic = $this->parse_conditional_rules( $rules );
814
815 3
		return $this;
816
	}
817
818
	/**
819
	 * Get the conditional logic rules
820
	 *
821
	 * @return array
822
	 */
823 3
	public function get_conditional_logic() {
824 3
		return $this->conditional_logic;
825
	}
826
827
	/**
828
	 * Validate and parse the conditional logic rules.
829
	 *
830
	 * @param array $rules
831
	 * @return array
832
	 */
833
	protected function parse_conditional_rules( $rules ) {
834
		if ( ! is_array( $rules ) ) {
835
			Incorrect_Syntax_Exception::raise( 'Conditional logic rules argument should be an array.' );
836
		}
837
838
		$allowed_operators = array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN' );
839
840
		$parsed_rules = array(
841
			'relation' => Helper::get_relation_type_from_array( $rules ),
842
			'rules' => array(),
843
		);
844
845
		foreach ( $rules as $key => $rule ) {
846
			if ( $key === 'relation' ) {
847
				continue; // Skip the relation key as it is already handled above
848
			}
849
850
			// Check if the rule is valid
851
			if ( ! is_array( $rule ) || empty( $rule['field'] ) ) {
852
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic rule format. ' .
853
				'The rule should be an array with the "field" key set.' );
854
			}
855
856
			// Check the compare operator
857
			if ( empty( $rule['compare'] ) ) {
858
				$rule['compare'] = '=';
859
			}
860 View Code Duplication
			if ( ! in_array( $rule['compare'], $allowed_operators ) ) {
861
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic compare operator: <code>' .
862
					$rule['compare'] . '</code><br>Allowed operators are: <code>' .
863
				implode( ', ', $allowed_operators ) . '</code>' );
864
			}
865
			if ( $rule['compare'] === 'IN' || $rule['compare'] === 'NOT IN' ) {
866
				if ( ! is_array( $rule['value'] ) ) {
867
					Incorrect_Syntax_Exception::raise( 'Invalid conditional logic value format. ' .
868
					'An array is expected, when using the "' . $rule['compare'] . '" operator.' );
869
				}
870
			}
871
872
			// Check the value
873
			if ( ! isset( $rule['value'] ) ) {
874
				$rule['value'] = '';
875
			}
876
877
			$parsed_rules['rules'][] = $rule;
878
		}
879
880
		return $parsed_rules;
881
	}
882
883
	/**
884
	 * Set the REST visibility of the field
885
	 * 
886
	 * @param bool $visible
887
	 */
888
	public function set_visible_in_rest_api( $visible ) {
889
		$this->visible_in_rest_api = $visible;
890
	}
891
	
892
	/**
893
	 * Get the REST visibility of the field
894
	 * 
895
	 * @return bool
896
	 */
897
	public function get_visible_in_rest_api() {
898
		return $this->visible_in_rest_api;
899
	}
900
901
	/**
902
	 * Configuration function for setting the field visibility in the response of the requests to the REST API
903
	 * 
904
	 * @param bool $visible
905
	 * @return Field $this
906
	 */
907
	public function show_in_rest( $visible = true ) {
908
		$this->set_visible_in_rest_api( $visible );
909
		return $this;
910
	}
911
912
	/**
913
	 * Returns an array that holds the field data, suitable for JSON representation.
914
	 * This data will be available in the Underscore template and the Backbone Model.
915
	 *
916
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
917
	 * @return array
918
	 */
919
	public function to_json( $load ) {
920
		if ( $load ) {
921
			$this->load();
922
		}
923
924
		$field_data = array(
925
			'id' => $this->get_id(),
926
			'type' => $this->get_type(),
927
			'label' => $this->get_label(),
928
			'name' => $this->get_name(),
929
			'base_name' => $this->get_base_name(),
930
			'value' => $this->get_value(),
931
			'default_value' => $this->get_default_value(),
932
			'help_text' => $this->get_help_text(),
933
			'context' => $this->get_context(),
934
			'required' => $this->is_required(),
935
			'lazyload' => $this->get_lazyload(),
936
			'width' => $this->get_width(),
937
			'classes' => $this->get_classes(),
938
			'conditional_logic' => $this->get_conditional_logic(),
939
		);
940
941
		return $field_data;
942
	}
943
944
	/**
945
	 * Hook administration scripts.
946
	 */
947
	public static function admin_hook_scripts() {
948
		wp_enqueue_media();
949
	}
950
951
	/**
952
	 * Hook administration styles.
953
	 */
954
	public static function admin_hook_styles() {
955
		wp_enqueue_style( 'thickbox' );
956
	}
957
}
958