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

CMB2_Field::args()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.25

Importance

Changes 0
Metric Value
cc 4
eloc 7
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 14
rs 9.2
ccs 6
cts 8
cp 0.75
crap 4.25
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 1
	}
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
		$date_format = $this->args( 'date_format' );
760
761 10
		if ( ! empty( $date_format ) && ! is_numeric( $meta_value ) ) {
762 2
			$date_format = stripslashes( $date_format );
763 2
			$meta_value = CMB2_Utils::get_timestamp_from_value( $meta_value, $date_format );
764 2
		} else {
765 8
			$meta_value = CMB2_Utils::make_valid_time_stamp( $meta_value );
766
		}
767
768 10
		if ( empty( $meta_value ) ) {
769
			return '';
770
		}
771
772 10
		return is_array( $meta_value )
773 10
			? array_map( array( $this, 'format_timestamp' ), $meta_value, $format )
774 10
			: $this->format_timestamp( $meta_value, $format );
775
	}
776
777
	/**
778
	 * Get timestamp from text date
779
	 *
780
	 * @since  2.2.0
781
	 * @param  string $value Date value
782
	 * @return mixed         Unix timestamp representing the date.
783
	 */
784
	public function get_timestamp_from_value( $value ) {
785
		return CMB2_Utils::get_timestamp_from_value( $value, $this->args( 'date_format' ) );
786
	}
787
788
	/**
789
	 * Get field render callback and Render the field row
790
	 *
791
	 * @since 1.0.0
792
	 */
793 10
	public function render_field() {
794 10
		$this->render_context = 'edit';
795
796 10
		$this->peform_param_callback( 'render_row_cb' );
797
798
		// For chaining
799 10
		return $this;
800
	}
801
802
	/**
803
	 * Default field render callback
804
	 *
805
	 * @since 2.1.1
806
	 */
807 9
	public function render_field_callback() {
808
809
		// If field is requesting to not be shown on the front-end
810 9
		if ( ! is_admin() && ! $this->args( 'on_front' ) ) {
811
			return;
812
		}
813
814
		// If field is requesting to be conditionally shown
815 9
		if ( ! $this->should_show() ) {
816
			return;
817
		}
818
819 9
		$this->peform_param_callback( 'before_row' );
820
821 9
		printf( "<div class=\"cmb-row %s\" data-fieldtype=\"%s\">\n", $this->row_classes(), $this->type() );
822
823 9
		if ( ! $this->args( 'show_names' ) ) {
824
			echo "\n\t<div class=\"cmb-td\">\n";
825
826
			$this->peform_param_callback( 'label_cb' );
827
828
		} else {
829
830 9
			if ( $this->get_param_callback_result( 'label_cb' ) ) {
831 9
				echo '<div class="cmb-th">', $this->peform_param_callback( 'label_cb' ), '</div>';
832 9
			}
833
834 9
			echo "\n\t<div class=\"cmb-td\">\n";
835
		}
836
837 9
		$this->peform_param_callback( 'before' );
838
839 9
		$types = new CMB2_Types( $this );
840 9
		$types->render();
841
842 9
		$this->peform_param_callback( 'after' );
843
844 9
		echo "\n\t</div>\n</div>";
845
846 9
		$this->peform_param_callback( 'after_row' );
847
848
		// For chaining
849 9
		return $this;
850
	}
851
852
	/**
853
	 * The default label_cb callback (if not a title field)
854
	 *
855
	 * @since  2.1.1
856
	 * @return string Label html markup
857
	 */
858 9
	public function label() {
859 9
		if ( ! $this->args( 'name' ) ) {
860
			return '';
861
		}
862
863 9
		$style = ! $this->args( 'show_names' ) ? ' style="display:none;"' : '';
864
865 9
		return sprintf( "\n" . '<label%1$s for="%2$s">%3$s</label>' . "\n", $style, $this->id(), $this->args( 'name' ) );
866
	}
867
868
	/**
869
	 * Defines the classes for the current CMB2 field row
870
	 *
871
	 * @since  2.0.0
872
	 * @return string Space concatenated list of classes
873
	 */
874 45
	public function row_classes() {
875
876 45
		$classes = array();
877
878
		/**
879
		 * By default, 'text_url' and 'text' fields get table-like styling
880
		 *
881
		 * @since 2.0.0
882
		 *
883
		 * @param array $field_types The types of fields which should get the 'table-layout' class
884
		 */
885 45
		$repeat_table_rows_types = apply_filters( 'cmb2_repeat_table_row_types', array(
886 45
			'text_url',
887 45
			'text',
888 45
		) );
889
890
		$conditional_classes = array(
891 45
			'cmb-type-' . str_replace( '_', '-', sanitize_html_class( $this->type() ) ) => true,
892 45
			'cmb2-id-' . str_replace( '_', '-', sanitize_html_class( $this->id() ) )    => true,
893 45
			'cmb-repeat'             => $this->args( 'repeatable' ),
894 45
			'cmb-repeat-group-field' => $this->group,
895 45
			'cmb-inline'             => $this->args( 'inline' ),
896 45
			'table-layout'           => 'edit' === $this->render_context && in_array( $this->type(), $repeat_table_rows_types ),
897 45
		);
898
899 45
		foreach ( $conditional_classes as $class => $condition ) {
900 45
			if ( $condition ) {
901 45
				$classes[] = $class;
902 45
			}
903 45
		}
904
905 45
		if ( $added_classes = $this->args( 'classes' ) ) {
906 1
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
907 45
		} elseif ( $added_classes = $this->get_param_callback_result( 'classes_cb' ) ) {
908 2
			$added_classes = is_array( $added_classes ) ? implode( ' ', $added_classes ) : (string) $added_classes;
909 2
		}
910
911 45
		if ( $added_classes ) {
912 3
			$classes[] = esc_attr( $added_classes );
913 3
		}
914
915
		/**
916
		 * Globally filter row classes
917
		 *
918
		 * @since 2.0.0
919
		 *
920
		 * @param string            $classes Space-separated list of row classes
921
		 * @param CMB2_Field object $field   This field object
922
		 */
923 45
		return apply_filters( 'cmb2_row_classes', implode( ' ', $classes ), $this );
924
	}
925
926
927
928
	/**
929
	 * Get field display callback and render the display value in the column.
930
	 *
931
	 * @since 2.2.2
932
	 */
933 33
	public function render_column() {
934 33
		$this->render_context = 'display';
935
936 33
		$this->peform_param_callback( 'display_cb' );
937
938
		// For chaining
939 33
		return $this;
940
	}
941
942
	/**
943
	 * Default callback to outputs field value in a display format.
944
	 *
945
	 * @since 2.2.2
946
	 */
947 33
	public function display_value_callback() {
948
		// If field is requesting to be conditionally shown
949 33
		if ( ! $this->should_show() ) {
950
			return;
951
		}
952
953 33
		$display = new CMB2_Field_Display( $this );
954
955
		/**
956
		 * A filter to bypass the default display.
957
		 *
958
		 * The dynamic portion of the hook name, $this->type(), refers to the field type.
959
		 *
960
		 * Passing a non-null value to the filter will short-circuit the default display.
961
		 *
962
		 * @param bool|mixed         $pre_output Default null value.
963
		 * @param CMB2_Field         $field      This field object.
964
		 * @param CMB2_Field_Display $display    The `CMB2_Field_Display` object.
965
		 */
966 33
		$pre_output = apply_filters( "cmb2_pre_field_display_{$this->type()}", null, $this, $display );
967
968 33
		if ( null !== $pre_output ) {
969
			echo $pre_output;
970
			return;
971
		}
972
973 33
		$this->peform_param_callback( 'before_display_wrap' );
974
975 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...
976
977 33
		$this->peform_param_callback( 'before_display' );
978
979 33
		CMB2_Field_Display::get( $this )->display();
980
981 33
		$this->peform_param_callback( 'after_display' );
982
983 33
		echo "\n</div>";
984
985 33
		$this->peform_param_callback( 'after_display_wrap' );
986
987
		// For chaining
988 33
		return $this;
989
	}
990
991
	/**
992
	 * Replaces a hash key - {#} - with the repeatable index
993
	 *
994
	 * @since  1.2.0
995
	 * @param  string $value Value to update
996
	 * @return string        Updated value
997
	 */
998 2
	public function replace_hash( $value ) {
999
		// Replace hash with 1 based count
1000 2
		return str_replace( '{#}', ( $this->index + 1 ), $value );
1001
	}
1002
1003
	/**
1004
	 * Retrieve text parameter from field's text array (if it has one), or use fallback text
1005
	 * For back-compatibility, falls back to checking the options array.
1006
	 *
1007
	 * @since  2.2.2
1008
	 * @param  string $text_key Key in field's text array
1009
	 * @param  string $fallback Fallback text
1010
	 * @return string            Text
1011
	 */
1012 10
	public function get_string( $text_key, $fallback ) {
1013
		// If null, populate with our field strings values.
1014 10
		if ( null === $this->strings ) {
1015 10
			$this->strings = (array) $this->args['text'];
1016
1017 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...
1018
				$strings = call_user_func( $this->args['text_cb'], $this );
1019
1020
				if ( $strings && is_array( $strings ) ) {
1021
					$this->strings += $strings;
1022
				}
1023
			}
1024 10
		}
1025
1026
		// If we have that string value, send it back.
1027 10
		if ( isset( $this->strings[ $text_key ] ) ) {
1028 1
			return $this->strings[ $text_key ];
1029
		}
1030
1031
		// Check options for back-compat.
1032 10
		$string = $this->options( $text_key );
1033
1034 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 1034 which is incompatible with the return type documented by CMB2_Field::get_string of type string.
Loading history...
1035
	}
1036
1037
	/**
1038
	 * Retrieve options args. Calls options_cb if it exists.
1039
	 *
1040
	 * @since  2.0.0
1041
	 * @param  string $key Specific option to retrieve
1042
	 * @return array        Array of options
1043
	 */
1044 32
	public function options( $key = '' ) {
1045 32
		if ( ! empty( $this->field_options ) ) {
1046 5
			if ( $key ) {
1047 5
				return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1048
			}
1049
1050 1
			return $this->field_options;
1051
		}
1052
1053 32
		$this->field_options = (array) $this->args['options'];
1054
1055 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...
1056 1
			$options = call_user_func( $this->args['options_cb'], $this );
1057
1058 1
			if ( $options && is_array( $options ) ) {
1059 1
				$this->field_options = $options + $this->field_options;
1060 1
			}
1061 1
		}
1062
1063 32
		if ( $key ) {
1064 11
			return array_key_exists( $key, $this->field_options ) ? $this->field_options[ $key ] : false;
1065
		}
1066
1067 25
		return $this->field_options;
1068
	}
1069
1070
	/**
1071
	 * Store JS dependencies as part of the field args.
1072
	 *
1073
	 * @since 2.2.0
1074
	 * @param array $dependencies Dependies to register for this field.
1075
	 */
1076 13
	public function add_js_dependencies( $dependencies = array() ) {
1077 13
		foreach ( (array) $dependencies as $dependency ) {
1078 13
			$this->args['js_dependencies'][ $dependency ] = $dependency;
1079 13
		}
1080
1081 13
		CMB2_JS::add_dependencies( $dependencies );
1082 13
	}
1083
1084
	/**
1085
	 * Get CMB2_Field default value, either from default param or default_cb param.
1086
	 *
1087
	 * @since  0.2.2
1088
	 *
1089
	 * @return mixed  Default field value
1090
	 */
1091 35
	public function get_default() {
1092 35
		if ( null !== $this->args['default'] ) {
1093 8
			return $this->args['default'];
1094
		}
1095
1096 34
		$param = is_callable( $this->args['default_cb'] ) ? 'default_cb' : 'default';
1097 34
		$default = $this->get_param_callback_result( $param );
1098
1099
		// Allow a filter override of the default value
1100 34
		$this->args['default'] = apply_filters( 'cmb2_default_filter', $default, $this );
1101
1102 34
		return $this->args['default'];
1103
	}
1104
1105
	/**
1106
	 * Fills in empty field parameters with defaults
1107
	 *
1108
	 * @since 1.1.0
1109
	 * @param array                                   $args Metabox field config array
1110
	 * @param array       Modified field config array.
1111
	 */
1112 111
	public function _set_field_defaults( $args ) {
1113
1114
		// Set up blank or default values for empty ones
1115 111
		$args = wp_parse_args( $args, array(
1116 111
			'type'              => '',
1117 111
			'name'              => '',
1118 111
			'desc'              => '',
1119 111
			'before'            => '',
1120 111
			'after'             => '',
1121 111
			'options'           => array(),
1122 111
			'options_cb'        => '',
1123 111
			'text'              => array(),
1124 111
			'text_cb'           => '',
1125 111
			'attributes'        => array(),
1126 111
			'protocols'         => null,
1127 111
			'default'           => null,
1128 111
			'default_cb'        => '',
1129 111
			'classes'           => null,
1130 111
			'classes_cb'        => '',
1131 111
			'select_all_button' => true,
1132 111
			'multiple'          => false,
1133 111
			'repeatable'        => isset( $args['type'] ) && 'group' == $args['type'],
1134 111
			'inline'            => false,
1135 111
			'on_front'          => true,
1136 111
			'show_names'        => true,
1137 111
			'save_field'        => true, // Will not save if false
1138 111
			'date_format'       => 'm\/d\/Y',
1139 111
			'time_format'       => 'h:i A',
1140 111
			'description'       => isset( $args['desc'] ) ? $args['desc'] : '',
1141 111
			'preview_size'      => 'file' == $args['type'] ? array( 350, 350 ) : array( 50, 50 ),
1142 111
			'render_row_cb'     => array( $this, 'render_field_callback' ),
1143 111
			'display_cb'        => array( $this, 'display_value_callback' ),
1144 111
			'label_cb'          => 'title' != $args['type'] ? array( $this, 'label' ) : '',
1145 111
			'column'            => false,
1146 111
			'js_dependencies'   => array(),
1147 111
			'show_in_rest'      => null,
1148 111
		) );
1149
1150
		/*
1151
		 * Deprecated usage:
1152
		 *
1153
		 * 'std' -- use 'default' (no longer works)
1154
		 * 'row_classes' -- use 'class', or 'class_cb'
1155
		 * 'default' -- as callback (use default_cb)
1156
		 */
1157 111
		$args = $this->convert_deprecated_params( $args );
1158
1159 111
		$args['repeatable'] = $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
1160 111
		$args['inline']     = $args['inline'] || false !== stripos( $args['type'], '_inline' );
1161
1162 111
		$args['options']    = 'group' == $args['type'] ? wp_parse_args( $args['options'], array(
1163 4
			'add_button'    => esc_html__( 'Add Group', 'cmb2' ),
1164 4
			'remove_button' => esc_html__( 'Remove Group', 'cmb2' ),
1165 111
		) ) : $args['options'];
1166
1167 111
		$args['_id']        = $args['id'];
1168 111
		$args['_name']      = $args['id'];
1169
1170 111
		if ( $this->group ) {
1171
1172 4
			$args['id']    = $this->group->args( 'id' ) . '_' . $this->group->index . '_' . $args['id'];
1173 4
			$args['_name'] = $this->group->args( 'id' ) . '[' . $this->group->index . '][' . $args['_name'] . ']';
1174 4
		}
1175
1176 111
		if ( 'wysiwyg' == $args['type'] ) {
1177 1
			$args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
1178 1
			$args['options']['textarea_name'] = $args['_name'];
1179 1
		}
1180
1181 111
		$option_types = apply_filters( 'cmb2_all_or_nothing_types', array( 'select', 'radio', 'radio_inline', 'taxonomy_select', 'taxonomy_radio', 'taxonomy_radio_inline' ), $this );
1182
1183 111
		if ( in_array( $args['type'], $option_types, true ) ) {
1184
1185 16
			$args['show_option_none'] = isset( $args['show_option_none'] ) ? $args['show_option_none'] : null;
1186 16
			$args['show_option_none'] = true === $args['show_option_none'] ? esc_html__( 'None', 'cmb2' ) : $args['show_option_none'];
1187
1188 16
			if ( null === $args['show_option_none'] ) {
1189 15
				$off_by_default = in_array( $args['type'], array( 'select', 'radio', 'radio_inline' ), true );
1190 15
				$args['show_option_none'] = $off_by_default ? false : esc_html__( 'None', 'cmb2' );
1191 15
			}
1192 16
		}
1193
1194 111
		$args['has_supporting_data'] = in_array(
1195 111
			$args['type'],
1196
			array(
1197
				// 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...
1198 111
				'file',
1199
				// 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...
1200 111
				'text_datetime_timestamp_timezone',
1201 111
			),
1202
			true
1203 111
		);
1204
1205 111
		return $args;
1206
	}
1207
1208
	/**
1209
	 * Get default field arguments specific to this CMB2 object.
1210
	 *
1211
	 * @since  2.2.0
1212
	 * @param  array      $field_args  Metabox field config array.
1213
	 * @param  CMB2_Field $field_group (optional) CMB2_Field object (group parent)
1214
	 * @return array                   Array of field arguments.
1215
	 */
1216 7
	protected function get_default_args( $field_args, $field_group = null ) {
1217 7
		$args = parent::get_default_args( array(), $this->group );
1218
1219 7
		if ( isset( $field_args['field_args'] ) ) {
1220
			$args = wp_parse_args( $field_args, $args );
1221
		} else {
1222 7
			$args['field_args'] = wp_parse_args( $field_args, $this->args );
1223
		}
1224
1225 7
		return $args;
1226
	}
1227
1228
	/**
1229
	 * Returns a cloned version of this field object with, but with
1230
	 * modified/overridden field arguments.
1231
	 *
1232
	 * @since  2.2.2
1233
	 * @param  array $field_args Array of field arguments, or entire array of
1234
	 *                           arguments for CMB2_Field
1235
	 *
1236
	 * @return CMB2_Field         The new CMB2_Field instance.
1237
	 */
1238 7
	public function get_field_clone( $field_args ) {
1239 7
		return $this->get_new_field( $field_args );
1240
	}
1241
1242
	/**
1243
	 * Returns the CMB2 instance this field is registered to.
1244
	 *
1245
	 * @since  2.2.2
1246
	 *
1247
	 * @return CMB2|WP_Error If new CMB2_Field is called without cmb_id arg, returns error.
1248
	 */
1249 1
	public function get_cmb() {
1250 1
		if ( ! $this->cmb_id ) {
1251
			return new WP_Error( 'no_cmb_id', esc_html__( 'Sorry, this field does not have a cmb_id specified.', 'cmb2' ) );
1252
		}
1253
1254 1
		return cmb2_get_metabox( $this->cmb_id, $this->object_id, $this->object_type );
1255
	}
1256
1257
	/**
1258
	 * Converts deprecated field parameters to the current/proper parameter, and throws a deprecation notice.
1259
	 *
1260
	 * @since 2.2.3
1261
	 * @param array                                   $args Metabox field config array.
1262
	 * @param array       Modified field config array.
1263
	 */
1264 111
	protected function convert_deprecated_params( $args ) {
1265
1266 111
		if ( isset( $args['row_classes'] ) ) {
1267
1268
			// We'll let this one be.
1269
			// $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...
1270
			// row_classes param could be a callback. This is definitely deprecated.
1271 2
			if ( is_callable( $args['row_classes'] ) ) {
1272
1273 1
				$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'row_classes', 'classes_cb' );
1274
1275 1
				$args['classes_cb'] = $args['row_classes'];
1276 1
				$args['classes'] = null;
1277 1
			} else {
1278
1279 1
				$args['classes'] = $args['row_classes'];
1280
			}
1281
1282 2
			unset( $args['row_classes'] );
1283 2
		}
1284
1285
		// default param can be passed a callback as well
1286 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...
1287
1288
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'default', 'default_cb' );
1289
1290
			$args['default_cb'] = $args['default'];
1291
			$args['default'] = null;
1292
		}
1293
1294
		// options param can be passed a callback as well
1295 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...
1296
1297
			$this->deprecated_param( __CLASS__ . '::__construct()', '2.2.3', self::DEPRECATED_CB_PARAM, 'options', 'options_cb' );
1298
1299
			$args['options_cb'] = $args['options'];
1300
			$args['options'] = array();
1301
		}
1302
1303 111
		return $args;
1304
	}
1305
1306
}
1307