Completed
Pull Request — master (#35)
by
unknown
02:53
created

Complex_Field::set_header_template()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
eloc 9
c 1
b 0
f 1
nc 4
nop 1
dl 0
loc 18
rs 9.4285
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_TABLE = 'table';
17
	const LAYOUT_LIST = 'list';
18
19
	protected $fields = array();
20
	protected $values = array();
21
	protected $groups = array();
22
23
	protected $layout = self::LAYOUT_TABLE;
24
	protected $values_min = -1;
25
	protected $values_max = -1;
26
27
	public $labels = array(
28
		'singular_name' => 'Entry',
29
		'plural_name' => 'Entries',
30
	);
31
32
	/**
33
	 * Initialization tasks
34
	 */
35
	public function init() {
36
		$this->labels = array(
37
			'singular_name' => __( 'Entry', 'carbon_fields' ),
38
			'plural_name' => __( 'Entries', 'carbon_fields' ),
39
		);
40
41
		// Include the complex group Underscore template
42
		$this->add_template( 'Complex-Group', array( $this, 'template_group' ) );
43
44
		parent::init();
45
	}
46
47
	/**
48
	 * Add a set/group of fields.
49
	 *
50
	 * @return $this
51
	 */
52
	public function add_fields() {
53
		$argv = func_get_args();
54
		$argc = count( $argv );
55
56
		if ( $argc == 1 ) {
57
			$fields = $argv[0];
58
			$name = '';
59
			$label = null;
60
		} else if ( $argc == 2 ) {
61 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...
62
				list( $fields, $name ) = $argv;
63
			} else {
64
				list( $name, $fields ) = $argv;
65
			}
66
			$label = null;
67
		} else if ( $argc == 3 ) {
68 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...
69
				list( $fields, $name, $label ) = $argv;
70
			} else {
71
				list( $name, $label, $fields ) = $argv;
72
			}
73
		}
74
75
		if ( array_key_exists( '_' . $name, $this->groups ) ) {
76
			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...
77
		}
78
79
		$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...
80
81
		$this->groups[ $group->get_name() ] = $group;
82
83
		return $this;
84
	}
85
86
	/**
87
	 * Set the group label Underscore template.
88
	 *
89
	 * @param  string|callable $template
90
	 * @return $this
91
	 */
92
	public function set_header_template( $template ) {
93
		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...
94
			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...
95
		}
96
97
		$template = is_callable( $template ) ? call_user_func( $template ) : $template;
98
99
		// Assign the template to the group that was added last
100
		$group = end( array_values( $this->groups ) );
101
		$group->set_label_template( $template );
102
103
		// Include the group label Underscore template
104
		$this->add_template( $group->get_group_id(), array( $group, 'template_label' ) );
105
106
		$this->groups[ $group->get_name() ] = $group;
107
108
		return $this;
109
	}
110
111
	/**
112
	 * Retrieve all groups of fields.
113
	 *
114
	 * @return array $fields
115
	 */
116
	public function get_fields() {
117
		$fields = array();
118
119
		foreach ( $this->groups as $group ) {
120
			$group_fields = $group->get_fields();
121
122
			$fields = array_merge( $fields, $group_fields );
123
		}
124
125
		return $fields;
126
	}
127
128
	/**
129
	 * Set the field labels.
130
	 * Currently supported values:
131
	 *  - singular_name - the singular entry label
132
	 *  - plural_name - the plural entries label
133
	 *
134
	 * @param  array $labels Labels
135
	 */
136
	public function setup_labels( $labels ) {
137
		$this->labels = array_merge( $this->labels, $labels );
138
		return $this;
139
	}
140
141
	/**
142
	 * Set the datastore of this field.
143
	 *
144
	 * @param Datastore_Interface $store
145
	 */
146
	public function set_datastore( Datastore_Interface $store ) {
147
		$this->store = $store;
148
149
		foreach ( $this->groups as $group ) {
150
			$group->set_datastore( $this->store );
151
		}
152
	}
153
154
	/**
155
	 * Load the field value from an input array based on it's name
156
	 *
157
	 * @param array $input (optional) Array of field names and values. Defaults to $_POST
158
	 **/
159
	public function set_value_from_input( $input = null ) {
160
		$this->values = array();
161
162
		if ( is_null( $input ) ) {
163
			$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...
164
		}
165
166
		if ( ! isset( $input[ $this->get_name() ] ) ) {
167
			return;
168
		}
169
170
		$input_groups = $input[ $this->get_name() ];
171
		$index = 0;
172
173
		foreach ( $input_groups as $values ) {
174
			$value_group = array();
175
			if ( ! isset( $values['group'] ) || ! isset( $this->groups[ $values['group'] ] ) ) {
176
				continue;
177
			}
178
179
			$group = $this->groups[ $values['group'] ];
180
			unset( $values['group'] );
181
182
			$group_fields = $group->get_fields();
183
184
			// trim input values to those used by the field
185
			$group_field_names = array_flip( $group->get_field_names() );
186
			$values = array_intersect_key( $values, $group_field_names );
187
188
			// check if group is empty
189
			if ( count( array_filter( $values, array( $this, 'array_filter_remove_empty_values' ) ) ) == 0 && ! in_array( '0', $values ) ) {
190
				continue;
191
			}
192
193
			foreach ( $group_fields as $field ) {
194
				// set value from the group
195
				$tmp_field = clone $field;
196
				if ( is_a( $tmp_field, __NAMESPACE__ . '\\Complex_Field' ) ) {
197
					if ( ! isset( $values[ $tmp_field->get_name() ] ) ) {
198
						continue; // bail if the complex field is empty
199
					}
200
201
					$new_name = $this->get_name() . $group->get_name() . '-' . $field->get_name() . '_' . $index;
202
					$new_values = array( $new_name => $values[ $tmp_field->get_name() ] );
203
204
					$tmp_field->set_name( $new_name );
205
					$tmp_field->set_value_from_input( $new_values );
206
				} else {
207
					$tmp_field->set_value_from_input( $values );
208
				}
209
210
				// update name to group name
211
				$tmp_field->set_name( $this->get_name() . $group->get_name() . '-' . $field->get_name() . '_' . $index );
212
				$value_group[] = $tmp_field;
213
			}
214
215
			$this->values[] = $value_group;
216
			$index++;
217
		}
218
	}
219
220
	/**
221
	 * Recursive callback function for array_filter()
222
	 *
223
	 * Checks if the given value is an array and calls itself recursively
224
	 * Otherwise, works as usual
225
	 */
226
	public function array_filter_remove_empty_values( $value ) {
227
		if ( is_array( $value ) ) {
228
			return array_filter( $value, array( $this, 'array_filter_remove_empty_values' ) );
229
		}
230
231
		if ( ! empty( $value ) ) {
232
			return true;
233
		}
234
	}
235
236
	/**
237
	 * Load all groups of fields and their data.
238
	 */
239
	public function load() {
240
		// load existing groups
241
		$this->load_values();
242
	}
243
244
	/**
245
	 * Save all contained groups of fields.
246
	 */
247
	public function save() {
248
		$this->delete();
249
250
		foreach ( $this->values as $value ) {
251
			foreach ( $value as $field ) {
252
				$field->save();
253
			}
254
		}
255
	}
256
257
	/**
258
	 * Delete the values of all contained fields.
259
	 */
260
	public function delete() {
261
		return $this->store->delete_values( $this );
262
	}
263
264
	/**
265
	 * Load and parse the field data
266
	 */
267
	public function load_values() {
268
		return $this->load_values_from_db();
269
	}
270
271
	/**
272
	 * Load and parse the field data from the database.
273
	 */
274
	public function load_values_from_db() {
275
		$this->values = array();
276
277
		$group_rows = $this->store->load_values( $this );
278
279
		return $this->process_loaded_values( $group_rows );
280
	}
281
282
	/**
283
	 * Load and parse a raw set of field data.
284
	 *
285
	 * @param  array $values Raw data entries
286
	 * @return array 		 Processed data entries
287
	 */
288
	public function load_values_from_array( $values ) {
289
		$this->values = array();
290
291
		$group_rows = array();
292
293
		$meta_key = $this->get_name();
294
295
		foreach ( $values as $key => $value ) {
296
			if ( strpos( $key, $meta_key ) !== 0 ) {
297
				continue;
298
			}
299
300
			$group_rows[] = array(
301
				'field_key' => preg_replace( '~^(' . preg_quote( $this->name, '~' ) . ')_\d+_~', '$1_', $key ),
302
				'field_value' => $value,
303
			);
304
		}
305
306
		return $this->process_loaded_values( $group_rows );
307
	}
308
309
	/**
310
	 * Parse groups of raw field data into the actual field hierarchy.
311
	 *
312
	 * @param  array $group_rows Group rows
313
	 */
314
	public function process_loaded_values( $group_rows ) {
315
		$input_groups = array();
316
317
		// Set default values
318
		$field_names = array();
319
		foreach ( $this->groups as $group ) {
320
			$group_fields = $group->get_fields();
321
			foreach ( $group_fields as $field ) {
322
				$field_names[] = $field->get_name();
323
				$field->set_value( $field->get_default_value() );
324
			}
325
		}
326
327
		if ( empty( $group_rows ) ) {
328
			return;
329
		}
330
331
		// load and parse values and group type
332
		foreach ( $group_rows as $row ) {
333
			if ( ! preg_match( Helper::get_complex_field_regex( $this->name, array_keys( $this->groups ), $field_names ), $row['field_key'], $field_name ) ) {
334
				continue;
335
			}
336
337
			$row['field_value'] = maybe_unserialize( $row['field_value'] );
338
			$input_groups[ $field_name['index'] ]['type'] = $field_name['group'];
339
340
			if ( ! empty( $field_name['trailing'] ) ) {
341
				$input_groups[ $field_name['index'] ][ $field_name['key'] . '_' . $field_name['sub'] . '-' . $field_name['trailing'] ] = $row['field_value'];
342 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...
343
				$input_groups[ $field_name['index'] ][ $field_name['key'] ][ $field_name['sub'] ] = $row['field_value'];
344
			} else {
345
				$input_groups[ $field_name['index'] ][ $field_name['key'] ] = $row['field_value'];
346
			}
347
		}
348
349
		// create groups list with loaded fields
350
		ksort( $input_groups );
351
352
		foreach ( $input_groups as $index => $values ) {
353
			$value_group = array( 'type' => $values['type'] );
354
			$group_fields = $this->groups[ $values['type'] ]->get_fields();
355
			unset( $values['type'] );
356
357
			foreach ( $group_fields as $field ) {
358
				// set value from the group
359
				$tmp_field = clone $field;
360
361
				if ( is_a( $field, __NAMESPACE__ . '\\Complex_Field' ) ) {
362
					$tmp_field->load_values_from_array( $values );
363
				} else {
364
					$tmp_field->set_value_from_input( $values );
365
				}
366
367
				$value_group[] = $tmp_field;
368
			}
369
370
			$this->values[] = $value_group;
371
		}
372
	}
373
374
	/**
375
	 * Retrieve the field values
376
	 * @return array
377
	 */
378
	public function get_values() {
379
		return $this->values;
380
	}
381
382
	/**
383
	 * Generate and set the field prefix.
384
	 * @param string $prefix
385
	 */
386
	public function set_prefix( $prefix ) {
387
		parent::set_prefix( $prefix );
388
389
		foreach ( $this->groups as $group ) {
390
			$group->set_prefix( $prefix );
391
		}
392
	}
393
394
	/**
395
	 * Returns an array that holds the field data, suitable for JSON representation.
396
	 * This data will be available in the Underscore template and the Backbone Model.
397
	 *
398
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
399
	 * @return array
400
	 */
401
	public function to_json( $load ) {
402
		$complex_data = parent::to_json( $load );
403
404
		$groups_data = array();
405
		$values_data = array();
406
407
		foreach ( $this->groups as $group ) {
408
			$groups_data[] = $group->to_json( false );
409
		}
410
411
		foreach ( $this->values as $fields ) {
412
			$group = $this->get_group_by_name( $fields['type'] );
413
			unset( $fields['type'] );
414
415
			$data = array(
416
				'name' => $group->get_name(),
417
				'label' => $group->get_label(),
418
				'group_id' => $group->get_group_id(),
419
				'fields' => array(),
420
			);
421
422
			foreach ( $fields as $index => $field ) {
423
				$data['fields'][] = $field->to_json( false );
424
			}
425
426
			$values_data[] = $data;
427
		}
428
429
		$complex_data = array_merge( $complex_data, array(
430
			'layout' => $this->layout,
431
			'labels' => $this->labels,
432
			'min' => $this->get_min(),
433
			'max' => $this->get_max(),
434
			'multiple_groups' => count( $groups_data ) > 1,
435
			'groups' => $groups_data,
436
			'value' => $values_data,
437
		) );
438
439
		return $complex_data;
440
	}
441
442
	/**
443
	 * The main Underscore template
444
	 */
445
	public function template() {
446
		?>
447
		<div class="carbon-subcontainer carbon-grid {{ multiple_groups ? 'multiple-groups' : '' }}">
448
	
449
			<div class="carbon-empty-row">
450
				{{{ crbl10n.complex_no_rows.replace('%s', labels.plural_name) }}}
451
			</div>
452
453
			<div class="carbon-groups-holder layout-{{ layout }}"></div>
454
455
			<div class="carbon-actions">
456
				<div class="carbon-button">
457
					<a href="#" class="button" data-group="{{{ multiple_groups ? '' : groups[0].name }}}">
458
						{{{ crbl10n.complex_add_button.replace('%s', labels.singular_name) }}}
459
						{{{ multiple_groups ? '&#8681;' : '' }}}
460
					</a>
461
462
					<# if (multiple_groups) { #>
463
						<ul>
464
							<# _.each(groups, function(group) { #>
465
								<li><a href="#" data-group="{{{ group.name }}}">{{{ group.label }}}</a></li>
466
							<# }); #>
467
						</ul>
468
					<# } #>
469
				</div>
470
			</div>
471
		</div>
472
		<?php
473
	}
474
475
	/**
476
	 * The Underscore template for a complex field group
477
	 */
478
	public function template_group() {
479
		?>
480
		<div id="carbon-{{{ complex_name }}}-complex-container" class="carbon-row carbon-group-row" data-group-id="{{ id }}">
481
			<input type="hidden" name="{{{ complex_name + '[' + index + ']' }}}[group]" value="{{ name }}" />
482
483
			<div class="carbon-drag-handle">
484
				<span class="group-number">{{{ order + 1 }}}</span><span class="group-name">{{{ label_template || label }}}</span>
485
			</div>
486
			<div class="carbon-group-actions">
487
				<a class="carbon-btn-collapse" href="#" title="<?php esc_attr_e( 'Collapse/Expand', 'carbon_fields' ); ?>"><?php _e( 'Collapse/Expand', 'carbon_fields' ); ?></a>
488
				<a class="carbon-btn-duplicate" href="#" title="<?php esc_attr_e( 'Clone', 'carbon_fields' ); ?>"><?php _e( 'Clone', 'carbon_fields' ); ?></a>
489
				<a class="carbon-btn-remove" href="#" title="<?php esc_attr_e( 'Remove', 'carbon_fields' ); ?>"><?php _e( 'Remove', 'carbon_fields' ); ?></a>
490
			</div>
491
492
			<div class="fields-container">
493
				<# _.each(fields, function(field) { #>
494
					<div class="carbon-row carbon-subrow subrow-{{{ field.type }}} {{{ field.classes.join(' ') }}}">
495
						<label for="{{{ complex_id + '-' + field.id + '-' + index }}}">
496
							{{ field.label }}
497
498
							<# if (field.required) { #>
499
								 <span class="carbon-required">*</span>
500
							<# } #>
501
						</label>
502
503
						<div class="field-holder {{{ complex_id + '-' + field.id + '-' + index }}}"></div>
504
505
						<# if (field.help_text) { #>
506
							<em class="help-text">
507
								{{{ field.help_text }}}
508
							</em>
509
						<# } #>
510
511
						<em class="carbon-error"></em>
512
					</div>
513
				<# }) #>
514
			</div>
515
		</div>
516
		<?php
517
	}
518
519
	/**
520
	 * Modify the layout of this field.
521
	 * Deprecated in favor of set_width().
522
	 *
523
	 * @deprecated
524
	 *
525
	 * @param string $layout
526
	 */
527
	public function set_layout( $layout ) {
528
		_doing_it_wrong( __METHOD__, __( 'Complex field layouts are deprecated, please use <code>set_width()</code> instead.', 'carbon_fields' ), null );
529
530
		if ( ! in_array( $layout, array( self::LAYOUT_TABLE, self::LAYOUT_LIST ) ) ) {
531
			Incorrect_Syntax_Exception::raise( 'Incorrect layout specifier. Available values are "<code>' . self::LAYOUT_TABLE . '</code>" and "<code>' . self::LAYOUT_LIST . '</code>"' );
532
		}
533
534
		$this->layout = $layout;
535
536
		return $this;
537
	}
538
539
	/**
540
	 * Set the minimum number of entries.
541
	 *
542
	 * @param int $min
543
	 */
544
	public function set_min( $min ) {
545
		$this->values_min = intval( $min );
546
		return $this;
547
	}
548
549
	/**
550
	 * Get the minimum number of entries.
551
	 *
552
	 * @return int $min
553
	 */
554
	public function get_min() {
555
		return $this->values_min;
556
	}
557
558
	/**
559
	 * Set the maximum number of entries.
560
	 *
561
	 * @param int $max
562
	 */
563
	public function set_max( $max ) {
564
		$this->values_max = intval( $max );
565
		return $this;
566
	}
567
568
	/**
569
	 * Get the maximum number of entries.
570
	 *
571
	 * @return int $max
572
	 */
573
	public function get_max() {
574
		return $this->values_max;
575
	}
576
577
	/**
578
	 * Retrieve the groups of this field.
579
	 *
580
	 * @return array
581
	 */
582
	public function get_group_names() {
583
		return array_keys( $this->groups );
584
	}
585
586
	/**
587
	 * Retrieve a group by its name
588
	 * @param  string $group_name        Group name
589
	 * @return Group_Field $group_object Group object
590
	 */
591
	public function get_group_by_name( $group_name ) {
592
		$group_object = null;
593
594
		foreach ( $this->groups as $group ) {
595
			if ( $group->get_name() == $group_name ) {
596
				$group_object = $group;
597
			}
598
		}
599
600
		return $group_object;
601
	}
602
}
603