Passed
Push — trunk ( 35f7f8...44999f )
by Justin
01:59
created

includes/CMB2_Field.php (4 issues)

1
<?php
2
/**
3
 * CMB2 field objects
4
 *
5
 * @since  1.1.0
6
 *
7
 * @category  WordPress_Plugin
8
 * @package   CMB2
9
 * @author    CMB2 team
10
 * @license   GPL-2.0+
11
 * @link      https://cmb2.io
12
 *
13
 * @method string _id()
14
 * @method string type()
15
 * @method mixed fields()
16
 */
17
class CMB2_Field extends CMB2_Base {
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 138
	public function __construct( $args ) {
124
125 138
		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 138
			$this->object_id   = isset( $args['object_id'] ) && '_' !== $args['object_id'] ? $args['object_id'] : 0;
132 138
			$this->object_type = isset( $args['object_type'] ) ? $args['object_type'] : 'post';
133
134 138
			if ( isset( $args['cmb_id'] ) ) {
135 69
				$this->cmb_id = $args['cmb_id'];
136 69
			}
137
		}
138
139 138
		$this->args = $this->_set_field_defaults( $args['field_args'], $args );
0 ignored issues
show
The call to CMB2_Field::_set_field_defaults() has too many arguments starting with $args. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

139
		/** @scrutinizer ignore-call */ 
140
  $this->args = $this->_set_field_defaults( $args['field_args'], $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. Please note the @ignore annotation hint above.

Loading history...
140
141 138
		if ( $this->object_id ) {
142 123
			$this->value = $this->get_data();
143 123
		}
144 138
	}
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 115
	public function __call( $name, $arguments ) {
155 115
		if ( 'string' === $name ) {
156
			return call_user_func_array( array( $this, 'get_string' ), $arguments );
157
		}
158
159 115
		$key = isset( $arguments[0] ) ? $arguments[0] : false;
160 115
		return $this->args( $name, $key );
0 ignored issues
show
It seems like $key can also be of type false; however, parameter $_key of CMB2_Field::args() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
		return $this->args( $name, /** @scrutinizer ignore-type */ $key );
Loading history...
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 131
	public function id( $raw = false ) {
171 131
		$id = $raw ? '_id' : 'id';
172 131
		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 134
	public function args( $key = '', $_key = '' ) {
184 134
		$arg = $this->_data( 'args', $key );
185
186 134
		if ( in_array( $key, array( 'default', 'default_cb' ), true ) ) {
187
188 1
			$arg = $this->get_default();
189
190 134
		} elseif ( $_key ) {
191
192
			$arg = isset( $arg[ $_key ] ) ? $arg[ $_key ] : false;
193
		}
194
195 134
		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 134
	public function _data( $var, $key = '' ) {
207 134
		$vars = $this->{$var};
208 134
		if ( $key ) {
209 134
			return array_key_exists( $key, $vars ) ? $vars[ $key ] : false;
210
		}
211 77
		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 54
	public function value( $key = '' ) {
222 54
		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 127
	public function get_data( $field_id = '', $args = array() ) {
234 127
		if ( $field_id ) {
235
			$args['field_id'] = $field_id;
236 127
		} elseif ( $this->group ) {
237
			$args['field_id'] = $this->group->id();
238
		}
239
240 127
		$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 127
		$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 127
		$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 127
		if ( 'cmb2_field_no_override_val' === $data ) {
282 127
			$data = 'options-page' === $a['type']
283 127
				? cmb2_options( $a['id'] )->get( $a['field_id'] )
284 127
				: get_metadata( $a['type'], $a['id'], $a['field_id'], ( $a['single'] || $a['repeat'] ) );
285 127
		}
286
287 127
		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 127
		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 23
	public function update_data( $new_value, $single = true ) {
305 23
		$a = $this->data_args( array(
306 23
			'single' => $single,
307 23
		) );
308
309 23
		$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
		 * @param CMB2_Field object $field This field object
333
		 */
334 23
		$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
		 * @since 2.0.0
344
		 */
345 23
		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_save", $override, $a, $this->args(), $this );
346
347
		// If override, return that
348 23
		if ( null !== $override ) {
349 1
			return $override;
350
		}
351
352
		// Options page handling (or temp data store)
353 23
		if ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
354 6
			return cmb2_options( $a['id'] )->update( $a['field_id'], $a['value'], false, $a['single'] );
355
		}
356
357
		// Add metadata if not single
358 17
		if ( ! $a['single'] ) {
359 1
			return add_metadata( $a['type'], $a['id'], $a['field_id'], $a['value'], false );
360
		}
361
362
		// Delete meta if we have an empty array
363 16
		if ( is_array( $a['value'] ) && empty( $a['value'] ) ) {
364
			return delete_metadata( $a['type'], $a['id'], $a['field_id'], $this->value );
365
		}
366
367
		// Update metadata
368 16
		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
	 * @param  string $old Old value
376
	 */
377 5
	public function remove_data( $old = '' ) {
378 5
		$a = $this->data_args( array(
379 5
			'old' => $old,
380 5
		) );
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
		 *                              					single meta value
396
		 * @param array $field_args All field arguments
397
		 * @param CMB2_Field object $field This field object
398
		 */
399 5
		$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
		 *                              					single meta value
418
		 * @param array $field_args All field arguments
419
		 * @param CMB2_Field object $field This field object
420
		 */
421 5
		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_remove", $override, $a, $this->args(), $this );
422
423
		// If no override, remove as usual
424 5
		if ( null !== $override ) {
425
			return $override;
426
		} // End if().
427
		// Option page handling.
428 5
		elseif ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
429 1
			return cmb2_options( $a['id'] )->remove( $a['field_id'] );
430
		}
431
432
		// Remove metadata
433 4
		return delete_metadata( $a['type'], $a['id'], $a['field_id'], $old );
434
	}
435
436
	/**
437
	 * Data variables for get/set data methods
438
	 *
439
	 * @since  1.1.0
440
	 * @param  array $args Override arguments
441
	 * @return array       Updated arguments
442
	 */
443 127
	public function data_args( $args = array() ) {
444 127
		$args = wp_parse_args( $args, array(
445 127
			'type'     => $this->object_type,
446 127
			'id'       => $this->object_id,
447 127
			'field_id' => $this->id( true ),
448 127
			'repeat'   => $this->args( 'repeatable' ),
449 127
			'single'   => ! $this->args( 'multiple' ),
450 127
		) );
451 127
		return $args;
452
	}
453
454
	/**
455
	 * Checks if field has a registered sanitization callback
456
	 *
457
	 * @since  1.0.1
458
	 * @param  mixed $meta_value Meta value
459
	 * @return mixed             Possibly sanitized meta value
460
	 */
461 25
	public function sanitization_cb( $meta_value ) {
462
463 25
		if ( $this->args( 'repeatable' ) && is_array( $meta_value ) ) {
464
			// Remove empties
465 2
			$meta_value = array_filter( $meta_value );
466 2
		}
467
468
		// Check if the field has a registered validation callback
469 25
		$cb = $this->maybe_callback( 'sanitization_cb' );
470 25
		if ( false === $cb ) {
471
			// If requesting NO validation, return meta value
472 2
			return $meta_value;
473 24
		} 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 24
		$sanitizer = new CMB2_Sanitize( $this, $meta_value );
479 24
		$field_type = $this->type();
480
481
		/**
482
		 * Filter the value before it is saved.
483
		 *
484
		 * The dynamic portion of the hook name, $field_type, refers to the field type.
485
		 *
486
		 * Passing a non-null value to the filter will short-circuit saving
487
		 * the field value, saving the passed value instead.
488
		 *
489
		 * @param bool|mixed $override_value Sanitization/Validation override value to return.
490
		 *                                   Default: null. false to skip it.
491
		 * @param mixed      $value      The value to be saved to this field.
492
		 * @param int        $object_id  The ID of the object where the value will be saved
493
		 * @param array      $field_args The current field's arguments
494
		 * @param object     $sanitizer  This `CMB2_Sanitize` object
495
		 */
496 24
		$override_value = apply_filters( "cmb2_sanitize_{$field_type}", null, $sanitizer->value, $this->object_id, $this->args(), $sanitizer );
497
498 24
		if ( null !== $override_value ) {
499 1
			return $override_value;
500
		}
501
502
		// Sanitization via 'CMB2_Sanitize'
503 23
		return $sanitizer->{$field_type}();
504
	}
505
506
	/**
507
	 * Process $_POST data to save this field's value
508
	 *
509
	 * @since  2.0.3
510
	 * @param  array $data_to_save $_POST data to check
511
	 * @return array|int|bool                Result of save, false on failure
512
	 */
513 4
	public function save_field_from_data( array $data_to_save ) {
514 4
		$this->data_to_save = $data_to_save;
515
516 4
		$meta_value = isset( $this->data_to_save[ $this->id( true ) ] )
517 4
			? $this->data_to_save[ $this->id( true ) ]
518 4
			: null;
519
520 4
		return $this->save_field( $meta_value );
521
	}
522
523
	/**
524
	 * Sanitize/store a value to this field
525
	 *
526
	 * @since  2.0.0
527
	 * @param  array $meta_value Desired value to sanitize/store
528
	 * @return array|int|bool              Result of save. false on failure
529
	 */
530 23
	public function save_field( $meta_value ) {
531
532 23
		$updated   = false;
533 23
		$action    = '';
534 23
		$new_value = $this->sanitization_cb( $meta_value );
535
536 23
		if ( ! $this->args( 'save_field' ) ) {
537
538
			// Nothing to see here.
539 1
			$action = 'disabled';
540
541 23
		} elseif ( $this->args( 'multiple' ) && ! $this->args( 'repeatable' ) && ! $this->group ) {
542
543 1
			$this->remove_data();
544 1
			$count = 0;
545
546 1
			if ( ! empty( $new_value ) ) {
547 1
				foreach ( $new_value as $add_new ) {
548 1
					if ( $this->update_data( $add_new, false ) ) {
549 1
						$count++;
550 1
					}
551 1
				}
552 1
			}
553
554 1
			$updated = $count ? $count : false;
555 1
			$action  = 'repeatable';
556
557 22
		} elseif ( ! CMB2_Utils::isempty( $new_value ) && $new_value !== $this->get_data() ) {
558 20
			$updated = $this->update_data( $new_value );
559 20
			$action  = 'updated';
560 21
		} elseif ( CMB2_Utils::isempty( $new_value ) ) {
561 4
			$updated = $this->remove_data();
562 4
			$action  = 'removed';
563 4
		}
564
565 23
		if ( $updated ) {
566 22
			$this->value = $this->get_data();
567 22
			$this->escaped_value = null;
568 22
		}
569
570 23
		$field_id = $this->id( true );
571
572
		/**
573
		 * Hooks after save field action.
574
		 *
575
		 * @since 2.2.0
576
		 *
577
		 * @param string            $field_id the current field id paramater.
578
		 * @param bool              $updated  Whether the metadata update action occurred.
579
		 * @param string            $action   Action performed. Could be "repeatable", "updated", or "removed".
580
		 * @param CMB2_Field object $field    This field object
581
		 */
582 23
		do_action( 'cmb2_save_field', $field_id, $updated, $action, $this );
583
584
		/**
585
		 * Hooks after save field action.
586
		 *
587
		 * The dynamic portion of the hook, $field_id, refers to the
588
		 * current field id paramater.
589
		 *
590
		 * @since 2.2.0
591
		 *
592
		 * @param bool              $updated Whether the metadata update action occurred.
593
		 * @param string            $action  Action performed. Could be "repeatable", "updated", or "removed".
594
		 * @param CMB2_Field object $field   This field object
595
		 */
596 22
		do_action( "cmb2_save_field_{$field_id}", $updated, $action, $this );
597
598 21
		return $updated;
599
	}
600
601
	/**
602
	 * Determine if current type is exempt from escaping
603
	 *
604
	 * @since  1.1.0
605
	 * @return bool  True if exempt
606
	 */
607 54
	public function escaping_exception() {
608
		// These types cannot be escaped
609 54
		return in_array( $this->type(), array(
610 54
			'file_list',
611 54
			'multicheck',
612 54
			'text_datetime_timestamp_timezone',
613 54
		) );
614
	}
615
616
	/**
617
	 * Determine if current type cannot be repeatable
618
	 *
619
	 * @since  1.1.0
620
	 * @param  string $type Field type to check
621
	 * @return bool         True if type cannot be repeatable
622
	 */
623 6
	public function repeatable_exception( $type ) {
624
		// These types cannot be repeatable.
625
		$internal_fields = array(
626
			// Use file_list instead
627 6
			'file'                             => 1,
628 6
			'radio'                            => 1,
629 6
			'title'                            => 1,
630 6
			'wysiwyg'                          => 1,
631 6
			'checkbox'                         => 1,
632 6
			'radio_inline'                     => 1,
633 6
			'taxonomy_radio'                   => 1,
634 6
			'taxonomy_radio_inline'            => 1,
635 6
			'taxonomy_radio_hierarchical'      => 1,
636 6
			'taxonomy_select'                  => 1,
637 6
			'taxonomy_multicheck'              => 1,
638 6
			'taxonomy_multicheck_inline'       => 1,
639 6
			'taxonomy_multicheck_hierarchical' => 1,
640
641 6
		);
642
643
		/**
644
		 * Filter field types that are non-repeatable.
645
		 *
646
		 * Note that this does *not* allow overriding the default non-repeatable types.
647
		 *
648
		 * @since 2.1.1
649
		 *
650
		 * @param array $fields Array of fields designated as non-repeatable. Note that the field names are *keys*,
651
		 *                      and not values. The value can be anything, because it is meaningless. Example:
652
		 *                      array( 'my_custom_field' => 1 )
653
		 */
654 6
		$all_fields = array_merge( apply_filters( 'cmb2_non_repeatable_fields', array() ), $internal_fields );
655 6
		return isset( $all_fields[ $type ] );
656
	}
657
658
	/**
659
	 * Determine if current type has its own defaults field-arguments method.
660
	 *
661
	 * @since  2.2.6
662
	 * @param  string $type Field type to check
663
	 * @return bool         True if has own method.
664
	 */
665 138
	public function has_args_method( $type ) {
666
667
		// These types have their own arguments parser.
668
		$type_methods = array(
669 138
			'group'   => 'set_field_defaults_group',
670 138
			'wysiwyg' => 'set_field_defaults_wysiwyg',
671 138
		);
672
673 138
		if ( isset( $type_methods[ $type ] ) ) {
674 6
			return $type_methods[ $type ];
675
		}
676
677 136
		$all_or_nothing_types = array_flip( apply_filters( 'cmb2_all_or_nothing_types', array(
678 136
			'select',
679 136
			'radio',
680 136
			'radio_inline',
681 136
			'taxonomy_select',
682 136
			'taxonomy_radio',
683 136
			'taxonomy_radio_inline',
684 136
			'taxonomy_radio_hierarchical',
685 136
		), $this ) );
686
687 136
		if ( isset( $all_or_nothing_types[ $type ] ) ) {
688 18
			return 'set_field_defaults_all_or_nothing_types';
689
		}
690
691 120
		return false;
692
	}
693
694
	/**
695
	 * Escape the value before output. Defaults to 'esc_attr()'
696
	 *
697
	 * @since  1.0.1
698
	 * @param  callable $func       Escaping function (if not esc_attr())
699
	 * @param  mixed    $meta_value Meta value
700
	 * @return mixed                Final value
701
	 */
702 54
	public function escaped_value( $func = 'esc_attr', $meta_value = '' ) {
703
704 54
		if ( null !== $this->escaped_value ) {
705 31
			return $this->escaped_value;
706
		}
707
708 54
		$meta_value = $meta_value ? $meta_value : $this->value();
709
710
		// Check if the field has a registered escaping callback
711 54
		if ( $cb = $this->maybe_callback( 'escape_cb' ) ) {
712
			// Ok, callback is good, let's run it.
713
			return call_user_func( $cb, $meta_value, $this->args(), $this );
714
		}
715
716 54
		$field_type = $this->type();
717
718
		/**
719
		 * Filter the value for escaping before it is ouput.
720
		 *
721
		 * The dynamic portion of the hook name, $field_type, refers to the field type.
722
		 *
723
		 * Passing a non-null value to the filter will short-circuit the built-in
724
		 * escaping for this field.
725
		 *
726
		 * @param bool|mixed $override_value Escaping override value to return.
727
		 *                                   Default: null. false to skip it.
728
		 * @param mixed      $meta_value The value to be output.
729
		 * @param array      $field_args The current field's arguments.
730
		 * @param object     $field      This `CMB2_Field` object.
731
		 */
732 54
		$esc = apply_filters( "cmb2_types_esc_{$field_type}", null, $meta_value, $this->args(), $this );
733 54
		if ( null !== $esc ) {
734
			return $esc;
735
		}
736
737 54
		if ( false === $cb || $this->escaping_exception() ) {
738
			// If requesting NO escaping, return meta value
739 5
			return $this->val_or_default( $meta_value );
740
		}
741
742
		// escaping function passed in?
743 49
		$func       = $func ? $func : 'esc_attr';
744 49
		$meta_value = $this->val_or_default( $meta_value );
745
746 49
		if ( is_array( $meta_value ) ) {
747
			foreach ( $meta_value as $key => $value ) {
748
				$meta_value[ $key ] = call_user_func( $func, $value );
749
			}
750
		} else {
751 49
			$meta_value = call_user_func( $func, $meta_value );
752
		}
753
754 49
		$this->escaped_value = $meta_value;
755 49
		return $this->escaped_value;
756
	}
757
758
	/**
759
	 * Return non-empty value or field default if value IS empty
760
	 *
761
	 * @since  2.0.0
762
	 * @param  mixed $meta_value Field value
763
	 * @return mixed             Field value, or default value
764
	 */
765 54
	public function val_or_default( $meta_value ) {
766 54
		return ! CMB2_Utils::isempty( $meta_value ) ? $meta_value : $this->get_default();
767
	}
768
769
	/**
770
	 * Offset a time value based on timezone
771
	 *
772
	 * @since  1.0.0
773
	 * @return string Offset time string
774
	 */
775
	public function field_timezone_offset() {
776
		return CMB2_Utils::timezone_offset( $this->field_timezone() );
777
	}
778
779
	/**
780
	 * Return timezone string
781
	 *
782
	 * @since  1.0.0
783
	 * @return string Timezone string
784
	 */
785
	public function field_timezone() {
786
		$value = '';
787
788
		// Is timezone arg set?
789
		if ( $this->args( 'timezone' ) ) {
790
			$value = $this->args( 'timezone' );
791
		} // End if().
792
		// Is there another meta key with a timezone stored as its value we should use?
793
		elseif ( $this->args( 'timezone_meta_key' ) ) {
794
			$value = $this->get_data( $this->args( 'timezone_meta_key' ) );
795
		}
796
797
		return $value;
798
	}
799
800
	/**
801
	 * Format the timestamp field value based on the field date/time format arg
802
	 *
803
	 * @since  2.0.0
804
	 * @param  int    $meta_value Timestamp
805
	 * @param  string $format     Either date_format or time_format
806
	 * @return string             Formatted date
807
	 */
808 10
	public function format_timestamp( $meta_value, $format = 'date_format' ) {
809 10
		return date( stripslashes( $this->args( $format ) ), $meta_value );
810
	}
811
812
	/**
813
	 * Return a formatted timestamp for a field
814
	 *
815
	 * @since  2.0.0
816
	 * @param  string $format     Either date_format or time_format
817
	 * @param  string $meta_value Optional meta value to check
818
	 * @return string             Formatted date
819
	 */
820 10
	public function get_timestamp_format( $format = 'date_format', $meta_value = 0 ) {
821 10
		$meta_value = $meta_value ? $meta_value : $this->escaped_value();
822 10
		$meta_value = CMB2_Utils::make_valid_time_stamp( $meta_value );
823
824 10
		if ( empty( $meta_value ) ) {
825
			return '';
826
		}
827
828 10
		return is_array( $meta_value )
829 10
			? array_map( array( $this, 'format_timestamp' ), $meta_value, $format )
830 10
			: $this->format_timestamp( $meta_value, $format );
831
	}
832
833
	/**
834
	 * Get timestamp from text date
835
	 *
836
	 * @since  2.2.0
837
	 * @param  string $value Date value
838
	 * @return mixed         Unix timestamp representing the date.
839
	 */
840
	public function get_timestamp_from_value( $value ) {
841
		return CMB2_Utils::get_timestamp_from_value( $value, $this->args( 'date_format' ) );
842
	}
843
844
	/**
845
	 * Get field render callback and Render the field row
846
	 *
847
	 * @since 1.0.0
848
	 */
849 10
	public function render_field() {
850 10
		$this->render_context = 'edit';
851
852 10
		$this->peform_param_callback( 'render_row_cb' );
853
854
		// For chaining
855 10
		return $this;
856
	}
857
858
	/**
859
	 * Default field render callback
860
	 *
861
	 * @since 2.1.1
862
	 */
863 14
	public function render_field_callback() {
864
865
		// If field is requesting to not be shown on the front-end
866 14
		if ( ! is_admin() && ! $this->args( 'on_front' ) ) {
867
			return;
868
		}
869
870
		// If field is requesting to be conditionally shown
871 14
		if ( ! $this->should_show() ) {
872
			return;
873
		}
874
875 14
		$this->peform_param_callback( 'before_row' );
876
877 14
		printf( "<div class=\"cmb-row %s\" data-fieldtype=\"%s\">\n", $this->row_classes(), $this->type() );
878
879 14
		if ( ! $this->args( 'show_names' ) ) {
880
			echo "\n\t<div class=\"cmb-td\">\n";
881
882
			$this->peform_param_callback( 'label_cb' );
883
884
		} else {
885
886 14
			if ( $this->get_param_callback_result( 'label_cb' ) ) {
887 14
				echo '<div class="cmb-th">', $this->peform_param_callback( 'label_cb' ), '</div>';
888 14
			}
889
890 14
			echo "\n\t<div class=\"cmb-td\">\n";
891
		}
892
893 14
		$this->peform_param_callback( 'before' );
894
895 14
		$types = new CMB2_Types( $this );
896 14
		$types->render();
897
898 14
		$this->peform_param_callback( 'after' );
899
900 14
		echo "\n\t</div>\n</div>";
901
902 14
		$this->peform_param_callback( 'after_row' );
903
904
		// For chaining
905 14
		return $this;
906
	}
907
908
	/**
909
	 * The default label_cb callback (if not a title field)
910
	 *
911
	 * @since  2.1.1
912
	 * @return string Label html markup
913
	 */
914 14
	public function label() {
915 14
		if ( ! $this->args( 'name' ) ) {
916
			return '';
917
		}
918
919 14
		$style = ! $this->args( 'show_names' ) ? ' style="display:none;"' : '';
920
921 14
		return sprintf( "\n" . '<label%1$s for="%2$s">%3$s</label>' . "\n", $style, $this->id(), $this->args( 'name' ) );
922
	}
923
924
	/**
925
	 * Defines the classes for the current CMB2 field row
926
	 *
927
	 * @since  2.0.0
928
	 * @return string Space concatenated list of classes
929
	 */
930 50
	public function row_classes() {
931
932 50
		$classes = array();
933
934
		/**
935
		 * By default, 'text_url' and 'text' fields get table-like styling
936
		 *
937
		 * @since 2.0.0
938
		 *
939
		 * @param array $field_types The types of fields which should get the 'table-layout' class
940
		 */
941 50
		$repeat_table_rows_types = apply_filters( 'cmb2_repeat_table_row_types', array(
942 50
			'text_url',
943 50
			'text',
944 50
		) );
945
946
		$conditional_classes = array(
947 50
			'cmb-type-' . str_replace( '_', '-', sanitize_html_class( $this->type() ) ) => true,
948 50
			'cmb2-id-' . str_replace( '_', '-', sanitize_html_class( $this->id() ) )    => true,
949 50
			'cmb-repeat'             => $this->args( 'repeatable' ),
950 50
			'cmb-repeat-group-field' => $this->group,
951 50
			'cmb-inline'             => $this->args( 'inline' ),
952 50
			'table-layout'           => 'edit' === $this->render_context && in_array( $this->type(), $repeat_table_rows_types ),
953 50
		);
954
955 50
		foreach ( $conditional_classes as $class => $condition ) {
956 50
			if ( $condition ) {
957 50
				$classes[] = $class;
958 50
			}
959 50
		}
960
961 50
		if ( $added_classes = $this->args( 'classes' ) ) {
962 1
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
963 50
		} elseif ( $added_classes = $this->get_param_callback_result( 'classes_cb' ) ) {
964 2
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
965 2
		}
966
967 50
		if ( $added_classes ) {
968 3
			$classes[] = esc_attr( $added_classes );
969 3
		}
970
971
		/**
972
		 * Globally filter row classes
973
		 *
974
		 * @since 2.0.0
975
		 *
976
		 * @param string            $classes Space-separated list of row classes
977
		 * @param CMB2_Field object $field   This field object
978
		 */
979 50
		return apply_filters( 'cmb2_row_classes', implode( ' ', $classes ), $this );
980
	}
981
982
983
984
	/**
985
	 * Get field display callback and render the display value in the column.
986
	 *
987
	 * @since 2.2.2
988
	 */
989 33
	public function render_column() {
990 33
		$this->render_context = 'display';
991
992 33
		$this->peform_param_callback( 'display_cb' );
993
994
		// For chaining
995 33
		return $this;
996
	}
997
998
	/**
999
	 * Default callback to outputs field value in a display format.
1000
	 *
1001
	 * @since 2.2.2
1002
	 */
1003 33
	public function display_value_callback() {
1004
		// If field is requesting to be conditionally shown
1005 33
		if ( ! $this->should_show() ) {
1006
			return;
1007
		}
1008
1009 33
		$display = new CMB2_Field_Display( $this );
1010 33
		$field_type = $this->type();
1011
1012
		/**
1013
		 * A filter to bypass the default display.
1014
		 *
1015
		 * The dynamic portion of the hook name, $field_type, refers to the field type.
1016
		 *
1017
		 * Passing a non-null value to the filter will short-circuit the default display.
1018
		 *
1019
		 * @param bool|mixed         $pre_output Default null value.
1020
		 * @param CMB2_Field         $field      This field object.
1021
		 * @param CMB2_Field_Display $display    The `CMB2_Field_Display` object.
1022
		 */
1023 33
		$pre_output = apply_filters( "cmb2_pre_field_display_{$field_type}", null, $this, $display );
1024
1025 33
		if ( null !== $pre_output ) {
1026
			echo $pre_output;
1027
			return;
1028
		}
1029
1030 33
		$this->peform_param_callback( 'before_display_wrap' );
1031
1032 33
		printf( "<div class=\"cmb-column %s\" data-fieldtype=\"%s\">\n", $this->row_classes( 'display' ), $field_type );
0 ignored issues
show
The call to CMB2_Field::row_classes() has too many arguments starting with 'display'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1032
		printf( "<div class=\"cmb-column %s\" data-fieldtype=\"%s\">\n", $this->/** @scrutinizer ignore-call */ row_classes( 'display' ), $field_type );

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. Please note the @ignore annotation hint above.

Loading history...
1033
1034 33
		$this->peform_param_callback( 'before_display' );
1035
1036 33
		CMB2_Field_Display::get( $this )->display();
1037
1038 33
		$this->peform_param_callback( 'after_display' );
1039
1040 33
		echo "\n</div>";
1041
1042 33
		$this->peform_param_callback( 'after_display_wrap' );
1043
1044
		// For chaining
1045 33
		return $this;
1046
	}
1047
1048
	/**
1049
	 * Replaces a hash key - {#} - with the repeatable index
1050
	 *
1051
	 * @since  1.2.0
1052
	 * @param  string $value Value to update
1053
	 * @return string        Updated value
1054
	 */
1055 2
	public function replace_hash( $value ) {
1056
		// Replace hash with 1 based count
1057 2
		return str_replace( '{#}', ( $this->index + 1 ), $value );
1058
	}
1059
1060
	/**
1061
	 * Retrieve text parameter from field's text array (if it has one), or use fallback text
1062
	 * For back-compatibility, falls back to checking the options array.
1063
	 *
1064
	 * @since  2.2.2
1065
	 * @param  string $text_key Key in field's text array
1066
	 * @param  string $fallback Fallback text
1067
	 * @return string            Text
1068
	 */
1069 10
	public function get_string( $text_key, $fallback ) {
1070
		// If null, populate with our field strings values.
1071 10
		if ( null === $this->strings ) {
1072 10
			$this->strings = (array) $this->args['text'];
1073
1074 10
			if ( is_callable( $this->args['text_cb'] ) ) {
1075
				$strings = call_user_func( $this->args['text_cb'], $this );
1076
1077
				if ( $strings && is_array( $strings ) ) {
1078
					$this->strings += $strings;
1079
				}
1080
			}
1081 10
		}
1082
1083
		// If we have that string value, send it back.
1084 10
		if ( isset( $this->strings[ $text_key ] ) ) {
1085 1
			return $this->strings[ $text_key ];
1086
		}
1087
1088
		// Check options for back-compat.
1089 10
		$string = $this->options( $text_key );
1090
1091 10
		return $string ? $string : $fallback;
1092
	}
1093
1094
	/**
1095
	 * Retrieve options args.
1096
	 *
1097
	 * @since  2.0.0
1098
	 * @param  string $key Specific option to retrieve
1099
	 * @return array|mixed Array of options or specific option.
1100
	 */
1101 43
	public function options( $key = '' ) {
1102 43
		if ( empty( $this->field_options ) ) {
1103 43
			$this->set_options();
1104 43
		}
1105
1106 43
		if ( $key ) {
1107 16
			return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1108
		}
1109
1110 32
		return $this->field_options;
1111
	}
1112
1113
	/**
1114
	 * Generates/sets options args. Calls options_cb if it exists.
1115
	 *
1116
	 * @since  2.2.5
1117
	 *
1118
	 * @return array Array of options
1119
	 */
1120 43
	public function set_options() {
1121 43
		$this->field_options = (array) $this->args['options'];
1122
1123 43
		if ( is_callable( $this->args['options_cb'] ) ) {
1124 1
			$options = call_user_func( $this->args['options_cb'], $this );
1125
1126 1
			if ( $options && is_array( $options ) ) {
1127 1
				$this->field_options = $options + $this->field_options;
1128 1
			}
1129 1
		}
1130
1131 43
		return $this->field_options;
1132
	}
1133
1134
	/**
1135
	 * Store JS dependencies as part of the field args.
1136
	 *
1137
	 * @since 2.2.0
1138
	 * @param array $dependencies Dependies to register for this field.
1139
	 */
1140 14
	public function add_js_dependencies( $dependencies = array() ) {
1141 14
		foreach ( (array) $dependencies as $dependency ) {
1142 14
			$this->args['js_dependencies'][ $dependency ] = $dependency;
1143 14
		}
1144
1145 14
		CMB2_JS::add_dependencies( $dependencies );
1146 14
	}
1147
1148
	/**
1149
	 * Get CMB2_Field default value, either from default param or default_cb param.
1150
	 *
1151
	 * @since  0.2.2
1152
	 *
1153
	 * @return mixed  Default field value
1154
	 */
1155 41
	public function get_default() {
1156 41
		$default = $this->args['default'];
1157
1158 41
		if ( null !== $default ) {
1159 8
			return apply_filters( 'cmb2_default_filter', $default, $this );
1160
		}
1161
1162 40
		$param = is_callable( $this->args['default_cb'] ) ? 'default_cb' : 'default';
1163 40
		$default = $this->args['default'] = $this->get_param_callback_result( $param );
1164
1165
		// Allow a filter override of the default value.
1166 40
		return apply_filters( 'cmb2_default_filter', $this->args['default'], $this );
1167
	}
1168
1169
	/**
1170
	 * Fills in empty field parameters with defaults
1171
	 *
1172
	 * @since 1.1.0
1173
	 *
1174
	 * @param  array  $args Field config array.
1175
	 * @return array        Modified field config array.
1176
	 */
1177 138
	public function _set_field_defaults( $args ) {
1178
1179
		// Set up blank or default values for empty ones
1180 138
		$args = wp_parse_args( $args, $this->get_default_field_args( $args ) );
1181
1182
		/*
1183
		 * Deprecated usage:
1184
		 *
1185
		 * 'std' -- use 'default' (no longer works)
1186
		 * 'row_classes' -- use 'class', or 'class_cb'
1187
		 * 'default' -- as callback (use default_cb)
1188
		 */
1189 138
		$args = $this->convert_deprecated_params( $args );
1190
1191 138
		$args['repeatable'] = $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
1192 138
		$args['inline']     = $args['inline'] || false !== stripos( $args['type'], '_inline' );
1193 138
		$args['_id']        = $args['id'];
1194 138
		$args['_name']      = $args['id'];
1195
1196 138
		if ( $method = $this->has_args_method( $args['type'] ) ) {
1197 24
			$args = $this->{$method}( $args );
1198 24
		}
1199
1200 138
		if ( $this->group ) {
1201 4
			$args = $this->set_group_sub_field_defaults( $args );
1202 4
		}
1203
1204 138
		$args['has_supporting_data'] = in_array(
1205 138
			$args['type'],
1206
			array(
1207
				// CMB2_Sanitize::_save_file_id_value()/CMB2_Sanitize::_get_group_file_value_array()
1208 138
				'file',
1209
				// See CMB2_Sanitize::_save_utc_value()
1210 138
				'text_datetime_timestamp_timezone',
1211 138
			),
1212
			true
1213 138
		);
1214
1215 138
		return $args;
1216
	}
1217
1218
	/**
1219
	 * Sets default arguments for the group field types.
1220
	 *
1221
	 * @since 2.2.6
1222
	 *
1223
	 * @param  array  $args Field config array.
1224
	 * @return array        Modified field config array.
1225
	 */
1226 5
	protected function set_field_defaults_group( $args ) {
1227 5
		$args['options'] = wp_parse_args( $args['options'], array(
1228 5
			'add_button'    => esc_html__( 'Add Group', 'cmb2' ),
1229 5
			'remove_button' => esc_html__( 'Remove Group', 'cmb2' ),
1230 5
		) );
1231
1232 5
		return $args;
1233
	}
1234
1235
	/**
1236
	 * Sets default arguments for the wysiwyg field types.
1237
	 *
1238
	 * @since 2.2.6
1239
	 *
1240
	 * @param  array  $args Field config array.
1241
	 * @return array        Modified field config array.
1242
	 */
1243 1
	protected function set_field_defaults_wysiwyg( $args ) {
1244 1
		$args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
1245 1
		$args['options']['textarea_name'] = $args['_name'];
1246
1247 1
		return $args;
1248
	}
1249
1250
	/**
1251
	 * Sets default arguments for the all-or-nothing field types.
1252
	 *
1253
	 * @since 2.2.6
1254
	 *
1255
	 * @param  array  $args Field config array.
1256
	 * @return array        Modified field config array.
1257
	 */
1258 18
	protected function set_field_defaults_all_or_nothing_types( $args ) {
1259 18
		$args['show_option_none'] = isset( $args['show_option_none'] ) ? $args['show_option_none'] : null;
1260 18
		$args['show_option_none'] = true === $args['show_option_none'] ? esc_html__( 'None', 'cmb2' ) : $args['show_option_none'];
1261
1262 18
		if ( null === $args['show_option_none'] ) {
1263 17
			$off_by_default = in_array( $args['type'], array( 'select', 'radio', 'radio_inline' ), true );
1264 17
			$args['show_option_none'] = $off_by_default ? false : esc_html__( 'None', 'cmb2' );
1265 17
		}
1266
1267 18
		return $args;
1268
	}
1269
1270
	/**
1271
	 * Sets default arguments for group sub-fields.
1272
	 *
1273
	 * @since 2.2.6
1274
	 *
1275
	 * @param  array  $args Field config array.
1276
	 * @return array        Modified field config array.
1277
	 */
1278 4
	protected function set_group_sub_field_defaults( $args ) {
1279 4
		$args['id']    = $this->group->args( 'id' ) . '_' . $this->group->index . '_' . $args['id'];
1280 4
		$args['_name'] = $this->group->args( 'id' ) . '[' . $this->group->index . '][' . $args['_name'] . ']';
1281
1282 4
		return $args;
1283
	}
1284
1285
	/**
1286
	 * Gets the default arguments for all fields.
1287
	 *
1288
	 * @since 2.2.6
1289
	 *
1290
	 * @param  array  $args Field config array.
1291
	 * @return array        Field defaults.
1292
	 */
1293 138
	protected function get_default_field_args( $args ) {
1294 138
		$type = isset( $args['type'] ) ? $args['type'] : '';
1295
1296
		return array(
1297 138
			'type'              => $type,
1298 138
			'name'              => '',
1299 138
			'desc'              => '',
1300 138
			'before'            => '',
1301 138
			'after'             => '',
1302 138
			'options'           => array(),
1303 138
			'options_cb'        => '',
1304 138
			'text'              => array(),
1305 138
			'text_cb'           => '',
1306 138
			'attributes'        => array(),
1307 138
			'protocols'         => null,
1308 138
			'default'           => null,
1309 138
			'default_cb'        => '',
1310 138
			'classes'           => null,
1311 138
			'classes_cb'        => '',
1312 138
			'select_all_button' => true,
1313 138
			'multiple'          => false,
1314 138
			'repeatable'        => 'group' === $type,
1315 138
			'inline'            => false,
1316 138
			'on_front'          => true,
1317 138
			'show_names'        => true,
1318 138
			'save_field'        => true, // Will not save if false
1319 138
			'date_format'       => 'm\/d\/Y',
1320 138
			'time_format'       => 'h:i A',
1321 138
			'description'       => isset( $args['desc'] ) ? $args['desc'] : '',
1322 138
			'preview_size'      => 'file' === $type ? array( 350, 350 ) : array( 50, 50 ),
1323 138
			'render_row_cb'     => array( $this, 'render_field_callback' ),
1324 138
			'display_cb'        => array( $this, 'display_value_callback' ),
1325 138
			'label_cb'          => 'title' !== $type ? array( $this, 'label' ) : '',
1326 138
			'column'            => false,
1327 138
			'js_dependencies'   => array(),
1328 138
			'show_in_rest'      => null,
1329 138
		);
1330
	}
1331
1332
	/**
1333
	 * Get default field arguments specific to this CMB2 object.
1334
	 *
1335
	 * @since  2.2.0
1336
	 * @param  array      $field_args  Metabox field config array.
1337
	 * @param  CMB2_Field $field_group (optional) CMB2_Field object (group parent)
1338
	 * @return array                   Array of field arguments.
1339
	 */
1340 8
	protected function get_default_args( $field_args, $field_group = null ) {
1341 8
		$args = parent::get_default_args( array(), $this->group );
1342
1343 8
		if ( isset( $field_args['field_args'] ) ) {
1344
			$args = wp_parse_args( $field_args, $args );
1345
		} else {
1346 8
			$args['field_args'] = wp_parse_args( $field_args, $this->args );
1347
		}
1348
1349 8
		return $args;
1350
	}
1351
1352
	/**
1353
	 * Returns a cloned version of this field object, but with
1354
	 * modified/overridden field arguments.
1355
	 *
1356
	 * @since  2.2.2
1357
	 * @param  array $field_args Array of field arguments, or entire array of
1358
	 *                           arguments for CMB2_Field
1359
	 *
1360
	 * @return CMB2_Field         The new CMB2_Field instance.
1361
	 */
1362 8
	public function get_field_clone( $field_args ) {
1363 8
		return $this->get_new_field( $field_args );
1364
	}
1365
1366
	/**
1367
	 * Returns the CMB2 instance this field is registered to.
1368
	 *
1369
	 * @since  2.2.2
1370
	 *
1371
	 * @return CMB2|WP_Error If new CMB2_Field is called without cmb_id arg, returns error.
1372
	 */
1373 2
	public function get_cmb() {
1374 2
		if ( ! $this->cmb_id ) {
1375
			return new WP_Error( 'no_cmb_id', esc_html__( 'Sorry, this field does not have a cmb_id specified.', 'cmb2' ) );
1376
		}
1377
1378 2
		return cmb2_get_metabox( $this->cmb_id, $this->object_id, $this->object_type );
1379
	}
1380
1381
	/**
1382
	 * Converts deprecated field parameters to the current/proper parameter, and throws a deprecation notice.
1383
	 *
1384
	 * @since 2.2.3
1385
	 * @param array                                   $args Metabox field config array.
1386
	 * @param array       Modified field config array.
0 ignored issues
show
The type Modified was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1387
	 */
1388 138
	protected function convert_deprecated_params( $args ) {
1389
1390 138
		if ( isset( $args['row_classes'] ) ) {
1391
1392
			// We'll let this one be.
1393
			// $this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_PARAM, 'row_classes', 'classes' );
1394
			// row_classes param could be a callback. This is definitely deprecated.
1395 2
			if ( is_callable( $args['row_classes'] ) ) {
1396
1397 1
				$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'row_classes', 'classes_cb' );
1398
1399 1
				$args['classes_cb'] = $args['row_classes'];
1400 1
				$args['classes'] = null;
1401 1
			} else {
1402
1403 1
				$args['classes'] = $args['row_classes'];
1404
			}
1405
1406 2
			unset( $args['row_classes'] );
1407 2
		}
1408
1409
		// default param can be passed a callback as well
1410 138
		if ( is_callable( $args['default'] ) ) {
1411
1412
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'default', 'default_cb' );
1413
1414
			$args['default_cb'] = $args['default'];
1415
			$args['default'] = null;
1416
		}
1417
1418
		// options param can be passed a callback as well
1419 138
		if ( is_callable( $args['options'] ) ) {
1420
1421
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'options', 'options_cb' );
1422
1423
			$args['options_cb'] = $args['options'];
1424
			$args['options'] = array();
1425
		}
1426
1427 138
		return $args;
1428
	}
1429
1430
}
1431