PluginProbe
WPGet API – Connect to any external REST API / 2.2.2
WPGet API – Connect to any external REST API v2.2.2
1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.3 2.1.4 2.1.5 2.2.0 2.2.1 2.2.10 2.2.2 2.2.3 All 97 releases
wpgetapi / lib / cmb2 / includes / CMB2_Hookup.php

CMB2_Hookup.php in WPGet API – Connect to any external REST API 2.2.2, at lib/cmb2/includes/CMB2_Hookup.php

1,045 lines 26.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles hooking CMB2 forms/metaboxes into the post/attachement/user screens
4 * and handles hooking in and saving those fields.
5 *
6 * @since 2.0.0
7 *
8 * @category WordPress_Plugin
9 * @package CMB2
10 * @author CMB2 team
11 * @license GPL-2.0+
12 * @link https://cmb2.io
13 */
14 class CMB2_Hookup extends CMB2_Hookup_Base {
15
16 /**
17 * Only allow JS registration once
18 *
19 * @var bool
20 * @since 2.0.7
21 */
22 protected static $js_registration_done = false;
23
24 /**
25 * Only allow CSS registration once
26 *
27 * @var bool
28 * @since 2.0.7
29 */
30 protected static $css_registration_done = false;
31
32 /**
33 * CMB taxonomies array for term meta
34 *
35 * @var array
36 * @since 2.2.0
37 */
38 protected $taxonomies = array();
39
40 /**
41 * Custom field columns.
42 *
43 * @var array
44 * @since 2.2.2
45 */
46 protected $columns = array();
47
48 /**
49 * Array of CMB2_Options_Hookup instances if options page metabox.
50 *
51 * @var CMB2_Options_Hookup[]|null
52 * @since 2.2.5
53 */
54 protected $options_hookup = null;
55
56 /**
57 * A functionalized constructor, used for the hookup action callbacks.
58 *
59 * @since 2.2.6
60 *
61 * @param CMB2 $cmb The CMB2 object to hookup.
62 *
63 * @return CMB2_Hookup_Base $hookup The hookup object.
64 */
65 public static function maybe_init_and_hookup( CMB2 $cmb ) {
66 if ( $cmb->prop( 'hookup' ) ) {
67
68 $hookup = new self( $cmb );
69
70 // Hook in the hookup... how meta.
71 return $hookup->universal_hooks();
72 }
73
74 return false;
75 }
76
77 public function universal_hooks() {
78 foreach ( get_class_methods( 'CMB2_Show_Filters' ) as $filter ) {
79 add_filter( 'cmb2_show_on', array( 'CMB2_Show_Filters', $filter ), 10, 3 );
80 }
81
82 if ( is_admin() ) {
83 // Register our scripts and styles for cmb.
84 $this->once( 'admin_enqueue_scripts', array( __CLASS__, 'register_scripts' ), 8 );
85 $this->once( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) );
86
87 $this->maybe_enqueue_column_display_styles();
88
89 switch ( $this->object_type ) {
90 case 'post':
91 return $this->post_hooks();
92 case 'comment':
93 return $this->comment_hooks();
94 case 'user':
95 return $this->user_hooks();
96 case 'term':
97 return $this->term_hooks();
98 case 'options-page':
99 return $this->options_page_hooks();
100 }
101 }
102
103 return $this;
104 }
105
106 public function post_hooks() {
107
108 // Fetch the context we set in our call.
109 $context = $this->cmb->prop( 'context' ) ? $this->cmb->prop( 'context' ) : 'normal';
110
111 // Call the proper hook based on the context provided.
112 switch ( $context ) {
113
114 case 'form_top':
115 add_action( 'edit_form_top', array( $this, 'add_context_metaboxes' ) );
116 break;
117
118 case 'before_permalink':
119 add_action( 'edit_form_before_permalink', array( $this, 'add_context_metaboxes' ) );
120 break;
121
122 case 'after_title':
123 add_action( 'edit_form_after_title', array( $this, 'add_context_metaboxes' ) );
124 break;
125
126 case 'after_editor':
127 add_action( 'edit_form_after_editor', array( $this, 'add_context_metaboxes' ) );
128 break;
129
130 default:
131 add_action( 'add_meta_boxes', array( $this, 'add_metaboxes' ) );
132 }
133
134 add_action( 'add_meta_boxes', array( $this, 'remove_default_tax_metaboxes' ) );
135 add_action( 'add_attachment', array( $this, 'save_post' ) );
136 add_action( 'edit_attachment', array( $this, 'save_post' ) );
137 add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
138
139 if ( $this->cmb->has_columns ) {
140 foreach ( $this->cmb->box_types() as $post_type ) {
141 add_filter( "manage_{$post_type}_posts_columns", array( $this, 'register_column_headers' ) );
142 add_action( "manage_{$post_type}_posts_custom_column", array( $this, 'column_display' ), 10, 2 );
143 add_filter( "manage_edit-{$post_type}_sortable_columns", array( $this, 'columns_sortable' ) );
144 add_action( 'pre_get_posts', array( $this, 'columns_sortable_orderby' ) );
145 }
146 }
147
148 return $this;
149 }
150
151 public function comment_hooks() {
152 add_action( 'add_meta_boxes_comment', array( $this, 'add_metaboxes' ) );
153 add_action( 'edit_comment', array( $this, 'save_comment' ) );
154
155 if ( $this->cmb->has_columns ) {
156 add_filter( 'manage_edit-comments_columns', array( $this, 'register_column_headers' ) );
157 add_action( 'manage_comments_custom_column', array( $this, 'column_display' ), 10, 3 );
158 add_filter( "manage_edit-comments_sortable_columns", array( $this, 'columns_sortable' ) );
159 add_action( 'pre_get_posts', array( $this, 'columns_sortable_orderby' ) );
160 }
161
162 return $this;
163 }
164
165 public function user_hooks() {
166 $priority = $this->get_priority();
167
168 add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
169 add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
170 add_action( 'user_new_form', array( $this, 'user_new_metabox' ), $priority );
171
172 add_action( 'personal_options_update', array( $this, 'save_user' ) );
173 add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
174 add_action( 'user_register', array( $this, 'save_user' ) );
175
176 if ( $this->cmb->has_columns ) {
177 add_filter( 'manage_users_columns', array( $this, 'register_column_headers' ) );
178 add_filter( 'manage_users_custom_column', array( $this, 'return_column_display' ), 10, 3 );
179 add_filter( "manage_users_sortable_columns", array( $this, 'columns_sortable' ) );
180 add_action( 'pre_get_posts', array( $this, 'columns_sortable_orderby' ) );
181 }
182
183 return $this;
184 }
185
186 public function term_hooks() {
187 if ( ! function_exists( 'get_term_meta' ) ) {
188 wp_die( esc_html__( 'Term Metadata is a WordPress 4.4+ feature. Please upgrade your WordPress install.', 'cmb2' ) );
189 }
190
191 if ( ! $this->cmb->prop( 'taxonomies' ) ) {
192 wp_die( esc_html__( 'Term metaboxes configuration requires a "taxonomies" parameter.', 'cmb2' ) );
193 }
194
195 $this->taxonomies = (array) $this->cmb->prop( 'taxonomies' );
196 $show_on_term_add = $this->cmb->prop( 'new_term_section' );
197 $priority = $this->get_priority( 8 );
198
199 foreach ( $this->taxonomies as $taxonomy ) {
200 // Display our form data.
201 add_action( "{$taxonomy}_edit_form", array( $this, 'term_metabox' ), $priority, 2 );
202
203 $show_on_add = is_array( $show_on_term_add )
204 ? in_array( $taxonomy, $show_on_term_add )
205 : (bool) $show_on_term_add;
206
207 /**
208 * Filter to determine if the term's fields should show in the "Add term" section.
209 *
210 * The dynamic portion of the hook name, $cmb_id, is the metabox id.
211 *
212 * @param bool $show_on_add Default is the value of the new_term_section cmb parameter.
213 * @param object $cmb The CMB2 instance
214 */
215 $show_on_add = apply_filters( "cmb2_show_on_term_add_form_{$this->cmb->cmb_id}", $show_on_add, $this->cmb );
216
217 // Display form in add-new section (unless specified not to).
218 if ( $show_on_add ) {
219 add_action( "{$taxonomy}_add_form_fields", array( $this, 'term_metabox' ), $priority, 2 );
220 }
221
222 if ( $this->cmb->has_columns ) {
223 add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'register_column_headers' ) );
224 add_filter( "manage_{$taxonomy}_custom_column", array( $this, 'return_column_display' ), 10, 3 );
225 add_filter( "manage_edit-{$taxonomy}_sortable_columns", array( $this, 'columns_sortable' ) );
226 add_action( 'pre_get_posts', array( $this, 'columns_sortable_orderby' ) );
227 }
228 }
229
230 add_action( 'created_term', array( $this, 'save_term' ), 10, 3 );
231 add_action( 'edited_terms', array( $this, 'save_term' ), 10, 2 );
232 add_action( 'delete_term', array( $this, 'delete_term' ), 10, 3 );
233
234 return $this;
235 }
236
237 public function options_page_hooks() {
238 $option_keys = $this->cmb->options_page_keys();
239
240 if ( ! empty( $option_keys ) ) {
241 foreach ( $option_keys as $option_key ) {
242 $this->options_hookup[ $option_key ] = new CMB2_Options_Hookup( $this->cmb, $option_key );
243 $this->options_hookup[ $option_key ]->hooks();
244 }
245 }
246
247 return $this;
248 }
249
250 /**
251 * Registers styles for CMB2
252 *
253 * @since 2.0.7
254 */
255 protected static function register_styles() {
256 if ( self::$css_registration_done ) {
257 return;
258 }
259
260 // Only use minified files if SCRIPT_DEBUG is off.
261 $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
262 $front = is_admin() ? '' : '-front';
263 $rtl = is_rtl() ? '-rtl' : '';
264
265 /**
266 * Filters the registered style dependencies for the cmb2 stylesheet.
267 *
268 * @param array $dependencies The registered style dependencies for the cmb2 stylesheet.
269 */
270 $dependencies = apply_filters( 'cmb2_style_dependencies', array() );
271 wp_register_style( 'cmb2-styles', CMB2_Utils::url( "css/cmb2{$front}{$rtl}{$min}.css" ), $dependencies );
272 wp_register_style( 'cmb2-display-styles', CMB2_Utils::url( "css/cmb2-display{$rtl}{$min}.css" ), $dependencies );
273
274 self::$css_registration_done = true;
275 }
276
277 /**
278 * Registers scripts for CMB2
279 *
280 * @since 2.0.7
281 */
282 protected static function register_js() {
283 if ( self::$js_registration_done ) {
284 return;
285 }
286
287 $hook = is_admin() ? 'admin_footer' : 'wp_footer';
288 add_action( $hook, array( 'CMB2_JS', 'enqueue' ), 8 );
289
290 self::$js_registration_done = true;
291 }
292
293 /**
294 * Registers scripts and styles for CMB2
295 *
296 * @since 1.0.0
297 */
298 public static function register_scripts() {
299 self::register_styles();
300 self::register_js();
301 }
302
303 /**
304 * Enqueues scripts and styles for CMB2 in admin_head.
305 *
306 * @since 1.0.0
307 *
308 * @param string $hook Current hook for the admin page.
309 */
310 public function do_scripts( $hook ) {
311 $hooks = array(
312 'post.php',
313 'post-new.php',
314 'page-new.php',
315 'page.php',
316 'comment.php',
317 'edit-tags.php',
318 'term.php',
319 'user-new.php',
320 'profile.php',
321 'user-edit.php',
322 );
323 // only pre-enqueue our scripts/styles on the proper pages
324 // show_form_for_type will have us covered if we miss something here.
325 if ( in_array( $hook, $hooks, true ) ) {
326 if ( $this->cmb->prop( 'cmb_styles' ) ) {
327 self::enqueue_cmb_css();
328 }
329 if ( $this->cmb->prop( 'enqueue_js' ) ) {
330 self::enqueue_cmb_js();
331 }
332 }
333 }
334
335 /**
336 * Register the CMB2 field column headers.
337 *
338 * @since 2.2.2
339 *
340 * @param array $columns Array of columns available for the admin page.
341 */
342 public function register_column_headers( $columns ) {
343 foreach ( $this->cmb->prop( 'fields' ) as $key => $field ) {
344 if ( empty( $field['column'] ) ) {
345 continue;
346 }
347
348 $column = $field['column'];
349
350 if ( false === $column['position'] ) {
351 $columns[ $field['id'] ] = $column['name'];
352 } else {
353 $before = array_slice( $columns, 0, absint( $column['position'] ) );
354 $before[ $field['id'] ] = $column['name'];
355 $columns = $before + $columns;
356 }
357
358 $column['field'] = $field;
359 $this->columns[ $field['id'] ] = $column;
360 }
361
362 return $columns;
363 }
364
365 /**
366 * The CMB2 field column display output.
367 *
368 * @since 2.2.2
369 *
370 * @param string $column_name Current column name.
371 * @param mixed $object_id Current object ID.
372 */
373 public function column_display( $column_name, $object_id ) {
374 if ( isset( $this->columns[ $column_name ] ) ) {
375 $field = new CMB2_Field( array(
376 'field_args' => $this->columns[ $column_name ]['field'],
377 'object_type' => $this->object_type,
378 'object_id' => $this->cmb->object_id( $object_id ),
379 'cmb_id' => $this->cmb->cmb_id,
380 ) );
381
382 $this->cmb->get_field( $field )->render_column();
383 }
384 }
385
386 /**
387 * Returns the columns sortable array.
388 *
389 * @since 2.6.1
390 *
391 * @param array $columns An array of sortable columns.
392 *
393 * @return array $columns An array of sortable columns with CMB2 columns.
394 */
395 public function columns_sortable( $columns ) {
396 foreach ( $this->cmb->prop( 'fields' ) as $key => $field ) {
397 if ( ! empty( $field['column'] ) && empty( $field['column']['disable_sortable'] ) ) {
398 $columns[ $field['id'] ] = $field['id'];
399 }
400 }
401
402 return $columns;
403 }
404
405 /**
406 * Return the query object to order by custom columns if selected
407 *
408 * @since 2.6.1
409 *
410 * @param object $query Object query from WordPress
411 *
412 * @return void
413 */
414 public function columns_sortable_orderby( $query ) {
415 if ( ! is_admin() ) {
416 return;
417 }
418
419 $orderby = $query->get( 'orderby' );
420
421 foreach ( $this->cmb->prop( 'fields' ) as $key => $field ) {
422 if (
423 empty( $field['column'] )
424 || ! empty( $field['column']['disable_sortable'] )
425 || $field['id'] !== $orderby
426 ) {
427 continue;
428 }
429
430 $query->set( 'meta_key', $field['id'] );
431
432 $type = $field['type'];
433
434 if ( ! empty( $field['attributes']['type'] ) ) {
435 switch ( $field['attributes']['type'] ) {
436 case 'number':
437 case 'date':
438 $type = $field['attributes']['type'];
439 break;
440 case 'range':
441 $type = 'number';
442 break;
443 }
444 }
445
446 switch ( $type ) {
447 case 'number':
448 case 'text_date_timestamp':
449 case 'text_datetime_timestamp':
450 case 'text_money':
451 $query->set( 'orderby', 'meta_value_num' );
452 break;
453 case 'text_time':
454 $query->set( 'orderby', 'meta_value_time' );
455 break;
456 case 'text_date':
457 $query->set( 'orderby', 'meta_value_date' );
458 break;
459
460 default:
461 $query->set( 'orderby', 'meta_value' );
462 break;
463 }
464 }
465 }
466
467 /**
468 * Returns the column display.
469 *
470 * @since 2.2.2
471 */
472 public function return_column_display( $empty, $custom_column, $object_id ) {
473 ob_start();
474 $this->column_display( $custom_column, $object_id );
475 $column = ob_get_clean();
476
477 return $column ? $column : $empty;
478 }
479
480 /**
481 * Output the CMB2 box/fields in an alternate context (not in a standard metabox area).
482 *
483 * @since 2.2.4
484 */
485 public function add_context_metaboxes() {
486
487 if ( ! $this->show_on() ) {
488 return;
489 }
490
491 $page = get_current_screen()->id;
492
493 foreach ( $this->cmb->box_types() as $object_type ) {
494 $screen = convert_to_screen( $object_type );
495
496 // If we're on the right post-type/object...
497 if ( isset( $screen->id ) && $screen->id === $page ) {
498
499 // Show the box.
500 $this->output_context_metabox();
501 }
502 }
503 }
504
505 /**
506 * Output the CMB2 box/fields in an alternate context (not in a standard metabox area).
507 *
508 * @since 2.2.4
509 */
510 public function output_context_metabox() {
511 $title = $this->cmb->prop( 'title' );
512
513 /*
514 * To keep from outputting the open/close markup, do not include
515 * a 'title' property in your metabox registration array.
516 *
517 * To output the fields 'naked' (without a postbox wrapper/style), then
518 * add a `'remove_box_wrap' => true` to your metabox registration array.
519 */
520 $add_wrap = ! empty( $title ) || ! $this->cmb->prop( 'remove_box_wrap' );
521 $add_handle = $add_wrap && ! empty( $title );
522
523 // Open the context-box wrap.
524 $this->context_box_title_markup_open( $add_handle );
525
526 // Show the form fields.
527 $this->cmb->show_form();
528
529 // Close the context-box wrap.
530 $this->context_box_title_markup_close( $add_handle );
531 }
532
533 /**
534 * Output the opening markup for a context box.
535 *
536 * @since 2.2.4
537 * @param bool $add_handle Whether to add the metabox handle and opening div for .inside.
538 */
539 public function context_box_title_markup_open( $add_handle = true ) {
540 $cmb_id = $this->cmb->cmb_id;
541 $title = $this->cmb->prop( 'title' );
542 $screen = get_current_screen();
543 $page = $screen->id;
544 $is_55 = CMB2_Utils::wp_at_least( '5.5' );
545
546 add_filter( "postbox_classes_{$page}_{$cmb_id}", array( $this, 'postbox_classes' ) );
547
548 $hidden_class = '';
549
550 if ( $is_55 ) {
551
552 // get_hidden_meta_boxes() doesn't apply in the block editor.
553 $is_hidden = ! $screen->is_block_editor() && in_array( $cmb_id, get_hidden_meta_boxes( $screen ), true );
554
555 $hidden_class = $is_hidden
556 ? ' hide-if-js'
557 : '';
558 }
559
560 $toggle_button = '<button type="button" class="handlediv button-link" aria-expanded="true"><span class="screen-reader-text">' . sprintf( __( 'Toggle panel: %s' ), $title ) . '</span><span class="toggle-indicator" aria-hidden="true"></span></button>';
561 $title_tag = '<h2 class="hndle"><span>' . esc_attr( $title ) . '</span></h2>' . "\n";
562
563 echo '<div id="' . $cmb_id . '" class="' . postbox_classes( $cmb_id, $page ) . $hidden_class . '">' . "\n";
564
565 if ( $add_handle ) {
566
567 if ( $is_55 ) {
568 echo '<div class="postbox-header">';
569 echo $title_tag;
570
571 echo '<div class="handle-actions hide-if-no-js">';
572 echo $toggle_button;
573 echo '</div>';
574
575 echo '</div>' . "\n";
576
577 } else {
578 echo $toggle_button;;
579 echo $title_tag;
580 }
581
582 echo '<div class="inside">' . "\n";
583 }
584 }
585
586 /**
587 * Output the closing markup for a context box.
588 *
589 * @since 2.2.4
590 * @param bool $add_inside_close Whether to add closing div for .inside.
591 */
592 public function context_box_title_markup_close( $add_inside_close = true ) {
593
594 // Load the closing divs for a title box.
595 if ( $add_inside_close ) {
596 echo '</div>' . "\n"; // .inside
597 }
598
599 echo '</div>' . "\n"; // .context-box
600 }
601
602 /**
603 * Add metaboxes (to 'post' or 'comment' object types)
604 *
605 * @since 1.0.0
606 */
607 public function add_metaboxes() {
608
609 if ( ! $this->show_on() ) {
610 return;
611 }
612
613 /*
614 * To keep from registering an actual post-screen metabox,
615 * omit the 'title' property from the metabox registration array.
616 *
617 * (WordPress will not display metaboxes without titles anyway)
618 *
619 * This is a good solution if you want to handle outputting your
620 * metaboxes/fields elsewhere in the post-screen.
621 */
622 if ( ! $this->cmb->prop( 'title' ) ) {
623 return;
624 }
625
626 $page = get_current_screen()->id;
627 add_filter( "postbox_classes_{$page}_{$this->cmb->cmb_id}", array( $this, 'postbox_classes' ) );
628
629 foreach ( $this->cmb->box_types() as $object_type ) {
630 add_meta_box(
631 $this->cmb->cmb_id,
632 $this->cmb->prop( 'title' ),
633 array( $this, 'metabox_callback' ),
634 $object_type,
635 $this->cmb->prop( 'context' ),
636 $this->cmb->prop( 'priority' ),
637 $this->cmb->prop( 'mb_callback_args' )
638 );
639 }
640 }
641
642 /**
643 * Remove the specified default taxonomy metaboxes for a post-type.
644 *
645 * @since 2.2.3
646 *
647 */
648 public function remove_default_tax_metaboxes() {
649 $to_remove = array_filter( (array) $this->cmb->tax_metaboxes_to_remove, 'taxonomy_exists' );
650 if ( empty( $to_remove ) ) {
651 return;
652 }
653
654 foreach ( $this->cmb->box_types() as $post_type ) {
655 foreach ( $to_remove as $taxonomy ) {
656 $mb_id = is_taxonomy_hierarchical( $taxonomy ) ? "{$taxonomy}div" : "tagsdiv-{$taxonomy}";
657 remove_meta_box( $mb_id, $post_type, 'side' );
658 }
659 }
660 }
661
662 /**
663 * Modify metabox postbox classes.
664 *
665 * @since 2.2.4
666 * @param array $classes Array of classes.
667 * @return array Modified array of classes
668 */
669 public function postbox_classes( $classes ) {
670 if ( $this->cmb->prop( 'closed' ) && ! in_array( 'closed', $classes ) ) {
671 $classes[] = 'closed';
672 }
673
674 if ( $this->cmb->is_alternate_context_box() ) {
675 $classes = $this->alternate_context_postbox_classes( $classes );
676 } else {
677 $classes[] = 'cmb2-postbox';
678 }
679
680 return $classes;
681 }
682
683 /**
684 * Modify metabox altnernate context postbox classes.
685 *
686 * @since 2.2.4
687 * @param array $classes Array of classes.
688 * @return array Modified array of classes
689 */
690 protected function alternate_context_postbox_classes( $classes ) {
691 $classes[] = 'context-box';
692 $classes[] = 'context-' . $this->cmb->prop( 'context' ) . '-box';
693
694 if ( in_array( $this->cmb->cmb_id, get_hidden_meta_boxes( get_current_screen() ) ) ) {
695 $classes[] = 'hide-if-js';
696 }
697
698 $add_wrap = $this->cmb->prop( 'title' ) || ! $this->cmb->prop( 'remove_box_wrap' );
699
700 if ( $add_wrap ) {
701 $classes[] = 'cmb2-postbox postbox';
702 } else {
703 $classes[] = 'cmb2-no-box-wrap';
704 }
705
706 return $classes;
707 }
708
709 /**
710 * Display metaboxes for a post or comment object.
711 *
712 * @since 1.0.0
713 */
714 public function metabox_callback() {
715 $object_id = 'comment' === $this->object_type ? get_comment_ID() : get_the_ID();
716 $this->cmb->show_form( $object_id, $this->object_type );
717 }
718
719 /**
720 * Display metaboxes for new user page.
721 *
722 * @since 1.0.0
723 *
724 * @param mixed $section User section metabox.
725 */
726 public function user_new_metabox( $section ) {
727 if ( $section === $this->cmb->prop( 'new_user_section' ) ) {
728 $object_id = $this->cmb->object_id();
729 $this->cmb->object_id( isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id );
730 $this->user_metabox();
731 }
732 }
733
734 /**
735 * Display metaboxes for a user object.
736 *
737 * @since 1.0.0
738 */
739 public function user_metabox() {
740 $this->show_form_for_type( 'user' );
741 }
742
743 /**
744 * Display metaboxes for a taxonomy term object.
745 *
746 * @since 2.2.0
747 */
748 public function term_metabox() {
749 $this->show_form_for_type( 'term' );
750 }
751
752 /**
753 * Display metaboxes for an object type.
754 *
755 * @since 2.2.0
756 * @param string $type Object type.
757 * @return void
758 */
759 public function show_form_for_type( $type ) {
760 if ( $type != $this->object_type ) {
761 return;
762 }
763
764 if ( ! $this->show_on() ) {
765 return;
766 }
767
768 if ( $this->cmb->prop( 'cmb_styles' ) ) {
769 self::enqueue_cmb_css();
770 }
771 if ( $this->cmb->prop( 'enqueue_js' ) ) {
772 self::enqueue_cmb_js();
773 }
774
775 $this->cmb->show_form( 0, $type );
776 }
777
778 /**
779 * Determines if metabox should be shown in current context.
780 *
781 * @since 2.0.0
782 * @return bool Whether metabox should be added/shown.
783 */
784 public function show_on() {
785 // If metabox is requesting to be conditionally shown.
786 $show = $this->cmb->should_show();
787
788 /**
789 * Filter to determine if metabox should show. Default is true.
790 *
791 * @param array $show Default is true, show the metabox.
792 * @param mixed $meta_box_args Array of the metabox arguments.
793 * @param mixed $cmb The CMB2 instance.
794 */
795 $show = (bool) apply_filters( 'cmb2_show_on', $show, $this->cmb->meta_box, $this->cmb );
796
797 return $show;
798 }
799
800 /**
801 * Get the CMB priority property set to numeric hook priority.
802 *
803 * @since 2.2.0
804 *
805 * @param integer $default Default display hook priority.
806 * @return integer Hook priority.
807 */
808 public function get_priority( $default = 10 ) {
809 $priority = $this->cmb->prop( 'priority' );
810
811 if ( ! is_numeric( $priority ) ) {
812 switch ( $priority ) {
813
814 case 'high':
815 $priority = 5;
816 break;
817
818 case 'low':
819 $priority = 20;
820 break;
821
822 default:
823 $priority = $default;
824 break;
825 }
826 }
827
828 return $priority;
829 }
830
831 /**
832 * Save data from post metabox
833 *
834 * @since 1.0.0
835 * @param int $post_id Post ID.
836 * @param mixed $post Post object.
837 * @return void
838 */
839 public function save_post( $post_id, $post = false ) {
840
841 $post_type = $post ? $post->post_type : get_post_type( $post_id );
842
843 $do_not_pass_go = (
844 ! $this->can_save( $post_type )
845 // Check user editing permissions.
846 || ( 'page' === $post_type && ! current_user_can( 'edit_page', $post_id ) )
847 || ! current_user_can( 'edit_post', $post_id )
848 );
849
850 if ( $do_not_pass_go ) {
851 return;
852 }
853
854 $this->cmb->save_fields( $post_id, 'post', $_POST );
855 }
856
857 /**
858 * Save data from comment metabox.
859 *
860 * @since 2.0.9
861 * @param int $comment_id Comment ID.
862 * @return void
863 */
864 public function save_comment( $comment_id ) {
865
866 $can_edit = current_user_can( 'moderate_comments', $comment_id );
867
868 if ( $this->can_save( get_comment_type( $comment_id ) ) && $can_edit ) {
869 $this->cmb->save_fields( $comment_id, 'comment', $_POST );
870 }
871 }
872
873 /**
874 * Save data from user fields.
875 *
876 * @since 1.0.x
877 * @param int $user_id User ID.
878 * @return void
879 */
880 public function save_user( $user_id ) {
881 // check permissions.
882 if ( $this->can_save( 'user' ) ) {
883 $this->cmb->save_fields( $user_id, 'user', $_POST );
884 }
885 }
886
887 /**
888 * Save data from term fields
889 *
890 * @since 2.2.0
891 * @param int $term_id Term ID.
892 * @param int $tt_id Term Taxonomy ID.
893 * @param string $taxonomy Taxonomy.
894 * @return void
895 */
896 public function save_term( $term_id, $tt_id, $taxonomy = '' ) {
897 $taxonomy = $taxonomy ? $taxonomy : $tt_id;
898
899 // check permissions.
900 if ( $this->taxonomy_can_save( $taxonomy ) && $this->can_save( 'term' ) ) {
901 $this->cmb->save_fields( $term_id, 'term', $_POST );
902 }
903 }
904
905 /**
906 * Delete term meta when a term is deleted.
907 *
908 * @since 2.2.0
909 * @param int $term_id Term ID.
910 * @param int $tt_id Term Taxonomy ID.
911 * @param string $taxonomy Taxonomy.
912 * @return void
913 */
914 public function delete_term( $term_id, $tt_id, $taxonomy = '' ) {
915 if ( $this->taxonomy_can_save( $taxonomy ) ) {
916
917 $data_to_delete = array();
918 foreach ( $this->cmb->prop( 'fields' ) as $field ) {
919 $data_to_delete[ $field['id'] ] = '';
920 }
921
922 $this->cmb->save_fields( $term_id, 'term', $data_to_delete );
923 }
924 }
925
926 /**
927 * Determines if the current object is able to be saved.
928 *
929 * @since 2.0.9
930 * @param string $type Current object type.
931 * @return bool Whether object can be saved.
932 */
933 public function can_save( $type = '' ) {
934
935 $can_save = (
936 $this->cmb->prop( 'save_fields' )
937 // check nonce.
938 && isset( $_POST[ $this->cmb->nonce() ] )
939 && wp_verify_nonce( $_POST[ $this->cmb->nonce() ], $this->cmb->nonce() )
940 // check if autosave.
941 && ! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
942 // get the metabox types & compare it to this type.
943 && ( $type && in_array( $type, $this->cmb->box_types() ) )
944 // Don't do updates during a switch-to-blog instance.
945 && ! ( is_multisite() && ms_is_switched() )
946 );
947
948 /**
949 * Filter to determine if metabox is allowed to save.
950 *
951 * @param bool $can_save Whether the current metabox can save.
952 * @param object $cmb The CMB2 instance.
953 */
954 return apply_filters( 'cmb2_can_save', $can_save, $this->cmb );
955 }
956
957 /**
958 * Determine if taxonomy of term being modified is cmb2-editable.
959 *
960 * @since 2.2.0
961 *
962 * @param string $taxonomy Taxonomy of term being modified.
963 * @return bool Whether taxonomy is editable.
964 */
965 public function taxonomy_can_save( $taxonomy ) {
966 if ( empty( $this->taxonomies ) || ! in_array( $taxonomy, $this->taxonomies ) ) {
967 return false;
968 }
969
970 $taxonomy_object = get_taxonomy( $taxonomy );
971 // Can the user edit this term?
972 if ( ! isset( $taxonomy_object->cap ) || ! current_user_can( $taxonomy_object->cap->edit_terms ) ) {
973 return false;
974 }
975
976 return true;
977 }
978
979 /**
980 * Enqueues the 'cmb2-display-styles' if the conditions match (has columns, on the right page, etc).
981 *
982 * @since 2.2.2.1
983 */
984 protected function maybe_enqueue_column_display_styles() {
985 global $pagenow;
986 if (
987 $pagenow
988 && $this->cmb->has_columns
989 && $this->cmb->prop( 'cmb_styles' )
990 && in_array( $pagenow, array( 'edit.php', 'users.php', 'edit-comments.php', 'edit-tags.php' ), 1 )
991 ) {
992 self::enqueue_cmb_css( 'cmb2-display-styles' );
993 }
994 }
995
996 /**
997 * Includes CMB2 styles.
998 *
999 * @since 2.0.0
1000 *
1001 * @param string $handle CSS handle.
1002 * @return mixed
1003 */
1004 public static function enqueue_cmb_css( $handle = 'cmb2-styles' ) {
1005
1006 /**
1007 * Filter to determine if CMB2'S css should be enqueued.
1008 *
1009 * @param bool $enqueue_css Default is true.
1010 */
1011 if ( ! apply_filters( 'cmb2_enqueue_css', true ) ) {
1012 return false;
1013 }
1014
1015 self::register_styles();
1016
1017 /*
1018 * White list the options as this method can be used as a hook callback
1019 * and have a different argument passed.
1020 */
1021 return wp_enqueue_style( 'cmb2-display-styles' === $handle ? $handle : 'cmb2-styles' );
1022 }
1023
1024 /**
1025 * Includes CMB2 JS.
1026 *
1027 * @since 2.0.0
1028 */
1029 public static function enqueue_cmb_js() {
1030
1031 /**
1032 * Filter to determine if CMB2'S JS should be enqueued.
1033 *
1034 * @param bool $enqueue_js Default is true.
1035 */
1036 if ( ! apply_filters( 'cmb2_enqueue_js', true ) ) {
1037 return false;
1038 }
1039
1040 self::register_js();
1041 return true;
1042 }
1043
1044 }
1045