CMB2_Field::_set_field_defaults()   F
last analyzed

Complexity

Conditions 15
Paths 416

Size

Total Lines 95
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 64
CRAP Score 15

Importance

Changes 0
Metric Value
cc 15
eloc 63
nc 416
nop 1
dl 0
loc 95
ccs 64
cts 64
cp 1
crap 15
rs 3.6499
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * CMB2 field objects
4
 *
5
 * @since  1.1.0
6
 *
7
 * @category  WordPress_Plugin
8
 * @package   CMB2
9
 * @author    WebDevStudios
10
 * @license   GPL-2.0+
11
 * @link      http://webdevstudios.com
12
 *
13
 * @method string _id()
14
 * @method string type()
15
 * @method mixed fields()
16
 */
17
class CMB2_Field extends CMB2_Base {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
18
19
	/**
20
	 * The object properties name.
21
	 *
22
	 * @var   string
23
	 * @since 2.2.3
24
	 */
25
	protected $properties_name = 'args';
26
27
	/**
28
	 * Field arguments
29
	 *
30
	 * @var   mixed
31
	 * @since 1.1.0
32
	 */
33
	public $args = array();
34
35
	/**
36
	 * Field group object or false (if no group)
37
	 *
38
	 * @var   mixed
39
	 * @since 1.1.0
40
	 */
41
	public $group = false;
42
43
	/**
44
	 * Field meta value
45
	 *
46
	 * @var   mixed
47
	 * @since 1.1.0
48
	 */
49
	public $value = null;
50
51
	/**
52
	 * Field meta value
53
	 *
54
	 * @var   mixed
55
	 * @since 1.1.0
56
	 */
57
	public $escaped_value = null;
58
59
	/**
60
	 * Grouped Field's current numeric index during the save process
61
	 *
62
	 * @var   mixed
63
	 * @since 2.0.0
64
	 */
65
	public $index = 0;
66
67
	/**
68
	 * Array of field options
69
	 *
70
	 * @var   array
71
	 * @since 2.0.0
72
	 */
73
	protected $field_options = array();
74
75
	/**
76
	 * Array of provided field text strings
77
	 *
78
	 * @var   array
79
	 * @since 2.0.0
80
	 */
81
	protected $strings;
82
83
	/**
84
	 * The field's render context. In most cases, 'edit', but can be 'display'.
85
	 *
86
	 * @var   string
87
	 * @since 2.2.2
88
	 */
89
	public $render_context = 'edit';
90
91
	/**
92
	 * All CMB2_Field callable field arguments.
93
	 * Can be used to determine if a field argument is callable.
94
	 *
95
	 * @var array
96
	 */
97
	public static $callable_fields = array(
98
		'default_cb',
99
		'classes_cb',
100
		'options_cb',
101
		'text_cb',
102
		'label_cb',
103
		'render_row_cb',
104
		'display_cb',
105
		'before_group',
106
		'before_group_row',
107
		'before_row',
108
		'before',
109
		'before_field',
110
		'after_field',
111
		'after',
112
		'after_row',
113
		'after_group_row',
114
		'after_group',
115
	);
116
117
	/**
118
	 * Constructs our field object
119
	 *
120
	 * @since 1.1.0
121
	 * @param array $args Field arguments
122
	 */
123 111
	public function __construct( $args ) {
124
125 111
		if ( ! empty( $args['group_field'] ) ) {
126 4
			$this->group       = $args['group_field'];
127 4
			$this->object_id   = $this->group->object_id;
128 4
			$this->object_type = $this->group->object_type;
129 4
			$this->cmb_id      = $this->group->cmb_id;
130 4
		} else {
131 111
			$this->object_id   = isset( $args['object_id'] ) && '_' !== $args['object_id'] ? $args['object_id'] : 0;
132 111
			$this->object_type = isset( $args['object_type'] ) ? $args['object_type'] : 'post';
133
134 111
			if ( isset( $args['cmb_id'] ) ) {
135 43
				$this->cmb_id = $args['cmb_id'];
136 43
			}
137
		}
138
139 111
		$this->args = $this->_set_field_defaults( $args['field_args'], $args );
0 ignored issues
show
Unused Code introduced by
The call to CMB2_Field::_set_field_defaults() has too many arguments starting with $args.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
140
141 111
		if ( $this->object_id ) {
142 103
			$this->value = $this->get_data();
143 103
		}
144 111
	}
145
146
	/**
147
	 * Non-existent methods fallback to checking for field arguments of the same name
148
	 *
149
	 * @since  1.1.0
150
	 * @param  string $name     Method name
151
	 * @param  array  $arguments Array of passed-in arguments
152
	 * @return mixed             Value of field argument
153
	 */
154 100
	public function __call( $name, $arguments ) {
155 100
		if ( 'string' === $name ) {
156
			return call_user_func_array( array( $this, 'get_string' ), $arguments );
157
		}
158
159 100
		$key = isset( $arguments[0] ) ? $arguments[0] : false;
160 100
		return $this->args( $name, $key );
161
	}
162
163
	/**
164
	 * Retrieves the field id
165
	 *
166
	 * @since  1.1.0
167
	 * @param  boolean $raw Whether to retrieve pre-modidifed id
168
	 * @return string       Field id
169
	 */
170 109
	public function id( $raw = false ) {
171 109
		$id = $raw ? '_id' : 'id';
172 109
		return $this->args( $id );
173
	}
174
175
	/**
176
	 * Get a field argument
177
	 *
178
	 * @since  1.1.0
179
	 * @param  string $key  Argument to check
180
	 * @param  string $_key Sub argument to check
181
	 * @return mixed        Argument value or false if non-existent
182
	 */
183 112
	public function args( $key = '', $_key = '' ) {
184 112
		$arg = $this->_data( 'args', $key );
185
186 112
		if ( in_array( $key, array( 'default', 'default_cb' ), true ) ) {
187
188 1
			$arg = $this->get_default();
189
190 112
		} elseif ( $_key ) {
191
192
			$arg = isset( $arg[ $_key ] ) ? $arg[ $_key ] : false;
193
		}
194
195 112
		return $arg;
196
	}
197
198
	/**
199
	 * Retrieve a portion of a field property
200
	 *
201
	 * @since  1.1.0
202
	 * @param  string $var Field property to check
203
	 * @param  string $key Field property array key to check
204
	 * @return mixed        Queried property value or false
205
	 */
206 112
	public function _data( $var, $key = '' ) {
207 112
		$vars = $this->{$var};
208 112
		if ( $key ) {
209 112
			return array_key_exists( $key, $vars ) ? $vars[ $key ] : false;
210
		}
211 62
		return $vars;
212
	}
213
214
	/**
215
	 * Get Field's value
216
	 *
217
	 * @since  1.1.0
218
	 * @param  string $key If value is an array, is used to get array key->value
219
	 * @return mixed       Field value or false if non-existent
220
	 */
221 47
	public function value( $key = '' ) {
222 47
		return $this->_data( 'value', $key );
223
	}
224
225
	/**
226
	 * Retrieves metadata/option data
227
	 *
228
	 * @since  1.0.1
229
	 * @param  string $field_id Meta key/Option array key
230
	 * @param  array  $args     Override arguments
231
	 * @return mixed            Meta/Option value
232
	 */
233 107
	public function get_data( $field_id = '', $args = array() ) {
234 107
		if ( $field_id ) {
235
			$args['field_id'] = $field_id;
236 107
		} elseif ( $this->group ) {
237
			$args['field_id'] = $this->group->id();
238
		}
239
240 107
		$a = $this->data_args( $args );
241
242
		/**
243
		 * Filter whether to override getting of meta value.
244
		 * Returning a non 'cmb2_field_no_override_val' value
245
		 * will effectively short-circuit the value retrieval.
246
		 *
247
		 * @since 2.0.0
248
		 *
249
		 * @param mixed $value     The value get_metadata() should
250
		 *                         return - a single metadata value,
251
		 *                         or an array of values.
252
		 *
253
		 * @param int   $object_id Object ID.
254
		 *
255
		 * @param array $args {
256
		 *     An array of arguments for retrieving data
257
		 *
258
		 *     @type string $type     The current object type
259
		 *     @type int    $id       The current object ID
260
		 *     @type string $field_id The ID of the field being requested
261
		 *     @type bool   $repeat   Whether current field is repeatable
262
		 *     @type bool   $single   Whether current field is a single database row
263
		 * }
264
		 *
265
		 * @param CMB2_Field object $field This field object
266
		 */
267 107
		$data = apply_filters( 'cmb2_override_meta_value', 'cmb2_field_no_override_val', $this->object_id, $a, $this );
268
269
		/**
270
		 * Filter and parameters are documented for 'cmb2_override_meta_value' filter (above).
271
		 *
272
		 * The dynamic portion of the hook, $field_id, refers to the current
273
		 * field id paramater. Returning a non 'cmb2_field_no_override_val' value
274
		 * will effectively short-circuit the value retrieval.
275
		 *
276
		 * @since 2.0.0
277
		 */
278 107
		$data = apply_filters( "cmb2_override_{$a['field_id']}_meta_value", $data, $this->object_id, $a, $this );
279
280
		// If no override, get value normally
281 107
		if ( 'cmb2_field_no_override_val' === $data ) {
282 104
			$data = 'options-page' === $a['type']
283 104
				? cmb2_options( $a['id'] )->get( $a['field_id'] )
284 104
				: get_metadata( $a['type'], $a['id'], $a['field_id'], ( $a['single'] || $a['repeat'] ) );
285 104
		}
286
287 107
		if ( $this->group ) {
288
289
			$data = is_array( $data ) && isset( $data[ $this->group->index ][ $this->args( '_id' ) ] )
290
				? $data[ $this->group->index ][ $this->args( '_id' ) ]
291
				: false;
292
		}
293
294 107
		return $data;
295
	}
296
297
	/**
298
	 * Updates metadata/option data
299
	 *
300
	 * @since  1.0.1
301
	 * @param  mixed $new_value Value to update data with
302
	 * @param  bool  $single    Whether data is an array (add_metadata)
303
	 */
304 13
	public function update_data( $new_value, $single = true ) {
305 13
		$a = $this->data_args( array(
306
			'single' => $single,
307 13
		) );
308
309
		$a['value'] = $a['repeat'] ? array_values( $new_value ) : $new_value;
310
311
		/**
312
		 * Filter whether to override saving of meta value.
313
		 * Returning a non-null value will effectively short-circuit the function.
314
		 *
315
		 * @since 2.0.0
316
		 *
317
		 * @param null|bool $check  Whether to allow updating metadata for the given type.
318
		 *
319
		 * @param array $args {
320
		 *     Array of data about current field including:
321
		 *
322
		 *     @type string $value    The value to set
323
		 *     @type string $type     The current object type
324
		 *     @type int    $id       The current object ID
325
		 *     @type string $field_id The ID of the field being updated
326
		 *     @type bool   $repeat   Whether current field is repeatable
327
		 *     @type bool   $single   Whether current field is a single database row
328
		 * }
329
		 *
330
		 * @param array $field_args All field arguments
331
		 *
332 13
		 * @param CMB2_Field object $field This field object
333
		 */
334
		$override = apply_filters( 'cmb2_override_meta_save', null, $a, $this->args(), $this );
335
336
		/**
337
		 * Filter and parameters are documented for 'cmb2_override_meta_save' filter (above).
338
		 *
339
		 * The dynamic portion of the hook, $a['field_id'], refers to the current
340
		 * field id paramater. Returning a non-null value
341
		 * will effectively short-circuit the function.
342
		 *
343 13
		 * @since 2.0.0
344
		 */
345
		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_save", $override, $a, $this->args(), $this );
346 13
347 2
		// If override, return that
348
		if ( null !== $override ) {
349
			return $override;
350
		}
351 12
352 5
		// Options page handling (or temp data store)
353
		if ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
354
			return cmb2_options( $a['id'] )->update( $a['field_id'], $a['value'], false, $a['single'] );
355
		}
356 7
357 1
		// Add metadata if not single
358
		if ( ! $a['single'] ) {
359
			return add_metadata( $a['type'], $a['id'], $a['field_id'], $a['value'], false );
360
		}
361 6
362
		// Delete meta if we have an empty array
363
		if ( is_array( $a['value'] ) && empty( $a['value'] ) ) {
364
			return delete_metadata( $a['type'], $a['id'], $a['field_id'], $this->value );
365
		}
366 6
367
		// Update metadata
368
		return update_metadata( $a['type'], $a['id'], $a['field_id'], $a['value'] );
369
	}
370
371
	/**
372
	 * Removes/updates metadata/option data
373
	 *
374
	 * @since  1.0.1
375 3
	 * @param  string $old Old value
376 3
	 */
377
	public function remove_data( $old = '' ) {
378
		$a = $this->data_args( array(
379
			'old' => $old,
380
		) );
381
382
		/**
383
		 * Filter whether to override removing of meta value.
384
		 * Returning a non-null value will effectively short-circuit the function.
385
		 *
386
		 * @since 2.0.0
387
		 *
388
		 * @param null|bool $delete Whether to allow metadata deletion of the given type.
389
		 * @param array $args       Array of data about current field including:
390
		 *                              'type'     : Current object type
391
		 *                              'id'       : Current object ID
392
		 *                              'field_id' : Current Field ID
393
		 *                              'repeat'   : Whether current field is repeatable
394
		 *                              'single'   : Whether to save as a
395 3
		 *                              					single meta value
396
		 * @param array $field_args All field arguments
397
		 * @param CMB2_Field object $field This field object
398
		 */
399
		$override = apply_filters( 'cmb2_override_meta_remove', null, $a, $this->args(), $this );
400
401
		/**
402
		 * Filter whether to override removing of meta value.
403
		 *
404
		 * The dynamic portion of the hook, $a['field_id'], refers to the current
405
		 * field id paramater. Returning a non-null value
406
		 * will effectively short-circuit the function.
407
		 *
408
		 * @since 2.0.0
409
		 *
410
		 * @param null|bool $delete Whether to allow metadata deletion of the given type.
411
		 * @param array $args       Array of data about current field including:
412
		 *                              'type'     : Current object type
413
		 *                              'id'       : Current object ID
414
		 *                              'field_id' : Current Field ID
415
		 *                              'repeat'   : Whether current field is repeatable
416
		 *                              'single'   : Whether to save as a
417 3
		 *                              					single meta value
418
		 * @param array $field_args All field arguments
419
		 * @param CMB2_Field object $field This field object
420 3
		 */
421
		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_remove", $override, $a, $this->args(), $this );
422
423 3
		// If no override, remove as usual
424 1
		if ( null !== $override ) {
425
			return $override;
426
		} // End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
427
		// Option page handling.
428 2
		elseif ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
429
			return cmb2_options( $a['id'] )->remove( $a['field_id'] );
430
		}
431
432
		// Remove metadata
433
		return delete_metadata( $a['type'], $a['id'], $a['field_id'], $old );
434
	}
435
436
	/**
437
	 * Data variables for get/set data methods
438 107
	 *
439 107
	 * @since  1.1.0
440 107
	 * @param  array $args Override arguments
441 107
	 * @return array       Updated arguments
442 107
	 */
443 107
	public function data_args( $args = array() ) {
444 107
		$args = wp_parse_args( $args, array(
445 107
			'type'     => $this->object_type,
446 107
			'id'       => $this->object_id,
447
			'field_id' => $this->id( true ),
448
			'repeat'   => $this->args( 'repeatable' ),
449
			'single'   => ! $this->args( 'multiple' ),
450
		) );
451
		return $args;
452
	}
453
454
	/**
455
	 * Checks if field has a registered sanitization callback
456 15
	 *
457
	 * @since  1.0.1
458 15
	 * @param  mixed $meta_value Meta value
459
	 * @return mixed             Possibly sanitized meta value
460 2
	 */
461 2
	public function sanitization_cb( $meta_value ) {
462
463
		if ( $this->args( 'repeatable' ) && is_array( $meta_value ) ) {
464 15
			// Remove empties
465 15
			$meta_value = array_filter( $meta_value );
466
		}
467 1
468 14
		// Check if the field has a registered validation callback
469
		$cb = $this->maybe_callback( 'sanitization_cb' );
470
		if ( false === $cb ) {
471
			// If requesting NO validation, return meta value
472
			return $meta_value;
473 14
		} elseif ( $cb ) {
474
			// Ok, callback is good, let's run it.
475
			return call_user_func( $cb, $meta_value, $this->args(), $this );
476
		}
477
478
		$sanitizer = new CMB2_Sanitize( $this, $meta_value );
479
480
		/**
481
		 * Filter the value before it is saved.
482
		 *
483
		 * The dynamic portion of the hook name, $this->type(), refers to the field type.
484
		 *
485
		 * Passing a non-null value to the filter will short-circuit saving
486
		 * the field value, saving the passed value instead.
487
		 *
488
		 * @param bool|mixed $override_value Sanitization/Validation override value to return.
489
		 *                                   Default false to skip it.
490 14
		 * @param mixed      $value      The value to be saved to this field.
491
		 * @param int        $object_id  The ID of the object where the value will be saved
492 14
		 * @param array      $field_args The current field's arguments
493 1
		 * @param object     $sanitizer  This `CMB2_Sanitize` object
494
		 */
495
		$override_value = apply_filters( "cmb2_sanitize_{$this->type()}", null, $sanitizer->value, $this->object_id, $this->args(), $sanitizer );
496
497 13
		if ( null !== $override_value ) {
498
			return $override_value;
499
		}
500
501
		// Sanitization via 'CMB2_Sanitize'
502
		return $sanitizer->{$this->type()}();
503
	}
504
505
	/**
506
	 * Process $_POST data to save this field's value
507 3
	 *
508 3
	 * @since  2.0.3
509
	 * @param  array $data_to_save $_POST data to check
510 3
	 * @return array|int|bool                Result of save, false on failure
511 3
	 */
512 3
	public function save_field_from_data( array $data_to_save ) {
513
		$this->data_to_save = $data_to_save;
514 3
515
		$meta_value = isset( $this->data_to_save[ $this->id( true ) ] )
516
			? $this->data_to_save[ $this->id( true ) ]
517
			: null;
518
519
		return $this->save_field( $meta_value );
520
	}
521
522
	/**
523
	 * Sanitize/store a value to this field
524 13
	 *
525
	 * @since  2.0.0
526 13
	 * @param  array $meta_value Desired value to sanitize/store
527 13
	 * @return array|int|bool              Result of save. false on failure
528 13
	 */
529
	public function save_field( $meta_value ) {
530 13
531
		$updated   = false;
532
		$action    = '';
533 1
		$new_value = $this->sanitization_cb( $meta_value );
534
535 13
		if ( ! $this->args( 'save_field' ) ) {
536
537 1
			// Nothing to see here.
538 1
			$action = 'disabled';
539
540 1
		} elseif ( $this->args( 'multiple' ) && ! $this->args( 'repeatable' ) && ! $this->group ) {
541 1
542 1
			$this->remove_data();
543 1
			$count = 0;
544 1
545 1
			if ( ! empty( $new_value ) ) {
546 1
				foreach ( $new_value as $add_new ) {
547
					if ( $this->update_data( $add_new, false ) ) {
548 1
						$count++;
549 1
					}
550
				}
551 12
			}
552 10
553 10
			$updated = $count ? $count : false;
554 11
			$action  = 'repeatable';
555 2
556 2
		} elseif ( ! CMB2_Utils::isempty( $new_value ) && $new_value !== $this->get_data() ) {
557 2
			$updated = $this->update_data( $new_value );
558
			$action  = 'updated';
559 13
		} elseif ( CMB2_Utils::isempty( $new_value ) ) {
560 12
			$updated = $this->remove_data();
561 12
			$action  = 'removed';
562 12
		}
563
564 13
		if ( $updated ) {
565
			$this->value = $this->get_data();
566
			$this->escaped_value = null;
567
		}
568
569
		$field_id = $this->id( true );
570
571
		/**
572
		 * Hooks after save field action.
573
		 *
574
		 * @since 2.2.0
575
		 *
576 13
		 * @param string            $field_id the current field id paramater.
577
		 * @param bool              $updated  Whether the metadata update action occurred.
578
		 * @param string            $action   Action performed. Could be "repeatable", "updated", or "removed".
579
		 * @param CMB2_Field object $field    This field object
580
		 */
581
		do_action( 'cmb2_save_field', $field_id, $updated, $action, $this );
582
583
		/**
584
		 * Hooks after save field action.
585
		 *
586
		 * The dynamic portion of the hook, $field_id, refers to the
587
		 * current field id paramater.
588
		 *
589
		 * @since 2.2.0
590 12
		 *
591
		 * @param bool              $updated Whether the metadata update action occurred.
592 11
		 * @param string            $action  Action performed. Could be "repeatable", "updated", or "removed".
593
		 * @param CMB2_Field object $field   This field object
594
		 */
595
		do_action( "cmb2_save_field_{$field_id}", $updated, $action, $this );
596
597
		return $updated;
598
	}
599
600
	/**
601 47
	 * Determine if current type is exempt from escaping
602
	 *
603 47
	 * @since  1.1.0
604 47
	 * @return bool  True if exempt
605 47
	 */
606 47
	public function escaping_exception() {
607 47
		// These types cannot be escaped
608
		return in_array( $this->type(), array(
609
			'file_list',
610
			'multicheck',
611
			'text_datetime_timestamp_timezone',
612
		) );
613
	}
614
615
	/**
616
	 * Determine if current type cannot be repeatable
617 5
	 *
618
	 * @since  1.1.0
619
	 * @param  string $type Field type to check
620
	 * @return bool         True if type cannot be repeatable
621 5
	 */
622 5
	public function repeatable_exception( $type ) {
623 5
		// These types cannot be repeatable.
624 5
		$internal_fields = array(
625 5
			// Use file_list instead
626 5
			'file'                => 1,
627 5
			'radio'               => 1,
628 5
			'title'               => 1,
629 5
			'wysiwyg'             => 1,
630 5
			'checkbox'            => 1,
631
			'radio_inline'        => 1,
632
			'taxonomy_radio'      => 1,
633
			'taxonomy_select'     => 1,
634
			'taxonomy_multicheck' => 1,
635
		);
636
637
		/**
638
		 * Filter field types that are non-repeatable.
639
		 *
640
		 * Note that this does *not* allow overriding the default non-repeatable types.
641
		 *
642
		 * @since 2.1.1
643 5
		 *
644 5
		 * @param array $fields Array of fields designated as non-repeatable. Note that the field names are *keys*,
645
		 *                      and not values. The value can be anything, because it is meaningless. Example:
646
		 *                      array( 'my_custom_field' => 1 )
647
		 */
648
		$all_fields = array_merge( apply_filters( 'cmb2_non_repeatable_fields', array() ), $internal_fields );
649
		return isset( $all_fields[ $type ] );
650
	}
651
652
	/**
653
	 * Escape the value before output. Defaults to 'esc_attr()'
654
	 *
655 47
	 * @since  1.0.1
656
	 * @param  callable $func       Escaping function (if not esc_attr())
657 47
	 * @param  mixed    $meta_value Meta value
658 28
	 * @return mixed                Final value
659
	 */
660
	public function escaped_value( $func = 'esc_attr', $meta_value = '' ) {
661 47
662
		if ( null !== $this->escaped_value ) {
663
			return $this->escaped_value;
664 47
		}
665
666
		$meta_value = $meta_value ? $meta_value : $this->value();
667
668
		// Check if the field has a registered escaping callback
669
		if ( $cb = $this->maybe_callback( 'escape_cb' ) ) {
670 47
			// Ok, callback is good, let's run it.
671 47
			return call_user_func( $cb, $meta_value, $this->args(), $this );
672
		}
673
674
		// Or custom escaping filter can be used
675 47
		$esc = apply_filters( "cmb2_types_esc_{$this->type()}", null, $meta_value, $this->args(), $this );
676
		if ( null !== $esc ) {
677 5
			return $esc;
678
		}
679
680
		if ( false === $cb || $this->escaping_exception() ) {
681 42
			// If requesting NO escaping, return meta value
682 42
			return $this->val_or_default( $meta_value );
683
		}
684 42
685
		// escaping function passed in?
686
		$func       = $func ? $func : 'esc_attr';
687
		$meta_value = $this->val_or_default( $meta_value );
688
689 42
		if ( is_array( $meta_value ) ) {
690
			foreach ( $meta_value as $key => $value ) {
691
				$meta_value[ $key ] = call_user_func( $func, $value );
692 42
			}
693 42
		} else {
694
			$meta_value = call_user_func( $func, $meta_value );
695
		}
696
697
		$this->escaped_value = $meta_value;
698
		return $this->escaped_value;
699
	}
700
701
	/**
702
	 * Return non-empty value or field default if value IS empty
703 47
	 *
704 47
	 * @since  2.0.0
705
	 * @param  mixed $meta_value Field value
706
	 * @return mixed             Field value, or default value
707
	 */
708
	public function val_or_default( $meta_value ) {
709
		return ! CMB2_Utils::isempty( $meta_value ) ? $meta_value : $this->get_default();
710
	}
711
712
	/**
713
	 * Offset a time value based on timezone
714
	 *
715
	 * @since  1.0.0
716
	 * @return string Offset time string
717
	 */
718
	public function field_timezone_offset() {
719
		return CMB2_Utils::timezone_offset( $this->field_timezone() );
720
	}
721
722
	/**
723
	 * Return timezone string
724
	 *
725
	 * @since  1.0.0
726
	 * @return string Timezone string
727
	 */
728
	public function field_timezone() {
729
		$value = '';
730
731
		// Is timezone arg set?
732
		if ( $this->args( 'timezone' ) ) {
733
			$value = $this->args( 'timezone' );
734
		} // End if().
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
735
		// Is there another meta key with a timezone stored as its value we should use?
736
		elseif ( $this->args( 'timezone_meta_key' ) ) {
737
			$value = $this->get_data( $this->args( 'timezone_meta_key' ) );
738
		}
739
740
		return $value;
741
	}
742
743
	/**
744
	 * Format the timestamp field value based on the field date/time format arg
745 10
	 *
746 10
	 * @since  2.0.0
747
	 * @param  int    $meta_value Timestamp
748
	 * @param  string $format     Either date_format or time_format
749
	 * @return string             Formatted date
750
	 */
751
	public function format_timestamp( $meta_value, $format = 'date_format' ) {
752
		return date( stripslashes( $this->args( $format ) ), $meta_value );
753
	}
754
755
	/**
756
	 * Return a formatted timestamp for a field
757 10
	 *
758 10
	 * @since  2.0.0
759 10
	 * @param  string $format     Either date_format or time_format
760
	 * @param  string $meta_value Optional meta value to check
761 10
	 * @return string             Formatted date
762
	 */
763
	public function get_timestamp_format( $format = 'date_format', $meta_value = 0 ) {
764
		$meta_value = $meta_value ? $meta_value : $this->escaped_value();
765 10
		$meta_value = CMB2_Utils::make_valid_time_stamp( $meta_value );
766 10
767 10
		if ( empty( $meta_value ) ) {
768
			return '';
769
		}
770
771
		return is_array( $meta_value )
772
			? array_map( array( $this, 'format_timestamp' ), $meta_value, $format )
773
			: $this->format_timestamp( $meta_value, $format );
774
	}
775
776
	/**
777
	 * Get timestamp from text date
778
	 *
779
	 * @since  2.2.0
780
	 * @param  string $value Date value
781
	 * @return mixed         Unix timestamp representing the date.
782
	 */
783
	public function get_timestamp_from_value( $value ) {
784
		return CMB2_Utils::get_timestamp_from_value( $value, $this->args( 'date_format' ) );
785
	}
786 10
787 10
	/**
788
	 * Get field render callback and Render the field row
789 10
	 *
790
	 * @since 1.0.0
791
	 */
792 10
	public function render_field() {
793
		$this->render_context = 'edit';
794
795
		$this->peform_param_callback( 'render_row_cb' );
796
797
		// For chaining
798
		return $this;
799
	}
800 9
801
	/**
802
	 * Default field render callback
803 9
	 *
804
	 * @since 2.1.1
805
	 */
806
	public function render_field_callback() {
807
808 9
		// If field is requesting to not be shown on the front-end
809
		if ( ! is_admin() && ! $this->args( 'on_front' ) ) {
810
			return;
811
		}
812 9
813
		// If field is requesting to be conditionally shown
814 9
		if ( ! $this->should_show() ) {
815
			return;
816 9
		}
817
818
		$this->peform_param_callback( 'before_row' );
819
820
		printf( "<div class=\"cmb-row %s\" data-fieldtype=\"%s\">\n", $this->row_classes(), $this->type() );
821
822
		if ( ! $this->args( 'show_names' ) ) {
823 9
			echo "\n\t<div class=\"cmb-td\">\n";
824 9
825 9
			$this->peform_param_callback( 'label_cb' );
826
827 9
		} else {
828
829
			if ( $this->get_param_callback_result( 'label_cb' ) ) {
830 9
				echo '<div class="cmb-th">', $this->peform_param_callback( 'label_cb' ), '</div>';
831
			}
832 9
833 9
			echo "\n\t<div class=\"cmb-td\">\n";
834
		}
835 9
836
		$this->peform_param_callback( 'before' );
837 9
838
		$types = new CMB2_Types( $this );
839 9
		$types->render();
840
841
		$this->peform_param_callback( 'after' );
842 9
843
		echo "\n\t</div>\n</div>";
844
845
		$this->peform_param_callback( 'after_row' );
846
847
		// For chaining
848
		return $this;
849
	}
850
851 9
	/**
852 9
	 * The default label_cb callback (if not a title field)
853
	 *
854
	 * @since  2.1.1
855
	 * @return string Label html markup
856 9
	 */
857
	public function label() {
858 9
		if ( ! $this->args( 'name' ) ) {
859
			return '';
860
		}
861
862
		$style = ! $this->args( 'show_names' ) ? ' style="display:none;"' : '';
863
864
		return sprintf( "\n" . '<label%1$s for="%2$s">%3$s</label>' . "\n", $style, $this->id(), $this->args( 'name' ) );
865
	}
866
867 45
	/**
868
	 * Defines the classes for the current CMB2 field row
869 45
	 *
870
	 * @since  2.0.0
871
	 * @return string Space concatenated list of classes
872
	 */
873
	public function row_classes() {
874
875
		$classes = array();
876
877
		/**
878 45
		 * By default, 'text_url' and 'text' fields get table-like styling
879 45
		 *
880 45
		 * @since 2.0.0
881 45
		 *
882
		 * @param array $field_types The types of fields which should get the 'table-layout' class
883
		 */
884 45
		$repeat_table_rows_types = apply_filters( 'cmb2_repeat_table_row_types', array(
885 45
			'text_url',
886 45
			'text',
887 45
		) );
888 45
889 45
		$conditional_classes = array(
890 45
			'cmb-type-' . str_replace( '_', '-', sanitize_html_class( $this->type() ) ) => true,
891
			'cmb2-id-' . str_replace( '_', '-', sanitize_html_class( $this->id() ) )    => true,
892 45
			'cmb-repeat'             => $this->args( 'repeatable' ),
893 45
			'cmb-repeat-group-field' => $this->group,
894 45
			'cmb-inline'             => $this->args( 'inline' ),
895 45
			'table-layout'           => 'edit' === $this->render_context && in_array( $this->type(), $repeat_table_rows_types ),
896 45
		);
897
898 45
		foreach ( $conditional_classes as $class => $condition ) {
899 1
			if ( $condition ) {
900 45
				$classes[] = $class;
901 2
			}
902 2
		}
903
904 45
		if ( $added_classes = $this->args( 'classes' ) ) {
905 3
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
906 3
		} elseif ( $added_classes = $this->get_param_callback_result( 'classes_cb' ) ) {
907
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
908
		}
909
910
		if ( $added_classes ) {
911
			$classes[] = esc_attr( $added_classes );
912
		}
913
914
		/**
915
		 * Globally filter row classes
916 45
		 *
917
		 * @since 2.0.0
918
		 *
919
		 * @param string            $classes Space-separated list of row classes
920
		 * @param CMB2_Field object $field   This field object
921
		 */
922
		return apply_filters( 'cmb2_row_classes', implode( ' ', $classes ), $this );
923
	}
924
925
926 33
927 33
	/**
928
	 * Get field display callback and render the display value in the column.
929 33
	 *
930
	 * @since 2.2.2
931
	 */
932 33
	public function render_column() {
933
		$this->render_context = 'display';
934
935
		$this->peform_param_callback( 'display_cb' );
936
937
		// For chaining
938
		return $this;
939
	}
940 33
941
	/**
942 33
	 * Default callback to outputs field value in a display format.
943
	 *
944
	 * @since 2.2.2
945
	 */
946 33
	public function display_value_callback() {
947
		// If field is requesting to be conditionally shown
948
		if ( ! $this->should_show() ) {
949
			return;
950
		}
951
952
		$display = new CMB2_Field_Display( $this );
953
954
		/**
955
		 * A filter to bypass the default display.
956
		 *
957
		 * The dynamic portion of the hook name, $this->type(), refers to the field type.
958
		 *
959 33
		 * Passing a non-null value to the filter will short-circuit the default display.
960
		 *
961 33
		 * @param bool|mixed         $pre_output Default null value.
962
		 * @param CMB2_Field         $field      This field object.
963
		 * @param CMB2_Field_Display $display    The `CMB2_Field_Display` object.
964
		 */
965
		$pre_output = apply_filters( "cmb2_pre_field_display_{$this->type()}", null, $this, $display );
966 33
967
		if ( null !== $pre_output ) {
968 33
			echo $pre_output;
969
			return;
970 33
		}
971
972 33
		$this->peform_param_callback( 'before_display_wrap' );
973
974 33
		printf( "<div class=\"cmb-column %s\" data-fieldtype=\"%s\">\n", $this->row_classes( 'display' ), $this->type() );
0 ignored issues
show
Unused Code introduced by
The call to CMB2_Field::row_classes() has too many arguments starting with 'display'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
975
976 33
		$this->peform_param_callback( 'before_display' );
977
978 33
		CMB2_Field_Display::get( $this )->display();
979
980
		$this->peform_param_callback( 'after_display' );
981 33
982
		echo "\n</div>";
983
984
		$this->peform_param_callback( 'after_display_wrap' );
985
986
		// For chaining
987
		return $this;
988
	}
989
990
	/**
991 2
	 * Replaces a hash key - {#} - with the repeatable index
992
	 *
993 2
	 * @since  1.2.0
994
	 * @param  string $value Value to update
995
	 * @return string        Updated value
996
	 */
997
	public function replace_hash( $value ) {
998
		// Replace hash with 1 based count
999
		return str_replace( '{#}', ( $this->index + 1 ), $value );
1000
	}
1001
1002
	/**
1003
	 * Retrieve text parameter from field's text array (if it has one), or use fallback text
1004
	 * For back-compatibility, falls back to checking the options array.
1005 10
	 *
1006
	 * @since  2.2.2
1007 10
	 * @param  string $text_key Key in field's text array
1008 10
	 * @param  string $fallback Fallback text
1009
	 * @return string            Text
1010 10
	 */
1011
	public function get_string( $text_key, $fallback ) {
1012
		// If null, populate with our field strings values.
1013
		if ( null === $this->strings ) {
1014
			$this->strings = (array) $this->args['text'];
1015
1016 View Code Duplication
			if ( is_callable( $this->args['text_cb'] ) ) {
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...
1017 10
				$strings = call_user_func( $this->args['text_cb'], $this );
1018
1019
				if ( $strings && is_array( $strings ) ) {
1020 10
					$this->strings += $strings;
1021 1
				}
1022
			}
1023
		}
1024
1025 10
		// If we have that string value, send it back.
1026
		if ( isset( $this->strings[ $text_key ] ) ) {
1027 10
			return $this->strings[ $text_key ];
1028
		}
1029
1030
		// Check options for back-compat.
1031
		$string = $this->options( $text_key );
1032
1033
		return $string ? $string : $fallback;
0 ignored issues
show
Bug Compatibility introduced by
The expression $string ? $string : $fallback; of type array|string adds the type array to the return on line 1033 which is incompatible with the return type documented by CMB2_Field::get_string of type string.
Loading history...
1034
	}
1035
1036
	/**
1037 32
	 * Retrieve options args. Calls options_cb if it exists.
1038 32
	 *
1039 5
	 * @since  2.0.0
1040 5
	 * @param  string $key Specific option to retrieve
1041
	 * @return array        Array of options
1042
	 */
1043 1
	public function options( $key = '' ) {
1044
		if ( ! empty( $this->field_options ) ) {
1045
			if ( $key ) {
1046 32
				return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1047
			}
1048 32
1049 1
			return $this->field_options;
1050
		}
1051 1
1052 1
		$this->field_options = (array) $this->args['options'];
1053 1
1054 1 View Code Duplication
		if ( is_callable( $this->args['options_cb'] ) ) {
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...
1055
			$options = call_user_func( $this->args['options_cb'], $this );
1056 32
1057 11
			if ( $options && is_array( $options ) ) {
1058
				$this->field_options = $options + $this->field_options;
1059
			}
1060 25
		}
1061
1062
		if ( $key ) {
1063
			return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1064
		}
1065
1066
		return $this->field_options;
1067
	}
1068
1069 13
	/**
1070 13
	 * Store JS dependencies as part of the field args.
1071 13
	 *
1072 13
	 * @since 2.2.0
1073
	 * @param array $dependencies Dependies to register for this field.
1074 13
	 */
1075 13
	public function add_js_dependencies( $dependencies = array() ) {
1076
		foreach ( (array) $dependencies as $dependency ) {
1077
			$this->args['js_dependencies'][ $dependency ] = $dependency;
1078
		}
1079
1080
		CMB2_JS::add_dependencies( $dependencies );
1081
	}
1082
1083
	/**
1084 35
	 * Get CMB2_Field default value, either from default param or default_cb param.
1085 35
	 *
1086 8
	 * @since  0.2.2
1087
	 *
1088
	 * @return mixed  Default field value
1089 34
	 */
1090 34
	public function get_default() {
1091
		if ( null !== $this->args['default'] ) {
1092
			return $this->args['default'];
1093 34
		}
1094
1095 34
		$param = is_callable( $this->args['default_cb'] ) ? 'default_cb' : 'default';
1096
		$default = $this->get_param_callback_result( $param );
1097
1098
		// Allow a filter override of the default value
1099
		$this->args['default'] = apply_filters( 'cmb2_default_filter', $default, $this );
1100
1101
		return $this->args['default'];
1102
	}
1103
1104
	/**
1105 111
	 * Fills in empty field parameters with defaults
1106
	 *
1107
	 * @since 1.1.0
1108 111
	 * @param array                                   $args Metabox field config array
1109 111
	 * @param array       Modified field config array.
1110 111
	 */
1111 111
	public function _set_field_defaults( $args ) {
1112 111
1113 111
		// Set up blank or default values for empty ones
1114 111
		$args = wp_parse_args( $args, array(
1115 111
			'type'              => '',
1116 111
			'name'              => '',
1117 111
			'desc'              => '',
1118 111
			'before'            => '',
1119 111
			'after'             => '',
1120 111
			'options'           => array(),
1121 111
			'options_cb'        => '',
1122 111
			'text'              => array(),
1123 111
			'text_cb'           => '',
1124 111
			'attributes'        => array(),
1125 111
			'protocols'         => null,
1126 111
			'default'           => null,
1127 111
			'default_cb'        => '',
1128 111
			'classes'           => null,
1129 111
			'classes_cb'        => '',
1130 111
			'select_all_button' => true,
1131 111
			'multiple'          => false,
1132 111
			'repeatable'        => isset( $args['type'] ) && 'group' == $args['type'],
1133 111
			'inline'            => false,
1134 111
			'on_front'          => true,
1135 111
			'show_names'        => true,
1136 111
			'save_field'        => true, // Will not save if false
1137 111
			'date_format'       => 'm\/d\/Y',
1138 111
			'time_format'       => 'h:i A',
1139 111
			'description'       => isset( $args['desc'] ) ? $args['desc'] : '',
1140 111
			'preview_size'      => 'file' == $args['type'] ? array( 350, 350 ) : array( 50, 50 ),
1141 111
			'render_row_cb'     => array( $this, 'render_field_callback' ),
1142
			'display_cb'        => array( $this, 'display_value_callback' ),
1143
			'label_cb'          => 'title' != $args['type'] ? array( $this, 'label' ) : '',
1144
			'column'            => false,
1145
			'js_dependencies'   => array(),
1146
			'show_in_rest'      => null,
1147
		) );
1148
1149
		/*
1150 111
		 * Deprecated usage:
1151
		 *
1152 111
		 * 'std' -- use 'default' (no longer works)
1153 111
		 * 'row_classes' -- use 'class', or 'class_cb'
1154
		 * 'default' -- as callback (use default_cb)
1155 111
		 */
1156 4
		$args = $this->convert_deprecated_params( $args );
1157 4
1158 111
		$args['repeatable'] = $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
1159
		$args['inline']     = $args['inline'] || false !== stripos( $args['type'], '_inline' );
1160 111
1161 111
		$args['options']    = 'group' == $args['type'] ? wp_parse_args( $args['options'], array(
1162
			'add_button'    => esc_html__( 'Add Group', 'cmb2' ),
1163 111
			'remove_button' => esc_html__( 'Remove Group', 'cmb2' ),
1164
		) ) : $args['options'];
1165 4
1166 4
		$args['_id']        = $args['id'];
1167 4
		$args['_name']      = $args['id'];
1168
1169 111
		if ( $this->group ) {
1170 1
1171 1
			$args['id']    = $this->group->args( 'id' ) . '_' . $this->group->index . '_' . $args['id'];
1172 1
			$args['_name'] = $this->group->args( 'id' ) . '[' . $this->group->index . '][' . $args['_name'] . ']';
1173
		}
1174 111
1175
		if ( 'wysiwyg' == $args['type'] ) {
1176 111
			$args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
1177
			$args['options']['textarea_name'] = $args['_name'];
1178 16
		}
1179 16
1180
		$option_types = apply_filters( 'cmb2_all_or_nothing_types', array( 'select', 'radio', 'radio_inline', 'taxonomy_select', 'taxonomy_radio', 'taxonomy_radio_inline' ), $this );
1181 16
1182 15
		if ( in_array( $args['type'], $option_types, true ) ) {
1183 15
1184 15
			$args['show_option_none'] = isset( $args['show_option_none'] ) ? $args['show_option_none'] : null;
1185 16
			$args['show_option_none'] = true === $args['show_option_none'] ? esc_html__( 'None', 'cmb2' ) : $args['show_option_none'];
1186
1187 111
			if ( null === $args['show_option_none'] ) {
1188 111
				$off_by_default = in_array( $args['type'], array( 'select', 'radio', 'radio_inline' ), true );
1189
				$args['show_option_none'] = $off_by_default ? false : esc_html__( 'None', 'cmb2' );
1190
			}
1191 111
		}
1192
1193 111
		$args['has_supporting_data'] = in_array(
1194 111
			$args['type'],
1195
			array(
1196 111
				// CMB2_Sanitize::_save_file_id_value()/CMB2_Sanitize::_get_group_file_value_array()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1197
				'file',
1198 111
				// See CMB2_Sanitize::_save_utc_value()
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1199
				'text_datetime_timestamp_timezone',
1200
			),
1201
			true
1202
		);
1203
1204
		return $args;
1205
	}
1206
1207
	/**
1208
	 * Get default field arguments specific to this CMB2 object.
1209 7
	 *
1210 7
	 * @since  2.2.0
1211
	 * @param  array      $field_args  Metabox field config array.
1212 7
	 * @param  CMB2_Field $field_group (optional) CMB2_Field object (group parent)
1213
	 * @return array                   Array of field arguments.
1214
	 */
1215 7
	protected function get_default_args( $field_args, $field_group = null ) {
1216
		$args = parent::get_default_args( array(), $this->group );
1217
1218 7
		if ( isset( $field_args['field_args'] ) ) {
1219
			$args = wp_parse_args( $field_args, $args );
1220
		} else {
1221
			$args['field_args'] = wp_parse_args( $field_args, $this->args );
1222
		}
1223
1224
		return $args;
1225
	}
1226
1227
	/**
1228
	 * Returns a cloned version of this field object with, but with
1229
	 * modified/overridden field arguments.
1230
	 *
1231 7
	 * @since  2.2.2
1232 7
	 * @param  array $field_args Array of field arguments, or entire array of
1233
	 *                           arguments for CMB2_Field
1234
	 *
1235
	 * @return CMB2_Field         The new CMB2_Field instance.
1236
	 */
1237
	public function get_field_clone( $field_args ) {
1238
		return $this->get_new_field( $field_args );
1239
	}
1240
1241
	/**
1242 1
	 * Returns the CMB2 instance this field is registered to.
1243 1
	 *
1244
	 * @since  2.2.2
1245
	 *
1246
	 * @return CMB2|WP_Error If new CMB2_Field is called without cmb_id arg, returns error.
1247 1
	 */
1248
	public function get_cmb() {
1249
		if ( ! $this->cmb_id ) {
1250
			return new WP_Error( 'no_cmb_id', esc_html__( 'Sorry, this field does not have a cmb_id specified.', 'cmb2' ) );
1251
		}
1252
1253
		return cmb2_get_metabox( $this->cmb_id, $this->object_id, $this->object_type );
1254
	}
1255
1256
	/**
1257 111
	 * Converts deprecated field parameters to the current/proper parameter, and throws a deprecation notice.
1258
	 *
1259 111
	 * @since 2.2.3
1260
	 * @param array                                   $args Metabox field config array.
1261
	 * @param array       Modified field config array.
1262
	 */
1263
	protected function convert_deprecated_params( $args ) {
1264 2
1265
		if ( isset( $args['row_classes'] ) ) {
1266 1
1267
			// We'll let this one be.
1268 1
			// $this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_PARAM, 'row_classes', 'classes' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1269 1
			// row_classes param could be a callback. This is definitely deprecated.
1270 1
			if ( is_callable( $args['row_classes'] ) ) {
1271
1272 1
				$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'row_classes', 'classes_cb' );
1273
1274
				$args['classes_cb'] = $args['row_classes'];
1275 2
				$args['classes'] = null;
1276 2
			} else {
1277
1278
				$args['classes'] = $args['row_classes'];
1279 111
			}
1280
1281
			unset( $args['row_classes'] );
1282
		}
1283
1284
		// default param can be passed a callback as well
1285 View Code Duplication
		if ( is_callable( $args['default'] ) ) {
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...
1286
1287
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'default', 'default_cb' );
1288 111
1289
			$args['default_cb'] = $args['default'];
1290
			$args['default'] = null;
1291
		}
1292
1293
		// options param can be passed a callback as well
1294 View Code Duplication
		if ( is_callable( $args['options'] ) ) {
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...
1295
1296 111
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'options', 'options_cb' );
1297
1298
			$args['options_cb'] = $args['options'];
1299
			$args['options'] = array();
1300
		}
1301
1302
		return $args;
1303
	}
1304
1305
}
1306