CMB2_Types

CMB field type objects.

Defined (2)

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

/includes/libraries/metabox/includes/CMB2_Types.php  
  1. class CMB2_Types { 
  2.  
  3. /** 
  4. * An iterator value for repeatable fields 
  5. * @var integer 
  6. * @since 1.0.0 
  7. */ 
  8. public $iterator = 0; 
  9.  
  10. /** 
  11. * Current CMB2_Field field object 
  12. * @var CMB2_Field object 
  13. * @since 1.0.0 
  14. */ 
  15. public $field; 
  16.  
  17. public function __construct( CMB2_Field $field ) { 
  18. $this->field = $field; 
  19.  
  20. /** 
  21. * Default fallback. Allows rendering fields via "cmb2_render_$name" hook 
  22. * @since 1.0.0 
  23. * @param string $name Non-existent method name 
  24. * @param array $arguments All arguments passed to the method 
  25. */ 
  26. public function __call( $name, $arguments ) { 
  27. /** 
  28. * Pass non-existent field types through an action 
  29. * The dynamic portion of the hook name, $name, refers to the field type. 
  30. * @param array $field The passed in `CMB2_Field` object 
  31. * @param mixed $escaped_value The value of this field escaped. 
  32. * It defaults to `sanitize_text_field`. 
  33. * If you need the unescaped value, you can access it 
  34. * via `$field->value()` 
  35. * @param int $object_id The ID of the current object 
  36. * @param string $object_type The type of object you are working with. 
  37. * Most commonly, `post` (this applies to all post-types),  
  38. * but could also be `comment`, `user` or `options-page`. 
  39. * @param object $field_type_object This `CMB2_Types` object 
  40. */ 
  41. do_action( "cmb2_render_$name", $this->field, $this->field->escaped_value(), $this->field->object_id, $this->field->object_type, $this ); 
  42.  
  43. /** 
  44. * Render a field (and handle repeatable) 
  45. * @since 1.1.0 
  46. */ 
  47. public function render() { 
  48. if ( $this->field->args( 'repeatable' ) ) { 
  49. $this->render_repeatable_field(); 
  50. } else { 
  51. $this->_render(); 
  52.  
  53. /** 
  54. * Render a field type 
  55. * @since 1.1.0 
  56. */ 
  57. protected function _render() { 
  58. $this->field->peform_param_callback( 'before_field' ); 
  59. echo $this->{$this->field->type()}(); 
  60. $this->field->peform_param_callback( 'after_field' ); 
  61.  
  62. /** 
  63. * Checks if we can get a post object, and if so, uses `get_the_terms` which utilizes caching 
  64. * @since 1.0.2 
  65. * @return mixed Array of terms on success 
  66. */ 
  67. public function get_object_terms() { 
  68. $object_id = $this->field->object_id; 
  69. $taxonomy = $this->field->args( 'taxonomy' ); 
  70.  
  71. if ( ! $post = get_post( $object_id ) ) { 
  72.  
  73. $cache_key = "cmb-cache-{$taxonomy}-{$object_id}"; 
  74.  
  75. // Check cache 
  76. $cached = get_transient( $cache_key ); 
  77. if ( $cached ) { 
  78. return $cached; 
  79.  
  80. $cached = wp_get_object_terms( $object_id, $taxonomy ); 
  81. // Do our own (minimal) caching. Long enough for a page-load. 
  82. set_transient( $cache_key, $cached, 60 ); 
  83. return $cached; 
  84.  
  85. // WP caches internally so it's better to use 
  86. return get_the_terms( $post, $taxonomy ); 
  87.  
  88.  
  89. /** 
  90. * Retrieve text parameter from field's options array (if it has one), or use fallback text 
  91. * @since 2.0.0 
  92. * @param string $option_key Key in field's options array 
  93. * @param string $fallback Fallback text 
  94. * @return string Text 
  95. */ 
  96. public function _text( $option_key, $fallback ) { 
  97. $has_string_param = $this->field->options( $option_key ); 
  98. return $has_string_param ? $has_string_param : $fallback; 
  99.  
  100. /** 
  101. * Determine a file's extension 
  102. * @since 1.0.0 
  103. * @param string $file File url 
  104. * @return string|false File extension or false 
  105. */ 
  106. public function get_file_ext( $file ) { 
  107. $parsed = @parse_url( $file, PHP_URL_PATH ); 
  108. return $parsed ? strtolower( pathinfo( $parsed, PATHINFO_EXTENSION ) ) : false; 
  109.  
  110. /** 
  111. * Get the file name from a url 
  112. * @since 2.0.0 
  113. * @param string $value File url or path 
  114. * @return string File name 
  115. */ 
  116. public function get_file_name_from_path( $value ) { 
  117. $parts = explode( '/', $value ); 
  118. return is_array( $parts ) ? end( $parts ) : $value; 
  119.  
  120. /** 
  121. * Determines if a file has a valid image extension 
  122. * @since 1.0.0 
  123. * @param string $file File url 
  124. * @return bool Whether file has a valid image extension 
  125. */ 
  126. public function is_valid_img_ext( $file ) { 
  127. $file_ext = $this->get_file_ext( $file ); 
  128.  
  129. $is_valid_types = (array) apply_filters( 'cmb2_valid_img_types', array( 'jpg', 'jpeg', 'png', 'gif', 'ico', 'icon' ) ); 
  130.  
  131. return ( $file_ext && in_array( $file_ext, $is_valid_types ) ); 
  132.  
  133. /** 
  134. * Handles parsing and filtering attributes while preserving any passed in via field config. 
  135. * @since 1.1.0 
  136. * @param array $args Override arguments 
  137. * @param string $element Element for filter 
  138. * @param array $defaults Default arguments 
  139. * @return array Parsed and filtered arguments 
  140. */ 
  141. public function parse_args( $args, $element, $defaults ) { 
  142. return wp_parse_args( apply_filters( "cmb2_{$element}_attributes", $this->field->maybe_set_attributes( $args ), $defaults, $this->field, $this ), $defaults ); 
  143.  
  144. /** 
  145. * Combines attributes into a string for a form element 
  146. * @since 1.1.0 
  147. * @param array $attrs Attributes to concatenate 
  148. * @param array $attr_exclude Attributes that should NOT be concatenated 
  149. * @return string String of attributes for form element 
  150. */ 
  151. public function concat_attrs( $attrs, $attr_exclude = array() ) { 
  152. $attributes = ''; 
  153. foreach ( $attrs as $attr => $val ) { 
  154. $excluded = in_array( $attr, (array) $attr_exclude, true ); 
  155. $empty = false === $val && 'value' !== $attr; 
  156. if ( ! $excluded && ! $empty ) { 
  157. // if data attribute, use single quote wraps, else double 
  158. $quotes = false !== stripos( $attr, 'data-' ) ? "'" : '"'; 
  159. $attributes .= sprintf( ' %1$s=%3$s%2$s%3$s', $attr, $val, $quotes ); 
  160. return $attributes; 
  161.  
  162. /** 
  163. * Generates html for concatenated items 
  164. * @since 1.1.0 
  165. * @param array $args Optional arguments 
  166. * @return string Concatenated html items 
  167. */ 
  168. public function concat_items( $args = array() ) { 
  169.  
  170. $method = isset( $args['method'] ) ? $args['method'] : 'select_option'; 
  171. unset( $args['method'] ); 
  172.  
  173. $value = $this->field->escaped_value() 
  174. ? $this->field->escaped_value() 
  175. : $this->field->args( 'default' ); 
  176.  
  177. $concatenated_items = ''; $i = 1; 
  178.  
  179. $options = array(); 
  180. if ( $option_none = $this->field->args( 'show_option_none' ) ) { 
  181. $options[ '' ] = $option_none; 
  182. $options = $options + (array) $this->field->options(); 
  183. foreach ( $options as $opt_value => $opt_label ) { 
  184.  
  185. // Clone args & modify for just this item 
  186. $a = $args; 
  187.  
  188. $a['value'] = $opt_value; 
  189. $a['label'] = $opt_label; 
  190.  
  191. // Check if this option is the value of the input 
  192. if ( $value == $opt_value ) { 
  193. $a['checked'] = 'checked'; 
  194.  
  195. $concatenated_items .= $this->$method( $a, $i++ ); 
  196.  
  197. return $concatenated_items; 
  198.  
  199. /** 
  200. * Generates html for an option element 
  201. * @since 1.1.0 
  202. * @param array $args Arguments array containing value, label, and checked boolean 
  203. * @return string Generated option element html 
  204. */ 
  205. public function select_option( $args = array() ) { 
  206. return sprintf( "\t" . '<option value="%s" %s>%s</option>', $args['value'], selected( isset( $args['checked'] ) && $args['checked'], true, false ), $args['label'] ) . "\n"; 
  207.  
  208. /** 
  209. * Generates html for list item with input 
  210. * @since 1.1.0 
  211. * @param array $args Override arguments 
  212. * @param int $i Iterator value 
  213. * @return string Gnerated list item html 
  214. */ 
  215. public function list_input( $args = array(), $i ) { 
  216. $a = $this->parse_args( $args, 'list_input', array( 
  217. 'type' => 'radio',  
  218. 'class' => 'cmb2-option',  
  219. 'name' => $this->_name(),  
  220. 'id' => $this->_id( $i ),  
  221. 'value' => $this->field->escaped_value(),  
  222. 'label' => '',  
  223. ) ); 
  224.  
  225. return sprintf( "\t" . '<li><input%s/> <label for="%s">%s</label></li>' . "\n", $this->concat_attrs( $a, array( 'label' ) ), $a['id'], $a['label'] ); 
  226.  
  227. /** 
  228. * Generates html for list item with checkbox input 
  229. * @since 1.1.0 
  230. * @param array $args Override arguments 
  231. * @param int $i Iterator value 
  232. * @return string Gnerated list item html 
  233. */ 
  234. public function list_input_checkbox( $args, $i ) { 
  235. $saved_value = $this->field->escaped_value(); 
  236. if ( is_array( $saved_value ) && in_array( $args['value'], $saved_value ) ) { 
  237. $args['checked'] = 'checked'; 
  238. $args['type'] = 'checkbox'; 
  239. return $this->list_input( $args, $i ); 
  240.  
  241. /** 
  242. * Generates repeatable field table markup 
  243. * @since 1.0.0 
  244. */ 
  245. public function render_repeatable_field() { 
  246. $table_id = $this->field->id() . '_repeat'; 
  247.  
  248. $this->_desc( true, true, true ); 
  249. ?> 
  250.  
  251. <div id="<?php echo $table_id; ?>" class="cmb-repeat-table cmb-nested"> 
  252. <div class="cmb-tbody cmb-field-list"> 
  253. <?php $this->repeatable_rows(); ?> 
  254. </div> 
  255. </div> 
  256. <p class="cmb-add-row"> 
  257. <button data-selector="<?php echo $table_id; ?>" class="cmb-add-row-button button"><?php echo esc_html( $this->_text( 'add_row_text', __( 'Add Row', 'cmb2' ) ) ); ?></button> 
  258. </p> 
  259.  
  260. <?php 
  261. // reset iterator 
  262. $this->iterator = 0; 
  263.  
  264. /** 
  265. * Generates repeatable field rows 
  266. * @since 1.1.0 
  267. */ 
  268. public function repeatable_rows() { 
  269. $meta_value = array_filter( (array) $this->field->escaped_value() ); 
  270. // check for default content 
  271. $default = $this->field->args( 'default' ); 
  272.  
  273. // check for saved data 
  274. if ( ! empty( $meta_value ) ) { 
  275. $meta_value = is_array( $meta_value ) ? array_filter( $meta_value ) : $meta_value; 
  276. $meta_value = ! empty( $meta_value ) ? $meta_value : $default; 
  277. } else { 
  278. $meta_value = $default; 
  279.  
  280. // Loop value array and add a row 
  281. if ( ! empty( $meta_value ) ) { 
  282. $count = count( $meta_value ); 
  283. foreach ( (array) $meta_value as $val ) { 
  284. $this->field->escaped_value = $val; 
  285. $this->repeat_row( $count < 2 ); 
  286. $this->iterator++; 
  287. } else { 
  288. // Otherwise add one row 
  289. $this->repeat_row( true ); 
  290.  
  291. // Then add an empty row 
  292. $this->field->escaped_value = ''; 
  293. $this->iterator = $this->iterator ? $this->iterator : 1; 
  294. $this->repeat_row( false, 'empty-row hidden' ); 
  295.  
  296. /** 
  297. * Generates a repeatable row's markup 
  298. * @since 1.1.0 
  299. * @param bool $disable_remover Whether remove button should be disabled 
  300. * @param string $class Repeatable table row's class 
  301. */ 
  302. protected function repeat_row( $disable_remover = false, $class = 'cmb-repeat-row' ) { 
  303. $disabled = $disable_remover ? ' button-disabled' : ''; 
  304. ?> 
  305.  
  306. <div class="cmb-row <?php echo $class; ?>"> 
  307. <div class="cmb-td"> 
  308. <?php $this->_render(); ?> 
  309. </div> 
  310. <div class="cmb-td cmb-remove-row"> 
  311. <button class="button cmb-remove-row-button<?php echo $disabled; ?>"><?php echo esc_html( $this->_text( 'remove_row_text', __( 'Remove', 'cmb2' ) ) ); ?></button> 
  312. </div> 
  313. </div> 
  314.  
  315. <?php 
  316.  
  317. /** 
  318. * Generates description markup 
  319. * @since 1.0.0 
  320. * @param boolean $paragraph Paragraph tag or span 
  321. * @param boolean $echo Whether to echo description or only return it 
  322. * @return string Field's description markup 
  323. */ 
  324. public function _desc( $paragraph = false, $echo = false, $repeat_group = false ) { 
  325. // Prevent description from printing multiple times for repeatable fields 
  326. if ( ! $repeat_group && ( $this->field->args( 'repeatable' ) || $this->iterator > 0 ) ) { 
  327. return ''; 
  328.  
  329. $desc = $this->field->args( 'description' ); 
  330.  
  331. if ( ! $desc ) { 
  332. return; 
  333.  
  334. $tag = $paragraph ? 'p' : 'span'; 
  335. $desc = sprintf( "\n" . '<%1$s class="cmb2-metabox-description">%2$s</%1$s>' . "\n", $tag, $desc ); 
  336.  
  337. if ( $echo ) { 
  338. echo $desc; 
  339. return $desc; 
  340.  
  341. /** 
  342. * Generate field name attribute 
  343. * @since 1.1.0 
  344. * @param string $suffix For multi-part fields 
  345. * @return string Name attribute 
  346. */ 
  347. public function _name( $suffix = '' ) { 
  348. return $this->field->args( '_name' ) . ( $this->field->args( 'repeatable' ) ? '[' . $this->iterator . ']' : '' ) . $suffix; 
  349.  
  350. /** 
  351. * Generate field id attribute 
  352. * @since 1.1.0 
  353. * @param string $suffix For multi-part fields 
  354. * @return string Id attribute 
  355. */ 
  356. public function _id( $suffix = '' ) { 
  357. return $this->field->id() . $suffix . ( $this->field->args( 'repeatable' ) ? '_' . $this->iterator . '" data-iterator="' . $this->iterator : '' ); 
  358.  
  359. /** 
  360. * Handles outputting an 'input' element 
  361. * @since 1.1.0 
  362. * @param array $args Override arguments 
  363. * @return string Form input element 
  364. */ 
  365. public function input( $args = array() ) { 
  366. $a = $this->parse_args( $args, 'input', array( 
  367. 'type' => 'text',  
  368. 'class' => 'regular-text',  
  369. 'name' => $this->_name(),  
  370. 'id' => $this->_id(),  
  371. 'value' => $this->field->escaped_value(),  
  372. 'desc' => $this->_desc( true ),  
  373. ) ); 
  374.  
  375. return sprintf( '<input%s/>%s', $this->concat_attrs( $a, array( 'desc' ) ), $a['desc'] ); 
  376.  
  377. /** 
  378. * Handles outputting an 'textarea' element 
  379. * @since 1.1.0 
  380. * @param array $args Override arguments 
  381. * @return string Form textarea element 
  382. */ 
  383. public function textarea( $args = array() ) { 
  384. $a = $this->parse_args( $args, 'textarea', array( 
  385. 'class' => 'cmb2_textarea',  
  386. 'name' => $this->_name(),  
  387. 'id' => $this->_id(),  
  388. 'cols' => 60,  
  389. 'rows' => 10,  
  390. 'value' => $this->field->escaped_value( 'esc_textarea' ),  
  391. 'desc' => $this->_desc( true ),  
  392. ) ); 
  393. return sprintf( '<textarea%s>%s</textarea>%s', $this->concat_attrs( $a, array( 'desc', 'value' ) ), $a['value'], $a['desc'] ); 
  394.  
  395. /** 
  396. * Begin Field Types 
  397. */ 
  398.  
  399. public function text() { 
  400. return $this->input(); 
  401.  
  402. public function hidden() { 
  403. return $this->input( array( 'type' => 'hidden', 'desc' => '', 'class' => false ) ); 
  404.  
  405. public function text_small() { 
  406. return $this->input( array( 'class' => 'cmb2-text-small', 'desc' => $this->_desc() ) ); 
  407.  
  408. public function text_medium() { 
  409. return $this->input( array( 'class' => 'cmb2-text-medium', 'desc' => $this->_desc() ) ); 
  410.  
  411. public function text_email() { 
  412. return $this->input( array( 'class' => 'cmb2-text-email cmb2-text-medium', 'type' => 'email' ) ); 
  413.  
  414. public function text_url() { 
  415. return $this->input( array( 'class' => 'cmb2-text-url cmb2-text-medium regular-text', 'value' => $this->field->escaped_value( 'esc_url' ) ) ); 
  416.  
  417. public function text_money() { 
  418. return ( ! $this->field->get_param_callback_result( 'before_field' ) ? '$ ' : ' ' ) . $this->input( array( 'class' => 'cmb2-text-money', 'desc' => $this->_desc() ) ); 
  419.  
  420. public function textarea_small() { 
  421. return $this->textarea( array( 'class' => 'cmb2-textarea-small', 'rows' => 4 ) ); 
  422.  
  423. public function textarea_code() { 
  424. return sprintf( '<pre>%s', $this->textarea( array( 'class' => 'cmb2-textarea-code', 'desc' => '</pre>' . $this->_desc( true ) ) ) ); 
  425.  
  426. public function wysiwyg( $args = array() ) { 
  427. $a = $this->parse_args( $args, 'input', array( 
  428. 'id' => $this->_id(),  
  429. 'value' => $this->field->escaped_value( 'stripslashes' ),  
  430. 'desc' => $this->_desc( true ),  
  431. 'options' => $this->field->options(),  
  432. ) ); 
  433.  
  434. wp_editor( $a['value'], $a['id'], $a['options'] ); 
  435. echo $a['desc']; 
  436.  
  437. public function text_date( $args = array() ) { 
  438. $args = wp_parse_args( $args, array( 
  439. 'class' => 'cmb2-text-small cmb2-datepicker',  
  440. 'value' => $this->field->get_timestamp_format(),  
  441. 'desc' => $this->_desc(),  
  442. ) ); 
  443.  
  444. CMB2_JS::add_dependencies( array( 'jquery-ui-core', 'jquery-ui-datepicker' ) ); 
  445.  
  446. return $this->input( $args ); 
  447.  
  448. // Alias for text_date 
  449. public function text_date_timestamp( $args = array() ) { 
  450. return $this->text_date( $args ); 
  451.  
  452. public function text_time( $args = array() ) { 
  453. $args = wp_parse_args( $args, array( 
  454. 'class' => 'cmb2-timepicker text-time',  
  455. 'value' => $this->field->get_timestamp_format( 'time_format' ),  
  456. 'desc' => $this->_desc(),  
  457. ) ); 
  458.  
  459. CMB2_JS::add_dependencies( array( 'jquery-ui-core', 'jquery-ui-datepicker', 'jquery-ui-datetimepicker' ) ); 
  460.  
  461. return $this->input( $args ); 
  462.  
  463. public function text_datetime_timestamp( $args = array() ) { 
  464. $args = wp_parse_args( $args, array( 
  465. 'value' => $this->field->escaped_value(),  
  466. 'desc' => $this->_desc(),  
  467. 'datepicker' => array(),  
  468. 'timepicker' => array(),  
  469. ) ); 
  470.  
  471. if ( empty( $args['value'] ) ) { 
  472. $args['value'] = $this->field->escaped_value(); 
  473. // This will be used if there is a select_timezone set for this field 
  474. $tz_offset = $this->field->field_timezone_offset(); 
  475. if ( ! empty( $tz_offset ) ) { 
  476. $args['value'] -= $tz_offset; 
  477.  
  478. $has_good_value = ! empty( $args['value'] ) && ! is_array( $args['value'] ); 
  479.  
  480. $date_args = wp_parse_args( $args['datepicker'], array( 
  481. 'class' => 'cmb2-text-small cmb2-datepicker',  
  482. 'name' => $this->_name( '[date]' ),  
  483. 'id' => $this->_id( '_date' ),  
  484. 'value' => $has_good_value ? $this->field->get_timestamp_format( 'date_format', $args['value'] ) : '',  
  485. 'desc' => '',  
  486. ) ); 
  487.  
  488. $time_args = wp_parse_args( $args['timepicker'], array( 
  489. 'class' => 'cmb2-timepicker text-time',  
  490. 'name' => $this->_name( '[time]' ),  
  491. 'id' => $this->_id( '_time' ),  
  492. 'value' => $has_good_value ? $this->field->get_timestamp_format( 'time_format', $args['value'] ) : '',  
  493. 'desc' => $args['desc'],  
  494. ) ); 
  495.  
  496. CMB2_JS::add_dependencies( array( 'jquery-ui-core', 'jquery-ui-datepicker', 'jquery-ui-datetimepicker' ) ); 
  497.  
  498. return $this->input( $date_args ) . "\n" . $this->input( $time_args ); 
  499.  
  500. public function text_datetime_timestamp_timezone( $args = array() ) { 
  501. $args = wp_parse_args( $args, array( 
  502. 'value' => $this->field->escaped_value(),  
  503. 'desc' => $this->_desc( true ),  
  504. 'text_datetime_timestamp' => array(),  
  505. 'select_timezone' => array(),  
  506. ) ); 
  507.  
  508. $args['value'] = $this->field->escaped_value(); 
  509. if ( is_array( $args['value'] ) ) { 
  510. $args['value'] = ''; 
  511.  
  512. $datetime = unserialize( $args['value'] ); 
  513. $args['value'] = $tzstring = ''; 
  514.  
  515. if ( $datetime && $datetime instanceof DateTime ) { 
  516. $tz = $datetime->getTimezone(); 
  517. $tzstring = $tz->getName(); 
  518. $args['value'] = $datetime->getTimestamp() + $tz->getOffset( new DateTime( 'NOW' ) ); 
  519.  
  520. $timestamp_args = wp_parse_args( $args['text_datetime_timestamp'], array( 
  521. 'desc' => '',  
  522. 'value' => $args['value'],  
  523. ) ); 
  524.  
  525. $timezone_args = wp_parse_args( $args['select_timezone'], array( 
  526. 'class' => 'cmb2_select cmb2-select-timezone',  
  527. 'name' => $this->_name( '[timezone]' ),  
  528. 'id' => $this->_id( '_timezone' ),  
  529. 'options' => wp_timezone_choice( $tzstring ),  
  530. 'desc' => $args['desc'],  
  531. ) ); 
  532.  
  533. return $this->text_datetime_timestamp( $timestamp_args ) . "\n" . $this->select( $timezone_args ); 
  534.  
  535. public function select_timezone() { 
  536. $this->field->args['default'] = $this->field->args( 'default' ) 
  537. ? $this->field->args( 'default' ) 
  538. : cmb2_utils()->timezone_string(); 
  539.  
  540. return $this->select( array( 
  541. 'class' => 'cmb2_select cmb2-select-timezone',  
  542. 'options' => wp_timezone_choice( $this->field->escaped_value() ),  
  543. 'desc' => $this->_desc(),  
  544. ) ); 
  545.  
  546. public function colorpicker() { 
  547. $meta_value = $this->field->escaped_value(); 
  548. $hex_color = '(([a-fA-F0-9]) {3}) {1, 2}$'; 
  549. if ( preg_match( '/^' . $hex_color . '/i', $meta_value ) ) { 
  550. // Value is just 123abc, so prepend # 
  551. $meta_value = '#' . $meta_value; 
  552. } elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta_value ) ) { 
  553. // Value doesn't match #123abc, so sanitize to just # 
  554. $meta_value = '#'; 
  555.  
  556. wp_enqueue_style( 'wp-color-picker' ); 
  557. CMB2_JS::add_dependencies( array( 'wp-color-picker' ) ); 
  558.  
  559. return $this->input( array( 'class' => 'cmb2-colorpicker cmb2-text-small', 'value' => $meta_value ) ); 
  560.  
  561. public function title( $args = array() ) { 
  562. $a = $this->parse_args( $args, 'title', array( 
  563. 'tag' => $this->field->object_type == 'post' ? 'h5' : 'h3',  
  564. 'class' => 'cmb2-metabox-title',  
  565. 'name' => $this->field->args( 'name' ),  
  566. 'desc' => $this->_desc( true ),  
  567. ) ); 
  568.  
  569. return sprintf( '<%1$s class="%2$s">%3$s</%1$s>%4$s', $a['tag'], $a['class'], $a['name'], $a['desc'] ); 
  570.  
  571. public function select( $args = array() ) { 
  572. $a = $this->parse_args( $args, 'select', array( 
  573. 'class' => 'cmb2_select',  
  574. 'name' => $this->_name(),  
  575. 'id' => $this->_id(),  
  576. 'desc' => $this->_desc( true ),  
  577. 'options' => $this->concat_items(),  
  578. ) ); 
  579.  
  580. $attrs = $this->concat_attrs( $a, array( 'desc', 'options' ) ); 
  581. return sprintf( '<select%s>%s</select>%s', $attrs, $a['options'], $a['desc'] ); 
  582.  
  583. public function taxonomy_select() { 
  584.  
  585. $names = $this->get_object_terms(); 
  586. $saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[key( $names )]->slug; 
  587. $terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' ); 
  588. $options = ''; 
  589.  
  590. $option_none = $this->field->args( 'show_option_none' ); 
  591. if ( ! empty( $option_none ) ) { 
  592. $option_none_value = apply_filters( 'cmb2_taxonomy_select_default_value', '' ); 
  593. $option_none_value = apply_filters( "cmb2_taxonomy_select_{$this->_id()}_default_value", $option_none_value ); 
  594.  
  595. $options .= $this->select_option( array( 
  596. 'label' => $option_none,  
  597. 'value' => $option_none_value,  
  598. 'checked' => $saved_term == $option_none_value,  
  599. ) ); 
  600.  
  601. foreach ( $terms as $term ) { 
  602. $options .= $this->select_option( array( 
  603. 'label' => $term->name,  
  604. 'value' => $term->slug,  
  605. 'checked' => $saved_term == $term->slug,  
  606. ) ); 
  607.  
  608. return $this->select( array( 'options' => $options ) ); 
  609.  
  610. public function radio( $args = array(), $type = 'radio' ) { 
  611. $a = $this->parse_args( $args, $type, array( 
  612. 'class' => 'cmb2-radio-list cmb2-list',  
  613. 'options' => $this->concat_items( array( 'label' => 'test', 'method' => 'list_input' ) ),  
  614. 'desc' => $this->_desc( true ),  
  615. ) ); 
  616.  
  617. return sprintf( '<ul class="%s">%s</ul>%s', $a['class'], $a['options'], $a['desc'] ); 
  618.  
  619. public function radio_inline() { 
  620. return $this->radio( array(), 'radio_inline' ); 
  621.  
  622. public function multicheck( $type = 'checkbox' ) { 
  623.  
  624. $classes = false === $this->field->args( 'select_all_button' ) 
  625. ? 'cmb2-checkbox-list no-select-all cmb2-list' 
  626. : 'cmb2-checkbox-list cmb2-list'; 
  627.  
  628. return $this->radio( array( 'class' => $classes, 'options' => $this->concat_items( array( 'name' => $this->_name() . '[]', 'method' => 'list_input_checkbox' ) ) ), $type ); 
  629.  
  630. public function multicheck_inline() { 
  631. $this->multicheck( 'multicheck_inline' ); 
  632.  
  633. public function checkbox() { 
  634. $meta_value = $this->field->escaped_value(); 
  635. $args = array( 'type' => 'checkbox', 'class' => 'cmb2-option cmb2-list', 'value' => 'on', 'desc' => '' ); 
  636. if ( ! empty( $meta_value ) ) { 
  637. $args['checked'] = 'checked'; 
  638. return sprintf( '%s <label for="%s">%s</label>', $this->input( $args ), $this->_id(), $this->_desc() ); 
  639.  
  640. public function taxonomy_radio() { 
  641. $names = $this->get_object_terms(); 
  642. $saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[key( $names )]->slug; 
  643. $terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' ); 
  644. $options = ''; $i = 1; 
  645.  
  646. if ( ! $terms ) { 
  647. $options .= sprintf( '<li><label>%s</label></li>', esc_html( $this->_text( 'no_terms_text', __( 'No terms', 'cmb2' ) ) ) ); 
  648. } else { 
  649. $option_none = $this->field->args( 'show_option_none' ); 
  650. if ( ! empty( $option_none ) ) { 
  651. $option_none_value = apply_filters( "cmb2_taxonomy_radio_{$this->_id()}_default_value", apply_filters( 'cmb2_taxonomy_radio_default_value', '' ) ); 
  652. $args = array( 
  653. 'value' => $option_none_value,  
  654. 'label' => $option_none,  
  655. ); 
  656. if ( $saved_term == $option_none_value ) { 
  657. $args['checked'] = 'checked'; 
  658. $options .= $this->list_input( $args, $i ); 
  659. $i++; 
  660.  
  661. foreach ( $terms as $term ) { 
  662. $args = array( 
  663. 'value' => $term->slug,  
  664. 'label' => $term->name,  
  665. ); 
  666.  
  667. if ( $saved_term == $term->slug ) { 
  668. $args['checked'] = 'checked'; 
  669. $options .= $this->list_input( $args, $i ); 
  670. $i++; 
  671.  
  672. return $this->radio( array( 'options' => $options ), 'taxonomy_radio' ); 
  673.  
  674. public function taxonomy_radio_inline() { 
  675. $this->taxonomy_radio(); 
  676.  
  677. public function taxonomy_multicheck() { 
  678.  
  679. $names = $this->get_object_terms(); 
  680. $saved_terms = is_wp_error( $names ) || empty( $names ) 
  681. ? $this->field->args( 'default' ) 
  682. : wp_list_pluck( $names, 'slug' ); 
  683. $terms = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' ); 
  684. $name = $this->_name() . '[]'; 
  685. $options = ''; $i = 1; 
  686.  
  687. if ( ! $terms ) { 
  688. $options .= sprintf( '<li><label>%s</label></li>', esc_html( $this->_text( 'no_terms_text', __( 'No terms', 'cmb2' ) ) ) ); 
  689. } else { 
  690.  
  691. foreach ( $terms as $term ) { 
  692. $args = array( 
  693. 'value' => $term->slug,  
  694. 'label' => $term->name,  
  695. 'type' => 'checkbox',  
  696. 'name' => $name,  
  697. ); 
  698.  
  699. if ( is_array( $saved_terms ) && in_array( $term->slug, $saved_terms ) ) { 
  700. $args['checked'] = 'checked'; 
  701. $options .= $this->list_input( $args, $i ); 
  702. $i++; 
  703.  
  704. $classes = false === $this->field->args( 'select_all_button' ) 
  705. ? 'cmb2-checkbox-list no-select-all cmb2-list' 
  706. : 'cmb2-checkbox-list cmb2-list'; 
  707.  
  708. return $this->radio( array( 'class' => $classes, 'options' => $options ), 'taxonomy_multicheck' ); 
  709.  
  710. public function taxonomy_multicheck_inline() { 
  711. $this->taxonomy_multicheck(); 
  712.  
  713. public function oembed() { 
  714. $meta_value = trim( $this->field->escaped_value() ); 
  715. $oembed = ! empty( $meta_value ) 
  716. ? cmb2_get_oembed( array( 
  717. 'url' => $this->field->escaped_value(),  
  718. 'object_id' => $this->field->object_id,  
  719. 'object_type' => $this->field->object_type,  
  720. 'oembed_args' => array( 'width' => '640' ),  
  721. 'field_id' => $this->_id(),  
  722. ) ) 
  723. : ''; 
  724.  
  725. echo $this->input( array( 
  726. 'class' => 'cmb2-oembed regular-text',  
  727. 'data-objectid' => $this->field->object_id,  
  728. 'data-objecttype' => $this->field->object_type,  
  729. ) ),  
  730. '<p class="cmb-spinner spinner" style="display:none;"></p>',  
  731. '<div id="', $this->_id( '-status' ), '" class="cmb2-media-status ui-helper-clearfix embed_wrap">', $oembed, '</div>'; 
  732.  
  733. public function file_list() { 
  734. $meta_value = $this->field->escaped_value(); 
  735. $name = $this->_name(); 
  736. $img_size = $this->field->args( 'preview_size' ); 
  737.  
  738. echo $this->input( array( 
  739. 'type' => 'hidden',  
  740. 'class' => 'cmb2-upload-file cmb2-upload-list',  
  741. 'size' => 45, 'desc' => '', 'value' => '',  
  742. 'data-previewsize' => is_array( $img_size ) ? sprintf( '[%s]', implode( ', ', $img_size ) ) : 50,  
  743. ) ),  
  744. $this->input( array( 
  745. 'type' => 'button',  
  746. 'class' => 'cmb2-upload-button button cmb2-upload-list',  
  747. 'value' => esc_html( $this->_text( 'add_upload_files_text', __( 'Add or Upload Files', 'cmb2' ) ) ),  
  748. 'name' => '', 'id' => '',  
  749. ) ); 
  750.  
  751. echo '<ul id="', $this->_id( '-status' ), '" class="cmb2-media-status cmb-attach-list">'; 
  752.  
  753. if ( $meta_value && is_array( $meta_value ) ) { 
  754.  
  755. foreach ( $meta_value as $id => $fullurl ) { 
  756. $id_input = $this->input( array( 
  757. 'type' => 'hidden',  
  758. 'value' => $fullurl,  
  759. 'name' => $name . '[' . $id . ']',  
  760. 'id' => 'filelist-' . $id,  
  761. 'data-id' => $id,  
  762. 'desc' => '',  
  763. 'class' => false,  
  764. ) ); 
  765.  
  766. if ( $this->is_valid_img_ext( $fullurl ) ) { 
  767.  
  768. $this->img_status_output( array( 
  769. 'image' => wp_get_attachment_image( $id, $img_size ),  
  770. 'tag' => 'li',  
  771. 'id_input' => $id_input,  
  772. ) ); 
  773.  
  774. } else { 
  775.  
  776. $this->file_status_output( array( 
  777. 'value' => $fullurl,  
  778. 'tag' => 'li',  
  779. 'id_input' => $id_input,  
  780. ) ); 
  781.  
  782.  
  783. echo '</ul>'; 
  784.  
  785. CMB2_JS::add_dependencies( 'media-editor' ); 
  786.  
  787. public function file() { 
  788. $meta_value = $this->field->escaped_value(); 
  789. $options = (array) $this->field->options(); 
  790. $img_size = $this->field->args( 'preview_size' ); 
  791.  
  792. // if options array and 'url' => false, then hide the url field 
  793. $input_type = array_key_exists( 'url', $options ) && false === $options['url'] ? 'hidden' : 'text'; 
  794.  
  795. echo $this->input( array( 
  796. 'type' => $input_type,  
  797. 'class' => 'cmb2-upload-file regular-text',  
  798. 'size' => 45,  
  799. 'desc' => '',  
  800. 'data-previewsize' => is_array( $img_size ) ? '[' . implode( ', ', $img_size ) . ']' : 350,  
  801. ) ); 
  802.  
  803. printf( '<input class="cmb2-upload-button button" type="button" value="%s" />', esc_attr( $this->_text( 'add_upload_file_text', __( 'Add or Upload File', 'cmb2' ) ) ) ); 
  804.  
  805. $this->_desc( true, true ); 
  806.  
  807. $cached_id = $this->_id(); 
  808. // Reset field args for attachment ID 
  809. $args = $this->field->args(); 
  810. $args['id'] = $cached_id . '_id'; 
  811. unset( $args['_id'], $args['_name'] ); 
  812.  
  813. // And get new field object 
  814. $this->field = new CMB2_Field( array( 
  815. 'field_args' => $args,  
  816. 'group_field' => $this->field->group,  
  817. 'object_type' => $this->field->object_type,  
  818. 'object_id' => $this->field->object_id,  
  819. ) ); 
  820.  
  821. // Get ID value 
  822. $_id_value = $this->field->escaped_value( 'absint' ); 
  823.  
  824. // If there is no ID saved yet, try to get it from the url 
  825. if ( $meta_value && ! $_id_value ) { 
  826. $_id_value = cmb2_utils()->image_id_from_url( esc_url_raw( $meta_value ) ); 
  827.  
  828. echo $this->input( array( 
  829. 'type' => 'hidden',  
  830. 'class' => 'cmb2-upload-file-id',  
  831. 'value' => $_id_value,  
  832. 'desc' => '',  
  833. ) ),  
  834. '<div id="', $this->_id( '-status' ), '" class="cmb2-media-status">'; 
  835. if ( ! empty( $meta_value ) ) { 
  836.  
  837. if ( $this->is_valid_img_ext( $meta_value ) ) { 
  838.  
  839. if ( $_id_value ) { 
  840. $image = wp_get_attachment_image( $_id_value, $img_size, null, array( 'class' => 'cmb-file-field-image' ) ); 
  841. } else { 
  842. $size = is_array( $img_size ) ? $img_size[0] : 350; 
  843. $image = '<img style="max-width: ' . absint( $size ) . 'px; width: 100%; height: auto;" src="' . $meta_value . '" alt="" />'; 
  844.  
  845. $this->img_status_output( array( 
  846. 'image' => $image,  
  847. 'tag' => 'div',  
  848. 'cached_id' => $cached_id,  
  849. ) ); 
  850.  
  851. } else { 
  852.  
  853. $this->file_status_output( array( 
  854. 'value' => $meta_value,  
  855. 'tag' => 'div',  
  856. 'cached_id' => $cached_id,  
  857. ) ); 
  858.  
  859. echo '</div>'; 
  860.  
  861. CMB2_JS::add_dependencies( 'media-editor' ); 
  862.  
  863. /** 
  864. * file/file_list image wrap 
  865. * @since 2.0.2 
  866. * @param array $args Array of arguments for output 
  867. * @return string Image wrap output 
  868. */ 
  869. public function img_status_output( $args ) { 
  870. printf( '<%1$s class="img-status">%2$s<p class="cmb2-remove-wrapper"><a href="#" class="cmb2-remove-file-button"%3$s>%4$s</a></p>%5$s</%1$s>',  
  871. $args['tag'],  
  872. $args['image'],  
  873. isset( $args['cached_id'] ) ? ' rel="' . $args['cached_id'] . '"' : '',  
  874. esc_html( $this->_text( 'remove_image_text', __( 'Remove Image', 'cmb2' ) ) ),  
  875. isset( $args['id_input'] ) ? $args['id_input'] : '' 
  876. ); 
  877.  
  878. /** 
  879. * file/file_list file wrap 
  880. * @since 2.0.2 
  881. * @param array $args Array of arguments for output 
  882. * @return string File wrap output 
  883. */ 
  884. public function file_status_output( $args ) { 
  885. printf( '<%1$s class="file-status"><span>%2$s <strong>%3$s</strong></span>   (<a href="%4$s" target="_blank" rel="external">%5$s</a> / <a href="#" class="cmb2-remove-file-button"%6$s>%7$s</a>)%8$s</%1$s>',  
  886. $args['tag'],  
  887. esc_html( $this->_text( 'file_text', __( 'File:', 'cmb2' ) ) ),  
  888. $this->get_file_name_from_path( $args['value'] ),  
  889. $args['value'],  
  890. esc_html( $this->_text( 'file-download-text', __( 'Download', 'cmb2' ) ) ),  
  891. isset( $args['cached_id'] ) ? ' rel="' . $args['cached_id'] . '"' : '',  
  892. esc_html( $this->_text( 'remove_text', __( 'Remove', 'cmb2' ) ) ),  
  893. isset( $args['id_input'] ) ? $args['id_input'] : '' 
  894. ); 
  895.  
/vendor/wordimpress/maps-builder-core/includes/libraries/metabox/includes/CMB2_Types.php  
  1. class CMB2_Types { 
  2.  
  3. /** 
  4. * An iterator value for repeatable fields 
  5. * @var integer 
  6. * @since 1.0.0 
  7. */ 
  8. public $iterator = 0; 
  9.  
  10. /** 
  11. * Current CMB2_Field field object 
  12. * @var CMB2_Field object 
  13. * @since 1.0.0 
  14. */ 
  15. public $field; 
  16.  
  17. /** 
  18. * Current CMB2_Type object 
  19. * @var CMB2_Type object 
  20. * @since 2.2.2 
  21. */ 
  22. public $type; 
  23.  
  24. public function __construct( CMB2_Field $field ) { 
  25. $this->field = $field; 
  26.  
  27. /** 
  28. * Default fallback. Allows rendering fields via "cmb2_render_$fieldtype" hook 
  29. * @since 1.0.0 
  30. * @param string $fieldtype Non-existent field type name 
  31. * @param array $arguments All arguments passed to the method 
  32. */ 
  33. public function __call( $fieldtype, $arguments ) { 
  34. $proxied = array( 
  35. 'get_object_terms' => array(),  
  36. 'is_valid_img_ext' => false,  
  37. 'parse_args' => array(),  
  38. 'concat_items' => '',  
  39. 'select_option' => '',  
  40. 'list_input' => '',  
  41. 'list_input_checkbox' => '',  
  42. 'img_status_output' => '',  
  43. 'file_status_output' => '',  
  44. 'parse_picker_options' => array(),  
  45. ); 
  46. if ( isset( $proxied[ $fieldtype ] ) ) { 
  47. // Proxies the method call to the CMB2_Type object 
  48. return $this->proxy_method( $fieldtype, $proxied[ $fieldtype ], $arguments ); 
  49.  
  50. /** 
  51. * Pass non-existent field types through an action 
  52. * The dynamic portion of the hook name, $fieldtype, refers to the field type. 
  53. * @param array $field The passed in `CMB2_Field` object 
  54. * @param mixed $escaped_value The value of this field escaped. 
  55. * It defaults to `sanitize_text_field`. 
  56. * If you need the unescaped value, you can access it 
  57. * via `$field->value()` 
  58. * @param int $object_id The ID of the current object 
  59. * @param string $object_type The type of object you are working with. 
  60. * Most commonly, `post` (this applies to all post-types),  
  61. * but could also be `comment`, `user` or `options-page`. 
  62. * @param object $field_type_object This `CMB2_Types` object 
  63. */ 
  64. do_action( "cmb2_render_$fieldtype", $this->field, $this->field->escaped_value(), $this->field->object_id, $this->field->object_type, $this ); 
  65.  
  66. /** 
  67. * Render a field (and handle repeatable) 
  68. * @since 1.1.0 
  69. */ 
  70. public function render() { 
  71. if ( $this->field->args( 'repeatable' ) ) { 
  72. $this->render_repeatable_field(); 
  73. } else { 
  74. $this->_render(); 
  75.  
  76. /** 
  77. * Render a field type 
  78. * @since 1.1.0 
  79. */ 
  80. protected function _render() { 
  81. $this->field->peform_param_callback( 'before_field' ); 
  82. echo $this->{$this->field->type()}(); 
  83. $this->field->peform_param_callback( 'after_field' ); 
  84.  
  85. /** 
  86. * Proxies the method call to the CMB2_Type object, if it exists, otherwise returns a default fallback value. 
  87. * @since 2.2.2 
  88. * @param string $method Method to call on the CMB2_Type object. 
  89. * @param mixed $default Default fallback value if method is not found. 
  90. * @return mixed Results from called method. 
  91. */ 
  92. protected function proxy_method( $method, $default, $args = array() ) { 
  93. if ( is_object( $this->type ) && method_exists( $this->type, $method ) ) { 
  94. return empty( $args ) 
  95. ? $this->type->$method() 
  96. : call_user_func_array( array( $this->type, $method ), $args ); 
  97.  
  98. return $default; 
  99.  
  100. /** 
  101. * Retrieve text parameter from field's options array (if it has one), or use fallback text 
  102. * @since 2.0.0 
  103. * @param string $text_key Key in field's options array 
  104. * @param string $fallback Fallback text 
  105. * @return string Text 
  106. */ 
  107. public function _text( $text_key, $fallback = '' ) { 
  108. return $this->field->string( $text_key, $fallback ); 
  109.  
  110. /** 
  111. * Determine a file's extension 
  112. * @since 1.0.0 
  113. * @param string $file File url 
  114. * @return string|false File extension or false 
  115. */ 
  116. public function get_file_ext( $file ) { 
  117. return cmb2_utils()->get_file_ext( $file ); 
  118.  
  119. /** 
  120. * Get the file name from a url 
  121. * @since 2.0.0 
  122. * @param string $value File url or path 
  123. * @return string File name 
  124. */ 
  125. public function get_file_name_from_path( $value ) { 
  126. return cmb2_utils()->get_file_name_from_path( $value ); 
  127.  
  128. /** 
  129. * Combines attributes into a string for a form element 
  130. * @since 1.1.0 
  131. * @param array $attrs Attributes to concatenate 
  132. * @param array $attr_exclude Attributes that should NOT be concatenated 
  133. * @return string String of attributes for form element 
  134. */ 
  135. public function concat_attrs( $attrs, $attr_exclude = array() ) { 
  136. $attr_exclude[] = 'rendered'; 
  137. $attributes = ''; 
  138. foreach ( $attrs as $attr => $val ) { 
  139. $excluded = in_array( $attr, (array) $attr_exclude, true ); 
  140. $empty = false === $val && 'value' !== $attr; 
  141. if ( ! $excluded && ! $empty ) { 
  142. // if data attribute, use single quote wraps, else double 
  143. $quotes = false !== stripos( $attr, 'data-' ) ? "'" : '"'; 
  144. $attributes .= sprintf( ' %1$s=%3$s%2$s%3$s', $attr, $val, $quotes ); 
  145. return $attributes; 
  146.  
  147. /** 
  148. * Generates repeatable field table markup 
  149. * @since 1.0.0 
  150. */ 
  151. public function render_repeatable_field() { 
  152. $table_id = $this->field->id() . '_repeat'; 
  153.  
  154. $this->_desc( true, true, true ); 
  155. ?> 
  156.  
  157. <div id="<?php echo $table_id; ?>" class="cmb-repeat-table cmb-nested"> 
  158. <div class="cmb-tbody cmb-field-list"> 
  159. <?php $this->repeatable_rows(); ?> 
  160. </div> 
  161. </div> 
  162. <p class="cmb-add-row"> 
  163. <button type="button" data-selector="<?php echo $table_id; ?>" class="cmb-add-row-button button"><?php echo esc_html( $this->_text( 'add_row_text', __( 'Add Row', 'cmb2' ) ) ); ?></button> 
  164. </p> 
  165.  
  166. <?php 
  167. // reset iterator 
  168. $this->iterator = 0; 
  169.  
  170. /** 
  171. * Generates repeatable field rows 
  172. * @since 1.1.0 
  173. */ 
  174. public function repeatable_rows() { 
  175. $meta_value = array_filter( (array) $this->field->escaped_value() ); 
  176. // check for default content 
  177. $default = $this->field->get_default(); 
  178.  
  179. // check for saved data 
  180. if ( ! empty( $meta_value ) ) { 
  181. $meta_value = is_array( $meta_value ) ? array_filter( $meta_value ) : $meta_value; 
  182. $meta_value = ! empty( $meta_value ) ? $meta_value : $default; 
  183. } else { 
  184. $meta_value = $default; 
  185.  
  186. // Loop value array and add a row 
  187. if ( ! empty( $meta_value ) ) { 
  188. $count = count( $meta_value ); 
  189. foreach ( (array) $meta_value as $val ) { 
  190. $this->field->escaped_value = $val; 
  191. $this->repeat_row( $count < 2 ); 
  192. $this->iterator++; 
  193. } else { 
  194.  
  195. // If value is empty (including empty array), then clear the value. 
  196. $this->field->escaped_value = $this->field->value = null; 
  197.  
  198. // Otherwise add one row 
  199. $this->repeat_row( true ); 
  200.  
  201. // Then add an empty row 
  202. $this->field->escaped_value = ''; 
  203. $this->iterator = $this->iterator ? $this->iterator : 1; 
  204. $this->repeat_row( false, 'empty-row hidden' ); 
  205.  
  206. /** 
  207. * Generates a repeatable row's markup 
  208. * @since 1.1.0 
  209. * @param bool $disable_remover Whether remove button should be disabled 
  210. * @param string $class Repeatable table row's class 
  211. */ 
  212. protected function repeat_row( $disable_remover = false, $class = 'cmb-repeat-row' ) { 
  213. $disabled = $disable_remover ? ' button-disabled' : ''; 
  214. ?> 
  215.  
  216. <div class="cmb-row <?php echo $class; ?>"> 
  217. <div class="cmb-td"> 
  218. <?php $this->_render(); ?> 
  219. </div> 
  220. <div class="cmb-td cmb-remove-row"> 
  221. <button type="button" class="button cmb-remove-row-button<?php echo $disabled; ?>"><?php echo esc_html( $this->_text( 'remove_row_text', __( 'Remove', 'cmb2' ) ) ); ?></button> 
  222. </div> 
  223. </div> 
  224.  
  225. <?php 
  226.  
  227. /** 
  228. * Generates description markup 
  229. * @since 1.0.0 
  230. * @param boolean $paragraph Paragraph tag or span 
  231. * @param boolean $echo Whether to echo description or only return it 
  232. * @return string Field's description markup 
  233. */ 
  234. public function _desc( $paragraph = false, $echo = false, $repeat_group = false ) { 
  235. // Prevent description from printing multiple times for repeatable fields 
  236. if ( ! $repeat_group && ( $this->field->args( 'repeatable' ) || $this->iterator > 0 ) ) { 
  237. return ''; 
  238.  
  239. $desc = $this->field->args( 'description' ); 
  240.  
  241. if ( ! $desc ) { 
  242. return; 
  243.  
  244. $tag = $paragraph ? 'p' : 'span'; 
  245. $desc = sprintf( "\n" . '<%1$s class="cmb2-metabox-description">%2$s</%1$s>' . "\n", $tag, $desc ); 
  246.  
  247. if ( $echo ) { 
  248. echo $desc; 
  249.  
  250. return $desc; 
  251.  
  252. /** 
  253. * Generate field name attribute 
  254. * @since 1.1.0 
  255. * @param string $suffix For multi-part fields 
  256. * @return string Name attribute 
  257. */ 
  258. public function _name( $suffix = '' ) { 
  259. return $this->field->args( '_name' ) . ( $this->field->args( 'repeatable' ) ? '[' . $this->iterator . ']' : '' ) . $suffix; 
  260.  
  261. /** 
  262. * Generate field id attribute 
  263. * @since 1.1.0 
  264. * @param string $suffix For multi-part fields 
  265. * @return string Id attribute 
  266. */ 
  267. public function _id( $suffix = '' ) { 
  268. return $this->field->id() . $suffix . ( $this->field->args( 'repeatable' ) ? '_' . $this->iterator . '" data-iterator="' . $this->iterator : '' ); 
  269.  
  270. /** 
  271. * Handles outputting an 'input' element 
  272. * @since 1.1.0 
  273. * @param array $args Override arguments 
  274. * @param array $type Field type 
  275. * @return string Form input element 
  276. */ 
  277. public function input( $args = array(), $type = __FUNCTION__ ) { 
  278. $this->type = new CMB2_Type_Text( $this, $args, $type ); 
  279. return $this->type->render(); 
  280.  
  281. /** 
  282. * Handles outputting an 'textarea' element 
  283. * @since 1.1.0 
  284. * @param array $args Override arguments 
  285. * @return string Form textarea element 
  286. */ 
  287. public function textarea( $args = array() ) { 
  288. $this->type = new CMB2_Type_Textarea( $this, $args ); 
  289. return $this->type->render(); 
  290.  
  291. /** 
  292. * Begin Field Types 
  293. */ 
  294.  
  295. public function text() { 
  296. return $this->input(); 
  297.  
  298. public function hidden() { 
  299. return $this->input( array( 
  300. 'type' => 'hidden',  
  301. 'desc' => '',  
  302. 'class' => false,  
  303. ) ); 
  304.  
  305. public function text_small() { 
  306. return $this->input( array( 
  307. 'class' => 'cmb2-text-small',  
  308. 'desc' => $this->_desc(),  
  309. ) ); 
  310.  
  311. public function text_medium() { 
  312. return $this->input( array( 
  313. 'class' => 'cmb2-text-medium',  
  314. 'desc' => $this->_desc(),  
  315. ) ); 
  316.  
  317. public function text_email() { 
  318. return $this->input( array( 
  319. 'class' => 'cmb2-text-email cmb2-text-medium',  
  320. 'type' => 'email',  
  321. ) ); 
  322.  
  323. public function text_url() { 
  324. return $this->input( array( 
  325. 'class' => 'cmb2-text-url cmb2-text-medium regular-text',  
  326. 'value' => $this->field->escaped_value( 'esc_url' ),  
  327. ) ); 
  328.  
  329. public function text_money() { 
  330. $input = $this->input( array( 
  331. 'class' => 'cmb2-text-money',  
  332. 'desc' => $this->_desc(),  
  333. ) ); 
  334. return ( ! $this->field->get_param_callback_result( 'before_field' ) ? '$ ' : ' ' ) . $input; 
  335.  
  336. public function textarea_small() { 
  337. return $this->textarea( array( 
  338. 'class' => 'cmb2-textarea-small',  
  339. 'rows' => 4,  
  340. ) ); 
  341.  
  342. public function textarea_code() { 
  343. $this->type = new CMB2_Type_Textarea_Code( $this ); 
  344. return $this->type->render(); 
  345.  
  346. public function wysiwyg( $args = array() ) { 
  347. $this->type = new CMB2_Type_Wysiwyg( $this, $args ); 
  348. return $this->type->render(); 
  349.  
  350. public function text_date( $args = array() ) { 
  351. $this->type = new CMB2_Type_Text_Date( $this, $args ); 
  352. return $this->type->render(); 
  353.  
  354. // Alias for text_date 
  355. public function text_date_timestamp( $args = array() ) { 
  356. return $this->text_date( $args ); 
  357.  
  358. public function text_time( $args = array() ) { 
  359. $this->type = new CMB2_Type_Text_Time( $this, $args ); 
  360. return $this->type->render(); 
  361.  
  362. public function text_datetime_timestamp( $args = array() ) { 
  363. $this->type = new CMB2_Type_Text_Datetime_Timestamp( $this, $args ); 
  364. return $this->type->render(); 
  365.  
  366. public function text_datetime_timestamp_timezone( $args = array() ) { 
  367. $this->type = new CMB2_Type_Text_Datetime_Timestamp_Timezone( $this, $args ); 
  368. return $this->type->render(); 
  369.  
  370. public function select_timezone() { 
  371. $this->type = new CMB2_Type_Select_Timezone( $this ); 
  372. return $this->type->render(); 
  373.  
  374. public function colorpicker( $args = array(), $meta_value = '' ) { 
  375. $this->type = new CMB2_Type_Colorpicker( $this, $args, $meta_value ); 
  376. return $this->type->render(); 
  377.  
  378. public function title( $args = array() ) { 
  379. $this->type = new CMB2_Type_Title( $this, $args ); 
  380. return $this->type->render(); 
  381.  
  382. public function select( $args = array() ) { 
  383. $this->type = new CMB2_Type_Select( $this, $args ); 
  384. return $this->type->render(); 
  385.  
  386. public function taxonomy_select() { 
  387. $this->type = new CMB2_Type_Taxonomy_Select( $this ); 
  388. return $this->type->render(); 
  389.  
  390. public function radio( $args = array(), $type = __FUNCTION__ ) { 
  391. $this->type = new CMB2_Type_Radio( $this, $args, $type ); 
  392. return $this->type->render(); 
  393.  
  394. public function radio_inline() { 
  395. return $this->radio( array(), __FUNCTION__ ); 
  396.  
  397. public function multicheck( $type = 'checkbox' ) { 
  398. $this->type = new CMB2_Type_Multicheck( $this, array(), $type ); 
  399. return $this->type->render(); 
  400.  
  401. public function multicheck_inline() { 
  402. return $this->multicheck( 'multicheck_inline' ); 
  403.  
  404. public function checkbox( $args = array(), $is_checked = null ) { 
  405. $this->type = new CMB2_Type_Checkbox( $this, $args, $is_checked ); 
  406. return $this->type->render(); 
  407.  
  408. public function taxonomy_radio() { 
  409. $this->type = new CMB2_Type_Taxonomy_Radio( $this ); 
  410. return $this->type->render(); 
  411.  
  412. public function taxonomy_radio_inline() { 
  413. return $this->taxonomy_radio(); 
  414.  
  415. public function taxonomy_multicheck() { 
  416. $this->type = new CMB2_Type_Taxonomy_Multicheck( $this ); 
  417. return $this->type->render(); 
  418.  
  419. public function taxonomy_multicheck_inline() { 
  420. return $this->taxonomy_multicheck(); 
  421.  
  422. public function oembed() { 
  423. $this->type = new CMB2_Type_Oembed( $this ); 
  424. return $this->type->render(); 
  425.  
  426. public function file_list() { 
  427. $this->type = new CMB2_Type_File_List( $this ); 
  428. return $this->type->render(); 
  429.  
  430. public function file() { 
  431. $this->type = new CMB2_Type_File( $this ); 
  432. return $this->type->render(); 
  433.