PluginProbe
Virtue/Ascend/Pinnacle Toolkit / 2.3
Virtue/Ascend/Pinnacle Toolkit v2.3
4.9.12.2 trunk 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.7 All 48 releases
virtue-toolkit / cmb / helpers / cmb_Meta_Box_field.php

cmb_Meta_Box_field.php in Virtue/Ascend/Pinnacle Toolkit 2.3, at cmb/helpers/cmb_Meta_Box_field.php

498 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * CMB field class
5 * @since 1.1.0
6 */
7 class cmb_Meta_Box_field {
8
9 /**
10 * Metabox object id
11 * @var mixed
12 * @since 1.1.0
13 */
14 public $object_id;
15
16 /**
17 * Metabox object type
18 * @var mixed
19 * @since 1.1.0
20 */
21 public $object_type;
22
23 /**
24 * Field arguments
25 * @var mixed
26 * @since 1.1.0
27 */
28 public $args;
29
30 /**
31 * Field group object
32 * @var mixed
33 * @since 1.1.0
34 */
35 public $group;
36
37 /**
38 * Field meta value
39 * @var mixed
40 * @since 1.1.0
41 */
42 public $value;
43
44 /**
45 * Constructs our field object
46 * @since 1.1.0
47 * @param array $field_args Field arguments
48 * @param array $group_field (optional) Group field object
49 */
50 public function __construct( $field_args, $group_field = null ) {
51 $this->object_id = cmb_Meta_Box::get_object_id();
52 $this->object_type = cmb_Meta_Box::get_object_type();
53 $this->group = ! empty( $group_field ) ? $group_field : false;
54 $this->args = $this->_set_field_defaults( $field_args );
55
56 // Allow an override for the field's value
57 // (assuming no one would want to save 'cmb_no_override_val' as a value)
58 $this->value = apply_filters( 'cmb_override_meta_value', 'cmb_no_override_val', $this->object_id, $this->args(), $this->object_type, $this );
59
60 // If no override, get our meta
61 $this->value = 'cmb_no_override_val' === $this->value
62 ? $this->get_data()
63 : $this->value;
64 }
65
66 /**
67 * Non-existent methods fallback to checking for field arguments of the same name
68 * @since 1.1.0
69 * @param string $name Method name
70 * @param array $arguments Array of passed-in arguments
71 * @return mixed Value of field argument
72 */
73 public function __call( $name, $arguments ) {
74 $key = isset( $arguments[0] ) ? $arguments[0] : false;
75 return $this->args( $name, $key );
76 }
77
78 /**
79 * Retrieves the field id
80 * @since 1.1.0
81 * @param boolean $raw Whether to retrieve pre-modidifed id
82 * @return string Field id
83 */
84 public function id( $raw = false ) {
85 $id = $raw ? '_id' : 'id';
86 return $this->args( $id );
87 }
88
89 /**
90 * Get a field argument
91 * @since 1.1.0
92 * @param string $key Argument to check
93 * @param string $key Sub argument to check
94 * @return mixed Argument value or false if non-existent
95 */
96 public function args( $key = '', $_key = '' ) {
97 $vars = $this->_data( 'args', $key );
98 if ( $_key ) {
99 return isset( $vars[ $_key ] ) ? $vars[ $_key ] : false;
100 }
101 return $vars;
102 }
103
104 /**
105 * Get Field's value
106 * @since 1.1.0
107 * @param string $key If value is an array, is used to get array key->value
108 * @return mixed Field value or false if non-existent
109 */
110 public function value( $key = '' ) {
111 return $this->_data( 'value', $key );
112 }
113
114 /**
115 * Retrieve a portion of a field property
116 * @since 1.1.0
117 * @param string $var Field property to check
118 * @param string $key Field property array key to check
119 * @return mixed Queried property value or false
120 */
121 public function _data( $var, $key = '' ) {
122 $vars = $this->$var;
123 if ( $key ) {
124 return isset( $vars[ $key ] ) ? $vars[ $key ] : false;
125 }
126 return $vars;
127 }
128
129 /**
130 * Retrieves metadata/option data
131 * @since 1.0.1
132 * @param string $field_id Meta key/Option array key
133 * @return mixed Meta/Option value
134 */
135 public function get_data( $field_id = '', $args = array() ) {
136 if ( $field_id ) {
137 $args['field_id'] = $field_id;
138 } else if ( $this->group ) {
139 $args['field_id'] = $this->group->id();
140 }
141 extract( $this->data_args( $args ) );
142
143 $data = 'options-page' === $type
144 ? cmb_Meta_Box::get_option( $id, $field_id )
145 : get_metadata( $type, $id, $field_id, ( $single || $repeat ) /* If multicheck this can be multiple values */ );
146
147 if ( $this->group && $data ) {
148 $data = isset( $data[ $this->group->args( 'count' ) ][ $this->args( '_id' ) ] )
149 ? $data[ $this->group->args( 'count' ) ][ $this->args( '_id' ) ]
150 : false;
151 }
152 return $data;
153 }
154
155 /**
156 * Updates metadata/option data
157 * @since 1.0.1
158 * @param mixed $value Value to update data with
159 * @param bool $single Whether data is an array (add_metadata)
160 */
161 public function update_data( $new_value, $single = true ) {
162 extract( $this->data_args( array( 'new_value' => $new_value, 'single' => $single ) ) );
163
164 $new_value = $repeat ? array_values( $new_value ) : $new_value;
165
166 if ( 'options-page' === $type )
167 return cmb_Meta_Box::update_option( $id, $field_id, $new_value, $single );
168
169 if ( ! $single )
170 return add_metadata( $type, $id, $field_id, $new_value, false );
171
172 return update_metadata( $type, $id, $field_id, $new_value );
173 }
174
175 /**
176 * Removes/updates metadata/option data
177 * @since 1.0.1
178 * @param string $old Old value
179 */
180 public function remove_data( $old = '' ) {
181 extract( $this->data_args() );
182
183 return 'options-page' === $type
184 ? cmb_Meta_Box::remove_option( $id, $field_id )
185 : delete_metadata( $type, $id, $field_id, $old );
186 }
187
188 /**
189 * data variables for get/set data methods
190 * @since 1.1.0
191 * @param array $args Override arguments
192 * @return array Updated arguments
193 */
194 public function data_args( $args = array() ) {
195 $args = wp_parse_args( $args, array(
196 'type' => $this->object_type,
197 'id' => $this->object_id,
198 'field_id' => $this->id( true ),
199 'repeat' => $this->args( 'repeatable' ),
200 'single' => ! $this->args( 'multiple' ),
201 ) );
202 return $args;
203 }
204
205 /**
206 * Checks if field has a registered validation callback
207 * @since 1.0.1
208 * @param mixed $meta_value Meta value
209 * @return mixed Possibly validated meta value
210 */
211 public function sanitization_cb( $meta_value ) {
212 if ( empty( $meta_value ) )
213 return $meta_value;
214
215 // Check if the field has a registered validation callback
216 $cb = $this->maybe_callback( 'sanitization_cb' );
217 if ( false === $cb ) {
218 // If requestion NO validation, return meta value
219 return $meta_value;
220 } elseif ( $cb ) {
221 // Ok, callback is good, let's run it.
222 return call_user_func( $cb, $meta_value, $this->args(), $this );
223 }
224
225 $clean = new cmb_Meta_Box_Sanitize( $this, $meta_value );
226 // Validation via 'cmb_Meta_Box_Sanitize' (with fallback filter)
227 return $clean->{$this->type()}( $meta_value );
228 }
229
230 /**
231 * Checks if field has a callback value
232 * @since 1.0.1
233 * @param string $cb Callback string
234 * @return mixed NULL, false for NO validation, or $cb string if it exists.
235 */
236 public function maybe_callback( $cb ) {
237 $field_args = $this->args();
238 if ( ! isset( $field_args[ $cb ] ) )
239 return;
240
241 // Check if metabox is requesting NO validation
242 $cb = false !== $field_args[ $cb ] && 'false' !== $field_args[ $cb ] ? $field_args[ $cb ] : false;
243
244 // If requestion NO validation, return false
245 if ( ! $cb )
246 return false;
247
248 if ( is_callable( $cb ) )
249 return $cb;
250 }
251
252 /**
253 * Determine if current type is excempt from escaping
254 * @since 1.1.0
255 * @return bool True if exempt
256 */
257 public function escaping_exception() {
258 // These types cannot be escaped
259 return in_array( $this->type(), array(
260 'file_list',
261 'multicheck',
262 'text_datetime_timestamp_timezone',
263 ) );
264 }
265
266 /**
267 * Determine if current type cannot be repeatable
268 * @since 1.1.0
269 * @param string $type Field type to check
270 * @return bool True if type cannot be repeatable
271 */
272 public function repeatable_exception( $type ) {
273 // These types cannot be escaped
274 return in_array( $type, array(
275 'file', // Use file_list
276 'radio',
277 'title',
278 'group',
279 // @todo Ajax load wp_editor: http://wordpress.stackexchange.com/questions/51776/how-to-load-wp-editor-through-ajax-jquery
280 'wysiwyg',
281 'checkbox',
282 'radio_inline',
283 'taxonomy_radio',
284 'taxonomy_select',
285 'taxonomy_multicheck',
286 ) );
287 }
288
289 /**
290 * Escape the value before output. Defaults to 'esc_attr()'
291 * @since 1.0.1
292 * @param mixed $meta_value Meta value
293 * @param mixed $func Escaping function (if not esc_attr())
294 * @return mixed Final value
295 */
296 public function escaped_value( $func = 'esc_attr', $meta_value = '' ) {
297
298 if ( isset( $this->escaped_value ) )
299 return $this->escaped_value;
300
301 $meta_value = $meta_value ? $meta_value : $this->value();
302 // Check if the field has a registered escaping callback
303 $cb = $this->maybe_callback( 'escape_cb' );
304 if ( false === $cb || $this->escaping_exception() ) {
305 // If requesting NO escaping, return meta value
306 return ! empty( $meta_value ) ? $meta_value : $this->args( 'default' );
307 } elseif ( $cb ) {
308 // Ok, callback is good, let's run it.
309 return call_user_func( $cb, $meta_value, $this->args(), $this );
310 }
311
312 // Or custom escaping filter can be used
313 $esc = apply_filters( 'cmb_types_esc_'. $this->type(), null, $meta_value, $this->args(), $this );
314 if ( null !== $esc ) {
315 return $esc;
316 }
317
318 // escaping function passed in?
319 $func = $func ? $func : 'esc_attr';
320 $meta_value = ! empty( $meta_value ) ? $meta_value : $this->args( 'default' );
321
322 if ( is_array( $meta_value ) ) {
323 foreach ( $meta_value as $key => $value ) {
324 $meta_value[ $key ] = call_user_func( $func, $value );
325 }
326 } else {
327 $meta_value = call_user_func( $func, $meta_value );
328 }
329
330 $this->escaped_value = $meta_value;
331 return $this->escaped_value;
332 }
333
334 /**
335 * Offset a time value based on timezone
336 * @since 1.0.0
337 * @return string Offset time string
338 */
339 public function field_timezone_offset() {
340 return cmb_Meta_Box::timezone_offset( $this->field_timezone() );
341 }
342
343 /**
344 * Return timezone string
345 * @since 1.0.0
346 * @return string Timezone string
347 */
348 public function field_timezone() {
349
350 // Is timezone arg set?
351 if ( $this->args( 'timezone' ) ) {
352 return $this->args( 'timezone' ) ;
353 }
354 // Is there another meta key with a timezone stored as its value we should use?
355 else if ( $this->args( 'timezone_meta_key' ) ) {
356 return $this->get_data( $this->args( 'timezone_meta_key' ) );
357 }
358
359 return false;
360 }
361
362 /**
363 * Render a field row
364 * @since 1.0.0
365 */
366 public function render_field() {
367
368 // If field is requesting to not be shown on the front-end
369 if ( ! is_admin() && ! $this->args( 'on_front' ) )
370 return;
371
372 // If field is requesting to be conditionally shown
373 if ( is_callable( $this->args( 'show_on_cb' ) ) && ! call_user_func( $this->args( 'show_on_cb' ), $this ) )
374 return;
375
376 $classes = 'cmb-type-'. sanitize_html_class( $this->type() );
377 $classes .= ' cmb_id_'. sanitize_html_class( $this->id() );
378 $classes .= $this->args( 'repeatable' ) ? ' cmb-repeat' : '';
379 // 'inline' flag, or _inline in the field type, set to true
380 $classes .= $this->args( 'inline' ) ? ' cmb-inline' : '';
381 $is_side = 'side' === $this->args( 'context' );
382
383 printf( "<tr class=\"%s\">\n", $classes );
384
385 if ( 'title' == $this->type() || ! $this->args( 'show_names' ) || $is_side ) {
386 echo "\t<td colspan=\"2\">\n";
387
388 if ( ! $this->args( 'show_names' ) || $is_side ) {
389 $style = ! $is_side || 'title' == $this->type() ? ' style="display:none;"' : '';
390 printf( "\n<label%s for=\"%s\">%s</label>\n", $style, $this->id(), $this->args( 'name' ) );
391 }
392 } else {
393
394 $style = 'post' == $this->object_type ? ' style="width:18%"' : '';
395 // $tag = 'side' !== $this->args( 'context' ) ? 'th' : 'p';
396 $tag = 'th';
397 printf( '<%1$s%2$s><label for="%3$s">%4$s</label></%1$s>', $tag, $style, $this->id(), $this->args( 'name' ) );
398
399 echo "\n\t<td>\n";
400 }
401
402 echo $this->args( 'before' );
403
404 $this_type = new cmb_Meta_Box_types( $this );
405 $this_type->render();
406
407 echo $this->args( 'after' );
408
409 echo "\n\t</td>\n</tr>";
410 }
411
412 /**
413 * Replaces a hash key - {#} - with the repeatable count
414 * @since 1.2.0
415 * @param string $value Value to update
416 * @return string Updated value
417 */
418 public function replace_hash( $value ) {
419 // Replace hash with 1 based count
420 return str_ireplace( '{#}', ( $this->count() + 1 ), $value );
421 }
422
423 /**
424 * Fills in empty field parameters with defaults
425 * @since 1.1.0
426 * @param array $args Metabox field config array
427 */
428 public function _set_field_defaults( $args ) {
429
430 // Set up blank or default values for empty ones
431 if ( ! isset( $args['name'] ) ) $args['name'] = '';
432 if ( ! isset( $args['desc'] ) ) $args['desc'] = '';
433 if ( ! isset( $args['before'] ) ) $args['before'] = '';
434 if ( ! isset( $args['after'] ) ) $args['after'] = '';
435 if ( ! isset( $args['protocols'] ) ) $args['protocols'] = null;
436 if ( ! isset( $args['description'] ) ) {
437 $args['description'] = isset( $args['desc'] ) ? $args['desc'] : '';
438 }
439 if ( ! isset( $args['default'] ) ) {
440 // Phase out 'std', and use 'default' instead
441 $args['default'] = isset( $args['std'] ) ? $args['std'] : '';
442 }
443 if ( ! isset( $args['preview_size'] ) ) $args['preview_size'] = array( 50, 50 );
444 if ( ! isset( $args['date_format'] ) ) $args['date_format'] = 'm\/d\/Y';
445 if ( ! isset( $args['time_format'] ) ) $args['time_format'] = 'h:i A';
446 // Allow a filter override of the default value
447 $args['default'] = apply_filters( 'cmb_default_filter', $args['default'], $args, $this->object_type, $this->object_type );
448 $args['allow'] = 'file' == $args['type'] && ! isset( $args['allow'] ) ? array( 'url', 'attachment' ) : array();
449 $args['save_id'] = 'file' == $args['type'] && ! ( isset( $args['save_id'] ) && ! $args['save_id'] );
450 // $args['multiple'] = isset( $args['multiple'] ) ? $args['multiple'] : ( 'multicheck' == $args['type'] ? true : false );
451 $args['multiple'] = isset( $args['multiple'] ) ? $args['multiple'] : false;
452 $args['repeatable'] = isset( $args['repeatable'] ) && $args['repeatable'] && ! $this->repeatable_exception( $args['type'] );
453 $args['inline'] = isset( $args['inline'] ) && $args['inline'] || false !== stripos( $args['type'], '_inline' );
454 $args['on_front'] = ! ( isset( $args['on_front'] ) && ! $args['on_front'] );
455 $args['attributes'] = isset( $args['attributes'] ) && is_array( $args['attributes'] ) ? $args['attributes'] : array();
456 $args['options'] = isset( $args['options'] ) && is_array( $args['options'] ) ? $args['options'] : array();
457
458 $args['options'] = 'group' == $args['type'] ? wp_parse_args( $args['options'], array(
459 'add_button' => __( 'Add Group', 'cmb' ),
460 'remove_button' => __( 'Remove Group', 'cmb' ),
461 ) ) : $args['options'];
462
463 $args['_id'] = $args['id'];
464 $args['_name'] = $args['id'];
465
466 if ( $this->group ) {
467 $args['id'] = $this->group->args( 'id' ) .'_'. $this->group->args( 'count' ) .'_'. $args['id'];
468 $args['_name'] = $this->group->args( 'id' ) .'['. $this->group->args( 'count' ) .']['. $args['_name'] .']';
469 }
470
471 if ( 'wysiwyg' == $args['type'] ) {
472 $args['id'] = strtolower( str_ireplace( '-', '_', $args['id'] ) );
473 $args['options']['textarea_name'] = $args['_name'];
474 }
475
476 $option_types = array( 'taxonomy_select', 'taxonomy_radio', 'taxonomy_radio_inline' );
477 if ( in_array( $args['type'], $option_types, true ) ) {
478
479 // @todo implemention
480 $args['show_option_all'] = isset( $args['show_option_all'] ) && ! $args['show_option_all'] ? false : true;
481 $args['show_option_none'] = isset( $args['show_option_none'] ) && ! $args['show_option_none'] ? false : true;
482
483 }
484
485 return $args;
486 }
487
488 /**
489 * Updates attributes array values unless they exist from the field config array
490 * @since 1.1.0
491 * @param array $attrs Array of attributes to update
492 */
493 public function maybe_set_attributes( $attrs = array() ) {
494 return wp_parse_args( $this->args['attributes'], $attrs );
495 }
496
497 }
498