Completed
Push — milestone/2_0/react-ui ( a41be9...7fda3d )
by
unknown
03:41
created

Container::attach()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 1
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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