Repository: CMB2/CMB2-Snippet-Library Branch: master Commit: d21e516b34da Files: 92 Total size: 222.6 KB Directory structure: gitextract_4vuue3u2/ ├── .gitignore ├── CONTRIBUTING.md ├── README.md ├── api/ │ ├── README.md │ └── cmb2-file-list-ordered.php ├── conditional-display/ │ ├── exclude-for-ids.php │ ├── hide-on-new-post-page.php │ ├── show-for-taxonomy-terms.php │ ├── show-if-matching-meta-value.php │ └── show-only-for-top-level-posts.php ├── custom-field-types/ │ ├── README.md │ ├── address-field-type/ │ │ ├── address-field-type.php │ │ └── class-cmb2-render-address-field.php │ ├── associate-wp-menu-field.php │ ├── autocomplete-field-type.php │ ├── button-field-type.php │ ├── dashicon-radio-field/ │ │ └── dashicon-radio-field.php │ ├── default-category-field.php │ ├── default-tags-field.php │ ├── form-field-field-type.php │ ├── multicheck_posttype-field_type.php │ ├── multicheck_title-field_type.php │ ├── post-list-field-type.php │ ├── select-multiple-field-type.php │ ├── star-rating-field-type/ │ │ ├── css/ │ │ │ └── star-rating-field-type.css │ │ └── star-rating-field-type.php │ ├── taxonomy-radio-with-image-field-type/ │ │ ├── DJ_Taxonomy_Radio_Hierarchical_With_Image.php │ │ ├── DJ_Taxonomy_Radio_With_Image_Display.php │ │ └── taxonomy-radio-with-image-field-type.php │ ├── textarea-with-checkbox.php │ └── year-range-field-type.php ├── filters-and-actions/ │ ├── README.md │ ├── cmb2-add-fields-dynamically.php │ ├── cmb2_all_or_nothing_types-filter.php │ ├── cmb2_before_form-and-cmb2_after_form-hooks.php │ ├── cmb2_init_$cmb_id-add-fields.php │ ├── cmb2_init_$cmb_id-modify-object-types.php │ ├── cmb2_init_$cmb_id-remove-field.php │ ├── cmb2_init_$cmb_id-replace-field.php │ ├── cmb2_init_before_hookup-add-fields.php │ ├── cmb2_init_before_hookup-remove-cmb2-metabox.php │ ├── cmb2_init_before_hookup-update-existing-fields.php │ ├── cmb2_override_{$field_id}_meta_value-filter.php │ ├── custom-css-for-specific-metabox.php │ ├── disable-styles-on-front-end-forms.php │ ├── localize-date-format.php │ ├── override-cmb2-data-source.php │ └── save-default-group-field-value-based-on-other-field.php ├── front-end/ │ ├── README.md │ ├── cmb2-front-end-editor.php │ ├── cmb2-front-end-submit.php │ ├── cmb2-front-end-wordpress-media-uploader.php │ ├── cmb2-metabox-shortcode.php │ └── output-file-list.php ├── helper-functions/ │ ├── README.md │ ├── helper-functions.php │ ├── modify-cmb2_metabox_form-format.php │ ├── modify-cmb2_metabox_form-output.php │ └── modify-cmb2_metabox_form-save-button-text.php ├── javascript/ │ ├── README.md │ ├── cmb2-auto-scroll-to-new-group.php │ ├── cmb2-js-validation-required.php │ ├── dynamically-change-group-field-title-from-subfield.php │ ├── limit-number-of-multiple-repeat-groups.php │ ├── limit-number-of-repeat-fields.php │ └── limit-number-of-repeat-groups.php ├── metaboxes/ │ └── README.md ├── misc/ │ ├── README.md │ ├── add-wrap-to-group-of-fields.php │ ├── adding-wordcount-to-cmb2-wysiwyg-field.php │ ├── cmb2-field-in-publish-box.php │ ├── helper-functions.php │ ├── outputting-cmb2-fields-in-featured-image-metabox.php │ ├── outputting-forms-outside-metaboxes.php │ ├── replace-wp-excerpt-with-cmb2-field.php │ └── replace-wp-title-content-thumbnail-with-cmb2-fields.php ├── modified-field-types/ │ ├── README.md │ ├── modify-button-text-for-file-type.php │ └── readonly-field-type.php ├── options-and-settings-pages/ │ ├── README.md │ ├── add-cmb2-settings-to-other-settings-pages.php │ ├── custom-display-callback.php │ ├── genesis-cpt-archive-metabox.php │ ├── genesis-settings-metabox.php │ ├── network-options-cmb.php │ ├── non-cmb2-options-page.php │ ├── options-pages-with-submenus.php │ ├── options-pages-with-tabs-and-submenus.php │ ├── submenu-options-pages.php │ └── theme-options-cmb.php ├── user-meta-and-settings/ │ └── README.md └── widgets/ └── widget-example.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Created by https://www.gitignore.io/api/osx ### OSX ### *.DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk ================================================ FILE: CONTRIBUTING.md ================================================ # Contribute To CMB2 Code Snippet Library The CMB2 code snippet library is a community-maintained repository and so contributions are always welcome. Thanks to EDD for [the inspiration](https://github.com/easydigitaldownloads/library) for this library. ## Submitting a Snippet To submit a code library for inclusion in the library, please fork the repository and then submit a [pull request](https://github.com/jtsternberg/CMB2-Snippet-Library/pulls). Pippin has an excellent tutorial for [submitting your first pull request](http://pippinsplugins.com/submitting-your-first-pull-request/). Guidelines for submission: - Each snippet should be placed in it's own file. - Each file should be named appropriately based on the purpose of the snippet. - Files should be placed in the appropriate category (folder). If no category exists, you may create one with your pull request. - All functions and classes should be prefixed with your own unique prefix, preferrably one that contains your initials followed by `_cmb2_`. For example: `jt_cmb2_{function name here}`. - (optional) Add [WordPress plugin headers](http://codex.wordpress.org/File_Header#Plugin_File_Header_Example) to allow others to use your snippet as a plugin. ================================================ FILE: README.md ================================================ CMB2 Code Snippet Library ======================== This is a community-maintained repository of code snippets that help modify the default behavior of [CMB2](https://github.com/WebDevStudios/CMB2/). Snippets are organized into categories (folders) and each snippet is placed in its own file with a name that describes what it does. Thank you to the EDD team for [the inspiration](https://github.com/easydigitaldownloads/library) for this library. ## Submitting Your Snippet We welcome and encourage everyone to submit their code snippets. If you would like to submit your snippet, please [fork](https://github.com/WebDevStudios/CMB2-Snippet-Library/fork) the repository and then create a [pull request](https://github.com/WebDevStudios/CMB2-Snippet-Library/compare/). Please refer to the [Contributing guidelines](https://github.com/WebDevStudios/CMB2-Snippet-Library/blob/master/CONTRIBUTING.md) before submitting your pull request. ## Proposing a Snippet If there is a snippet you are unable to find and would like to propose get written, please open an [issue](https://github.com/WebDevStudios/CMB2-Snippet-Library/issues) and describe your need. ## Notes This is not a tutorial archive. Please see the [CMB2 github repo wiki](https://github.com/WebDevStudios/CMB2/wiki) if you're looking for official documentation and tutorials. These snippets come with no guarantees. Due to the constant evolution of the CMB2 codebase, it is possible that the behavior of these snippets may change overtime. Find something broken? [Let us know](https://github.com/WebDevStudios/CMB2-Snippet-Library/issues)! ================================================ FILE: api/README.md ================================================ CMB2 API Snippets ========== Snippets related to the CMB2 API endpoints/functionality. ================================================ FILE: api/cmb2-file-list-ordered.php ================================================ $file_url ) { $value[] = array( 'id' => $file_id, 'url' => $file_url, ); } } return $value; } /** * Filters the value before it is sent to the REST request. * * "_yourprefix_demo_file_list" is a dynamic portion of the hook name, referring to the field id. */ add_filter( 'cmb2_get_rest_value_for__yourprefix_demo_file_list', 'yourprefix_cmb2_ordered_file_list_array_in_api', 10, 2 ); return; // Another method to make this modification to several different file_list fields. // Do not use both of these methods. Pick one. define( 'YOURPREFIX_FILE_LIST_IDS', array( '_yourprefix_demo_file_list', 'xyz' // etc. ) ); function yourprefix_cmb2_ordered_file_list_array_in_api_2( $value, $field ) { // Replace if ( in_array( $field->_id(), YOURPREFIX_FILE_LIST_IDS, true ) && ! empty( $value ) && is_array( $value ) ) { $files = $value; $value = array(); foreach ( $files as $file_id => $file_url ) { $value[] = array( 'id' => $file_id, 'url' => $file_url, ); } } return $value; } add_filter( 'cmb2_get_rest_value_file_list', 'yourprefix_cmb2_ordered_file_list_array_in_api_2', 10, 2 ); ================================================ FILE: conditional-display/exclude-for-ids.php ================================================ 'exclude_for_ids', 'title' => 'Demo', 'exclude_ids' => array( 1, 2, 3, 55 ), // Exclude metabox on these post-ids 'show_on_cb' => 'cmb2_exclude_for_ids', // function should return a bool value ) ); /** * Exclude metabox on specific IDs * @param object $cmb CMB2 object * @return bool True/false whether to show the metabox */ function cmb2_exclude_for_ids( $cmb ) { $ids_to_exclude = $cmb->prop( 'exclude_ids', array() ); $excluded = in_array( $cmb->object_id(), $ids_to_exclude, true ); return ! $excluded; } ================================================ FILE: conditional-display/hide-on-new-post-page.php ================================================ 'exclude_for_ids', 'title' => 'Demo', 'exclude_from' => array( 'post-new.php' ), // Exclude metabox on new-post screen 'show_on_cb' => 'tgm_exclude_from_new', // function should return a bool value ) ); /** * Removes metabox from appearing on post new screens before the post * ID has been set. * @author Thomas Griffin * @param object $cmb CMB2 object * @return bool True/false whether to show the metabox */ function tgm_exclude_from_new( $cmb ) { global $pagenow; $exclude_from = $cmb->prop( 'exclude_from', array( 'post-new.php' ) ); $excluded = in_array( $pagenow, $exclude_from, true ); return ! $excluded; } ================================================ FILE: conditional-display/show-for-taxonomy-terms.php ================================================ 'show_for_taxonomy_terms', 'title' => 'Demo', 'show_on_cb' => 'be_taxonomy_show_on_filter', // function should return a bool value 'show_on_terms' => array( 'category' => array( 'featured' ), 'post_tag' => array( 'best-of' ), ), ) ); /** * Taxonomy show_on filter * @author Bill Erickson * @param object $cmb CMB2 object * @return bool True/false whether to show the metabox */ function be_taxonomy_show_on_filter( $cmb ) { $tax_terms_to_show_on = $cmb->prop( 'show_on_terms', array() ); if ( empty( $tax_terms_to_show_on ) || ! $cmb->object_id() ) { return false; } $post_id = $cmb->object_id(); $post = get_post( $post_id ); foreach( (array) $tax_terms_to_show_on as $taxonomy => $slugs ) { if ( ! is_array( $slugs ) ) { $slugs = array( $slugs ); } $terms = $post ? get_the_terms( $post, $taxonomy ) : wp_get_object_terms( $post_id, $taxonomy ); if ( ! empty( $terms ) ) { foreach( $terms as $term ) { if ( in_array( $term->slug, $slugs, true ) ) { wp_die( ': '. print_r( 'show it', true ) .'' ); // Ok, show this metabox return true; } } } } return false; } ================================================ FILE: conditional-display/show-if-matching-meta-value.php ================================================ 'wiki_status_metabox', 'title' => 'Status Metabox', 'object_types' => array( 'page', ), // Post type ) ); $cmb->add_field( array( 'name' => 'Status', 'id' => 'wiki_status', 'type' => 'select', 'default' => 'internal', 'options' => array( 'internal' => 'Internal', 'external' => 'External', ), ) ); /** * Metabox to conditionally display if the 'status' is set to 'External'. */ $cmb = new_cmb2_box( array( 'id' => 'wiki_conditonal_metabox', 'title' => 'Contact Info', 'object_types' => array( 'page', ), // Post type 'show_on_cb' => 'cmb_only_show_for_external', // function should return a bool value ) ); $cmb->add_field( array( 'name' => 'Email', 'id' => 'wiki_email', 'type' => 'text_email', ) ); } /** * Only display a metabox if the page's 'status' is 'external' * @param object $cmb CMB2 object * @return bool True/false whether to show the metabox */ function cmb_only_show_for_external( $cmb ) { $status = get_post_meta( $cmb->object_id(), 'wiki_status', 1 ); // Only show if status is 'external' return 'external' === $status; } ================================================ FILE: conditional-display/show-only-for-top-level-posts.php ================================================ 'exclude_for_ids', 'title' => 'Demo', 'show_on_cb' => 'ba_metabox_add_for_top_level_posts_only', // function should return a bool value ) ); /** * Exclude metabox on non top level posts * @author Travis Northcutt * @param object $cmb CMB2 object * @return bool True/false whether to show the metabox */ function ba_metabox_add_for_top_level_posts_only( $cmb ) { $has_parent = $cmb->object_id() && get_post_ancestors( $cmb->object_id() ); return ! $has_parent; } ================================================ FILE: custom-field-types/README.md ================================================ Custom Field Types ========== Snippets for [adding custom CMB2 field types](https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-field-types). ================================================ FILE: custom-field-types/address-field-type/address-field-type.php ================================================ '', 'address-2' => '', 'city' => '', 'state' => '', 'zip' => '', 'country' => '', ) ); $output = '
'; $output .= '

Address: ' . esc_html( $address['address-1'] ) . '

'; if ( $address['address-2'] ) { $output .= '

' . esc_html( $address['address-2'] ) . '

'; } $output .= '

City: ' . esc_html( $address['city'] ) . '

'; $output .= '

State: ' . esc_html( $address['state'] ) . '

'; $output .= '

Zip: ' . esc_html( $address['zip'] ) . '

'; $output .= '
'; return apply_filters( 'jt_cmb2_get_address_field', $output ); } function cmb2_init_address_field() { require_once dirname( __FILE__ ) . '/class-cmb2-render-address-field.php'; CMB2_Render_Address_Field::init(); } add_action( 'cmb2_init', 'cmb2_init_address_field' ); ================================================ FILE: custom-field-types/address-field-type/class-cmb2-render-address-field.php ================================================ 'Alabama', 'AK' => 'Alaska', 'AZ' => 'Arizona', 'AR' => 'Arkansas', 'CA' => 'California', 'CO' => 'Colorado', 'CT' => 'Connecticut', 'DE' => 'Delaware', 'DC' => 'District Of Columbia', 'FL' => 'Florida', 'GA' => 'Georgia', 'HI' => 'Hawaii', 'ID' => 'Idaho', 'IL' => 'Illinois', 'IN' => 'Indiana', 'IA' => 'Iowa', 'KS' => 'Kansas', 'KY' => 'Kentucky', 'LA' => 'Louisiana', 'ME' => 'Maine', 'MD' => 'Maryland', 'MA' => 'Massachusetts', 'MI' => 'Michigan', 'MN' => 'Minnesota', 'MS' => 'Mississippi', 'MO' => 'Missouri', 'MT' => 'Montana', 'NE' => 'Nebraska', 'NV' => 'Nevada', 'NH' => 'New Hampshire', 'NJ' => 'New Jersey', 'NM' => 'New Mexico', 'NY' => 'New York', 'NC' => 'North Carolina', 'ND' => 'North Dakota', 'OH' => 'Ohio', 'OK' => 'Oklahoma', 'OR' => 'Oregon', 'PA' => 'Pennsylvania', 'RI' => 'Rhode Island', 'SC' => 'South Carolina', 'SD' => 'South Dakota', 'TN' => 'Tennessee', 'TX' => 'Texas', 'UT' => 'Utah', 'VT' => 'Vermont', 'VA' => 'Virginia', 'WA' => 'Washington', 'WV' => 'West Virginia', 'WI' => 'Wisconsin', 'WY' => 'Wyoming' ); public static function init() { add_filter( 'cmb2_render_class_address', array( __CLASS__, 'class_name' ) ); add_filter( 'cmb2_sanitize_address', array( __CLASS__, 'maybe_save_split_values' ), 12, 4 ); /** * The following snippets are required for allowing the address field * to work as a repeatable field, or in a repeatable group. */ add_filter( 'cmb2_sanitize_address', array( __CLASS__, 'sanitize' ), 10, 5 ); add_filter( 'cmb2_types_esc_address', array( __CLASS__, 'escape' ), 10, 4 ); add_filter( 'cmb2_override_meta_value', array( __CLASS__, 'get_split_meta_value' ), 12, 4 ); } public static function class_name() { return __CLASS__; } /** * Handles outputting the address field. */ public function render() { // make sure we assign each part of the value we need. $value = wp_parse_args( $this->field->escaped_value(), array( 'address-1' => '', 'address-2' => '', 'city' => '', 'state' => '', 'zip' => '', 'country' => '', ) ); if ( ! $this->field->args( 'do_country' ) ) { $state_list = $this->field->args( 'state_list', array() ); if ( empty( $state_list ) ) { $state_list = self::$state_list; } // Add the "label" option. Can override via the field text param. $state_list = array( '' => esc_html( $this->_text( 'address_select_state_text', 'Select a State' ) ) ) + $state_list; $state_options = ''; foreach ( $state_list as $abrev => $state ) { $state_options .= ''; } } $state_label = 'State'; if ( $this->field->args( 'do_country' ) ) { $state_label .= '/Province'; } ob_start(); // Do html. ?>

types->input( array( 'name' => $this->_name( '[address-1]' ), 'id' => $this->_id( '_address_1' ), 'value' => $value['address-1'], 'desc' => '', ) ); ?>

types->input( array( 'name' => $this->_name( '[address-2]' ), 'id' => $this->_id( '_address_2' ), 'value' => $value['address-2'], 'desc' => '', ) ); ?>

types->input( array( 'class' => 'cmb_text_small', 'name' => $this->_name( '[city]' ), 'id' => $this->_id( '_city' ), 'value' => $value['city'], 'desc' => '', ) ); ?>

field->args( 'do_country' ) ) : ?> types->input( array( 'class' => 'cmb_text_small', 'name' => $this->_name( '[state]' ), 'id' => $this->_id( '_state' ), 'value' => $value['state'], 'desc' => '', ) ); ?> types->select( array( 'name' => $this->_name( '[state]' ), 'id' => $this->_id( '_state' ), 'options' => $state_options, 'desc' => '', ) ); ?>

types->input( array( 'class' => 'cmb_text_small', 'name' => $this->_name( '[zip]' ), 'id' => $this->_id( '_zip' ), 'value' => $value['zip'], 'type' => 'number', 'desc' => '', ) ); ?>
field->args( 'do_country' ) ) : ?>

types->input( array( 'name' => $this->_name( '[country]' ), 'id' => $this->_id( '_country' ), 'value' => $value['country'], 'desc' => '', ) ); ?>

_desc();?>

rendered( ob_get_clean() ); } /** * Optionally save the Address values into separate fields */ public static function maybe_save_split_values( $override_value, $value, $object_id, $field_args ) { if ( ! isset( $field_args['split_values'] ) || ! $field_args['split_values'] ) { // Don't do the override. return $override_value; } $address_keys = array( 'address-1', 'address-2', 'city', 'state', 'zip' ); foreach ( $address_keys as $key ) { if ( ! empty( $value[ $key ] ) ) { update_post_meta( $object_id, $field_args['id'] . 'addr_' . $key, sanitize_text_field( $value[ $key ] ) ); } } remove_filter( 'cmb2_sanitize_address', array( __CLASS__, 'sanitize' ), 10, 5 ); // Tell CMB2 we already did the update. return true; } public static function sanitize( $check, $meta_value, $object_id, $field_args, $sanitize_object ) { // if not repeatable, bail out. if ( ! is_array( $meta_value ) || ! $field_args['repeatable'] ) { return $check; } foreach ( $meta_value as $key => $val ) { $meta_value[ $key ] = array_filter( array_map( 'sanitize_text_field', $val ) ); } return array_filter( $meta_value ); } public static function escape( $check, $meta_value, $field_args, $field_object ) { // if not repeatable, bail out. if ( ! is_array( $meta_value ) || ! $field_args['repeatable'] ) { return $check; } foreach ( $meta_value as $key => $val ) { $meta_value[ $key ] = array_filter( array_map( 'esc_attr', $val ) ); } return array_filter( $meta_value ); } public static function get_split_meta_value( $data, $object_id, $field_args, $field ) { if ( 'address' !== $field->args['type'] ) { return $data; } if ( ! isset( $field->args['split_values'] ) || ! $field->args['split_values'] ) { // Don't do the override. return $data; } $prefix = $field->args['id'] . 'addr_'; // Construct an array to iterate to fetch individual meta values for our override. // Should match the values in the render() method. $metakeys = array( 'address-1', 'address-2', 'city', 'state', 'zip', 'country', ); $newdata = array(); foreach ( $metakeys as $metakey ) { // Use our prefix to construct the whole meta key from the postmeta table. $newdata[ $metakey ] = get_post_meta( $object_id, $prefix . $metakey, true ); } return $newdata; } } ================================================ FILE: custom-field-types/associate-wp-menu-field.php ================================================ menu_types = array( 'post', 'page' ); $menu_assoc->metabox_id = 'associated_post_menu_box'; $menu_assoc->menu_meta_key = 'associated_post_menu'; if ( is_admin() ) { // Register menu association metabox to post types $cmb = $menu_assoc->register_post_menu_box(); } } add_action( 'cmb2_init', 'cmb2_register_post_menu_box' ); class CMB2_Post_Menu_Association { public $menu_types = array(); public $metabox_id = ''; public $menu_meta_key = ''; public $menu_title_meta_key = ''; protected static $single_instance = null; protected $associated_post = null; protected $menu_id = 0; /** * Creates or returns an instance of this class. * @since 0.1.0 * @return CMB2_Post_Menu_Association A single instance of this class. */ public static function get_instance() { if ( null === self::$single_instance ) { self::$single_instance = new self(); } return self::$single_instance; } protected function __construct() { add_action( 'all_admin_notices', array( $this, 'associate_menu_post_message' ) ); add_action( 'wp_create_nav_menu', array( $this, 'set_menu_to_post' ) ); } public function register_post_menu_box() { return new_cmb2_box( $this->register_post_menu_box_args() ); } public function register_post_menu_box_args() { $title_key = $this->menu_title_meta_key(); return apply_filters( 'register_post_menu_box_args', array( 'id' => $this->metabox_id, 'title' => 'Associated Menu', 'object_types' => $this->menu_types, // Post type 'context' => 'side', 'priority' => 'low', 'fields' => array( $title_key => array( 'name' => 'Menu Widget Title', 'id' => $title_key, 'type' => 'text', ), $this->menu_meta_key => array( 'desc' => 'If no menu is selected, associated menu widget will not show.', 'id' => $this->menu_meta_key, 'type' => 'select', 'options_cb' => array( $this, 'get_menus_list_options' ), 'after' => array( $this, 'post_menu_edit_or_create_link' ), ), ), ) ); } public function get_menus_list_options() { $menus = wp_get_nav_menus(); if ( ! empty( $menus ) ) { $menus = wp_list_pluck( $menus, 'name', 'term_id' ); } else { $menus = array(); } $menus = array( '' => 'Select Menu' ) + $menus; return $menus; } function post_menu_edit_or_create_link( $args, $field ) { static $script_added = false; $menu_id = get_post_meta( $field->object_id(), $this->menu_meta_key, 1 ); $url = admin_url( '/nav-menus.php?action=edit&menu=' . absint( $menu_id ) . '&post_association=' . $field->object_id() ); $link_title = $menu_id ? 'Edit Selected Menu' : 'Create New Menu'; ?>

Note: In order for this menu to display, you will need to ensure the "Associated Post Menu" widget is placed in the widget area for this template.

menu_meta_key ) { return; } if ( empty( $_REQUEST['menu'] ) ) { $this->associate_menu_message( $_REQUEST['post_association'], 'When created, this Menu will be set as the %s Menu for: %s (%d)' ); } else { $this->associate_menu_message( $_REQUEST['post_association'], 'This Menu is set as the %s Menu for: %s (%d)' ); } } public function associate_menu_message( $post_id, $message ) { global $pagenow; if ( empty( $post_id ) || 'nav-menus.php' !== $pagenow ) { return; } $post = get_post( absint( $post_id ) ); if ( empty( $post ) ) { return; } $pt = get_post_type_object( $post->post_type ); printf( '

%s

', sprintf( $message, $pt->labels->singular_name, get_edit_post_link( $post->ID ) .'#'. $this->metabox_id, get_the_title( $post->ID ), $post->ID ) ); } public function set_menu_to_post( $menu_id ) { if ( empty( $_REQUEST['post_association'] ) || empty( $menu_id ) || ! $this->menu_meta_key ) { return; } $post = get_post( absint( $_REQUEST['post_association'] ) ); if ( empty( $post ) || ! in_array( $post->post_type, $this->menu_types, true ) ) { return; } $this->menu_id = $menu_id; $this->associated_post = $post; update_post_meta( $post->ID, $this->menu_meta_key, $menu_id ); // Modify the post-menu-save redirect to add our query var. add_filter( 'wp_redirect', array( $this, 'redirect_with_post_association' ) ); } public function redirect_with_post_association( $location ) { if ( $this->menu_id && $location === admin_url( 'nav-menus.php?menu='. $this->menu_id ) ) { // Add our associated post id query var. $location = add_query_arg( 'post_association', $this->associated_post->ID, $location ); } return $location; } public function menu_title_meta_key() { return $this->menu_title_meta_key ? $this->menu_title_meta_key : $this->menu_meta_key . '_widget_title'; } } CMB2_Post_Menu_Association::get_instance(); /** * Handles the Post Menu Widget * * @since 3.0.0 * * @see WP_Widget */ class CMB2_Post_Menu_Widget extends WP_Widget { /** * Sets up a new Associated Post Menu widget instance. * * @since 3.0.0 * @access public */ public function __construct() { $widget_ops = array( 'customize_selective_refresh' => true, 'description' => 'Shows an associated custom menu in your sidebar, if it is set.', 'classname' => 'associated-post-menu', ); parent::__construct( 'associated-post-menu', 'Associated Post Menu', $widget_ops ); } /** * Outputs the content for the associated Menu widget instance. * * @since 3.0.0 * @access public * * @param array $args Display arguments including 'before_title', 'after_title', * 'before_widget', and 'after_widget'. * @param array $instance Settings for the current Associated Post Menu widget instance. */ public function widget( $args, $instance ) { // Get menu $menu_id = absint( get_post_meta( get_the_ID(), CMB2_Post_Menu_Association::get_instance()->menu_meta_key, 1 ) ); $nav_menu = ! empty( $menu_id ) ? wp_get_nav_menu_object( $menu_id ) : false; if ( ! $nav_menu ) { return; } $widget_title = get_post_meta( get_the_ID(), CMB2_Post_Menu_Association::get_instance()->menu_title_meta_key(), 1 ); if ( empty( $widget_title ) ) { $widget_title = isset( $instance['title'] ) ? $instance['title'] : ''; } /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */ $widget_title = apply_filters( 'widget_title', empty( $widget_title ) ? '' : $widget_title, $instance, $this->id_base ); echo $args['before_widget']; if ( ! empty( $widget_title ) ) { echo $args['before_title'] . $widget_title . $args['after_title']; } $nav_menu_args = array( 'fallback_cb' => '', 'menu' => $nav_menu, ); /** * Filters the arguments for the Associated Post Menu widget. * * @since 4.2.0 * @since 4.4.0 Added the `$instance` parameter. * * @param array $nav_menu_args { * An array of arguments passed to wp_nav_menu() to retrieve a custom menu. * * @type callable|bool $fallback_cb Callback to fire if the menu doesn't exist. Default empty. * @type mixed $menu Menu ID, slug, or name. * } * @param WP_Term $nav_menu Nav menu object for the current menu. * @param array $args Display arguments for the current widget. * @param array $instance Array of settings for the current widget. */ wp_nav_menu( apply_filters( 'widget_nav_menu_args', $nav_menu_args, $nav_menu, $args, $instance ) ); echo $args['after_widget']; } /** * Handles updating settings for the current Associated Post Menu widget instance. * * @since 3.0.0 * @access public * * @param array $new_instance New settings for this instance as input by the user via * WP_Widget::form(). * @param array $old_instance Old settings for this instance. * @return array Updated settings to save. */ public function update( $new_instance, $old_instance ) { $instance = array(); if ( ! empty( $new_instance['title'] ) ) { $instance['title'] = sanitize_text_field( $new_instance['title'] ); } return $instance; } /** * Outputs the settings form for the Associated Post Menu widget. * * @since 3.0.0 * @access public * * @param array $instance Current settings. */ public function form( $instance ) { $title = isset( $instance['title'] ) ? $instance['title'] : ''; // If no menus exists, direct the user to go and create some. ?> 'autocomplete_test', 'title' => __('Autocomplete Field Examples', 'autocomplete_cmb2'), 'object_types' => array('post'), ) ); $cmb->add_field( array( 'name' => __('Related Fruit', 'autocomplete_cmb2'), 'desc' => __('Fruit that is related to this post', 'autocomplete_cmb2'), 'id' => $prefix.'related_fruit', 'type' => 'autocomplete', 'options' => array( array('value' => 1, 'name' => 'Apple'), array('value' => 2, 'name' => 'Orange'), array('value' => 3, 'name' => 'Grape') ) ) ); $cmb->add_field( array( 'name' => __('Related Fruits', 'autocomplete_cmb2'), 'desc' => __('Repeatable related fruits', 'autocomplete_cmb2'), 'id' => $prefix.'related_fruits', 'type' => 'autocomplete', 'repeatable' => true, 'repeatable_class' => 'related-fruits', 'options' => array( array('value' => 1, 'name' => 'Apple'), array('value' => 2, 'name' => 'Orange'), array('value' => 3, 'name' => 'Grape') ) ) ); $cmb->add_field( array( 'name' => __('Related Post', 'autocomplete_cmb2'), 'desc' => __('Post that is related to this one', 'autocomplete_cmb2'), 'id' => $prefix.'related_post', 'type' => 'autocomplete', 'source' => 'get_post_options', 'mapping_function' => 'autocomplete_cmb2_get_post_title_from_id' ) ); $cmb->add_field( array( 'name' => __('Related Posts', 'autocomplete_cmb2'), 'desc' => __('Posts that are related to this one', 'autocomplete_cmb2'), 'id' => $prefix.'related_posts', 'repeatable' => true, 'type' => 'autocomplete', 'source' => 'get_post_options', 'repeatable_class' => 'related-posts', 'mapping_function' => 'autocomplete_cmb2_get_post_title_from_id' ) ); } /** * Gets the post title from the ID for mapping purposes in autocompletes. * * @param int $id * @return string */ function autocomplete_cmb2_get_post_title_from_id($id) { if (empty($id)) { return ''; } $post = get_post($id); return $post->post_title; } /** * Renders the autocomplete type * * @param CMB2_Field $field_object * @param string $escaped_value The value of this field passed through the escaping filter. It defaults to sanitize_text_field. * If you need the unescaped value, you can access it via $field_type_object->value(). * @param string $object_id The id of the object you are working with. Most commonly, the post id. * @param string $object_type The type of object you are working with. Most commonly, post (this applies to all post-types), * but could also be comment, user or options-page. * @param CMB2_Object $field_type_object This is an instance of the CMB2 object and gives you access to all of the methods that CMB2 uses to build its field types. */ function autocomplete_cmb2_render_autocomplete($field_object, $escaped_value, $object_id, $object_type, $field_type_object) { // Store the value in a hidden field. echo $field_type_object->hidden(); if (isset($field_object->args['repeatable_class'])) { $repeatable_class = $field_object->args['repeatable_class']; } $options = $field_object->options(); // Set up the options or source PHP variables. if (empty($options)) { $source = $field_object->args['source']; $value = $field_object->args['mapping_function']($field_object->escaped_value); } else { // Set the value. if (empty($field_object->escaped_value)) { $value = ''; } else { foreach ($options as $option) { if ($option['value'] == $field_object->escaped_value) { $value = $option['name']; break; } } } } // Set up the autocomplete field. Replace the '_' with '-' to not interfere with the ID from CMB2. $id = str_replace('_', '-', $field_object->args['id']); if ( '_' !== substr( $field_object->args['id'], 0, 1 ) ) { $id = '-' . $field_object->args['id']; } // Don't use the ID on repeatable elements as it won't change; use the class instead. echo ''; if (!$field_object->args['repeatable'] && isset($field_object->args['desc'])) { echo '

'.$field_object->args['desc'].'

'; } // Now, set up the script. ?> get_results($wpdb->prepare(" SELECT ID, post_title FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN $post_type_query AND post_title LIKE %s ORDER BY post_title ASC ", $like_test), OBJECT); if ($include_empty) { $post_options = array(array('name' => '--- Select ---', 'value' => '')); } else { $post_options = array(); } foreach ($posts as $post) { $post_options[] = array( 'name' => $post->post_title, 'value' => $post->ID ); } return $post_options; } /** * Gets the jQuery autocomplete widget ready. */ function autocomplete_cmb2_admin_enqueue_scripts() { wp_enqueue_script('jquery-ui-autocomplete'); } /** * Gets the post options in JSON format for the autocomplete */ function autocomplete_cmb2_get_post_autocomplete_options() { die(json_encode(autocomplete_cmb2_get_post_options_using_post_type('post', false, '%'.$_GET['q'].'%'))); } add_action('cmb2_render_autocomplete', 'autocomplete_cmb2_render_autocomplete', 10, 5); add_action('admin_enqueue_scripts', 'autocomplete_cmb2_admin_enqueue_scripts'); add_action('wp_ajax_get_post_options', 'autocomplete_cmb2_get_post_autocomplete_options'); add_filter('cmb2_admin_init', 'autocomplete_cmb2_meta_boxes'); ================================================ FILE: custom-field-types/button-field-type.php ================================================ 'demo_metabox', * 'title' => __( 'Test Metabox', 'yourprefix' ), * 'object_types' => array( 'page', ), * ) ); * * $cmb_demo->add_field( array( * 'type' => 'button', * 'name' => __( 'Button', 'yourprefix' ), * 'desc' => __( 'Button description (optional)', 'yourprefix' ), * 'id' => '_yourprefix_demo_button', * 'attributes' => array( * 'value' => 'Click Me', * 'onclick' => 'alert(\'You clicked the button!\');', * ), * ) ); * } * add_action( 'cmb2_init', 'yourprefix_register_demo_metabox' ); */ // render button add_action( 'cmb2_render_button', 'jt_cmb2__cmb_render_button', 10, 5 ); function jt_cmb2__cmb_render_button( $field, $escaped_value, $object_id, $object_type, $field_type_object ) { echo $field_type_object->input( array( 'class' => 'button', 'type' => 'button', ) ); } ================================================ FILE: custom-field-types/dashicon-radio-field/dashicon-radio-field.php ================================================ args['options'] = ml_cmb2_dashicons_return_array(); echo $field_type_object->radio(); remove_filter( 'cmb2_list_input_attributes', 'ml_cmb2_dashicon_radio_attributes', 10, 4 ); ml_cmb2_dashicon_radio_css(); } add_action( 'cmb2_render_dashicon_radio', 'ml_cmb2_render_dashicon_radio_callback', 10, 5 ); /** * Custom labels for dashicon_radio inputs * * @param array $args * @param array $defaults * @param object $field * @param object $cmb * @return array */ function ml_cmb2_dashicon_radio_attributes( $args, $defaults, $field, $cmb ) { if ( $args['value'] ) { $args['label'] = ' ' . $args['label']; } return $args; } /** * Custom CMB2 css for dashicon_radio field * * @return void */ function ml_cmb2_dashicon_radio_css() { static $added = false; if ( $added ) { return; } $added = true; ?> __( 'Menu', 'cmb2' ), 'dashicons-dashboard' => __( 'Dashboard', 'cmb2' ), 'dashicons-admin-site' => __( 'Admin Site', 'cmb2' ), 'dashicons-admin-media' => __( 'Admin Media', 'cmb2' ), 'dashicons-admin-page' => __( 'Admin Page', 'cmb2' ), 'dashicons-admin-comments' => __( 'Admin Comments', 'cmb2' ), 'dashicons-admin-appearance' => __( 'Admin Appearance', 'cmb2' ), 'dashicons-admin-plugins' => __( 'Admin Plugins', 'cmb2' ), 'dashicons-admin-users' => __( 'Admin Users', 'cmb2' ), 'dashicons-admin-tools' => __( 'Admin Tools', 'cmb2' ), 'dashicons-admin-settings' => __( 'Admin Settings', 'cmb2' ), 'dashicons-admin-network' => __( 'Admin Network', 'cmb2' ), 'dashicons-admin-generic' => __( 'Admin Generic', 'cmb2' ), 'dashicons-admin-home' => __( 'Admin Home', 'cmb2' ), 'dashicons-admin-collapse' => __( 'Admin Collapse', 'cmb2' ), 'dashicons-admin-links' => __( 'Admin Links', 'cmb2' ), 'dashicons-admin-post' => __( 'Admin Post', 'cmb2' ), 'dashicons-format-standard' => __( 'Admin Plugins', 'cmb2' ), 'dashicons-format-image' => __( 'Image Post Format', 'cmb2' ), 'dashicons-format-gallery' => __( 'Gallery Post Format', 'cmb2' ), 'dashicons-format-audio' => __( 'Audio Post Format', 'cmb2' ), 'dashicons-format-video' => __( 'Video Post Format', 'cmb2' ), 'dashicons-format-links' => __( 'Link Post Format', 'cmb2' ), 'dashicons-format-chat' => __( 'Chat Post Format', 'cmb2' ), 'dashicons-format-status' => __( 'Status Post Format', 'cmb2' ), 'dashicons-format-aside' => __( 'Aside Post Format', 'cmb2' ), 'dashicons-format-quote' => __( 'Quote Post Format', 'cmb2' ), 'dashicons-welcome-write-blog' => __( 'Welcome Write Blog', 'cmb2' ), 'dashicons-welcome-edit-page' => __( 'Welcome Edit Page', 'cmb2' ), 'dashicons-welcome-add-page' => __( 'Welcome Add Page', 'cmb2' ), 'dashicons-welcome-view-site' => __( 'Welcome View Site', 'cmb2' ), 'dashicons-welcome-widgets-menus' => __( 'Welcome Widget Menus', 'cmb2' ), 'dashicons-welcome-comments' => __( 'Welcome Comments', 'cmb2' ), 'dashicons-welcome-learn-more' => __( 'Welcome Learn More', 'cmb2' ), 'dashicons-image-crop' => __( 'Image Crop', 'cmb2' ), 'dashicons-image-rotate-left' => __( 'Image Rotate Left', 'cmb2' ), 'dashicons-image-rotate-right' => __( 'Image Rotate Right', 'cmb2' ), 'dashicons-image-flip-vertical' => __( 'Image Flip Vertical', 'cmb2' ), 'dashicons-image-flip-horizontal' => __( 'Image Flip Horizontal', 'cmb2' ), 'dashicons-undo' => __( 'Undo', 'cmb2' ), 'dashicons-redo' => __( 'Redo', 'cmb2' ), 'dashicons-editor-bold' => __( 'Editor Bold', 'cmb2' ), 'dashicons-editor-italic' => __( 'Editor Italic', 'cmb2' ), 'dashicons-editor-ul' => __( 'Editor UL', 'cmb2' ), 'dashicons-editor-ol' => __( 'Editor OL', 'cmb2' ), 'dashicons-editor-quote' => __( 'Editor Quote', 'cmb2' ), 'dashicons-editor-alignleft' => __( 'Editor Align Left', 'cmb2' ), 'dashicons-editor-aligncenter' => __( 'Editor Align Center', 'cmb2' ), 'dashicons-editor-alignright' => __( 'Editor Align Right', 'cmb2' ), 'dashicons-editor-insertmore' => __( 'Editor Insert More', 'cmb2' ), 'dashicons-editor-spellcheck' => __( 'Editor Spell Check', 'cmb2' ), 'dashicons-editor-distractionfree' => __( 'Editor Distraction Free', 'cmb2' ), 'dashicons-editor-expand' => __( 'Editor Expand', 'cmb2' ), 'dashicons-editor-contract' => __( 'Editor Contract', 'cmb2' ), 'dashicons-editor-kitchensink' => __( 'Editor Kitchen Sink', 'cmb2' ), 'dashicons-editor-underline' => __( 'Editor Underline', 'cmb2' ), 'dashicons-editor-justify' => __( 'Editor Justify', 'cmb2' ), 'dashicons-editor-textcolor' => __( 'Editor Text Colour', 'cmb2' ), 'dashicons-editor-paste-word' => __( 'Editor Paste Word', 'cmb2' ), 'dashicons-editor-paste-text' => __( 'Editor Paste Text', 'cmb2' ), 'dashicons-editor-removeformatting' => __( 'Editor Remove Formatting', 'cmb2' ), 'dashicons-editor-video' => __( 'Editor Video', 'cmb2' ), 'dashicons-editor-customchar' => __( 'Editor Custom Character', 'cmb2' ), 'dashicons-editor-outdent' => __( 'Editor Outdent', 'cmb2' ), 'dashicons-editor-indent' => __( 'Editor Indent', 'cmb2' ), 'dashicons-editor-help' => __( 'Editor Help', 'cmb2' ), 'dashicons-editor-strikethrough' => __( 'Editor Strikethrough', 'cmb2' ), 'dashicons-editor-unlink' => __( 'Editor Unlink', 'cmb2' ), 'dashicons-editor-rtl' => __( 'Editor RTL', 'cmb2' ), 'dashicons-editor-break' => __( 'Editor Break', 'cmb2' ), 'dashicons-editor-code' => __( 'Editor Code', 'cmb2' ), 'dashicons-editor-paragraph' => __( 'Editor Paragraph', 'cmb2' ), 'dashicons-align-left' => __( 'Align Left', 'cmb2' ), 'dashicons-align-right' => __( 'Align Right', 'cmb2' ), 'dashicons-align-center' => __( 'Align Center', 'cmb2' ), 'dashicons-align-none' => __( 'Align None', 'cmb2' ), 'dashicons-lock' => __( 'Lock', 'cmb2' ), 'dashicons-calendar' => __( 'Calendar', 'cmb2' ), 'dashicons-visibility' => __( 'Visibility', 'cmb2' ), 'dashicons-post-status' => __( 'Post Status', 'cmb2' ), 'dashicons-edit' => __( 'Edit', 'cmb2' ), 'dashicons-post-trash' => __( 'Post Trash', 'cmb2' ), 'dashicons-trash' => __( 'Trash', 'cmb2' ), 'dashicons-external' => __( 'External', 'cmb2' ), 'dashicons-arrow-up' => __( 'Arrow Up', 'cmb2' ), 'dashicons-arrow-down' => __( 'Arrow Down', 'cmb2' ), 'dashicons-arrow-left' => __( 'Arrow Left', 'cmb2' ), 'dashicons-arrow-right' => __( 'Arrow Right', 'cmb2' ), 'dashicons-arrow-up-alt' => __( 'Arrow Up (alt)', 'cmb2' ), 'dashicons-arrow-down-alt' => __( 'Arrow Down (alt)', 'cmb2' ), 'dashicons-arrow-left-alt' => __( 'Arrow Left (alt)', 'cmb2' ), 'dashicons-arrow-right-alt' => __( 'Arrow Right (alt)', 'cmb2' ), 'dashicons-arrow-up-alt2' => __( 'Arrow Up (alt 2)', 'cmb2' ), 'dashicons-arrow-down-alt2' => __( 'Arrow Down (alt 2)', 'cmb2' ), 'dashicons-arrow-left-alt2' => __( 'Arrow Left (alt 2)', 'cmb2' ), 'dashicons-arrow-right-alt2' => __( 'Arrow Right (alt 2)', 'cmb2' ), 'dashicons-leftright' => __( 'Arrow Left-Right', 'cmb2' ), 'dashicons-sort' => __( 'Sort', 'cmb2' ), 'dashicons-randomize' => __( 'Randomise', 'cmb2' ), 'dashicons-list-view' => __( 'List View', 'cmb2' ), 'dashicons-exerpt-view' => __( 'Excerpt View', 'cmb2' ), 'dashicons-hammer' => __( 'Hammer', 'cmb2' ), 'dashicons-art' => __( 'Art', 'cmb2' ), 'dashicons-migrate' => __( 'Migrate', 'cmb2' ), 'dashicons-performance' => __( 'Performance', 'cmb2' ), 'dashicons-universal-access' => __( 'Universal Access', 'cmb2' ), 'dashicons-universal-access-alt' => __( 'Universal Access (alt)', 'cmb2' ), 'dashicons-tickets' => __( 'Tickets', 'cmb2' ), 'dashicons-nametag' => __( 'Name Tag', 'cmb2' ), 'dashicons-clipboard' => __( 'Clipboard', 'cmb2' ), 'dashicons-heart' => __( 'Heart', 'cmb2' ), 'dashicons-megaphone' => __( 'Megaphone', 'cmb2' ), 'dashicons-schedule' => __( 'Schedule', 'cmb2' ), 'dashicons-wordpress' => __( 'WordPress', 'cmb2' ), 'dashicons-wordpress-alt' => __( 'WordPress (alt)', 'cmb2' ), 'dashicons-pressthis' => __( 'Press This', 'cmb2' ), 'dashicons-update' => __( 'Update', 'cmb2' ), 'dashicons-screenoptions' => __( 'Screen Options', 'cmb2' ), 'dashicons-info' => __( 'Info', 'cmb2' ), 'dashicons-cart' => __( 'Cart', 'cmb2' ), 'dashicons-feedback' => __( 'Feedback', 'cmb2' ), 'dashicons-cloud' => __( 'Cloud', 'cmb2' ), 'dashicons-translation' => __( 'Translation', 'cmb2' ), 'dashicons-tag' => __( 'Tag', 'cmb2' ), 'dashicons-category' => __( 'Category', 'cmb2' ), 'dashicons-archive' => __( 'Archive', 'cmb2' ), 'dashicons-tagcloud' => __( 'Tag Cloud', 'cmb2' ), 'dashicons-text' => __( 'Text', 'cmb2' ), 'dashicons-media-archive' => __( 'Media Archive', 'cmb2' ), 'dashicons-media-audio' => __( 'Media Audio', 'cmb2' ), 'dashicons-media-code' => __( 'Media Code)', 'cmb2' ), 'dashicons-media-default' => __( 'Media Default', 'cmb2' ), 'dashicons-media-document' => __( 'Media Document', 'cmb2' ), 'dashicons-media-interactive' => __( 'Media Interactive', 'cmb2' ), 'dashicons-media-spreadsheet' => __( 'Media Spreadsheet', 'cmb2' ), 'dashicons-media-text' => __( 'Media Text', 'cmb2' ), 'dashicons-media-video' => __( 'Media Video', 'cmb2' ), 'dashicons-playlist-audio' => __( 'Audio Playlist', 'cmb2' ), 'dashicons-playlist-video' => __( 'Video Playlist', 'cmb2' ), 'dashicons-yes' => __( 'Yes', 'cmb2' ), 'dashicons-no' => __( 'No', 'cmb2' ), 'dashicons-no-alt' => __( 'No (alt)', 'cmb2' ), 'dashicons-plus' => __( 'Plus', 'cmb2' ), 'dashicons-plus-alt' => __( 'Plus (alt)', 'cmb2' ), 'dashicons-minus' => __( 'Minus', 'cmb2' ), 'dashicons-dismiss' => __( 'Dismiss', 'cmb2' ), 'dashicons-marker' => __( 'Marker', 'cmb2' ), 'dashicons-star-filled' => __( 'Star Filled', 'cmb2' ), 'dashicons-star-half' => __( 'Star Half', 'cmb2' ), 'dashicons-star-empty' => __( 'Star Empty', 'cmb2' ), 'dashicons-flag' => __( 'Flag', 'cmb2' ), 'dashicons-share' => __( 'Share', 'cmb2' ), 'dashicons-share1' => __( 'Share 1', 'cmb2' ), 'dashicons-share-alt' => __( 'Share (alt)', 'cmb2' ), 'dashicons-share-alt2' => __( 'Share (alt 2)', 'cmb2' ), 'dashicons-twitter' => __( 'twitter', 'cmb2' ), 'dashicons-rss' => __( 'RSS', 'cmb2' ), 'dashicons-email' => __( 'Email', 'cmb2' ), 'dashicons-email-alt' => __( 'Email (alt)', 'cmb2' ), 'dashicons-facebook' => __( 'Facebook', 'cmb2' ), 'dashicons-facebook-alt' => __( 'Facebook (alt)', 'cmb2' ), 'dashicons-networking' => __( 'Networking', 'cmb2' ), 'dashicons-googleplus' => __( 'Google+', 'cmb2' ), 'dashicons-location' => __( 'Location', 'cmb2' ), 'dashicons-location-alt' => __( 'Location (alt)', 'cmb2' ), 'dashicons-camera' => __( 'Camera', 'cmb2' ), 'dashicons-images-alt' => __( 'Images', 'cmb2' ), 'dashicons-images-alt2' => __( 'Images Alt', 'cmb2' ), 'dashicons-video-alt' => __( 'Video (alt)', 'cmb2' ), 'dashicons-video-alt2' => __( 'Video (alt 2)', 'cmb2' ), 'dashicons-video-alt3' => __( 'Video (alt 3)', 'cmb2' ), 'dashicons-vault' => __( 'Vault', 'cmb2' ), 'dashicons-shield' => __( 'Shield', 'cmb2' ), 'dashicons-shield-alt' => __( 'Shield (alt)', 'cmb2' ), 'dashicons-sos' => __( 'SOS', 'cmb2' ), 'dashicons-search' => __( 'Search', 'cmb2' ), 'dashicons-slides' => __( 'Slides', 'cmb2' ), 'dashicons-analytics' => __( 'Analytics', 'cmb2' ), 'dashicons-chart-pie' => __( 'Pie Chart', 'cmb2' ), 'dashicons-chart-bar' => __( 'Bar Chart', 'cmb2' ), 'dashicons-chart-line' => __( 'Line Chart', 'cmb2' ), 'dashicons-chart-area' => __( 'Area Chart', 'cmb2' ), 'dashicons-groups' => __( 'Groups', 'cmb2' ), 'dashicons-businessman' => __( 'Businessman', 'cmb2' ), 'dashicons-id' => __( 'ID', 'cmb2' ), 'dashicons-id-alt' => __( 'ID (alt)', 'cmb2' ), 'dashicons-products' => __( 'Products', 'cmb2' ), 'dashicons-awards' => __( 'Awards', 'cmb2' ), 'dashicons-forms' => __( 'Forms', 'cmb2' ), 'dashicons-testimonial' => __( 'Testimonial', 'cmb2' ), 'dashicons-portfolio' => __( 'Portfolio', 'cmb2' ), 'dashicons-book' => __( 'Book', 'cmb2' ), 'dashicons-book-alt' => __( 'Book (alt)', 'cmb2' ), 'dashicons-download' => __( 'Download', 'cmb2' ), 'dashicons-upload' => __( 'Upload', 'cmb2' ), 'dashicons-backup' => __( 'Backup', 'cmb2' ), 'dashicons-clock' => __( 'Clock', 'cmb2' ), 'dashicons-lightbulb' => __( 'Lightbulb', 'cmb2' ), 'dashicons-microphone' => __( 'Microphone', 'cmb2' ), 'dashicons-desktop' => __( 'Desktop', 'cmb2' ), 'dashicons-tablet' => __( 'Tablet', 'cmb2' ), 'dashicons-smartphone' => __( 'Smartphone', 'cmb2' ), 'dashicons-smiley' => __( 'Smiley', 'cmb2' ), ); return $icons; } ================================================ FILE: custom-field-types/default-category-field.php ================================================ args( 'taxonomy' ); $taxonomy = $taxonomy ? $taxonomy : 'category'; if ( 'post' !== $object_type ) { wp_die( 'This won\'t work for non-"post" object types!' ); } remove_meta_box( "{$object_type}div", 'post', 'side' ); post_categories_meta_box( get_post( $object_id ), array( 'args' => array( 'taxonomy' => $taxonomy, ), ) ); } add_action( 'cmb2_render_default_categories', 'cmb2_render_default_categories_field_type', 10, 4 ); function cmb2_default_categories_let_wp_save( $null, $a, $field_args, $field ) { if ( 'default_categories' === $field->args( 'type' ) ) { // Let WP handle it. return false; } return $null; } add_filter( 'cmb2_override_meta_save', 'cmb2_default_categories_let_wp_save', 10, 4 ); function cmb2_remove_default_category_metabox_for_taxonomy() { foreach ( CMB2_Boxes::get_all() as $cmb ) { foreach ( $cmb->prop( 'fields' ) as $field ) { if ( 'default_categories' === $field['type'] ) { $taxonomy = isset( $field['taxonomy'] ) ? $field['taxonomy'] : 'category'; remove_meta_box( "{$taxonomy}div", 'post', 'side' ); } } } } add_action( 'admin_init', 'cmb2_remove_default_category_metabox_for_taxonomy' ); ================================================ FILE: custom-field-types/default-tags-field.php ================================================ args( 'taxonomy' ); $taxonomy = $taxonomy ? $taxonomy : 'post_tag'; if ( 'post' !== $object_type ) { wp_die( 'This won\'t work for non-"post" object types!' ); } wp_enqueue_script( 'tags-box' ); add_action( 'admin_footer', 'cmb2_init_post_tag_box' ); post_tags_meta_box( get_post( $object_id ), array( 'args' => array( 'taxonomy' => $taxonomy, ), ) ); } add_action( 'cmb2_render_default_tags', 'cmb2_render_default_tags_field_type', 10, 4 ); function cmb2_init_post_tag_box() { ?> args( 'type' ) ) { // Let WP handle it. return false; } return $null; } add_filter( 'cmb2_override_meta_save', 'cmb2_default_tags_let_wp_save', 10, 4 ); function cmb2_remove_default_tag_metabox_for_taxonomy() { foreach ( CMB2_Boxes::get_all() as $cmb ) { foreach ( $cmb->prop( 'fields' ) as $field ) { if ( 'default_tags' === $field['type'] ) { $taxonomy = isset( $field['taxonomy'] ) ? $field['taxonomy'] : 'post_tag'; remove_meta_box( "tagsdiv-{$taxonomy}", 'post', 'side' ); } } } } add_action( 'admin_init', 'cmb2_remove_default_tag_metabox_for_taxonomy' ); ================================================ FILE: custom-field-types/form-field-field-type.php ================================================ add_field( array( * 'name' => 'Campos', * 'desc' => 'Adiciona campos ao formulário', * 'id' => '_form_fields', * 'type' => 'formfield', * 'repeatable' => true, * 'text' => array( * 'add_row_text' => 'Adicionar Campo', * 'formfield_field_id_label' => 'ID do Campo', * 'formfield_field_label_label' => 'Título do campo', * 'formfield_field_type_label' => 'Tipo do campo', * 'formfield_field_size_label' => 'Tamanho do campo', * 'formfield_text_field_option_label' => 'Texto', * 'formfield_email_field_option_label' => 'Email', * 'formfield_money_field_option_label' => 'Dinheiro', * 'formfield_date_field_option_label' => 'Data', * ), * ) ); * */ /** * Render 'formfield' custom field type * * @since 0.1.0 * * @param array $field The passed in `CMB2_Field` object * @param mixed $value The value of this field escaped. * It defaults to `sanitize_text_field`. * If you need the unescaped value, you can access it * via `$field->value()` * @param int $object_id The ID of the current object * @param string $object_type The type of object you are working with. * Most commonly, `post` (this applies to all post-types), * but could also be `comment`, `user` or `options-page`. * @param object $field_type The `CMB2_Types` object */ function jt_cmb2_render_formfield_field_callback( $field, $value, $object_id, $object_type, $field_type ) { // make sure we specify each part of the value we need. $value = wp_parse_args( $value, array( 'id' => '', 'label' => '', 'type' => 'text', 'size' => '', ) ); $type_options = array( 'text' => $field_type->_text( 'formfield_text_field_option_label', 'Text' ), 'email' => $field_type->_text( 'formfield_email_field_option_label', 'Email' ), 'money' => $field_type->_text( 'formfield_money_field_option_label', 'Money' ), 'date' => $field_type->_text( 'formfield_date_field_option_label', 'Date' ), ); $types = ''; foreach ( $type_options as $type => $label ) { $selected = selected( $value['type'], $type, false ); $label = esc_html( $label ); $types .= ""; } ?>
input( array( 'name' => $field_type->_name( '[id]' ), 'id' => $field_type->_id( '_id' ), 'value' => $value['id'], 'desc' => '' ) ) ?>
input( array( 'name' => $field_type->_name( '[label]' ), 'id' => $field_type->_id( '_label' ), 'value' => $value['label'], 'desc' => '' ) ) ?>
select( array( 'name' => $field_type->_name( '[type]' ), 'id' => $field_type->_id( '_type' ), 'options' => $types, 'desc' => '' ) ) ?>
input( array( 'name' => $field_type->_name( '[size]' ), 'id' => $field_type->_id( '_size' ), 'value' => $value['size'], 'desc' => '' ) ) ?>
_desc() ) : ?>

_desc();?>

$val ) { $val['type'] = isset( $val['type'] ) ? $val['type'] : 'text'; if ( 'text' === $val['type'] ) { unset( $val['type'] ); $val = array_filter( $val ); if ( empty( $val ) ) { unset( $meta_value[ $key ] ); continue; } else { $val['type'] = 'text'; } } $meta_value[ $key ] = array_map( 'sanitize_text_field', $val ); } return $meta_value; } add_filter( 'cmb2_sanitize_formfield', 'jt_cmb2_sanitize_formfield_field', 10, 4 ); function jt_cmb2_types_esc_formfield_field( $check, $meta_value, $field_args ) { // Nothing needed if not array value or not a repeatable field. if ( ! is_array( $meta_value ) || empty( $field_args['repeatable'] ) ) { return $check; } foreach ( $meta_value as $key => $val ) { $meta_value[ $key ] = array_map( 'esc_attr', $val ); } return $meta_value; } add_filter( 'cmb2_types_esc_formfield', 'jt_cmb2_types_esc_formfield_field', 10, 3 ); ================================================ FILE: custom-field-types/multicheck_posttype-field_type.php ================================================ =' ) ) { $field_type_object->type = new CMB2_Type_Radio( $field_type_object ); } $cpts = get_post_types(); // To disable the avalaibility of post types unset( $cpts[ 'nav_menu_item' ] ); unset( $cpts[ 'revision' ] ); $cpts = apply_filters( 'multicheck_posttype_' . $field->args[ '_id' ], $cpts ); $options = ''; $i = 1; $values = (array) $escaped_value; if ( $cpts ) { foreach ( $cpts as $cpt ) { $args = array( 'value' => $cpt, 'label' => $cpt, 'type' => 'checkbox', 'name' => $field->args['_name'] . '[]', ); if ( in_array( $cpt, $values ) ) { $args[ 'checked' ] = 'checked'; } $options .= $field_type_object->list_input( $args, $i ); $i++; } } $classes = false === $field->args( 'select_all_button' ) ? 'cmb2-checkbox-list no-select-all cmb2-list' : 'cmb2-checkbox-list cmb2-list'; echo $field_type_object->radio( array( 'class' => $classes, 'options' => $options ), 'multicheck_posttype' ); } ================================================ FILE: custom-field-types/multicheck_title-field_type.php ================================================ add_field( array( 'name' => __( 'Fields Extra', $this->plugin_slug ), 'id' => 'extra_fields', 'type' => 'multicheck_title', 'data' => $fields ) ); */ // render Title multicheck add_action( 'cmb2_render_multicheck_title', 'cmb_render_multicheck_title', 10, 5 ); function cmb_render_multicheck_title( $field, $escaped_value, $object_id, $object_type, $field_type_object ) { $data_field = $field->args[ 'data' ]; $values = ( array ) $escaped_value; $i = 0; if ( version_compare( CMB2_VERSION, '2.2.2', '>=' ) ) { $field_type_object->type = new CMB2_Type_Multicheck( $field_type_object ); } if ( $data_field ) { foreach ( $data_field as $title => $extra_fields ) { $options = ''; foreach ( $extra_fields as $extra_field => $value ) { $args = array( 'value' => $extra_field, 'label' => $value, 'type' => 'checkbox', 'name' => $field->args[ '_name' ] . '[]', ); if ( in_array( $extra_field, $values) ) { $args[ 'checked' ] = 'checked'; } $options .= $field_type_object->list_input( $args, $i ); $i++; } echo '

'.$title.'

'; $classes = false === $field->args( 'select_all_button' ) ? 'cmb2-checkbox-list no-select-all cmb2-list' : 'cmb2-checkbox-list cmb2-list'; echo $field_type_object->radio( array( 'class' => $classes, 'options' => $options ), 'title_multicheck' ); } } else { echo __( 'Nothing' ); } } ================================================ FILE: custom-field-types/post-list-field-type.php ================================================ args( 'select_type' ); echo $field_type->input( array( 'autocomplete' => 'off', 'style' => 'display:none' ) ); echo ''; // JS needed for modal wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'jquery-ui-sortable' ); if ( !is_admin() ) { // Will need custom styling! // @todo add styles for front-end require_once( ABSPATH . 'wp-admin/includes/template.php' ); } ?> args['_name'] . '[]" id="' . $field->args['_id'] . '"'; foreach ( $field->args['attributes'] as $attribute => $value ) { $select_multiple .= " $attribute=\"$value\""; } $select_multiple .= ' />'; foreach ( $field->options() as $value => $name ) { $selected = ( $escaped_value && in_array( $value, $escaped_value ) ) ? 'selected="selected"' : ''; $select_multiple .= ''; } $select_multiple .= ''; $select_multiple .= $field_type_object->_desc( true ); echo $select_multiple; // WPCS: XSS ok. } add_action( 'cmb2_render_select_multiple', 'cmb2_render_select_multiple_field_type', 10, 5 ); /** * Sanitize the selected value. */ function cmb2_sanitize_select_multiple_callback( $override_value, $value ) { if ( is_array( $value ) ) { foreach ( $value as $key => $saved_value ) { $value[$key] = sanitize_text_field( $saved_value ); } return $value; } return; } add_filter( 'cmb2_sanitize_select_multiple', 'cmb2_sanitize_select_multiple_callback', 10, 2 ); ================================================ FILE: custom-field-types/star-rating-field-type/css/star-rating-field-type.css ================================================ @charset "UTF-8"; #cmb2-star-rating-metabox .star-cb-group { /* remove inline-block whitespace */ font-size: 0; /* flip the order so we can use the + and ~ combinators */ unicode-bidi: bidi-override; direction: rtl; /* the hidden clearer */ } #cmb2-star-rating-metabox .star-cb-group * { font-size: 1rem; } #cmb2-star-rating-metabox .star-cb-group > input { display: none; } #cmb2-star-rating-metabox .star-cb-group > input + label { /* only enough room for the star */ display: inline-block; overflow: hidden; text-indent: 9999px; width: 1.75em; white-space: nowrap; cursor: pointer; } #cmb2-star-rating-metabox .star-cb-group > input + label:before { display: inline-block; text-indent: -9999px; content: "\f154"; font-family: 'dashicons'; color: #888; font-size: 1.75em; } #cmb2-star-rating-metabox .star-cb-group > input:checked ~ label:before, #cmb2-star-rating-metabox .star-cb-group > input + label:hover ~ label:before, #cmb2-star-rating-metabox .star-cb-group > input + label:hover:before { content: "\f155"; font-family: 'dashicons'; color: #FFC926; text-shadow: 0 0 1px #333; font-size: 1.75em; } #cmb2-star-rating-metabox .star-cb-group > .star-cb-clear + label { text-indent: -9999px; width: .5em; margin-left: -.5em; } #cmb2-star-rating-metabox .star-cb-group > .star-cb-clear + label:before { width: .5em; } #cmb2-star-rating-metabox .star-cb-group:hover > input + label:before { content: "\f154"; font-family: 'dashicons'; color: #888; text-shadow: none; font-size: 1.75em; } #cmb2-star-rating-metabox .star-cb-group:hover > input + label:hover ~ label:before, #cmb2-star-rating-metabox .star-cb-group:hover > input + label:hover:before { content: "\f155"; font-family: 'dashicons'; color: #FFC926; text-shadow: 0 0 1px #333; font-size: 1.75em; } #cmb2-star-rating-metabox fieldset { border: 0; background: transparent; border-radius: 1px; } ================================================ FILE: custom-field-types/star-rating-field-type/star-rating-field-type.php ================================================ '; $x = 1; $total = 5; while( $x <= $rating ) { $stars_container .= ''; $x++; } if( $rating < $total ) { while( $rating < $total ) { $stars_container .= ''; $rating++; } } $stars_container .= ''; wp_enqueue_style( 'dashicons' ); return $stars_container; } /** * Render 'star rating' custom field type * * @since 0.1.0 * * @param array $field The passed in `CMB2_Field` object * @param mixed $value The value of this field escaped. * It defaults to `sanitize_text_field`. * If you need the unescaped value, you can access it * via `$field->value()` * @param int $object_id The ID of the current object * @param string $object_type The type of object you are working with. * Most commonly, `post` (this applies to all post-types), * but could also be `comment`, `user` or `options-page`. * @param object $field_type_object The `CMB2_Types` object */ function eh_cmb2_render_star_rating_field_callback( $field, $value, $object_id, $object_type, $field_type_object ) { // enqueue styles wp_enqueue_style( 'star-rating-metabox-css', plugin_dir_url(__FILE__) . '/css/star-rating-field-type.css', array( 'cmb2-styles' ), 'all', false ); ?>
0 ) { ?> />
_desc( true ); } add_filter( 'cmb2_render_star_rating', 'eh_cmb2_render_star_rating_field_callback', 10, 5 ); ================================================ FILE: custom-field-types/taxonomy-radio-with-image-field-type/DJ_Taxonomy_Radio_Hierarchical_With_Image.php ================================================ term_id ) ) { return ''; } $this->parent = $parent_term->term_id; $terms = $this->get_terms(); $options = ''; if ( ! empty( $terms ) && is_array( $terms ) ) { // DJ - BEGIN $options = ''; // DJ - END } return $options; } protected function list_term_input( $term, $saved_term ) { $this->term = $term; $this->saved_term = $saved_term; return parent::list_term_input( $term, $saved_term ); } public function list_input( $args = array(), $i ) { if ( empty( $this->term ) ) { return parent::list_input( $args, $i ); } $a = $this->parse_args( 'list_input', array( 'type' => 'radio', 'class' => 'cmb2-option', 'name' => $this->_name(), 'id' => $this->_id( $i ), 'value' => $this->field->escaped_value(), 'label' => '', ), $args ); $taxonomy = $this->field->args( 'taxonomy' ); $image = ''; $is_parent = ''; $image_url = isset( $this->term->term_id ) ? get_term_meta( $this->term->term_id, 'yourprefix_category_avatar', true ) : ''; if ( ! empty( $image_url ) && $this->term->parent == 0 ) { $image = ''.$a['label'].''; } else { $image = ''; } $atts = $this->concat_attrs( $a, array( 'label' ) ); if ( isset( $this->term->term_id ) && get_term_children( $this->term->term_id, $taxonomy ) ) { $is_parent = 'class="parent"'; return sprintf( "\t" . '
  • ' . "\n", $is_parent, $atts, $a['id'], $image, $a['label'] ); } else { return sprintf( "\t" . '
  • ' . "\n", $is_parent, $atts, $a['id'], $image, $a['label'] ); } } } ================================================ FILE: custom-field-types/taxonomy-radio-with-image-field-type/DJ_Taxonomy_Radio_With_Image_Display.php ================================================ taxonomy(); return $sanitize_object->_is_empty_array( $sanitized_value ) ? '' : $sanitized_value; } function cmb2_init_taxonomy_radio_with_image_field_type() { add_filter( 'cmb2_render_class_taxonomy_radio_with_image', 'dj_taxonomy_radio_with_image_field_type_class_name' ); add_filter( 'cmb2_display_class_taxonomy_radio_with_image', 'dj_taxonomy_radio_with_image_field_type_display_class_name' ); add_filter( 'cmb2_all_or_nothing_types', 'dj_add_taxonomy_radio_with_image' ); add_filter( 'cmb2_non_repeatable_fields', 'dj_add_taxonomy_radio_with_image' ); /** * The following snippet is required for allowing the taxonomy_radio_with_image field * to save to the term fields. */ add_filter( 'cmb2_sanitize_taxonomy_radio_with_image', 'dj_taxonomy_radio_with_image_sanitize', 10, 5 ); } add_action( 'cmb2_init', 'cmb2_init_taxonomy_radio_with_image_field_type' ); ================================================ FILE: custom-field-types/textarea-with-checkbox.php ================================================ '', 'status' => '', ] ); $checked = false; if ( ! empty( $field_escaped_value['status'] ) ) { $checked = true; } ?>
    textarea( [ 'name' => $field_type_object->_name( '[text]' ), 'id' => $field_type_object->_id( '_text' ), 'value' => $field_escaped_value['text'], ] ); ?>

    checkbox( [ 'type' => 'checkbox', 'name' => $field_type_object->_name( '[status]' ), 'id' => $field_type_object->_id( '_status' ), ], $checked ); ?>
    _desc( true ); } /** * Sanitize Field. */ public static function sanitize_textarea_with_checkbox( $check, $meta_value, $object_id, $field_args, $sanitize_object ) { if ( !is_array( $meta_value ) || !( array_key_exists('repeatable', $field_args ) && $field_args['repeatable'] == TRUE ) ) { return $check; } $new_values = array(); foreach ( $meta_value as $key => $val ) { if( !empty( $meta_value[$key]['text'] ) ) { $new_values[$key] = array_filter( array_map( 'sanitize_text_field', $val ) ); } } return array_filter( array_values( $new_values ) ); } /** * Escape Field. */ public static function escape_textarea_with_checkbox( $check, $meta_value, $field_args, $field_object ) { if ( !is_array( $meta_value ) || ! $field_args['repeatable'] ) { return $check; } $new_values = array(); foreach ( $meta_value as $key => $val ) { if( !empty( $meta_value[$key]['text'] ) ) { $new_values[$key] = array_filter( array_map( 'esc_attr', $val ) ); } } return array_filter( array_values( $new_values ) ); } } $cmb2_field_textarea_with_checkbox = new CMB2_Field_Textarea_With_Checkbox(); } ================================================ FILE: custom-field-types/year-range-field-type.php ================================================ 'demo_metabox', * 'title' => __( 'Test Metabox', 'cmb2' ), * 'object_types' => array( 'page', ), * ) ); * * $cmb_demo->add_field( array( * 'name' => __( 'Date Year Range', 'cmb2' ), * 'desc' => __( 'field description (optional)', 'cmb2' ), * 'id' => 'yourprefix_demo_date_year_range', * 'type' => 'date_year_range', * // Optionally set default values. * 'options' => array( * 'earliest' => 1930, // Set the earliest year that should be shown. * // 'start_reverse_sort' => true, * // 'finish_reverse_sort' => false, * ), * 'default' => array( * 'start' => 1930, * 'finish' => 'current', * ), * // 'text' => array( * // 'start_label' => 'Start', // Optionally change start text. * // 'finish_label' => 'Finish', // Optionally change finish text. * // 'separator' => ' to ', // Optionally change separator string/text. * // ), * // 'split_values' => true, // Split values to sep. meta fields. * ) ); * * } * add_action( 'cmb2_init', 'yourprefix_register_demo_metabox' ); */ /** * Render 'date_year_range' custom field type * * @since 0.1.0 * * @param array $field The passed in `CMB2_Field` object * @param mixed $value The value of this field escaped. * It defaults to `sanitize_text_field`. * If you need the unescaped value, you can access it * via `$field->value()` * @param int $object_id The ID of the current object * @param string $object_type The type of object you are working with. * Most commonly, `post` (this applies to all post-types), * but could also be `comment`, `user` or `options-page`. * @param object $type_object The `CMB2_Types` object */ function jt_cmb2_date_year_range( $field, $value, $object_id, $object_type, $type_object ) { $earliest = $field->options( 'earliest' ); $earliest = $earliest ? absint( $earliest ) : 1900; $start_reverse_sort = $field->options( 'start_reverse_sort' ); $start_reverse_sort = $start_reverse_sort ? true : false; $finish_reverse_sort = $field->options( 'finish_reverse_sort' ); $finish_reverse_sort = $finish_reverse_sort ? true : false; $value = wp_parse_args( $value, array( 'start' => '', 'finish' => '', ) ); $desc = $field->args( 'description' ); $field->args['description'] = ''; $type_object->type = new CMB2_Type_Select( $type_object ); echo ''. $type_object->_text( 'start_label', 'Starting Year' ) . ' '; $start_options = jt_cmb2_date_year_range_options( $type_object, $earliest, $value['start'], $start_reverse_sort ); echo $type_object->select( array( 'name' => $type_object->_name( '[start]' ), 'id' => $type_object->_id( '_start' ), 'value' => $value['start'], 'class' => 'cmb2_select cmb2-year-range-start', 'options' => $start_options, 'desc' => '', ) ); echo $type_object->_text( 'separator', ' — ' ); $end_options = jt_cmb2_date_year_range_options( $type_object, $earliest, $value['finish'], $finish_reverse_sort ); echo $type_object->select( array( 'name' => $type_object->_name( '[finish]' ), 'id' => $type_object->_id( '_finish' ), 'value' => $value['finish'], 'class' => 'cmb2_select cmb2-year-range-end', 'options' => $end_options, 'desc' => '', ) ); echo ' '. $type_object->_text( 'finish_label', 'Final Year' ) . ''; $field->args['description'] = $desc; $type_object->_desc( true, true ); add_action( is_admin() ? 'admin_footer' : 'wp_footer', 'jt_cmb2_date_year_range_js' ); } add_filter( 'cmb2_render_date_year_range', 'jt_cmb2_date_year_range', 10, 5 ); function jt_cmb2_date_year_range_js() { static $done = false; if ( ! $done ) { $done = true; } ?> '', 'label' => __( 'Not Set' ), ); if ( cmb2_utils()->isempty( $value ) ) { $not_set['checked'] = 'checked'; } for ( $i = $earliest; $i <= date( 'Y' ); $i++ ) { $a = array( 'value' => $i, 'label' => $i ); if ( absint( $value ) === $i ) { $a['checked'] = 'checked'; } $options[] = $a; } $a = array( 'value' => 'current', 'label' => __( 'Current' ), ); if ( 'current' === $value ) { $a['checked'] = 'checked'; } $options[] = $a; if ( $reverse ) { $options = array_reverse( $options ); } array_unshift( $options, $not_set ); return implode( "\n", array_map( array( $type_object, 'select_option' ), $options ) ); } /** * Optionally save the values into separate fields. */ function jt_cmb2_date_year_range_split_values( $override_value, $value, $object_id, $field_args ) { if ( ! isset( $field_args['split_values'] ) || ! $field_args['split_values'] ) { // Don't do the override return $override_value; } $keys = array( 'start', 'finish' ); foreach ( $keys as $key ) { if ( ! empty( $value[ $key ] ) ) { update_post_meta( $object_id, $field_args['id'] . '_'. $key, $value[ $key ] ); } } // Tell CMB2 we already did the update return true; } add_filter( 'cmb2_sanitize_date_year_range', 'jt_cmb2_date_year_range_split_values', 12, 4 ); /** * Optionally fetch the values from separate fields as well. */ function jt_cmb2_date_year_range_get_split_values( $no_override, $object_id, $args, $field ) { if ( 'date_year_range' !== $field->args( 'type' ) || ! $field->args( 'split_values' ) ) { return $no_override; } $value = array( 'start' => get_post_meta( $object_id, $args['field_id'] . '_start', 1 ), 'finish' => get_post_meta( $object_id, $args['field_id'] . '_finish', 1 ), ); return $value; } add_filter( 'cmb2_override_meta_value', 'jt_cmb2_date_year_range_get_split_values', 10, 4 ); /** * The following snippets are required for allowing the date_year_range field * to work as a repeatable field, or in a repeatable group */ function jt_cmb2_sanitize_date_year_range( $check, $meta_value, $object_id, $field_args, $sanitizer ) { // if not repeatable, bail out. if ( ! is_array( $meta_value ) || ! $field_args['repeatable'] ) { return $check; } foreach ( $meta_value as $key => $val ) { $meta_value[ $key ] = array_filter( array_map( 'sanitize_text_field', $val ) ); } return array_filter( $meta_value ); } add_filter( 'cmb2_sanitize_date_year_range', 'jt_cmb2_sanitize_date_year_range', 10, 5 ); function jt_cmb2_esc_date_year_range( $check, $meta_value, $field_args, $field_object ) { // if not repeatable, bail out. if ( ! is_array( $meta_value ) || ! $field_args['repeatable'] ) { return $check; } foreach ( $meta_value as $key => $val ) { $meta_value[ $key ] = array_filter( array_map( 'esc_attr', $val ) ); } return array_filter( $meta_value ); } add_filter( 'cmb2_types_esc_date_year_range', 'jt_cmb2_esc_date_year_range', 10, 4 ); ================================================ FILE: filters-and-actions/README.md ================================================ CMB2 Filters and Actions ========== CMB2 has many filters and actions. Included here are snippets which demonstrate some handy ways to use those hooks. ================================================ FILE: filters-and-actions/cmb2-add-fields-dynamically.php ================================================ 'dynamic_fields_box', 'title' => 'Some test metaboxes', 'object_types' => array( 'page', 'post' ), ) ); $cmb->add_field( array( 'name' => 'Set number of next item', 'id' => 'number_of_next_item', 'type' => 'text', 'default' => '1', 'attributes' => array( 'type' => 'number', 'pattern' => '\d*', ), 'sanitization_cb' => 'absint', 'escape_cb' => 'absint', ) ); // Add dynamic fields during normal view. add_action( 'cmb2_init_hookup_dynamic_fields_box', 'add_fields_dynamically_to_box' ); // Add dynamic fields during save process. add_action( 'cmb2_post_process_fields_dynamic_fields_box', 'add_fields_dynamically_to_box' ); } function add_fields_dynamically_to_box( $cmb ) { if ( $cmb->object_id() ) { $position = 2; // Loop through however many items are selected in previous field $number_of_items = get_post_meta( $cmb->object_id(), 'number_of_next_item', true ); $number = 1; while ( $number <= $number_of_items ) { $cmb->add_field( array( 'name' => 'Item #' . $number, 'desc' => 'item_' . $number, 'id' => 'item_' . $number, 'type' => 'text', ), $position++ ); $number++; } } } ================================================ FILE: filters-and-actions/cmb2_all_or_nothing_types-filter.php ================================================ '; echo '

    Welcome to my metabox!

    '; add_action( 'cmb2_after_form', 'yourprefix_add_html_after_cmb2_output', 10, 4 ); } add_action( 'cmb2_before_form', 'yourprefix_add_html_before_cmb2_output', 10, 4 ); function yourprefix_add_html_after_cmb2_output( $cmb_id, $object_id, $object_type, $cmb ) { echo ''; } // This can be done a bit more simply this way: function add_html_before_yourprefix_demo_metabox_output( $cmb_id, $object_id, $object_type, $cmb ) { echo '
    '; echo '

    Welcome to my metabox!

    '; add_action( "cmb2_after_{$object_type}_form_{$cmb_id}", 'add_html_after_yourprefix_demo_metabox_output', 10, 4 ); } // Only output above the _yourprefix_demo_metabox metabox. add_action( 'cmb2_before_post_form__yourprefix_demo_metabox', 'add_html_before_yourprefix_demo_metabox_output', 10, 4 ); function add_html_after_yourprefix_demo_metabox_output( $cmb_id, $object_id, $object_type, $cmb ) { echo '
    '; } ================================================ FILE: filters-and-actions/cmb2_init_$cmb_id-add-fields.php ================================================ add_field( array( 'name' => __( 'New at the top', 'your_textdomain' ), 'desc' => __( 'Using the "cmb2_init_{$cmb_id}" hook', 'your_textdomain' ), 'id' => '_new_at_the_top', 'type' => 'text', ), 1 ); } add_action( 'cmb2_init__yourprefix_demo_metabox', 'yourprefix_add_new_field_to_top_of_demo_metabox' ); ================================================ FILE: filters-and-actions/cmb2_init_$cmb_id-modify-object-types.php ================================================ box_types(); $types[] = 'books'; // Your custom post type slug. // Bam. $cmb->set_prop( 'object_types', $types ); } add_action( 'cmb2_init_yourprefix_demo_metabox', 'yourprefix_demo_metabox_modify_object_types' ); ================================================ FILE: filters-and-actions/cmb2_init_$cmb_id-remove-field.php ================================================ remove_field( '_yourprefix_demo_textsmall' ); } add_action( 'cmb2_init__yourprefix_demo_metabox', 'yourprefix_remove_field_from_demo_metabox' ); ================================================ FILE: filters-and-actions/cmb2_init_$cmb_id-replace-field.php ================================================ remove_field( '_yourprefix_demo_textsmall' ); $cmb->add_field( array( 'name' => __( 'REPLACED Text Small Field', 'cmb2' ), 'desc' => __( 'Using the "cmb2_init_{$cmb_id}" hook', 'your_textdomain' ), 'id' => '_yourprefix_demo_textsmall', 'type' => 'text_money', ), 17 /* This needs to be the nth position of the original field */ ); } } add_action( 'cmb2_init_hookup__yourprefix_demo_metaboxx', 'yourprefix_replace_field_in_demo_metaboxx', 999 ); ================================================ FILE: filters-and-actions/cmb2_init_before_hookup-add-fields.php ================================================ update_field_property( '_yourprefix_demo_text2', 'type', 'text' ); /** * Since '_yourprefix_demo_text2' doesn't exist, Let's create it. * Always need to compare this value strictly to false, as a field_id COULD be 0 or '' */ if ( false === $field_id ) { $cmb->add_field( // Normal field setup array( 'name' => __( 'Test Text 2', 'your_textdomain' ), 'desc' => __( 'Test Text 2 description', 'your_textdomain' ), 'id' => '_yourprefix_demo_text2', 'type' => 'text', 'attributes' => array( 'placeholder' => __( "I'm some placeholder text", 'your_textdomain' ) ), ), 3 // Insert this field in the third position ); } } add_action( 'cmb2_init_before_hookup', 'yourprefix_add_new_field_in_3rd_position' ); function yourprefix_add_new_field_to_group() { // Try to get a metabox w/ the id of '_yourprefix_group_metabox' if ( $cmb_group_demo = cmb2_get_metabox( '_yourprefix_group_metabox' ) ) { $cmb_group_demo->add_group_field( array( 'name' => __( 'Test Text 2', 'your_textdomain' ), 'desc' => __( 'field description (optional)', 'your_textdomain' ), 'id' => 'text2', 'type' => 'text', 'attributes' => array( 'placeholder' => __( "I'm some placeholder text", 'your_textdomain' ) ), ), '_yourprefix_group_demo', // Add this to the _yourprefix_group_demo group field 2 // And insert it into the 2nd position ); } } add_action( 'cmb2_init_before_hookup', 'yourprefix_add_new_field_to_group' ); ================================================ FILE: filters-and-actions/cmb2_init_before_hookup-remove-cmb2-metabox.php ================================================ update_field_property( '_yourprefix_demo_text', 'show_on_cb', false ); /** * Always need to compare this value strictly to false, as a field_id COULD be 0 or '' */ if ( false !== $field_id ) { /** * Because we don't want to 'stomp' a field's 'attributes' property * (It may already have some attributes), we're going to get * the field's attributes property and append to it. */ // Get all fields for this metabox $fields = $cmb->prop( 'fields' ); // Get the attributes array if it exists, or else create it $attributes = isset( $fields['_yourprefix_demo_text']['attributes'] ) ? $fields['_yourprefix_demo_text']['attributes'] : array(); // Add placeholder text $attributes['placeholder'] = __( "I'm some placeholder text", 'your_textdomain' ); // Update the field's 'attributes' property $cmb->update_field_property( '_yourprefix_demo_text', 'attributes', $attributes ); } } add_action( 'cmb2_init_before_hookup', 'yourprefix_update_fields_properties' ); ================================================ FILE: filters-and-actions/cmb2_override_{$field_id}_meta_value-filter.php ================================================ get( $args['field_id'] ) : get_metadata( $args['type'], $args['id'], $args['field_id'], ( $args['single'] || $args['repeat'] ) ); // Get the default values from JSON if ( null === $defaults ) { // Get your JSON blob.. hard-coded for demo. $json = '[{"description":"This is a description<\/strong>","image":"\/wp-content\/uploads\/2016\/10\/default-image-1.jpg","image_id":663},{"title":"2nd Title","description":"This is a second description<\/strong>","image":"\/wp-content\/uploads\/2016\/10\/default-image-2.jpg","image_id":655,"image_caption":"This is an image caption."}]'; $defaults = json_decode( $json, 1 ); } // Set our group field value to the default. $value = $defaults; // If the group field's retrieved value is not empty... if ( ! empty( $data ) ) { $value = array(); // Then loop the defaults and mash the field's value up w/ the default. foreach ( $defaults as $key => $default_group_val ) { $value[ $key ] = isset( $data[ $key ] ) ? wp_parse_args( $data[ $key ], $default_group_val ) : $default_group_val; } } return $value; } add_filter( 'cmb2_override_yourprefix_group_demo_meta_value', 'yourprefix_get_default_group_value_from_json', 10, 4 ); ================================================ FILE: filters-and-actions/custom-css-for-specific-metabox.php ================================================ 'custom_css_test', 'title' => __( 'Custom CSS Test', 'cmb2' ), 'object_types' => array( 'page', ), ) ); $cmb->add_field( array( 'id' => '_cmb2_test_text', 'type' => 'text', ) ); } add_action( 'cmb2_admin_init', 'js_custom_css_for_metabox' ); function js_add_custom_css_for_metabox( $post_id, $cmb ) { ?> 'Hey, this is your first entry', 'description' => 'Go ahead and delete this entry, or update its contents', ), // Default group 2. array( 'title' => 'Hey, this is your 2nd entry', 'description' => '#2', ), ) ); } $cmb_group = new_cmb2_box( array( 'id' => 'yourprefix_group_alt_data_metabox', 'title' => __( 'Repeating Field Group', 'cmb2' ), 'object_types' => array( 'post', ), 'show_on' => array( 'id' => array( 1000, ) ), 'show_in_rest' => WP_REST_Server::ALLMETHODS, ) ); // $group_field_id is the field id string, so in this case: '_yourprefix_group_demo' $group_field_id = $cmb_group->add_field( array( 'id' => 'yourprefix_group_alt_data_demo', 'type' => 'group', 'options' => array( 'group_title' => __( 'Entry {#}', 'cmb2' ), // {#} gets replaced by row number 'add_button' => __( 'Add Another Entry', 'cmb2' ), 'remove_button' => __( 'Remove Entry', 'cmb2' ), 'sortable' => true, // beta ), ) ); /** * Group fields works the same, except ids only need * to be unique to the group. Prefix is not needed. * * The parent field's id needs to be passed as the second argument. */ $cmb_group->add_group_field( $group_field_id, array( 'name' => 'Entry Title', 'id' => 'title', 'type' => 'text', ) ); $cmb_group->add_group_field( $group_field_id, array( 'name' => 'Description', 'description' => 'Write a short description for this entry', 'id' => 'description', 'type' => 'wysiwyg', 'options' => array( 'textarea_rows' => 3, ), ) ); }; add_filter( 'cmb2_override_yourprefix_group_alt_data_demo_meta_value', 'yourprefix_group_alt_data_demo_override_meta_value', 10, 4 ); function yourprefix_group_alt_data_demo_override_meta_value( $data, $object_id, $args, $field ) { // Here, we're pulling from the options table, but you can query from any data source here. // If from a custom table, you can use the $object_id to query against. return get_option( 'yourprefix_group_alt_data_demo', array() ); } add_filter( 'cmb2_override_yourprefix_group_alt_data_demo_meta_save', 'yourprefix_group_alt_data_demo_override_meta_save', 10, 4 ); function yourprefix_group_alt_data_demo_override_meta_save( $override, $args, $field_args, $field ) { // Here, we're storing the data to the options table, but you can store to any data source here. // If to a custom table, you can use the $args['id'] as the reference id. $updated = update_option( 'yourprefix_group_alt_data_demo', $args['value'] ); return !! $updated; } add_filter( 'cmb2_override_yourprefix_group_alt_data_demo_meta_remove', 'yourprefix_group_alt_data_demo_override_meta_remove', 10, 4 ); function yourprefix_group_alt_data_demo_override_meta_remove( $override, $args, $field_args, $field ) { // Here, we're removing from the options table, but you can query to remove from any data source here. // If from a custom table, you can use the $args['id'] to query against. // (If we do "delete_option", then our default value will be re-applied, which isn't desired.) $updated = update_option( 'yourprefix_group_alt_data_demo', array() ); return !! $updated; } ================================================ FILE: filters-and-actions/save-default-group-field-value-based-on-other-field.php ================================================ 'yourprefix_group_metabox', 'title' => __( 'Repeating Field Group', 'cmb2' ), 'object_types' => array( 'page', ), ) ); $cmb->add_field( $group_field_id, array( 'name' => __( 'Radio', 'cmb2' ), 'id' => 'yourprefix_group_radio', 'type' => 'radio', 'options' => array( 'standard' => __( 'Option One', 'cmb2' ), 'custom' => __( 'Option Two', 'cmb2' ), 'none' => __( 'Option Three', 'cmb2' ), ), ) ); $group_field_id = $cmb->add_field( array( 'id' => 'yourprefix_group_demo', 'type' => 'group', 'description' => __( 'Generates reusable form entries', 'cmb2' ), 'options' => array( 'group_title' => __( 'Entry {#}', 'cmb2' ), 'add_button' => __( 'Add Another Entry', 'cmb2' ), 'remove_button' => __( 'Remove Entry', 'cmb2' ), 'sortable' => true, ), ) ); $cmb->add_group_field( $group_field_id, array( 'name' => 'Entry Title', 'id' => 'title', 'type' => 'text', ) ); $cmb->add_group_field( $group_field_id, array( 'name' => 'Description', 'description' => 'Write a short description for this entry', 'id' => 'description', 'type' => 'textarea_small', ) ); } add_action( 'cmb2_init', 'yourprefix_register_repeatable_group_field_metabox' ); // If the radio field is set to 'standard', then update the group field value to have one group filled-in. function hook_in_and_add_default_group_value( $post_id, $updated, $cmb ) { // If 'my_meta_key' was updated, then proceed w/ my stuff. if ( in_array( 'yourprefix_group_radio', $updated ) ) { if ( 'standard' === get_post_meta( $post_id, 'yourprefix_group_radio', 1 ) ) { // do stuff update_post_meta( $post_id, 'yourprefix_group_demo', array( array( 'title' => 'Title of group 1', 'description' => 'Description of group 1', ) ) ); } } } add_action( 'cmb2_save_post_fields_yourprefix_group_metabox', 'hook_in_and_add_default_group_value', 10, 3 ); ================================================ FILE: front-end/README.md ================================================ Front-end ========== Snippets that use CMB2 on the front-end (not wp-admin) side of your site. ================================================ FILE: front-end/cmb2-front-end-editor.php ================================================ You do not have permission to edit this post.'; } } return $content; } add_filter( 'the_content', 'jt_add_edit_form_to_frontend' ); /** * Modify the edit links to point to the front-end editor. */ function jt_modify_edit_link( $link ) { if ( ! is_admin() ) { $link = esc_url_raw( wp_nonce_url( remove_query_arg( 'edit' ), 'edit', 'edit' ) ); } return $link; } add_filter( 'get_edit_post_link', 'jt_modify_edit_link' ); /** * Hook in later and prepend our title/content fields to our existing metabox */ function jt_edit_core_fields() { if ( ! is_admin() ) { // only if on front-end // Get existing metabox $cmb = cmb2_get_metabox( '_yourprefix_demo_metabox' ); // and prepend title $cmb->add_field( array( 'name' => __( 'Title', 'cmb2' ), 'id' => 'post_title', 'type' => 'text', 'before' => 'jt_edit_core_maybe_redirect', ), 1 ); // and content fields $cmb->add_field( array( 'name' => __( 'Content', 'cmb2' ), 'id' => 'post_content', 'type' => 'wysiwyg', ), 2 ); } } add_action( 'cmb2_init', 'jt_edit_core_fields', 99 ); /** * If edit was saved, redirect to non-edit page */ function jt_edit_core_maybe_redirect() { if ( isset( $_POST['post_content'] ) ) { $url = esc_url_raw( remove_query_arg( 'edit' ) ); echo ""; } } /** * We don't want CMB2 to fetch data from meta for post title and post content */ function jt_cmb2_override_core_field_get( $val, $object_id, $a, $field ) { global $post; if ( in_array( $field->id(), array( 'post_title', 'post_content' ), true ) ) { if ( isset( $post->ID ) ) { $val = get_post_field( $field->id(), $post ); } else { $val = ''; } } return $val; } add_filter( 'cmb2_override_meta_value', 'jt_cmb2_override_core_field_get', 10, 4 ); /** * We don't want CMB2 to save data to meta for post title and post content */ function jt_cmb2_override_core_field_set( $status, $a, $args, $field ) { global $post; if ( in_array( $field->id(), array( 'post_title', 'post_content' ), true ) ) { if ( isset( $post->ID ) ) { $status = wp_update_post( array( $field->id() => $a['value'], 'ID' => $post->ID, ) ); } else { $status = false; } } return $status; } add_filter( 'cmb2_override_meta_save', 'jt_cmb2_override_core_field_set', 10, 4 ); ================================================ FILE: front-end/cmb2-front-end-submit.php ================================================ 'front-end-post-form', 'object_types' => array( 'post' ), 'hookup' => false, 'save_fields' => false, ) ); $cmb->add_field( array( 'name' => __( 'New Post Title', 'YOURTEXTDOMAIN' ), 'id' => 'submitted_post_title', 'type' => 'text', 'default' => ! empty( $_POST['submitted_post_title'] ) ? $_POST['submitted_post_title'] : __( 'New Post', 'YOURTEXTDOMAIN' ), ) ); $cmb->add_field( array( 'default_cb' => 'yourprefix_maybe_set_default_from_posted_values', 'name' => __( 'New Post Content', 'YOURTEXTDOMAIN' ), 'id' => 'submitted_post_content', 'type' => 'wysiwyg', 'options' => array( 'textarea_rows' => 12, 'media_buttons' => false, ), ) ); $cmb->add_field( array( 'default_cb' => 'yourprefix_maybe_set_default_from_posted_values', 'name' => __( 'Featured Image for New Post', 'YOURTEXTDOMAIN' ), 'id' => 'submitted_post_thumbnail', 'type' => 'text', 'attributes' => array( 'type' => 'file', // Let's use a standard file upload field ), ) ); $cmb->add_field( array( 'default_cb' => 'yourprefix_maybe_set_default_from_posted_values', 'name' => __( 'Categories', 'YOURTEXTDOMAIN' ), 'id' => 'submitted_categories', 'type' => 'taxonomy_multicheck', 'taxonomy' => 'category', // Taxonomy Slug ) ); $cmb->add_field( array( 'default_cb' => 'yourprefix_maybe_set_default_from_posted_values', 'name' => __( 'Your Name', 'YOURTEXTDOMAIN' ), 'desc' => __( 'Please enter your name for author credit on the new post.', 'YOURTEXTDOMAIN' ), 'id' => 'submitted_author_name', 'type' => 'text', ) ); $cmb->add_field( array( 'default_cb' => 'yourprefix_maybe_set_default_from_posted_values', 'name' => __( 'Your Email', 'YOURTEXTDOMAIN' ), 'desc' => __( 'Please enter your email so we can contact you if we use your post.', 'YOURTEXTDOMAIN' ), 'id' => 'submitted_author_email', 'type' => 'text_email', ) ); } add_action( 'cmb2_init', 'yourprefix_frontend_form_register' ); /** * Sets the front-end-post-form field values if form has already been submitted. * * @return string */ function yourprefix_maybe_set_default_from_posted_values( $args, $field ) { if ( ! empty( $_POST[ $field->id() ] ) ) { return $_POST[ $field->id() ]; } return ''; } /** * Gets the front-end-post-form cmb instance * * @return CMB2 object */ function yourprefix_frontend_cmb2_get() { // Use ID of metabox in yourprefix_frontend_form_register $metabox_id = 'front-end-post-form'; // Post/object ID is not applicable since we're using this form for submission $object_id = 'fake-oject-id'; // Get CMB2 metabox object return cmb2_get_metabox( $metabox_id, $object_id ); } /** * Handle the cmb_frontend_form shortcode * * @param array $atts Array of shortcode attributes * @return string Form html */ function yourprefix_do_frontend_form_submission_shortcode( $atts = array() ) { // Get CMB2 metabox object $cmb = yourprefix_frontend_cmb2_get(); // Get $cmb object_types $post_types = $cmb->prop( 'object_types' ); // Current user $user_id = get_current_user_id(); // Parse attributes $atts = shortcode_atts( array( 'post_author' => $user_id ? $user_id : 1, // Current user, or admin 'post_status' => 'pending', 'post_type' => reset( $post_types ), // Only use first object_type in array ), $atts, 'cmb_frontend_form' ); /* * Let's add these attributes as hidden fields to our cmb form * so that they will be passed through to our form submission */ foreach ( $atts as $key => $value ) { $cmb->add_hidden_field( array( 'field_args' => array( 'id' => "atts[$key]", 'type' => 'hidden', 'default' => $value, ), ) ); } // Initiate our output variable $output = ''; // Get any submission errors if ( ( $error = $cmb->prop( 'submission_error' ) ) && is_wp_error( $error ) ) { // If there was an error with the submission, add it to our ouput. $output .= '

    ' . sprintf( __( 'There was an error in the submission: %s', 'YOURTEXTDOMAIN' ), ''. $error->get_error_message() .'' ) . '

    '; } // If the post was submitted successfully, notify the user. if ( isset( $_GET['post_submitted'] ) && ( $post = get_post( absint( $_GET['post_submitted'] ) ) ) ) { // Get submitter's name $name = get_post_meta( $post->ID, 'submitted_author_name', 1 ); $name = $name ? ' '. $name : ''; // Add notice of submission to our output $output .= '

    ' . sprintf( __( 'Thank you%s, your new post has been submitted and is pending review by a site administrator.', 'YOURTEXTDOMAIN' ), esc_html( $name ) ) . '

    '; } // Get our form $output .= cmb2_get_metabox_form( $cmb, 'fake-oject-id', array( 'save_button' => __( 'Submit Post', 'YOURTEXTDOMAIN' ) ) ); return $output; } add_shortcode( 'cmb_frontend_form', 'yourprefix_do_frontend_form_submission_shortcode' ); /** * Handles form submission on save. Redirects if save is successful, otherwise sets an error message as a cmb property * * @return void */ function yourprefix_handle_frontend_new_post_form_submission() { // If no form submission, bail if ( empty( $_POST ) || ! isset( $_POST['submit-cmb'], $_POST['object_id'] ) ) { return false; } // Get CMB2 metabox object $cmb = yourprefix_frontend_cmb2_get(); $post_data = array(); // Get our shortcode attributes and set them as our initial post_data args if ( isset( $_POST['atts'] ) ) { foreach ( (array) $_POST['atts'] as $key => $value ) { $post_data[ $key ] = sanitize_text_field( $value ); } unset( $_POST['atts'] ); } // Check security nonce if ( ! isset( $_POST[ $cmb->nonce() ] ) || ! wp_verify_nonce( $_POST[ $cmb->nonce() ], $cmb->nonce() ) ) { return $cmb->prop( 'submission_error', new WP_Error( 'security_fail', __( 'Security check failed.' ) ) ); } // Check title submitted if ( empty( $_POST['submitted_post_title'] ) ) { return $cmb->prop( 'submission_error', new WP_Error( 'post_data_missing', __( 'New post requires a title.' ) ) ); } // And that the title is not the default title if ( $cmb->get_field( 'submitted_post_title' )->default() == $_POST['submitted_post_title'] ) { return $cmb->prop( 'submission_error', new WP_Error( 'post_data_missing', __( 'Please enter a new title.' ) ) ); } /** * Fetch sanitized values */ $sanitized_values = $cmb->get_sanitized_values( $_POST ); // Set our post data arguments $post_data['post_title'] = $sanitized_values['submitted_post_title']; unset( $sanitized_values['submitted_post_title'] ); $post_data['post_content'] = $sanitized_values['submitted_post_content']; unset( $sanitized_values['submitted_post_content'] ); // Create the new post $new_submission_id = wp_insert_post( $post_data, true ); // If we hit a snag, update the user if ( is_wp_error( $new_submission_id ) ) { return $cmb->prop( 'submission_error', $new_submission_id ); } $cmb->save_fields( $new_submission_id, 'post', $sanitized_values ); /** * Other than post_type and post_status, we want * our uploaded attachment post to have the same post-data */ unset( $post_data['post_type'] ); unset( $post_data['post_status'] ); // Try to upload the featured image $img_id = yourprefix_frontend_form_photo_upload( $new_submission_id, $post_data ); // If our photo upload was successful, set the featured image if ( $img_id && ! is_wp_error( $img_id ) ) { set_post_thumbnail( $new_submission_id, $img_id ); } /* * Redirect back to the form page with a query variable with the new post ID. * This will help double-submissions with browser refreshes */ wp_redirect( esc_url_raw( add_query_arg( 'post_submitted', $new_submission_id ) ) ); exit; } add_action( 'cmb2_after_init', 'yourprefix_handle_frontend_new_post_form_submission' ); /** * Handles uploading a file to a WordPress post * * @param int $post_id Post ID to upload the photo to * @param array $attachment_post_data Attachement post-data array */ function yourprefix_frontend_form_photo_upload( $post_id, $attachment_post_data = array() ) { // Make sure the right files were submitted if ( empty( $_FILES ) || ! isset( $_FILES['submitted_post_thumbnail'] ) || isset( $_FILES['submitted_post_thumbnail']['error'] ) && 0 !== $_FILES['submitted_post_thumbnail']['error'] ) { return; } // Filter out empty array values $files = array_filter( $_FILES['submitted_post_thumbnail'] ); // Make sure files were submitted at all if ( empty( $files ) ) { return; } // Make sure to include the WordPress media uploader API if it's not (front-end) if ( ! function_exists( 'media_handle_upload' ) ) { require_once( ABSPATH . 'wp-admin/includes/image.php' ); require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once( ABSPATH . 'wp-admin/includes/media.php' ); } // Upload the file and send back the attachment post ID return media_handle_upload( 'submitted_post_thumbnail', $post_id, $attachment_post_data ); } ================================================ FILE: front-end/cmb2-front-end-wordpress-media-uploader.php ================================================ add_cap( 'upload_files' ); } add_action( 'init', 'nevestam_allow_contributor_uploads' ); /** * Display only user-uploaded files to each user * * @param WP_Query $wp_query_obj */ function nevestam_restrict_media_library( $wp_query_obj ) { global $current_user, $pagenow; if ( ! is_a( $current_user, 'WP_User' ) ) { return; } if ( 'admin-ajax.php' != $pagenow || 'query-attachments' != $_REQUEST['action'] ) { return; } if ( ! current_user_can( 'manage_media_library' ) ) { $wp_query_obj->set( 'author', $current_user->ID ); } } add_action( 'pre_get_posts', 'nevestam_restrict_media_library' ); ================================================ FILE: front-end/cmb2-metabox-shortcode.php ================================================ ID; } // If no metabox id is set, yell about it if ( empty( $atts['id'] ) ) { return 'Please add an "id" attribute to specify the CMB2 form to display.'; } $metabox_id = esc_attr( $atts['id'] ); $object_id = absint( $atts['post_id'] ); // Get our form $form = cmb2_get_metabox_form( $metabox_id, $object_id ); return $form; } add_shortcode( 'cmb-form', 'jt_cmb2_do_frontend_form_shortcode' ); ================================================ FILE: front-end/output-file-list.php ================================================ $attachment_url ) { $images .= '
    '; $images .= wp_get_attachment_image( $attachment_id, $img_size ); $images .= '
    '; } return $images ? '
    ' . $images . '
    ' : ''; } ================================================ FILE: helper-functions/README.md ================================================ CMB2 Helper Functions ========== Snippets for working with the [included helper functions](https://github.com/WebDevStudios/CMB2/blob/master/includes/helper-functions.php). Related CMB2 issues: * [#130](https://github.com/WebDevStudios/CMB2/issues/130#issuecomment-68160722) ================================================ FILE: helper-functions/helper-functions.php ================================================ autoembed( $content ); $content = $wp_embed->run_shortcode( $content ); $content = wpautop( $content ); $content = do_shortcode( $content ); return $content; } /** * Sample template tag function for outputting a cmb2 file_list. * * @link https://github.com/WebDevStudios/CMB2/wiki/Field-Types#sample-function-for-getting-and-outputting-file_list-images Wiki * * @param string $meta_key The 'file_list' field meta key. * @param string $img_size Size of image to display. */ function yourprefix_cmb2_output_file_list( $meta_key, $img_size = 'medium' ) { // Get the list of files $files = get_post_meta( get_the_ID(), $meta_key, 1 ); echo '
    '; // Loop through them and output an image foreach ( (array) $files as $attachment_id => $attachment_url ) { echo '
    '; echo wp_get_attachment_image( $attachment_id, $img_size ); echo '
    '; } echo '
    '; } ================================================ FILE: helper-functions/modify-cmb2_metabox_form-format.php ================================================ '
    %3$s
    ', ) ); ================================================ FILE: helper-functions/modify-cmb2_metabox_form-output.php ================================================ cmb_id to retrieve the metabox ID * * @return string Possibly modified form output */ function myprefix_options_modify_cmb2_metabox_form_format( $form_format, $object_id, $cmb ) { if ( 'myprefix_options' == $object_id && 'option_metabox' == $cmb->cmb_id ) { $form_format = '
    %3$s
    '; } return $form_format; } add_filter( 'cmb2_get_metabox_form_format', 'myprefix_options_modify_cmb2_metabox_form_format', 10, 3 ); ================================================ FILE: helper-functions/modify-cmb2_metabox_form-save-button-text.php ================================================ __( 'Save Settings', 'your-textdomain' ), ) ); ================================================ FILE: javascript/README.md ================================================ CMB2 Javascript ========== Custom javascript snippets for interacting with CMB2. ================================================ FILE: javascript/cmb2-auto-scroll-to-new-group.php ================================================ 'yourprefix_group_titles_metabox', 'title' => __( 'Repeating Field Group with Updating Titles', 'cmb2' ), 'object_types' => array( 'page', ), 'show_in_rest' => 'read_and_write', ) ); $group_field_id = $cmb_group->add_field( array( 'id' => 'yourprefix_group_titles_demo', 'type' => 'group', 'description' => __( 'Generates reusable form entries', 'cmb2' ), 'options' => array( 'group_title' => __( 'Entry {#}', 'cmb2' ), // {#} gets replaced by row number 'add_button' => __( 'Add Another Entry', 'cmb2' ), 'remove_button' => __( 'Remove Entry', 'cmb2' ), 'sortable' => true, // beta ), 'after_group' => 'yourprefix_add_js_for_repeatable_titles', ) ); $cmb_group->add_group_field( $group_field_id, array( 'name' => 'Title', 'id' => 'title', 'type' => 'text', ) ); $cmb_group->add_group_field( $group_field_id, array( 'name' => 'Description', 'id' => 'description', 'type' => 'textarea_small', ) ); } add_action( 'cmb2_init', 'yourprefix_register_repeatable_group_field_title_example' ); function yourprefix_add_js_for_repeatable_titles() { add_action( is_admin() ? 'admin_footer' : 'wp_footer', 'yourprefix_add_js_for_repeatable_titles_to_footer' ); } function yourprefix_add_js_for_repeatable_titles_to_footer() { ?> 'field_group_test_one', 'title' => __( 'Repeating Field Group One', 'cmb2' ), 'object_types' => array( 'page', ), 'rows_limit' => 3, // custom attribute to use in our JS 'groupId' => '_cmb2_repeat_group_one', // custom attribute to use in our JS to retrieve the ID of the group that should be handled ) ); $cmb_two = new_cmb2_box( array( 'id' => 'field_group_test_two', 'title' => __( 'Repeating Field Group Two', 'cmb2' ), 'object_types' => array( 'page', ), 'rows_limit' => 2, // custom attribute to use in our JS 'groupId' => '_cmb2_repeat_group_two', // custom attribute to use in our JS to retrieve the ID of the group that should be handled ) ); $group_one = $cmb_one->add_field( array( 'id' => '_cmb2_repeat_group_one', 'type' => 'group', 'description' => __( 'Generates reusable form entries', 'cmb2' ), 'options' => array( 'group_title' => __( 'Entry {#}', 'cmb2' ), // {#} gets replaced by row number 'add_button' => __( 'Add Another Entry', 'cmb2' ), 'remove_button' => __( 'Remove Entry', 'cmb2' ), 'sortable' => true, // beta ), ) ); $cmb_one->add_group_field( $group_one, array( 'name' => 'Entry Title', 'id' => 'title', 'type' => 'text', ) ); $cmb_one->add_group_field( $group_one, array( 'name' => 'Description', 'desc' => 'Write a short description for this entry', 'id' => 'description', 'type' => 'textarea_small', ) ); $group_two = $cmb_two->add_field( array( 'id' => '_cmb2_repeat_group_two', 'type' => 'group', 'description' => __( 'Generates reusable form entries', 'cmb2' ), 'options' => array( 'group_title' => __( 'Entry {#}', 'cmb2' ), // {#} gets replaced by row number 'add_button' => __( 'Add Another Entry', 'cmb2' ), 'remove_button' => __( 'Remove Entry', 'cmb2' ), 'sortable' => true, // beta ), ) ); $cmb_two->add_group_field( $group_two, array( 'name' => 'Entry Title', 'id' => 'title', 'type' => 'text', ) ); $cmb_two->add_group_field( $group_two, array( 'name' => 'Description', 'desc' => 'Write a short description for this entry', 'id' => 'description', 'type' => 'textarea_small', ) ); } add_action( 'cmb2_admin_init', 'js_limited_group_setup', 9999 ); $repeater_metaboxes = array('field_group_test_one','field_group_test_two'); // IDs of the metabox containing the repeater group foreach ($repeater_metaboxe as $value) { add_action( 'cmb2_after_post_form_'.$value, 'js_limit_group_repeat', 10, 2); } function js_limit_group_repeat( $post_id, $cmb ) { // Grab the custom attribute to determine the limit $limit = absint( $cmb->prop( 'rows_limit' ) ); $limit = $limit ? $limit : 0; $group = $cmb->prop( 'groupId' ) ?> 'test_limit_rows', 'title' => __( 'Repeating Field Group', 'cmb2' ), 'object_types' => array( 'page', ), 'rows_limit' => 3, ) ); $cmb->add_field( array( 'name' => 'Entry Title', 'id' => 'text_repeat_test', 'type' => 'text', 'repeatable' => true, // Repeatable fields are supported w/in repeatable groups (for most types) ) ); } add_action( 'cmb2_admin_init', 'js_limited_repeat_field_setup', 9999 ); function js_limit_field_repeat( $post_id, $cmb ) { // Grab the custom attribute to determine the limit $limit = absint( $cmb->prop( 'rows_limit' ) ); $limit = $limit ? $limit : 0; ?> 'field_group_test', 'title' => __( 'Repeating Field Group', 'cmb2' ), 'object_types' => array( 'page', ), 'rows_limit' => 3, // custom attribute to use in our JS ) ); $group_id = $cmb->add_field( array( 'id' => '_cmb2_repeat_group', 'type' => 'group', 'description' => __( 'Generates reusable form entries', 'cmb2' ), 'options' => array( 'group_title' => __( 'Entry {#}', 'cmb2' ), // {#} gets replaced by row number 'add_button' => __( 'Add Another Entry', 'cmb2' ), 'remove_button' => __( 'Remove Entry', 'cmb2' ), 'sortable' => true, // beta ), ) ); $cmb->add_group_field( $group_id, array( 'name' => 'Entry Title', 'id' => 'title', 'type' => 'text', ) ); $cmb->add_group_field( $group_id, array( 'name' => 'Description', 'desc' => 'Write a short description for this entry', 'id' => 'description', 'type' => 'textarea_small', ) ); } add_action( 'cmb2_admin_init', 'js_limited_group_setup', 9999 ); function js_limit_group_repeat( $post_id, $cmb ) { // Grab the custom attribute to determine the limit $limit = absint( $cmb->prop( 'rows_limit' ) ); $limit = $limit ? $limit : 0; ?> id in the above example. add_action( 'cmb2_after_post_form_field_group_test', 'js_limit_group_repeat', 10, 2 ); ================================================ FILE: metaboxes/README.md ================================================ Metaboxes ========== These are examples of different metabox configurations. ================================================ FILE: misc/README.md ================================================ Miscellaneous Snippets ========== Random CMB2 and WordPress snippets ================================================ FILE: misc/add-wrap-to-group-of-fields.php ================================================ $prefix . 'metabox', 'title' => esc_html__( 'Test Metabox', 'cmb2' ), 'object_types' => array( 'page', ), // Post type ) ); // Markup to add a metabox-like toggle box: http://b.ustin.co/12Uba $advanced_open = '

    Toggle Advanced Options

    '; $advanced_close = '
    '; $cmb->add_field( array( 'before_row' => $advanced_open, 'name' => esc_html__( 'Test Text', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => $prefix . 'text', 'type' => 'text', ) ); $cmb->add_field( array( 'name' => esc_html__( 'Test Text Small', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => $prefix . 'textsmall', 'type' => 'text_small', ) ); $cmb->add_field( array( 'name' => esc_html__( 'Test Text Medium', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => $prefix . 'textmedium', 'type' => 'text_medium', 'after_row' => $advanced_close, ) ); // Optionally do other fields here... } ================================================ FILE: misc/adding-wordcount-to-cmb2-wysiwyg-field.php ================================================ 'hold-my-wysiwyg', 'object_types' => array( 'post' ), ) ); $cmb->add_field( array( 'name' => __( 'WYSIWYG content', 'YOURTEXTDOMAIN' ), 'id' => 'wysiwyg_content', 'type' => 'wysiwyg', 'after' => 'cmb2_wysiwyg_word_counter', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_feat_img_fields' ); /** * Outputs wordcount for wysiwyg field. * * Basically copied from: https://github.com/WordPress/WordPress/blob/3099f4d9edc5f2f2b6ef8becc966135edde909a8/wp-admin/js/post.js#L1219-L1271 * and: https://github.com/WordPress/WordPress/blob/3099f4d9edc5f2f2b6ef8becc966135edde909a8/wp-admin/edit-form-advanced.php#L714 */ function cmb2_wysiwyg_word_counter( $args, $field ) { wp_enqueue_script( 'word-count', array( 'jquery', 'underscore', 'word-count' ) ); ?>

    0' ); ?>

    * @link https://joebuckle.me/quickie/wordpress-add-options-to-post-admin-publish-meta-box/ * @link https://github.com/CMB2/CMB2-Snippet-Library/blob/master/misc/outputting-forms-outside-metaboxes.php * @link https://codex.wordpress.org/Plugin_API/Action_Reference/post_submitbox_misc_actions */ /** * Register the CMB2 metabox. */ function yourprefix_cmb2_fields() { $prefix = '_yourprefix_'; $cmb = new_cmb2_box( [ 'id' => $prefix . 'publish_box', 'object_types' => [ 'post' ], // Any public post type. 'show_names' => false, // Disables the display for the CMB2 label. ] ); $cmb->add_field( [ 'before' => '', // Output the label w/o the default CMB2 styles. 'id' => $prefix . 'field', 'desc' => __( 'Field description (optional)', 'cmb2' ), 'type' => 'text', // Any valid CMB2 field type. 'attributes' => [ 'style' => 'max-width: 80%;', // Cleans up the default CMB2 styles a bit. Move to stylesheet? ] ] ); } add_action( 'post_submitbox_misc_actions', 'yourprefix_filter_publish_box' ); /** * Display the CMB2 form in the WordPress publish metabox. * * @param object $post The WP_Post object. */ function yourprefix_filter_publish_box( $post ) { $cmb = cmb2_get_metabox( '_yourprefix_publish_box' ); // Must match the box ID. if ( in_array( $post->post_type, $cmb->prop( 'object_types' ), true ) ) { $cmb->show_form(); } } add_action( 'cmb2_admin_init', 'yourprefix_cmb2_fields' ); ================================================ FILE: misc/helper-functions.php ================================================ value data for saving. Likely $_POST data. */ function cmb2_save_metabox_fields_data( $meta_box_id, $object_id, array $data_to_save ) { $cmb = cmb2_get_metabox( $meta_box_id, $object_id ); $cmb->save_fields( $object_id, $cmb->object_type(), $data_to_save ); } /** * Returns array of sanitized field values (without saving them) from * provided array of values (Likely $_POST data.) * * Combined with the metabox `'save_fields' => false` config option, you can use this to * save the box data somewhere else. * * @link https://wordpress.org/support/topic/sanitizing-data-outside-metabox-context Forum post * * @param mixed $meta_box_id Metabox ID (or metabox config array) * @param int $object_id ID of post/user/comment/options-page to save the data against * @param array $data_to_save Array of key => value data for saving. Likely $_POST data. */ function cmb2_get_metabox_sanitized_values( $meta_box_id, array $data_to_save ) { $cmb = cmb2_get_metabox( $meta_box_id ); $cmb->get_sanitized_values( $data_to_save ); } ================================================ FILE: misc/outputting-cmb2-fields-in-featured-image-metabox.php ================================================ 'feat-image-fields', 'object_types' => array( 'post' ), ) ); $cmb->add_field( array( 'name' => 'Featured Image Position', 'id' => 'feat_img_placement', 'type' => 'select', 'options' => array( '' => 'Center', // The default -- no value. Keeps out of the database. 'left' => 'Left', 'right' => 'Right', ), 'before' => '', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_feat_img_fields' ); function yourprefix_feat_img_output_fields( $content, $post_id, $thumbnail_id ) { $cmb = cmb2_get_metabox( 'feat-image-fields' ); if ( $cmb && in_array( get_post_type(), $cmb->prop( 'object_types' ), 1 ) ) { ob_start(); $cmb->show_form(); // grab the data from the output buffer and add it to our $content variable $content .= ob_get_clean(); } return $content; } add_filter( 'admin_post_thumbnail_html', 'yourprefix_feat_img_output_fields', 10, 3 ); ================================================ FILE: misc/outputting-forms-outside-metaboxes.php ================================================ '_yourprefix_display_title', 'object_types' => array( 'page' ), //'title' => '', omit the 'title' field to keep the normal wp metabox from displaying ) ); $cmb->add_field( array( 'name' => 'Display title for this page?', 'id' => '_yourprefix_display_title', 'type' => 'checkbox', ) ); $cmb->add_field( array( 'name' => 'A textarea', 'id' => '_yourprefix_display_title_text', 'type' => 'textarea', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_register_cmb2_fields' ); /** * Display checkbox metabox below title field * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L517-L523 */ function yourprefix_output_custom_mb_location() { $cmb = cmb2_get_metabox( '_yourprefix_display_title' ); if ( in_array( get_post_type(), $cmb->prop( 'object_types' ), 1 ) ) { $cmb->show_form(); } } add_action( 'edit_form_after_title', 'yourprefix_output_custom_mb_location' ); /** * More hooks in the post-editor screen as of 4.1 */ /** * Display checkbox metabox below wysiwyg editor field * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L560-L567 */ // add_action( 'edit_form_after_editor', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L217-L225 */ // add_action( 'dbx_post_advanced', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L241-L249 */ // add_action( 'add_meta_boxes', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L416-L423 */ // add_action( 'post_edit_form_tag', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L447-L456 */ // add_action( 'edit_form_top', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L480-L487 */ // add_action( 'edit_form_before_permalink', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L516-L523 */ // add_action( 'edit_form_after_title', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L560-L567 */ // add_action( 'edit_form_after_editor', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L574-L597 */ // add_action( 'submitpost_box', 'yourprefix_output_custom_mb_location' ); // add_action( 'submitpage_box', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L609-L628 */ // add_action( 'edit_form_advanced', 'yourprefix_output_custom_mb_location' ); // add_action( 'edit_page_form', 'yourprefix_output_custom_mb_location' ); /** * @link https://github.com/WordPress/WordPress/blob/56d6682461be82da1a3bafc454dad2c9da451a38/wp-admin/edit-form-advanced.php#L636-L643 */ // add_action( 'dbx_post_sidebar', 'yourprefix_output_custom_mb_location' ); ================================================ FILE: misc/replace-wp-excerpt-with-cmb2-field.php ================================================ 'cmb2_excerpt', 'title' => 'Excerpt', 'object_types' => array( 'post', ), // Post type // 'context' => 'side', ) ); $cmb->add_field( array( /* * As long as the 'id' matches the name field of the regular WP field, * WP will handle the saving for you. */ 'id' => 'excerpt', 'name' => 'Excerpt', 'desc' => 'Excerpts are optional hand-crafted summaries of your content that can be used in your theme. Learn more about manual excerpts.', 'type' => 'textarea', 'escape_cb' => false, ) ); } add_action( 'cmb2_admin_init', 'cmb2_register_excerpt_replacement_box' ); /** * Remove the default WordPress excerpt field. */ function cmb2_admin_hide_excerpt_field() { add_action( 'add_meta_boxes', '_cmb2_admin_hide_excerpt_field' ); } add_filter( 'admin_init', 'cmb2_admin_hide_excerpt_field' ); function _cmb2_admin_hide_excerpt_field() { $screen = get_current_screen(); if ( isset( $screen->post_type ) && 'post' === $screen->post_type ) { remove_meta_box( 'postexcerpt', null, 'normal' ); } } /** * Override the WordPress Excerpt field */ function cmb2_override_excerpt_display( $data, $post_id ) { return get_post_field( 'post_excerpt', $post_id ); } add_filter( 'cmb2_override_excerpt_meta_value', 'cmb2_override_excerpt_display', 10, 2 ); /* * WP will handle the saving for us, so don't save to meta. */ add_filter( 'cmb2_override_excerpt_meta_save', '__return_true' ); ================================================ FILE: misc/replace-wp-title-content-thumbnail-with-cmb2-fields.php ================================================ 'CPT', 'singular_name' => 'CPT', 'menu_name' => 'CPT', 'parent_item_colon' => 'Parent CPT', 'all_items' => 'All CPT', 'view_item' => 'View CPT', 'add_new_item' => 'Add New CPT', 'add_new' => 'Add New', 'edit_item' => 'Edit CPT', 'update_item' => 'Update CPT', 'search_items' => 'Search CPT', 'not_found' => 'Not Found', 'not_found_in_trash' => 'Not found in Trash', ); register_post_type( 'cpt', array( 'labels' => $labels, 'supports' => array( 'title' ), 'supports' => array( '' ), 'public' => true, 'has_archive' => true, ) ); } add_action( 'init', 'register_test_cpt' ); function register_test_cpt_metabox() { $cmb_subsub = new_cmb2_box( array ( 'id' => 'metabox', 'title' => 'Edit', 'object_types' => array( 'cpt' ), ) ); $cmb_subsub->add_field( array( 'id' => 'post_title', // Saves to WP post title, allows the_title() 'name' => 'Title', 'desc' => 'Provide a title.', 'default' => '', 'type' => 'text', ) ); $cmb_subsub->add_field( array( 'id' => 'post_content', // Saves to WP post content, allows the_content() 'name' => 'Description', 'desc' => 'Enter a brief description', 'type' => 'textarea', // wysiwyg is problematic when replacing post_content ) ); $cmb_subsub->add_field( array( 'id' => '_thumbnail', // Saves to WP post thumbnail, allows the_post_thumbnail() 'name' => 'Image', 'desc' => 'Upload/Select an image.', 'type' => 'file', 'options' => array( 'url' => false, ), 'text' => array( 'add_upload_file_text' => 'Add Image' ), ) ); }; add_action( 'cmb2_admin_init', 'register_test_cpt_metabox' ); /* * Override the title/content field retrieval so CMB2 doesn't look in post-meta. */ function cmb2_override_post_title_display( $data, $post_id ) { return get_post_field( 'post_title', $post_id ); } function cmb2_override_post_content_display( $data, $post_id ) { return get_post_field( 'post_content', $post_id ); } add_filter( 'cmb2_override_post_title_meta_value', 'cmb2_override_post_title_display', 10, 2 ); add_filter( 'cmb2_override_post_content_meta_value', 'cmb2_override_post_content_display', 10, 2 ); /* * WP will handle the saving for us, so don't save title/content to meta. */ add_filter( 'cmb2_override_post_title_meta_save', '__return_true' ); add_filter( 'cmb2_override_post_content_meta_save', '__return_true' ); ================================================ FILE: modified-field-types/README.md ================================================ Modified Field Types ========== These are examples of using the built-in [CMB2 field-types](https://github.com/WebDevStudios/CMB2/wiki/Field-Types), but modifiying them with the [available parameters](https://github.com/WebDevStudios/CMB2/wiki/Field-Types#common-field-parameters). ================================================ FILE: modified-field-types/modify-button-text-for-file-type.php ================================================ add_field( array( 'name' => 'Image', 'desc' => 'Upload an image.', 'id' => '_jt_cmb2_image', 'type' => 'file', 'options' => array( 'add_upload_file_text' => __( 'Add or Upload Image', 'jt_cmb2' ), ), ) ); ================================================ FILE: modified-field-types/readonly-field-type.php ================================================ add_field( array( 'name' => 'Read Only', 'description' => 'The value of this input should be saved somewhere else.', 'id' => '_jtcmb2_readonly', 'type' => 'text', 'save_field' => false, // Otherwise CMB2 will end up removing the value. 'attributes' => array( 'readonly' => 'readonly', 'disabled' => 'disabled', ), ) ); ================================================ FILE: options-and-settings-pages/README.md ================================================ Options and Settings Pages ========== These snippets demonstrate how to create options page metaboxes or hook into genesis settings metaboxes. There are also examples for how you can retrieve an option, using `myprefix_get_option( 'test_text' )`. Obviously replace all instances of `myprefix` with a unique project-specific prefix. [Check these snippets out](https://github.com/WebDevStudios/CMB2-Snippet-Library/tree/master/helper-functions) if you're looking to modify the form output of the `cmb2_metabox_form` function. ================================================ FILE: options-and-settings-pages/add-cmb2-settings-to-other-settings-pages.php ================================================ hooks(); } return self::$instance; } /** * Initiate our hooks * @since 0.1.0 */ public function hooks() { add_action( 'cmb2_admin_init', array( $this, 'register_metabox' ) ); add_action( 'current_screen', array( $this, 'maybe_save' ) ); add_filter( 'admin_footer' , array( $this , 'maybe_hookup_fields' ), 2 /* Early before all scripts are output. */ ); } /** * Add the options metabox to the array of metaboxes * @since 0.1.0 */ function register_metabox() { $cmb = new_cmb2_box( array( 'id' => $this->metabox_id, 'hookup' => false, 'object_types' => array( 'options-page' ), ) ); // Set our CMB2 fields $cmb->add_field( array( 'name' => __( 'Test Text', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_text', 'type' => 'text', // 'default' => 'Default Text', ) ); $cmb->add_field( array( 'name' => __( 'Test Color Picker', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_colorpicker', 'type' => 'colorpicker', 'default' => '#bada55', ) ); } /** * Register our setting to WP * @since 0.1.0 */ public function maybe_save() { if ( empty( $_POST ) ) { return; } $url = wp_get_referer(); // Check if our screen id is in the referrer url. if ( false === strpos( $url, $this->screen_id ) ) { return; } // Hook into whitelist_options as we know it's only called if the default save-checks have finished. add_filter( 'whitelist_options', array( $this, 'save_our_options' ) ); } /** * Simply used as a options.php life-cycle hook to save our settings * (since there doesn't appear to be any proper hooks) * * @since 0.1.0 * * @param array $whitelist_options * * @return array */ public function save_our_options( $whitelist_options ) { $cmb = cmb2_get_metabox( $this->metabox_id, $this->key ); if ( $cmb ) { $hookup = new CMB2_hookup( $cmb ); if ( $hookup->can_save( 'options-page' ) ) { $cmb->save_fields( $this->key, 'options-page', $_POST ); } } // Our saving is done, so cleanup. remove_filter( 'whitelist_options', array( $this, 'save_our_options' ) ); return $whitelist_options; } /** * Maybe hookup our CMB2 fields. * * @since 0.1.0 */ public function maybe_hookup_fields() { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : (object) array( 'id' => null ); // Only show on our screen. if ( $this->screen_id !== $screen->id ) { return; } CMB2_hookup::enqueue_cmb_css(); $this->admin_page_display(); } /** * CMB2 fields output * Wile hide by default in the footer, then use JS to move it inside the form. Hacky, yep. * * @since 0.1.0 */ public function admin_page_display() { ?> {$field}; } throw new Exception( 'Invalid property: ' . $field ); } } /** * Helper function to get/return the Prefix_Add_CMB2_To_Settings_Page object * @since 0.1.0 * @return Prefix_Add_CMB2_To_Settings_Page object */ function myprefix_cmb2_on_settings() { return Prefix_Add_CMB2_To_Settings_Page::get_instance(); } /** * Wrapper function around cmb2_get_option * @since 0.1.0 * @param string $key Options array key * @param mixed $default Optional default value * @return mixed Option value */ function myprefix_get_option( $key = '', $default = false ) { if ( function_exists( 'cmb2_get_option' ) ) { // Use cmb2_get_option as it passes through some key filters. return cmb2_get_option( myprefix_cmb2_on_settings()->key, $key, $default ); } // Fallback to get_option if CMB2 is not loaded yet. $opts = get_option( myprefix_cmb2_on_settings()->key, $default ); $val = $default; if ( 'all' == $key ) { $val = $opts; } elseif ( is_array( $opts ) && array_key_exists( $key, $opts ) && false !== $opts[ $key ] ) { $val = $opts[ $key ]; } return $val; } // Get it started myprefix_cmb2_on_settings(); ================================================ FILE: options-and-settings-pages/custom-display-callback.php ================================================ 'yourprefix_theme_options_page', 'title' => 'Theme Options', 'object_types' => array( 'options-page' ), 'option_key' => 'yourprefix_theme_options', 'icon_url' => 'dashicons-palmtree', 'display_cb' => 'yourprefix_theme_options_page_output', // Override the options-page form output (CMB2_Hookup::options_page_output()). 'description' => 'Custom description', // Will be displayed via our display_cb. ) ); $cmb_options->add_field( array( 'name' => 'Site Background Color', 'desc' => 'field description (optional)', 'id' => 'bg_color', 'type' => 'colorpicker', 'default' => '#ffffff', ) ); } function yourprefix_theme_options_page_output( $hookup ) { // Output custom markup for the options-page. ?>
    cmb->prop( 'title' ) ) : ?>

    cmb->prop( 'title' ) ); ?>

    cmb->prop( 'description' ) ) : ?>

    cmb->prop( 'description' ) ); ?>

    options_page_metabox(); ?> cmb->prop( 'save_button' ) ), 'primary', 'submit-cmb' ); ?>
    hooks(); } return self::$instances[ $post_type ]; } /** * Constructor * * @since 0.1.0 * * @param string $post_type Post type slug. */ protected function __construct( $post_type ) { $this->post_type = $post_type; $this->admin_hook = sprintf( $this->admin_hook, $post_type ); $this->key = sprintf( $this->key, $post_type ); $this->metabox_id = sprintf( $this->metabox_id, $post_type ); } /** * Initiate our hooks * * @since 0.1.0 */ public function hooks() { add_action( 'init', array( $this, 'init' ) ); add_action( 'admin_menu', array( $this, 'admin_hooks' ) ); add_action( 'cmb2_admin_init', array( $this, 'init_metabox' ) ); } /** * Initiate admin hooks. * * @since 0.1.0 */ public function init() { // Add custom archive support for CPT. add_post_type_support( $this->post_type, 'genesis-cpt-archives-settings' ); } /** * Add admin hooks. * * @since 0.1.0 */ public function admin_hooks() { // Include CMB CSS in the head to avoid FOUC. add_action( "admin_print_styles-{$this->admin_hook}", array( 'CMB2_hookup', 'enqueue_cmb_css' ) ); // Hook into the genesis cpt settings save and add in the CMB2 sanitized values. add_filter( "sanitize_option_genesis-cpt-archive-settings-{$this->post_type}", array( $this, 'add_sanitized_values' ), 999 ); // Hook up our Genesis metabox. add_action( 'genesis_cpt_archives_settings_metaboxes', array( $this, 'add_meta_box' ) ); } /** * Hook up our Genesis metabox. * * @since 0.1.0 */ public function add_meta_box() { $cmb = $this->init_metabox(); add_meta_box( $cmb->cmb_id, $cmb->prop( 'title' ), array( $this, 'output_metabox' ), $this->admin_hook, $cmb->prop( 'context' ), $cmb->prop( 'priority' ) ); } /** * Output our Genesis metabox. * * @since 0.1.0 */ public function output_metabox() { $cmb = $this->init_metabox(); $cmb->show_form( $cmb->object_id(), $cmb->object_type() ); } /** * If saving the cpt settings option, add the CMB2 sanitized values. * * @since 0.1.0 * * @param array $new_value Array of values for the setting. * * @return array Updated array of values for the setting. */ public function add_sanitized_values( $new_value ) { if ( ! empty( $_POST ) ) { $cmb = $this->init_metabox(); $new_value = array_merge( $new_value, $cmb->get_sanitized_values( $_POST ) ); } return $new_value; } /** * Register our Genesis metabox and return the CMB2 instance. * * @since 0.1.0 * * @return CMB2 instance. */ public function init_metabox() { if ( null !== $this->cmb ) { return $this->cmb; } $this->cmb = cmb2_get_metabox( array( 'id' => $this->metabox_id, 'title' => __( 'I\'m a Genesis Archive Settings CMB2 metabox', 'myprefix' ), 'hookup' => false, // We'll handle ourselves. (add_sanitized_values()) 'cmb_styles' => false, // We'll handle ourselves. (admin_hooks()) 'context' => 'main', // Important for Genesis. // 'priority' => 'low', // Defaults to 'high'. 'object_types' => array( $this->admin_hook ), 'show_on' => array( // These are important, don't remove. 'key' => 'options-page', 'value' => array( $this->key ), ), ), $this->key, 'options-page' ); // Set our CMB2 fields. $this->cmb->add_field( array( 'name' => __( 'Test Text', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_text', 'type' => 'text', // 'default' => 'Default Text', ) ); $this->cmb->add_field( array( 'name' => __( 'Test Color Picker', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_colorpicker', 'type' => 'colorpicker', 'default' => '#bada55', ) ); return $this->cmb; } /** * Public getter method for retrieving protected/private variables * * @since 0.1.0 * * @param string $field Field to retrieve. * * @throws Exception Throws an exception if the field is invalid. * * @return mixed Field value or exception is thrown */ public function __get( $field ) { // Allowed fields to retrieve. if ( 'cmb' === $field ) { return $this->init_metabox(); } if ( in_array( $field, array( 'metabox_id', 'post_type', 'admin_hook', 'key' ), true ) ) { return $this->{$field}; } throw new Exception( 'Invalid property: ' . $field ); } } /** * Helper function to get/return the Myprefix_Genesis_CPT_Settings_Metabox object. * * @since 0.1.0 * * @param string $post_type Post type slug. * * @return Myprefix_Genesis_CPT_Settings_Metabox object */ function myprefix_genesis_cpt_settings( $post_type ) { return Myprefix_Genesis_CPT_Settings_Metabox::get_instance( $post_type ); } // Get it started. // myprefix_genesis_cpt_settings( 'custom-post-type-slug' ); ================================================ FILE: options-and-settings-pages/genesis-settings-metabox.php ================================================ hooks(); } return self::$instance; } /** * Constructor * * @since 0.1.0 */ protected function __construct() { } /** * Initiate our hooks * * @since 0.1.0 */ public function hooks() { add_action( 'admin_menu', array( $this, 'admin_hooks' ) ); add_action( 'cmb2_admin_init', array( $this, 'init_metabox' ) ); } /** * Add menu options page * * @since 0.1.0 */ public function admin_hooks() { // Include CMB CSS in the head to avoid FOUC. add_action( "admin_print_styles-{$this->admin_hook}", array( 'CMB2_hookup', 'enqueue_cmb_css' ) ); // Hook into the genesis cpt setttings save and add in the CMB2 sanitized values. add_filter( "sanitize_option_{$this->key}", array( $this, 'add_sanitized_values' ), 999 ); // Hook up our Genesis metabox. add_action( 'genesis_theme_settings_metaboxes', array( $this, 'add_meta_box' ) ); } /** * Hook up our Genesis metabox. * * @since 0.1.0 */ public function add_meta_box() { $cmb = $this->init_metabox(); add_meta_box( $cmb->cmb_id, $cmb->prop( 'title' ), array( $this, 'output_metabox' ), $this->admin_hook, $cmb->prop( 'context' ), $cmb->prop( 'priority' ) ); } /** * Output our Genesis metabox. * * @since 0.1.0 */ public function output_metabox() { $cmb = $this->init_metabox(); $cmb->show_form( $cmb->object_id(), $cmb->object_type() ); } /** * If saving the cpt settings option, add the CMB2 sanitized values. * * @since 0.1.0 * * @param array $new_value Array of values for the setting. * * @return array Updated array of values for the setting. */ public function add_sanitized_values( $new_value ) { if ( ! empty( $_POST ) ) { $cmb = $this->init_metabox(); $new_value = array_merge( $new_value, $cmb->get_sanitized_values( $_POST ) ); } return $new_value; } /** * Register our Genesis metabox and return the CMB2 instance. * * @since 0.1.0 * * @return CMB2 instance. */ public function init_metabox() { if ( null !== $this->cmb ) { return $this->cmb; } $this->cmb = cmb2_get_metabox( array( 'id' => $this->metabox_id, 'title' => __( 'I\'m a Genesis Settings CMB2 metabox', 'myprefix' ), 'hookup' => false, // We'll handle ourselves. (add_sanitized_values()) 'cmb_styles' => false, // We'll handle ourselves. (admin_hooks()) 'context' => 'main', // Important for Genesis. // 'priority' => 'low', // Defaults to 'high'. 'object_types' => array( $this->admin_hook ), 'show_on' => array( // These are important, don't remove. 'key' => 'options-page', 'value' => array( $this->key ), ), ), $this->key, 'options-page' ); // Set our CMB2 fields. $this->cmb->add_field( array( 'name' => __( 'Test Text', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_text', 'type' => 'text', // 'default' => 'Default Text', ) ); $this->cmb->add_field( array( 'name' => __( 'Test Color Picker', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_colorpicker', 'type' => 'colorpicker', 'default' => '#bada55', ) ); return $this->cmb; } /** * Public getter method for retrieving protected/private variables. * * @since 0.1.0 * * @param string $field Field to retrieve. * * @throws Exception Throws an exception if the field is invalid. * * @return mixed Field value or exception is thrown */ public function __get( $field ) { if ( 'cmb' === $field ) { return $this->init_metabox(); } // Allowed fields to retrieve. if ( in_array( $field, array( 'key', 'admin_page', 'metabox_id', 'admin_hook' ), true ) ) { return $this->{$field}; } throw new Exception( 'Invalid property: ' . $field ); } } /** * Helper function to get/return the Myprefix_Genesis_Settings_Metabox object * * @since 0.1.0 * * @return Myprefix_Genesis_Settings_Metabox object */ function myprefix_genesis_settings_metabox() { return Myprefix_Genesis_Settings_Metabox::get_instance(); } // Get it started. myprefix_genesis_settings_metabox(); ================================================ FILE: options-and-settings-pages/network-options-cmb.php ================================================ 'myprefix_network_option_metabox', 'title' => esc_html__( 'Network Setting', 'myprefix' ), 'object_types' => array( 'options-page' ), /* * The following parameters are specific to the options-page box * Several of these parameters are passed along to add_menu_page()/add_submenu_page(). */ 'option_key' => 'myprefix_network_options', // The option key and admin menu page slug. // 'icon_url' => 'dashicons-palmtree', // Menu icon. Only applicable if 'parent_slug' is left empty. // 'menu_title' => esc_html__( 'Options', 'myprefix' ), // Falls back to 'title' (above). // 'parent_slug' => 'themes.php', // Make options page a submenu item of the themes menu. // 'capability' => 'manage_options', // Cap required to view options-page. // 'position' => 1, // Menu position. Only applicable if 'parent_slug' is left empty. 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page. // 'display_cb' => false, // Override the options-page form output (CMB2_Hookup::options_page_output()). // 'save_button' => esc_html__( 'Save Theme Options', 'myprefix' ), // The text for the options-page save button. Defaults to 'Save'. ) ); /* * Options fields ids only need * to be unique within this box. * Prefix is not needed. */ $cmb_options->add_field( array( 'name' => __( 'Test Text', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_text', 'type' => 'text', 'default' => 'Default Text', ) ); $cmb_options->add_field( array( 'name' => __( 'Test Color Picker', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_colorpicker', 'type' => 'colorpicker', 'default' => '#bada55', ) ); } /** * Wrapper function around cmb2_get_option * @since 0.1.0 * @param string $key Options array key * @param mixed $default Optional default value * @return mixed Option value */ function myprefix_get_network_option( $key = '', $default = false ) { if ( function_exists( 'cmb2_get_option' ) ) { // Use cmb2_get_option as it passes through some key filters. return cmb2_get_option( 'myprefix_network_options', $key, $default ); } // Fallback to get_site_option if CMB2 is not loaded yet. $opts = get_site_option( 'myprefix_network_options', $default ); $val = $default; if ( 'all' == $key ) { $val = $opts; } elseif ( is_array( $opts ) && array_key_exists( $key, $opts ) && false !== $opts[ $key ] ) { $val = $opts[ $key ]; } return $val; } ================================================ FILE: options-and-settings-pages/non-cmb2-options-page.php ================================================ 'wporg_field_pill', 'class' => 'wporg_row', 'wporg_custom_data' => 'custom', ) ); } /** * Register our wporg_settings_init to the admin_init action hook. */ add_action( 'admin_init', 'wporg_settings_init' ); /** * Custom option and settings: * - callback functions */ /** * Developers section callback function. * * @param array $args The settings array, defining title, id, callback. */ function wporg_section_developers_callback( $args ) { ?>

    . * - the "class" key value is used for the "class" attribute of the containing the field. * Note: you can add custom key value pairs to be used inside your callbacks. * * @param array $args */ function wporg_field_pill_cb( $args ) { // Get the value of the setting we've registered with register_setting() $options = get_option( 'wporg_options' ); ?>

    options_page_tab_nav_output(); ?>
    'yourprefix_main_options_page', 'title' => esc_html__( 'Main Options', 'cmb2' ), 'object_types' => array( 'options-page' ), /* * The following parameters are specific to the options-page box * Several of these parameters are passed along to add_menu_page()/add_submenu_page(). */ 'option_key' => 'yourprefix_main_options', // The option key and admin menu page slug. // 'icon_url' => 'dashicons-palmtree', // Menu icon. Only applicable if 'parent_slug' is left empty. // 'menu_title' => esc_html__( 'Options', 'cmb2' ), // Falls back to 'title' (above). // 'parent_slug' => 'themes.php', // Make options page a submenu item of the themes menu. // 'capability' => 'manage_options', // Cap required to view options-page. // 'position' => 1, // Menu position. Only applicable if 'parent_slug' is left empty. // 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page. // 'display_cb' => false, // Override the options-page form output (CMB2_Hookup::options_page_output()). // 'save_button' => esc_html__( 'Save Theme Options', 'cmb2' ), // The text for the options-page save button. Defaults to 'Save'. // 'disable_settings_errors' => true, // On settings pages (not options-general.php sub-pages), allows disabling. // 'message_cb' => 'yourprefix_options_page_message_callback', ) ); /** * Options fields ids only need * to be unique within this box. * Prefix is not needed. */ $main_options->add_field( array( 'name' => esc_html__( 'Site Background Color', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => 'bg_color', 'type' => 'colorpicker', 'default' => '#ffffff', ) ); /** * Registers secondary options page, and set main item as parent. */ $secondary_options = new_cmb2_box( array( 'id' => 'yourprefix_secondary_options_page', 'title' => esc_html__( 'Secondary Options', 'cmb2' ), 'object_types' => array( 'options-page' ), 'option_key' => 'yourprefix_secondary_options', 'parent_slug' => 'yourprefix_main_options', ) ); $secondary_options->add_field( array( 'name' => esc_html__( 'Test Radio', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => 'radio', 'type' => 'radio', 'options' => array( 'option1' => esc_html__( 'Option One', 'cmb2' ), 'option2' => esc_html__( 'Option Two', 'cmb2' ), 'option3' => esc_html__( 'Option Three', 'cmb2' ), ), ) ); /** * Registers tertiary options page, and set main item as parent. */ $tertiary_options = new_cmb2_box( array( 'id' => 'yourprefix_tertiary_options_page', 'title' => esc_html__( 'Tertiary Options', 'cmb2' ), 'object_types' => array( 'options-page' ), 'option_key' => 'yourprefix_tertiary_options', 'parent_slug' => 'yourprefix_main_options', ) ); $tertiary_options->add_field( array( 'name' => esc_html__( 'Test Text Area for Code', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => 'textarea_code', 'type' => 'textarea_code', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_register_main_options_metabox' ); ================================================ FILE: options-and-settings-pages/options-pages-with-tabs-and-submenus.php ================================================ 'yourprefix_main_options_page', 'title' => 'Main Options', 'object_types' => array( 'options-page' ), 'option_key' => 'yourprefix_main_options', 'tab_group' => 'yourprefix_main_options', 'tab_title' => 'Main', ); // 'tab_group' property is supported in > 2.4.0. if ( version_compare( CMB2_VERSION, '2.4.0' ) ) { $args['display_cb'] = 'yourprefix_options_display_with_tabs'; } $main_options = new_cmb2_box( $args ); /** * Options fields ids only need * to be unique within this box. * Prefix is not needed. */ $main_options->add_field( array( 'name' => 'Site Background Color', 'desc' => 'field description (optional)', 'id' => 'bg_color', 'type' => 'colorpicker', 'default' => '#ffffff', ) ); /** * Registers secondary options page, and set main item as parent. */ $args = array( 'id' => 'yourprefix_secondary_options_page', 'menu_title' => 'Secondary Options', // Use menu title, & not title to hide main h2. 'object_types' => array( 'options-page' ), 'option_key' => 'yourprefix_secondary_options', 'parent_slug' => 'yourprefix_main_options', 'tab_group' => 'yourprefix_main_options', 'tab_title' => 'Secondary', ); // 'tab_group' property is supported in > 2.4.0. if ( version_compare( CMB2_VERSION, '2.4.0' ) ) { $args['display_cb'] = 'yourprefix_options_display_with_tabs'; } $secondary_options = new_cmb2_box( $args ); $secondary_options->add_field( array( 'name' => 'Test Radio', 'desc' => 'field description (optional)', 'id' => 'radio', 'type' => 'radio', 'options' => array( 'option1' => 'Option One', 'option2' => 'Option Two', 'option3' => 'Option Three', ), ) ); /** * Registers tertiary options page, and set main item as parent. */ $args = array( 'id' => 'yourprefix_tertiary_options_page', 'menu_title' => 'Tertiary Options', // Use menu title, & not title to hide main h2. 'object_types' => array( 'options-page' ), 'option_key' => 'yourprefix_tertiary_options', 'parent_slug' => 'yourprefix_main_options', 'tab_group' => 'yourprefix_main_options', 'tab_title' => 'Tertiary', ); // 'tab_group' property is supported in > 2.4.0. if ( version_compare( CMB2_VERSION, '2.4.0' ) ) { $args['display_cb'] = 'yourprefix_options_display_with_tabs'; } $tertiary_options = new_cmb2_box( $args ); $tertiary_options->add_field( array( 'name' => 'Test Text Area for Code', 'desc' => 'field description (optional)', 'id' => 'textarea_code', 'type' => 'textarea_code', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_register_main_options_metabox' ); /** * A CMB2 options-page display callback override which adds tab navigation among * CMB2 options pages which share this same display callback. * * @param CMB2_Options_Hookup $cmb_options The CMB2_Options_Hookup object. */ function yourprefix_options_display_with_tabs( $cmb_options ) { $tabs = yourprefix_options_page_tabs( $cmb_options ); ?>

    options_page_metabox(); ?> cmb->prop( 'save_button' ) ), 'primary', 'submit-cmb' ); ?>
    cmb->prop( 'tab_group' ); $tabs = array(); foreach ( CMB2_Boxes::get_all() as $cmb_id => $cmb ) { if ( $tab_group === $cmb->prop( 'tab_group' ) ) { $tabs[ $cmb->options_page_keys()[0] ] = $cmb->prop( 'tab_title' ) ? $cmb->prop( 'tab_title' ) : $cmb->prop( 'title' ); } } return $tabs; } ================================================ FILE: options-and-settings-pages/submenu-options-pages.php ================================================ 'yourprefix_options_submenu_page', 'title' => esc_html__( 'Page Options', 'cmb2' ), 'object_types' => array( 'options-page' ), /* * The following parameters are specific to the options-page box * Several of these parameters are passed along to add_menu_page()/add_submenu_page(). */ 'option_key' => 'yourprefix_page_options', // The option key and admin menu page slug. // 'icon_url' => '', // Menu icon. Only applicable if 'parent_slug' is left empty. // 'menu_title' => esc_html__( 'Options', 'cmb2' ), // Falls back to 'title' (above). 'parent_slug' => 'edit.php?post_type=page', // Make options page a submenu item of the themes menu. // 'capability' => 'manage_options', // Cap required to view options-page. // 'position' => 1, // Menu position. Only applicable if 'parent_slug' is left empty. // 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page. // 'display_cb' => false, // Override the options-page form output (CMB2_Hookup::options_page_output()). // 'save_button' => esc_html__( 'Save Theme Options', 'cmb2' ), // The text for the options-page save button. Defaults to 'Save'. // 'disable_settings_errors' => true, // On settings pages (not options-general.php sub-pages), allows disabling. // 'message_cb' => 'yourprefix_options_page_message_callback', ) ); $cmb->add_field( array( 'name' => esc_html__( 'Background Color for Pages', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => 'bg_color', 'type' => 'colorpicker', 'default' => '#ffffff', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_register_options_submenu_for_page_post_type' ); /** * Hook in and register a submenu options page for the Appearance menu. */ function yourprefix_register_options_submenu_appearance_menu() { /** * Registers options page menu item and form. */ $cmb_options = new_cmb2_box( array( 'id' => 'yourprefix_options_submenu_appearance_menu', 'title' => esc_html__( 'Appearance Options', 'cmb2' ), 'object_types' => array( 'options-page' ), /* * The following parameters are specific to the options-page box * Several of these parameters are passed along to add_menu_page()/add_submenu_page(). */ 'option_key' => 'yourprefix_theme_appearance_options', // The option key and admin menu page slug. // 'icon_url' => '', // Menu icon. Only applicable if 'parent_slug' is left empty. // 'menu_title' => esc_html__( 'Options', 'cmb2' ), // Falls back to 'title' (above). 'parent_slug' => 'themes.php', // Make options page a submenu item of the themes menu. // 'capability' => 'manage_options', // Cap required to view options-page. // 'position' => 1, // Menu position. Only applicable if 'parent_slug' is left empty. // 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page. // 'display_cb' => false, // Override the options-page form output (CMB2_Hookup::options_page_output()). // 'save_button' => esc_html__( 'Save Theme Options', 'cmb2' ), // The text for the options-page save button. Defaults to 'Save'. // 'disable_settings_errors' => true, // On settings pages (not options-general.php sub-pages), allows disabling. // 'message_cb' => 'yourprefix_options_page_message_callback', ) ); /** * Options fields ids only need * to be unique within this box. * Prefix is not needed. */ $cmb_options->add_field( array( 'name' => esc_html__( 'Site Background Color', 'cmb2' ), 'desc' => esc_html__( 'field description (optional)', 'cmb2' ), 'id' => 'bg_color', 'type' => 'colorpicker', 'default' => '#ffffff', ) ); } add_action( 'cmb2_admin_init', 'yourprefix_register_options_submenu_appearance_menu' ); ================================================ FILE: options-and-settings-pages/theme-options-cmb.php ================================================ 'myprefix_option_metabox', 'title' => esc_html__( 'Site Options', 'myprefix' ), 'object_types' => array( 'options-page' ), /* * The following parameters are specific to the options-page box * Several of these parameters are passed along to add_menu_page()/add_submenu_page(). */ 'option_key' => 'myprefix_options', // The option key and admin menu page slug. // 'icon_url' => 'dashicons-palmtree', // Menu icon. Only applicable if 'parent_slug' is left empty. // 'menu_title' => esc_html__( 'Options', 'myprefix' ), // Falls back to 'title' (above). // 'parent_slug' => 'themes.php', // Make options page a submenu item of the themes menu. // 'capability' => 'manage_options', // Cap required to view options-page. // 'position' => 1, // Menu position. Only applicable if 'parent_slug' is left empty. // 'admin_menu_hook' => 'network_admin_menu', // 'network_admin_menu' to add network-level options page. // 'display_cb' => false, // Override the options-page form output (CMB2_Hookup::options_page_output()). // 'save_button' => esc_html__( 'Save Theme Options', 'myprefix' ), // The text for the options-page save button. Defaults to 'Save'. ) ); /* * Options fields ids only need * to be unique within this box. * Prefix is not needed. */ $cmb_options->add_field( array( 'name' => __( 'Test Text', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_text', 'type' => 'text', 'default' => 'Default Text', ) ); $cmb_options->add_field( array( 'name' => __( 'Test Color Picker', 'myprefix' ), 'desc' => __( 'field description (optional)', 'myprefix' ), 'id' => 'test_colorpicker', 'type' => 'colorpicker', 'default' => '#bada55', ) ); } /** * Wrapper function around cmb2_get_option * @since 0.1.0 * @param string $key Options array key * @param mixed $default Optional default value * @return mixed Option value */ function myprefix_get_option( $key = '', $default = false ) { if ( function_exists( 'cmb2_get_option' ) ) { // Use cmb2_get_option as it passes through some key filters. return cmb2_get_option( 'myprefix_options', $key, $default ); } // Fallback to get_option if CMB2 is not loaded yet. $opts = get_option( 'myprefix_options', $default ); $val = $default; if ( 'all' == $key ) { $val = $opts; } elseif ( is_array( $opts ) && array_key_exists( $key, $opts ) && false !== $opts[ $key ] ) { $val = $opts[ $key ]; } return $val; } ================================================ FILE: user-meta-and-settings/README.md ================================================ User Meta and Settings ========== These are examples of [using CMB2 to generate user fields](https://github.com/WebDevStudios/CMB2/wiki/Adding-metaboxes-to-user-profile). ================================================ FILE: widgets/widget-example.php ================================================ widget_slug, esc_html__( 'CMB2 Widget Boilerplate Title', 'your-textdomain' ), array( 'classname' => $this->widget_slug, 'customize_selective_refresh' => true, 'description' => esc_html__( 'A CMB2 widget boilerplate description.', 'your-textdomain' ), ) ); self::$defaults = array( 'title' => esc_html__( 'CMB2 Widget Title', 'your-textdomain' ), 'image' => '', 'desc' => '', 'color' => '#bada55', ); $this->cmb2_fields = array( array( 'name' => 'Title', 'id_key' => 'title', 'id' => 'title', 'type' => 'text', ), array( 'name' => 'Image', 'desc' => 'Upload an image or enter an URL.', 'id_key' => 'image', 'id' => 'image', 'type' => 'file', 'options' => array( 'url' => false ), 'text' => array( 'add_upload_file_text' => 'Upload An Image' ), ), array( 'name' => 'Description', 'id_key' => 'desc', 'id' => 'desc', 'type' => 'textarea', ), array( 'name' => 'Color', 'id_key' => 'color', 'id' => 'color', 'type' => 'colorpicker', ), ); add_action( 'save_post', array( $this, 'flush_widget_cache' ) ); add_action( 'deleted_post', array( $this, 'flush_widget_cache' ) ); add_action( 'switch_theme', array( $this, 'flush_widget_cache' ) ); add_shortcode( self::$shortcode, array( __CLASS__, 'get_widget' ) ); } /** * Delete this widget's cache. * * Note: Could also delete any transients * delete_transient( 'some-transient-generated-by-this-widget' ); */ public function flush_widget_cache() { wp_cache_delete( $this->id, 'widget' ); } /** * Front-end display of widget. * * @param array $args The widget arguments set up when a sidebar is registered. * @param array $instance The widget settings as set by user. */ public function widget( $args, $instance ) { echo self::get_widget( array( 'args' => $args, 'instance' => $instance, 'cache_id' => $this->id, // whatever the widget id is ) ); } /** * Return the widget/shortcode output * * @param array $atts Array of widget/shortcode attributes/args * @return string Widget output */ public static function get_widget( $atts ) { $widget = ''; // Set up default values for attributes $atts = shortcode_atts( array( // Ensure variables 'instance' => array(), 'before_widget' => '', 'after_widget' => '', 'before_title' => '', 'after_title' => '', 'cache_id' => '', 'flush_cache' => isset( $_GET['delete-trans'] ), // Check for cache-buster ), isset( $atts['args'] ) ? (array) $atts['args'] : array(), self::$shortcode ); $instance = shortcode_atts( self::$defaults, ! empty( $atts['instance'] ) ? (array) $atts['instance'] : array(), self::$shortcode ); /* * If cache_id is not passed, we're not using the widget (but the shortcode), * so generate a hash cache id from the shortcode arguments */ if ( empty( $atts['cache_id'] ) ) { $atts['cache_id'] = md5( serialize( $atts ) ); } // Get from cache unless being requested not to $widget = ! $atts['flush_cache'] ? wp_cache_get( $atts['cache_id'], 'widget' ) : ''; // If $widget is empty, rebuild our cache if ( empty( $widget ) ) { $widget = ''; // Before widget hook $widget .= $atts['before_widget']; $widget .= '
    '; // Title $widget .= ( $instance['title'] ) ? $atts['before_title'] . esc_html( $instance['title'] ) . $atts['after_title'] : ''; $widget .= wpautop( wp_kses_post( $instance['desc'] ) ); $widget .= '
    '; // After widget hook $widget .= $atts['after_widget']; wp_cache_set( $atts['cache_id'], $widget, 'widget', WEEK_IN_SECONDS ); } return $widget; } /** * Update form values as they are saved. * * @param array $new_instance New settings for this instance as input by the user. * @param array $old_instance Old settings for this instance. * @return array Settings to save or bool false to cancel saving. */ public function update( $new_instance, $old_instance ) { $this->flush_widget_cache(); $sanitized = $this->cmb2( true )->get_sanitized_values( $new_instance ); return $sanitized; } /** * Back-end widget form with defaults. * * @param array $instance Current settings. */ public function form( $instance ) { // If there are no settings, set up defaults $this->_instance = wp_parse_args( (array) $instance, self::$defaults ); $cmb2 = $this->cmb2(); $cmb2->object_id( $this->option_name ); CMB2_hookup::enqueue_cmb_css(); CMB2_hookup::enqueue_cmb_js(); $cmb2->show_form(); } /** * Creates a new instance of CMB2 and adds some fields * @since 0.1.0 * @return CMB2 */ public function cmb2( $saving = false ) { // Create a new box in the class $cmb2 = new CMB2( array( 'id' => $this->option_name .'_box', // Option name is taken from the WP_Widget class. 'hookup' => false, 'show_on' => array( 'key' => 'options-page', // Tells CMB2 to handle this as an option 'value' => array( $this->option_name ) ), ), $this->option_name ); foreach ( $this->cmb2_fields as $field ) { if ( ! $saving ) { $field['id'] = $this->get_field_name( $field['id'] ); } $field['default_cb'] = array( $this, 'default_cb' ); $cmb2->add_field( $field ); } return $cmb2; } /** * Sets the field default, or the field value. * * @param array $field_args CMB2 field args array * @param CMB2_Field $field CMB2 Field object. * * @return mixed Field value. */ public function default_cb( $field_args, $field ) { return isset( $this->_instance[ $field->args( 'id_key' ) ] ) ? $this->_instance[ $field->args( 'id_key' ) ] : null; } } /** * Register this widget with WordPress. */ function register_wds_widget_boilerplate() { register_widget( 'CMB2_Widget_Boilerplate' ); } add_action( 'widgets_init', 'register_wds_widget_boilerplate' );