Completed
Push — milestone/2_0/react-ui ( fa3453...17c6c0 )
by
unknown
03:35
created

Field::set_required()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 0
cts 3
cp 0
crap 2
1
<?php
2
3
namespace Carbon_Fields\Field;
4
5
use Carbon_Fields\Carbon_Fields;
6
use Carbon_Fields\Pimple\Container as PimpleContainer;
7
use Carbon_Fields\Datastore\Datastore_Interface;
8
use Carbon_Fields\Datastore\Datastore_Holder_Interface;
9
use Carbon_Fields\Value_Set\Value_Set;
10
use Carbon_Fields\Helper\Helper;
11
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
12
13
/**
14
 * Base field class.
15
 * Defines the key container methods and their default implementations.
16
 * Implements factory design pattern.
17
 */
18
class Field implements Datastore_Holder_Interface {
19
	
20
	/**
21
	 * Array of field class names that have had their activation method called
22
	 *
23
	 * @var array<string>
24
	 */
25
	protected static $activated_field_types = array();
26
27
	/**
28
	 * Globally unique field identificator. Generated randomly
29
	 *
30
	 * @var string
31
	 */
32
	protected $id;
33
34
	/**
35
	 * Stores the initial <kbd>$type</kbd> variable passed to the <code>factory()</code> method
36
	 *
37
	 * @see factory
38
	 * @var string
39
	 */
40
	public $type;
41
42
	/**
43
	 * Array of ancestor field names
44
	 *
45
	 * @var array
46
	 */
47
	protected $hierarchy = array();
48
49
	/**
50
	 * Array of complex entry ids
51
	 *
52
	 * @var array
53
	 */
54
	protected $hierarchy_index = array();
55
56
	/**
57
	 * Field value
58
	 *
59
	 * @var Value_Set
60
	 */
61
	protected $value_set;
62
63
	/**
64
	 * Default field value
65
	 *
66
	 * @var mixed
67
	 */
68
	protected $default_value = '';
69
70
	/**
71
	 * Sanitized field name used as input name attribute during field render
72
	 *
73
	 * @see factory()
74
	 * @see set_name()
75
	 * @var string
76
	 */
77
	protected $name;
78
79
	/**
80
	 * Field name prefix
81
	 *
82
	 * @see set_name()
83
	 * @var string
84
	 */
85
	protected $name_prefix = '_';
86
87
	/**
88
	 * The base field name which is used in the container.
89
	 *
90
	 * @see set_base_name()
91
	 * @var string
92
	 */
93
	protected $base_name;
94
95
	/**
96
	 * Field name used as label during field render
97
	 *
98
	 * @see factory()
99
	 * @see set_label()
100
	 * @var string
101
	 */
102
	protected $label;
103
104
	/**
105
	 * Additional text containing information and guidance for the user
106
	 *
107
	 * @see help_text()
108
	 * @var string
109
	 */
110
	protected $help_text;
111
112
	/**
113
	 * Field DataStore instance to which save, load and delete calls are delegated
114
	 *
115
	 * @see set_datastore()
116
	 * @see get_datastore()
117
	 * @var Datastore_Interface
118
	 */
119
	protected $datastore;
120
121
	/**
122
	 * Flag whether the datastore is the default one or replaced with a custom one
123
	 *
124
	 * @see set_datastore()
125
	 * @see get_datastore()
126
	 * @var boolean
127
	 */
128
	protected $has_default_datastore = true;
129
130
	/**
131
	 * The type of the container this field is in
132
	 *
133
	 * @see get_context()
134
	 * @var string
135
	 */
136
	protected $context;
137
138
	/**
139
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
140
	 *
141
	 * @see set_autoload()
142
	 * @var bool
143
	 */
144
	protected $autoload = false;
145
146
	/**
147
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
148
	 *
149
	 * @see set_lazyload()
150
	 * @var bool
151
	 */
152
	protected $lazyload = false;
153
154
	/**
155
	 * The width of the field.
156
	 *
157
	 * @see set_width()
158
	 * @var int
159
	 */
160
	protected $width = 0;
161
162
	/**
163
	 * Custom CSS classes.
164
	 *
165
	 * @see set_classes()
166
	 * @var array
167
	 */
168
	protected $classes = array();
169
170
	/**
171
	 * Whether or not this field is required.
172
	 *
173
	 * @see set_required()
174
	 * @var bool
175
	 */
176
	protected $required = false;
177
178
	/**
179
	 * Stores the field conditional logic rules.
180
	 *
181
	 * @var array
182
	 */
183
	protected $conditional_logic = array();
184
185
	/**
186
	 * Whether the field should be included in the response of the requests to the REST API
187
	 *
188
	 * @see  set_visible_in_rest_api
189
	 * @see  get_visible_in_rest_api
190
	 * @var boolean
191
	 */
192
	protected $visible_in_rest_api = false;
193
194
	/**
195
	 * Clone the Value_Set object as well
196
	 *
197
	 * @var array
198
	 */
199
	public function __clone() {
200
		$this->set_value_set( clone $this->get_value_set() );
201
	}
202
203
	/**
204
	 * Create a new field of type $raw_type and name $name and label $label.
205
	 *
206
	 * @param string $raw_type
207
	 * @param string $name lower case and underscore-delimited
208
	 * @param string $label (optional) Automatically generated from $name if not present
209
	 * @return Field
210
	 */
211 14
	public static function factory( $raw_type, $name, $label = null ) {
212 14
		$type = Helper::normalize_type( $raw_type );
213
214 14
		if ( Carbon_Fields::has( $type, 'fields' ) ) {
215
			return Carbon_Fields::resolve_with_arguments( $type, array(
216
				'type' => $type,
217
				'name' => $name,
218
				'label' => $label,
219
			), 'fields' );
220
		}
221
222
		// Fallback to class name-based resolution
223 14
		$class = Helper::type_to_class( $type, __NAMESPACE__, '_Field' );
224 14 View Code Duplication
		if ( ! class_exists( $class ) ) {
225 4
			Incorrect_Syntax_Exception::raise( 'Unknown field "' . $raw_type . '".' );
226 1
			$class = __NAMESPACE__ . '\\Broken_Field';
227 1
		}
228
229 11
		$field = new $class( $type, $name, $label );
230 7
		return $field;
231
	}
232
233
	/**
234
	 * An alias of factory().
235
	 *
236
	 * @see Field::factory()
237
	 * @return Field
238
	 */
239 14
	public static function make( $type, $name, $label = null ) {
240 14
		return static::factory( $type, $name, $label );
241
	}
242
243
	/**
244
	 * Create a field from a certain type with the specified label.
245
	 * 
246
	 * @param string $type  Field type
247
	 * @param string $name  Field name
248
	 * @param string $label Field label
249
	 */
250 11
	public function __construct( $type, $name, $label ) {
251 11
		Carbon_Fields::verify_boot();
252
		
253 11
		$this->type = $type;
254 11
		$this->set_base_name( $name );
255 11
		$this->set_name( $name );
256 7
		$this->set_label( $label );
257
258
		// Pick random ID
259 7
		$random_string = md5( mt_rand() . $this->get_name() . $this->get_label() );
260 7
		$random_string = substr( $random_string, 0, 5 ); // 5 chars should be enough
261 7
		$this->id = 'carbon-' . $random_string;
262
263 7
		$this->init();
264 7
	}
265
266
	/**
267
	 * Returns the type of the field based on the class.
268
	 * The class is stripped by the "CarbonFields" prefix.
269
	 * Also the "Field" suffix is removed.
270
	 * Then underscores and backslashes are removed.
271
	 *
272
	 * @return string
273
	 */
274
	public function get_type() {
275
		$class = get_class( $this );
276
		return Helper::class_to_type( $class, '_Field' );
277
	}
278
279
	/**
280
	 * Activate the field once the container is attached.
281
	 */
282
	public function activate() {
283
		$this->admin_init();
284
285
		add_action( 'admin_print_footer_scripts', array( get_class(), 'admin_hook_scripts' ), 5 );
286
		add_action( 'admin_print_footer_scripts', array( get_class(), 'admin_hook_styles' ), 5 );
287
		static::activate_field_type( get_class( $this ) );
288
289
		do_action( 'carbon_fields_field_activated', $this );
290
	}
291
292
	/**
293
	 * Activate a field type
294
	 * @param string $class_name
295
	 */
296
	public static function activate_field_type( $class_name ) {
297
		if ( in_array( $class_name, static::$activated_field_types ) ) {
298
			return;
299
		}
300
301
		add_action( 'admin_print_footer_scripts', array( $class_name, 'admin_enqueue_scripts' ), 5 );
302
		call_user_func( array( $class_name, 'field_type_activated' ) );
303
304
		static::$activated_field_types[] = $class_name;
305
	}
306
307
	/**
308
	 * Prepare the field type for use
309
	 * Called once per field type when activated
310
	 */
311
	public static function field_type_activated() {}
312
313
	/**
314
	 * Get array of hierarchy field names
315
	 *
316
	 * @return array
317
	 */
318
	public function get_hierarchy() {
319
		return $this->hierarchy;
320
	}
321
322
	/**
323
	 * Set array of hierarchy field names
324
	 */
325
	public function set_hierarchy( $hierarchy ) {
326
		$this->hierarchy = $hierarchy;
327
	}
328
329
	/**
330
	 * Get array of hierarchy indexes
331
	 *
332
	 * @return array
333
	 */
334
	public function get_hierarchy_index() {
335
		return $this->hierarchy_index;
336
	}
337
338
	/**
339
	 * Set array of hierarchy indexes
340
	 */
341
	public function set_hierarchy_index( $hierarchy_index ) {
342
		$hierarchy_index = ( ! empty( $hierarchy_index ) ) ? $hierarchy_index : array( 0 );
343
		$this->hierarchy_index = $hierarchy_index;
344
	}
345
346
	/**
347
	 * Return whether the field is a root field and holds a single value
348
	 *
349
	 * @return bool
350
	 */
351 3
	public function is_simple_root_field() {
352 3
		$hierarchy = $this->get_hierarchy();
353
		return (
354 3
			empty( $hierarchy )
355 3
			&&
356 2
			in_array( $this->get_value_set()->get_type(), array( Value_Set::TYPE_SINGLE_VALUE, Value_Set::TYPE_MULTIPLE_PROPERTIES ) )
357 3
		);
358
	}
359
360
	/**
361
	 * Perform instance initialization
362
	 */
363
	public function init() {}
364
365
	/**
366
	 * Instance initialization when in the admin area
367
	 * Called during field boot
368
	 */
369
	public function admin_init() {}
370
371
	/**
372
	 * Enqueue scripts and styles in admin
373
	 * Called once per field type
374
	 */
375
	public static function admin_enqueue_scripts() {}
376
377
	/**
378
	 * Get value from datastore
379
	 *
380
	 * @param bool $fallback_to_default
381
	 * @return mixed
382
	 */
383
	protected function get_value_from_datastore( $fallback_to_default = true ) {
384
		$value_tree = $this->get_datastore()->load( $this );
385
		
386
		$value = null;
387
		if ( isset( $value_tree['value_set'] ) ) {
388
			$value = $value_tree['value_set'];
389
		}
390
391
		if ( $value === null && $fallback_to_default ) {
392
			$value = $this->get_default_value();
393
		}
394
395
		return $value;
396
	}
397
398
	/**
399
	 * Load value from datastore
400
	 */
401 2
	public function load() {
402 2
		$value = $this->get_value_from_datastore();
403 2
		$this->set_value( $value );
404 2
	}
405
406
	/**
407
	 * Save value to storage
408
	 */
409 5
	public function save() {
410 5
		$delete_on_save = ! in_array( $this->get_value_set()->get_type(), array( Value_Set::TYPE_SINGLE_VALUE, Value_Set::TYPE_MULTIPLE_PROPERTIES ) );
411 5
		$delete_on_save = apply_filters( 'carbon_fields_should_delete_field_value_on_save', $delete_on_save, $this );
412 5
		if ( $delete_on_save ) {
413 2
			$this->delete();
414 2
		}
415
416 5
		$save = apply_filters( 'carbon_fields_should_save_field_value', true, $this->get_value(), $this );
417 5
		if ( $save ) {
418 5
			$this->get_datastore()->save( $this );
419 5
		}
420 5
	}
421
422
	/**
423
	 * Delete value from storage
424
	 */
425 1
	public function delete() {
426 1
		$this->get_datastore()->delete( $this );
427 1
	}
428
429
	/**
430
	 * Load the field value from an input array based on it's name
431
	 *
432
	 * @param array $input Array of field names and values.
433
	 */
434 2
	public function set_value_from_input( $input ) {
435 2
		if ( isset( $input[ $this->get_name() ] ) ) {
436 1
			$this->set_value( $input[ $this->get_name() ] );
437 1
		} else {
438 1
			$this->clear_value();
439
		}
440 2
	}
441
442
	/**
443
	 * Return whether the datastore instance is the default one or has been overriden
444
	 *
445
	 * @return boolean
446
	 */
447
	public function has_default_datastore() {
448
		return $this->has_default_datastore;
449
	}
450
451
	/**
452
	 * Get the DataStore instance
453
	 *
454
	 * @return Datastore_Interface $datastore
455
	 */
456 1
	public function get_datastore() {
457 1
		return $this->datastore;
458
	}
459
460
	/**
461
	 * Set datastore instance
462
	 *
463
	 * @param Datastore_Interface $datastore
464
	 * @return object $this
465
	 */
466 1
	public function set_datastore( Datastore_Interface $datastore, $set_as_default = false ) {
467 1
		if ( $set_as_default && ! $this->has_default_datastore() ) {
468
			return $this; // datastore has been overriden with a custom one - abort changing to a default one
469
		}
470 1
		$this->datastore = $datastore;
471 1
		$this->has_default_datastore = $set_as_default;
472 1
		return $this;
473
	}
474
475
	/**
476
	 * Return the type of the container this field is in
477
	 *
478
	 * @return string
479
	 */
480
	public function get_context() {
481
		return $this->context;
482
	}
483
484
	/**
485
	 * Assign the type of the container this field is in
486
	 *
487
	 * @param string
488
	 * @return object $this
489
	 */
490
	public function set_context( $context ) {
491
		$this->context = $context;
492
		return $this;
493
	}
494
495
	/**
496
	 * Get the Value_Set object
497
	 *
498
	 * @return Value_Set
499
	 */
500 2
	public function get_value_set() {
501 2
		if ( $this->value_set === null ) {
502 1
			$this->set_value_set( new Value_Set() );
503 1
		}
504 2
		return $this->value_set;
505
	}
506
507
	/**
508
	 * Set the Value_Set object
509
	 *
510
	 * @param Value_Set $value_set
511
	 */
512 1
	public function set_value_set( $value_set ) {
513 1
		$this->value_set = $value_set;
514 1
	}
515
516
	/**
517
	 * Alias for $this->get_value_set()->get(); with fallback to default value
518
	 *
519
	 * @return mixed
520
	 */
521 3
	public function get_value() {
522 3
		if ( $this->get_value_set()->get() === null ) {
523 1
			$this->set_value( $this->get_default_value() );
524 1
		}
525 3
		return $this->get_value_set()->get();
526
	}
527
528
	/**
529
	 * Alias for $this->get_value_set()->get_set(); with fallback to default value
530
	 *
531
	 * @return array<array>
532
	 */
533
	public function get_full_value() {
534
		if ( $this->get_value_set()->get_set() === null ) {
535
			$this->set_value( $this->get_default_value() );
536
		}
537
		return $this->get_value_set()->get_set();
538
	}
539
540
	/**
541
	 * Return a differently formatted value for end-users
542
	 *
543
	 * @return mixed
544
	 */
545 2
	public function get_formatted_value() {
546 2
		return $this->get_value();
547
	}
548
549
	/**
550
	 * Alias for $this->get_value_set()->set( $value );
551
	 */
552 1
	public function set_value( $value ) {
553 1
		$this->get_value_set()->set( $value );
554 1
	}
555
556
	/**
557
	 * Clear the field value to a blank one (but not the default one)
558
	 */
559
	public function clear_value() {
560
		$this->get_value_set()->set( array() );
561
	}
562
563
	/**
564
	 * Get default field value
565
	 *
566
	 * @return mixed
567
	 */
568 1
	public function get_default_value() {
569 1
		return $this->default_value;
570
	}
571
572
	/**
573
	 * Set default field value
574
	 *
575
	 * @param mixed $default_value
576
	 */
577 1
	public function set_default_value( $default_value ) {
578 1
		$this->default_value = $default_value;
579 1
		return $this;
580
	}
581
582
	/**
583
	 * Return the field base name.
584
	 *
585
	 * @return string
586
	 */
587
	public function get_base_name() {
588
		return $this->base_name;
589
	}
590
591
	/**
592
	 * Set field base name as defined in the container.
593
	 */
594
	public function set_base_name( $name ) {
595
		$this->base_name = $name;
596
	}
597
598
	/**
599
	 * Return the field name
600
	 *
601
	 * @return string
602
	 */
603 2
	public function get_name() {
604 2
		return $this->name;
605
	}
606
607
	/**
608
	 * Set field name.
609
	 * Use only if you are completely aware of what you are doing.
610
	 *
611
	 * @param string $name Field name, either sanitized or not
612
	 */
613 6
	public function set_name( $name ) {
614 6
		if ( empty( $name ) ) {
615 1
			Incorrect_Syntax_Exception::raise( 'Field name can\'t be empty' );
616
			return;
617
		}
618
619
		// symbols ]-[ are supported in a hidden way - required for widgets to work (WP imposes dashes and square brackets on field names)
620 5
		$regex = '/\A[a-z0-9_\-\[\]]+\z/';
621 5
		if ( ! preg_match( $regex, $name ) ) {
622 3
			Incorrect_Syntax_Exception::raise( 'Field name can only contain lowercase alphanumeric characters and underscores ("' . $name . '" passed).' );
623
			return;
624
		}
625
626 2
		$name_prefix = $this->get_name_prefix();
627 2
		$name = ( substr( $name, 0, strlen( $name_prefix ) ) !== $name_prefix ? $name_prefix . $name : $name );
628
629 2
		$this->name = $name;
630 2
	}
631
632
	/**
633
	 * Return the field name prefix
634
	 *
635
	 * @return string
636
	 */
637 3
	public function get_name_prefix() {
638 3
		return $this->name_prefix;
639
	}
640
641
	/**
642
	 * Set field name prefix
643
	 * Use only if you are completely aware of what you are doing.
644
	 *
645
	 * @param string $name_prefix
646
	 */
647 3
	public function set_name_prefix( $name_prefix ) {
648 3
		$name_prefix = strval( $name_prefix );
649 3
		$old_prefix_length = strlen( $this->name_prefix );
650 3
		$this->name_prefix = '';
651 3
		$this->set_name( substr( $this->get_name(), $old_prefix_length ) );
652
653 3
		$this->name_prefix = $name_prefix;
654 3
		$this->set_name( $this->name_prefix . $this->get_name() );
655 3
	}
656
657
	/**
658
	 * Return field label.
659
	 *
660
	 * @return string
661
	 */
662
	public function get_label() {
663
		return $this->label;
664
	}
665
666
	/**
667
	 * Set field label.
668
	 *
669
	 * @param string $label If null, the label will be generated from the field name
670
	 */
671 View Code Duplication
	public function set_label( $label ) {
672
		// Try to guess field label from it's name
673
		if ( is_null( $label ) ) {
674
			// remove the leading underscore(if it's there)
675
			$label = preg_replace( '~^_~', '', $this->name );
676
677
			// remove the leading "crb_"(if it's there)
678
			$label = preg_replace( '~^crb_~', '', $label );
679
680
			// split the name into words and make them capitalized
681
			$label = mb_convert_case( str_replace( '_', ' ', $label ), MB_CASE_TITLE );
682
		}
683
684
		$this->label = $label;
685
	}
686
687
	/**
688
	 * Return the field help text
689
	 *
690
	 * @return object $this
691
	 */
692
	public function get_help_text() {
693
		return $this->help_text;
694
	}
695
696
	/**
697
	 * Set additional text to be displayed during field render,
698
	 * containing information and guidance for the user
699
	 *
700
	 * @return object $this
701
	 */
702
	public function set_help_text( $help_text ) {
703
		$this->help_text = $help_text;
704
		return $this;
705
	}
706
707
	/**
708
	 * Alias for set_help_text()
709
	 *
710
	 * @see set_help_text()
711
	 * @return object $this
712
	 */
713
	public function help_text( $help_text ) {
714
		return $this->set_help_text( $help_text );
715
	}
716
717
	/**
718
	 * Return whether or not this value should be auto loaded.
719
	 *
720
	 * @return bool
721
	 */
722
	public function get_autoload() {
723
		return $this->autoload;
724
	}
725
726
	/**
727
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
728
	 *
729
	 * @param bool $autoload
730
	 * @return object $this
731
	 */
732
	public function set_autoload( $autoload ) {
733
		$this->autoload = $autoload;
734
		return $this;
735
	}
736
737
	/**
738
	 * Return whether or not this field should be lazyloaded.
739
	 *
740
	 * @return bool
741
	 */
742
	public function get_lazyload() {
743
		return $this->lazyload;
744
	}
745
746
	/**
747
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
748
	 *
749
	 * @param bool $lazyload
750
	 * @return object $this
751
	 */
752
	public function set_lazyload( $lazyload ) {
753
		$this->lazyload = $lazyload;
754
		return $this;
755
	}
756
757
	/**
758
	 * Get the field width.
759
	 *
760
	 * @return int $width
761
	 */
762
	public function get_width() {
763
		return $this->width;
764
	}
765
766
	/**
767
	 * Set the field width.
768
	 *
769
	 * @param int $width
770
	 * @return object $this
771
	 */
772
	public function set_width( $width ) {
773
		$this->width = (int) $width;
774
		return $this;
775
	}
776
777
	/**
778
	 * Get custom CSS classes.
779
	 *
780
	 * @return array<string>
781
	 */
782
	public function get_classes() {
783
		return $this->classes;
784
	}
785
786
	/**
787
	 * Set CSS classes that the container should use.
788
	 *
789
	 * @param string|array<string> $classes
790
	 * @return object $this
791
	 */
792
	public function set_classes( $classes ) {
793
		$this->classes = Helper::sanitize_classes( $classes );
794
		return $this;
795
	}
796
797
	/**
798
	 * Whether this field is mandatory for the user
799
	 *
800
	 * @param bool $required
801
	 * @return object $this
802
	 */
803
	public function set_required( $required = true ) {
804
		$this->required = $required;
805
		return $this;
806
	}
807
808
	/**
809
	 * Return whether this field is mandatory for the user
810
	 *
811
	 * @return bool
812
	 */
813
	public function is_required() {
814
		return $this->required;
815
	}
816
817
	/**
818
	 * HTML id attribute getter.
819
	 * @return string
820
	 */
821 1
	public function get_id() {
822 1
		return $this->id;
823
	}
824
825
	/**
826
	 * HTML id attribute setter
827
	 * @param string $id
828
	 */
829 1
	public function set_id( $id ) {
830 1
		$this->id = $id;
831 1
	}
832
833
	/**
834
	 * Set the field visibility conditional logic.
835
	 *
836
	 * @param array
837
	 */
838 8
	public function set_conditional_logic( $rules ) {
839 8
		$this->conditional_logic = $this->parse_conditional_rules( $rules );
840
841 3
		return $this;
842
	}
843
844
	/**
845
	 * Get the conditional logic rules
846
	 *
847
	 * @return array
848
	 */
849 3
	public function get_conditional_logic() {
850 3
		return $this->conditional_logic;
851
	}
852
853
	/**
854
	 * Validate and parse the conditional logic rules.
855
	 *
856
	 * @param array $rules
857
	 * @return array
858
	 */
859
	protected function parse_conditional_rules( $rules ) {
860
		if ( ! is_array( $rules ) ) {
861
			Incorrect_Syntax_Exception::raise( 'Conditional logic rules argument should be an array.' );
862
			return array();
863
		}
864
865
		$allowed_operators = array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN' );
866
867
		$parsed_rules = array(
868
			'relation' => Helper::get_relation_type_from_array( $rules ),
869
			'rules' => array(),
870
		);
871
872
		foreach ( $rules as $key => $rule ) {
873
			if ( $key === 'relation' ) {
874
				continue; // Skip the relation key as it is already handled above
875
			}
876
877
			// Check if the rule is valid
878
			if ( ! is_array( $rule ) || empty( $rule['field'] ) ) {
879
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic rule format. ' .
880
				'The rule should be an array with the "field" key set.' );
881
				return array();
882
			}
883
884
			// Fill in optional keys with defaults
885
			$rule = array_merge( array(
886
				'compare' => '=',
887
				'value' => '',
888
			), $rule );
889
890 View Code Duplication
			if ( ! in_array( $rule['compare'], $allowed_operators ) ) {
891
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic compare operator: <code>' .
892
					$rule['compare'] . '</code><br>Allowed operators are: <code>' .
893
				implode( ', ', $allowed_operators ) . '</code>' );
894
				return array();
895
			}
896
897
			if ( in_array( $rule['compare'], array( 'IN', 'NOT IN' ) ) && ! is_array( $rule['value'] ) ) {
898
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic value format. ' .
899
					'An array is expected, when using the "' . $rule['compare'] . '" operator.' );
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 20.
Loading history...
900
				return array();
901
			}
902
903
			$parsed_rules['rules'][] = $rule;
904
		}
905
906
		return $parsed_rules;
907
	}
908
909
	/**
910
	 * Set the REST visibility of the field
911
	 * 
912
	 * @param bool $visible
913
	 */
914
	public function set_visible_in_rest_api( $visible ) {
915
		$this->visible_in_rest_api = $visible;
916
	}
917
	
918
	/**
919
	 * Get the REST visibility of the field
920
	 * 
921
	 * @return bool
922
	 */
923
	public function get_visible_in_rest_api() {
924
		return $this->visible_in_rest_api;
925
	}
926
927
	/**
928
	 * Configuration function for setting the field visibility in the response of the requests to the REST API
929
	 * 
930
	 * @param bool $visible
931
	 * @return Field $this
932
	 */
933
	public function show_in_rest( $visible = true ) {
934
		$this->set_visible_in_rest_api( $visible );
935
		return $this;
936
	}
937
938
	/**
939
	 * Returns an array that holds the field data, suitable for JSON representation.
940
	 *
941
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
942
	 * @return array
943
	 */
944
	public function to_json( $load ) {
945
		if ( $load ) {
946
			$this->load();
947
		}
948
949
		$field_data = array(
950
			'id' => $this->get_id(),
951
			'type' => $this->get_type(),
952
			'label' => $this->get_label(),
953
			'name' => $this->get_name(),
954
			'base_name' => $this->get_base_name(),
955
			'value' => $this->get_value(),
956
			'default_value' => $this->get_default_value(),
957
			'help_text' => $this->get_help_text(),
958
			'context' => $this->get_context(),
959
			'required' => $this->is_required(),
960
			'lazyload' => $this->get_lazyload(),
961
			'width' => $this->get_width(),
962
			'classes' => $this->get_classes(),
963
			'conditional_logic' => $this->get_conditional_logic(),
964
		);
965
966
		return $field_data;
967
	}
968
969
	/**
970
	 * Hook administration scripts.
971
	 */
972
	public static function admin_hook_scripts() {
973
		wp_enqueue_media();
974
	}
975
976
	/**
977
	 * Hook administration styles.
978
	 */
979
	public static function admin_hook_styles() {
980
		wp_enqueue_style( 'thickbox' );
981
	}
982
}
983