Completed
Push — milestone/2_0/react-ui ( 5689d1...3d03d0 )
by
unknown
10:59 queued 03:13
created

Field::set_id()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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