Showing preview only (247K chars total). Download the full file or copy to clipboard to get everything.
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
================================================
<?php
/**
* By default, when fetching the value for the file_list field via the REST API, the order is
* obliterated when the data is converted to JSON via json_encode. This replaces the default value
* of the file_list field with an array of arrays, which will preserve the orginal order.
*
* @see https://github.com/CMB2/CMB2/issues/1150
*/
/**
* Returns an array of file arrays with id/url paramaters, which preserves the original file ordering.
*
* @param mixed $value The value from CMB2_Field::get_data()
* @param CMB2_Field $field The field object.
*/
function yourprefix_cmb2_ordered_file_list_array_in_api( $value, $field ) {
if ( ! 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;
}
/**
* 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
================================================
<?php
/**
* Allow metabox to show up everywhere except a specified list of page IDs.
* @link https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-show_on-filters#example-exclude-on-ids wiki
*/
$cmb = new_cmb2_box( array(
'id' => '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
================================================
<?php
/**
* Remove metabox from appearing on post new screens before the post has been saved.
* Can also add additional screens to exclude via the `'exclude_from'` property.
* @link https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-show_on-filters#example-exclude-on-new-post-screens wiki
*/
$cmb = new_cmb2_box( array(
'id' => '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
================================================
<?php
/**
* This allows you to specify one or more taxonomies, and for each taxonomy one or more terms.
* If a post is tagged one of those terms, this metabox shows up on its Edit screen.
* @link https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-show_on-filters#example-taxonomy-show_on-filter wiki
*/
$cmb = new_cmb2_box( array(
'id' => '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( '<xmp>: '. print_r( 'show it', true ) .'</xmp>' );
// Ok, show this metabox
return true;
}
}
}
}
return false;
}
================================================
FILE: conditional-display/show-if-matching-meta-value.php
================================================
<?php
/**
* Only show contact metabox if status set to external.
* @link https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-show_on-filters#examples wiki
*/
add_action( 'cmb2_admin_init', 'cmb2_register_conditional_metabox' );
/**
* Hook in and add a demo metabox. Can only happen on the 'cmb2_admin_init' or 'cmb2_init' hook.
*/
function cmb2_register_conditional_metabox() {
/**
* Metabox to save the 'status' where 'Internal' is the default.
*/
$cmb = new_cmb2_box( array(
'id' => '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
================================================
<?php
/**
* Exclude metabox on non top level posts
* @link https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-show_on-filters#example-exclude-on-non-top-level-posts wiki
*/
$cmb = new_cmb2_box( array(
'id' => '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
================================================
<?php
/*
* Plugin Name: CMB2 Custom Field Type - Address
* Description: Makes available an 'address' CMB2 Custom Field Type. Based on https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-field-types#example-4-multiple-inputs-one-field-lets-create-an-address-field
* Author: jtsternberg
* Author URI: http://dsgnwrks.pro
* Version: 0.1.0
*/
/**
* Template tag for displaying an address from the CMB2 address field type (on the front-end)
*
* @since 0.1.0
*
* @param string $metakey The 'id' of the 'address' field (the metakey for get_post_meta)
* @param integer $post_id (optional) post ID. If using in the loop, it is not necessary
*/
function jt_cmb2_address_field( $metakey, $post_id = 0 ) {
echo jt_cmb2_get_address_field( $metakey, $post_id );
}
/**
* Template tag for returning an address from the CMB2 address field type (on the front-end)
*
* @since 0.1.0
*
* @param string $metakey The 'id' of the 'address' field (the metakey for get_post_meta)
* @param integer $post_id (optional) post ID. If using in the loop, it is not necessary
*/
function jt_cmb2_get_address_field( $metakey, $post_id = 0 ) {
$post_id = $post_id ? $post_id : get_the_ID();
$address = get_post_meta( $post_id, $metakey, 1 );
// Set default values for each address key
$address = wp_parse_args( $address, array(
'address-1' => '',
'address-2' => '',
'city' => '',
'state' => '',
'zip' => '',
'country' => '',
) );
$output = '<div class="cmb2-address">';
$output .= '<p><strong>Address:</strong> ' . esc_html( $address['address-1'] ) . '</p>';
if ( $address['address-2'] ) {
$output .= '<p>' . esc_html( $address['address-2'] ) . '</p>';
}
$output .= '<p><strong>City:</strong> ' . esc_html( $address['city'] ) . '</p>';
$output .= '<p><strong>State:</strong> ' . esc_html( $address['state'] ) . '</p>';
$output .= '<p><strong>Zip:</strong> ' . esc_html( $address['zip'] ) . '</p>';
$output .= '</div><!-- .cmb2-address -->';
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
================================================
<?php
/**
* Handles 'address' custom field type.
*/
class CMB2_Render_Address_Field extends CMB2_Type_Base {
/**
* List of states. To translate, pass array of states in the 'state_list' field param.
*
* @var array
*/
protected static $state_list = array( 'AL' => '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 .= '<option value="' . $abrev . '" ' . selected( $value['state'], $abrev, false ) . '>' . $state . '</option>';
}
}
$state_label = 'State';
if ( $this->field->args( 'do_country' ) ) {
$state_label .= '/Province';
}
ob_start();
// Do html.
?>
<div><p><label for="<?php echo $this->_id( '_address_1', false ); ?>"><?php echo esc_html( $this->_text( 'address_address_1_text', 'Address 1' ) ); ?></label></p>
<?php echo $this->types->input( array(
'name' => $this->_name( '[address-1]' ),
'id' => $this->_id( '_address_1' ),
'value' => $value['address-1'],
'desc' => '',
) ); ?>
</div>
<div><p><label for="<?php echo $this->_id( '_address_2', false ); ?>'"><?php echo esc_html( $this->_text( 'address_address_2_text', 'Address 2' ) ); ?></label></p>
<?php echo $this->types->input( array(
'name' => $this->_name( '[address-2]' ),
'id' => $this->_id( '_address_2' ),
'value' => $value['address-2'],
'desc' => '',
) ); ?>
</div>
<div style="overflow: hidden;">
<div class="alignleft"><p><label for="<?php echo $this->_id( '_city', false ); ?>'"><?php echo esc_html( $this->_text( 'address_city_text', 'City' ) ); ?></label></p>
<?php echo $this->types->input( array(
'class' => 'cmb_text_small',
'name' => $this->_name( '[city]' ),
'id' => $this->_id( '_city' ),
'value' => $value['city'],
'desc' => '',
) ); ?>
</div>
<div class="alignleft"><p><label for="<?php echo $this->_id( '_state', false ); ?>'"><?php echo esc_html( $this->_text( 'address_state_text', $state_label ) ); ?></label></p>
<?php if ( $this->field->args( 'do_country' ) ) : ?>
<?php echo $this->types->input( array(
'class' => 'cmb_text_small',
'name' => $this->_name( '[state]' ),
'id' => $this->_id( '_state' ),
'value' => $value['state'],
'desc' => '',
) ); ?>
<?php else : ?>
<?php echo $this->types->select( array(
'name' => $this->_name( '[state]' ),
'id' => $this->_id( '_state' ),
'options' => $state_options,
'desc' => '',
) ); ?>
<?php endif; ?>
</div>
<div class="alignleft"><p><label for="<?php echo $this->_id( '_zip', false ); ?>'"><?php echo esc_html( $this->_text( 'address_zip_text', 'Zip' ) ); ?></label></p>
<?php echo $this->types->input( array(
'class' => 'cmb_text_small',
'name' => $this->_name( '[zip]' ),
'id' => $this->_id( '_zip' ),
'value' => $value['zip'],
'type' => 'number',
'desc' => '',
) ); ?>
</div>
</div>
<?php if ( $this->field->args( 'do_country' ) ) : ?>
<div class="clear"><p><label for="<?php echo $this->_id( '_country', false ); ?>'"><?php echo esc_html( $this->_text( 'address_country_text', 'Country' ) ); ?></label></p>
<?php echo $this->types->input( array(
'name' => $this->_name( '[country]' ),
'id' => $this->_id( '_country' ),
'value' => $value['country'],
'desc' => '',
) ); ?>
</div>
<?php endif; ?>
<p class="clear">
<?php echo $this->_desc();?>
</p>
<?php
// grab the data from the output buffer.
return $this->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
================================================
<?php
/**
* Associates a WP menu with a post, and provides links between the post/menu editing interfaces.
* Screenshots:
* - metabox: http://b.ustin.co/Gxhf
* - widget: http://b.ustin.co/lD30
*/
function cmb2_register_post_menu_box() {
$menu_assoc = CMB2_Post_Menu_Association::get_instance();
$menu_assoc->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';
?>
<a href="<?php echo esc_url( $url ); ?>"><?php echo $link_title; ?></a>
<p class="cmb2-metabox-description explain-widget-necessary"><strong>Note:</strong> In order for this menu to display, you will need to ensure the "Associated Post Menu" widget is placed in the <a href="<?php echo admin_url( 'widgets.php' ); ?>">widget area</a> for this template.</p>
<?php if ( ! $script_added ) : ?>
<script type="text/javascript">
if ( '#<?php echo $this->metabox_id; ?>' === window.location.hash ) {
var el = document.getElementById( '<?php echo $this->metabox_id; ?>' );
el.className += ' post-menu-box-highlighted';
}
</script>
<style type="text/css">
.post-menu-box-highlighted {
box-shadow: 0 0 10px 5px rgba(226, 73, 73, 0.28);
}
#side-sortables #<?php echo $this->metabox_id; ?> .explain-widget-necessary {
padding-bottom: 0;
padding-top: 10px;
margin-bottom: -15px;
}
</style>
<?php endif;
$script_added = true;
}
public function associate_menu_post_message() {
if ( empty( $_REQUEST['post_association'] ) || ! $this->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: <strong><a href="%s">%s</a></strong> (%d)' );
} else {
$this->associate_menu_message( $_REQUEST['post_association'], 'This Menu is set as the %s Menu for: <strong><a href="%s">%s</a></strong> (%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(
'<div id="message" class="updated"><p>%s</p></div>',
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.
?>
<div class="nav-menu-widget-form-controls">
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">Fallback Title:</label>
<input type="text" class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo esc_attr( $title ); ?>"/>
</p>
</div>
<?php
}
}
function cmb2_register_post_menu_widget() {
register_widget('CMB2_Post_Menu_Widget');
}
add_action( 'widgets_init', 'cmb2_register_post_menu_widget' );
================================================
FILE: custom-field-types/autocomplete-field-type.php
================================================
<?php
/*
* Plugin Name: CMB2 Custom Field Type - Autocomplete
* Description: Makes available an autocomplete custom field type.
* Author: johnsonpaul1014
* Version: 1.0.0
*/
/**
*
* It is a little complex but is very flexible, and it is a great option when you have
* way too many things to put in a select.
*
* It uses a hidden field for the CMB2 data, and puts the value from the input used for the
* autocomplete in the hidden field on blur of the autocomplete field so it always gets populated.
*
* There are two types available: options pre-built and one that uses a remote source.
* To use the first option, simply build it like a select with the standard CMB2 "options" argument.
* For a remote source, you will use the "source" argument that corresponds to an AJAX function.
* Then, you pass in a "matching_function" to look up the selected autocomplete value using the
* CMB2 field value.
*
* It can also be used as a repeatable field if a "repeatable_class" argument is passed when
* constructing the field. This argument is necessary to allow for mapping the autocomplete
* jQuery UI calls to the appropriate field.
*
* The example fields in this plugin demonstrate all types: pre-built single field,
* pre-built repeatable field, remote single field and remote repeatable field.
*
*/
/**
* Define the metabox and field configurations.
*/
function autocomplete_cmb2_meta_boxes() {
// Start with an underscore to hide fields from custom fields list
$prefix = '_autocomplete_cmb2_';
$cmb = new_cmb2_box( array(
'id' => '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 '<input size="50"'.(empty($repeatable_class) ? ' id="'.$id.'"' : '') . ' value="'.htmlspecialchars($value).'"'.
(!empty($repeatable_class) ? ' class="'.$repeatable_class.'"' : '').'/>';
if (!$field_object->args['repeatable'] && isset($field_object->args['desc'])) {
echo '<p class="cmb2-metabox-description">'.$field_object->args['desc'].'</p>';
}
// Now, set up the script.
?>
<script>
jQuery(document).ready(function($) {
var options = [];
var nameToValue = [];
<?php
if (!empty($options)) {
foreach ($options as $option) {
echo "options.push('".addcslashes($option['name'], "'")."');\r\n";
echo "nameToValue['".addcslashes($option['name'], "'")."'] = '".$option['value']."';\r\n";
}
}
if (!empty($repeatable_class)) { ?>
$('.<?php echo $repeatable_class; ?>').each(function(i, el) {
if (typeof $(this).data('ui-autocomplete') === 'undefined') {
$(this).autocomplete({
<?php } else { ?>
$('#<?php echo $id; ?>').autocomplete({
<?php } ?>
source: <?php if (empty($options)) { ?>
function(request, response) {
$.ajax(
{url: ajaxurl,
data: {
action: '<?php echo $source; ?>',
q: request.term
},
success: function(data) {
// Set up options and name to value for this returned set.
var values = $.parseJSON(data);
options = [];
nameToValue = [];
for (optionI in values) {
var option = values[optionI];
options.push(option.name);
nameToValue[option.name] = option.value;
}
response(options);
}
});
} <?php } else {
echo 'options';
} ?>
});
// Also set up a blur function to update the ID.
$(<?php echo empty($repeatable_class) ? "'#".$id."'" : 'this'; ?>).blur(function(e) {
$(this).prev('input').val(nameToValue[$(this).val()]);
});
<?php
if (!empty($repeatable_class)) { ?>
}
});
<?php
}
?>
});
</script>
<?php
}
/**
* Gets post options using a post type
*
* @param mixed $post_type array or string of post type(s)
* @param boolean $include_empty whether or not to include an empty value
* @param string $like_test used to query for posts like a certain value
* @return array
*/
function autocomplete_cmb2_get_post_options_using_post_type($post_type, $include_empty = false, $like_test = '%%') {
// Use a query instead of "get_posts" to save on a ton of memory.
global $wpdb;
if (is_array($post_type)) {
$post_type_query = "('".implode("', '", $post_type)."')";
} else {
$post_type_query = "('".$post_type."')";
}
$posts = $wpdb->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
================================================
<?php
/*
* Button field type
* Screenshot: https://github.com/CMB2/CMB2/assets/1098900/c8e1aa00-1947-480d-8c30-bd58f5e9dcbc
*/
/**
* Example field registration:
*
* function yourprefix_register_demo_metabox() {
*
* $cmb_demo = new_cmb2_box( array(
* 'id' => '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
================================================
<?php
/*
Plugin Name: CMB2 Dashicon Radio Field
Description: https://github.com/modemlooper/cmb2-dashicon-radio
Version: 1.0.0
Author: modemlooper
Author URI: http://twitter.com/modemlooper
License: GPL-2.0+
*/
/**
* Custom render for dashicon_radio field
*
* @param object $field
* @param string $escaped_value
* @param string $object_id
* @param string $object_type
* @param object $field_type_object
* @return void
*/
function ml_cmb2_render_dashicon_radio_callback( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
add_filter( 'cmb2_list_input_attributes', 'ml_cmb2_dashicon_radio_attributes', 10, 4 );
$field->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'] = '<span class="dashicons ' . $args['value'] . '"></span> ' . $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;
?>
<style type="text/css" media="screen">
.cmb-type-dashicon-radio .cmb-td {
height: 200px;
overflow: scroll;
background-color: rgb(240, 240, 240);
}
.cmb-type-dashicon-radio .cmb2-radio-list {
padding: 10px;
}
.cmb-type-dashicon-radio li {
display: inline-block;
min-width: 222px;
}
</style>
<?php
}
/**
* Returns array of dashicon data
*
* @return array
*/
function ml_cmb2_dashicons_return_array() {
$icons = array(
'dashicons-menu' => __( '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
================================================
<?php
/**
* CMB2 Default Category field/metabox
*
* @package CMB2 Default Category field/metabox
*/
/**
* Adds a custom field type which uses the WordPress default post-categories metabox.
*
* @param object $field The CMB2_Field type object.
* @param string $value The saved (and escaped) value.
* @param int $object_id The current post ID.
* @param string $object_type The current object type.
* @return void
*/
function cmb2_render_default_categories_field_type( $field, $escaped_value, $object_id, $object_type ) {
$taxonomy = $field->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
================================================
<?php
/**
* CMB2 Default Tags field/metabox
*
* @package CMB2 Default Tags field/metabox
*/
/**
* Adds a custom field type which uses the WordPress default post-tags metabox.
*
* @param object $field The CMB2_Field type object.
* @param string $value The saved (and escaped) value.
* @param int $object_id The current post ID.
* @param string $object_type The current object type.
* @return void
*/
function cmb2_render_default_tags_field_type( $field, $escaped_value, $object_id, $object_type ) {
$taxonomy = $field->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() {
?>
<script type="text/javascript">
jQuery( function( $ ) {
window.tagBox && window.tagBox.init();
});
</script>
<?php
}
function cmb2_default_tags_let_wp_save( $null, $a, $field_args, $field ) {
if ( 'default_tags' === $field->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
================================================
<?php
/*
* Plugin Name: CMB2 Custom Field Type - Form Fields
* Description: Makes available a 'formfield' CMB2 Custom Field Type. Based on https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-field-types#example-4-multiple-inputs-one-field-lets-create-an-formfield-field
* Author: jtsternberg
* Author URI: http://dsgnwrks.pro
* Version: 0.1.0
*
* Example use with translation of strings:
*
* $cmb_demo->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 .= "<option value=\"{$type}\" {$selected}>{$label}</option>";
}
?>
<table>
<tr>
<td>
<label for="<?php echo $field_type->_id( '_formfield_1' ); ?>"><?php echo esc_html( $field_type->_text( 'formfield_field_id_label', 'Field ID' ) ); ?></label>
<?php
echo $field_type->input( array(
'name' => $field_type->_name( '[id]' ),
'id' => $field_type->_id( '_id' ),
'value' => $value['id'],
'desc' => ''
) )
?>
</td>
</tr>
<tr>
<td>
<label for="<?php echo $field_type->_id( '_formfield_1' ); ?>"><?php echo esc_html( $field_type->_text( 'formfield_field_label_label', 'Field label' ) ); ?></label>
<?php
echo $field_type->input( array(
'name' => $field_type->_name( '[label]' ),
'id' => $field_type->_id( '_label' ),
'value' => $value['label'],
'desc' => ''
) )
?>
</td>
</tr>
<tr>
<td>
<label for="<?php echo $field_type->_id( '_formfield_1' ); ?>"><?php echo esc_html( $field_type->_text( 'formfield_field_type_label', 'Field type' ) ); ?></label>
<?php
echo $field_type->select( array(
'name' => $field_type->_name( '[type]' ),
'id' => $field_type->_id( '_type' ),
'options' => $types,
'desc' => ''
) )
?>
</td>
</tr>
<tr>
<td>
<label for="<?php echo $field_type->_id( '_formfield_1' ); ?>"><?php echo esc_html( $field_type->_text( 'formfield_field_size_label', 'Field Size' ) ); ?></label>
<?php
echo $field_type->input( array(
'name' => $field_type->_name( '[size]' ),
'id' => $field_type->_id( '_size' ),
'value' => $value['size'],
'desc' => ''
) )
?>
</td>
</tr>
</table>
<?php if ( $field_type->_desc() ) : ?>
<p class="clear">
<?php echo $field_type->_desc();?>
</p>
<?php endif;
}
add_filter( 'cmb2_render_formfield', 'jt_cmb2_render_formfield_field_callback', 10, 5 );
/**
* The following snippets are required for allowing the formfield field
* to work as a repeatable field, or in a repeatable group
*/
function jt_cmb2_sanitize_formfield_field( $check, $meta_value, $object_id, $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 ) {
$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
================================================
<?php
/**
* CMB2 Multicheck by Post Type
*
* @package CMB2 Default Tags field/metabox
* @author Daniele Mte90 Scasciafratte
*/
add_action( 'cmb2_render_multicheck_posttype', 'ds_cmb_render_multicheck_posttype', 10, 5 );
function ds_cmb_render_multicheck_posttype( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
if ( version_compare( CMB2_VERSION, '2.2.2', '>=' ) ) {
$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
================================================
<?php
/**
* CMB2 Multicheck by Title
*
* @package CMB2 Default Tags field/metabox
* @author Daniele Mte90 Scasciafratte
*/
/*
// Example
$array[ 'id_of_the_key' ] = __( 'ID of the key' );
$fields[ 'Title of the section' ] = $array;
$cmb->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 '<h2>'.$title.'</h2>';
$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
================================================
<?php
//By Daniele Mte90 Scasciafratte
//Based on https://github.com/WebDevStudios/CMB2-Post-Search-field
//That field have a list separated by a comma of post id and allow to sort and remove
//render post_list
function cmb2_post_list_render_field( $field, $escaped_value, $object_id, $object_type, $field_type ) {
$select_type = $field->args( 'select_type' );
echo $field_type->input( array(
'autocomplete' => 'off',
'style' => 'display:none'
) );
echo '<ul style="cursor:move">';
if ( !empty( $field->escaped_value ) ) {
$list = explode( ',', $field->escaped_value );
foreach ( $list as $value ) {
echo '<li data-id="' . trim( $value ) . '"><b>' . __( 'Title' ) . ':</b> ' . get_the_title( $value );
echo '<div title="' . __( 'Remove' ) . '" style="color: #999;margin: -0.1em 0 0 2px; cursor: pointer;" class="cmb-post-list-remove dashicons dashicons-no"></div>';
echo '</li>';
}
}
echo '</ul>';
// 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' );
}
?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
'use strict';
$('.cmb-type-post-list').on('click', '.cmb-post-list-remove', function () {
var ids = $('.cmb-type-post-list.cmb2-id-<?php echo str_replace( '_', '-', sanitize_html_class( $field->args( 'id' ) ) ) ?>').find('.cmb-td input[type="text"]').val();
var $choosen = $(this);
if (ids.indexOf(',') !== -1) {
ids = ids.split(',');
var loopids = ids.slice(0);
$.each(loopids, function (index, value) {
var cleaned = value.trim().toString();
if (String($choosen.parent().data('id')) === cleaned) {
$choosen.parent().remove();
ids.splice(index, 1);
}
});
$('.cmb-type-post-list.cmb2-id-<?php echo str_replace( '_', '-', sanitize_html_class( $field->args( 'id' ) ) ) ?>').find('.cmb-td input[type="text"]').val(ids.join(','));
} else {
$choosen.parent().remove();
$('.cmb-type-post-list.cmb2-id-<?php echo str_replace( '_', '-', sanitize_html_class( $field->args( 'id' ) ) ) ?>').find('.cmb-td input[type="text"]').val('');
}
});
$(".cmb-type-post-list.cmb2-id-<?php echo str_replace( '_', '-', sanitize_html_class( $field->args( 'id' ) ) ) ?> ul").sortable({
update: function (event, ui) {
var ids = [];
$('.cmb-type-post-list.cmb2-id-<?php echo str_replace( '_', '-', sanitize_html_class( $field->args( 'id' ) ) ) ?> ul li').each(function (index, value) {
ids.push($(this).data('id'));
});
$('.cmb-type-post-list.cmb2-id-<?php echo str_replace( '_', '-', sanitize_html_class( $field->args( 'id' ) ) ) ?>').find('.cmb-td input[type="text"]').val(ids.join(', '));
}
});
});
</script>
<?php
}
add_action( 'cmb2_render_post_list', 'cmb2_post_list_render_field', 10, 5 );
================================================
FILE: custom-field-types/select-multiple-field-type.php
================================================
<?php
/**
* CMB2 Select Multiple Custom Field Type
* @package CMB2 Select Multiple Field Type
*/
/**
* Adds a custom field type for select multiples.
* @param object $field The CMB2_Field type object.
* @param string $value The saved (and escaped) value.
* @param int $object_id The current post ID.
* @param string $object_type The current object type.
* @param object $field_type_object The CMB2_Types object.
* @return void
*/
function cmb2_render_select_multiple_field_type( $field, $escaped_value, $object_id, $object_type, $field_type_object ) {
$select_multiple = '<select class="widefat" multiple name="' . $field->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 .= '<option class="cmb2-option" value="' . esc_attr( $value ) . '" ' . $selected . '>' . esc_html( $name ) . '</option>';
}
$select_multiple .= '</select>';
$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
================================================
<?php
/*
* Plugin Name: CMB2 Custom Field Type - Star Rating
* Description: Makes available a 'star_rating' CMB2 Custom Field Type. Based on https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-field-types#example-4-multiple-inputs-one-field-lets-create-an-address-field
* Author: Evan Herman
* Author URI: https://www.evan-herman.com
* Version: 0.1.0
*/
/**
* Template tag for displaying an star rating from the CMB2 star rating field type (on the front-end)
*
* @since 0.1.0
*
* @param string $metakey The 'id' of the 'star rating' field (the metakey for get_post_meta)
* @param integer $post_id (optional) post ID. If using in the loop, it is not necessary
*/
function eh_cmb2_star_rating_field( $metakey, $post_id = 0 ) {
echo eh_cmb2_get_star_rating_field( $metakey, $post_id );
}
/**
* Template tag for returning a star rating from the CMB2 star rating field type (on the front-end)
*
* @since 0.1.0
*
* @param string $metakey The 'id' of the 'star rating' field (the metakey for get_post_meta)
* @param integer $post_id (optional) post ID. If using in the loop, it is not necessary
*/
function eh_cmb2_get_star_rating_field( $metakey, $post_id = 0 ) {
$post_id = $post_id ? $post_id : get_the_ID();
$rating = get_post_meta( $post_id, $metakey, 1 );
$stars_container = '<section class="cmb2-star-container">';
$x = 1;
$total = 5;
while( $x <= $rating ) {
$stars_container .= '<span class="dashicons dashicons-star-filled"></span>';
$x++;
}
if( $rating < $total ) {
while( $rating < $total ) {
$stars_container .= '<span class="dashicons dashicons-star-empty"></span>';
$rating++;
}
}
$stars_container .= '</section>';
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 );
?>
<section id="cmb2-star-rating-metabox">
<fieldset>
<span class="star-cb-group">
<?php
$y = 5;
while( $y > 0 ) {
?>
<input type="radio" id="rating-<?php echo $y; ?>" name="<?php echo $field_type_object->_id( false ); ?>" value="<?php echo $y; ?>" <?php checked( $value, $y ); ?>/>
<label for="rating-<?php echo $y; ?>"><?php echo $y; ?></label>
<?php
$y--;
}
?>
</span>
</fieldset>
</section>
<?php
echo $field_type_object->_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
================================================
<?php
/**
* Handles 'taxonomy_radio_with_image' custom field type.
*/
class DJ_Taxonomy_Radio_Hierarchical_With_Image extends CMB2_Type_Taxonomy_Radio_Hierarchical {
protected $term;
protected $saved_term;
/**
* Build children hierarchy.
*
* @param object $parent_term The parent term object.
* @param array|string $saved Array of terms set to the object, or single term slug.
*
* @return string List of terms.
*/
protected function build_children( $parent_term, $saved ) {
if ( empty( $parent_term->term_id ) ) {
return '';
}
$this->parent = $parent_term->term_id;
$terms = $this->get_terms();
$options = '';
if ( ! empty( $terms ) && is_array( $terms ) ) {
// DJ - BEGIN
$options = '<ul class="cmb2-indented-hierarchy">';
$options .= $this->loop_terms( $terms, $saved );
$options .= '</ul>';
// 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 = '<img style="max-width: 30px; height: auto; vertical-align: middle; margin-right: 5px;" src="'.$image_url.'" alt="'.$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" . '<li %s><span><input%s/><label for="%s">%s<span>%s</span></label></span>' . "\n", $is_parent, $atts, $a['id'], $image, $a['label'] );
} else {
return sprintf( "\t" . '<li %s><span><input%s/><label for="%s">%s<span>%s</span></label></span></li>' . "\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
================================================
<?php
/**
* Handles 'taxonomy_radio_with_image' custom field type.
*/
class DJ_Taxonomy_Radio_With_Image_Display extends CMB2_Display_Taxonomy_Radio {}
================================================
FILE: custom-field-types/taxonomy-radio-with-image-field-type/taxonomy-radio-with-image-field-type.php
================================================
<?php
/**
* Custom field type to add term images to the output of the taxonomy radio field.
* See https://wordpress.org/support/topic/disable-cmb2-on-some-view/
*/
function dj_taxonomy_radio_with_image_field_type_class_name() {
$class_name = 'DJ_Taxonomy_Radio_Hierarchical_With_Image';
require_once dirname( __FILE__ ) . '/'. $class_name .'.php';
return $class_name;
}
function dj_taxonomy_radio_with_image_field_type_display_class_name() {
$class_name = 'DJ_Taxonomy_Radio_With_Image_Display';
require_once dirname( __FILE__ ) . '/'. $class_name .'.php';
return $class_name;
}
function dj_add_taxonomy_radio_with_image( $types ) {
$types[] = 'taxonomy_radio_with_image';
return $types;
}
function dj_taxonomy_radio_with_image_sanitize( $check, $meta_value, $object_id, $field_args, $sanitize_object ) {
$sanitized_value = $sanitize_object->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
================================================
<?php
/**
* CMB2 Multicheck by Post Type
*
* @package CMB2 Default Tags field/metabox
* @author Daniele Mte90 Scasciafratte
*/
if ( !defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'CMB2_Field_Textarea_With_Checkbox' ) ) {
/**
* Class CMB2_Field_Textarea_With_Checkbox
*/
class CMB2_Field_Textarea_With_Checkbox {
/**
* Current version number
*/
const VERSION = '1.0.0';
/**
* Initialize the plugin
*/
public function __construct() {
add_action( 'cmb2_render_textarea_with_checkbox', [$this, 'render_textarea_with_checkbox'], 10, 5 );
add_filter( 'cmb2_sanitize_textarea_with_checkbox', [$this, 'sanitize_textarea_with_checkbox'], 10, 5 );
add_filter( 'cmb2_types_esc_textarea_with_checkbox', [$this, 'escape_textarea_with_checkbox'], 10, 4 );
}
public function render_textarea_with_checkbox( $field, $field_escaped_value, $field_object_id, $field_object_type, $field_type_object ) {
// the properties of the fields.
$field_escaped_value = wp_parse_args( $field_escaped_value, [
'text' => '',
'status' => '',
] );
$checked = false;
if ( ! empty( $field_escaped_value['status'] ) ) {
$checked = true;
}
?>
<div style="overflow: hidden;">
<?= $field_type_object->textarea( [
'name' => $field_type_object->_name( '[text]' ),
'id' => $field_type_object->_id( '_text' ),
'value' => $field_escaped_value['text'],
] ); ?>
</div>
<div style="overflow: hidden">
<p><label for="<?= $field_type_object->_id( '_status' ); ?>"><?= $field_type_object->field->args('title_checkbox'); ?></label></p>
<?= $field_type_object->checkbox( [
'type' => 'checkbox',
'name' => $field_type_object->_name( '[status]' ),
'id' => $field_type_object->_id( '_status' ),
], $checked ); ?>
</div>
<?php
echo $field_type_object->_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
================================================
<?php
/*
* Year Range field type.. two year-pickers, start and end.
* Screenshot: http://b.ustin.co/15lKk
*/
/**
* Example field registration:
*
* function yourprefix_register_demo_metabox() {
*
* $cmb_demo = new_cmb2_box( array(
* 'id' => '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 '<em>'. $type_object->_text( 'start_label', 'Starting Year' ) . '</em> ';
$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 ' <em>'. $type_object->_text( 'finish_label', 'Final Year' ) . '</em>';
$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;
}
?>
<script type="text/javascript">
jQuery( function( $ ) {
var $options = {};
function makeSelected( $newoptions, selected ) {
var $selected = $newoptions.filter( '[value="'+ selected +'"]' );
if ( ! $selected.length ) {
$selected = $newoptions.filter( '[value=""]' );
}
// Clear out previous selected
$newoptions.filter( ':selected' ).prop( 'selected', false );
$selected.prop( 'selected', true );
return $newoptions;
}
function getNewOptions( $options, start, selected ) {
if ( start ) {
$options = $options.filter( function() {
var val = $( this ).val();
return'current' === start ? 'current' === val || '' === val : ( val >= start || ! val );
} );
}
return makeSelected( $options.clone(), selected );
}
$( document.body ).on( 'change', '.cmb2-year-range-start', function() {
var $this = $( this );
var start = $this.find( ':selected' ).val();
var $endPicker = $this.parent().find( '.cmb2-year-range-end' );
var id = $endPicker.attr( 'id' );
var selectedEnd = $endPicker.find( ':selected' ).val();
if ( ! $options[ id ] ) {
// Store a cached version of the unmodified options.
$options[ id ] = $endPicker.find( 'option' ).clone();
}
$endPicker.html( getNewOptions( $options[ id ], start, selectedEnd ) );
} );
// Kick it off.
$( '.cmb2-year-range-start' ).trigger( 'change' );
});
</script>
<?php
}
function jt_cmb2_date_year_range_options( $type_object, $earliest, $value, $reverse = false ) {
$options = array();
$not_set = array(
'value' => '',
'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
================================================
<?php
/**
* This file demonstrates adding new fields dynamically, based on the existing post meta.
* @link https://geek.hellyer.kiwi/2018/08/11/dynamically-controlling-cmb2-metaboxes/
*/
add_action( 'cmb2_admin_init', 'register_dynamic_fields_box' );
function register_dynamic_fields_box() {
$cmb = new_cmb2_box( array(
'id' => '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
================================================
<?php
/**
* CMB2 has a defined set of "all or nothing types".
* This filter allows us to change that.
*/
function add_select2_to_all_or_nothing_types( $types ) {
$types[] = 'select2';
return $types;
}
add_filter( 'cmb2_all_or_nothing_types', 'add_select2_to_all_or_nothing_types' );
================================================
FILE: filters-and-actions/cmb2_before_form-and-cmb2_after_form-hooks.php
================================================
<?php
/**
* This file demonstrates using the following hooks:
* cmb2_before_form and cmb2_before_{$object_type}_form_{$cmb_id}
* Docs: https://github.com/CMB2/CMB2/blob/a7b93886e56a9c9f6e78ea0efbe1b01bcbb1a248/includes/CMB2.php#L245-L270
* cmb2_after_form and cmb2_after_{$object_type}_form_{$cmb_id}
* Docs: https://github.com/CMB2/CMB2/blob/a7b93886e56a9c9f6e78ea0efbe1b01bcbb1a248/includes/CMB2.php#L361-L385
*/
function yourprefix_add_html_before_cmb2_output( $cmb_id, $object_id, $object_type, $cmb ) {
// Only output above the _yourprefix_demo_metabox metabox.
if ( '_yourprefix_demo_metabox' !== $cmb_id ) {
return;
}
echo '<div class="my-custom-wrapper">';
echo '<h4>Welcome to my metabox!</h4>';
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 '</div><!-- .my-custom-wrapper-->';
}
// 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 '<div class="my-custom-wrapper">';
echo '<h4>Welcome to my metabox!</h4>';
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 '</div><!-- .my-custom-wrapper-->';
}
================================================
FILE: filters-and-actions/cmb2_init_$cmb_id-add-fields.php
================================================
<?php
/**
* This file demonstrates adding new fields to a registered CMB2 metaboxes during its "cmb2_init_{$cmb_id}" hook
*/
function yourprefix_add_new_field_to_top_of_demo_metabox( $cmb ) {
$cmb->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
================================================
<?php
/**
* This snippet demonstrates modifying (during its "cmb2_init_{$cmb_id}" hook) the object-types
* registered to a CMB2 box.
*
* The "cmb2_init_{$cmb_id}" hook occurs during the initiation of the CMB2 object.
*
* The dynamic portion of the hook name, `$cmb_id`, is the registered cmb2 box id,
* so in our example case: "yourprefix_demo_metabox".
*/
function yourprefix_demo_metabox_modify_object_types( $cmb ) {
$types = $cmb->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
================================================
<?php
/**
* This file demonstrates removing fields from a registered CMB2 metaboxes during its "cmb2_init_{$cmb_id}" hook
*/
function yourprefix_remove_field_from_demo_metabox( $cmb ) {
$cmb->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
================================================
<?php
/**
* This file demonstrates adding replacing a registered field in the CMB2 metaboxe
* with an id of `_yourprefix_demo_metaboxx`, during its "cmb2_init_hookup_{$cmb_id}" hook.
*/
function yourprefix_replace_field_in_demo_metaboxx( $cmb ) {
// Should we replace the field with our new one?
$some_condition = true;
if ( $some_condition ) {
$cmb->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
================================================
<?php
/**
* This file demonstrates adding new fields to registered CMB2 metaboxes/objects
*/
function yourprefix_add_new_field_in_3rd_position() {
$prefix = '_yourprefix_demo_';
// Retrieve a CMB2 instance
$cmb = cmb2_get_metabox( '_yourprefix_demo_metabox' );
// This should return false because we don't have a '_yourprefix_demo_text2' field
$field_id = $cmb->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
================================================
<?php
/**
* You can remove an entire CMB2 metabox. But be polite.
*/
function yourprefix_remove_metabox() {
// to remove a cmb metabox.. use wisely
CMB2_Boxes::remove( '_yourprefix_demo_metabox' );
}
add_action( 'cmb2_init_before_hookup', 'yourprefix_remove_metabox' );
================================================
FILE: filters-and-actions/cmb2_init_before_hookup-update-existing-fields.php
================================================
<?php
/**
* This file demonstrates modifying existing registered CMB2 metabox fields
*/
function yourprefix_update_fields_properties() {
// Retrieve a CMB2 instance
$cmb = cmb2_get_metabox( '_yourprefix_demo_metabox' );
/**
* Update a property on the '_yourprefix_demo_text' field.
* In this case, we'll remove the show_on_cb conditional callback
* (to instead always display the field)
*
* If field exists, and property updated, it will return the field id
*/
$field_id = $cmb->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
================================================
<?php
/**
* This file demonstrates providing a default value for a group field from a JSON blob.
* It is using the fields from the group field example in:
* [example-functions.php](https://github.com/WebDevStudios/CMB2/blob/3b0cc0a696f70d1f3ce7c94af8318f4dd3f34688/example-functions.php#L460-L522).
*/
/**
* Filters the value for our group field.
*
* @param mixed $value The value get_metadata() should
* return - a single metadata value,
* or an array of values.
*
* @param int $object_id Object ID.
*
* @param array $args {
* An array of arguments for retrieving data
*
* @type string $type The current object type
* @type int $id The current object ID
* @type string $field_id The ID of the field being requested
* @type bool $repeat Whether current field is repeatable
* @type bool $single Whether current field is a single database row
* }
*
* @param CMB2_Field object $field This field object
*
* @return array The group field value array.
*/
function yourprefix_get_default_group_value_from_json( $value, $object_id, $args, $field ) {
static $defaults = null;
// Only set the default if the original value has not been overridden,
// and if there is no existing value.
if ( 'cmb2_field_no_override_val' !== $value ) {
return $value;
}
// Get the value for the field.
$data = 'options-page' === $args['type']
? cmb2_options( $args['id'] )->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 <strong>description<\/strong>","image":"\/wp-content\/uploads\/2016\/10\/default-image-1.jpg","image_id":663},{"title":"2nd Title","description":"This is a second <strong>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
================================================
<?php
/**
* Add custom CSS which only loads for a particular metabox
*/
/**
* Setup the metabox
*/
function js_custom_css_for_metabox() {
$cmb = new_cmb2_box( array(
'id' => '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 ) {
?>
<style type="text/css" media="screen">
#custom_css_test .regular-text {
width: 99%;
}
</style>
<?php
}
$object = 'post'; // post | term
$cmb_id = 'custom_css_test';
add_action( "cmb2_after_{$object}_form_{$cmb_id}", 'js_add_custom_css_for_metabox', 10, 2 );
================================================
FILE: filters-and-actions/disable-styles-on-front-end-forms.php
================================================
<?php
/**
* This file demonstrates how to disable CMB2 styles on all front end forms.
*
* It’s important, when using the `cmb2_enqueue_*` filters to only disable for your
* specific conditions/scenarios. It’s entirely possible that another plugin/theme is
* using CMB2 and *needs* the styles on the front-end, so blindly disabling can cause issues.
*/
function yourprefix_disable_cmb2_front_end_styles( $enabled ) {
if ( ! is_admin() /* && meets_your_specific_conditions() */ ) {
$enabled = false;
}
return $enabled;
}
add_filter( 'cmb2_enqueue_css', 'yourprefix_disable_cmb2_front_end_styles' );
================================================
FILE: filters-and-actions/localize-date-format.php
================================================
<?php
/**
* A demo of the helper function used to
* localise any date picker form in CMB2.
* See http://api.jqueryui.com/datepicker/
* for more info.
* Refer to the CMB Field Types Wiki entry
* if you wish to implement a different date format
* per meta field using date_format.
* This snippet was modified from one at the following link:
* https://github.com/WebDevStudios/CMB2/issues/73
*/
add_filter( 'cmb2_localized_data', 'prefix_cmb_set_date_format' );
function prefix_cmb_set_date_format( $l10n ) {
// Set your date format replacing 'dd-mm-yy' (UK format)
$l10n['defaults']['date_picker']['dateFormat'] = 'dd-mm-yy';
return $l10n;
}
================================================
FILE: filters-and-actions/override-cmb2-data-source.php
================================================
<?php
/**
* Demonstrates using an alternate data source for storing/retrieving data for a CMB2 box.
* In this case, we're simply storing/retrieving/removing from an option in the options table,
* but this can be extended to handle data storage to/from custom tables, Redis, REST APIs, etc.
*/
add_action( 'cmb2_init', 'yourprefix_register_yourprefix_group_alt_data_metabox' );
/**
* Hook in and add a metabox to demonstrate repeatable grouped fields
*/
function yourprefix_register_yourprefix_group_alt_data_metabox() {
$default_values = get_option( 'yourprefix_group_alt_data_demo' );
if ( ! is_array( $default_values ) ) {
add_option( 'yourprefix_group_alt_data_demo', array(
// Default group 1.
array(
'title' => '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
================================================
<?php
/**
* The following snippet is untested, but provides a proof of concept to how you can save a default value for a group field based on the value of another field.
*/
// Setup a group field... the group field is proceeded by a radio field.
function yourprefix_register_repeatable_group_field_metabox() {
/**
* Repeatable Field Groups
*/
$cmb = new_cmb2_box( array(
'id' => '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
================================================
<?php
/*
* Frontend editor, including title/content
*/
function jt_add_edit_form_to_frontend( $content ) {
if ( isset( $_GET['edit'] ) ) {
if ( current_user_can( 'edit_posts' ) && wp_verify_nonce( $_GET['edit'], 'edit' ) ) {
$content = cmb2_get_metabox_form( '_yourprefix_demo_metabox', get_the_ID() );
} else {
$content = '<h2 class="edit-error">You do not have permission to edit this post.</h2>';
}
}
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 "<script type='text/javascript'>window.location.href = '$url';</script>";
}
}
/**
* 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
================================================
<?php
/**
* @link http://webdevstudios.com/2015/03/30/use-cmb2-to-create-a-new-post-submission-form/ Original tutorial
*/
/**
* Register the form and fields for our front-end submission form
*/
function yourprefix_frontend_form_register() {
$cmb = new_cmb2_box( array(
'id' => '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 .= '<h3>' . sprintf( __( 'There was an error in the submission: %s', 'YOURTEXTDOMAIN' ), '<strong>'. $error->get_error_message() .'</strong>' ) . '</h3>';
}
// 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 .= '<h3>' . sprintf( __( 'Thank you%s, your new post has been submitted and is pending review by a site administrator.', 'YOURTEXTDOMAIN' ), esc_html( $name ) ) . '</h3>';
}
// 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
================================================
<?php
/**
* Use the WordPress Media Uploader on the frontend. Limit to only displaying current
* user's uploaded media. Props [@vasikgreif](https://github.com/vasikgreif)
*
* @link https://github.com/WebDevStudios/CMB2/issues/283 Original concept
*/
/**
* Allow the media uploader work on specific pages
*/
function nevestam_allow_contributor_uploads() {
if ( is_admin() ) {
return;
}
$path = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';
if ( ! $path || '/page-slug' != $path ) {
return;
}
/**
* Replace 'subscriber' with the required role to update, can also be contributor
*/
$subscriber = get_role( 'subscriber' );
// This is the only cap needed to upload files.
$subscriber->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
================================================
<?php
/*
* Plugin Name: CMB2 - Front-end Shortcode
* Description: Display CMB2 metabox forms on the front-end using a shortcode
* Author: jtsternberg
* Author URI: http://dsgnwrks.pro
* Version: 0.1.0
*/
/**
* Shortcode to display a CMB2 form for a post ID.
* Adding this shortcode to your WordPress editor would look something like this:
*
* [cmb-form id="test_metabox" post_id=2]
*
* The shortcode requires a metabox ID, and (optionally) can take
* a WordPress post ID (or user/comment ID) to be editing.
*
* @param array $atts Shortcode attributes
* @return string Form HTML markup
*/
function jt_cmb2_do_frontend_form_shortcode( $atts = array() ) {
global $post;
/**
* Make sure a WordPress post ID is set.
* We'll default to the current post/page
*/
if ( ! isset( $atts['post_id'] ) ) {
$atts['post_id'] = $post->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
================================================
<?php
/*
* Plugin Name: CMB2 Template Tag - Output File List
* Description: Custom functions that allow you to get or ouput the file_list images in a specified size
* Author: jtsternberg
* Author URI: http://dsgnwrks.pro
* Version: 0.1.0
*/
/**
* Outputs a cmb2 file_list
*
* @param string $file_list_meta_key The field meta key. ($prefix . 'file_list')
* @param string $img_size Size of image to show
*/
function jt_cmb2_file_list_images( $file_list_meta_key, $img_size = 'medium' ) {
echo jt_cmb2_get_file_list_images( $file_list_meta_key, $img_size );
}
/**
* Returns a cmb2 file_list
*
* @param string $file_list_meta_key The field meta key. ($prefix . 'file_list')
* @param string $img_size Size of image to show
* @return string The html markup for the images
*/
function jt_cmb2_get_file_list_images( $file_list_meta_key, $img_size = 'medium' ) {
// Get the list of files
$files = get_post_meta( get_the_ID(), $file_list_meta_key, 1 );
$images = '';
// Loop through them and output an image
foreach ( (array) $files as $attachment_id => $attachment_url ) {
$images .= '<div class="file-list-image">';
$images .= wp_get_attachment_image( $attachment_id, $img_size );
$images .= '</div>';
}
return $images ? '<div class="file-list-wrap">' . $images . '</div>' : '';
}
================================================
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
================================================
<?php
/**
* Just a collection of random helper functions for CMB2.
* If you borrow these, please replace "yourprefix_" with something unique to your project.
*/
/**
* If it exists, handles uploading a file from the $_FILES array, and setting data to CMB2 file field.
*
* @param string $files_key Array key in $_FILES array.
* @param int $post_id Post ID
* @param string $meta_key The CMB2 'file' field ID.
* @param string $title Override the default file title handling.
*
* @return array|WP_Error
*/
function yourprefix_upload_file_for_cmb2( $files_key, $post_id, $meta_key = '', $title = '' ) {
if (
empty( $_FILES[ $files_key ] )
|| isset( $_FILES[ $files_key ]['error'] ) && 0 !== $_FILES[ $files_key ]['error']
) {
return false;
}
require_once( ABSPATH . 'wp-admin/includes/media.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$post_data = array();
if ( $title ) {
$post_data['post_title'] = get_the_title( $post_id ) . ': Flyer';
}
$id = media_handle_upload( $files_key, $post_id, $post_dataarray );
if ( is_wp_error( $id ) ) {
return $id;
}
$src = wp_get_attachment_url( $id );
if ( $meta_key ) {
update_post_meta( $post_id, $meta_key, $src );
update_post_meta( $post_id, "{$meta_key}_id", $id );
}
return compact( 'src', 'id' );
}
/**
* Handles sideloading a file from given $file_url, and setting data to CMB2 file field.
*
* @param string $file_url URL to file to sideload.
* @param int $post_id Post ID
* @param string $meta_key The CMB2 'file' field ID.
* @param string $title Override the default file title handling.
*
* @return array|WP_Error
*/
function yourprefix_sideload_file_for_cmb2( $file_url, $post_id, $meta_key, = '', $title = null ) {
require_once( ABSPATH . 'wp-admin/includes/media.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$parts = explode( '/', $file_url );
$file_array = array();
$file_array['name'] = end( $parts );
// Download file to temp location.
$file_array['tmp_name'] = download_url( $file_url );
// If error storing temporarily, return the error.
if ( is_wp_error( $file_array['tmp_name'] ) ) {
return $file_array['tmp_name'];
}
// Do the validation and storage stuff.
$id = media_handle_sideload( $file_array, $post_id, $title );
// If error storing permanently, unlink.
if ( is_wp_error( $id ) ) {
@unlink( $file_array['tmp_name'] );
return $id;
}
$src = wp_get_attachment_url( $id );
if ( $meta_key ) {
update_post_meta( $post_id, $meta_key, $src );
update_post_meta( $post_id, "{$meta_key}_id", $id );
}
return compact( 'src', 'id' );
}
/**
* If you want oembed filters to apply to the wysiwyg content, add this helper function to your theme or plugin.
*
* @link https://github.com/WebDevStudios/CMB2/wiki/Field-Types#notes-2 Wiki
*
* @param string $meta_key The CMB2 text field (e.g. 'wysiwyg', 'textarea', etc) ID.
* @param int $post_id Post ID
*
* @return string If the field has a value, returns the formatted value;
*/
function yourprefix_get_cmb2_wysiwyg_output( $meta_key, $post_id = 0 ) {
global $wp_embed;
$post_id = $post_id ? $post_id : get_the_id();
$content = get_post_meta( $post_id, $meta_key, 1 );
if ( ! $content ) {
return '';
}
$content = $wp_embed->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 '<div class="file-list-wrap">';
// Loop through them and output an image
foreach ( (array) $files as $attachment_id => $attachment_url ) {
echo '<div class="file-list-image">';
echo wp_get_attachment_image( $attachment_id, $img_size );
echo '</div>';
}
echo '</div>';
}
================================================
FILE: helper-functions/modify-cmb2_metabox_form-format.php
================================================
<?php
/**
* To change the formatting of the form,
* again, pass the third parameter (the arguments array),
* and specify the 'form_format' param
*
* In our case, we're modifying the save button text,
* and we're giving the save button a secondary button class
*/
cmb2_metabox_form( $meta_box, $object_id, array(
'form_format' => '<form class="cmb-form" method="post" id="%1$s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%2$s">%3$s<div class="submit-wrap"><input type="submit" name="submit-cmb" value="' . __( 'Save Settings', 'your-textdomain' ) . '" class="button-secondary"></div></form>',
) );
================================================
FILE: helper-functions/modify-cmb2_metabox_form-output.php
================================================
<?php
/**
* You can use the 'cmb2_get_metabox_form_format' filter to modify the form format,
* but keep in mind it will affect the form format for all uses of
* the cmb2_metabox_form, cmb2_print_metabox_form, and cmb2_get_metabox_form functions,
* so you should make sure you're looking at the right form.
*
* If you're using the options-page example,
* (https://github.com/WebDevStudios/CMB2-Snippet-Library/tree/master/options-and-settings-pages)
* You would do it like this:
*/
/**
* Modify CMB2 Default Form Output
*
* @param string $form_format Form output format
* @param string $object_id In the case of an options page, this will be the option key
* @param object $cmb CMB2 object. Can use $cmb->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 = '<form class="cmb-form" method="post" id="%1$s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%2$s">%3$s<div class="submit-wrap"><input type="submit" name="submit-cmb" value="' . __( 'Save Settings', 'myprefix' ) . '" class="button-primary"></div></form>';
}
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
================================================
<?php
/**
* To change just the text of the save button,
* pass the third parameter (the arguments array),
* and specify the 'save_button' param
*/
cmb2_metabox_form( $meta_box, $object_id, array(
'save_button' => __( '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
================================================
<?php
/*
* Plugin Name: CMB2 Auto-scroll to new group
* Description: This feature was removed in CMB2 2.0.3. Install this plugin to re-activate.
* Author: jtsternberg
* Author URI: http://dsgnwrks.pro
* Version: 0.1.0
*/
function jt_cmb_group_autoscroll_js() {
// If not cmb2 scripts on this page, bail
if ( ! wp_script_is( 'cmb2-scripts', 'enqueued' ) ) {
return;
}
?>
<script type="text/javascript">
window.CMB2 = window.CMB2 || {};
(function(window, document, $, cmb, undefined){
'use strict';
// We'll keep it in the CMB2 object namespace
cmb.initAutoScrollGroup = function(){
cmb.metabox().find('.cmb-repeatable-group').on( 'cmb2_add_row', cmb.autoScrollGroup );
};
cmb.autoScrollGroup = function( evt, row ) {
var $focus = $(row).find('input:not([type="button"]), textarea, select').first();
if ( $focus.length ) {
$( 'html, body' ).animate({
scrollTop: Math.round( $focus.offset().top - 150 )
}, 1000);
$focus.focus();
}
};
$(document).ready( cmb.initAutoScrollGroup );
})(window, document, jQuery, CMB2);
</script>
<?php
}
add_action( 'admin_footer', 'jt_cmb_group_autoscroll_js', 999 );
================================================
FILE: javascript/cmb2-js-validation-required.php
================================================
<?php
/*
* Plugin Name: CMB2 js validation for "required" fields
* Description: Uses js to validate CMB2 fields that have the 'data-validation' attribute set to 'required'
* Version: 0.1.0
*/
/**
* Documentation in the wiki:
* @link https://github.com/WebDevStudios/CMB2/wiki/Plugin-code-to-add-JS-validation-of-%22required%22-fields
*/
function cmb2_after_form_do_js_validation( $post_id, $cmb ) {
static $added = false;
// Only add this to the page once (not for every metabox)
if ( $added ) {
return;
}
$added = true;
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$form = $( document.getElementById( 'post' ) );
$htmlbody = $( 'html, body' );
$toValidate = $( '[data-validation]' );
if ( ! $toValidate.length ) {
return;
}
function checkValidation( evt ) {
var labels = [];
var $first_error_row = null;
var $row = null;
function add_required( $row ) {
$row.css({ 'background-color': 'rgb(255, 170, 170)' });
$first_error_row = $first_error_row ? $first_error_row : $row;
labels.push( $row.find( '.cmb-th label' ).text() );
}
function remove_required( $row ) {
$row.css({ background: '' });
}
$toValidate.each( function() {
var $this = $(this);
var val = $this.val();
$row = $this.parents( '.cmb-row' );
if ( $this.is( '[type="button"]' ) || $this.is( '.cmb2-upload-file-id' ) ) {
return true;
}
if ( 'required' === $this.data( 'validation' ) ) {
if ( $row.is( '.cmb-type-file-list' ) ) {
var has_LIs = $row.find( 'ul.cmb-attach-list li' ).length > 0;
if ( ! has_LIs ) {
add_required( $row );
} else {
remove_required( $row );
}
} else {
if ( ! val ) {
add_required( $row );
} else {
remove_required( $row );
}
}
}
});
if ( $first_error_row ) {
evt.preventDefault();
alert( '<?php _e( 'The following fields are required and highlighted below:', 'cmb2' ); ?> ' + labels.join( ', ' ) );
$htmlbody.animate({
scrollTop: ( $first_error_row.offset().top - 200 )
}, 1000);
} else {
// Feel free to comment this out or remove
alert( 'submission is good!' );
}
}
$form.on( 'submit', checkValidation );
});
</script>
<?php
}
add_action( 'cmb2_after_form', 'cmb2_after_form_do_js_validation', 10, 2 );
================================================
FILE: javascript/dynamically-change-group-field-title-from-subfield.php
================================================
<?php
/**
* Custom Repeatable Group.
* The "group_title" will display the value of the 'title' sub-field, if it exists,
* or fall back to the default CMB2 group title method.
*/
/**
* Hook in and add a metabox to demonstrate repeatable grouped fields
*/
function yourprefix_register_repeatable_group_field_title_example() {
/**
* Repeatable Field Groups
*/
$cmb_group = new_cmb2_box( array(
'id' => '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() {
?>
<script type="text/javascript">
jQuery( function( $ ) {
var $box = $( document.getElementById( 'yourprefix_group_titles_metabox' ) );
var replaceTitles = function() {
$box.find( '.cmb-group-title' ).each( function() {
var $this = $( this );
var txt = $this.next().find( '[id$="title"]' ).val();
var rowindex;
if ( ! txt ) {
txt = $box.find( '[data-grouptitle]' ).data( 'grouptitle' );
if ( txt ) {
rowindex = $this.parents( '[data-iterator]' ).data( 'iterator' );
txt = txt.replace( '{#}', ( rowindex + 1 ) );
}
}
if ( txt ) {
$this.text( txt );
}
});
};
var replaceOnKeyUp = function( evt ) {
var $this = $( evt.target );
var id = 'title';
if ( evt.target.id.indexOf(id, evt.target.id.length - id.length) !== -1 ) {
$this.parents( '.cmb-row.cmb-repeatable-grouping' ).find( '.cmb-group-title' ).text( $this.val() );
}
};
$box
.on( 'cmb2_add_row cmb2_remove_row cmb2_shift_rows_complete', replaceTitles )
.on( 'keyup', replaceOnKeyUp );
replaceTitles();
});
</script>
<?php
}
================================================
FILE: javascript/limit-number-of-multiple-repeat-groups.php
================================================
<?php
/**
* Set a max limit on the number of times
* a repeating group can be added for various groups in one page
*/
/**
* Setup the groups fields metabox
*/
function js_limited_group_setup() {
/**
* Repeatable Field Groups
*/
$cmb_one = new_cmb2_box( array(
'id' => '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' )
?>
<script type="text/javascript">
jQuery(document).ready(function($){
// Only allow 3 groups
var limit = <?php echo $limit; ?>;
var fieldGroupId = '<?php echo $group; ?>';
var $fieldGroupTable = $( document.getElementById( fieldGroupId + '_repeat' ) );
var countRows = function() {
return $fieldGroupTable.find( '> .cmb-row.cmb-repeatable-grouping' ).length;
};
var disableAdder = function() {
$fieldGroupTable.find('.cmb-add-group-row.button-secondary').prop( {disabled: true} );
};
var enableAdder = function() {
$fieldGroupTable.find('.cmb-add-group-row.button-secondary').prop( {disabled: false} );
};
$fieldGroupTable
.on( 'cmb2_add_row', function() {
if ( countRows() >= limit ) {
disableAdder();
}
})
.on( 'cmb2_remove_row', function() {
if ( countRows() < limit ) {
enableAdder();
}
});
});
</script>
<?php
}
================================================
FILE: javascript/limit-number-of-repeat-fields.php
================================================
<?php
/**
* Set a max limit on the number of times
* a repeating field can be added.
*/
/**
* Setup the metabox
*/
function js_limited_repeat_field_setup() {
$cmb = new_cmb2_box( array(
'id' => '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;
?>
<script type="text/javascript">
jQuery(document).ready(function($){
// Only allow 3 groups
var limit = <?php echo $limit; ?>;
var fieldGroupId = 'text_repeat_test';
var $fieldTable = $( document.getElementById( fieldGroupId + '_repeat' ) );
var $repeatWrap = $fieldTable.find( '.cmb-repeat-table.cmb-nested' ).first();
var countRows = function() {
return $repeatWrap.find( '.cmb-row.cmb-repeat-row' ).length;
};
var disableAdder = function() {
$repeatWrap.parents( '.cmb-repeat.table-layout' ).find('.cmb-add-row-button').prop( 'disabled', true );
};
var enableAdder = function() {
$repeatWrap.parents( '.cmb-repeat.table-layout' ).find('.cmb-add-row-button').prop( 'disabled', false );
};
$fieldTable
.on( 'cmb2_add_row', function( evt, row ) {
var $row = $( row );
$repeatWrap = $row.parents( '.cmb-repeat-table.cmb-nested' );
if ( countRows() >= limit ) {
disableAdder();
}
})
.on( 'cmb2_remove_row', function() {
if ( countRows() < limit ) {
enableAdder();
}
});
});
</script>
<?php
}
add_action( 'cmb2_after_post_form_test_limit_rows', 'js_limit_field_repeat', 10, 2 );
================================================
FILE: javascript/limit-number-of-repeat-groups.php
================================================
<?php
/**
* Set a max limit on the number of times
* a repeating group can be added.
*/
/**
* Setup the group field metabox
*/
function js_limited_group_setup() {
/**
* Repeatable Field Groups
*/
$cmb = new_cmb2_box( array(
'id' => '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;
?>
<script type="text/javascript">
jQuery(document).ready(function($){
// Only allow 3 groups
var limit = <?php echo $limit; ?>;
var fieldGroupId = '_cmb2_repeat_group'; // This should match the ID of your group field.
var $fieldGroupTable = $( document.getElementById( fieldGroupId + '_repeat' ) );
var countRows = function() {
return $fieldGroupTable.find( '> .cmb-row.cmb-repeatable-grouping' ).length;
};
var disableAdder = function() {
$fieldGroupTable.find('.cmb-add-group-row').prop( 'disabled', true );
};
if ( countRows() >= limit ) {
disableAdder();
}
var enableAdder = function() {
$fieldGroupTable.find('.cmb-add-group-row').prop( 'disabled', false );
};
if ( countRows() < limit ) {
enableAdder();
}
$fieldGroupTable
.on( 'cmb2_add_row', function() {
if ( countRows() >= limit ) {
disableAdder();
}
})
.on( 'cmb2_remove_row', function() {
if ( countRows() < limit ) {
enableAdder();
}
});
});
</script>
<?php
}
// Replace `field_group_test` with the ID of the CMB2 meta box in question e.g. this
// should match the value of $cmb->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
================================================
<?php
/**
* Example of adding an opening/closing wrap around a group of fields.
* Gif: http://b.ustin.co/12Uba
*/
add_action( 'cmb2_admin_init', 'yourprefix_register_demo_metabox' );
/**
* Hook in and add a demo metabox. Can only happen on the 'cmb2_admin_init' or 'cmb2_init' hook.
*/
function yourprefix_register_demo_metabox() {
$prefix = 'yourprefix_demo_';
$cmb_demo = new_cmb2_box( array(
'id' => $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 = '
<div class="advanced-toggle advanced-toggle-wrap postbox closed">
<button type="button" class="handlediv button-link" aria-expanded="true"><span class="screen-reader-text">Click to toggle</span><span class="toggle-indicator" aria-hidden="true"></span></button>
<h3 class="hndle ui-sortable-handle"><span>Toggle Advanced Options</span></h3>
<div class="inside">
';
$advanced_close = '</div></div>';
$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
================================================
<?php
/**
* Register a wysiwyg field and add the wordcount below it.
*/
function yourprefix_feat_img_fields() {
$cmb = new_cmb2_box( array(
'id' => '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' ) );
?>
<p id="<?php echo $field->id(); ?>-word-count" class="hide-if-no-js cmb2-wysiwyg-word-count"><?php printf( __( 'Word count: %s' ), '<span class="word-count">0</span>' ); ?></p>
<script type="text/javascript">
jQuery( function( $ ) {
var editorId = '<?php echo $field->id(); ?>';
/**
* TinyMCE word count display
*/
( function( $, counter ) {
$( function() {
var $content = $( '#' + editorId ),
$count = $( '#' + editorId + '-word-count' ).find( '.word-count' ),
prevCount = 0,
contentEditor;
/**
* Get the word count from TinyMCE and display it
*/
function update() {
var text, count;
if ( ! contentEditor || contentEditor.isHidden() ) {
text = $content.val();
} else {
text = contentEditor.getContent( { format: 'raw' } );
}
count = counter.count( text );
if ( count !== prevCount ) {
$count.text( count );
}
prevCount = count;
}
/**
* Bind the word count update triggers.
*
* When a node change in the main TinyMCE editor has been triggered.
* When a key has been released in the plain text content editor.
*/
$( document ).on( 'tinymce-editor-init', function( event, editor ) {
if ( editor.id !== editorId ) {
return;
}
contentEditor = editor;
editor.on( 'nodechange keyup', _.debounce( update, 1000 ) );
} );
$content.on( 'input keyup', _.debounce( update, 1000 ) );
update();
} );
} )( jQuery, new wp.utils.WordCounter() );
});
</script>
<?php
}
================================================
FILE: misc/cmb2-field-in-publish-box.php
================================================
<?php
/**
* Add a CMB2 field to the WordPress publish box.
*
* @author Chris Reynolds <chris@hmn.md>
* @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' => '<label for="' . $prefix . 'field">' . __( 'Your field name', 'cmb2' ) . '</label>', // 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
================================================
<?php
/**
* Miscellaneous CMB2 Helper functions
*/
/**
* Save fields data from an array of data (Likely $_POST data.)
*
* @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_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
================================================
<?php
/**
* Display CMB2 fields in the featured-image metabox.
*/
function yourprefix_feat_img_fields() {
$cmb = new_cmb2_box( array(
'id' => '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' => '<style>
#cmb2-metabox-feat-image-fields .cmb-th,
#cmb2-metabox-feat-image-fields .cmb-td,
#side-sortables .cmb2-wrap #cmb2-metabox-feat-image-fields .cmb-row {
padding: 0;
}
</style>',
) );
}
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
================================================
<?php
/**
* Display CMB2 fields in other areas of the post screen (not in metaboxes)
*/
/**
* Hook in and add a demo metabox.
*/
function yourprefix_register_cmb2_fields() {
$cmb = new_cmb2_box( array(
'id' => '_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
================================================
<?php
/**
* If you want to replace the default WordPress excerpt field with CMB2 field,
* it can be done with the following snippets.
*/
function cmb2_register_excerpt_replacement_box() {
$cmb = new_cmb2_box( array(
'id' => '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. <a href="https://codex.wordpress.org/Excerpt" target="_blank">Learn more about manual excerpts.</a>',
'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
================================================
<?php
/**
* Use CMB2 fields to replace WordPress title/content/thumbnail fields.
*/
/**
* Register a dummy cpt for demonstration
*/
function register_test_cpt() {
$labels = array(
'name' => '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
================================================
<?php
// Do your $cmb = new_cmb2_box(), then add this field.
// See https://github.com/WebDevStudios/CMB2/blob/develop/example-functions.php for more.
/**
* The 'file' type accepts any type of file which WordPress allows.
* We want to change our text to indicate that they should be images.
*/
$cmb->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
================================================
<?php
// Do your $cmb = new_cmb2_box(), then add this field.
// See https://github.com/WebDevStudios/CMB2/blob/develop/example-functions.php for more.
/**
* A CMB2 Readonly Field Type
*/
$cmb->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
================================================
<?php
/**
* CMB2 Network Settings
* @version 0.1.0
*/
class Prefix_Add_CMB2_To_Settings_Page {
/**
* Option key, and option page slug
* @var string
*/
protected $key = 'myprefix_settings';
/**
* Settings page metabox id
* @var string
*/
protected $metabox_id = 'myprefix_setting_metabox';
/**
* Settings page screen id where metabox should show.
* @var string
*/
protected $screen_id = 'options-general';
/**
* Holds an instance of the project
*
* @Prefix_Add_CMB2_To_Settings_Page
**/
protected static $instance = null;
/**
* Constructor
* @since 0.1.0
*/
protected function __construct() {}
/**
* Get the running object
*
* @return Prefix_Add_CMB2_To_Settings_Page
**/
public static function get_instance() {
if( is_null( self::$instance ) ) {
self::$instance = new self();
self::$instance->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() {
?>
<div id="cmb2-options-page-<?php echo $this->key; ?>" class="wrap cmb2-options-page <?php echo $this->key; ?>" style="display:none">
<?php cmb2_get_metabox( $this->metabox_id, $this->key, 'options-page' )->show_form(); ?>
</div>
<script type="text/javascript">
var cmb2 = document.getElementById( 'cmb2-options-page-<?php echo $this->key; ?>' );
var submit = document.getElementById( 'submit' ).parentNode;
submit.parentNode.insertBefore( cmb2, submit );
cmb2.style.display = '';
</script>
<?php
}
/**
* Public getter method for retrieving protected/private variables
* @since 0.1.0
* @param string $field Field to retrieve
* @return mixed Field value or exception is thrown
*/
public function __get( $field ) {
// Allowed fields to retrieve
if ( in_array( $field, array( 'key', 'metabox_id', 'screen_id' ), true ) ) {
return $this->{$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
================================================
<?php
add_action( 'cmb2_admin_init', 'yourprefix_register_theme_options_metabox' );
/**
* Hook in and register a metabox to handle a theme options page and adds a menu item.
*/
function yourprefix_register_theme_options_metabox() {
$cmb_options = new_cmb2_box( array(
'id' => '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.
?>
<div class="wrap cmb2-options-page option-<?php echo $hookup->option_key; ?>">
<?php if ( $hookup->cmb->prop( 'title' ) ) : ?>
<h2><?php echo wp_kses_post( $hookup->cmb->prop( 'title' ) ); ?></h2>
<?php endif; ?>
<?php if ( $hookup->cmb->prop( 'description' ) ) : ?>
<h2><?php echo wp_kses_post( $hookup->cmb->prop( 'description' ) ); ?></h2>
<?php endif; ?>
<form class="cmb-form" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="POST" id="<?php echo $hookup->cmb->cmb_id; ?>" enctype="multipart/form-data" encoding="multipart/form-data">
<input type="hidden" name="action" value="<?php echo esc_attr( $hookup->option_key ); ?>">
<?php $hookup->options_page_metabox(); ?>
<?php submit_button( esc_attr( $hookup->cmb->prop( 'save_button' ) ), 'primary', 'submit-cmb' ); ?>
</form>
</div>
<?php
}
================================================
FILE: options-and-settings-pages/genesis-cpt-archive-metabox.php
================================================
<?php
/**
* CMB2 Genesis CPT Archive Metabox
*
* To fetch these options, use `genesis_get_cpt_option()`, e.g.
* // In CPT archive template:
* if ( genesis_has_post_type_archive_support() ) {
* $color = genesis_get_cpt_option( 'test_colorpicker' );
* }
*
* @version 0.1.0
*/
class Myprefix_Genesis_CPT_Settings_Metabox {
/**
* Metabox id
*
* @var string
*/
protected $metabox_id = 'genesis-cpt-archive-settings-metabox-%1$s';
/**
* CPT slug
*
* @var string
*/
protected $post_type = '';
/**
* CPT slug
*
* @var string
*/
protected $admin_hook = '%1$s_page_genesis-cpt-archive-%1$s';
/**
* Option key, and option page slug
*
* @var string
*/
protected $key = 'genesis-cpt-archive-settings-%1$s';
/**
* Holds an instance of CMB2
*
* @var CMB2
*/
protected $cmb = null;
/**
* Holds all instances of this class.
*
* @var Myprefix_Genesis_CPT_Settings_Metabox
*/
protected static $instances = array();
/**
* Returns an instance.
*
* @since 0.1.0
*
* @param string $post_type Post type slug.
*
* @return Myprefix_Genesis_CPT_Settings_Metabox
*/
public static function get_instance( $post_type ) {
if ( empty( self::$instances[ $post_type ] ) ) {
self::$instances[ $post_type ] = new self( $post_type );
self::$instances[ $post_type ]->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_p
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
SYMBOL INDEX (230 symbols across 73 files)
FILE: api/cmb2-file-list-ordered.php
function yourprefix_cmb2_ordered_file_list_array_in_api (line 17) | function yourprefix_cmb2_ordered_file_list_array_in_api( $value, $field ) {
function yourprefix_cmb2_ordered_file_list_array_in_api_2 (line 50) | function yourprefix_cmb2_ordered_file_list_array_in_api_2( $value, $fiel...
FILE: conditional-display/exclude-for-ids.php
function cmb2_exclude_for_ids (line 19) | function cmb2_exclude_for_ids( $cmb ) {
FILE: conditional-display/hide-on-new-post-page.php
function tgm_exclude_from_new (line 22) | function tgm_exclude_from_new( $cmb ) {
FILE: conditional-display/show-for-taxonomy-terms.php
function be_taxonomy_show_on_filter (line 24) | function be_taxonomy_show_on_filter( $cmb ) {
FILE: conditional-display/show-if-matching-meta-value.php
function cmb2_register_conditional_metabox (line 11) | function cmb2_register_conditional_metabox() {
function cmb_only_show_for_external (line 54) | function cmb_only_show_for_external( $cmb ) {
FILE: conditional-display/show-only-for-top-level-posts.php
function ba_metabox_add_for_top_level_posts_only (line 19) | function ba_metabox_add_for_top_level_posts_only( $cmb ) {
FILE: custom-field-types/address-field-type/address-field-type.php
function jt_cmb2_address_field (line 18) | function jt_cmb2_address_field( $metakey, $post_id = 0 ) {
function jt_cmb2_get_address_field (line 30) | function jt_cmb2_get_address_field( $metakey, $post_id = 0 ) {
function cmb2_init_address_field (line 57) | function cmb2_init_address_field() {
FILE: custom-field-types/address-field-type/class-cmb2-render-address-field.php
class CMB2_Render_Address_Field (line 6) | class CMB2_Render_Address_Field extends CMB2_Type_Base {
method init (line 15) | public static function init() {
method class_name (line 28) | public static function class_name() { return __CLASS__; }
method render (line 33) | public function render() {
method maybe_save_split_values (line 145) | public static function maybe_save_split_values( $override_value, $valu...
method sanitize (line 165) | public static function sanitize( $check, $meta_value, $object_id, $fie...
method escape (line 179) | public static function escape( $check, $meta_value, $field_args, $fiel...
method get_split_meta_value (line 192) | public static function get_split_meta_value( $data, $object_id, $field...
FILE: custom-field-types/associate-wp-menu-field.php
function cmb2_register_post_menu_box (line 9) | function cmb2_register_post_menu_box() {
class CMB2_Post_Menu_Association (line 23) | class CMB2_Post_Menu_Association {
method get_instance (line 39) | public static function get_instance() {
method __construct (line 47) | protected function __construct() {
method register_post_menu_box (line 52) | public function register_post_menu_box() {
method register_post_menu_box_args (line 56) | public function register_post_menu_box_args() {
method get_menus_list_options (line 81) | public function get_menus_list_options() {
method post_menu_edit_or_create_link (line 93) | function post_menu_edit_or_create_link( $args, $field ) {
method associate_menu_post_message (line 128) | public function associate_menu_post_message() {
method associate_menu_message (line 140) | public function associate_menu_message( $post_id, $message ) {
method set_menu_to_post (line 166) | public function set_menu_to_post( $menu_id ) {
method redirect_with_post_association (line 186) | public function redirect_with_post_association( $location ) {
method menu_title_meta_key (line 195) | public function menu_title_meta_key() {
class CMB2_Post_Menu_Widget (line 209) | class CMB2_Post_Menu_Widget extends WP_Widget {
method __construct (line 217) | public function __construct() {
method widget (line 236) | public function widget( $args, $instance ) {
method update (line 296) | public function update( $new_instance, $old_instance ) {
method form (line 313) | public function form( $instance ) {
function cmb2_register_post_menu_widget (line 328) | function cmb2_register_post_menu_widget() {
FILE: custom-field-types/autocomplete-field-type.php
function autocomplete_cmb2_meta_boxes (line 36) | function autocomplete_cmb2_meta_boxes() {
function autocomplete_cmb2_get_post_title_from_id (line 97) | function autocomplete_cmb2_get_post_title_from_id($id) {
function autocomplete_cmb2_render_autocomplete (line 118) | function autocomplete_cmb2_render_autocomplete($field_object, $escaped_v...
function autocomplete_cmb2_get_post_options_using_post_type (line 240) | function autocomplete_cmb2_get_post_options_using_post_type($post_type, ...
function autocomplete_cmb2_admin_enqueue_scripts (line 278) | function autocomplete_cmb2_admin_enqueue_scripts() {
function autocomplete_cmb2_get_post_autocomplete_options (line 285) | function autocomplete_cmb2_get_post_autocomplete_options() {
FILE: custom-field-types/button-field-type.php
function jt_cmb2__cmb_render_button (line 34) | function jt_cmb2__cmb_render_button( $field, $escaped_value, $object_id,...
FILE: custom-field-types/dashicon-radio-field/dashicon-radio-field.php
function ml_cmb2_render_dashicon_radio_callback (line 21) | function ml_cmb2_render_dashicon_radio_callback( $field, $escaped_value,...
function ml_cmb2_dashicon_radio_attributes (line 42) | function ml_cmb2_dashicon_radio_attributes( $args, $defaults, $field, $c...
function ml_cmb2_dashicon_radio_css (line 55) | function ml_cmb2_dashicon_radio_css() {
function ml_cmb2_dashicons_return_array (line 85) | function ml_cmb2_dashicons_return_array() {
FILE: custom-field-types/default-category-field.php
function cmb2_render_default_categories_field_type (line 17) | function cmb2_render_default_categories_field_type( $field, $escaped_val...
function cmb2_default_categories_let_wp_save (line 36) | function cmb2_default_categories_let_wp_save( $null, $a, $field_args, $f...
function cmb2_remove_default_category_metabox_for_taxonomy (line 46) | function cmb2_remove_default_category_metabox_for_taxonomy() {
FILE: custom-field-types/default-tags-field.php
function cmb2_render_default_tags_field_type (line 17) | function cmb2_render_default_tags_field_type( $field, $escaped_value, $o...
function cmb2_init_post_tag_box (line 37) | function cmb2_init_post_tag_box() {
function cmb2_default_tags_let_wp_save (line 47) | function cmb2_default_tags_let_wp_save( $null, $a, $field_args, $field ) {
function cmb2_remove_default_tag_metabox_for_taxonomy (line 57) | function cmb2_remove_default_tag_metabox_for_taxonomy() {
FILE: custom-field-types/form-field-field-type.php
function jt_cmb2_render_formfield_field_callback (line 49) | function jt_cmb2_render_formfield_field_callback( $field, $value, $objec...
function jt_cmb2_sanitize_formfield_field (line 140) | function jt_cmb2_sanitize_formfield_field( $check, $meta_value, $object_...
function jt_cmb2_types_esc_formfield_field (line 166) | function jt_cmb2_types_esc_formfield_field( $check, $meta_value, $field_...
FILE: custom-field-types/multicheck_posttype-field_type.php
function ds_cmb_render_multicheck_posttype (line 11) | function ds_cmb_render_multicheck_posttype( $field, $escaped_value, $obj...
FILE: custom-field-types/multicheck_title-field_type.php
function cmb_render_multicheck_title (line 25) | function cmb_render_multicheck_title( $field, $escaped_value, $object_id...
FILE: custom-field-types/post-list-field-type.php
function cmb2_post_list_render_field (line 7) | function cmb2_post_list_render_field( $field, $escaped_value, $object_id...
FILE: custom-field-types/select-multiple-field-type.php
function cmb2_render_select_multiple_field_type (line 16) | function cmb2_render_select_multiple_field_type( $field, $escaped_value,...
function cmb2_sanitize_select_multiple_callback (line 40) | function cmb2_sanitize_select_multiple_callback( $override_value, $value...
FILE: custom-field-types/star-rating-field-type/star-rating-field-type.php
function eh_cmb2_star_rating_field (line 18) | function eh_cmb2_star_rating_field( $metakey, $post_id = 0 ) {
function eh_cmb2_get_star_rating_field (line 30) | function eh_cmb2_get_star_rating_field( $metakey, $post_id = 0 ) {
function eh_cmb2_render_star_rating_field_callback (line 67) | function eh_cmb2_render_star_rating_field_callback( $field, $value, $obj...
FILE: custom-field-types/taxonomy-radio-with-image-field-type/DJ_Taxonomy_Radio_Hierarchical_With_Image.php
class DJ_Taxonomy_Radio_Hierarchical_With_Image (line 6) | class DJ_Taxonomy_Radio_Hierarchical_With_Image extends CMB2_Type_Taxono...
method build_children (line 18) | protected function build_children( $parent_term, $saved ) {
method list_term_input (line 39) | protected function list_term_input( $term, $saved_term ) {
method list_input (line 45) | public function list_input( $args = array(), $i ) {
FILE: custom-field-types/taxonomy-radio-with-image-field-type/DJ_Taxonomy_Radio_With_Image_Display.php
class DJ_Taxonomy_Radio_With_Image_Display (line 6) | class DJ_Taxonomy_Radio_With_Image_Display extends CMB2_Display_Taxonomy...
FILE: custom-field-types/taxonomy-radio-with-image-field-type/taxonomy-radio-with-image-field-type.php
function dj_taxonomy_radio_with_image_field_type_class_name (line 7) | function dj_taxonomy_radio_with_image_field_type_class_name() {
function dj_taxonomy_radio_with_image_field_type_display_class_name (line 15) | function dj_taxonomy_radio_with_image_field_type_display_class_name() {
function dj_add_taxonomy_radio_with_image (line 23) | function dj_add_taxonomy_radio_with_image( $types ) {
function dj_taxonomy_radio_with_image_sanitize (line 29) | function dj_taxonomy_radio_with_image_sanitize( $check, $meta_value, $ob...
function cmb2_init_taxonomy_radio_with_image_field_type (line 35) | function cmb2_init_taxonomy_radio_with_image_field_type() {
FILE: custom-field-types/textarea-with-checkbox.php
class CMB2_Field_Textarea_With_Checkbox (line 16) | class CMB2_Field_Textarea_With_Checkbox {
method __construct (line 25) | public function __construct() {
method render_textarea_with_checkbox (line 31) | public function render_textarea_with_checkbox( $field, $field_escaped_...
method sanitize_textarea_with_checkbox (line 64) | public static function sanitize_textarea_with_checkbox( $check, $meta_...
method escape_textarea_with_checkbox (line 82) | public static function escape_textarea_with_checkbox( $check, $meta_va...
FILE: custom-field-types/year-range-field-type.php
function jt_cmb2_date_year_range (line 62) | function jt_cmb2_date_year_range( $field, $value, $object_id, $object_ty...
function jt_cmb2_date_year_range_js (line 115) | function jt_cmb2_date_year_range_js() {
function jt_cmb2_date_year_range_options (line 173) | function jt_cmb2_date_year_range_options( $type_object, $earliest, $valu...
function jt_cmb2_date_year_range_split_values (line 218) | function jt_cmb2_date_year_range_split_values( $override_value, $value, ...
function jt_cmb2_date_year_range_get_split_values (line 240) | function jt_cmb2_date_year_range_get_split_values( $no_override, $object...
function jt_cmb2_sanitize_date_year_range (line 259) | function jt_cmb2_sanitize_date_year_range( $check, $meta_value, $object_...
function jt_cmb2_esc_date_year_range (line 274) | function jt_cmb2_esc_date_year_range( $check, $meta_value, $field_args, ...
FILE: filters-and-actions/cmb2-add-fields-dynamically.php
function register_dynamic_fields_box (line 8) | function register_dynamic_fields_box() {
function add_fields_dynamically_to_box (line 35) | function add_fields_dynamically_to_box( $cmb ) {
FILE: filters-and-actions/cmb2_all_or_nothing_types-filter.php
function add_select2_to_all_or_nothing_types (line 8) | function add_select2_to_all_or_nothing_types( $types ) {
FILE: filters-and-actions/cmb2_before_form-and-cmb2_after_form-hooks.php
function yourprefix_add_html_before_cmb2_output (line 10) | function yourprefix_add_html_before_cmb2_output( $cmb_id, $object_id, $o...
function yourprefix_add_html_after_cmb2_output (line 23) | function yourprefix_add_html_after_cmb2_output( $cmb_id, $object_id, $ob...
function add_html_before_yourprefix_demo_metabox_output (line 30) | function add_html_before_yourprefix_demo_metabox_output( $cmb_id, $objec...
function add_html_after_yourprefix_demo_metabox_output (line 39) | function add_html_after_yourprefix_demo_metabox_output( $cmb_id, $object...
FILE: filters-and-actions/cmb2_init_$cmb_id-add-fields.php
function yourprefix_add_new_field_to_top_of_demo_metabox (line 6) | function yourprefix_add_new_field_to_top_of_demo_metabox( $cmb ) {
FILE: filters-and-actions/cmb2_init_$cmb_id-modify-object-types.php
function yourprefix_demo_metabox_modify_object_types (line 11) | function yourprefix_demo_metabox_modify_object_types( $cmb ) {
FILE: filters-and-actions/cmb2_init_$cmb_id-remove-field.php
function yourprefix_remove_field_from_demo_metabox (line 6) | function yourprefix_remove_field_from_demo_metabox( $cmb ) {
FILE: filters-and-actions/cmb2_init_$cmb_id-replace-field.php
function yourprefix_replace_field_in_demo_metaboxx (line 7) | function yourprefix_replace_field_in_demo_metaboxx( $cmb ) {
FILE: filters-and-actions/cmb2_init_before_hookup-add-fields.php
function yourprefix_add_new_field_in_3rd_position (line 6) | function yourprefix_add_new_field_in_3rd_position() {
function yourprefix_add_new_field_to_group (line 38) | function yourprefix_add_new_field_to_group() {
FILE: filters-and-actions/cmb2_init_before_hookup-remove-cmb2-metabox.php
function yourprefix_remove_metabox (line 5) | function yourprefix_remove_metabox() {
FILE: filters-and-actions/cmb2_init_before_hookup-update-existing-fields.php
function yourprefix_update_fields_properties (line 6) | function yourprefix_update_fields_properties() {
FILE: filters-and-actions/cmb2_override_{$field_id}_meta_value-filter.php
function yourprefix_get_default_group_value_from_json (line 31) | function yourprefix_get_default_group_value_from_json( $value, $object_i...
FILE: filters-and-actions/custom-css-for-specific-metabox.php
function js_custom_css_for_metabox (line 9) | function js_custom_css_for_metabox() {
function js_add_custom_css_for_metabox (line 23) | function js_add_custom_css_for_metabox( $post_id, $cmb ) {
FILE: filters-and-actions/disable-styles-on-front-end-forms.php
function yourprefix_disable_cmb2_front_end_styles (line 10) | function yourprefix_disable_cmb2_front_end_styles( $enabled ) {
FILE: filters-and-actions/localize-date-format.php
function prefix_cmb_set_date_format (line 16) | function prefix_cmb_set_date_format( $l10n ) {
FILE: filters-and-actions/override-cmb2-data-source.php
function yourprefix_register_yourprefix_group_alt_data_metabox (line 12) | function yourprefix_register_yourprefix_group_alt_data_metabox() {
function yourprefix_group_alt_data_demo_override_meta_value (line 74) | function yourprefix_group_alt_data_demo_override_meta_value( $data, $obj...
function yourprefix_group_alt_data_demo_override_meta_save (line 82) | function yourprefix_group_alt_data_demo_override_meta_save( $override, $...
function yourprefix_group_alt_data_demo_override_meta_remove (line 91) | function yourprefix_group_alt_data_demo_override_meta_remove( $override,...
FILE: filters-and-actions/save-default-group-field-value-based-on-other-field.php
function yourprefix_register_repeatable_group_field_metabox (line 8) | function yourprefix_register_repeatable_group_field_metabox() {
function hook_in_and_add_default_group_value (line 59) | function hook_in_and_add_default_group_value( $post_id, $updated, $cmb ) {
FILE: front-end/cmb2-front-end-editor.php
function jt_add_edit_form_to_frontend (line 6) | function jt_add_edit_form_to_frontend( $content ) {
function jt_modify_edit_link (line 22) | function jt_modify_edit_link( $link ) {
function jt_edit_core_fields (line 33) | function jt_edit_core_fields() {
function jt_edit_core_maybe_redirect (line 60) | function jt_edit_core_maybe_redirect() {
function jt_cmb2_override_core_field_get (line 70) | function jt_cmb2_override_core_field_get( $val, $object_id, $a, $field ) {
function jt_cmb2_override_core_field_set (line 88) | function jt_cmb2_override_core_field_set( $status, $a, $args, $field ) {
FILE: front-end/cmb2-front-end-submit.php
function yourprefix_frontend_form_register (line 10) | function yourprefix_frontend_form_register() {
function yourprefix_maybe_set_default_from_posted_values (line 80) | function yourprefix_maybe_set_default_from_posted_values( $args, $field ) {
function yourprefix_frontend_cmb2_get (line 93) | function yourprefix_frontend_cmb2_get() {
function yourprefix_do_frontend_form_submission_shortcode (line 110) | function yourprefix_do_frontend_form_submission_shortcode( $atts = array...
function yourprefix_handle_frontend_new_post_form_submission (line 174) | function yourprefix_handle_frontend_new_post_form_submission() {
function yourprefix_frontend_form_photo_upload (line 260) | function yourprefix_frontend_form_photo_upload( $post_id, $attachment_po...
FILE: front-end/cmb2-front-end-wordpress-media-uploader.php
function nevestam_allow_contributor_uploads (line 12) | function nevestam_allow_contributor_uploads() {
function nevestam_restrict_media_library (line 40) | function nevestam_restrict_media_library( $wp_query_obj ) {
FILE: front-end/cmb2-metabox-shortcode.php
function jt_cmb2_do_frontend_form_shortcode (line 22) | function jt_cmb2_do_frontend_form_shortcode( $atts = array() ) {
FILE: front-end/output-file-list.php
function jt_cmb2_file_list_images (line 16) | function jt_cmb2_file_list_images( $file_list_meta_key, $img_size = 'med...
function jt_cmb2_get_file_list_images (line 27) | function jt_cmb2_get_file_list_images( $file_list_meta_key, $img_size = ...
FILE: helper-functions/helper-functions.php
function yourprefix_upload_file_for_cmb2 (line 17) | function yourprefix_upload_file_for_cmb2( $files_key, $post_id, $meta_ke...
function yourprefix_sideload_file_for_cmb2 (line 62) | function yourprefix_sideload_file_for_cmb2( $file_url, $post_id, $meta_k...
function yourprefix_get_cmb2_wysiwyg_output (line 109) | function yourprefix_get_cmb2_wysiwyg_output( $meta_key, $post_id = 0 ) {
function yourprefix_cmb2_output_file_list (line 135) | function yourprefix_cmb2_output_file_list( $meta_key, $img_size = 'mediu...
FILE: helper-functions/modify-cmb2_metabox_form-output.php
function myprefix_options_modify_cmb2_metabox_form_format (line 22) | function myprefix_options_modify_cmb2_metabox_form_format( $form_format,...
FILE: javascript/cmb2-auto-scroll-to-new-group.php
function jt_cmb_group_autoscroll_js (line 10) | function jt_cmb_group_autoscroll_js() {
FILE: javascript/cmb2-js-validation-required.php
function cmb2_after_form_do_js_validation (line 13) | function cmb2_after_form_do_js_validation( $post_id, $cmb ) {
FILE: javascript/dynamically-change-group-field-title-from-subfield.php
function yourprefix_register_repeatable_group_field_title_example (line 11) | function yourprefix_register_repeatable_group_field_title_example() {
function yourprefix_add_js_for_repeatable_titles (line 50) | function yourprefix_add_js_for_repeatable_titles() {
function yourprefix_add_js_for_repeatable_titles_to_footer (line 54) | function yourprefix_add_js_for_repeatable_titles_to_footer() {
FILE: javascript/limit-number-of-multiple-repeat-groups.php
function js_limited_group_setup (line 9) | function js_limited_group_setup() {
function js_limit_group_repeat (line 89) | function js_limit_group_repeat( $post_id, $cmb ) {
FILE: javascript/limit-number-of-repeat-fields.php
function js_limited_repeat_field_setup (line 10) | function js_limited_repeat_field_setup() {
function js_limit_field_repeat (line 28) | function js_limit_field_repeat( $post_id, $cmb ) {
FILE: javascript/limit-number-of-repeat-groups.php
function js_limited_group_setup (line 10) | function js_limited_group_setup() {
function js_limit_group_repeat (line 48) | function js_limit_group_repeat( $post_id, $cmb ) {
FILE: misc/add-wrap-to-group-of-fields.php
function yourprefix_register_demo_metabox (line 11) | function yourprefix_register_demo_metabox() {
FILE: misc/adding-wordcount-to-cmb2-wysiwyg-field.php
function yourprefix_feat_img_fields (line 6) | function yourprefix_feat_img_fields() {
function cmb2_wysiwyg_word_counter (line 29) | function cmb2_wysiwyg_word_counter( $args, $field ) {
FILE: misc/cmb2-field-in-publish-box.php
function yourprefix_cmb2_fields (line 14) | function yourprefix_cmb2_fields() {
function yourprefix_filter_publish_box (line 41) | function yourprefix_filter_publish_box( $post ) {
FILE: misc/helper-functions.php
function cmb2_save_metabox_fields_data (line 16) | function cmb2_save_metabox_fields_data( $meta_box_id, $object_id, array ...
function cmb2_get_metabox_sanitized_values (line 34) | function cmb2_get_metabox_sanitized_values( $meta_box_id, array $data_to...
FILE: misc/outputting-cmb2-fields-in-featured-image-metabox.php
function yourprefix_feat_img_fields (line 6) | function yourprefix_feat_img_fields() {
function yourprefix_feat_img_output_fields (line 34) | function yourprefix_feat_img_output_fields( $content, $post_id, $thumbna...
FILE: misc/outputting-forms-outside-metaboxes.php
function yourprefix_register_cmb2_fields (line 9) | function yourprefix_register_cmb2_fields() {
function yourprefix_output_custom_mb_location (line 37) | function yourprefix_output_custom_mb_location() {
FILE: misc/replace-wp-excerpt-with-cmb2-field.php
function cmb2_register_excerpt_replacement_box (line 7) | function cmb2_register_excerpt_replacement_box() {
function cmb2_admin_hide_excerpt_field (line 35) | function cmb2_admin_hide_excerpt_field() {
function _cmb2_admin_hide_excerpt_field (line 40) | function _cmb2_admin_hide_excerpt_field() {
function cmb2_override_excerpt_display (line 52) | function cmb2_override_excerpt_display( $data, $post_id ) {
FILE: misc/replace-wp-title-content-thumbnail-with-cmb2-fields.php
function register_test_cpt (line 9) | function register_test_cpt() {
function register_test_cpt_metabox (line 36) | function register_test_cpt_metabox() {
function cmb2_override_post_title_display (line 78) | function cmb2_override_post_title_display( $data, $post_id ) {
function cmb2_override_post_content_display (line 81) | function cmb2_override_post_content_display( $data, $post_id ) {
FILE: options-and-settings-pages/add-cmb2-settings-to-other-settings-pages.php
class Prefix_Add_CMB2_To_Settings_Page (line 6) | class Prefix_Add_CMB2_To_Settings_Page {
method __construct (line 37) | protected function __construct() {}
method get_instance (line 44) | public static function get_instance() {
method hooks (line 56) | public function hooks() {
method register_metabox (line 66) | function register_metabox() {
method maybe_save (line 97) | public function maybe_save() {
method save_our_options (line 122) | public function save_our_options( $whitelist_options ) {
method maybe_hookup_fields (line 144) | public function maybe_hookup_fields() {
method admin_page_display (line 162) | public function admin_page_display() {
method __get (line 182) | public function __get( $field ) {
function myprefix_cmb2_on_settings (line 198) | function myprefix_cmb2_on_settings() {
function myprefix_get_option (line 210) | function myprefix_get_option( $key = '', $default = false ) {
FILE: options-and-settings-pages/custom-display-callback.php
function yourprefix_register_theme_options_metabox (line 6) | function yourprefix_register_theme_options_metabox() {
function yourprefix_theme_options_page_output (line 28) | function yourprefix_theme_options_page_output( $hookup ) {
FILE: options-and-settings-pages/genesis-cpt-archive-metabox.php
class Myprefix_Genesis_CPT_Settings_Metabox (line 14) | class Myprefix_Genesis_CPT_Settings_Metabox {
method get_instance (line 67) | public static function get_instance( $post_type ) {
method __construct (line 83) | protected function __construct( $post_type ) {
method hooks (line 95) | public function hooks() {
method init (line 107) | public function init() {
method admin_hooks (line 117) | public function admin_hooks() {
method add_meta_box (line 133) | public function add_meta_box() {
method output_metabox (line 150) | public function output_metabox() {
method add_sanitized_values (line 164) | public function add_sanitized_values( $new_value ) {
method init_metabox (line 184) | public function init_metabox() {
method __get (line 235) | public function __get( $field ) {
function myprefix_genesis_cpt_settings (line 259) | function myprefix_genesis_cpt_settings( $post_type ) {
FILE: options-and-settings-pages/genesis-settings-metabox.php
class Myprefix_Genesis_Settings_Metabox (line 11) | class Myprefix_Genesis_Settings_Metabox {
method get_instance (line 60) | public static function get_instance() {
method __construct (line 74) | protected function __construct() {
method hooks (line 82) | public function hooks() {
method admin_hooks (line 92) | public function admin_hooks() {
method add_meta_box (line 109) | public function add_meta_box() {
method output_metabox (line 126) | public function output_metabox() {
method add_sanitized_values (line 140) | public function add_sanitized_values( $new_value ) {
method init_metabox (line 160) | public function init_metabox() {
method __get (line 211) | public function __get( $field ) {
function myprefix_genesis_settings_metabox (line 233) | function myprefix_genesis_settings_metabox() {
FILE: options-and-settings-pages/network-options-cmb.php
function myprefix_register_network_options_metabox (line 13) | function myprefix_register_network_options_metabox() {
function myprefix_get_network_option (line 71) | function myprefix_get_network_option( $key = '', $default = false ) {
FILE: options-and-settings-pages/non-cmb2-options-page.php
function wporg_settings_init (line 14) | function wporg_settings_init() {
function wporg_section_developers_callback (line 58) | function wporg_section_developers_callback( $args ) {
function wporg_field_pill_cb (line 74) | function wporg_field_pill_cb( $args ) {
function wporg_options_page (line 102) | function wporg_options_page() {
function wporg_options_page_html (line 123) | function wporg_options_page_html() {
function wporg_options_page_to_cmb2_tabs (line 162) | function wporg_options_page_to_cmb2_tabs( $tabs, $tab_group ) {
FILE: options-and-settings-pages/options-pages-with-submenus.php
function yourprefix_register_main_options_metabox (line 6) | function yourprefix_register_main_options_metabox() {
FILE: options-and-settings-pages/options-pages-with-tabs-and-submenus.php
function yourprefix_register_main_options_metabox (line 5) | function yourprefix_register_main_options_metabox() {
function yourprefix_options_display_with_tabs (line 107) | function yourprefix_options_display_with_tabs( $cmb_options ) {
function yourprefix_options_page_tabs (line 136) | function yourprefix_options_page_tabs( $cmb_options ) {
FILE: options-and-settings-pages/submenu-options-pages.php
function yourprefix_register_options_submenu_for_page_post_type (line 6) | function yourprefix_register_options_submenu_for_page_post_type() {
function yourprefix_register_options_submenu_appearance_menu (line 48) | function yourprefix_register_options_submenu_appearance_menu() {
FILE: options-and-settings-pages/theme-options-cmb.php
function myprefix_register_theme_options_metabox (line 13) | function myprefix_register_theme_options_metabox() {
function myprefix_get_option (line 70) | function myprefix_get_option( $key = '', $default = false ) {
FILE: widgets/widget-example.php
class CMB2_Widget_Boilerplate (line 16) | class CMB2_Widget_Boilerplate extends WP_Widget {
method __construct (line 65) | public function __construct() {
method flush_widget_cache (line 130) | public function flush_widget_cache() {
method widget (line 140) | public function widget( $args, $instance ) {
method get_widget (line 156) | public static function get_widget( $atts ) {
method update (line 228) | public function update( $new_instance, $old_instance ) {
method form (line 238) | public function form( $instance ) {
method cmb2 (line 255) | public function cmb2( $saving = false ) {
method default_cb (line 289) | public function default_cb( $field_args, $field ) {
function register_wds_widget_boilerplate (line 300) | function register_wds_widget_boilerplate() {
Condensed preview — 92 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (251K chars).
[
{
"path": ".gitignore",
"chars": 470,
"preview": "\n# Created by https://www.gitignore.io/api/osx\n\n### OSX ###\n*.DS_Store\r\n.AppleDouble\r\n.LSOverride\r\n\r\n# Icon must end wit"
},
{
"path": "CONTRIBUTING.md",
"chars": 1227,
"preview": "# Contribute To CMB2 Code Snippet Library\n\nThe CMB2 code snippet library is a community-maintained repository and so con"
},
{
"path": "README.md",
"chars": 1608,
"preview": "CMB2 Code Snippet Library\n========================\n\nThis is a community-maintained repository of code snippets that help"
},
{
"path": "api/README.md",
"chars": 88,
"preview": "CMB2 API Snippets\n==========\n\nSnippets related to the CMB2 API endpoints/functionality.\n"
},
{
"path": "api/cmb2-file-list-ordered.php",
"chars": 1913,
"preview": "<?php\n\n/**\n * By default, when fetching the value for the file_list field via the REST API, the order is\n * obliterated "
},
{
"path": "conditional-display/exclude-for-ids.php",
"chars": 787,
"preview": "<?php\n/**\n * Allow metabox to show up everywhere except a specified list of page IDs.\n * @link https://github.com/WebDev"
},
{
"path": "conditional-display/hide-on-new-post-page.php",
"chars": 1001,
"preview": "<?php\n/**\n * Remove metabox from appearing on post new screens before the post has been saved.\n * Can also add additiona"
},
{
"path": "conditional-display/show-for-taxonomy-terms.php",
"chars": 1524,
"preview": "<?php\n/**\n * This allows you to specify one or more taxonomies, and for each taxonomy one or more terms.\n * If a post is"
},
{
"path": "conditional-display/show-if-matching-meta-value.php",
"chars": 1678,
"preview": "<?php\n/**\n * Only show contact metabox if status set to external.\n * @link https://github.com/WebDevStudios/CMB2/wiki/Ad"
},
{
"path": "conditional-display/show-only-for-top-level-posts.php",
"chars": 716,
"preview": "<?php\n/**\n * Exclude metabox on non top level posts\n * @link https://github.com/WebDevStudios/CMB2/wiki/Adding-your-own-"
},
{
"path": "custom-field-types/README.md",
"chars": 149,
"preview": "Custom Field Types\n==========\n\nSnippets for [adding custom CMB2 field types](https://github.com/WebDevStudios/CMB2/wiki/"
},
{
"path": "custom-field-types/address-field-type/address-field-type.php",
"chars": 2261,
"preview": "<?php\n/*\n * Plugin Name: CMB2 Custom Field Type - Address\n * Description: Makes available an 'address' CMB2 Custom Field"
},
{
"path": "custom-field-types/address-field-type/class-cmb2-render-address-field.php",
"chars": 8346,
"preview": "<?php\n\n/**\n * Handles 'address' custom field type.\n */\nclass CMB2_Render_Address_Field extends CMB2_Type_Base {\n\n\t/**\n\t "
},
{
"path": "custom-field-types/associate-wp-menu-field.php",
"chars": 10403,
"preview": "<?php\n/**\n * Associates a WP menu with a post, and provides links between the post/menu editing interfaces.\n * Screensho"
},
{
"path": "custom-field-types/autocomplete-field-type.php",
"chars": 9315,
"preview": "<?php\n\n/*\n * Plugin Name: CMB2 Custom Field Type - Autocomplete\n * Description: Makes available an autocomplete custom f"
},
{
"path": "custom-field-types/button-field-type.php",
"chars": 1211,
"preview": "<?php\n/*\n * Button field type\n * Screenshot: https://github.com/CMB2/CMB2/assets/1098900/c8e1aa00-1947-480d-8c30-bd58f5e"
},
{
"path": "custom-field-types/dashicon-radio-field/dashicon-radio-field.php",
"chars": 16246,
"preview": "<?php\n/*\nPlugin Name: CMB2 Dashicon Radio Field\nDescription: https://github.com/modemlooper/cmb2-dashicon-radio\nVersion:"
},
{
"path": "custom-field-types/default-category-field.php",
"chars": 1771,
"preview": "<?php\n/**\n * CMB2 Default Category field/metabox\n *\n * @package CMB2 Default Category field/metabox\n */\n\n/**\n * Adds a c"
},
{
"path": "custom-field-types/default-tags-field.php",
"chars": 1904,
"preview": "<?php\n/**\n * CMB2 Default Tags field/metabox\n *\n * @package CMB2 Default Tags field/metabox\n */\n\n/**\n * Adds a custom fi"
},
{
"path": "custom-field-types/form-field-field-type.php",
"chars": 6082,
"preview": "<?php\n/*\n * Plugin Name: CMB2 Custom Field Type - Form Fields\n * Description: Makes available a 'formfield' CMB2 Custom "
},
{
"path": "custom-field-types/multicheck_posttype-field_type.php",
"chars": 1364,
"preview": "<?php\n/**\n * CMB2 Multicheck by Post Type\n *\n * @package CMB2 Default Tags field/metabox\n * @author Daniele Mte90 Scasci"
},
{
"path": "custom-field-types/multicheck_title-field_type.php",
"chars": 1657,
"preview": "<?php\n\n/**\n * CMB2 Multicheck by Title\n *\n * @package CMB2 Default Tags field/metabox\n * @author Daniele Mte90 Scasciafr"
},
{
"path": "custom-field-types/post-list-field-type.php",
"chars": 3016,
"preview": "<?php\n//By Daniele Mte90 Scasciafratte\n//Based on https://github.com/WebDevStudios/CMB2-Post-Search-field\n//That field h"
},
{
"path": "custom-field-types/select-multiple-field-type.php",
"chars": 1795,
"preview": "<?php\n/**\n * CMB2 Select Multiple Custom Field Type\n * @package CMB2 Select Multiple Field Type\n */\n\n/**\n * Adds a custo"
},
{
"path": "custom-field-types/star-rating-field-type/css/star-rating-field-type.css",
"chars": 1948,
"preview": "@charset \"UTF-8\";\n#cmb2-star-rating-metabox .star-cb-group {\n /* remove inline-block whitespace */\n font-size: 0;\n /"
},
{
"path": "custom-field-types/star-rating-field-type/star-rating-field-type.php",
"chars": 3515,
"preview": "<?php\n/*\n * Plugin Name: CMB2 Custom Field Type - Star Rating\n * Description: Makes available a 'star_rating' CMB2 Custo"
},
{
"path": "custom-field-types/taxonomy-radio-with-image-field-type/DJ_Taxonomy_Radio_Hierarchical_With_Image.php",
"chars": 2464,
"preview": "<?php\n\n/**\n * Handles 'taxonomy_radio_with_image' custom field type.\n */\nclass DJ_Taxonomy_Radio_Hierarchical_With_Image"
},
{
"path": "custom-field-types/taxonomy-radio-with-image-field-type/DJ_Taxonomy_Radio_With_Image_Display.php",
"chars": 155,
"preview": "<?php\n\n/**\n * Handles 'taxonomy_radio_with_image' custom field type.\n */\nclass DJ_Taxonomy_Radio_With_Image_Display exte"
},
{
"path": "custom-field-types/taxonomy-radio-with-image-field-type/taxonomy-radio-with-image-field-type.php",
"chars": 1743,
"preview": "<?php\n/**\n * Custom field type to add term images to the output of the taxonomy radio field.\n * See https://wordpress.or"
},
{
"path": "custom-field-types/textarea-with-checkbox.php",
"chars": 3284,
"preview": "<?php\n\n/**\n * CMB2 Multicheck by Post Type\n *\n * @package CMB2 Default Tags field/metabox\n * @author Daniele Mte90 Scasc"
},
{
"path": "custom-field-types/year-range-field-type.php",
"chars": 8863,
"preview": "<?php\n/*\n * Year Range field type.. two year-pickers, start and end.\n * Screenshot: http://b.ustin.co/15lKk\n */\n\n/**\n * "
},
{
"path": "filters-and-actions/README.md",
"chars": 152,
"preview": "CMB2 Filters and Actions\n==========\n\nCMB2 has many filters and actions. Included here are snippets which demonstrate som"
},
{
"path": "filters-and-actions/cmb2-add-fields-dynamically.php",
"chars": 1526,
"preview": "<?php\n/**\n * This file demonstrates adding new fields dynamically, based on the existing post meta.\n * @link https://gee"
},
{
"path": "filters-and-actions/cmb2_all_or_nothing_types-filter.php",
"chars": 290,
"preview": "<?php\n\n/**\n * CMB2 has a defined set of \"all or nothing types\".\n * This filter allows us to change that.\n */\n\nfunction a"
},
{
"path": "filters-and-actions/cmb2_before_form-and-cmb2_after_form-hooks.php",
"chars": 1702,
"preview": "<?php\n/**\n * This file demonstrates using the following hooks:\n * cmb2_before_form and cmb2_before_{$object_type}_form_{"
},
{
"path": "filters-and-actions/cmb2_init_$cmb_id-add-fields.php",
"chars": 529,
"preview": "<?php\n/**\n * This file demonstrates adding new fields to a registered CMB2 metaboxes during its \"cmb2_init_{$cmb_id}\" ho"
},
{
"path": "filters-and-actions/cmb2_init_$cmb_id-modify-object-types.php",
"chars": 664,
"preview": "<?php\n/**\n * This snippet demonstrates modifying (during its \"cmb2_init_{$cmb_id}\" hook) the object-types\n * registered "
},
{
"path": "filters-and-actions/cmb2_init_$cmb_id-remove-field.php",
"chars": 341,
"preview": "<?php\n/**\n * This file demonstrates removing fields from a registered CMB2 metaboxes during its \"cmb2_init_{$cmb_id}\" ho"
},
{
"path": "filters-and-actions/cmb2_init_$cmb_id-replace-field.php",
"chars": 842,
"preview": "<?php\n/**\n * This file demonstrates adding replacing a registered field in the CMB2 metaboxe\n * with an id of `_yourpref"
},
{
"path": "filters-and-actions/cmb2_init_before_hookup-add-fields.php",
"chars": 1901,
"preview": "<?php\n/**\n * This file demonstrates adding new fields to registered CMB2 metaboxes/objects\n */\n\nfunction yourprefix_add_"
},
{
"path": "filters-and-actions/cmb2_init_before_hookup-remove-cmb2-metabox.php",
"chars": 274,
"preview": "<?php\n/**\n * You can remove an entire CMB2 metabox. But be polite.\n */\nfunction yourprefix_remove_metabox() {\n\t// to rem"
},
{
"path": "filters-and-actions/cmb2_init_before_hookup-update-existing-fields.php",
"chars": 1506,
"preview": "<?php\n/**\n * This file demonstrates modifying existing registered CMB2 metabox fields\n */\n\nfunction yourprefix_update_fi"
},
{
"path": "filters-and-actions/cmb2_override_{$field_id}_meta_value-filter.php",
"chars": 2707,
"preview": "<?php\n/**\n * This file demonstrates providing a default value for a group field from a JSON blob.\n * It is using the fie"
},
{
"path": "filters-and-actions/custom-css-for-specific-metabox.php",
"chars": 803,
"preview": "<?php\n/**\n * Add custom CSS which only loads for a particular metabox\n */\n\n/**\n * Setup the metabox\n */\nfunction js_cust"
},
{
"path": "filters-and-actions/disable-styles-on-front-end-forms.php",
"chars": 612,
"preview": "<?php\n/**\n * This file demonstrates how to disable CMB2 styles on all front end forms.\n * \n * It’s important, when using"
},
{
"path": "filters-and-actions/localize-date-format.php",
"chars": 661,
"preview": "<?php\n\n/**\n * A demo of the helper function used to \n * localise any date picker form in CMB2.\n * See http://api.jqueryu"
},
{
"path": "filters-and-actions/override-cmb2-data-source.php",
"chars": 3947,
"preview": "<?php\n/**\n * Demonstrates using an alternate data source for storing/retrieving data for a CMB2 box.\n * In this case, we"
},
{
"path": "filters-and-actions/save-default-group-field-value-based-on-other-field.php",
"chars": 2410,
"preview": "<?php\n\n/**\n * The following snippet is untested, but provides a proof of concept to how you can save a default value for"
},
{
"path": "front-end/README.md",
"chars": 95,
"preview": "Front-end\n==========\n\nSnippets that use CMB2 on the front-end (not wp-admin) side of your site."
},
{
"path": "front-end/cmb2-front-end-editor.php",
"chars": 2732,
"preview": "<?php\n/*\n * Frontend editor, including title/content\n */\n\nfunction jt_add_edit_form_to_frontend( $content ) {\n\tif ( isse"
},
{
"path": "front-end/cmb2-front-end-submit.php",
"chars": 9369,
"preview": "<?php\n/**\n * @link http://webdevstudios.com/2015/03/30/use-cmb2-to-create-a-new-post-submission-form/ Original tutorial\n"
},
{
"path": "front-end/cmb2-front-end-wordpress-media-uploader.php",
"chars": 1345,
"preview": "<?php\n/**\n * Use the WordPress Media Uploader on the frontend. Limit to only displaying current\n * user's uploaded media"
},
{
"path": "front-end/cmb2-metabox-shortcode.php",
"chars": 1320,
"preview": "<?php\n/*\n * Plugin Name: CMB2 - Front-end Shortcode\n * Description: Display CMB2 metabox forms on the front-end using a "
},
{
"path": "front-end/output-file-list.php",
"chars": 1357,
"preview": "<?php\n/*\n * Plugin Name: CMB2 Template Tag - Output File List\n * Description: Custom functions that allow you to get or "
},
{
"path": "helper-functions/README.md",
"chars": 277,
"preview": "CMB2 Helper Functions\n==========\n\nSnippets for working with the [included helper functions](https://github.com/WebDevStu"
},
{
"path": "helper-functions/helper-functions.php",
"chars": 4372,
"preview": "<?php\n/**\n * Just a collection of random helper functions for CMB2.\n * If you borrow these, please replace \"yourprefix_\""
},
{
"path": "helper-functions/modify-cmb2_metabox_form-format.php",
"chars": 672,
"preview": "<?php\n\n/**\n * To change the formatting of the form,\n * again, pass the third parameter (the arguments array),\n * and spe"
},
{
"path": "helper-functions/modify-cmb2_metabox_form-output.php",
"chars": 1495,
"preview": "<?php\n/**\n * You can use the 'cmb2_get_metabox_form_format' filter to modify the form format,\n * but keep in mind it wil"
},
{
"path": "helper-functions/modify-cmb2_metabox_form-save-button-text.php",
"chars": 266,
"preview": "<?php\n\n/**\n * To change just the text of the save button,\n * pass the third parameter (the arguments array),\n * and spec"
},
{
"path": "javascript/README.md",
"chars": 81,
"preview": "CMB2 Javascript\n==========\n\nCustom javascript snippets for interacting with CMB2."
},
{
"path": "javascript/cmb2-auto-scroll-to-new-group.php",
"chars": 1182,
"preview": "<?php\n/*\n * Plugin Name: CMB2 Auto-scroll to new group\n * Description: This feature was removed in CMB2 2.0.3. Install t"
},
{
"path": "javascript/cmb2-js-validation-required.php",
"chars": 2377,
"preview": "<?php\n/*\n * Plugin Name: CMB2 js validation for \"required\" fields\n * Description: Uses js to validate CMB2 fields that h"
},
{
"path": "javascript/dynamically-change-group-field-title-from-subfield.php",
"chars": 2833,
"preview": "<?php\n/**\n * Custom Repeatable Group.\n * The \"group_title\" will display the value of the 'title' sub-field, if it exists"
},
{
"path": "javascript/limit-number-of-multiple-repeat-groups.php",
"chars": 4033,
"preview": "<?php\n/**\n * Set a max limit on the number of times\n * a repeating group can be added for various groups in one page\n */"
},
{
"path": "javascript/limit-number-of-repeat-fields.php",
"chars": 2003,
"preview": "<?php\n/**\n * Set a max limit on the number of times\n * a repeating field can be added.\n */\n\n/**\n * Setup the metabox\n */"
},
{
"path": "javascript/limit-number-of-repeat-groups.php",
"chars": 2753,
"preview": "<?php\n/**\n * Set a max limit on the number of times\n * a repeating group can be added.\n */\n\n/**\n * Setup the group field"
},
{
"path": "metaboxes/README.md",
"chars": 77,
"preview": "Metaboxes\n==========\n\nThese are examples of different metabox configurations."
},
{
"path": "misc/README.md",
"chars": 70,
"preview": "Miscellaneous Snippets\n==========\n\nRandom CMB2 and WordPress snippets\n"
},
{
"path": "misc/add-wrap-to-group-of-fields.php",
"chars": 1790,
"preview": "<?php\n/**\n * Example of adding an opening/closing wrap around a group of fields.\n * Gif: http://b.ustin.co/12Uba\n */\n\nad"
},
{
"path": "misc/adding-wordcount-to-cmb2-wysiwyg-field.php",
"chars": 2551,
"preview": "<?php\n/**\n * Register a wysiwyg field and add the wordcount below it.\n */\n\nfunction yourprefix_feat_img_fields() {\n\n\t$cm"
},
{
"path": "misc/cmb2-field-in-publish-box.php",
"chars": 1671,
"preview": "<?php\n/**\n * Add a CMB2 field to the WordPress publish box.\n *\n * @author Chris Reynolds <chris@hmn.md>\n * @link https"
},
{
"path": "misc/helper-functions.php",
"chars": 1487,
"preview": "<?php\n/**\n * Miscellaneous CMB2 Helper functions\n */\n\n\n/**\n * Save fields data from an array of data (Likely $_POST data"
},
{
"path": "misc/outputting-cmb2-fields-in-featured-image-metabox.php",
"chars": 1246,
"preview": "<?php\n/**\n * Display CMB2 fields in the featured-image metabox.\n */\n\nfunction yourprefix_feat_img_fields() {\n\n\t$cmb = ne"
},
{
"path": "misc/outputting-forms-outside-metaboxes.php",
"chars": 3935,
"preview": "<?php\n/**\n * Display CMB2 fields in other areas of the post screen (not in metaboxes)\n */\n\n/**\n * Hook in and add a demo"
},
{
"path": "misc/replace-wp-excerpt-with-cmb2-field.php",
"chars": 1757,
"preview": "<?php\n/**\n * If you want to replace the default WordPress excerpt field with CMB2 field,\n * it can be done with the foll"
},
{
"path": "misc/replace-wp-title-content-thumbnail-with-cmb2-fields.php",
"chars": 2710,
"preview": "<?php\n/**\n * Use CMB2 fields to replace WordPress title/content/thumbnail fields.\n */\n\n/**\n * Register a dummy cpt for d"
},
{
"path": "modified-field-types/README.md",
"chars": 282,
"preview": "Modified Field Types\n==========\n\nThese are examples of using the built-in [CMB2 field-types](https://github.com/WebDevSt"
},
{
"path": "modified-field-types/modify-button-text-for-file-type.php",
"chars": 520,
"preview": "<?php\n\n// Do your $cmb = new_cmb2_box(), then add this field.\n// See https://github.com/WebDevStudios/CMB2/blob/develop/"
},
{
"path": "modified-field-types/readonly-field-type.php",
"chars": 552,
"preview": "<?php\n\n// Do your $cmb = new_cmb2_box(), then add this field.\n// See https://github.com/WebDevStudios/CMB2/blob/develop/"
},
{
"path": "options-and-settings-pages/README.md",
"chars": 529,
"preview": "Options and Settings Pages\n==========\n\nThese snippets demonstrate how to create options page metaboxes or hook into gene"
},
{
"path": "options-and-settings-pages/add-cmb2-settings-to-other-settings-pages.php",
"chars": 5753,
"preview": "<?php\n/**\n * CMB2 Network Settings\n * @version 0.1.0\n */\nclass Prefix_Add_CMB2_To_Settings_Page {\n\n\t/**\n \t * Option key,"
},
{
"path": "options-and-settings-pages/custom-display-callback.php",
"chars": 1899,
"preview": "<?php\nadd_action( 'cmb2_admin_init', 'yourprefix_register_theme_options_metabox' );\n/**\n * Hook in and register a metabo"
},
{
"path": "options-and-settings-pages/genesis-cpt-archive-metabox.php",
"chars": 6230,
"preview": "<?php\n\n/**\n * CMB2 Genesis CPT Archive Metabox\n *\n * To fetch these options, use `genesis_get_cpt_option()`, e.g.\n * "
},
{
"path": "options-and-settings-pages/genesis-settings-metabox.php",
"chars": 5302,
"preview": "<?php\n\n/**\n * CMB2 Genesis Settings Metabox\n *\n * To fetch these options, use `genesis_get_option()`, e.g.\n * $colo"
},
{
"path": "options-and-settings-pages/network-options-cmb.php",
"chars": 3215,
"preview": "<?php\n/**\n * This snippet has been updated to reflect the official supporting of options pages by CMB2\n * in version 2.2"
},
{
"path": "options-and-settings-pages/non-cmb2-options-page.php",
"chars": 5102,
"preview": "<?php\n/**\n * Adding standard WP Settings API options page as sub-menu item to CMB2 Tabs.\n *\n * @see https://developer.wo"
},
{
"path": "options-and-settings-pages/options-pages-with-submenus.php",
"chars": 3542,
"preview": "<?php\n\n/**\n * Hook in and register a metabox to handle a theme options page and adds a menu item.\n */\nfunction yourprefi"
},
{
"path": "options-and-settings-pages/options-pages-with-tabs-and-submenus.php",
"chars": 4961,
"preview": "<?php\n/**\n * Hook in and register a metabox to handle a theme options page and adds a menu item.\n */\nfunction yourprefix"
},
{
"path": "options-and-settings-pages/submenu-options-pages.php",
"chars": 4168,
"preview": "<?php\n\n/**\n * Hook in and register a submenu options page for the Page post-type menu.\n */\nfunction yourprefix_register_"
},
{
"path": "options-and-settings-pages/theme-options-cmb.php",
"chars": 3152,
"preview": "<?php\n/**\n * This snippet has been updated to reflect the official supporting of options pages by CMB2\n * in version 2.2"
},
{
"path": "user-meta-and-settings/README.md",
"chars": 171,
"preview": "User Meta and Settings\n==========\n\nThese are examples of [using CMB2 to generate user fields](https://github.com/WebDevS"
},
{
"path": "widgets/widget-example.php",
"chars": 7360,
"preview": "<?php\n/**\n * Plugin Name: CMB2 Widget Boilerplate\n * Description: A boilerplate for building widgets with CMB2. Early al"
}
]
About this extraction
This page contains the full source code of the CMB2/CMB2-Snippet-Library GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 92 files (222.6 KB), approximately 69.0k tokens, and a symbol index with 230 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.