Completed
Push — milestone/2_0/react-ui ( 1c376a...57d10c )
by
unknown
02:51
created

Field::set_hierarchy_index()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 6
rs 10
1
<?php
2
3
namespace Carbon_Fields\Field;
4
5
use Carbon_Fields\Datastore\Datastore_Interface;
6
use Carbon_Fields\Datastore\Datastore_Holder_Interface;
7
use Carbon_Fields\Value_Set\Value_Set;
8
use Carbon_Fields\Helper\Helper;
9
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
10
11
/**
12
 * Base field class.
13
 * Defines the key container methods and their default implementations.
14
 * Implements factory design pattern.
15
 **/
16
class Field implements Datastore_Holder_Interface {
17
	
18
	/**
19
	 * Globally unique field identificator. Generated randomly
20
	 *
21
	 * @var string
22
	 */
23
	protected $id;
24
25
	/**
26
	 * Stores the initial <kbd>$type</kbd> variable passed to the <code>factory()</code> method
27
	 *
28
	 * @see factory
29
	 * @var string
30
	 */
31
	public $type;
32
33
	/**
34
	 * Array of ancestor field names
35
	 *
36
	 * @var array
37
	 **/
38
	protected $hierarchy = array();
39
40
	/**
41
	 * Array of complex entry ids
42
	 *
43
	 * @var array
44
	 **/
45
	protected $hierarchy_index = array();
46
47
	/**
48
	 * Field value
49
	 *
50
	 * @var Value_Set
51
	 */
52
	protected $value_set;
53
54
	/**
55
	 * Default field value
56
	 *
57
	 * @var mixed
58
	 */
59
	protected $default_value = '';
60
61
	/**
62
	 * Sanitized field name used as input name attribute during field render
63
	 *
64
	 * @see factory()
65
	 * @see set_name()
66
	 * @var string
67
	 */
68
	protected $name;
69
70
	/**
71
	 * Field name prefix
72
	 *
73
	 * @see set_name()
74
	 * @var string
75
	 */
76
	protected $name_prefix = '_';
77
78
	/**
79
	 * The base field name which is used in the container.
80
	 *
81
	 * @see set_base_name()
82
	 * @var string
83
	 */
84
	protected $base_name;
85
86
	/**
87
	 * Field name used as label during field render
88
	 *
89
	 * @see factory()
90
	 * @see set_label()
91
	 * @var string
92
	 */
93
	protected $label;
94
95
	/**
96
	 * Additional text containing information and guidance for the user
97
	 *
98
	 * @see help_text()
99
	 * @var string
100
	 */
101
	protected $help_text;
102
103
	/**
104
	 * Field DataStore instance to which save, load and delete calls are delegated
105
	 *
106
	 * @see set_datastore()
107
	 * @see get_datastore()
108
	 * @var Datastore_Interface
109
	 */
110
	protected $datastore;
111
112
	/**
113
	 * Flag whether the datastore is the default one or replaced with a custom one
114
	 *
115
	 * @see set_datastore()
116
	 * @see get_datastore()
117
	 * @var boolean
118
	 */
119
	protected $has_default_datastore = true;
120
121
	/**
122
	 * The type of the container this field is in
123
	 *
124
	 * @see get_context()
125
	 * @var string
126
	 */
127
	protected $context;
128
129
	/**
130
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
131
	 *
132
	 * @see set_autoload()
133
	 * @var bool
134
	 **/
135
	protected $autoload = false;
136
137
	/**
138
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
139
	 *
140
	 * @see set_lazyload()
141
	 * @var bool
142
	 **/
143
	protected $lazyload = false;
144
145
	/**
146
	 * The width of the field.
147
	 *
148
	 * @see set_width()
149
	 * @var int
150
	 **/
151
	protected $width = 0;
152
153
	/**
154
	 * Custom CSS classes.
155
	 *
156
	 * @see add_class()
157
	 * @var array
158
	 **/
159
	protected $classes = array();
160
161
	/**
162
	 * Whether or not this field is required.
163
	 *
164
	 * @see set_required()
165
	 * @var bool
166
	 **/
167
	protected $required = false;
168
169
	/**
170
	 * Stores the field conditional logic rules.
171
	 *
172
	 * @var array
173
	 **/
174
	protected $conditional_logic = array();
175
176
	/**
177
	 * Whether the field should be included in the response of the requests to the REST API
178
	 *
179
	 * @see  set_visible_in_rest_api
180
	 * @see  get_visible_in_rest_api
181
	 * @var boolean
182
	 */
183
	protected $visible_in_rest_api = false;
184
185
	/**
186
	 * Clone the Value_Set object as well
187
	 *
188
	 * @var array
189
	 **/
190
	public function __clone() {
191
		$this->set_value_set( clone $this->get_value_set() );
192
	}
193
194
	/**
195
	 * Create a new field of type $type and name $name and label $label.
196
	 *
197
	 * @param string $type
198
	 * @param string $name lower case and underscore-delimited
199
	 * @param string $label (optional) Automatically generated from $name if not present
200
	 * @return Field
201
	 **/
202 14
	public static function factory( $type, $name, $label = null ) {
203 14
		$type = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $type ) ) );
204
205 14
		$class = __NAMESPACE__ . '\\' . $type . '_Field';
206
207 14
		if ( ! class_exists( $class ) && class_exists( $type ) ) {
208
			$reflection = new \ReflectionClass( $type );
209
			if ( $reflection->isSubclassOf( get_class() ) ) {
210
				$class = $type;
211
			} else {
212
				Incorrect_Syntax_Exception::raise( 'Field must be of type Carbon_Fields\\Field\\Field' );
213
				$class = __NAMESPACE__ . '\\Broken_Field';
214
			}
215
		}
216
217 14 View Code Duplication
		if ( ! class_exists( $class ) ) {
218 4
			Incorrect_Syntax_Exception::raise( 'Unknown field "' . $type . '".' );
219 1
			$class = __NAMESPACE__ . '\\Broken_Field';
220 1
		}
221
222 11
		$field = new $class( $type, $name, $label );
223
224 7
		return $field;
225
	}
226
227
	/**
228
	 * An alias of factory().
229
	 *
230
	 * @see Field::factory()
231
	 * @return Field
232
	 **/
233 14
	public static function make( $type, $name, $label = null ) {
234 14
		return static::factory( $type, $name, $label );
235
	}
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 11
	protected function __construct( $type, $name, $label ) {
245 11
		\Carbon_Fields\Carbon_Fields::verify_boot();
246
		
247 11
		$this->type = $type;
248 11
		$this->set_base_name( $name );
249 11
		$this->set_name( $name );
250 7
		$this->set_label( $label );
251
252
		// Pick random ID
253 7
		$random_string = md5( mt_rand() . $this->get_name() . $this->get_label() );
254 7
		$random_string = substr( $random_string, 0, 5 ); // 5 chars should be enough
255 7
		$this->id = 'carbon-' . $random_string;
256
257 7
		$this->init();
258 7
	}
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_print_footer_scripts', array( get_class(), 'admin_hook_scripts' ), 5 );
280
		add_action( 'admin_print_footer_scripts', array( get_class(), 'admin_hook_styles' ), 5 );
281
		add_action( 'admin_print_footer_scripts', 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 3
	public function is_simple_root_field() {
325 3
		$hierarchy = $this->get_hierarchy();
326
		return (
327 3
			empty( $hierarchy )
328 3
			&&
329
			(
330 2
				$this->get_value_set()->get_type() === Value_Set::TYPE_SINGLE_VALUE
331 2
				||
332 2
				$this->get_value_set()->get_type() === Value_Set::TYPE_MULTIPLE_PROPERTIES
333 2
			)
334 3
		);
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 2
		$value = $this->get_value_from_datastore();
380 2
		$this->set_value( $value );
381 2
	}
382
383
	/**
384
	 * Save value to storage
385
	 **/
386 5
	public function save() {
387 5
		$delete_on_save = ! in_array( $this->get_value_set()->get_type(), array( Value_Set::TYPE_SINGLE_VALUE, Value_Set::TYPE_MULTIPLE_PROPERTIES ) );
388 5
		$delete_on_save = apply_filters( 'carbon_fields_should_delete_field_value_on_save', $delete_on_save, $this );
389 5
		if ( $delete_on_save ) {
390 2
			$this->delete();
391 2
		}
392
393 5
		$save = apply_filters( 'carbon_fields_should_save_field_value', true, $this->get_value(), $this );
394 5
		if ( $save ) {
395 5
			$this->get_datastore()->save( $this );
396 5
		}
397 5
	}
398
399
	/**
400
	 * Delete value from storage
401
	 */
402 1
	public function delete() {
403 1
		$this->get_datastore()->delete( $this );
404 1
	}
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 2
		if ( isset( $input[ $this->get_name() ] ) ) {
413 1
			$this->set_value( $input[ $this->get_name() ] );
414 1
		} else {
415 1
			$this->clear_value();
416
		}
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
	}
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 1
			$this->set_value_set( new Value_Set() );
480 1
		}
481 2
		return $this->value_set;
482
	}
483
484
	/**
485
	 * Set the Value_Set object
486
	 *
487
	 * @param Value_Set $value_set
488
	 **/
489 1
	public function set_value_set( $value_set ) {
490 1
		$this->value_set = $value_set;
491 1
	}
492
493
	/**
494
	 * Alias for $this->get_value_set()->get(); with fallback to default value
495
	 *
496
	 * @return mixed
497
	 **/
498 3
	public function get_value() {
499 3
		if ( $this->get_value_set()->get() === null ) {
500 1
			$this->set_value( $this->get_default_value() );
501 1
		}
502 3
		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 2
	public function get_formatted_value() {
523 2
		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 1
		$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 2
	public function get_name() {
581 2
		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
			return;
594
		}
595
596
		// symbols ]-[ are supported in a hidden way - required for widgets to work (WP imposes dashes and square brackets on field names)
597 5
		$regex = '/\A[a-z0-9_\-\[\]]+\z/';
598 5
		if ( ! preg_match( $regex, $name ) ) {
599 3
			Incorrect_Syntax_Exception::raise( 'Field name can only contain lowercase alphanumeric characters and underscores ("' . $name . '" passed).' );
600
		}
601
602 2
		$name_prefix = $this->get_name_prefix();
603 2
		$name = ( substr( $name, 0, strlen( $name_prefix ) ) !== $name_prefix ? $name_prefix . $name : $name );
604
605 2
		$this->name = $name;
606 2
	}
607
608
	/**
609
	 * Return the field name prefix
610
	 *
611
	 * @return string
612
	 **/
613 3
	public function get_name_prefix() {
614 3
		return $this->name_prefix;
615
	}
616
617
	/**
618
	 * Set field name prefix
619
	 * Use only if you are completely aware of what you are doing.
620
	 *
621
	 * @param string $name_prefix
622
	 **/
623 3
	public function set_name_prefix( $name_prefix ) {
624 3
		$name_prefix = strval( $name_prefix );
625 3
		$old_prefix_length = strlen( $this->name_prefix );
626 3
		$this->name_prefix = '';
627 3
		$this->set_name( substr( $this->get_name(), $old_prefix_length ) );
628
629 3
		$this->name_prefix = $name_prefix;
630 3
		$this->set_name( $this->name_prefix . $this->get_name() );
631 3
	}
632
633
	/**
634
	 * Return field label.
635
	 *
636
	 * @return string
637
	 **/
638
	public function get_label() {
639
		return $this->label;
640
	}
641
642
	/**
643
	 * Set field label.
644
	 *
645
	 * @param string $label If null, the label will be generated from the field name
646
	 **/
647 View Code Duplication
	public function set_label( $label ) {
648
		// Try to guess field label from it's name
649
		if ( is_null( $label ) ) {
650
			// remove the leading underscore(if it's there)
651
			$label = preg_replace( '~^_~', '', $this->name );
652
653
			// remove the leading "crb_"(if it's there)
654
			$label = preg_replace( '~^crb_~', '', $label );
655
656
			// split the name into words and make them capitalized
657
			$label = mb_convert_case( str_replace( '_', ' ', $label ), MB_CASE_TITLE );
658
		}
659
660
		$this->label = $label;
661
	}
662
663
	/**
664
	 * Return the field help text
665
	 *
666
	 * @return object $this
667
	 **/
668
	public function get_help_text() {
669
		return $this->help_text;
670
	}
671
672
	/**
673
	 * Set additional text to be displayed during field render,
674
	 * containing information and guidance for the user
675
	 *
676
	 * @return object $this
677
	 **/
678
	public function set_help_text( $help_text ) {
679
		$this->help_text = $help_text;
680
		return $this;
681
	}
682
683
	/**
684
	 * Alias for set_help_text()
685
	 *
686
	 * @see set_help_text()
687
	 * @return object $this
688
	 **/
689
	public function help_text( $help_text ) {
690
		return $this->set_help_text( $help_text );
691
	}
692
693
	/**
694
	 * Return whether or not this value should be auto loaded.
695
	 *
696
	 * @return bool
697
	 **/
698
	public function get_autoload() {
699
		return $this->autoload;
700
	}
701
702
	/**
703
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
704
	 *
705
	 * @param bool $autoload
706
	 * @return object $this
707
	 **/
708
	public function set_autoload( $autoload ) {
709
		$this->autoload = $autoload;
710
		return $this;
711
	}
712
713
	/**
714
	 * Return whether or not this field should be lazyloaded.
715
	 *
716
	 * @return bool
717
	 **/
718
	public function get_lazyload() {
719
		return $this->lazyload;
720
	}
721
722
	/**
723
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
724
	 *
725
	 * @param bool $lazyload
726
	 * @return object $this
727
	 **/
728
	public function set_lazyload( $lazyload ) {
729
		$this->lazyload = $lazyload;
730
		return $this;
731
	}
732
733
	/**
734
	 * Get the field width.
735
	 *
736
	 * @return int $width
737
	 **/
738
	public function get_width() {
739
		return $this->width;
740
	}
741
742
	/**
743
	 * Set the field width.
744
	 *
745
	 * @param int $width
746
	 * @return object $this
747
	 **/
748
	public function set_width( $width ) {
749
		$this->width = (int) $width;
750
		return $this;
751
	}
752
753
	/**
754
	 * Get custom CSS classes.
755
	 *
756
	 * @return array<string>
757
	 */
758
	public function get_classes() {
759
		return $this->classes;
760
	}
761
762
	/**
763
	 * Set CSS classes that the container should use.
764
	 *
765
	 * @param string|array<string> $classes
766
	 * @return object $this
767
	 */
768
	public function set_classes( $classes ) {
769
		$this->classes = Helper::sanitize_classes( $classes );
770
		return $this;
771
	}
772
773
	/**
774
	 * Whether this field is mandatory for the user
775
	 *
776
	 * @param bool $required
777
	 * @return object $this
778
	 **/
779
	public function set_required( $required = true ) {
780
		$this->required = $required;
781
		return $this;
782
	}
783
784
	/**
785
	 * Return whether this field is mandatory for the user
786
	 *
787
	 * @return bool
788
	 **/
789
	public function is_required() {
790
		return $this->required;
791
	}
792
793
	/**
794
	 * HTML id attribute getter.
795
	 * @return string
796
	 */
797 1
	public function get_id() {
798 1
		return $this->id;
799
	}
800
801
	/**
802
	 * HTML id attribute setter
803
	 * @param string $id
804
	 */
805 1
	public function set_id( $id ) {
806 1
		$this->id = $id;
807 1
	}
808
809
	/**
810
	 * Set the field visibility conditional logic.
811
	 *
812
	 * @param array
813
	 */
814 8
	public function set_conditional_logic( $rules ) {
815 8
		$this->conditional_logic = $this->parse_conditional_rules( $rules );
816
817 3
		return $this;
818
	}
819
820
	/**
821
	 * Get the conditional logic rules
822
	 *
823
	 * @return array
824
	 */
825 3
	public function get_conditional_logic() {
826 3
		return $this->conditional_logic;
827
	}
828
829
	/**
830
	 * Validate and parse the conditional logic rules.
831
	 *
832
	 * @param array $rules
833
	 * @return array
834
	 */
835
	protected function parse_conditional_rules( $rules ) {
836
		if ( ! is_array( $rules ) ) {
837
			Incorrect_Syntax_Exception::raise( 'Conditional logic rules argument should be an array.' );
838
			return array();
839
		}
840
841
		$allowed_operators = array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN' );
842
843
		$parsed_rules = array(
844
			'relation' => Helper::get_relation_type_from_array( $rules ),
845
			'rules' => array(),
846
		);
847
848
		foreach ( $rules as $key => $rule ) {
849
			if ( $key === 'relation' ) {
850
				continue; // Skip the relation key as it is already handled above
851
			}
852
853
			// Check if the rule is valid
854
			if ( ! is_array( $rule ) || empty( $rule['field'] ) ) {
855
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic rule format. ' .
856
				'The rule should be an array with the "field" key set.' );
857
				return array();
858
			}
859
860
			// Check the compare operator
861
			if ( empty( $rule['compare'] ) ) {
862
				$rule['compare'] = '=';
863
			}
864 View Code Duplication
			if ( ! in_array( $rule['compare'], $allowed_operators ) ) {
865
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic compare operator: <code>' .
866
					$rule['compare'] . '</code><br>Allowed operators are: <code>' .
867
				implode( ', ', $allowed_operators ) . '</code>' );
868
				return array();
869
			}
870
			if ( $rule['compare'] === 'IN' || $rule['compare'] === 'NOT IN' ) {
871
				if ( ! is_array( $rule['value'] ) ) {
872
					Incorrect_Syntax_Exception::raise( 'Invalid conditional logic value format. ' .
873
					'An array is expected, when using the "' . $rule['compare'] . '" operator.' );
874
					return array();
875
				}
876
			}
877
878
			// Check the value
879
			if ( ! isset( $rule['value'] ) ) {
880
				$rule['value'] = '';
881
			}
882
883
			$parsed_rules['rules'][] = $rule;
884
		}
885
886
		return $parsed_rules;
887
	}
888
889
	/**
890
	 * Set the REST visibility of the field
891
	 * 
892
	 * @param bool $visible
893
	 */
894
	public function set_visible_in_rest_api( $visible ) {
895
		$this->visible_in_rest_api = $visible;
896
	}
897
	
898
	/**
899
	 * Get the REST visibility of the field
900
	 * 
901
	 * @return bool
902
	 */
903
	public function get_visible_in_rest_api() {
904
		return $this->visible_in_rest_api;
905
	}
906
907
	/**
908
	 * Configuration function for setting the field visibility in the response of the requests to the REST API
909
	 * 
910
	 * @param bool $visible
911
	 * @return Field $this
912
	 */
913
	public function show_in_rest( $visible = true ) {
914
		$this->set_visible_in_rest_api( $visible );
915
		return $this;
916
	}
917
918
	/**
919
	 * Returns an array that holds the field data, suitable for JSON representation.
920
	 *
921
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
922
	 * @return array
923
	 */
924
	public function to_json( $load ) {
925
		if ( $load ) {
926
			$this->load();
927
		}
928
929
		$field_data = array(
930
			'id' => $this->get_id(),
931
			'type' => $this->get_type(),
932
			'label' => $this->get_label(),
933
			'name' => $this->get_name(),
934
			'base_name' => $this->get_base_name(),
935
			'value' => $this->get_value(),
936
			'default_value' => $this->get_default_value(),
937
			'help_text' => $this->get_help_text(),
938
			'context' => $this->get_context(),
939
			'required' => $this->is_required(),
940
			'lazyload' => $this->get_lazyload(),
941
			'width' => $this->get_width(),
942
			'classes' => $this->get_classes(),
943
			'conditional_logic' => $this->get_conditional_logic(),
944
		);
945
946
		return $field_data;
947
	}
948
949
	/**
950
	 * Hook administration scripts.
951
	 */
952
	public static function admin_hook_scripts() {
953
		wp_enqueue_media();
954
	}
955
956
	/**
957
	 * Hook administration styles.
958
	 */
959
	public static function admin_hook_styles() {
960
		wp_enqueue_style( 'thickbox' );
961
	}
962
}
963