Completed
Push — milestone/2.0 ( 784680...06cd51 )
by
unknown
02:57
created

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

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
914
915
		$parsed_rules = array(
916
			'relation' => Helper::get_relation_type_from_array( $rules ),
917
			'rules' => array(),
918
		);
919
920
		foreach ( $rules as $key => $rule ) {
921
			if ( $key === 'relation' ) {
922
				continue; // Skip the relation key as it is already handled above
923
			}
924
925
			// Check if the rule is valid
926
			if ( ! is_array( $rule ) || empty( $rule['field'] ) ) {
927
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic rule format. ' .
928
				'The rule should be an array with the "field" key set.' );
929
			}
930
931
			// Check the compare operator
932
			if ( empty( $rule['compare'] ) ) {
933
				$rule['compare'] = '=';
934
			}
935
			if ( ! in_array( $rule['compare'], $allowed_operators ) ) {
936
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic compare operator: <code>' .
937
					$rule['compare'] . '</code><br>Allowed operators are: <code>' .
938
				implode( ', ', $allowed_operators ) . '</code>' );
939
			}
940
			if ( $rule['compare'] === 'IN' || $rule['compare'] === 'NOT IN' ) {
941
				if ( ! is_array( $rule['value'] ) ) {
942
					Incorrect_Syntax_Exception::raise( 'Invalid conditional logic value format. ' .
943
					'An array is expected, when using the "' . $rule['compare'] . '" operator.' );
944
				}
945
			}
946
947
			// Check the value
948
			if ( ! isset( $rule['value'] ) ) {
949
				$rule['value'] = '';
950
			}
951
952
			$parsed_rules['rules'][] = $rule;
953
		}
954
955
		return $parsed_rules;
956
	}
957
958
	/**
959
	 * Configuration function for setting the field visibility in the response of the requests to the REST API
960
	 * 
961
	 * @param bool $visible
962
	 * @return Field $this
963
	 */
964
	public function show_in_rest( $visible = true ) {
965
		$this->set_visible_in_rest_api( $visible );
966
		return $this;
967
	}
968
	/**
969
	 * Set the REST visibility of the field
970
	 * 
971
	 * @param bool $visible
972
	 */
973
	public function set_visible_in_rest_api( $visible ) {
974
		$this->visible_in_rest_api = $visible;
975
	}
976
	/**
977
	 * Get the REST visibility of the field
978
	 * 
979
	 * @return bool
980
	 */
981
	public function get_visible_in_rest_api() {
982
		return $this->visible_in_rest_api;
983
	}
984
985
	/**
986
	 * Hook administration scripts.
987
	 */
988
	public static function admin_hook_scripts() {
989
		wp_enqueue_media();
990
		wp_enqueue_script( 'carbon-fields', \Carbon_Fields\URL . '/assets/js/fields.js', array( 'carbon-app', 'carbon-containers' ), \Carbon_Fields\VERSION );
991
		wp_localize_script( 'carbon-fields', 'crbl10n',
992
			array(
993
				'title' => __( 'Files', \Carbon_Fields\TEXT_DOMAIN ),
994
				'geocode_zero_results' => __( 'The address could not be found. ', \Carbon_Fields\TEXT_DOMAIN ),
995
				'geocode_not_successful' => __( 'Geocode was not successful for the following reason: ', \Carbon_Fields\TEXT_DOMAIN ),
996
				'max_num_items_reached' => __( 'Maximum number of items reached (%s items)', \Carbon_Fields\TEXT_DOMAIN ),
997
				'max_num_rows_reached' => __( 'Maximum number of rows reached (%s rows)', \Carbon_Fields\TEXT_DOMAIN ),
998
				'cannot_create_more_rows' => __( 'Cannot create more than %s rows', \Carbon_Fields\TEXT_DOMAIN ),
999
				'complex_no_rows' => __( 'There are no %s yet. Click <a href="#">here</a> to add one.', \Carbon_Fields\TEXT_DOMAIN ),
1000
				'complex_add_button' => __( 'Add %s', \Carbon_Fields\TEXT_DOMAIN ),
1001
				'complex_min_num_rows_not_reached' => __( 'Minimum number of rows not reached (%1$d %2$s)', \Carbon_Fields\TEXT_DOMAIN ),
1002
				'message_form_validation_failed' => __( 'Please fill out all fields correctly. ', \Carbon_Fields\TEXT_DOMAIN ),
1003
				'message_required_field' => __( 'This field is required. ', \Carbon_Fields\TEXT_DOMAIN ),
1004
				'message_choose_option' => __( 'Please choose an option. ', \Carbon_Fields\TEXT_DOMAIN ),
1005
1006
				'enter_name_of_new_sidebar' => __( 'Please enter the name of the new sidebar:', \Carbon_Fields\TEXT_DOMAIN ),
1007
			)
1008
		);
1009
	}
1010
1011
	/**
1012
	 * Hook administration styles.
1013
	 */
1014
	public static function admin_hook_styles() {
1015
		wp_enqueue_style( 'thickbox' );
1016
	}
1017
}
1018