Completed
Push — master ( fd0450...c69bde )
by
unknown
04:15
created

Complex_Field::delete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
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
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
173
174
		foreach ( $input_groups as $values ) {
175
			$value_group = array();
176
			if ( ! isset( $values['group'] ) || ! isset( $this->groups[ $values['group'] ] ) ) {
177
				continue;
178
			}
179
180
			$group = $this->groups[ $values['group'] ];
181
			unset( $values['group'] );
182
183
			$group_fields = $group->get_fields();
184
185
			// trim input values to those used by the field
186
			$group_field_names = array_flip( $group->get_field_names() );
187
			$values = array_intersect_key( $values, $group_field_names );
188
189
			foreach ( $group_fields as $field ) {
190
				// set value from the group
191
				$tmp_field = clone $field;
192
				if ( is_a( $tmp_field, __NAMESPACE__ . '\\Complex_Field' ) ) {
193
					if ( ! isset( $values[ $tmp_field->get_name() ] ) ) {
194
						continue; // bail if the complex field is empty
195
					}
196
197
					$new_name = $this->get_name() . $group->get_name() . '-' . $field->get_name() . '_' . $index;
198
					$new_values = array( $new_name => $values[ $tmp_field->get_name() ] );
199
200
					$tmp_field->set_name( $new_name );
201
					$tmp_field->set_value_from_input( $new_values );
202
				} else {
203
					$tmp_field->set_value_from_input( $values );
204
				}
205
206
				// update name to group name
207
				$tmp_field->set_name( $this->get_name() . $group->get_name() . '-' . $field->get_name() . '_' . $index );
208
				$value_group[] = $tmp_field;
209
			}
210
211
			$this->values[] = $value_group;
212
			$index++;
213
		}
214
	}
215
216
	/**
217
	 * Load all groups of fields and their data.
218
	 */
219
	public function load() {
220
		// load existing groups
221
		$this->load_values();
222
	}
223
224
	/**
225
	 * Save all contained groups of fields.
226
	 */
227
	public function save() {
228
		$this->delete();
229
230
		foreach ( $this->values as $value ) {
231
			foreach ( $value as $field ) {
232
				$field->save();
233
			}
234
		}
235
	}
236
237
	/**
238
	 * Delete the values of all contained fields.
239
	 */
240
	public function delete() {
241
		return $this->store->delete_values( $this );
242
	}
243
244
	/**
245
	 * Load and parse the field data
246
	 */
247
	public function load_values() {
248
		return $this->load_values_from_db();
249
	}
250
251
	/**
252
	 * Load and parse the field data from the database.
253
	 */
254
	public function load_values_from_db() {
255
		$this->values = array();
256
257
		$group_rows = $this->store->load_values( $this );
258
259
		return $this->process_loaded_values( $group_rows );
260
	}
261
262
	/**
263
	 * Load and parse a raw set of field data.
264
	 *
265
	 * @param  array $values Raw data entries
266
	 * @return array 		 Processed data entries
267
	 */
268
	public function load_values_from_array( $values ) {
269
		$this->values = array();
270
271
		$group_rows = array();
272
273
		$meta_key = $this->get_name();
274
275
		foreach ( $values as $key => $value ) {
276
			if ( strpos( $key, $meta_key ) !== 0 ) {
277
				continue;
278
			}
279
280
			$group_rows[] = array(
281
				'field_key' => preg_replace( '~^(' . preg_quote( $this->name, '~' ) . ')_\d+_~', '$1_', $key ),
282
				'field_value' => $value,
283
			);
284
		}
285
286
		return $this->process_loaded_values( $group_rows );
287
	}
288
289
	/**
290
	 * Parse groups of raw field data into the actual field hierarchy.
291
	 *
292
	 * @param  array $group_rows Group rows
293
	 */
294
	public function process_loaded_values( $group_rows ) {
295
		$input_groups = array();
296
297
		// Set default values
298
		$field_names = array();
299
		foreach ( $this->groups as $group ) {
300
			$group_fields = $group->get_fields();
301
			foreach ( $group_fields as $field ) {
302
				$field_names[] = $field->get_name();
303
				$field->set_value( $field->get_default_value() );
304
			}
305
		}
306
307
		if ( empty( $group_rows ) ) {
308
			return;
309
		}
310
311
		// load and parse values and group type
312
		foreach ( $group_rows as $row ) {
313
			if ( ! preg_match( Helper::get_complex_field_regex( $this->name, array_keys( $this->groups ), $field_names ), $row['field_key'], $field_name ) ) {
314
				continue;
315
			}
316
317
			$row['field_value'] = maybe_unserialize( $row['field_value'] );
318
			$input_groups[ $field_name['index'] ]['type'] = $field_name['group'];
319
320
			if ( ! empty( $field_name['trailing'] ) ) {
321
				$input_groups[ $field_name['index'] ][ $field_name['key'] . '_' . $field_name['sub'] . '-' . $field_name['trailing'] ] = $row['field_value'];
322 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...
323
				$input_groups[ $field_name['index'] ][ $field_name['key'] ][ $field_name['sub'] ] = $row['field_value'];
324
			} else {
325
				$input_groups[ $field_name['index'] ][ $field_name['key'] ] = $row['field_value'];
326
			}
327
		}
328
329
		// create groups list with loaded fields
330
		ksort( $input_groups );
331
332
		foreach ( $input_groups as $index => $values ) {
333
			$value_group = array( 'type' => $values['type'] );
334
			$group_fields = $this->groups[ $values['type'] ]->get_fields();
335
			unset( $values['type'] );
336
337
			foreach ( $group_fields as $field ) {
338
				// set value from the group
339
				$tmp_field = clone $field;
340
341
				if ( is_a( $field, __NAMESPACE__ . '\\Complex_Field' ) ) {
342
					$tmp_field->load_values_from_array( $values );
343
				} else {
344
					$tmp_field->set_value_from_input( $values );
345
				}
346
347
				$value_group[] = $tmp_field;
348
			}
349
350
			$this->values[] = $value_group;
351
		}
352
	}
353
354
	/**
355
	 * Retrieve the field values
356
	 * @return array
357
	 */
358
	public function get_values() {
359
		return $this->values;
360
	}
361
362
	/**
363
	 * Generate and set the field prefix.
364
	 * @param string $prefix
365
	 */
366
	public function set_prefix( $prefix ) {
367
		parent::set_prefix( $prefix );
368
369
		foreach ( $this->groups as $group ) {
370
			$group->set_prefix( $prefix );
371
		}
372
	}
373
374
	/**
375
	 * Returns an array that holds the field data, suitable for JSON representation.
376
	 * This data will be available in the Underscore template and the Backbone Model.
377
	 *
378
	 * @param bool $load  Should the value be loaded from the database or use the value from the current instance.
379
	 * @return array
380
	 */
381
	public function to_json( $load ) {
382
		$complex_data = parent::to_json( $load );
383
384
		$groups_data = array();
385
		$values_data = array();
386
387
		foreach ( $this->groups as $group ) {
388
			$groups_data[] = $group->to_json( false );
389
		}
390
391
		foreach ( $this->values as $fields ) {
392
			$group = $this->get_group_by_name( $fields['type'] );
393
			unset( $fields['type'] );
394
395
			$data = array(
396
				'name' => $group->get_name(),
397
				'label' => $group->get_label(),
398
				'group_id' => $group->get_group_id(),
399
				'fields' => array(),
400
			);
401
402
			foreach ( $fields as $index => $field ) {
403
				$data['fields'][] = $field->to_json( false );
404
			}
405
406
			$values_data[] = $data;
407
		}
408
409
		$complex_data = array_merge( $complex_data, array(
410
			'layout' => $this->layout,
411
			'labels' => $this->labels,
412
			'min' => $this->get_min(),
413
			'max' => $this->get_max(),
414
			'multiple_groups' => count( $groups_data ) > 1,
415
			'groups' => $groups_data,
416
			'value' => $values_data,
417
		) );
418
419
		return $complex_data;
420
	}
421
422
	/**
423
	 * The main Underscore template
424
	 */
425
	public function template() {
426
		?>
427
		<div class="carbon-subcontainer carbon-grid {{ multiple_groups ? 'multiple-groups' : '' }}">
428
	
429
			<div class="carbon-empty-row">
430
				{{{ crbl10n.complex_no_rows.replace('%s', labels.plural_name) }}}
431
			</div>
432
433
			<div class="carbon-groups-holder layout-{{ layout }}"></div>
434
435
			<div class="carbon-actions">
436
				<div class="carbon-button">
437
					<a href="#" class="button" data-group="{{{ multiple_groups ? '' : groups[0].name }}}">
438
						{{{ crbl10n.complex_add_button.replace('%s', labels.singular_name) }}}
439
						{{{ multiple_groups ? '&#8681;' : '' }}}
440
					</a>
441
442
					<# if (multiple_groups) { #>
443
						<ul>
444
							<# _.each(groups, function(group) { #>
445
								<li><a href="#" data-group="{{{ group.name }}}">{{{ group.label }}}</a></li>
446
							<# }); #>
447
						</ul>
448
					<# } #>
449
				</div>
450
			</div>
451
		</div>
452
		<?php
453
	}
454
455
	/**
456
	 * The Underscore template for a complex field group
457
	 */
458
	public function template_group() {
459
		?>
460
		<div id="carbon-{{{ complex_name }}}-complex-container" class="carbon-row carbon-group-row" data-group-id="{{ id }}">
461
			<input type="hidden" name="{{{ complex_name + '[' + index + ']' }}}[group]" value="{{ name }}" />
462
463
			<div class="carbon-drag-handle">
464
				<span class="group-number">{{{ order + 1 }}}</span><span class="group-name">{{{ label_template || label }}}</span>
465
			</div>
466
			<div class="carbon-group-actions">
467
				<a class="carbon-btn-collapse" href="#" title="<?php esc_attr_e( 'Collapse/Expand', 'carbon-fields' ); ?>"><?php _e( 'Collapse/Expand', 'carbon-fields' ); ?></a>
468
				<a class="carbon-btn-duplicate" href="#" title="<?php esc_attr_e( 'Clone', 'carbon-fields' ); ?>"><?php _e( 'Clone', 'carbon-fields' ); ?></a>
469
				<a class="carbon-btn-remove" href="#" title="<?php esc_attr_e( 'Remove', 'carbon-fields' ); ?>"><?php _e( 'Remove', 'carbon-fields' ); ?></a>
470
			</div>
471
472
			<div class="fields-container">
473
				<# _.each(fields, function(field) { #>
474
					<div class="carbon-row carbon-subrow subrow-{{{ field.type }}} {{{ field.classes.join(' ') }}}">
475
						<label for="{{{ complex_id + '-' + field.id + '-' + index }}}">
476
							{{ field.label }}
477
478
							<# if (field.required) { #>
479
								 <span class="carbon-required">*</span>
480
							<# } #>
481
						</label>
482
483
						<div class="field-holder {{{ complex_id + '-' + field.id + '-' + index }}}"></div>
484
485
						<# if (field.help_text) { #>
486
							<em class="help-text">
487
								{{{ field.help_text }}}
488
							</em>
489
						<# } #>
490
491
						<em class="carbon-error"></em>
492
					</div>
493
				<# }) #>
494
			</div>
495
		</div>
496
		<?php
497
	}
498
499
	/**
500
	 * Modify the layout of this field.
501
	 * Deprecated in favor of set_width().
502
	 *
503
	 * @deprecated
504
	 *
505
	 * @param string $layout
506
	 */
507
	public function set_layout( $layout ) {
508
		_doing_it_wrong( __METHOD__, __( 'Complex field layouts are deprecated, please use <code>set_width()</code> instead.', 'carbon-fields' ), null );
509
510
		if ( ! in_array( $layout, array( self::LAYOUT_TABLE, self::LAYOUT_LIST ) ) ) {
511
			Incorrect_Syntax_Exception::raise( 'Incorrect layout specifier. Available values are "<code>' . self::LAYOUT_TABLE . '</code>" and "<code>' . self::LAYOUT_LIST . '</code>"' );
512
		}
513
514
		$this->layout = $layout;
515
516
		return $this;
517
	}
518
519
	/**
520
	 * Set the minimum number of entries.
521
	 *
522
	 * @param int $min
523
	 */
524
	public function set_min( $min ) {
525
		$this->values_min = intval( $min );
526
		return $this;
527
	}
528
529
	/**
530
	 * Get the minimum number of entries.
531
	 *
532
	 * @return int $min
533
	 */
534
	public function get_min() {
535
		return $this->values_min;
536
	}
537
538
	/**
539
	 * Set the maximum number of entries.
540
	 *
541
	 * @param int $max
542
	 */
543
	public function set_max( $max ) {
544
		$this->values_max = intval( $max );
545
		return $this;
546
	}
547
548
	/**
549
	 * Get the maximum number of entries.
550
	 *
551
	 * @return int $max
552
	 */
553
	public function get_max() {
554
		return $this->values_max;
555
	}
556
557
	/**
558
	 * Retrieve the groups of this field.
559
	 *
560
	 * @return array
561
	 */
562
	public function get_group_names() {
563
		return array_keys( $this->groups );
564
	}
565
566
	/**
567
	 * Retrieve a group by its name
568
	 * @param  string $group_name        Group name
569
	 * @return Group_Field $group_object Group object
570
	 */
571
	public function get_group_by_name( $group_name ) {
572
		$group_object = null;
573
574
		foreach ( $this->groups as $group ) {
575
			if ( $group->get_name() == $group_name ) {
576
				$group_object = $group;
577
			}
578
		}
579
580
		return $group_object;
581
	}
582
}
583