cmb_Meta_Box_field

CMB field class.

Defined (1)

The class is defined in the following location(s).

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