├── post-search-dialog.png ├── post-search-field.png ├── composer.json ├── .gitignore ├── README.md ├── cmb2_post_search_field.php └── lib └── init.php /post-search-dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMB2/CMB2-Post-Search-field/HEAD/post-search-dialog.png -------------------------------------------------------------------------------- /post-search-field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMB2/CMB2-Post-Search-field/HEAD/post-search-field.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cmb2/cmb2-post-search-field", 3 | "description": "Custom field for CMB2 which adds a post-search dialog for searching/attaching other post IDs.", 4 | "license": "GPL-2.0+", 5 | "authors": [ 6 | { 7 | "name": "Justin Sternberg", 8 | "email": "justin@dsgnwrks.pro", 9 | "homepage": "https://dsgnwrks.pro", 10 | "role": "Developer" 11 | }, 12 | { 13 | "name": "WebDevStudios", 14 | "email": "contact@webdevstudios.com", 15 | "homepage": "https://github.com/WebDevStudios", 16 | "role": "Developer" 17 | } 18 | ], 19 | "keywords": ["wordpress", "plugin", "metabox","search","field"], 20 | "homepage": "https://github.com/CMB2/CMB2", 21 | "type": "wordpress-plugin", 22 | "support": { 23 | "issues": "https://github.com/CMB2/CMB2-Post-Search-field/issues", 24 | "source": "https://github.com/CMB2/CMB2-Post-Search-field" 25 | }, 26 | "require": { 27 | "php": ">5.2.4" 28 | }, 29 | "suggest": { 30 | "composer/installers": "~1.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | ### OSX ### 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear on external disk 16 | .Spotlight-V100 17 | .Trashes 18 | 19 | # Directories potentially created on remote AFP share 20 | .AppleDB 21 | .AppleDesktop 22 | Network Trash Folder 23 | Temporary Items 24 | .apdisk 25 | 26 | 27 | ### Node ### 28 | # Logs 29 | logs 30 | *.log 31 | 32 | # Runtime data 33 | pids 34 | *.pid 35 | *.seed 36 | 37 | # Directory for instrumented libs generated by jscoverage/JSCover 38 | lib-cov 39 | 40 | # Coverage directory used by tools like istanbul 41 | coverage 42 | 43 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 44 | .grunt 45 | 46 | # Compiled binary addons (http://nodejs.org/api/addons.html) 47 | build/Release 48 | 49 | # Dependency directory 50 | # Deployed apps should consider commenting this line out: 51 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 52 | node_modules 53 | 54 | # Sass Cache 55 | *.sass-cache 56 | 57 | dandelion.yml 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CMB2 Post Search field 2 | ====================== 3 | 4 | Custom field for CMB2 which adds a post-search dialog for searching/attaching other post IDs. 5 | 6 | Adds a new text field type (with a button), `post_search_text` that adds a quick post search dialog for saving post IDs to a text input. 7 | 8 | ## Example 9 | 10 | ```php 11 | // Classic CMB2 declaration 12 | $cmb = new_cmb2_box( array( 13 | 'id' => 'prefix-metabox-id', 14 | 'title' => __( 'Post Info' ), 15 | 'object_types' => array( 'post', ), // Post type 16 | ) ); 17 | 18 | // Add new field 19 | $cmb->add_field( array( 20 | 'name' => __( 'Related post' ), 21 | 'id' => 'prefix_related_post', 22 | 'type' => 'post_search_text', // This field type 23 | // post type also as array 24 | 'post_type' => 'post', 25 | // Default is 'checkbox', used in the modal view to select the post type 26 | 'select_type' => 'radio', 27 | // Will replace any selection with selection from modal. Default is 'add' 28 | 'select_behavior' => 'replace', 29 | ) ); 30 | ``` 31 | 32 | ## Screenshots 33 | 34 | 1. Field display 35 | ![Field display](https://raw.githubusercontent.com/WebDevStudios/CMB2-Post-Search-field/master/post-search-field.png) 36 | 37 | 2. Search Modal 38 | ![Search Modal](https://raw.githubusercontent.com/WebDevStudios/CMB2-Post-Search-field/master/post-search-dialog.png) 39 | 40 | ---- 41 | 42 | If you're looking for a more general way to attach posts (or other custom post types) with a drag and drop interface, you might consider [CMB2 Attached Posts Field](https://github.com/WebDevStudios/cmb2-attached-posts) instead. 43 | -------------------------------------------------------------------------------- /cmb2_post_search_field.php: -------------------------------------------------------------------------------- 1 | 20 | * @copyright 2016 WebDevstudios 21 | * @license GPL-2.0+ 22 | * @version 0.2.5 23 | * @link https://github.com/WebDevStudios/CMB2-Post-Search-field 24 | * @since 0.2.4 25 | */ 26 | 27 | /** 28 | * Copyright (c) 2016 WebDevstudios (email : contact@webdevstudios.com) 29 | * 30 | * This program is free software; you can redistribute it and/or modify 31 | * it under the terms of the GNU General Public License, version 2 or, at 32 | * your discretion, any later version, as published by the Free 33 | * Software Foundation. 34 | * 35 | * This program is distributed in the hope that it will be useful, 36 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 37 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 | * GNU General Public License for more details. 39 | * 40 | * You should have received a copy of the GNU General Public License 41 | * along with this program; if not, write to the Free Software 42 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 43 | */ 44 | 45 | /** 46 | * Loader versioning: http://jtsternberg.github.io/wp-lib-loader/ 47 | */ 48 | 49 | if ( ! class_exists( 'CMB2_Post_Search_field_025', false ) ) { 50 | 51 | /** 52 | * Versioned loader class-name 53 | * 54 | * This ensures each version is loaded/checked. 55 | * 56 | * @category WordPressLibrary 57 | * @package CMB2_Post_Search_field 58 | * @author WebDevstudios 59 | * @license GPL-2.0+ 60 | * @version 0.2.5 61 | * @link https://github.com/WebDevStudios/CMB2-Post-Search-field 62 | * @since 0.2.4 63 | */ 64 | class CMB2_Post_Search_field_025 { 65 | 66 | /** 67 | * CMB2_Post_Search_field version number 68 | * @var string 69 | * @since 0.2.4 70 | */ 71 | const VERSION = '0.2.5'; 72 | 73 | /** 74 | * Current version hook priority. 75 | * Will decrement with each release 76 | * 77 | * @var int 78 | * @since 0.2.4 79 | */ 80 | const PRIORITY = 9998; 81 | 82 | /** 83 | * Starts the version checking process. 84 | * Creates CMB2_POST_SEARCH_FIELD_LOADED definition for early detection by 85 | * other scripts. 86 | * 87 | * Hooks CMB2_Post_Search_field inclusion to the cmb2_post_search_field_load hook 88 | * on a high priority which decrements (increasing the priority) with 89 | * each version release. 90 | * 91 | * @since 0.2.4 92 | */ 93 | public function __construct() { 94 | if ( ! defined( 'CMB2_POST_SEARCH_FIELD_LOADED' ) ) { 95 | /** 96 | * A constant you can use to check if CMB2_Post_Search_field is loaded 97 | * for your plugins/themes with CMB2_Post_Search_field dependency. 98 | * 99 | * Can also be used to determine the priority of the hook 100 | * in use for the currently loaded version. 101 | */ 102 | define( 'CMB2_POST_SEARCH_FIELD_LOADED', self::PRIORITY ); 103 | } 104 | 105 | // Use the hook system to ensure only the newest version is loaded. 106 | add_action( 'cmb2_post_search_field_load', array( $this, 'include_lib' ), self::PRIORITY ); 107 | 108 | // Use the hook system to ensure only the newest version is loaded. 109 | add_action( 'after_setup_theme', array( $this, 'do_hook' ) ); 110 | } 111 | 112 | /** 113 | * Fires the cmb2_attached_posts_field_load action hook 114 | * (from the after_setup_theme hook). 115 | * 116 | * @since 1.2.3 117 | */ 118 | public function do_hook() { 119 | // Then fire our hook. 120 | do_action( 'cmb2_post_search_field_load' ); 121 | } 122 | 123 | /** 124 | * A final check if CMB2_Post_Search_field exists before kicking off 125 | * our CMB2_Post_Search_field loading. 126 | * 127 | * CMB2_POST_SEARCH_FIELD_VERSION and CMB2_POST_SEARCH_FIELD_DIR constants are 128 | * set at this point. 129 | * 130 | * @since 0.2.4 131 | */ 132 | public function include_lib() { 133 | if ( class_exists( 'CMB2_Post_Search_field', false ) ) { 134 | return; 135 | } 136 | 137 | if ( ! defined( 'CMB2_POST_SEARCH_FIELD_VERSION' ) ) { 138 | /** 139 | * Defines the currently loaded version of CMB2_Post_Search_field. 140 | */ 141 | define( 'CMB2_POST_SEARCH_FIELD_VERSION', self::VERSION ); 142 | } 143 | 144 | if ( ! defined( 'CMB2_POST_SEARCH_FIELD_DIR' ) ) { 145 | /** 146 | * Defines the directory of the currently loaded version of CMB2_Post_Search_field. 147 | */ 148 | define( 'CMB2_POST_SEARCH_FIELD_DIR', dirname( __FILE__ ) . '/' ); 149 | } 150 | 151 | // Include and initiate CMB2_Post_Search_field. 152 | require_once CMB2_POST_SEARCH_FIELD_DIR . 'lib/init.php'; 153 | } 154 | 155 | } 156 | 157 | // Kick it off. 158 | new CMB2_Post_Search_field_025; 159 | } 160 | -------------------------------------------------------------------------------- /lib/init.php: -------------------------------------------------------------------------------- 1 | 11 | * @license GPL-2.0+ 12 | * @version 0.2.5 13 | * @link https://github.com/WebDevStudios/CMB2-Post-Search-field 14 | * @since 0.2.4 15 | */ 16 | class CMB2_Post_Search_field { 17 | 18 | protected static $single_instance = null; 19 | 20 | /** 21 | * Creates or returns an instance of this class. 22 | * @since 0.2.4 23 | * @return CMB2_Post_Search_field A single instance of this class. 24 | */ 25 | public static function get_instance() { 26 | if ( null === self::$single_instance ) { 27 | self::$single_instance = new self(); 28 | } 29 | 30 | return self::$single_instance; 31 | } 32 | 33 | protected function __construct() { 34 | add_action( 'cmb2_render_post_search_text', array( $this, 'render_field' ), 10, 5 ); 35 | add_action( 'cmb2_after_form', array( $this, 'render_js' ), 10, 4 ); 36 | add_action( 'cmb2_post_search_field_add_find_posts_div', array( $this, 'add_find_posts_div' ) ); 37 | add_action( 'admin_init', array( $this, 'ajax_find_posts' ) ); 38 | 39 | } 40 | 41 | public function render_field( $field, $escaped_value, $object_id, $object_type, $field_type ) { 42 | echo $field_type->input( array( 43 | 'data-search' => json_encode( array( 44 | 'posttype' => $field->args( 'post_type' ), 45 | 'selecttype' => 'radio' == $field->args( 'select_type' ) ? 'radio' : 'checkbox', 46 | 'selectbehavior' => 'replace' == $field->args( 'select_behavior' ) ? 'replace' : 'add', 47 | 'errortxt' => esc_attr( $field_type->_text( 'error_text', __( 'An error has occurred. Please reload the page and try again.' ) ) ), 48 | 'findtxt' => esc_attr( $field_type->_text( 'find_text', __( 'Find Posts or Pages' ) ) ), 49 | ) ), 50 | ) ); 51 | } 52 | 53 | public function render_js( $cmb_id, $object_id, $object_type, $cmb ) { 54 | static $rendered; 55 | 56 | if ( $rendered ) { 57 | return; 58 | } 59 | 60 | $fields = $cmb->prop( 'fields' ); 61 | 62 | if ( ! is_array( $fields ) ) { 63 | return; 64 | } 65 | 66 | $has_post_search_field = $this->has_post_search_text_field( $fields ); 67 | 68 | if ( ! $has_post_search_field ) { 69 | return; 70 | } 71 | 72 | // JS needed for modal 73 | // wp_enqueue_media(); 74 | wp_enqueue_script( 'jquery' ); 75 | wp_enqueue_script( 'wp-backbone' ); 76 | 77 | if ( ! is_admin() ) { 78 | // Will need custom styling! 79 | // @todo add styles for front-end 80 | require_once( ABSPATH . 'wp-admin/includes/template.php' ); 81 | do_action( 'cmb2_post_search_field_add_find_posts_div' ); 82 | } 83 | 84 | // markup needed for modal 85 | add_action( 'admin_footer', 'find_posts_div' ); 86 | 87 | // @TODO this should really be in its own JS file. 88 | ?> 89 | 255 | 262 | has_post_search_text_field( $field['fields'] ) ) { 272 | return true; 273 | } 274 | } 275 | if ( 'post_search_text' == $field['type'] ) { 276 | return true; 277 | } 278 | } 279 | 280 | return false; 281 | } 282 | 283 | /** 284 | * Add the find posts div via a hook so we can relocate it manually 285 | */ 286 | public function add_find_posts_div() { 287 | add_action( 'wp_footer', 'find_posts_div' ); 288 | } 289 | 290 | 291 | /** 292 | * Check to see if we have a post type set and, if so, add the 293 | * pre_get_posts action to set the queried post type 294 | */ 295 | public function ajax_find_posts() { 296 | if ( 297 | defined( 'DOING_AJAX' ) 298 | && DOING_AJAX 299 | && isset( $_POST['cmb2_post_search'], $_POST['action'], $_POST['post_search_cpt'] ) 300 | && 'find_posts' == $_POST['action'] 301 | && ! empty( $_POST['post_search_cpt'] ) 302 | ) { 303 | add_action( 'pre_get_posts', array( $this, 'set_post_type' ) ); 304 | } 305 | } 306 | 307 | /** 308 | * Set the post type via pre_get_posts 309 | * @param array $query The query instance 310 | */ 311 | public function set_post_type( $query ) { 312 | $types = $_POST['post_search_cpt']; 313 | $types = is_array( $types ) ? array_map( 'esc_attr', $types ) : esc_attr( $types ); 314 | $query->set( 'post_type', $types ); 315 | } 316 | 317 | } 318 | CMB2_Post_Search_field::get_instance(); 319 | 320 | // preserve a couple functions for back-compat. 321 | 322 | 323 | if ( ! function_exists( 'cmb2_post_search_render_field' ) ) { 324 | function cmb2_post_search_render_field( $field, $escaped_value, $object_id, $object_type, $field_type ) { 325 | _deprecated_function( __FUNCTION__, '0.2.4', 'Please access these methods through the CMB2_Post_Search_field::get_instance() object.' ); 326 | 327 | return CMB2_Post_Search_field::get_instance()->render_field( $field, $escaped_value, $object_id, $object_type, $field_type ); 328 | } 329 | } 330 | 331 | // Remove old versions. 332 | remove_action( 'cmb2_render_post_search_text', 'cmb2_post_search_render_field', 10, 5 ); 333 | remove_action( 'cmb2_after_form', 'cmb2_post_search_render_js', 10, 4 ); 334 | 335 | if ( ! function_exists( 'cmb2_has_post_search_text_field' ) ) { 336 | function cmb2_has_post_search_text_field( $fields ) { 337 | _deprecated_function( __FUNCTION__, '0.2.4', 'Please access these methods through the CMB2_Post_Search_field::get_instance() object.' ); 338 | 339 | return CMB2_Post_Search_field::get_instance()->has_post_search_text_field( $fields ); 340 | } 341 | } 342 | --------------------------------------------------------------------------------