Completed
Pull Request — trunk (#867)
by
unknown
06:00
created

CMB2_Field::get_timestamp_format()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5.0144

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 12
nop 2
dl 0
loc 17
ccs 11
cts 12
cp 0.9167
crap 5.0144
rs 8.8571
c 0
b 0
f 0
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
	 * @var   string
22
	 * @since 2.2.3
23
	 */
24
	protected $properties_name = 'args';
25
26
	/**
27
	 * Field arguments
28
	 * @var   mixed
29
	 * @since 1.1.0
30
	 */
31
	public $args = array();
32
33
	/**
34
	 * Field group object or false (if no group)
35
	 * @var   mixed
36
	 * @since 1.1.0
37
	 */
38
	public $group = false;
39
40
	/**
41
	 * Field meta value
42
	 * @var   mixed
43
	 * @since 1.1.0
44
	 */
45
	public $value = null;
46
47
	/**
48
	 * Field meta value
49
	 * @var   mixed
50
	 * @since 1.1.0
51
	 */
52
	public $escaped_value = null;
53
54
	/**
55
	 * Grouped Field's current numeric index during the save process
56
	 * @var   mixed
57
	 * @since 2.0.0
58
	 */
59
	public $index = 0;
60
61
	/**
62
	 * Array of field options
63
	 * @var   array
64
	 * @since 2.0.0
65
	 */
66
	protected $field_options = array();
67
68
	/**
69
	 * Array of provided field text strings
70
	 * @var   array
71
	 * @since 2.0.0
72
	 */
73
	protected $strings;
74
75
	/**
76
	 * The field's render context. In most cases, 'edit', but can be 'display'.
77
	 * @var   string
78
	 * @since 2.2.2
79
	 */
80
	public $render_context = 'edit';
81
82
	/**
83
	 * All CMB2_Field callable field arguments.
84
	 * Can be used to determine if a field argument is callable.
85
	 *
86
	 * @var array
87
	 */
88
	public static $callable_fields = array(
89
		'default_cb',
90
		'classes_cb',
91
		'options_cb',
92
		'text_cb',
93
		'label_cb',
94
		'render_row_cb',
95
		'display_cb',
96
		'before_group',
97
		'before_group_row',
98
		'before_row',
99
		'before',
100
		'before_field',
101
		'after_field',
102
		'after',
103
		'after_row',
104
		'after_group_row',
105
		'after_group',
106
	);
107
108
	/**
109
	 * Constructs our field object
110
	 * @since 1.1.0
111
	 * @param array $args Field arguments
112
	 */
113 111
	public function __construct( $args ) {
114
115 111
		if ( ! empty( $args['group_field'] ) ) {
116 4
			$this->group       = $args['group_field'];
117 4
			$this->object_id   = $this->group->object_id;
118 4
			$this->object_type = $this->group->object_type;
119 4
			$this->cmb_id      = $this->group->cmb_id;
120 4
		} else {
121 111
			$this->object_id   = isset( $args['object_id'] ) && '_' !== $args['object_id'] ? $args['object_id'] : 0;
122 111
			$this->object_type = isset( $args['object_type'] ) ? $args['object_type'] : 'post';
123
124 111
			if ( isset( $args['cmb_id'] ) ) {
125 43
				$this->cmb_id = $args['cmb_id'];
126 43
			}
127
		}
128
129 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...
130
131 111
		if ( $this->object_id ) {
132 103
			$this->value = $this->get_data();
133 103
		}
134 111
	}
135
136
	/**
137
	 * Non-existent methods fallback to checking for field arguments of the same name
138
	 * @since  1.1.0
139
	 * @param  string $name     Method name
140
	 * @param  array  $arguments Array of passed-in arguments
141
	 * @return mixed             Value of field argument
142
	 */
143 100
	public function __call( $name, $arguments ) {
144 100
		if ( 'string' === $name ) {
145
			return call_user_func_array( array( $this, 'get_string' ), $arguments );
146
		}
147
148 100
		$key = isset( $arguments[0] ) ? $arguments[0] : false;
149 100
		return $this->args( $name, $key );
150
	}
151
152
	/**
153
	 * Retrieves the field id
154
	 * @since  1.1.0
155
	 * @param  boolean $raw Whether to retrieve pre-modidifed id
156
	 * @return string       Field id
157
	 */
158 109
	public function id( $raw = false ) {
159 109
		$id = $raw ? '_id' : 'id';
160 109
		return $this->args( $id );
161 1
	}
162
163
	/**
164
	 * Get a field argument
165
	 * @since  1.1.0
166
	 * @param  string $key  Argument to check
167
	 * @param  string $_key Sub argument to check
168
	 * @return mixed        Argument value or false if non-existent
169
	 */
170 112
	public function args( $key = '', $_key = '' ) {
171 112
		$arg = $this->_data( 'args', $key );
172
173 112
		if ( in_array( $key, array( 'default', 'default_cb' ), true ) ) {
174
175 1
			$arg = $this->get_default();
176
177 112
		} elseif ( $_key ) {
178
179
			$arg = isset( $arg[ $_key ] ) ? $arg[ $_key ] : false;
180
		}
181
182 112
		return $arg;
183
	}
184
185
	/**
186
	 * Retrieve a portion of a field property
187
	 * @since  1.1.0
188
	 * @param  string  $var Field property to check
189
	 * @param  string  $key Field property array key to check
190
	 * @return mixed        Queried property value or false
191
	 */
192 112
	public function _data( $var, $key = '' ) {
193 112
		$vars = $this->{$var};
194 112
		if ( $key ) {
195 112
			return array_key_exists( $key, $vars ) ? $vars[ $key ] : false;
196
		}
197 62
		return $vars;
198
	}
199
200
	/**
201
	 * Get Field's value
202
	 * @since  1.1.0
203
	 * @param  string $key If value is an array, is used to get array key->value
204
	 * @return mixed       Field value or false if non-existent
205
	 */
206 47
	public function value( $key = '' ) {
207 47
		return $this->_data( 'value', $key );
208
	}
209
210
	/**
211
	 * Retrieves metadata/option data
212
	 * @since  1.0.1
213
	 * @param  string $field_id Meta key/Option array key
214
	 * @param  array  $args     Override arguments
215
	 * @return mixed            Meta/Option value
216
	 */
217 107
	public function get_data( $field_id = '', $args = array() ) {
218 107
		if ( $field_id ) {
219
			$args['field_id'] = $field_id;
220 107
		} else if ( $this->group ) {
221
			$args['field_id'] = $this->group->id();
222
		}
223
224 107
		$a = $this->data_args( $args );
225
226
		/**
227
		 * Filter whether to override getting of meta value.
228
		 * Returning a non 'cmb2_field_no_override_val' value
229
		 * will effectively short-circuit the value retrieval.
230
		 *
231
		 * @since 2.0.0
232
		 *
233
		 * @param mixed $value     The value get_metadata() should
234
		 *                         return - a single metadata value,
235
		 *                         or an array of values.
236
		 *
237
		 * @param int   $object_id Object ID.
238
		 *
239
		 * @param array $args {
240
		 *     An array of arguments for retrieving data
241
		 *
242
		 *     @type string $type     The current object type
243
		 *     @type int    $id       The current object ID
244
		 *     @type string $field_id The ID of the field being requested
245
		 *     @type bool   $repeat   Whether current field is repeatable
246
		 *     @type bool   $single   Whether current field is a single database row
247
		 * }
248
		 *
249
		 * @param CMB2_Field object $field This field object
250
		 */
251 107
		$data = apply_filters( 'cmb2_override_meta_value', 'cmb2_field_no_override_val', $this->object_id, $a, $this );
252
253
		/**
254
		 * Filter and parameters are documented for 'cmb2_override_meta_value' filter (above).
255
		 *
256
		 * The dynamic portion of the hook, $field_id, refers to the current
257
		 * field id paramater. Returning a non 'cmb2_field_no_override_val' value
258
		 * will effectively short-circuit the value retrieval.
259
		 *
260
		 * @since 2.0.0
261
		 */
262 107
		$data = apply_filters( "cmb2_override_{$a['field_id']}_meta_value", $data, $this->object_id, $a, $this );
263
264
		// If no override, get value normally
265 107
		if ( 'cmb2_field_no_override_val' === $data ) {
266 104
			$data = 'options-page' === $a['type']
267 104
				? cmb2_options( $a['id'] )->get( $a['field_id'] )
268 104
				: get_metadata( $a['type'], $a['id'], $a['field_id'], ( $a['single'] || $a['repeat'] ) );
269 104
		}
270
271 107
		if ( $this->group ) {
272
273
			$data = is_array( $data ) && isset( $data[ $this->group->index ][ $this->args( '_id' ) ] )
274
				? $data[ $this->group->index ][ $this->args( '_id' ) ]
275
				: false;
276
		}
277
278 107
		return $data;
279
	}
280
281
	/**
282
	 * Updates metadata/option data
283
	 * @since  1.0.1
284
	 * @param  mixed $new_value Value to update data with
285
	 * @param  bool  $single    Whether data is an array (add_metadata)
286
	 */
287 13
	public function update_data( $new_value, $single = true ) {
288 13
		$a = $this->data_args( array( 'single' => $single ) );
289
290 13
		$a['value'] = $a['repeat'] ? array_values( $new_value ) : $new_value;
291
292
		/**
293
		 * Filter whether to override saving of meta value.
294
		 * Returning a non-null value will effectively short-circuit the function.
295
		 *
296
		 * @since 2.0.0
297
		 *
298
		 * @param null|bool $check  Whether to allow updating metadata for the given type.
299
		 *
300
		 * @param array $args {
301
		 *     Array of data about current field including:
302
		 *
303
		 *     @type string $value    The value to set
304
		 *     @type string $type     The current object type
305
		 *     @type int    $id       The current object ID
306
		 *     @type string $field_id The ID of the field being updated
307
		 *     @type bool   $repeat   Whether current field is repeatable
308
		 *     @type bool   $single   Whether current field is a single database row
309
		 * }
310
		 *
311
		 * @param array $field_args All field arguments
312
		 *
313
		 * @param CMB2_Field object $field This field object
314
		 */
315 13
		$override = apply_filters( 'cmb2_override_meta_save', null, $a, $this->args(), $this );
316
317
		/**
318
		 * Filter and parameters are documented for 'cmb2_override_meta_save' filter (above).
319
		 *
320
		 * The dynamic portion of the hook, $a['field_id'], refers to the current
321
		 * field id paramater. Returning a non-null value
322
		 * will effectively short-circuit the function.
323
		 *
324
		 * @since 2.0.0
325
		 */
326 13
		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_save", $override, $a, $this->args(), $this );
327
328
		// If override, return that
329 13
		if ( null !== $override ) {
330 2
			return $override;
331
		}
332
333
		// Options page handling (or temp data store)
334 12
		if ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
335 5
			return cmb2_options( $a['id'] )->update( $a['field_id'], $a['value'], false, $a['single'] );
336
		}
337
338
		// Add metadata if not single
339 7
		if ( ! $a['single'] ) {
340 1
			return add_metadata( $a['type'], $a['id'], $a['field_id'], $a['value'], false );
341
		}
342
343
		// Delete meta if we have an empty array
344 6
		if ( is_array( $a['value'] ) && empty( $a['value'] ) ) {
345
			return delete_metadata( $a['type'], $a['id'], $a['field_id'], $this->value );
346
		}
347
348
		// Update metadata
349 6
		return update_metadata( $a['type'], $a['id'], $a['field_id'], $a['value'] );
350
	}
351
352
	/**
353
	 * Removes/updates metadata/option data
354
	 * @since  1.0.1
355
	 * @param  string $old Old value
356
	 */
357 3
	public function remove_data( $old = '' ) {
358 3
		$a = $this->data_args( array( 'old' => $old ) );
359
360
		/**
361
		 * Filter whether to override removing of meta value.
362
		 * Returning a non-null value will effectively short-circuit the function.
363
		 *
364
		 * @since 2.0.0
365
		 *
366
		 * @param null|bool $delete Whether to allow metadata deletion of the given type.
367
		 * @param array $args       Array of data about current field including:
368
		 *                              'type'     : Current object type
369
		 *                              'id'       : Current object ID
370
		 *                              'field_id' : Current Field ID
371
		 *                              'repeat'   : Whether current field is repeatable
372
		 *                              'single'   : Whether to save as a
373
		 *                              					single meta value
374
		 * @param array $field_args All field arguments
375
		 * @param CMB2_Field object $field This field object
376
		 */
377 3
		$override = apply_filters( 'cmb2_override_meta_remove', null, $a, $this->args(), $this );
378
379
		/**
380
		 * Filter whether to override removing of meta value.
381
		 *
382
		 * The dynamic portion of the hook, $a['field_id'], refers to the current
383
		 * field id paramater. Returning a non-null value
384
		 * 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 3
		$override = apply_filters( "cmb2_override_{$a['field_id']}_meta_remove", $override, $a, $this->args(), $this );
400
401
		// If no override, remove as usual
402 3
		if ( null !== $override ) {
403
			return $override;
404
		}
405
		// Option page handling
406 3
		elseif ( 'options-page' === $a['type'] || empty( $a['id'] ) ) {
407 1
			return cmb2_options( $a['id'] )->remove( $a['field_id'] );
408
		}
409
410
		// Remove metadata
411 2
		return delete_metadata( $a['type'], $a['id'], $a['field_id'], $old );
412
	}
413
414
	/**
415
	 * Data variables for get/set data methods
416
	 * @since  1.1.0
417
	 * @param  array $args Override arguments
418
	 * @return array       Updated arguments
419
	 */
420 107
	public function data_args( $args = array() ) {
421 107
		$args = wp_parse_args( $args, array(
422 107
			'type'     => $this->object_type,
423 107
			'id'       => $this->object_id,
424 107
			'field_id' => $this->id( true ),
425 107
			'repeat'   => $this->args( 'repeatable' ),
426 107
			'single'   => ! $this->args( 'multiple' ),
427 107
		) );
428 107
		return $args;
429
	}
430
431
	/**
432
	 * Checks if field has a registered sanitization callback
433
	 * @since  1.0.1
434
	 * @param  mixed $meta_value Meta value
435
	 * @return mixed             Possibly sanitized meta value
436
	 */
437 15
	public function sanitization_cb( $meta_value ) {
438
439 15
		if ( $this->args( 'repeatable' ) && is_array( $meta_value ) ) {
440
			// Remove empties
441 2
			$meta_value = array_filter( $meta_value );
442 2
		}
443
444
		// Check if the field has a registered validation callback
445 15
		$cb = $this->maybe_callback( 'sanitization_cb' );
446 15
		if ( false === $cb ) {
447
			// If requesting NO validation, return meta value
448 1
			return $meta_value;
449 14
		} elseif ( $cb ) {
450
			// Ok, callback is good, let's run it.
451
			return call_user_func( $cb, $meta_value, $this->args(), $this );
452
		}
453
454 14
		$sanitizer = new CMB2_Sanitize( $this, $meta_value );
455
456
		/**
457
		 * Filter the value before it is saved.
458
		 *
459
		 * The dynamic portion of the hook name, $this->type(), refers to the field type.
460
		 *
461
		 * Passing a non-null value to the filter will short-circuit saving
462
		 * the field value, saving the passed value instead.
463
		 *
464
		 * @param bool|mixed $override_value Sanitization/Validation override value to return.
465
		 *                                   Default false to skip it.
466
		 * @param mixed      $value      The value to be saved to this field.
467
		 * @param int        $object_id  The ID of the object where the value will be saved
468
		 * @param array      $field_args The current field's arguments
469
		 * @param object     $sanitizer  This `CMB2_Sanitize` object
470
		 */
471 14
		$override_value = apply_filters( "cmb2_sanitize_{$this->type()}", null, $sanitizer->value, $this->object_id, $this->args(), $sanitizer );
472
473 14
		if ( null !== $override_value ) {
474 1
			return $override_value;
475
		}
476
477
		// Sanitization via 'CMB2_Sanitize'
478 13
		return $sanitizer->{$this->type()}();
479
	}
480
481
	/**
482
	 * Process $_POST data to save this field's value
483
	 * @since  2.0.3
484
	 * @param  array $data_to_save $_POST data to check
485
	 * @return array|int|bool                Result of save, false on failure
486
	 */
487 3
	public function save_field_from_data( array $data_to_save ) {
488 3
		$this->data_to_save = $data_to_save;
489
490 3
		$meta_value = isset( $this->data_to_save[ $this->id( true ) ] )
491 3
			? $this->data_to_save[ $this->id( true ) ]
492 3
			: null;
493
494 3
		return $this->save_field( $meta_value );
495
	}
496
497
	/**
498
	 * Sanitize/store a value to this field
499
	 * @since  2.0.0
500
	 * @param  array $meta_value Desired value to sanitize/store
501
	 * @return array|int|bool              Result of save. false on failure
502
	 */
503 13
	public function save_field( $meta_value ) {
504
505 13
		$updated   = false;
506 13
		$action    = '';
507 13
		$new_value = $this->sanitization_cb( $meta_value );
508
509 13
		if ( ! $this->args( 'save_field' ) ) {
510
511
			// Nothing to see here.
512 1
			$action = 'disabled';
513
514 13
		} elseif ( $this->args( 'multiple' ) && ! $this->args( 'repeatable' ) && ! $this->group ) {
515
516 1
			$this->remove_data();
517 1
			$count = 0;
518
519 1
			if ( ! empty( $new_value ) ) {
520 1
				foreach ( $new_value as $add_new ) {
521 1
					if ( $this->update_data( $add_new, false ) ) {
522 1
						$count++;
523 1
					}
524 1
				}
525 1
			}
526
527 1
			$updated = $count ? $count : false;
528 1
			$action  = 'repeatable';
529
530 12
		} elseif ( ! CMB2_Utils::isempty( $new_value ) && $new_value !== $this->get_data() ) {
531 10
			$updated = $this->update_data( $new_value );
532 10
			$action  = 'updated';
533 11
		} elseif ( CMB2_Utils::isempty( $new_value ) ) {
534 2
			$updated = $this->remove_data();
535 2
			$action  = 'removed';
536 2
		}
537
538 13
		if ( $updated ) {
539 12
			$this->value = $this->get_data();
540 12
			$this->escaped_value = null;
541 12
		}
542
543 13
		$field_id = $this->id( true );
544
545
		/**
546
		 * Hooks after save field action.
547
		 *
548
		 * @since 2.2.0
549
		 *
550
		 * @param string            $field_id the current field id paramater.
551
		 * @param bool              $updated  Whether the metadata update action occurred.
552
		 * @param string            $action   Action performed. Could be "repeatable", "updated", or "removed".
553
		 * @param CMB2_Field object $field    This field object
554
		 */
555 13
		do_action( 'cmb2_save_field', $field_id, $updated, $action, $this );
556
557
		/**
558
		 * Hooks after save field action.
559
		 *
560
		 * The dynamic portion of the hook, $field_id, refers to the
561
		 * current field id paramater.
562
		 *
563
		 * @since 2.2.0
564
		 *
565
		 * @param bool              $updated Whether the metadata update action occurred.
566
		 * @param string            $action  Action performed. Could be "repeatable", "updated", or "removed".
567
		 * @param CMB2_Field object $field   This field object
568
		 */
569 12
		do_action( "cmb2_save_field_{$field_id}", $updated, $action, $this );
570
571 11
		return $updated;
572
	}
573
574
	/**
575
	 * Determine if current type is exempt from escaping
576
	 * @since  1.1.0
577
	 * @return bool  True if exempt
578
	 */
579 47
	public function escaping_exception() {
580
		// These types cannot be escaped
581 47
		return in_array( $this->type(), array(
582 47
			'file_list',
583 47
			'multicheck',
584 47
			'text_datetime_timestamp_timezone',
585 47
		) );
586
	}
587
588
	/**
589
	 * Determine if current type cannot be repeatable
590
	 * @since  1.1.0
591
	 * @param  string $type Field type to check
592
	 * @return bool         True if type cannot be repeatable
593
	 */
594 5
	public function repeatable_exception( $type ) {
595
		// These types cannot be repeatable.
596
		$internal_fields = array(
597
			// Use file_list instead
598 5
			'file'                => 1,
599 5
			'radio'               => 1,
600 5
			'title'               => 1,
601 5
			'wysiwyg'             => 1,
602 5
			'checkbox'            => 1,
603 5
			'radio_inline'        => 1,
604 5
			'taxonomy_radio'      => 1,
605 5
			'taxonomy_select'     => 1,
606 5
			'taxonomy_multicheck' => 1,
607 5
		);
608
609
		/**
610
		 * Filter field types that are non-repeatable.
611
		 *
612
		 * Note that this does *not* allow overriding the default non-repeatable types.
613
		 *
614
		 * @since 2.1.1
615
		 *
616
		 * @param array $fields Array of fields designated as non-repeatable. Note that the field names are *keys*,
617
		 *                      and not values. The value can be anything, because it is meaningless. Example:
618
		 *                      array( 'my_custom_field' => 1 )
619
		 */
620 5
		$all_fields = array_merge( apply_filters( 'cmb2_non_repeatable_fields', array() ), $internal_fields );
621 5
		return isset( $all_fields[ $type ] );
622
	}
623
624
	/**
625
	 * Escape the value before output. Defaults to 'esc_attr()'
626
	 * @since  1.0.1
627
	 * @param  callable $func       Escaping function (if not esc_attr())
628
	 * @param  mixed    $meta_value Meta value
629
	 * @return mixed                Final value
630
	 */
631 47
	public function escaped_value( $func = 'esc_attr', $meta_value = '' ) {
632
633 47
		if ( null !== $this->escaped_value ) {
634 28
			return $this->escaped_value;
635
		}
636
637 47
		$meta_value = $meta_value ? $meta_value : $this->value();
638
639
		// Check if the field has a registered escaping callback
640 47
		if ( $cb = $this->maybe_callback( 'escape_cb' ) ) {
641
			// Ok, callback is good, let's run it.
642
			return call_user_func( $cb, $meta_value, $this->args(), $this );
643
		}
644
645
		// Or custom escaping filter can be used
646 47
		$esc = apply_filters( "cmb2_types_esc_{$this->type()}", null, $meta_value, $this->args(), $this );
647 47
		if ( null !== $esc ) {
648
			return $esc;
649
		}
650
651 47
		if ( false === $cb || $this->escaping_exception() ) {
652
			// If requesting NO escaping, return meta value
653 5
			return $this->val_or_default( $meta_value );
654
		}
655
656
		// escaping function passed in?
657 42
		$func       = $func ? $func : 'esc_attr';
658 42
		$meta_value = $this->val_or_default( $meta_value );
659
660 42
		if ( is_array( $meta_value ) ) {
661
			foreach ( $meta_value as $key => $value ) {
662
				$meta_value[ $key ] = call_user_func( $func, $value );
663
			}
664
		} else {
665 42
			$meta_value = call_user_func( $func, $meta_value );
666
		}
667
668 42
		$this->escaped_value = $meta_value;
669 42
		return $this->escaped_value;
670
	}
671
672
	/**
673
	 * Return non-empty value or field default if value IS empty
674
	 * @since  2.0.0
675
	 * @param  mixed $meta_value Field value
676
	 * @return mixed             Field value, or default value
677
	 */
678 47
	public function val_or_default( $meta_value ) {
679 47
		return ! CMB2_Utils::isempty( $meta_value ) ? $meta_value : $this->get_default();
680
	}
681
682
	/**
683
	 * Offset a time value based on timezone
684
	 * @since  1.0.0
685
	 * @return string Offset time string
686
	 */
687
	public function field_timezone_offset() {
688
		return CMB2_Utils::timezone_offset( $this->field_timezone() );
689
	}
690
691
	/**
692
	 * Return timezone string
693
	 * @since  1.0.0
694
	 * @return string Timezone string
695
	 */
696
	public function field_timezone() {
697
		$value = '';
698
699
		// Is timezone arg set?
700
		if ( $this->args( 'timezone' ) ) {
701
			$value = $this->args( 'timezone' );
702
		}
703
		// Is there another meta key with a timezone stored as its value we should use?
704
		else if ( $this->args( 'timezone_meta_key' ) ) {
705
			$value = $this->get_data( $this->args( 'timezone_meta_key' ) );
706
		}
707
708
		return $value;
709
	}
710
711
	/**
712
	 * Format the timestamp field value based on the field date/time format arg
713
	 * @since  2.0.0
714
	 * @param  int    $meta_value Timestamp
715
	 * @param  string $format     Either date_format or time_format
716
	 * @return string             Formatted date
717
	 */
718 5
	public function format_timestamp( $meta_value, $format = 'date_format' ) {
719 5
		return date( stripslashes( $this->args( $format ) ), $meta_value );
720
	}
721
722
	/**
723
	 * Return a formatted timestamp for a field
724
	 * @since  2.0.0
725
	 * @param  string $format     Either date_format or time_format
726
	 * @param  string $meta_value Optional meta value to check
727
	 * @return string             Formatted date
728
	 */
729 10
	public function get_timestamp_format( $format = 'date_format', $meta_value = 0 ) {
730 10
		$meta_value = $meta_value ? $meta_value : $this->escaped_value();
731 10
		$date_format = $this->args( 'date_format' );
732 10
		if ( ! empty( $date_format ) ) {
733 10
			$meta_value = CMB2_Utils::get_timestamp_from_value( $meta_value, $date_format );
734 10
		} else {
735
			$meta_value = CMB2_Utils::make_valid_time_stamp( $meta_value );
736
		}
737
738 10
		if ( empty( $meta_value ) ) {
739 8
			return '';
740
		}
741
742 2
		return is_array( $meta_value )
743 2
			? array_map( array( $this, 'format_timestamp' ), $meta_value, $format )
744 2
			: $this->format_timestamp( $meta_value, $format );
745
	}
746
747
	/**
748
	 * Get timestamp from text date
749
	 * @since  2.2.0
750
	 * @param  string $value Date value
751
	 * @return mixed         Unix timestamp representing the date.
752
	 */
753
	public function get_timestamp_from_value( $value ) {
754
		return CMB2_Utils::get_timestamp_from_value( $value, $this->args( 'date_format' ) );
755
	}
756
757
	/**
758
	 * Get field render callback and Render the field row
759
	 * @since 1.0.0
760
	 */
761 10
	public function render_field() {
762 10
		$this->render_context = 'edit';
763
764 10
		$this->peform_param_callback( 'render_row_cb' );
765
766
		// For chaining
767 10
		return $this;
768
	}
769
770
	/**
771
	 * Default field render callback
772
	 * @since 2.1.1
773
	 */
774 9
	public function render_field_callback() {
775
776
		// If field is requesting to not be shown on the front-end
777 9
		if ( ! is_admin() && ! $this->args( 'on_front' ) ) {
778
			return;
779
		}
780
781
		// If field is requesting to be conditionally shown
782 9
		if ( ! $this->should_show() ) {
783
			return;
784
		}
785
786 9
		$this->peform_param_callback( 'before_row' );
787
788 9
		printf( "<div class=\"cmb-row %s\" data-fieldtype=\"%s\">\n", $this->row_classes(), $this->type() );
789
790 9
		if ( ! $this->args( 'show_names' ) ) {
791
			echo "\n\t<div class=\"cmb-td\">\n";
792
793
			$this->peform_param_callback( 'label_cb' );
794
795
		} else {
796
797 9
			if ( $this->get_param_callback_result( 'label_cb' ) ) {
798 9
				echo '<div class="cmb-th">', $this->peform_param_callback( 'label_cb' ), '</div>';
799 9
			}
800
801 9
			echo "\n\t<div class=\"cmb-td\">\n";
802
		}
803
804 9
		$this->peform_param_callback( 'before' );
805
806 9
		$types = new CMB2_Types( $this );
807 9
		$types->render();
808
809 9
		$this->peform_param_callback( 'after' );
810
811 9
		echo "\n\t</div>\n</div>";
812
813 9
		$this->peform_param_callback( 'after_row' );
814
815
		// For chaining
816 9
		return $this;
817
	}
818
819
	/**
820
	 * The default label_cb callback (if not a title field)
821
	 *
822
	 * @since  2.1.1
823
	 * @return string Label html markup
824
	 */
825 9
	public function label() {
826 9
		if ( ! $this->args( 'name' ) ) {
827
			return '';
828
		}
829
830 9
		$style = ! $this->args( 'show_names' ) ? ' style="display:none;"' : '';
831
832 9
		return sprintf( "\n" . '<label%1$s for="%2$s">%3$s</label>' . "\n", $style, $this->id(), $this->args( 'name' ) );
833
	}
834
835
	/**
836
	 * Defines the classes for the current CMB2 field row
837
	 *
838
	 * @since  2.0.0
839
	 * @return string Space concatenated list of classes
840
	 */
841 45
	public function row_classes() {
842
843 45
		$classes = array();
844
845
		/**
846
		 * By default, 'text_url' and 'text' fields get table-like styling
847
		 *
848
		 * @since 2.0.0
849
		 *
850
		 * @param array $field_types The types of fields which should get the 'table-layout' class
851
		 */
852 45
		$repeat_table_rows_types = apply_filters( 'cmb2_repeat_table_row_types', array(
853 45
			'text_url', 'text',
854 45
		) );
855
856
		$conditional_classes = array(
857 45
			'cmb-type-' . str_replace( '_', '-', sanitize_html_class( $this->type() ) ) => true,
858 45
			'cmb2-id-' . str_replace( '_', '-', sanitize_html_class( $this->id() ) )    => true,
859 45
			'cmb-repeat'             => $this->args( 'repeatable' ),
860 45
			'cmb-repeat-group-field' => $this->group,
861 45
			'cmb-inline'             => $this->args( 'inline' ),
862 45
			'table-layout'           => 'edit' === $this->render_context && in_array( $this->type(), $repeat_table_rows_types ),
863 45
		);
864
865 45
		foreach ( $conditional_classes as $class => $condition ) {
866 45
			if ( $condition ) {
867 45
				$classes[] = $class;
868 45
			}
869 45
		}
870
871 45
		if ( $added_classes = $this->args( 'classes' ) ) {
872 1
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
873 45
		} elseif ( $added_classes = $this->get_param_callback_result( 'classes_cb' ) ) {
874 2
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
875 2
		}
876
877 45
		if ( $added_classes ) {
878 3
			$classes[] = esc_attr( $added_classes );
879 3
		}
880
881
		/**
882
		 * Globally filter row classes
883
		 *
884
		 * @since 2.0.0
885
		 *
886
		 * @param string            $classes Space-separated list of row classes
887
		 * @param CMB2_Field object $field   This field object
888
		 */
889 45
		return apply_filters( 'cmb2_row_classes', implode( ' ', $classes ), $this );
890
	}
891
892
893
894
	/**
895
	 * Get field display callback and render the display value in the column.
896
	 * @since 2.2.2
897
	 */
898 33
	public function render_column() {
899 33
		$this->render_context = 'display';
900
901 33
		$this->peform_param_callback( 'display_cb' );
902
903
		// For chaining
904 33
		return $this;
905
	}
906
907
	/**
908
	 * Default callback to outputs field value in a display format.
909
	 * @since 2.2.2
910
	 */
911 33
	public function display_value_callback() {
912
		// If field is requesting to be conditionally shown
913 33
		if ( ! $this->should_show() ) {
914
			return;
915
		}
916
917 33
		$display = new CMB2_Field_Display( $this );
918
919
		/**
920
		 * A filter to bypass the default display.
921
		 *
922
		 * The dynamic portion of the hook name, $this->type(), refers to the field type.
923
		 *
924
		 * Passing a non-null value to the filter will short-circuit the default display.
925
		 *
926
		 * @param bool|mixed         $pre_output Default null value.
927
		 * @param CMB2_Field         $field      This field object.
928
		 * @param CMB2_Field_Display $display    The `CMB2_Field_Display` object.
929
		 */
930 33
		$pre_output = apply_filters( "cmb2_pre_field_display_{$this->type()}", null, $this, $display );
931
932 33
		if ( null !== $pre_output ) {
933
			echo $pre_output;
934
			return;
935
		}
936
937 33
		$this->peform_param_callback( 'before_display_wrap' );
938
939 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...
940
941 33
		$this->peform_param_callback( 'before_display' );
942
943 33
		CMB2_Field_Display::get( $this )->display();
944
945 33
		$this->peform_param_callback( 'after_display' );
946
947 33
		echo "\n</div>";
948
949 33
		$this->peform_param_callback( 'after_display_wrap' );
950
951
		// For chaining
952 33
		return $this;
953
	}
954
955
	/**
956
	 * Replaces a hash key - {#} - with the repeatable index
957
	 * @since  1.2.0
958
	 * @param  string $value Value to update
959
	 * @return string        Updated value
960
	 */
961 2
	public function replace_hash( $value ) {
962
		// Replace hash with 1 based count
963 2
		return str_replace( '{#}', ( $this->index + 1 ), $value );
964
	}
965
966
	/**
967
	 * Retrieve text parameter from field's text array (if it has one), or use fallback text
968
	 * For back-compatibility, falls back to checking the options array.
969
	 *
970
	 * @since  2.2.2
971
	 * @param  string  $text_key Key in field's text array
972
	 * @param  string  $fallback Fallback text
973
	 * @return string            Text
974
	 */
975 10
	public function get_string( $text_key, $fallback ) {
976
		// If null, populate with our field strings values.
977 10
		if ( null === $this->strings ) {
978 10
			$this->strings = (array) $this->args['text'];
979
980 10 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...
981
				$strings = call_user_func( $this->args['text_cb'], $this );
982
983
				if ( $strings && is_array( $strings ) ) {
984
					$this->strings += $strings;
985
				}
986
			}
987 10
		}
988
989
		// If we have that string value, send it back.
990 10
		if ( isset( $this->strings[ $text_key ] ) ) {
991 1
			return $this->strings[ $text_key ];
992
		}
993
994
		// Check options for back-compat.
995 10
		$string = $this->options( $text_key );
996
997 10
		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 997 which is incompatible with the return type documented by CMB2_Field::get_string of type string.
Loading history...
998
	}
999
1000
	/**
1001
	 * Retrieve options args. Calls options_cb if it exists.
1002
	 * @since  2.0.0
1003
	 * @param  string  $key Specific option to retrieve
1004
	 * @return array        Array of options
1005
	 */
1006 32
	public function options( $key = '' ) {
1007 32
		if ( ! empty( $this->field_options ) ) {
1008 5
			if ( $key ) {
1009 5
				return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1010
			}
1011
1012 1
			return $this->field_options;
1013
		}
1014
1015 32
		$this->field_options = (array) $this->args['options'];
1016
1017 32 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...
1018 1
			$options = call_user_func( $this->args['options_cb'], $this );
1019
1020 1
			if ( $options && is_array( $options ) ) {
1021 1
				$this->field_options = $options + $this->field_options;
1022 1
			}
1023 1
		}
1024
1025 32
		if ( $key ) {
1026 11
			return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1027
		}
1028
1029 25
		return $this->field_options;
1030
	}
1031
1032
	/**
1033
	 * Store JS dependencies as part of the field args.
1034
	 * @since 2.2.0
1035
	 * @param array $dependencies Dependies to register for this field.
1036
	 */
1037 13
	public function add_js_dependencies( $dependencies = array() ) {
1038 13
		foreach ( (array) $dependencies as $dependency ) {
1039 13
			$this->args['js_dependencies'][ $dependency ] = $dependency;
1040 13
		}
1041
1042 13
		CMB2_JS::add_dependencies( $dependencies );
1043 13
	}
1044
1045
	/**
1046
	 * Get CMB2_Field default value, either from default param or default_cb param.
1047
	 *
1048
	 * @since  0.2.2
1049
	 *
1050
	 * @return mixed  Default field value
1051
	 */
1052 35
	public function get_default() {
1053 35
		if ( null !== $this->args['default'] ) {
1054 8
			return $this->args['default'];
1055
		}
1056
1057 34
		$param = is_callable( $this->args['default_cb'] ) ? 'default_cb' : 'default';
1058 34
		$default = $this->get_param_callback_result( $param );
1059
1060
		// Allow a filter override of the default value
1061 34
		$this->args['default'] = apply_filters( 'cmb2_default_filter', $default, $this );
1062
1063 34
		return $this->args['default'];
1064
	}
1065
1066
	/**
1067
	 * Fills in empty field parameters with defaults
1068
	 * @since 1.1.0
1069
	 * @param array $args Metabox field config array
1070
	 * @param array       Modified field config array.
1071
	 */
1072 111
	public function _set_field_defaults( $args ) {
1073
1074
		// Set up blank or default values for empty ones
1075 111
		$args = wp_parse_args( $args, array(
1076 111
			'type'              => '',
1077 111
			'name'              => '',
1078 111
			'desc'              => '',
1079 111
			'before'            => '',
1080 111
			'after'             => '',
1081 111
			'options'           => array(),
1082 111
			'options_cb'        => '',
1083 111
			'text'              => array(),
1084 111
			'text_cb'           => '',
1085 111
			'attributes'        => array(),
1086 111
			'protocols'         => null,
1087 111
			'default'           => null,
1088 111
			'default_cb'        => '',
1089 111
			'classes'           => null,
1090 111
			'classes_cb'        => '',
1091 111
			'select_all_button' => true,
1092 111
			'multiple'          => false,
1093 111
			'repeatable'        => isset( $args['type'] ) && 'group' == $args['type'],
1094 111
			'inline'            => false,
1095 111
			'on_front'          => true,
1096 111
			'show_names'        => true,
1097 111
			'save_field'        => true, // Will not save if false
1098 111
			'date_format'       => 'm\/d\/Y',
1099 111
			'time_format'       => 'h:i A',
1100 111
			'description'       => isset( $args['desc'] ) ? $args['desc'] : '',
1101 111
			'preview_size'      => 'file' == $args['type'] ? array( 350, 350 ) : array( 50, 50 ),
1102 111
			'render_row_cb'     => array( $this, 'render_field_callback' ),
1103 111
			'display_cb'        => array( $this, 'display_value_callback' ),
1104 111
			'label_cb'          => 'title' != $args['type'] ? array( $this, 'label' ) : '',
1105 111
			'column'            => false,
1106 111
			'js_dependencies'   => array(),
1107 111
			'show_in_rest'      => null,
1108 111
		) );
1109
1110
		/*
1111
		 * Deprecated usage:
1112
		 *
1113
		 * 'std' -- use 'default' (no longer works)
1114
		 * 'row_classes' -- use 'class', or 'class_cb'
1115
		 * 'default' -- as callback (use default_cb)
1116
		 */
1117 111
		$args = $this->convert_deprecated_params( $args );
1118
1119 111
		$args['repeatable'] = $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
1120 111
		$args['inline']     = $args['inline'] || false !== stripos( $args['type'], '_inline' );
1121
1122 111
		$args['options']    = 'group' == $args['type'] ? wp_parse_args( $args['options'], array(
1123 4
			'add_button'    => esc_html__( 'Add Group', 'cmb2' ),
1124 4
			'remove_button' => esc_html__( 'Remove Group', 'cmb2' ),
1125 111
		) ) : $args['options'];
1126
1127 111
		$args['_id']        = $args['id'];
1128 111
		$args['_name']      = $args['id'];
1129
1130 111
		if ( $this->group ) {
1131
1132 4
			$args['id']    = $this->group->args( 'id' ) . '_' . $this->group->index . '_' . $args['id'];
1133 4
			$args['_name'] = $this->group->args( 'id' ) . '[' . $this->group->index . '][' . $args['_name'] . ']';
1134 4
		}
1135
1136 111
		if ( 'wysiwyg' == $args['type'] ) {
1137 1
			$args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
1138 1
			$args['options']['textarea_name'] = $args['_name'];
1139 1
		}
1140
1141 111
		$option_types = apply_filters( 'cmb2_all_or_nothing_types', array( 'select', 'radio', 'radio_inline', 'taxonomy_select', 'taxonomy_radio', 'taxonomy_radio_inline' ), $this );
1142
1143 111
		if ( in_array( $args['type'], $option_types, true ) ) {
1144
1145 16
			$args['show_option_none'] = isset( $args['show_option_none'] ) ? $args['show_option_none'] : null;
1146 16
			$args['show_option_none'] = true === $args['show_option_none'] ? esc_html__( 'None', 'cmb2' ) : $args['show_option_none'];
1147
1148 16
			if ( null === $args['show_option_none'] ) {
1149 15
				$off_by_default = in_array( $args['type'], array( 'select', 'radio', 'radio_inline' ), true );
1150 15
				$args['show_option_none'] = $off_by_default ? false : esc_html__( 'None', 'cmb2' );
1151 15
			}
1152
1153 16
		}
1154
1155 111
		$args['has_supporting_data'] = in_array(
1156 111
			$args['type'],
1157
			array(
1158
				// 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...
1159 111
				'file',
1160
				// 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...
1161 111
				'text_datetime_timestamp_timezone',
1162 111
			),
1163
			true
1164 111
		);
1165
1166 111
		return $args;
1167
	}
1168
1169
	/**
1170
	 * Get default field arguments specific to this CMB2 object.
1171
	 * @since  2.2.0
1172
	 * @param  array      $field_args  Metabox field config array.
1173
	 * @param  CMB2_Field $field_group (optional) CMB2_Field object (group parent)
1174
	 * @return array                   Array of field arguments.
1175
	 */
1176 7
	protected function get_default_args( $field_args, $field_group = null ) {
1177 7
		$args = parent::get_default_args( array(), $this->group );
1178
1179 7
		if ( isset( $field_args['field_args'] ) ) {
1180
			$args = wp_parse_args( $field_args, $args );
1181
		} else {
1182 7
			$args['field_args'] = wp_parse_args( $field_args, $this->args );
1183
		}
1184
1185 7
		return $args;
1186
	}
1187
1188
	/**
1189
	 * Returns a cloned version of this field object with, but with
1190
	 * modified/overridden field arguments.
1191
	 *
1192
	 * @since  2.2.2
1193
	 * @param  array  $field_args Array of field arguments, or entire array of
1194
	 *                            arguments for CMB2_Field
1195
	 *
1196
	 * @return CMB2_Field         The new CMB2_Field instance.
1197
	 */
1198 7
	public function get_field_clone( $field_args ) {
1199 7
		return $this->get_new_field( $field_args );
1200
	}
1201
1202
	/**
1203
	 * Returns the CMB2 instance this field is registered to.
1204
	 *
1205
	 * @since  2.2.2
1206
	 *
1207
	 * @return CMB2|WP_Error If new CMB2_Field is called without cmb_id arg, returns error.
1208
	 */
1209 1
	public function get_cmb() {
1210 1
		if ( ! $this->cmb_id ) {
1211
			return new WP_Error( 'no_cmb_id', esc_html__( 'Sorry, this field does not have a cmb_id specified.', 'cmb2' ) );
1212
		}
1213
1214 1
		return cmb2_get_metabox( $this->cmb_id, $this->object_id, $this->object_type );
1215
	}
1216
1217
	/**
1218
	 * Converts deprecated field parameters to the current/proper parameter, and throws a deprecation notice.
1219
	 * @since 2.2.3
1220
	 * @param array $args Metabox field config array.
1221
	 * @param array       Modified field config array.
1222
	 */
1223 111
	protected function convert_deprecated_params( $args ) {
1224
1225 111
		if ( isset( $args['row_classes'] ) ) {
1226
1227
			// We'll let this one be.
1228
			// $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...
1229
1230
			// row_classes param could be a callback. This is definitely deprecated.
1231 2
			if ( is_callable( $args['row_classes'] ) ) {
1232
1233 1
				$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'row_classes', 'classes_cb' );
1234
1235 1
				$args['classes_cb'] = $args['row_classes'];
1236 1
				$args['classes'] = null;
1237 1
			} else {
1238
1239 1
				$args['classes'] = $args['row_classes'];
1240
			}
1241
1242 2
			unset( $args['row_classes'] );
1243 2
		}
1244
1245
1246
		// default param can be passed a callback as well
1247 111 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...
1248
1249
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'default', 'default_cb' );
1250
1251
			$args['default_cb'] = $args['default'];
1252
			$args['default'] = null;
1253
		}
1254
1255
		// options param can be passed a callback as well
1256 111 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...
1257
1258
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'options', 'options_cb' );
1259
1260
			$args['options_cb'] = $args['options'];
1261
			$args['options'] = array();
1262
		}
1263
1264 111
		return $args;
1265
	}
1266
1267
}
1268