Completed
Pull Request — master (#77)
by
unknown
03:13 queued 01:18
created

Field   C

Complexity

Total Complexity 79

Size/Duplication

Total Lines 834
Duplicated Lines 4.2 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 11.94%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
c 4
b 1
f 0
dl 35
loc 834
ccs 32
cts 268
cp 0.1194
rs 5
wmc 79
lcom 1
cbo 2

54 Methods

Rating   Name   Duplication   Size   Complexity  
A make() 0 3 1
A init() 0 1 1
A admin_init() 0 1 1
A template() 0 1 1
A get_templates() 0 3 1
A add_template() 0 3 1
A load() 0 7 2
A save() 0 3 1
A delete() 0 3 1
A set_value_from_input() 0 11 3
A set_datastore() 0 4 1
A get_datastore() 0 3 1
A set_context() 0 4 1
A get_context() 0 3 1
A set_value() 0 3 1
A set_default_value() 0 4 1
A get_default_value() 0 3 1
A get_value() 0 3 1
A get_name() 0 3 1
A set_base_name() 0 3 1
A get_base_name() 0 3 1
A set_label() 10 15 2
A get_label() 0 3 1
A set_help_text() 0 4 1
A help_text() 0 3 1
A get_help_text() 0 3 1
A set_autoload() 0 4 1
A get_autoload() 0 3 1
A set_lazyload() 0 4 1
A get_lazyload() 0 3 1
A set_width() 0 4 1
A get_width() 0 3 1
A add_class() 0 8 2
A get_classes() 0 3 1
A set_required() 0 4 1
A get_id() 0 3 1
A set_id() 0 3 1
A is_required() 0 3 1
A get_type() 0 5 1
A clean_type() 0 11 1
A get_html_class() 0 17 3
A process_value() 0 3 1
B to_json() 0 26 2
A set_conditional_logic() 0 5 1
A get_conditional_logic() 0 3 1
A __construct() 12 12 1
A boot() 0 10 1
A admin_enqueue_scripts() 0 1 1
A set_name() 0 13 4
A set_prefix() 0 8 1
A factory() 4 20 3
C parse_conditional_rules() 9 59 13
A admin_hook_styles() 0 3 1
B admin_hook_scripts() 0 26 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Field often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Field, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Carbon_Fields\Field;
4
5
use Carbon_Fields\Datastore\Datastore_Interface;
6
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
7
8
/**
9
 * Base field class.
10
 * Defines the key container methods and their default implementations.
11
 * Implements factory design pattern.
12
 **/
13
class Field {
14
	/**
15
	 * Stores all the field Backbone templates
16
	 *
17
	 * @see factory()
18
	 * @see add_template()
19
	 * @var array
20
	 */
21
	protected $templates = array();
22
23
	/**
24
	 * Globally unique field identificator. Generated randomly
25
	 *
26
	 * @var string
27
	 */
28
	protected $id;
29
30
	/**
31
	 * Stores the initial <kbd>$type</kbd> variable passed to the <code>factory()</code> method
32
	 *
33
	 * @see factory
34
	 * @var string
35
	 */
36
	public $type;
37
38
	/**
39
	 * Field value
40
	 *
41
	 * @var mixed
42
	 */
43
	protected $value;
44
45
	/**
46
	 * Default field value
47
	 *
48
	 * @var mixed
49
	 */
50
	protected $default_value;
51
52
	/**
53
	 * Sanitized field name used as input name attribute during field render
54
	 *
55
	 * @see factory()
56
	 * @see set_name()
57
	 * @var string
58
	 */
59
	protected $name;
60
61
	/**
62
	 * The base field name which is used in the container.
63
	 *
64
	 * @see set_base_name()
65
	 * @var string
66
	 */
67
	protected $base_name;
68
69
	/**
70
	 * Field name used as label during field render
71
	 *
72
	 * @see factory()
73
	 * @see set_label()
74
	 * @var string
75
	 */
76
	protected $label;
77
78
	/**
79
	 * Additional text containing information and guidance for the user
80
	 *
81
	 * @see help_text()
82
	 * @var string
83
	 */
84
	protected $help_text;
85
86
	/**
87
	 * Field DataStore instance to which save, load and delete calls are delegated
88
	 *
89
	 * @see set_datastore()
90
	 * @see get_datastore()
91
	 * @var Datastore_Interface
92
	 */
93
	protected $store;
94
95
	/**
96
	 * The type of the container this field is in
97
	 *
98
	 * @see get_context()
99
	 * @var string
100
	 */
101
	protected $context;
102
103
	/**
104
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
105
	 *
106
	 * @see set_autoload()
107
	 * @var bool
108
	 **/
109
	protected $autoload = false;
110
111
	/**
112
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
113
	 *
114
	 * @see set_lazyload()
115
	 * @var bool
116
	 **/
117
	protected $lazyload = false;
118
119
	/**
120
	 * The width of the field.
121
	 *
122
	 * @see set_width()
123
	 * @var int
124
	 **/
125
	protected $width = 0;
126
127
	/**
128
	 * Custom CSS classes.
129
	 *
130
	 * @see add_class()
131
	 * @var array
132
	 **/
133
	protected $classes = array();
134
135
	/**
136
	 * Whether or not this field is required.
137
	 *
138
	 * @see set_required()
139
	 * @var bool
140
	 **/
141
	protected $required = false;
142
143
	/**
144
	 * Prefix to be prepended to the field name during load, save, delete and <strong>render</strong>
145
	 *
146
	 * @var string
147
	 **/
148
	protected $name_prefix = '_';
149
150
	/**
151
	 * Stores the field conditional logic rules.
152
	 *
153
	 * @var array
154
	 **/
155
	protected $conditional_logic = array();
156
157
	/**
158
	 * Create a new field of type $type and name $name and label $label.
159
	 *
160
	 * @param string $type
161
	 * @param string $name lower case and underscore-delimited
162
	 * @param string $label (optional) Automatically generated from $name if not present
163
	 * @return object $field
164
	 **/
165 14
	public static function factory( $type, $name, $label = null ) {
166
		// backward compatibility: `file` type used to be called `attachment`
167 14
		if ( $type === 'attachment' ) {
168
			$type = 'file';
169
		}
170
171 14
		$type = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $type ) ) );
172
173 14
		$class = __NAMESPACE__ . '\\' . $type . '_Field';
174
175 14 View Code Duplication
		if ( ! class_exists( $class ) ) {
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...
176 4
			Incorrect_Syntax_Exception::raise( 'Unknown field "' . $type . '".' );
177 1
			$class = __NAMESPACE__ . '\\Broken_Field';
178 1
		}
179
180 11
		$field = new $class( $name, $label );
181 10
		$field->type = $type;
182
183 10
		return $field;
184
	}
185
186
	/**
187
	 * An alias of factory().
188
	 *
189
	 * @see Field::factory()
190
	 **/
191 14
	public static function make( $type, $name, $label = null ) {
192 14
		return self::factory( $type, $name, $label );
193
	}
194
195
	/**
196
	 * Create a field from a certain type with the specified label.
197
	 * @param string $name  Field name
198
	 * @param string $label Field label
199
	 */
200 11 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...
201 11
		$this->set_name( $name );
202 10
		$this->set_label( $label );
203 10
		$this->set_base_name( $name );
204
205
		// Pick random ID
206 10
		$random_string = md5( mt_rand() . $this->get_name() . $this->get_label() );
207 10
		$random_string = substr( $random_string, 0, 5 ); // 5 chars should be enough
208 10
		$this->id = 'carbon-' . $random_string;
209
210 10
		$this->init();
211 10
	}
212
213
	/**
214
	 * Boot the field once the container is attached.
215
	 **/
216
	public function boot() {
217
		$this->admin_init();
218
219
		$this->add_template( $this->get_type(), array( $this, 'template' ) );
220
221
		add_action( 'admin_footer', array( get_class(), 'admin_hook_scripts' ), 5 );
222
		add_action( 'admin_footer', array( get_class(), 'admin_hook_styles' ), 5 );
223
224
		add_action( 'admin_footer', array( get_class( $this ), 'admin_enqueue_scripts' ), 5 );
225
	}
226
227
	/**
228
	 * Perform instance initialization after calling setup()
229
	 **/
230
	public function init() {}
231
232
	/**
233
	 * Instance initialization when in the admin area.
234
	 * Called during field boot.
235
	 **/
236
	public function admin_init() {}
237
238
	/**
239
	 * Enqueue admin scripts.
240
	 * Called once per field type.
241
	 **/
242
	public static function admin_enqueue_scripts() {}
243
244
	/**
245
	 * Prints the main Underscore template
246
	 **/
247
	public function template() { }
248
249
	/**
250
	 * Returns all the Backbone templates
251
	 *
252
	 * @return array
253
	 **/
254
	public function get_templates() {
255
		return $this->templates;
256
	}
257
258
	/**
259
	 * Adds a new Backbone template
260
	 **/
261
	public function add_template( $name, $callback ) {
262
		$this->templates[ $name ] = $callback;
263
	}
264
265
	/**
266
	 * Delegate load to the field DataStore instance
267
	 **/
268
	public function load() {
269
		$this->store->load( $this );
270
271
		if ( $this->get_value() === false ) {
272
			$this->set_value( $this->default_value );
273
		}
274
	}
275
276
	/**
277
	 * Delegate save to the field DataStore instance
278
	 **/
279
	public function save() {
280
		return $this->store->save( $this );
281
	}
282
283
	/**
284
	 * Delegate delete to the field DataStore instance
285
	 **/
286
	public function delete() {
287
		return $this->store->delete( $this );
288
	}
289
290
	/**
291
	 * Load the field value from an input array based on it's name
292
	 *
293
	 * @param array $input (optional) Array of field names and values. Defaults to $_POST
294
	 **/
295
	public function set_value_from_input( $input = null ) {
296
		if ( is_null( $input ) ) {
297
			$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...
298
		}
299
300
		if ( ! isset( $input[ $this->name ] ) ) {
301
			$this->set_value( null );
302
		} else {
303
			$this->set_value( stripslashes_deep( $input[ $this->name ] ) );
304
		}
305
	}
306
307
	/**
308
	 * Assign DataStore instance for use during load, save and delete
309
	 *
310
	 * @param object $store
311
	 * @return object $this
312
	 **/
313
	public function set_datastore( Datastore_Interface $store ) {
314
		$this->store = $store;
315
		return $this;
316
	}
317
318
	/**
319
	 * Return the DataStore instance used by the field
320
	 *
321
	 * @return object $store
322
	 **/
323
	public function get_datastore() {
324
		return $this->store;
325
	}
326
327
	/**
328
	 * Assign the type of the container this field is in
329
	 *
330
	 * @param string
331
	 * @return object $this
332
	 **/
333
	public function set_context( $context ) {
334
		$this->context = $context;
335
		return $this;
336
	}
337
338
	/**
339
	 * Return the type of the container this field is in
340
	 *
341
	 * @return string
342
	 **/
343
	public function get_context() {
344
		return $this->context;
345
	}
346
347
	/**
348
	 * Directly modify the field value
349
	 *
350
	 * @param mixed $value
351
	 **/
352
	public function set_value( $value ) {
353
		$this->value = $value;
354
	}
355
356
	/**
357
	 * Set default field value
358
	 *
359
	 * @param mixed $default_value
360
	 **/
361
	public function set_default_value( $default_value ) {
362
		$this->default_value = $default_value;
363
		return $this;
364
	}
365
366
	/**
367
	 * Get default field value
368
	 *
369
	 * @return mixed
370
	 **/
371
	public function get_default_value() {
372
		return $this->default_value;
373
	}
374
375
	/**
376
	 * Return the field value
377
	 *
378
	 * @return mixed
379
	 **/
380
	public function get_value() {
381
		return $this->value;
382
	}
383
384
	/**
385
	 * Set field name.
386
	 * Use only if you are completely aware of what you are doing.
387
	 *
388
	 * @param string $name Field name, either sanitized or not
389
	 **/
390
	public function set_name( $name ) {
391
		$name = preg_replace( '~\s+~', '_', mb_strtolower( $name ) );
392
393
		if ( empty( $name ) ) {
394
			Incorrect_Syntax_Exception::raise( 'Field name can\'t be empty' );
395
		}
396
397
		if ( $this->name_prefix && strpos( $name, $this->name_prefix ) !== 0 ) {
398
			$name = $this->name_prefix . $name;
399
		}
400
401
		$this->name = $name;
402
	}
403
404
	/**
405
	 * Return the field name
406
	 *
407
	 * @return string
408
	 **/
409
	public function get_name() {
410
		return $this->name;
411
	}
412
413
	/**
414
	 * Set field base name as defined in the container.
415
	 **/
416
	public function set_base_name( $name ) {
417
		$this->base_name = $name;
418
	}
419
420
	/**
421
	 * Return the field base name.
422
	 *
423
	 * @return string
424
	 **/
425
	public function get_base_name() {
426
		return $this->base_name;
427
	}
428
429
	/**
430
	 * Set field name prefix. Calling this method will update the current field
431
	 * name and the conditional logic fields.
432
	 *
433
	 * @param string $prefix
434
	 * @return object $this
435
	 **/
436
	public function set_prefix( $prefix ) {
437
		$escaped_prefix = preg_quote( $this->name_prefix, '~' );
438
		$this->name = preg_replace( '~^' . $escaped_prefix . '~', '', $this->name );
439
		$this->name_prefix = $prefix;
440
		$this->name = $this->name_prefix . $this->name;
441
442
		return $this;
443
	}
444
445
	/**
446
	 * Set field label.
447
	 *
448
	 * @param string $label If null, the label will be generated from the field name
449
	 **/
450
	public function set_label( $label ) {
451
		// Try to guess field label from it's name
452 View Code Duplication
		if ( is_null( $label ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
453
			// remove the leading underscore(if it's there)
454
			$label = preg_replace( '~^_~', '', $this->name );
455
456
			// remove the leading "crb_"(if it's there)
457
			$label = preg_replace( '~^crb_~', '', $label );
458
459
			// split the name into words and make them capitalized
460
			$label = mb_convert_case( str_replace( '_', ' ', $label ), MB_CASE_TITLE );
461
		}
462
463
		$this->label = $label;
464
	}
465
466
	/**
467
	 * Return field label.
468
	 *
469
	 * @return string
470
	 **/
471
	public function get_label() {
472
		return $this->label;
473
	}
474
475
	/**
476
	 * Set additional text to be displayed during field render,
477
	 * containing information and guidance for the user
478
	 *
479
	 * @return object $this
480
	 **/
481
	public function set_help_text( $help_text ) {
482
		$this->help_text = $help_text;
483
		return $this;
484
	}
485
486
	/**
487
	 * Alias for set_help_text()
488
	 *
489
	 * @see set_help_text()
490
	 * @return object $this
491
	 **/
492
	public function help_text( $help_text ) {
493
		return $this->set_help_text( $help_text );
494
	}
495
496
	/**
497
	 * Return the field help text
498
	 *
499
	 * @return object $this
500
	 **/
501
	public function get_help_text() {
502
		return $this->help_text;
503
	}
504
505
	/**
506
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
507
	 *
508
	 * @param bool $autoload
509
	 * @return object $this
510
	 **/
511
	public function set_autoload( $autoload ) {
512
		$this->autoload = $autoload;
513
		return $this;
514
	}
515
516
	/**
517
	 * Return whether or not this value should be auto loaded.
518
	 *
519
	 * @return bool
520
	 **/
521
	public function get_autoload() {
522
		return $this->autoload;
523
	}
524
525
	/**
526
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
527
	 *
528
	 * @param bool $lazyload
529
	 * @return object $this
530
	 **/
531
	public function set_lazyload( $lazyload ) {
532
		$this->lazyload = $lazyload;
533
		return $this;
534
	}
535
536
	/**
537
	 * Return whether or not this field should be lazyloaded.
538
	 *
539
	 * @return bool
540
	 **/
541
	public function get_lazyload() {
542
		return $this->lazyload;
543
	}
544
545
	/**
546
	 * Set the field width.
547
	 *
548
	 * @param int $width
549
	 * @return object $this
550
	 **/
551
	public function set_width( $width ) {
552
		$this->width = (int) $width;
553
		return $this;
554
	}
555
556
	/**
557
	 * Get the field width.
558
	 *
559
	 * @return int $width
560
	 **/
561
	public function get_width() {
562
		return $this->width;
563
	}
564
565
	/**
566
	 *  Add custom CSS class to the field html container.
567
	 *
568
	 * @param string|array $classes
569
	 * @return object $this
570
	 **/
571
	public function add_class( $classes ) {
572
		if ( ! is_array( $classes ) ) {
573
			$classes = array_values( array_filter( explode( ' ', $classes ) ) );
574
		}
575
576
		$this->classes = array_map( 'sanitize_html_class', $classes );
577
		return $this;
578
	}
579
580
	/**
581
	 * Get the field custom CSS classes.
582
	 *
583
	 * @return array
584
	 **/
585
	public function get_classes() {
586
		return $this->classes;
587
	}
588
589
	/**
590
	 * Whether this field is mandatory for the user
591
	 *
592
	 * @param bool $required
593
	 * @return object $this
594
	 **/
595
	public function set_required( $required ) {
596
		$this->required = $required;
597
		return $this;
598
	}
599
600
	/**
601
	 * HTML id attribute getter.
602
	 * @return string
603
	 */
604 1
	public function get_id() {
605 1
		return $this->id;
606
	}
607
608
	/**
609
	 * HTML id attribute setter
610
	 * @param string $id
611
	 */
612 1
	public function set_id( $id ) {
613 1
		$this->id = $id;
614 1
	}
615
616
	/**
617
	 * Return whether this field is mandatory for the user
618
	 *
619
	 * @return bool
620
	 **/
621
	public function is_required() {
622
		return $this->required;
623
	}
624
625
	/**
626
	 * Returns the type of the field based on the class.
627
	 * The class is stripped by the "CarbonFields" prefix.
628
	 * Also the "Field" suffix is removed.
629
	 * Then underscores and backslashes are removed.
630
	 *
631
	 * @return string
632
	 */
633
	public function get_type() {
634
		$class = get_class( $this );
635
636
		return $this->clean_type( $class );
637
	}
638
639
	/**
640
	 * Cleans up an object class for usage as HTML class
641
	 *
642
	 * @return string
643
	 */
644
	protected function clean_type( $type ) {
645
		$remove = array(
646
			'_',
647
			'\\',
648
			'CarbonFields',
649
			'Field',
650
		);
651
		$clean_class = str_replace( $remove, '', $type );
652
653
		return $clean_class;
654
	}
655
656
	/**
657
	 * Return an array of html classes to be used for the field container
658
	 *
659
	 * @return array
660
	 */
661
	public function get_html_class() {
662
		$html_classes = array();
663
664
		$object_class = get_class( $this );
665
		$html_classes[] = $this->get_type();
666
667
		$parent_class = $object_class;
668
		while ( $parent_class = get_parent_class( $parent_class ) ) {
669
			$clean_class = $this->clean_type( $parent_class );
670
671
			if ( $clean_class ) {
672
				$html_classes[] = $clean_class;
673
			}
674
		}
675
676
		return $html_classes;
677
	}
678
679
	/**
680
	 * Allows the value of a field to be processed after loading.
681
	 * Can be implemented by the extending class if necessary.
682
	 *
683
	 * @return array
684
	 */
685
	public function process_value() {
686
687
	}
688
689
	/**
690
	 * Returns an array that holds the field data, suitable for JSON representation.
691
	 * This data will be available in the Underscore template and the Backbone Model.
692
	 *
693
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
694
	 * @return array
695
	 */
696
	public function to_json( $load ) {
697
		if ( $load ) {
698
			$this->load();
699
		}
700
701
		$this->process_value();
702
703
		$field_data = array(
704
			'id' => $this->get_id(),
705
			'type' => $this->get_type(),
706
			'label' => $this->get_label(),
707
			'name' => $this->get_name(),
708
			'base_name' => $this->get_base_name(),
709
			'value' => $this->get_value(),
710
			'default_value' => $this->get_default_value(),
711
			'help_text' => $this->get_help_text(),
712
			'context' => $this->get_context(),
713
			'required' => $this->is_required(),
714
			'lazyload' => $this->get_lazyload(),
715
			'width' => $this->get_width(),
716
			'classes' => $this->get_classes(),
717
			'conditional_logic' => $this->get_conditional_logic(),
718
		);
719
720
		return $field_data;
721
	}
722
723
	/**
724
	 * Set the field visibility conditional logic.
725
	 *
726
	 * @param array
727
	 */
728 8
	public function set_conditional_logic( $rules ) {
729 8
		$this->conditional_logic = $this->parse_conditional_rules( $rules );
730
731 3
		return $this;
732
	}
733
734
	/**
735
	 * Get the conditional logic rules
736
	 *
737
	 * @return array
738
	 */
739 3
	public function get_conditional_logic() {
740 3
		return $this->conditional_logic;
741
	}
742
743
	/**
744
	 * Validate and parse the conditional logic rules.
745
	 *
746
	 * @param array $rules
747
	 * @return array
748
	 */
749
	protected function parse_conditional_rules( $rules ) {
750
		if ( ! is_array( $rules ) ) {
751
			Incorrect_Syntax_Exception::raise( 'Conditional logic rules argument should be an array.' );
752
		}
753
754
		$allowed_operators = array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN' );
755
		$allowed_relations = array( 'AND', 'OR' );
756
757
		$parsed_rules = array(
758
			'relation' => 'AND',
759
			'rules' => array(),
760
		);
761
762
		foreach ( $rules as $key => $rule ) {
763
			// Check if we have a relation key
764
			if ( $key === 'relation' ) {
765
				$relation = strtoupper( $rule );
766
767 View Code Duplication
				if ( ! in_array( $relation, $allowed_relations ) ) {
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...
768
					Incorrect_Syntax_Exception::raise( 'Invalid relation type ' . $rule . '. ' .
769
					'The rule should be one of the following: "' . implode( '", "', $allowed_relations ) . '"' );
770
				}
771
772
				$parsed_rules['relation'] = $relation;
773
				continue;
774
			}
775
776
			// Check if the rule is valid
777
			if ( ! is_array( $rule ) || empty( $rule['field'] ) ) {
778
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic rule format. ' .
779
				'The rule should be an array with the "field" key set.' );
780
			}
781
782
			// Check the compare operator
783
			if ( empty( $rule['compare'] ) ) {
784
				$rule['compare'] = '=';
785
			}
786 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...
787
				Incorrect_Syntax_Exception::raise( 'Invalid conditional logic compare operator: <code>' .
788
					$rule['compare'] . '</code><br>Allowed operators are: <code>' .
789
				implode( ', ', $allowed_operators ) . '</code>' );
790
			}
791
			if ( $rule['compare'] === 'IN' || $rule['compare'] === 'NOT IN' ) {
792
				if ( ! is_array( $rule['value'] ) ) {
793
					Incorrect_Syntax_Exception::raise( 'Invalid conditional logic value format. ' .
794
					'An array is expected, when using the "' . $rule['compare'] . '" operator.' );
795
				}
796
			}
797
798
			// Check the value
799
			if ( ! isset( $rule['value'] ) ) {
800
				$rule['value'] = '';
801
			}
802
803
			$parsed_rules['rules'][] = $rule;
804
		}
805
806
		return $parsed_rules;
807
	}
808
809
810
	/**
811
	 * Hook administration scripts.
812
	 */
813
	public static function admin_hook_scripts() {
814
		wp_enqueue_media();
815
		wp_enqueue_script( 'carbon-fields', \Carbon_Fields\URL . '/assets/js/fields.js', array( 'carbon-app', 'carbon-containers' ) );
816
		wp_localize_script( 'carbon-fields', 'crbl10n',
817
			array(
818
				'title' => __( 'Files', 'carbon-fields' ),
819
				'geocode_zero_results' => __( 'The address could not be found. ', 'carbon-fields' ),
820
				'geocode_not_successful' => __( 'Geocode was not successful for the following reason: ', 'carbon-fields' ),
821
				'max_num_items_reached' => __( 'Maximum number of items reached (%s items)', 'carbon-fields' ),
822
				'max_num_rows_reached' => __( 'Maximum number of rows reached (%s rows)', 'carbon-fields' ),
823
				'cannot_create_more_rows' => __( 'Cannot create more than %s rows', 'carbon-fields' ),
824
				'enter_name_of_new_sidebar' => __( 'Please enter the name of the new sidebar:', 'carbon-fields' ),
825
				'remove_sidebar_confirmation' => __( 'Are you sure you wish to remove this sidebar?', 'carbon-fields' ),
826
				'add_sidebar' => __( 'Add Sidebar', 'carbon-fields' ),
827
				'complex_no_rows' => __( 'There are no %s yet. Click <a href="#">here</a> to add one.', 'carbon-fields' ),
828
				'complex_add_button' => __( 'Add %s', 'carbon-fields' ),
829
				'complex_min_num_rows_not_reached' => __( 'Minimum number of rows not reached (%d %s)', 'carbon-fields' ),
830
				'message_form_validation_failed' => __( 'Please fill out all fields correctly. ', 'carbon-fields' ),
831
				'message_required_field' => __( 'This field is required. ', 'carbon-fields' ),
832
				'message_choose_option' => __( 'Please choose an option. ', 'carbon-fields' ),
833
				'message_validation_failed_number_min' => __( 'Value must be greater than or equal to %s.', 'carbon-fields' ),
834
				'message_validation_failed_number_max' => __( 'Value must be less than or equal to %s.', 'carbon-fields' ),
835
				'message_validation_failed_number_step' => __( 'Please enter a valid value. The two nearest valid values are %1$s and %2$s.', 'carbon-fields' ),
836
			)
837
		);
838
	}
839
840
	/**
841
	 * Hook administration styles.
842
	 */
843
	public static function admin_hook_styles() {
844
		wp_enqueue_style( 'thickbox' );
845
	}
846
} // END Field
847