Completed
Push — milestone/2_0/react-ui ( b737dc...fa3453 )
by
unknown
02:59
created

Container::has_default_datastore()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Carbon_Fields\Container;
4
5
use Carbon_Fields\Carbon_Fields;
6
use Carbon_Fields\Helper\Helper;
7
use Carbon_Fields\Field\Field;
8
use Carbon_Fields\Field\Group_Field;
9
use Carbon_Fields\Container\Fulfillable\Fulfillable_Collection;
10
use Carbon_Fields\Datastore\Datastore_Interface;
11
use Carbon_Fields\Datastore\Datastore_Holder_Interface;
12
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
13
14
/**
15
 * Base container class.
16
 * Defines the key container methods and their default implementations.
17
 */
18
abstract class Container implements Datastore_Holder_Interface {
19
	/**
20
	 * Where to put a particular tab -- at the head or the tail. Tail by default
21
	 */
22
	const TABS_TAIL = 1;
23
	const TABS_HEAD = 2;
24
25
	/**
26
	 * Separator signifying field hierarchy relation
27
	 * Used when searching for fields in a specific complex field
28
	 */
29
	const HIERARCHY_FIELD_SEPARATOR = '/';
30
31
	/**
32
	 * Separator signifying complex_field->group relation
33
	 * Used when searching for fields in a specific complex field group
34
	 */
35
	const HIERARCHY_GROUP_SEPARATOR = ':';
36
37
	/**
38
	 * Stores if the container is active on the current page
39
	 *
40
	 * @see activate()
41
	 * @var bool
42
	 */
43
	protected $active = false;
44
45
	/**
46
	 * List of registered unique field names for this container instance
47
	 *
48
	 * @see register_field_name()
49
	 * @var array
50
	 */
51
	protected $registered_field_names = array();
52
53
	/**
54
	 * Tabs available
55
	 */
56
	protected $tabs = array();
57
58
	/**
59
	 * List of default container settings
60
	 *
61
	 * @see init()
62
	 * @var array
63
	 */
64
	public $settings = array();
65
66
	/**
67
	 * Title of the container
68
	 *
69
	 * @var string
70
	 */
71
	public $title = '';
72
73
	/**
74
	 * List of notification messages to be displayed on the front-end
75
	 *
76
	 * @var array
77
	 */
78
	protected $notifications = array();
79
80
	/**
81
	 * List of error messages to be displayed on the front-end
82
	 *
83
	 * @var array
84
	 */
85
	protected $errors = array();
86
87
	/**
88
	 * List of container fields
89
	 *
90
	 * @see add_fields()
91
	 * @var array
92
	 */
93
	protected $fields = array();
94
95
	/**
96
	 * Array of custom CSS classes.
97
	 *
98
	 * @see set_classes()
99
	 * @see get_classes()
100
	 * @var array<string>
101
	 */
102
	protected $classes = array();
103
104
	/**
105
	 * Container datastores. Propagated to all container fields
106
	 *
107
	 * @see set_datastore()
108
	 * @see get_datastore()
109
	 * @var object
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
	 * Fulfillable_Collection to use when checking attachment/saving conditions
124
	 *
125
	 * @var Fulfillable_Collection
126
	 */
127
	protected $condition_collection;
128
129
	/**
130
	 * Translator to use when translating conditions to json
131
	 *
132
	 * @var Carbon_Fields\Container\Fulfillable\Translator\Translator
133
	 */
134
	protected $condition_translator;
135
136
	/**
137
	 * Create a new container of type $type and name $name.
138
	 *
139
	 * @param  string $raw_type
140
	 * @param  string $name      Human-readable name of the container
141
	 * @return object $container
142
	 */
143 8
	public static function factory( $raw_type, $name ) {
144 8
		$normalized_type = Helper::normalize_type( $raw_type );
145 8
		$class = Helper::type_to_class( $normalized_type, __NAMESPACE__, '_Container' );
146
147 8 View Code Duplication
		if ( ! class_exists( $class ) ) {
148 3
			Incorrect_Syntax_Exception::raise( 'Unknown container "' . $raw_type . '".' );
149 1
			$class = __NAMESPACE__ . '\\Broken_Container';
150 1
		}
151
152 6
		$repository = Carbon_Fields::resolve( 'container_repository' );
153 6
		$fulfillable_collection = Carbon_Fields::resolve( 'container_condition_fulfillable_collection' );
1 ignored issue
show
Comprehensibility Naming introduced by
The variable name $fulfillable_collection exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
154 6
		$condition_translator = Carbon_Fields::resolve( 'container_condition_translator_json' );
155 6
		$unique_id = $repository->get_unique_panel_id( $name );
156 6
		$container = new $class( $unique_id, $name, $normalized_type, $fulfillable_collection, $condition_translator );
157 6
		$repository->register_container( $container );
158
159 6
		return $container;
160
	}
161
162
	/**
163
	 * An alias of factory().
164
	 *
165
	 * @see Container::factory()
166
	 */
167
	public static function make( $type, $name ) {
168
		return static::factory( $type, $name );
169
	}
170
171
	/**
172
	 * Create a new container
173
	 *
174
	 * @param string                 $unique_id            Unique id of the container
175
	 * @param string                 $title                title of the container
176
	 * @param string                 $type                 Type of the container
177
	 * @param Fulfillable_Collection $condition_collection
178
	 * @param Carbon_Fields\Container\Fulfillable\Translator\Translator $condition_translator
179
	 */
180 2
	public function __construct( $unique_id, $title, $type, $condition_collection, $condition_translator ) {
181 2
		Carbon_Fields::verify_boot();
182
183 2
		if ( empty( $title ) ) {
184 1
			Incorrect_Syntax_Exception::raise( 'Empty container title is not supported' );
185
		}
186
187 1
		$this->id = $unique_id;
188 1
		$this->title = $title;
189 1
		$this->type = $type;
190 1
		$this->condition_collection = $condition_collection;
191 1
		$this->condition_collection->set_condition_type_list(
192 1
			array_merge( $this->get_condition_types( true ), $this->get_condition_types( false ) ),
193
			true
194 1
		);
195 1
		$this->condition_translator = $condition_translator;
196 1
	}
197
198
	/**
199
	 * Get array of all static condition types
200
	 *
201
	 * @param  boolean       $static
202
	 * @return array<string>
203
	 */
204
	protected function get_condition_types( $static ) {
205
		$group = $static ? 'static' : 'dynamic';
206
		$container_type = Helper::class_to_type( get_class( $this ), '_Container' );
207
208
		$condition_types = array();
209
		$condition_types = apply_filters( 'carbon_fields_' . $container_type . '_container_' . $group . '_condition_types', $condition_types, $container_type, $this );
210
		$condition_types = apply_filters( 'carbon_fields_container_' . $group . '_condition_types', $condition_types, $container_type, $this );
211
212
		return $condition_types;
213
	}
214
215
	/**
216
	 * Return whether the container is active
217
	 */
218
	public function active() {
219
		return $this->active;
220
	}
221
222
	/**
223
	 * Activate the container and trigger an action
224
	 */
225
	protected function activate() {
226
		$this->active = true;
227
		$this->boot();
228
		do_action( 'carbon_fields_container_activated', $this );
229
230
		$fields = $this->get_fields();
231
		foreach ( $fields as $field ) {
232
			$field->activate();
233
		}
234
	}
235
236
	/**
237
	 * Perform instance initialization
238
	 */
239
	abstract public function init();
240
241
	/**
242
	 * Boot the container once it's attached.
243
	 */
244
	protected function boot() {
245
		add_action( 'admin_print_footer_scripts', array( get_class(), 'admin_hook_styles' ), 5 );
246
	}
247
248
	/**
249
	 * Load the value for each field in the container.
250
	 * Could be used internally during container rendering
251
	 */
252
	public function load() {
253
		foreach ( $this->fields as $field ) {
254
			$field->load();
255
		}
256
	}
257
258
	/**
259
	 * Called first as part of the container save procedure.
260
	 * Responsible for checking the request validity and
261
	 * calling the container-specific save() method
262
	 *
263
	 * @see save()
264
	 * @see is_valid_save()
265
	 */
266
	public function _save() {
267
		$param = func_get_args();
268
		if ( call_user_func_array( array( $this, '_is_valid_save' ), $param ) ) {
269
			call_user_func_array( array( $this, 'save' ), $param );
270
		}
271
	}
272
273
	/**
274
	 * Load submitted data and save each field in the container
275
	 *
276
	 * @see is_valid_save()
277
	 */
278
	public function save( $data = null ) {
279
		foreach ( $this->fields as $field ) {
280
			$field->set_value_from_input( stripslashes_deep( $_POST ) );
281
			$field->save();
282
		}
283
	}
284
285
	/**
286
	 * Checks whether the current save request is valid
287
	 *
288
	 * @return bool
289
	 */
290
	final protected function _is_valid_save() {
291
		$params = func_get_args();
292
		$is_valid_save = call_user_func_array( array( $this, 'is_valid_save' ), $params );
293
		return apply_filters( 'carbon_fields_container_is_valid_save', $is_valid_save, $this );
294
	}
295
296
	/**
297
	 * Checks whether the current save request is valid
298
	 *
299
	 * @return bool
300
	 */
301
	abstract protected function is_valid_save();
302
303
	/**
304
	 * Called first as part of the container attachment procedure.
305
	 * Responsible for checking it's OK to attach the container
306
	 * and if it is, calling the container-specific attach() method
307
	 *
308
	 * @see attach()
309
	 * @see is_valid_attach()
310
	 */
311
	public function _attach() {
312
		$param = func_get_args();
313
		if ( $this->is_valid_attach() ) {
314
			call_user_func_array( array( $this, 'attach' ), $param );
315
316
			// Allow containers to activate but not load (useful in cases such as theme options)
317
			if ( $this->should_activate() ) {
318
				$this->activate();
319
			}
320
		}
321
	}
322
323
	/**
324
	 * Attach the container rendering and helping methods
325
	 * to concrete WordPress Action hooks
326
	 */
327
	public function attach() {}
328
329
	/**
330
	 * Perform checks whether the container should be attached during the current request
331
	 *
332
	 * @return bool True if the container is allowed to be attached
333
	 */
334
	final public function is_valid_attach() {
335
		$is_valid_attach = $this->is_valid_attach_for_request();
336
		return apply_filters( 'carbon_fields_container_is_valid_attach', $is_valid_attach, $this );
337
	}
338
339
	/**
340
	 * Get environment array for page request (in admin)
341
	 *
342
	 * @return array
343
	 */
344
	abstract protected function get_environment_for_request();
345
346
	/**
347
	 * Check container attachment rules against current page request (in admin)
348
	 *
349
	 * @return bool
350
	 */
351
	abstract protected function is_valid_attach_for_request();
352
353
	/**
354
	 * Check if conditions pass for request
355
	 *
356
	 * @return bool
357
	 */
358
	protected function static_conditions_pass() {
359
		$environment = $this->get_environment_for_request();
360
		$static_condition_collection = $this->condition_collection->evaluate(
361
			$this->get_condition_types( false ),
362
			true
363
		);
364
		return $static_condition_collection->is_fulfilled( $environment );
365
	}
366
367
	/**
368
	 * Get environment array for object id
369
	 *
370
	 * @param integer $object_id
371
	 * @return array
372
	 */
373
	abstract protected function get_environment_for_object( $object_id );
374
375
	/**
376
	 * Check container attachment rules against object id
377
	 *
378
	 * @param int $object_id
379
	 * @return bool
380
	 */
381
	abstract public function is_valid_attach_for_object( $object_id );
382
383
	/**
384
	 * Check if all conditions pass for object
385
	 *
386
	 * @return bool
387
	 */
388
	protected function all_conditions_pass( $object_id ) {
389
		$environment = $this->get_environment_for_object( $object_id );
390
		return $this->condition_collection->is_fulfilled( $environment );
391
	}
392
393
	/**
394
	 * Whether this container is currently viewed.
395
	 */
396
	public function should_activate() {
397
		return $this->is_valid_attach();
398
	}
399
400
	/**
401
	 * Perform a check whether the current container has fields
402
	 *
403
	 * @return bool
404
	 */
405
	public function has_fields() {
406
		return (bool) $this->fields;
407
	}
408
409
	/**
410
	 * Returns the private container array of fields.
411
	 * Use only if you are completely aware of what you are doing.
412
	 *
413
	 * @return array
414
	 */
415
	public function get_fields() {
416
		return $this->fields;
417
	}
418
419
	/**
420
	 * Return root field from container with specified name
421
	 *
422
	 * @example crb_complex
423
	 *
424
	 * @param string $field_name
425
	 * @return Field
426
	 */
427
	public function get_root_field_by_name( $field_name ) {
428
		$fields = $this->get_fields();
429
		foreach ( $fields as $field ) {
430
			if ( $field->get_base_name() === $field_name ) {
431
				return $field;
432
			}
433
		}
434
		return null;
435
	}
436
437
	/**
438
	 * Get a regex to match field name patterns used to fetch specific fields
439
	 *
440
	 * @return string
441
	 */
442
	protected function get_field_pattern_regex() {
443
		// matches:
444
		// field_name
445
		// field_name[0]
446
		// field_name[0]:group_name
447
		// field_name:group_name
448
		$regex = '/
449
			\A
450
			(?P<field_name>[a-z0-9_]+)
451
			(?:\[(?P<group_index>\d+)\])?
452
			(?:' .  preg_quote( static::HIERARCHY_GROUP_SEPARATOR, '/' ). '(?P<group_name>[a-z0-9_]+))?
453
			\z
454
		/x';
455
		return $regex;
456
	}
457
458
	/**
459
	 * Return field from container with specified name
460
	 *
461
	 * @example crb_complex/text_field
462
	 * @example crb_complex/complex_2
463
	 * @example crb_complex/complex_2:text_group/text_field
464
	 *
465
	 * @param string $field_name Can specify a field inside a complex with a / (slash) separator
466
	 * @return Field
467
	 */
468
	public function get_field_by_name( $field_name ) {
469
		$hierarchy = array_filter( explode( static::HIERARCHY_FIELD_SEPARATOR, $field_name ) );
470
		$field = null;
471
472
		$field_group = $this->get_fields();
473
		$hierarchy_left = $hierarchy;
474
		$field_pattern_regex = $this->get_field_pattern_regex();
475
		$hierarchy_index = array();
476
477
		while ( ! empty( $hierarchy_left ) ) {
478
			$segment = array_shift( $hierarchy_left );
479
			$segment_pieces = array();
480
			if ( ! preg_match( $field_pattern_regex, $segment, $segment_pieces ) ) {
481
				Incorrect_Syntax_Exception::raise( 'Invalid field name pattern used: ' . $field_name );
482
				return null;
483
			}
484
485
			$segment_field_name = $segment_pieces['field_name'];
486
			$segment_group_index = isset( $segment_pieces['group_index'] ) ? $segment_pieces['group_index'] : 0;
487
			$segment_group_name = isset( $segment_pieces['group_name'] ) ? $segment_pieces['group_name'] : Group_Field::DEFAULT_GROUP_NAME;
488
489
			foreach ( $field_group as $f ) {
490
				if ( $f->get_base_name() === $segment_field_name ) {
491
					if ( empty( $hierarchy_left ) ) {
492
						$field = clone $f;
493
						$field->set_hierarchy_index( $hierarchy_index );
494
					} else {
495
						if ( is_a( $f, 'Carbon_Fields\\Field\\Complex_Field' ) ) {
496
							$group = $f->get_group_by_name( $segment_group_name );
497
							if ( ! $group ) {
498
								Incorrect_Syntax_Exception::raise( 'Unknown group name specified when fetching a value inside a complex field: "' . $segment_group_name . '".' );
499
								return null;
500
							}
501
							$field_group = $group->get_fields();
502
							$hierarchy_index[] = $segment_group_index;
503
						} else {
504
							Incorrect_Syntax_Exception::raise( 'Attempted to look for a nested field inside a non-complex field.' );
505
							return null;
506
						}
507
					}
508
					break;
509
				}
510
			}
511
		}
512
513
		return $field;
514
	}
515
516
	/**
517
	 * Perform checks whether there is a field registered with the name $name.
518
	 * If not, the field name is recorded.
519
	 *
520
	 * @param string $name
521
	 * @return boolean
522
	 */
523 View Code Duplication
	protected function register_field_name( $name ) {
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...
524
		if ( in_array( $name, $this->registered_field_names ) ) {
525
			Incorrect_Syntax_Exception::raise( 'Field name "' . $name . '" already registered' );
526
			return false;
527
		}
528
529
		$this->registered_field_names[] = $name;
530
		return true;
531
	}
532
533
	/**
534
	 * Return whether the datastore instance is the default one or has been overriden
535
	 *
536
	 * @return boolean
537
	 */
538 6
	public function has_default_datastore() {
539 6
		return $this->has_default_datastore;
540
	}
541
542
	/**
543
	 * Set datastore instance
544
	 *
545
	 * @param Datastore_Interface $datastore
546
	 * @return object $this
547
	 */
548 6 View Code Duplication
	public function set_datastore( Datastore_Interface $datastore, $set_as_default = false ) {
549 6
		if ( $set_as_default && ! $this->has_default_datastore() ) {
550 1
			return $this; // datastore has been overriden with a custom one - abort changing to a default one
551
		}
552 6
		$this->datastore = $datastore;
553 6
		$this->has_default_datastore = $set_as_default;
554
555 6
		foreach ( $this->fields as $field ) {
556
			$field->set_datastore( $this->get_datastore(), true );
557 6
		}
558 6
		return $this;
559
	}
560
561
	/**
562
	 * Get the DataStore instance
563
	 *
564
	 * @return Datastore_Interface $datastore
565
	 */
566 6
	public function get_datastore() {
567 6
		return $this->datastore;
568
	}
569
570
	/**
571
	 * Return WordPress nonce name used to identify the current container instance
572
	 *
573
	 * @return string
574
	 */
575
	protected function get_nonce_name() {
576
		return 'carbon_fields_container_' . $this->id . '_nonce';
577
	}
578
579
	/**
580
	 * Return WordPress nonce name used to identify the current container instance
581
	 *
582
	 * @return string
583
	 */
584
	protected function get_nonce_value() {
585
		return wp_create_nonce( $this->get_nonce_name() );
586
	}
587
588
	/**
589
	 * Check if the nonce is present in the request and that it is verified
590
	 *
591
	 * @return bool
592
	 */
593
	protected function verified_nonce_in_request() {
594
		$input = stripslashes_deep( $_REQUEST );
595
		$nonce_name = $this->get_nonce_name();
596
		$nonce_value = isset( $input[ $nonce_name ] ) ? $input[ $nonce_name ] : '';
597
		return wp_verify_nonce( $nonce_value, $nonce_name );
598
	}
599
600
	/**
601
	 * Internal function that creates the tab and associates it with particular field set
602
	 *
603
	 * @param string $tab_name
604
	 * @param array $fields
605
	 * @param int $queue_end
606
	 * @return object $this
607
	 */
608
	private function create_tab( $tab_name, $fields, $queue_end = self::TABS_TAIL ) {
609
		if ( isset( $this->tabs[ $tab_name ] ) ) {
610
			Incorrect_Syntax_Exception::raise( "Tab name duplication for $tab_name" );
611
		}
612
613
		if ( $queue_end === static::TABS_TAIL ) {
614
			$this->tabs[ $tab_name ] = array();
615
		} else if ( $queue_end === static::TABS_HEAD ) {
616
			$this->tabs = array_merge(
617
				array( $tab_name => array() ),
618
				$this->tabs
619
			);
620
		}
621
622
		foreach ( $fields as $field ) {
623
			$field_name = $field->get_name();
624
			$this->tabs[ $tab_name ][ $field_name ] = $field;
625
		}
626
627
		$this->settings['tabs'] = $this->get_tabs_json();
628
	}
629
630
	/**
631
	 * Whether the container is tabbed or not
632
	 *
633
	 * @return bool
634
	 */
635
	public function is_tabbed() {
636
		return (bool) $this->tabs;
637
	}
638
639
	/**
640
	 * Retrieve all fields that are not defined under a specific tab
641
	 *
642
	 * @return array
643
	 */
644
	protected function get_untabbed_fields() {
645
		$tabbed_fields_names = array();
646
		foreach ( $this->tabs as $tab_fields ) {
647
			$tabbed_fields_names = array_merge( $tabbed_fields_names, array_keys( $tab_fields ) );
648
		}
649
650
		$all_fields_names = array();
651
		foreach ( $this->fields as $field ) {
652
			$all_fields_names[] = $field->get_name();
653
		}
654
655
		$fields_not_in_tabs = array_diff( $all_fields_names, $tabbed_fields_names );
656
657
		$untabbed_fields = array();
658
		foreach ( $this->fields as $field ) {
659
			if ( in_array( $field->get_name(), $fields_not_in_tabs ) ) {
660
				$untabbed_fields[] = $field;
661
			}
662
		}
663
664
		return $untabbed_fields;
665
	}
666
667
	/**
668
	 * Retrieve all tabs.
669
	 * Create a default tab if there are any untabbed fields.
670
	 *
671
	 * @return array
672
	 */
673
	protected function get_tabs() {
674
		$untabbed_fields = $this->get_untabbed_fields();
675
676
		if ( ! empty( $untabbed_fields ) ) {
677
			$this->create_tab( __( 'General', 'carbon-fields' ), $untabbed_fields, static::TABS_HEAD );
678
		}
679
680
		return $this->tabs;
681
	}
682
683
	/**
684
	 * Build the tabs JSON
685
	 *
686
	 * @return array
687
	 */
688
	protected function get_tabs_json() {
689
		$tabs_json = array();
690
		$tabs = $this->get_tabs();
691
692
		foreach ( $tabs as $tab_name => $fields ) {
693
			foreach ( $fields as $field_name => $field ) {
694
				$tabs_json[ $tab_name ][] = $field_name;
695
			}
696
		}
697
698
		return $tabs_json;
699
	}
700
701
	/**
702
	 * Get custom CSS classes.
703
	 *
704
	 * @return array<string>
705
	 */
706
	public function get_classes() {
707
		return $this->classes;
708
	}
709
710
	/**
711
	 * Set CSS classes that the container should use.
712
	 *
713
	 * @param string|array<string> $classes
714
	 * @return object $this
715
	 */
716
	public function set_classes( $classes ) {
717
		$this->classes = Helper::sanitize_classes( $classes );
718
		return $this;
719
	}
720
721
	/**
722
	 * Returns an array that holds the container data, suitable for JSON representation.
723
	 *
724
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
725
	 * @return array
726
	 */
727
	public function to_json( $load ) {
728
		$conditions = $this->condition_collection->evaluate( $this->get_condition_types( true ), $this->get_environment_for_request(), array( 'CUSTOM' ) );
729
		$conditions = $this->condition_translator->fulfillable_to_foreign( $conditions );
730
731
		$container_data = array(
732
			'id' => $this->id,
733
			'type' => $this->type,
734
			'title' => $this->title,
735
			'classes' => $this->get_classes(),
736
			'settings' => $this->settings,
737
			'conditions' => $conditions,
738
			'fields' => array(),
739
			'nonce' => array(
740
				'name' => $this->get_nonce_name(),
741
				'value' => $this->get_nonce_value(),
742
			),
743
		);
744
745
		$fields = $this->get_fields();
746
		foreach ( $fields as $field ) {
747
			$field_data = $field->to_json( $load );
748
			$container_data['fields'][] = $field_data;
749
		}
750
751
		return $container_data;
752
	}
753
754
	/**
755
	 * Enqueue admin styles
756
	 */
757
	public static function admin_hook_styles() {
758
		wp_enqueue_style( 'carbon-main', \Carbon_Fields\URL . '/assets/dist/carbon.css', array(), \Carbon_Fields\VERSION );
759
	}
760
761
	/**
762
	 * COMMON USAGE METHODS
763
	 */
764
765
	/**
766
	 * Append array of fields to the current fields set. All items of the array
767
	 * must be instances of Field and their names should be unique for all
768
	 * Carbon containers.
769
	 * If a field does not have DataStore already, the container datastore is
770
	 * assigned to them instead.
771
	 *
772
	 * @param array $fields
773
	 * @return object $this
774
	 */
775
	public function add_fields( $fields ) {
776
		foreach ( $fields as $field ) {
777
			if ( ! is_a( $field, 'Carbon_Fields\\Field\\Field' ) ) {
778
				Incorrect_Syntax_Exception::raise( 'Object must be of type Carbon_Fields\\Field\\Field' );
779
				return $this;
780
			}
781
782
			$unique = $this->register_field_name( $field->get_name() );
783
			if ( ! $unique ) {
784
				return $this;
785
			}
786
787
			$field->set_context( $this->type );
788
			if ( ! $field->get_datastore() ) {
789
				$field->set_datastore( $this->get_datastore(), $this->has_default_datastore() );
790
			}
791
		}
792
793
		$this->fields = array_merge( $this->fields, $fields );
794
795
		return $this;
796
	}
797
798
	/**
799
	 * Configuration function for adding tab with fields
800
	 *
801
	 * @param string $tab_name
802
	 * @param array $fields
803
	 * @return object $this
804
	 */
805
	public function add_tab( $tab_name, $fields ) {
806
		$this->add_fields( $fields );
807
		$this->create_tab( $tab_name, $fields );
808
		return $this;
809
	}
810
811
	/**
812
	 * Proxy function to set attachment conditions
813
	 *
814
	 * @see    Fulfillable_Collection::where()
815
	 * @return Container $this
816
	 */
817
	public function where() {
818
		call_user_func_array( array( $this->condition_collection, 'where' ), func_get_args() );
819
		return $this;
820
	}
821
822
	/**
823
	 * Proxy function to set attachment conditions
824
	 *
825
	 * @see    Fulfillable_Collection::or_where()
826
	 * @return Container $this
827
	 */
828
	public function or_where() {
829
		call_user_func_array( array( $this->condition_collection, 'or_where' ), func_get_args() );
830
		return $this;
831
	}
832
}
833