Completed
Pull Request — master (#108)
by
unknown
03:24
created

Complex_Field::set_static()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Carbon_Fields\Field;
4
5
use Carbon_Fields\Datastore\Datastore_Interface;
6
use Carbon_Fields\Helper\Helper;
7
use Carbon_Fields\Field\Field;
8
use Carbon_Fields\Field\Group_Field;
9
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
10
11
/**
12
 * Complex field class.
13
 * Allows nested repeaters with multiple field groups to be created.
14
 */
15
class Complex_Field extends Field {
16
	const LAYOUT_GRID = 'grid'; // default
17
	const LAYOUT_LIST = 'list'; // deprecated
18
	const LAYOUT_TABBED = 'tabbed'; // deprecated
19
	const LAYOUT_TABBED_HORIZONTAL = 'tabbed-horizontal';
20
	const LAYOUT_TABBED_VERTICAL = 'tabbed-vertical';
21
22
	protected $fields = array();
23
	protected $values = array();
24
	protected $groups = array();
25
26
	protected $layout = self::LAYOUT_GRID;
27
	public $static = false;
28
	protected $values_min = -1;
29
	protected $values_max = -1;
30
31
	public $labels = array(
32
		'singular_name' => 'Entry',
33
		'plural_name' => 'Entries',
34
	);
35
36
	/**
37
	 * Initialization tasks.
38
	 */
39
	public function init() {
40
		$this->labels = array(
41
			'singular_name' => __( 'Entry', 'carbon-fields' ),
42
			'plural_name' => __( 'Entries', 'carbon-fields' ),
43
		);
44
45
		// Include the complex group Underscore templates
46
		$this->add_template( 'Complex-Group', array( $this, 'template_group' ) );
47
		$this->add_template( 'Complex-Group-Tab-Item', array( $this, 'template_group_tab_item' ) );
48
49
		parent::init();
50
	}
51
52
	/**
53
	 * Add a set/group of fields.
54
	 *
55
	 * @return $this
56
	 */
57
	public function add_fields() {
58
		$argv = func_get_args();
59
		$argc = count( $argv );
60
61
		if ( $argc == 1 ) {
62
			$fields = $argv[0];
63
			$name = '';
64
			$label = null;
65
		} else if ( $argc == 2 ) {
66 View Code Duplication
			if ( is_array( $argv[0] ) ) {
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...
67
				list( $fields, $name ) = $argv;
68
			} else {
69
				list( $name, $fields ) = $argv;
70
			}
71
			$label = null;
72
		} else if ( $argc == 3 ) {
73 View Code Duplication
			if ( is_array( $argv[0] ) ) {
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...
74
				list( $fields, $name, $label ) = $argv;
75
			} else {
76
				list( $name, $label, $fields ) = $argv;
77
			}
78
		}
79
80
		if ( array_key_exists( '_' . $name, $this->groups ) ) {
81
			Incorrect_Syntax_Exception::raise( 'Group with name "' . $name . '" in Complex Field "' . $this->get_label() . '" already exists.' );
0 ignored issues
show
Bug introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
82
		}
83
84
		$group = new Group_Field($name, $label, $fields);
0 ignored issues
show
Bug introduced by
The variable $label does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $fields does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
85
86
		$this->groups[ $group->get_name() ] = $group;
87
88
		return $this;
89
	}
90
91
	/**
92
	 * Set the group label Underscore template.
93
	 *
94
	 * @param  string|callable $template
95
	 * @return $this
96
	 */
97
	public function set_header_template( $template ) {
98
		if ( count($this->groups) === 0 ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
99
			Incorrect_Syntax_Exception::raise( "Can't set group label template. There are no present groups for Complex Field " . $this->get_label() . "." );
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...
100
		}
101
102
		$template = is_callable( $template ) ? call_user_func( $template ) : $template;
103
104
		// Assign the template to the group that was added last
105
		$values = array_values( $this->groups );
106
		$group = end( $values );
107
		$group->set_label_template( $template );
108
109
		// Include the group label Underscore template
110
		$this->add_template( $group->get_group_id(), array( $group, 'template_label' ) );
111
112
		$this->groups[ $group->get_name() ] = $group;
113
114
		return $this;
115
	}
116
117
	/**
118
	 * Retrieve all groups of fields.
119
	 *
120
	 * @return array $fields
121
	 */
122
	public function get_fields() {
123
		$fields = array();
124
125
		foreach ( $this->groups as $group ) {
126
			$group_fields = $group->get_fields();
127
128
			$fields = array_merge( $fields, $group_fields );
129
		}
130
131
		return $fields;
132
	}
133
134
	/**
135
	 * Set the field labels.
136
	 * Currently supported values:
137
	 *  - singular_name - the singular entry label
138
	 *  - plural_name - the plural entries label
139
	 *
140
	 * @param  array $labels Labels
141
	 */
142
	public function setup_labels( $labels ) {
143
		$this->labels = array_merge( $this->labels, $labels );
144
		return $this;
145
	}
146
147
	/**
148
	 * Set the datastore of this field.
149
	 *
150
	 * @param Datastore_Interface $store
151
	 */
152
	public function set_datastore( Datastore_Interface $store ) {
153
		$this->store = $store;
154
155
		foreach ( $this->groups as $group ) {
156
			$group->set_datastore( $this->store );
157
		}
158
	}
159
160
	/**
161
	 * Load the field value from an input array based on it's name.
162
	 *
163
	 * @param array $input (optional) Array of field names and values. Defaults to $_POST
164
	 **/
165
	public function set_value_from_input( $input = null ) {
166
		$this->values = array();
167
168
		if ( is_null( $input ) ) {
169
			$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...
170
		}
171
172
		if ( ! isset( $input[ $this->get_name() ] ) ) {
173
			return;
174
		}
175
176
		$input_groups = $input[ $this->get_name() ];
177
		$index = 0;
178
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
179
180
		foreach ( $input_groups as $values ) {
181
			$value_group = array();
182
			if ( ! isset( $values['group'] ) || ! isset( $this->groups[ $values['group'] ] ) ) {
183
				continue;
184
			}
185
186
			$group = $this->groups[ $values['group'] ];
187
			unset( $values['group'] );
188
189
			$group_fields = $group->get_fields();
190
191
			// trim input values to those used by the field
192
			$group_field_names = array_flip( $group->get_field_names() );
193
			$values = array_intersect_key( $values, $group_field_names );
194
195
			foreach ( $group_fields as $field ) {
196
				// set value from the group
197
				$tmp_field = clone $field;
198
				if ( is_a( $tmp_field, __NAMESPACE__ . '\\Complex_Field' ) ) {
199
					if ( ! isset( $values[ $tmp_field->get_name() ] ) ) {
200
						continue; // bail if the complex field is empty
201
					}
202
203
					$new_name = $this->get_name() . $group->get_name() . '-' . $field->get_name() . '_' . $index;
204
					$new_values = array( $new_name => $values[ $tmp_field->get_name() ] );
205
206
					$tmp_field->set_name( $new_name );
207
					$tmp_field->set_value_from_input( $new_values );
208
				} else {
209
					$tmp_field->set_value_from_input( $values );
210
				}
211
212
				// update name to group name
213
				$tmp_field->set_name( $this->get_name() . $group->get_name() . '-' . $field->get_name() . '_' . $index );
214
				$value_group[] = $tmp_field;
215
			}
216
217
			$this->values[] = $value_group;
218
			$index++;
219
		}
220
	}
221
222
	/**
223
	 * Load all groups of fields and their data.
224
	 */
225
	public function load() {
226
		// load existing groups
227
		$this->load_values();
228
	}
229
230
	/**
231
	 * Save all contained groups of fields.
232
	 */
233
	public function save() {
234
		$this->delete();
235
236
		foreach ( $this->values as $value ) {
237
			foreach ( $value as $field ) {
238
				$field->save();
239
			}
240
		}
241
	}
242
243
	/**
244
	 * Delete the values of all contained fields.
245
	 */
246
	public function delete() {
247
		return $this->store->delete_values( $this );
248
	}
249
250
	/**
251
	 * Load and parse the field data.
252
	 */
253
	public function load_values() {
254
		return $this->load_values_from_db();
255
	}
256
257
	/**
258
	 * Load and parse the field data from the database.
259
	 */
260
	public function load_values_from_db() {
261
		$this->values = array();
262
263
		$group_rows = $this->store->load_values( $this );
264
265
		return $this->process_loaded_values( $group_rows );
266
	}
267
268
	/**
269
	 * Load and parse a raw set of field data.
270
	 *
271
	 * @param  array $values Raw data entries
272
	 * @return array 		 Processed data entries
273
	 */
274
	public function load_values_from_array( $values ) {
275
		$this->values = array();
276
277
		$group_rows = array();
278
279
		$meta_key = $this->get_name();
280
281
		foreach ( $values as $key => $value ) {
282
			if ( strpos( $key, $meta_key ) !== 0 ) {
283
				continue;
284
			}
285
286
			$group_rows[] = array(
287
				'field_key' => preg_replace( '~^(' . preg_quote( $this->name, '~' ) . ')_\d+_~', '$1_', $key ),
288
				'field_value' => $value,
289
			);
290
		}
291
292
		return $this->process_loaded_values( $group_rows );
293
	}
294
295
	/**
296
	 * Parse groups of raw field data into the actual field hierarchy.
297
	 *
298
	 * @param  array $group_rows Group rows
299
	 */
300
	public function process_loaded_values( $group_rows ) {
301
		$input_groups = array();
302
303
		// Set default values
304
		$field_names = array();
305
		foreach ( $this->groups as $group ) {
306
			$group_fields = $group->get_fields();
307
			foreach ( $group_fields as $field ) {
308
				$field_names[] = $field->get_name();
309
				$field->set_value( $field->get_default_value() );
310
			}
311
		}
312
313
		if ( empty( $group_rows ) ) {
314
			return;
315
		}
316
317
		// load and parse values and group type
318
		foreach ( $group_rows as $row ) {
319
			if ( ! preg_match( Helper::get_complex_field_regex( $this->name, array_keys( $this->groups ), $field_names ), $row['field_key'], $field_name ) ) {
320
				continue;
321
			}
322
323
			$row['field_value'] = maybe_unserialize( $row['field_value'] );
324
			$input_groups[ $field_name['index'] ]['type'] = $field_name['group'];
325
326
			if ( ! empty( $field_name['trailing'] ) ) {
327
				$input_groups[ $field_name['index'] ][ $field_name['key'] . '_' . $field_name['sub'] . '-' . $field_name['trailing'] ] = $row['field_value'];
328 View Code Duplication
			} else if ( ! empty( $field_name['sub'] ) ) {
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...
329
				$input_groups[ $field_name['index'] ][ $field_name['key'] ][ $field_name['sub'] ] = $row['field_value'];
330
			} else {
331
				$input_groups[ $field_name['index'] ][ $field_name['key'] ] = $row['field_value'];
332
			}
333
		}
334
335
		// create groups list with loaded fields
336
		ksort( $input_groups );
337
338
		foreach ( $input_groups as $index => $values ) {
339
			$value_group = array( 'type' => $values['type'] );
340
			$group_fields = $this->groups[ $values['type'] ]->get_fields();
341
			unset( $values['type'] );
342
343
			foreach ( $group_fields as $field ) {
344
				// set value from the group
345
				$tmp_field = clone $field;
346
347
				if ( is_a( $field, __NAMESPACE__ . '\\Complex_Field' ) ) {
348
					$tmp_field->load_values_from_array( $values );
349
				} else {
350
					$tmp_field->set_value_from_input( $values );
351
				}
352
353
				$value_group[] = $tmp_field;
354
			}
355
356
			$this->values[] = $value_group;
357
		}
358
	}
359
360
	/**
361
	 * Retrieve the field values.
362
	 * @return array
363
	 */
364
	public function get_values() {
365
		return $this->values;
366
	}
367
368
	/**
369
	 * Generate and set the field prefix.
370
	 * @param string $prefix
371
	 */
372
	public function set_prefix( $prefix ) {
373
		parent::set_prefix( $prefix );
374
375
		foreach ( $this->groups as $group ) {
376
			$group->set_prefix( $prefix );
377
		}
378
	}
379
380
	/**
381
	 * Returns an array that holds the field data, suitable for JSON representation.
382
	 * This data will be available in the Underscore template and the Backbone Model.
383
	 *
384
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
385
	 * @return array
386
	 */
387
	public function to_json( $load ) {
388
		$complex_data = parent::to_json( $load );
389
390
		$groups_data = array();
391
		$values_data = array();
392
393
		foreach ( $this->groups as $group ) {
394
			$groups_data[] = $group->to_json( false );
395
		}
396
397
		foreach ( $this->values as $fields ) {
398
			$group = $this->get_group_by_name( $fields['type'] );
399
			unset( $fields['type'] );
400
401
			$data = array(
402
				'name' => $group->get_name(),
403
				'label' => $group->get_label(),
404
				'group_id' => $group->get_group_id(),
405
				'static' => $this->static,
406
				'fields' => array(),
407
			);
408
409
			foreach ( $fields as $index => $field ) {
410
				$data['fields'][] = $field->to_json( false );
411
			}
412
413
			$values_data[] = $data;
414
		}
415
416
		$complex_data = array_merge( $complex_data, array(
417
			'layout' => $this->layout,
418
			'static' => $this->static,
419
			'labels' => $this->labels,
420
			'min' => $this->static ? count( $groups_data ) : $this->get_min(),
421
			'max' => $this->static ? count( $groups_data ) : $this->get_max(),
422
			'multiple_groups' => count( $groups_data ) > 1,
423
			'groups' => $groups_data,
424
			'value' => $values_data,
425
		) );
426
427
		return $complex_data;
428
	}
429
430
	/**
431
	 * The main Underscore template.
432
	 */
433
	public function template() {
434
		?>
435
		<div class="carbon-subcontainer carbon-grid {{ multiple_groups ? 'multiple-groups' : '' }}">
436
			<div class="carbon-empty-row">
437
				{{{ crbl10n.complex_no_rows.replace('%s', labels.plural_name) }}}
438
			</div>
439
440
			<div class="groups-wrapper layout-{{ layout }}">
441
				<# if (layout === '<?php echo self::LAYOUT_TABBED_HORIZONTAL ?>' || layout === '<?php echo self::LAYOUT_TABBED_VERTICAL ?>' ) { #>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not 'self'
Loading history...
442
					<div class="group-tabs-nav-holder">
443
						<ul class="group-tabs-nav"></ul>
444
445
						<div class="carbon-actions">
446
							<div class="carbon-button">
447
								<a href="#" class="button" data-group="{{{ multiple_groups ? '' : groups[0].name }}}">
448
									+
449
								</a>
450
451
								<# if (multiple_groups) { #>
452
									<ul>
453
										<# _.each(groups, function(group) { #>
454
											<li><a href="#" data-group="{{{ group.name }}}">{{{ group.label }}}</a></li>
455
										<# }); #>
456
									</ul>
457
								<# } #>
458
							</div>
459
						</div>
460
					</div><!-- /.group-tabs-nav-holder -->
461
				<# } #>
462
463
				<div class="carbon-groups-holder"></div>
464
				<div class="clear"></div>
465
			</div>
466
467
			<div class="carbon-actions">
468
				<div class="carbon-button">
469
					<a href="#" class="button" data-group="{{{ multiple_groups ? '' : groups[0].name }}}">
470
						{{{ crbl10n.complex_add_button.replace('%s', labels.singular_name) }}}
471
						{{{ multiple_groups ? '&#8681;' : '' }}}
472
					</a>
473
474
					<# if (multiple_groups) { #>
475
						<ul>
476
							<# _.each(groups, function(group) { #>
477
								<li><a href="#" data-group="{{{ group.name }}}">{{{ group.label }}}</a></li>
478
							<# }); #>
479
						</ul>
480
					<# } #>
481
				</div>
482
			</div>
483
		</div>
484
		<?php
485
	}
486
487
	/**
488
	 * The Underscore template for the complex field group.
489
	 */
490
	public function template_group() {
491
		?>
492
		<div id="carbon-{{{ complex_name }}}-complex-container" class="carbon-row carbon-group-row {{ static ? 'static' : '' }}" data-group-id="{{ id }}">
493
			<input type="hidden" name="{{{ complex_name + '[' + index + ']' }}}[group]" value="{{ name }}" />
494
495
			<div class="carbon-drag-handle">
496
				<span class="group-number">{{{ order + 1 }}}</span><span class="group-name">{{{ label_template || label }}}</span>
497
			</div>
498
499
			<div class="carbon-group-actions">
500
				<a class="carbon-btn-collapse" href="#" title="<?php esc_attr_e( 'Collapse/Expand', 'carbon_fields' ); ?>">
501
					<?php _e( 'Collapse/Expand', 'carbon_fields' ); ?>
502
				</a>
503
504
				<# if (!static) { #>
505
					<a class="carbon-btn-duplicate" href="#" title="<?php esc_attr_e( 'Clone', 'carbon_fields' ); ?>">
506
						<?php _e( 'Clone', 'carbon_fields' ); ?>
507
					</a>
508
509
					<a class="carbon-btn-remove" href="#" title="<?php esc_attr_e( 'Remove', 'carbon_fields' ); ?>">
510
						<?php _e( 'Remove', 'carbon_fields' ); ?>
511
					</a>
512
				<# } #>
513
			</div>
514
515
			<div class="fields-container">
516
				<# _.each(fields, function(field) { #>
517
					<div class="carbon-row carbon-subrow subrow-{{{ field.type }}} {{{ field.classes.join(' ') }}}">
518
						<label for="{{{ complex_id + '-' + field.id + '-' + index }}}">
519
							{{ field.label }}
520
521
							<# if (field.required) { #>
522
								 <span class="carbon-required">*</span>
523
							<# } #>
524
						</label>
525
526
						<div class="field-holder {{{ complex_id + '-' + field.id + '-' + index }}}"></div>
527
528
						<# if (field.help_text) { #>
529
							<em class="help-text">
530
								{{{ field.help_text }}}
531
							</em>
532
						<# } #>
533
534
						<em class="carbon-error"></em>
535
					</div>
536
				<# }) #>
537
			</div>
538
		</div>
539
		<?php
540
	}
541
542
	 /**
543
	 * The Underscore template for the group item tab.
544
	 */
545
	public function template_group_tab_item() {
546
		?>
547
		<li class="group-tab-item" data-group-id="{{ id }}">
548
			<a href="#">
549
				<span class="group-handle"></span>
550
				
551
				<# if (label_template || label) { #>
552
					<span class="group-name">{{{ label_template || label }}}</span>
553
				<# } #>
554
				<span class="group-number">{{{ order + 1 }}}</span>
555
				<span class="dashicons dashicons-warning carbon-complex-group-error-badge" ></span>
556
			</a>
557
		</li>
558
		<?php
559
	}
560
561
	/**
562
	 * Modify the layout of this field.
563
	 *
564
	 * @param string $layout
565
	 * @return Complex_Field
566
	 */
567
	public function set_layout( $layout ) {
568
		$available_layouts = array(
569
			self::LAYOUT_GRID,
570
			self::LAYOUT_TABBED_HORIZONTAL,
571
			self::LAYOUT_TABBED_VERTICAL,
572
			self::LAYOUT_LIST,
573
		);
574
575
		if ( $layout === self::LAYOUT_TABBED ) {
576
			// The library used to provide just one kind of tabs -- horizontal ones. Later vertical tabs were added.
577
			// So the "tabbed" name was renamed to "tabbed-horizontal" and "tabbed-vertical" layout was introduced.
578
			_doing_it_wrong( __METHOD__, sprintf( __( 'Complex field "%1$s" layout is deprecated, please use "%2$s" or "%3$s" instead.', 'carbon_fields' ), self::LAYOUT_TABBED, self::LAYOUT_TABBED_HORIZONTAL, self::LAYOUT_TABBED_VERTICAL ), null );
579
580
			$layout = self::LAYOUT_TABBED_HORIZONTAL;
581
		}
582
583 View Code Duplication
		if ( ! in_array( $layout,  $available_layouts ) ) {
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...
584
			$error_message = 'Incorrect layout ``' . $layout . '" specified. ' .
585
				'Available layouts: ' . implode( ', ', $available_layouts );
586
587
			Incorrect_Syntax_Exception::raise( $error_message );
588
		}
589
590
		if ( $layout === self::LAYOUT_LIST ) {
591
			_doing_it_wrong( __METHOD__, __( 'Complex field <code>' . self::LAYOUT_LIST . '</code> layout is deprecated, please use <code>set_width()</code> instead.', 'carbon_fields' ), null );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not 'self'
Loading history...
592
		}
593
594
		$this->layout = $layout;
595
596
		return $this;
597
	}
598
599
	/**
600
	 * Set the complex fields to static.
601
	 * If you set the type to static, there will be no options to add or remove any group.
602
	 * Min and max values are going to be ignored.
603
	 *
604
	 * @param string $static
605
	 * @return Complex_Field
606
	 */
607
	public function set_static($static) {
608
		$this->static = $static;
0 ignored issues
show
Documentation Bug introduced by
The property $static was declared of type boolean, but $static 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...
609
		return $this;
610
	}
611
612
	/**
613
	 * Set the minimum number of entries.
614
	 *
615
	 * @param int $min
616
	 * @return Complex_Field
617
	 */
618
	public function set_min( $min ) {
619
		$this->values_min = intval( $min );
620
		return $this;
621
	}
622
623
	/**
624
	 * Get the minimum number of entries.
625
	 *
626
	 * @return int $min
627
	 */
628
	public function get_min() {
629
		return $this->values_min;
630
	}
631
632
	/**
633
	 * Set the maximum number of entries.
634
	 *
635
	 * @param int $max
636
	 * @return Complex_Field
637
	 */
638
	public function set_max( $max ) {
639
		$this->values_max = intval( $max );
640
		return $this;
641
	}
642
643
	/**
644
	 * Get the maximum number of entries.
645
	 *
646
	 * @return int $max
647
	 */
648
	public function get_max() {
649
		return $this->values_max;
650
	}
651
652
	/**
653
	 * Retrieve the groups of this field.
654
	 *
655
	 * @return array
656
	 */
657
	public function get_group_names() {
658
		return array_keys( $this->groups );
659
	}
660
661
	/**
662
	 * Retrieve a group by its name.
663
	 *
664
	 * @param  string $group_name        Group name
665
	 * @return Group_Field $group_object Group object
666
	 */
667
	public function get_group_by_name( $group_name ) {
668
		$group_object = null;
669
670
		foreach ( $this->groups as $group ) {
671
			if ( $group->get_name() == $group_name ) {
672
				$group_object = $group;
673
			}
674
		}
675
676
		return $group_object;
677
	}
678
}
679