Completed
Push — trunk ( 71a5fb...cd501a )
by
unknown
500:15 queued 497:50
created

CMB2_Field::field_timezone()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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

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

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

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

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