Completed
Push — master ( c1d793...05802a )
by Marin
07:13
created

Field::admin_hook_scripts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 23
rs 9.0857
cc 1
eloc 20
nc 1
nop 0
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 {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
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 int
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 Carbon_DataStore
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 pretended 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
	 * Stores the field options (if any)
159
	 *
160
	 * @var string
161
	 **/
162
	protected $options = array();
163
164
	/**
165
	 * Create a new field of type $type and name $name and label $label.
166
	 *
167
	 * @param string $type
168
	 * @param string $name lower case and underscore-delimited
169
	 * @param string $label (optional) Automatically generated from $name if not present
170
	 * @return object $field
171
	 **/
172
	static public function factory( $type, $name, $label=null ) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
introduced by
Expected 1 space between argument "$label" and equals sign; 0 found
Loading history...
introduced by
Expected 1 space between default value and equals sign for argument "$label";
Loading history...
173
		$type = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $type ) ) );
174
175
		$class = __NAMESPACE__ . "\\" . $type . '_Field';
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal \\ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
176
177
		if ( ! class_exists( $class ) ) {
178
			throw new Incorrect_Syntax_Exception( 'Unknown field "' . $type . '".' );
179
		}
180
181
		if ( strpos( $name, '-' ) !== false ) {
1 ignored issue
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
182
			throw new Incorrect_Syntax_Exception( 'Forbidden character "-" in name "' . $name . '".' );
183
		}
184
185
		$field = new $class( $name, $label );
186
		$field->type = $type;
187
		$field->add_template( $field->get_type(), array( $field, 'template' ) );
188
189
		return $field;
190
	}
191
192
	/**
193
	 * An alias of factory().
194
	 *
195
	 * @see Field::factory()
196
	 **/
197
	static public function make( $type, $name, $label=null ) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
introduced by
Expected 1 space between argument "$label" and equals sign; 0 found
Loading history...
introduced by
Expected 1 space between default value and equals sign for argument "$label";
Loading history...
198
		return self::factory( $type, $name, $label );
199
	}
200
201
	/**
202
	 * Create a field from a certain type with the specified label.
203
	 * @param string $name  Field name
204
	 * @param string $label Field label
205
	 */
206
	private function __construct( $name, $label ) {
207
		$this->set_name( $name );
208
		$this->set_label( $label );
209
		$this->set_base_name( $name );
210
211
		// Pick random ID
212
		$random_string = md5( mt_rand() . $this->get_name() . $this->get_label() );
213
		$random_string = substr( $random_string, 0, 5 ); // 5 chars should be enough
214
		$this->id = 'carbon-' . $random_string;
0 ignored issues
show
Documentation Bug introduced by
The property $id was declared of type integer, but 'carbon-' . $random_string is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
215
216
		$this->init();
217
		if ( is_admin() ) {
218
			$this->admin_init();
219
		}
220
221
		add_action( 'admin_print_scripts', array( $this, 'admin_hook_scripts' ) );
222
		add_action( 'admin_print_styles', array( $this, 'admin_hook_styles' ) );
223
	}
224
225
	/**
226
	 * Perform instance initialization after calling setup()
227
	 **/
228
	public function init() {}
229
230
	/**
231
	 * Instance initialization when in the admin area. Called during object construction
232
	 **/
233
	public function admin_init() {}
234
235
	/**
236
	 * Enqueue admin scripts.
237
	 * Called once per field type.
238
	 **/
239
	public function admin_enqueue_scripts() {}
240
241
	/**
242
	 * Prints the main Underscore template
243
	 **/
244
	public function template() { }
245
246
	/**
247
	 * Returns all the backbone templates
248
	 *
249
	 * @return array
250
	 **/
251
	public function get_templates() {
252
		return $this->templates;
253
	}
254
255
	/**
256
	 * Adds a new backbone template
257
	 **/
258
	public function add_template( $name, $callback ) {
259
		$this->templates[ $name ] = $callback;
260
	}
261
262
	/**
263
	 * Delegate load to the field DataStore instance
264
	 **/
265
	public function load() {
266
		$this->store->load( $this );
267
268
		if ( $this->get_value() === false ) {
1 ignored issue
show
introduced by
Found "=== false". Use Yoda Condition checks, you must
Loading history...
269
			$this->set_value( $this->default_value );
270
		}
271
	}
272
273
	/**
274
	 * Delegate save to the field DataStore instance
275
	 **/
276
	public function save() {
277
		return $this->store->save( $this );
278
	}
279
280
	/**
281
	 * Delegate delete to the field DataStore instance
282
	 **/
283
	public function delete() {
284
		return $this->store->delete( $this );
285
	}
286
287
	/**
288
	 * Load the field value from an input array based on it's name
289
	 *
290
	 * @param array $input (optional) Array of field names and values. Defaults to $_POST
291
	 **/
292
	public function set_value_from_input( $input = null ) {
293
		if ( is_null( $input ) ) {
294
			$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...
295
		}
296
297
		if ( ! isset( $input[ $this->name ] ) ) {
298
			$this->set_value( null );
299
		} else {
300
			$this->set_value( stripslashes_deep( $input[ $this->name ] ) );
301
		}
302
	}
303
304
	/**
305
	 * Assign DataStore instance for use during load, save and delete
306
	 *
307
	 * @param object $store
308
	 * @return object $this
309
	 **/
310
	public function set_datastore( Datastore_Interface $store ) {
311
		$this->store = $store;
0 ignored issues
show
Documentation Bug introduced by
It seems like $store of type object<Carbon_Fields\Dat...re\Datastore_Interface> is incompatible with the declared type object<Carbon_Fields\Field\Carbon_DataStore> of property $store.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
312
		return $this;
313
	}
314
315
	/**
316
	 * Return the DataStore instance used by the field
317
	 *
318
	 * @return object $store
319
	 **/
320
	public function get_datastore() {
321
		return $this->store;
322
	}
323
324
	/**
325
	 * Assign the type of the container this field is in
326
	 *
327
	 * @param string
328
	 * @return object $this
329
	 **/
330
	public function set_context( $context ) {
331
		$this->context = $context;
332
		return $this;
333
	}
334
335
	/**
336
	 * Return the type of the container this field is in
337
	 *
338
	 * @return string
339
	 **/
340
	public function get_context() {
341
		return $this->context;
342
	}
343
344
	/**
345
	 * Directly modify the field value
346
	 *
347
	 * @param mixed $value
348
	 **/
349
	public function set_value( $value ) {
350
		$this->value = $value;
351
	}
352
353
	/**
354
	 * Set default field value
355
	 *
356
	 * @param mixed $value
0 ignored issues
show
Bug introduced by
There is no parameter named $value. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
357
	 **/
358
	public function set_default_value( $default_value ) {
359
		$this->default_value = $default_value;
360
		return $this;
361
	}
362
363
	/**
364
	 * Get default field value
365
	 *
366
	 * @return mixed
367
	 **/
368
	public function get_default_value() {
369
		return $this->default_value;
370
	}
371
372
	/**
373
	 * Return the field value
374
	 *
375
	 * @return mixed
376
	 **/
377
	public function get_value() {
378
		return $this->value;
379
	}
380
381
	/**
382
	 * Set field name.
383
	 * Use only if you are completely aware of what you are doing.
384
	 *
385
	 * @param string $name Field name, either sanitized or not
386
	 **/
387
	public function set_name( $name ) {
388
		$name = preg_replace( '~\s+~', '_', strtolower( $name ) );
389
390
		if ( $this->name_prefix && strpos( $name, $this->name_prefix ) !== 0 ) {
1 ignored issue
show
introduced by
Found "!== 0". Use Yoda Condition checks, you must
Loading history...
391
			$name = $this->name_prefix . $name;
392
		}
393
394
		$this->name = $name;
395
	}
396
397
	/**
398
	 * Return the field name
399
	 *
400
	 * @return string
401
	 **/
402
	public function get_name() {
403
		return $this->name;
404
	}
405
406
	/**
407
	 * Set field base name as defined in the container.
408
	 **/
409
	public function set_base_name( $name ) {
410
		$this->base_name = $name;
411
	}
412
413
	/**
414
	 * Return the field base name.
415
	 *
416
	 * @return string
417
	 **/
418
	public function get_base_name() {
419
		return $this->base_name;
420
	}
421
422
	/**
423
	 * Set field name prefix. Calling this method will update the current field name and the conditional logic fields.
424
	 *
425
	 * @param string $prefix
426
	 * @return object $this
427
	 **/
428
	public function set_prefix( $prefix ) {
429
		$this->name = preg_replace( '~^' . preg_quote( $this->name_prefix, '~' ) . '~', '', $this->name );
430
		$this->name_prefix = $prefix;
431
		$this->name = $this->name_prefix . $this->name;
432
433
		return $this;
434
	}
435
436
	/**
437
	 * Set field label.
438
	 *
439
	 * @param string $label If null, the label will be generated from the field name
440
	 **/
441 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...
442
		// Try to guess field label from it's name
443
		if ( is_null( $label ) ) {
444
			// remove the leading underscore(if it's there)
445
			$label = preg_replace( '~^_~', '', $this->name );
446
447
			// remove the leading "crb_"(if it's there)
448
			$label = preg_replace( '~^crb_~', '', $label );
449
450
			// split the name into words and make them capitalized
451
			$label = ucwords( str_replace( '_', ' ', $label ) );
452
		}
453
454
		$this->label = $label;
455
	}
456
457
	/**
458
	 * Return field label.
459
	 * 
460
	 * @return string
461
	 **/
462
	public function get_label() {
463
		return $this->label;
464
	}
465
466
	/**
467
	 * Set additional text to be displayed during field render,
468
	 * containing information and guidance for the user
469
	 *
470
	 * @return object $this
471
	 **/
472
	public function set_help_text( $help_text ) {
473
		$this->help_text = $help_text;
474
		return $this;
475
	}
476
477
	/**
478
	 * Alias for set_help_text()
479
	 *
480
	 * @see set_help_text()
481
	 * @return object $this
482
	 **/
483
	public function help_text( $help_text ) {
484
		return $this->set_help_text( $help_text );
485
	}
486
487
	/**
488
	 * Return the field help text
489
	 *
490
	 * @return object $this
491
	 **/
492
	public function get_help_text() {
493
		return $this->help_text;
494
	}
495
496
	/**
497
	 * Whether or not this value should be auto loaded. Applicable to theme options only.
498
	 *
499
	 * @param bool $autoload
500
	 * @return object $this
501
	 **/
502
	public function set_autoload( $autoload ) {
503
		$this->autoload = $autoload;
504
		return $this;
505
	}
506
507
	/**
508
	 * Return whether or not this value should be auto loaded.
509
	 *
510
	 * @return bool
511
	 **/
512
	public function get_autoload() {
513
		return $this->autoload;
514
	}
515
516
	/**
517
	 * Whether or not this field will be initialized when the field is in the viewport (visible).
518
	 * 
519
	 * @param bool $autoload
0 ignored issues
show
Bug introduced by
There is no parameter named $autoload. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
520
	 * @return object $this
521
	 **/
522
	public function set_lazyload( $lazyload ) {
523
		$this->lazyload = $lazyload;
524
		return $this;
525
	}
526
527
	/**
528
	 * Return whether or not this field should be lazyloaded.
529
	 * 
530
	 * @return bool
531
	 **/
532
	public function get_lazyload() {
533
		return $this->lazyload;
534
	}
535
536
	/**
537
	 * Set the field width.
538
	 * 
539
	 * @param int $width
540
	 * @return object $this
541
	 **/
542
	public function set_width( $width ) {
543
		$this->width = (int) $width;
544
		return $this;
545
	}
546
547
	/**
548
	 * Get the field width.
549
	 * 
550
	 * @return int $width
551
	 **/
552
	public function get_width() {
553
		return $this->width;
554
	}
555
556
	/**
557
	 *  Add custom CSS class to the field html container.
558
	 * 
559
	 * @param string|array $classes
560
	 * @return object $this
561
	 **/
562
	public function add_class( $classes ) {
563
		if ( ! is_array( $classes ) ) {
564
			$classes = array_values( array_filter( explode( ' ', $classes ) ) );
565
		}
566
567
		$this->classes = array_map( 'sanitize_html_class', $classes );
568
		return $this;
569
	}
570
571
	/**
572
	 * Get the field custom CSS classes.
573
	 * 
574
	 * @return array
575
	 **/
576
	public function get_classes() {
577
		return $this->classes;
578
	}
579
580
	/**
581
	 * Whether this field is mandatory for the user
582
	 *
583
	 * @param bool $required
584
	 * @return object $this
585
	 **/
586
	public function set_required( $required ) {
587
		$this->required = $required;
588
		return $this;
589
	}
590
591
	/**
592
	 * HTML id attribute getter.
593
	 * @return string
594
	 */
595
	public function get_id() {
596
		return $this->id;
597
	}
598
599
	/**
600
	 * HTML id attribute setter
601
	 * @param string $id
602
	 */
603
	public function set_id( $id ) {
604
		$this->id = $id;
0 ignored issues
show
Documentation Bug introduced by
The property $id was declared of type integer, but $id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
605
	}
606
607
	/**
608
	 * Return whether this field is mandatory for the user
609
	 *
610
	 * @return bool
611
	 **/
612
	public function is_required() {
613
		return $this->required;
614
	}
615
616
	/**
617
	 * Returns the type of the field based on the class.
618
	 * The class is stripped by the "CarbonFields" prefix. 
619
	 * Also the "Field" suffix is removed. 
620
	 * Then underscores and backslashes are removed.
621
	 *
622
	 * @return string
623
	 */
624
	public function get_type() {
625
		$class = get_class( $this );
626
627
		return $this->clean_type( $class );
628
	}
629
630
	/**
631
	 * Cleans up an object class for usage as HTML class
632
	 *
633
	 * @return string
634
	 */
635
	protected function clean_type( $type ) {
636
		$remove = array(
637
			'_',
638
			'\\',
639
			'CarbonFields',
640
			'Field',
641
		);
642
		$clean_class = str_replace( $remove, '', $type );
643
644
		return $clean_class;
645
	}
646
647
	/**
648
	 * Return an array of html classes to be used for the field container
649
	 *
650
	 * @return array
651
	 */
652
	public function get_html_class() {
653
		$html_classes = array();
654
655
		$object_class = get_class( $this );
656
		$html_classes[] = $this->get_type();
657
658
		$parent_class = $object_class;
659
		while ( $parent_class = get_parent_class( $parent_class ) ) {
660
			$clean_class = $this->clean_type( $parent_class );
661
662
			if ( $clean_class ) {
663
				$html_classes[] = $clean_class;
664
			}
665
		}
666
667
		return $html_classes;
668
	}
669
670
	/**
671
	 * Allows the value of a field to be processed after loading.
672
	 * Can be implemented by the extending class if necessary.
673
	 * 
674
	 * @return array
675
	 */
676
	public function process_value() {
677
678
	}
679
680
	/**
681
	 * Returns an array that holds the field data, suitable for JSON representation.
682
	 * This data will be available in the Underscore template and the Backbone Model.
683
	 * 
684
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
685
	 * @return array
686
	 */
687
	public function to_json( $load ) {
688
		if ( $load ) {
689
			$this->load();
690
		}
691
692
		$this->process_value();
693
694
		$field_data = array(
695
			'id' => $this->get_id(),
696
			'type' => $this->get_type(),
697
			'label' => $this->get_label(),
698
			'name' => $this->get_name(),
699
			'base_name' => $this->get_base_name(),
700
			'value' => $this->get_value(),
701
			'default_value' => $this->get_default_value(),
702
			'help_text' => $this->get_help_text(),
703
			'context' => $this->get_context(),
704
			'required' => $this->is_required(),
705
			'lazyload' => $this->get_lazyload(),
706
			'width' => $this->get_width(),
707
			'classes' => $this->get_classes(),
708
			'conditional_logic' => $this->get_conditional_logic(),
709
		);
710
711
		return $field_data;
712
	}
713
714
	/**
715
	 * Set the field visibility conditional logic.
716
	 *
717
	 * @param array
718
	 */
719
	public function set_conditional_logic( $rules ) {
720
		$this->conditional_logic = $this->parse_conditional_rules( $rules );
721
722
		return $this;
723
	}
724
725
	/**
726
	 * Get the conditional logic rules
727
	 *
728
	 * @return array
729
	 */
730
	protected function get_conditional_logic() {
731
		return $this->conditional_logic;
732
	}
733
734
	/**
735
	 * Validate and parse the conditional logic rules.
736
	 *
737
	 * @param array $rules
738
	 * @return array
739
	 */
740
	protected function parse_conditional_rules( $rules ) {
741
		if ( ! is_array( $rules ) ) {
742
			throw new Incorrect_Syntax_Exception( 'Conditional logic rules argument should be an array.' );
743
		}
744
745
		$parsed_rules = array(
746
			'relation' => 'AND',
747
			'rules' => array(),
748
		);
749
750
		$allowed_operators = array( '=', '!=', '>', '>=', '<', '<=', 'IN', 'NOT IN' );
751
752
		foreach ( $rules as $key => $rule ) {
753
			// Check if we have a relation key
754
			if ( $key === 'relation' ) {
1 ignored issue
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
755
				if ( $rule === 'OR' ) {
1 ignored issue
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
756
					$parsed_rules['relation'] = $rule;
757
				}
758
				continue;
759
			}
760
761
			// Check if the rule is valid
762
			if ( ! is_array( $rule ) || empty( $rule['field'] ) ) {
763
				throw new Incorrect_Syntax_Exception( 'Invalid conditional logic rule format. The rule should be an array with the "field" key set.' );
764
			}
765
766
			// Check the compare oparator
767
			if ( empty( $rule['compare'] ) ) {
768
				$rule['compare'] = '=';
769
			}
770
			if ( ! in_array( $rule['compare'], $allowed_operators ) ) {
771
				throw new Incorrect_Syntax_Exception( 'Invalid conditional logic compare oparator: <code>' . $rule['compare'] . '</code><br>' . 
772
					'Allowed oparators are: <code>' . implode( ', ', $allowed_operators ) . '</code>' );
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...
773
			}
774
			if ( $rule['compare'] === 'IN' || $rule['compare'] === 'NOT IN' ) {
1 ignored issue
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
775
				if ( ! is_array( $rule['value'] ) ) {
776
					throw new Incorrect_Syntax_Exception( 'Invalid conditional logic value format. An array is expected, when using the "' . $rule['compare'] . '" operator.' );
777
				}
778
			}
779
780
			// Check the value
781
			if ( ! isset( $rule['value'] ) ) {
782
				$rule['value'] = '';
783
			}
784
785
			$parsed_rules['rules'][] = $rule;
786
		}
787
788
		return $parsed_rules;
789
	}
790
791
	/**
792
	 * Set the field options
793
	 * Callbacks are supported
794
	 *
795
	 * @param array|callback $options
796
	 */
797
	protected function _set_options( $options ) {
798
		$this->options = (array) $options;
0 ignored issues
show
Documentation Bug introduced by
It seems like (array) $options of type array is incompatible with the declared type string of property $options.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
799
	}
800
801
	/**
802
	 * Add options to the field
803
	 * Callbacks are supported
804
	 *
805
	 * @param array|callback $options
806
	 */
807
	protected function _add_options( $options ) {
808
		$this->options[] = $options;
809
	}
810
811
	/**
812
	 * Check if there are callbacks and populate the options
813
	 */
814
	protected function load_options() {
815
		if ( empty( $this->options ) ) {
816
			return false;
817
		}
818
819
		$options = array();
820
		foreach ( $this->options as $key => $value ) {
0 ignored issues
show
Bug introduced by
The expression $this->options of type string is not traversable.
Loading history...
821
			if ( is_callable( $value ) ) {
822
				$options = $options + (array) call_user_func( $value );
823
			} else if ( is_array( $value ) ) {
824
				$options = $options + $value;
825
			} else {
826
				$options[ $key ] = $value;
827
			}
828
		}
829
830
		$this->options = $options;
0 ignored issues
show
Documentation Bug introduced by
It seems like $options of type array is incompatible with the declared type string of property $options.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
831
	}
832
833
	/**
834
	 * Changes the options array structure. This is needed to keep the array items order when it is JSON encoded.
835
	 *
836
	 * @param array $options
837
	 * @return array
838
	 */
839
	public function parse_options( $options ) {
840
		$parsed = array();
841
842
		foreach ( $options as $key => $value ) {
843
			$parsed[] = array(
844
				'name' => $value,
845
				'value' => $key,
846
			);
847
		}
848
849
		return $parsed;
850
	}
851
852
	/**
853
	 * Hook administration scripts.
854
	 */
855
	public function admin_hook_scripts() {
856
		wp_enqueue_media();
857
		wp_enqueue_script( 'carbon-fields', URL . '/assets/js/fields.js', array( 'carbon-app', 'carbon-containers' ) );
858
		wp_localize_script( 'carbon-fields', 'crbl10n',
859
			array(
860
				'title' => __( 'Files', 'crb' ),
861
				'geocode_zero_results' => __( 'The address could not be found. ', 'crb' ),
862
				'geocode_not_successful' => __( 'Geocode was not successful for the following reason: ', 'crb' ),
863
				'max_num_items_reached' => __( 'Maximum number of items reached (%s items)', 'crb' ),
864
				'max_num_rows_reached' => __( 'Maximum number of rows reached (%s rows)', 'crb' ),
865
				'cannot_create_more_rows' => __( 'Cannot create more than %s rows', 'crb' ),
866
				'enter_name_of_new_sidebar' => __( 'Please enter the name of the new sidebar:', 'crb' ),
867
				'remove_sidebar_confirmation' => __( 'Are you sure you wish to remove this sidebar?', 'crb' ),
868
				'add_sidebar' => __( 'Add Sidebar', 'crb' ),
869
				'complex_no_rows' => __( 'There are no %s yet. Click <a href="#">here</a> to add one.', 'crb' ),
870
				'complex_add_button' => __( 'Add %s', 'crb' ),
871
				'complex_min_num_rows_not_reached' => __( 'Minimum number of rows not reached (%d %s)', 'crb' ),
872
				'message_form_validation_failed' => __( 'Please fill out all fields correctly. ', 'crb' ),
873
				'message_required_field' => __( 'This field is required. ', 'crb' ),
874
				'message_choose_option' => __( 'Please choose an option. ', 'crb' ),
875
			)
876
		);
877
	}
878
879
	/**
880
	 * Hook administration styles.
881
	 */
882
	public function admin_hook_styles() {
883
		wp_enqueue_style( 'thickbox' );
884
	}
885
} // END Field
886