Completed
Push — trunk ( 5d123b...5dfd19 )
by Justin
06:53
created

CMB2_Field::__construct()   C

Complexity

Conditions 7
Paths 34

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7

Importance

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