Completed
Pull Request — trunk (#836)
by Justin
03:31
created

CMB2_hookup::remove_default_tax_metaboxes()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 4
nop 1
dl 0
loc 10
rs 9.2
c 0
b 0
f 0
ccs 0
cts 0
cp 0
crap 20
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    WebDevStudios
11
 * @license   GPL-2.0+
12
 * @link      http://webdevstudios.com
13
 */
14
class CMB2_hookup extends CMB2_Hookup_Base {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
15
16
	/**
17
	 * Only allow JS registration once
18
	 * @var   bool
19
	 * @since 2.0.7
20
	 */
21
	protected static $js_registration_done = false;
22
23
	/**
24
	 * Only allow CSS registration once
25
	 * @var   bool
26
	 * @since 2.0.7
27
	 */
28
	protected static $css_registration_done = false;
29
30
	/**
31
	 * CMB taxonomies array for term meta
32
	 * @var   array
33
	 * @since 2.2.0
34
	 */
35
	protected $taxonomies = array();
36
37
	/**
38
	 * Custom field columns.
39
	 * @var   array
40
	 * @since 2.2.2
41
	 */
42
	protected $columns = array();
43
44
	/**
45
	 * Constructor
46
	 * @since 2.0.0
47
	 * @param CMB2 $cmb The CMB2 object to hookup
48
	 */
49
	public function __construct( CMB2 $cmb ) {
50
		$this->cmb = $cmb;
51
		$this->object_type = $this->cmb->mb_object_type();
52
	}
53
54
	public function universal_hooks() {
55
		foreach ( get_class_methods( 'CMB2_Show_Filters' ) as $filter ) {
56
			add_filter( 'cmb2_show_on', array( 'CMB2_Show_Filters', $filter ), 10, 3 );
57
		}
58
59
		if ( is_admin() ) {
60
			// register our scripts and styles for cmb
61
			$this->once( 'admin_enqueue_scripts', array( __CLASS__, 'register_scripts' ), 8 );
62
			$this->once( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) );
63
64
			$this->maybe_enqueue_column_display_styles();
65
66
			switch ( $this->object_type ) {
67
				case 'post':
68
					return $this->post_hooks();
69
				case 'comment':
70
					return $this->comment_hooks();
71
				case 'user':
72
					return $this->user_hooks();
73
				case 'term':
74
					return $this->term_hooks();
75
			}
76
		}
77
	}
78
79
	public function post_hooks() {
80
81
		// Fetch the context we set in our call.
82
		$context = ! empty( $this->cmb->prop( 'context' ) ) ? $this->cmb->prop( 'context' ) : 'normal';
83
84
		// Call the proper hook based on the context provided.
85
		switch ( $context ) {
86
87 View Code Duplication
			case 'form_top':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
88
				add_action( 'edit_form_top', array( $this, 'add_context_metabox' ) );
89
				add_filter( 'cmb2_wrap_classes', array( $this, 'add_context_class' ), 10, 2 );
90
91
				break;
92
93 View Code Duplication
			case 'before_permalink':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
94
				add_action( 'edit_form_before_permalink', array( $this, 'add_context_metabox' ) );
95
				add_filter( 'cmb2_wrap_classes', array( $this, 'add_context_class' ), 10, 2 );
96
97
				break;
98
99 View Code Duplication
			case 'after_title':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
				add_action( 'edit_form_after_title', array( $this, 'add_context_metabox' ) );
101
				add_filter( 'cmb2_wrap_classes', array( $this, 'add_context_class' ), 10, 2 );
102
103
				break;
104
105 View Code Duplication
			case 'after_editor':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
106
				add_action( 'edit_form_after_editor', array( $this, 'add_context_metabox' ) );
107
				add_filter( 'cmb2_wrap_classes', array( $this, 'add_context_class' ), 10, 2 );
108
109
				break;
110 1
111 1
			default:
112 1
				add_action( 'add_meta_boxes', array( $this, 'add_metaboxes' ) );
113
		}
114
115
		add_action( 'add_attachment', array( $this, 'save_post' ) );
116 1
		add_action( 'edit_attachment', array( $this, 'save_post' ) );
117
		add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
118 1
119
		if ( $this->cmb->has_columns ) {
120 1
			foreach ( $this->cmb->prop( 'object_types' ) as $post_type ) {
121 1
				add_filter( "manage_{$post_type}_posts_columns", array( $this, 'register_column_headers' ) );
122 1
				add_action( "manage_{$post_type}_posts_custom_column", array( $this, 'column_display' ), 10, 2 );
123 1
			}
124 1
		}
125 1
	}
126 1
127 1
	public function comment_hooks() {
128 1
		add_action( 'add_meta_boxes_comment', array( $this, 'add_metaboxes' ) );
129
		add_action( 'edit_comment', array( $this, 'save_comment' ) );
130 1
131
		if ( $this->cmb->has_columns ) {
132
			add_filter( 'manage_edit-comments_columns', array( $this, 'register_column_headers' ) );
133 1
			add_action( 'manage_comments_custom_column', array( $this, 'column_display'  ), 10, 3 );
134
		}
135 1
	}
136
137 1
	public function user_hooks() {
138
		$priority = $this->get_priority();
139 1
140 1
		add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
141 1
		add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
142 1
		add_action( 'user_new_form', array( $this, 'user_new_metabox' ), $priority );
143 1
144 1
		add_action( 'personal_options_update', array( $this, 'save_user' ) );
145
		add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
146 1
		add_action( 'user_register', array( $this, 'save_user' ) );
147
148 1 View Code Duplication
		if ( $this->cmb->has_columns ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149 1
			add_filter( 'manage_users_columns', array( $this, 'register_column_headers' ) );
150 1
			add_filter( 'manage_users_custom_column', array( $this, 'return_column_display'  ), 10, 3 );
151 1
		}
152 1
	}
153 1
154 1
	public function term_hooks() {
155 1
		if ( ! function_exists( 'get_term_meta' ) ) {
156 1
			wp_die( esc_html__( 'Term Metadata is a WordPress 4.4+ feature. Please upgrade your WordPress install.', 'cmb2' ) );
157 1
		}
158 1
159 1
		if ( ! $this->cmb->prop( 'taxonomies' ) ) {
160 1
			wp_die( esc_html__( 'Term metaboxes configuration requires a "taxonomies" parameter.', 'cmb2' ) );
161 1
		}
162
163 1
		$this->taxonomies = (array) $this->cmb->prop( 'taxonomies' );
164 1
		$show_on_term_add = $this->cmb->prop( 'new_term_section' );
165 1
		$priority         = $this->get_priority( 8 );
166 1
167
		foreach ( $this->taxonomies as $taxonomy ) {
168 1
			// Display our form data
169 1
			add_action( "{$taxonomy}_edit_form", array( $this, 'term_metabox' ), $priority, 2 );
170
171 1
			$show_on_add = is_array( $show_on_term_add )
172 1
				? in_array( $taxonomy, $show_on_term_add )
173 1
				: (bool) $show_on_term_add;
174 1
175 1
			$show_on_add = apply_filters( "cmb2_show_on_term_add_form_{$this->cmb->cmb_id}", $show_on_add, $this->cmb );
176 1
177 1
			// Display form in add-new section (unless specified not to)
178 1
			if ( $show_on_add ) {
179
				add_action( "{$taxonomy}_add_form_fields", array( $this, 'term_metabox' ), $priority, 2 );
180 1
			}
181
182 1 View Code Duplication
			if ( $this->cmb->has_columns ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
183 1
				add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'register_column_headers' ) );
184
				add_filter( "manage_{$taxonomy}_custom_column", array( $this, 'return_column_display'  ), 10, 3 );
185
			}
186
		}
187
188
		add_action( 'created_term', array( $this, 'save_term' ), 10, 3 );
189
		add_action( 'edited_terms', array( $this, 'save_term' ), 10, 2 );
190
		add_action( 'delete_term', array( $this, 'delete_term' ), 10, 3 );
191
192
	}
193
194
	/**
195
	 * Registers styles for CMB2
196
	 * @since 2.0.7
197
	 */
198
	protected static function register_styles() {
199
		if ( self::$css_registration_done ) {
200
			return;
201
		}
202
203
		// Only use minified files if SCRIPT_DEBUG is off
204
		$min   = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
205
		$front = is_admin() ? '' : '-front';
206
		$rtl   = is_rtl() ? '-rtl' : '';
207
208
		// Filter required styles and register stylesheet
209
		$dependencies = apply_filters( 'cmb2_style_dependencies', array() );
210
		wp_register_style( 'cmb2-styles', CMB2_Utils::url( "css/cmb2{$front}{$rtl}{$min}.css" ), $dependencies );
211
		wp_register_style( 'cmb2-display-styles', CMB2_Utils::url( "css/cmb2-display{$rtl}{$min}.css" ), $dependencies );
212
213
		self::$css_registration_done = true;
214
	}
215
216
	/**
217
	 * Registers scripts for CMB2
218
	 * @since  2.0.7
219
	 */
220
	protected static function register_js() {
221
		if ( self::$js_registration_done ) {
222
			return;
223
		}
224
225
		$hook = is_admin() ? 'admin_footer' : 'wp_footer';
226
		add_action( $hook, array( 'CMB2_JS', 'enqueue' ), 8 );
227
228
		self::$js_registration_done = true;
229
	}
230
231
	/**
232
	 * Registers scripts and styles for CMB2
233
	 * @since  1.0.0
234
	 */
235
	public static function register_scripts() {
236
		self::register_styles();
237
		self::register_js();
238
	}
239
240
	/**
241
	 * Enqueues scripts and styles for CMB2 in admin_head.
242
	 * @since  1.0.0
243
	 */
244
	public function do_scripts( $hook ) {
245
		$hooks = array(
246
			'post.php',
247
			'post-new.php',
248
			'page-new.php',
249
			'page.php',
250
			'comment.php',
251
			'edit-tags.php',
252
			'term.php',
253
			'user-new.php',
254
			'profile.php',
255
			'user-edit.php',
256
		);
257
		// only pre-enqueue our scripts/styles on the proper pages
258
		// show_form_for_type will have us covered if we miss something here.
259
		if ( in_array( $hook, $hooks, true ) ) {
260
			if ( $this->cmb->prop( 'cmb_styles' ) ) {
261
				self::enqueue_cmb_css();
262
			}
263
			if ( $this->cmb->prop( 'enqueue_js' ) ) {
264
				self::enqueue_cmb_js();
265
			}
266
		}
267
	}
268
269
	/**
270
	 * Register the CMB2 field column headers.
271
	 * @since 2.2.2
272
	 */
273
	public function register_column_headers( $columns ) {
274
		$fields = $this->cmb->prop( 'fields' );
275
276
		foreach ( $fields as $key => $field ) {
277
			if ( ! isset( $field['column'] ) ) {
278
				continue;
279
			}
280
281
			$column = $field['column'];
282
283
			if ( false === $column['position'] ) {
284
285
				$columns[ $field['id'] ] = $column['name'];
286
287
			} else {
288
289
				$before = array_slice( $columns, 0, absint( $column['position'] ) );
290
				$before[ $field['id'] ] = $column['name'];
291
				$columns = $before + $columns;
292
			}
293
294
			$column['field'] = $field;
295
			$this->columns[ $field['id'] ] = $column;
296
		}
297
298
		return $columns;
299
	}
300
301
	/**
302
	 * The CMB2 field column display output.
303
	 * @since 2.2.2
304
	 */
305
	public function column_display( $column_name, $object_id ) {
306
		if ( isset( $this->columns[ $column_name ] ) ) {
307
 			$field = new CMB2_Field( array(
308
				'field_args'  => $this->columns[ $column_name ]['field'],
309
				'object_type' => $this->object_type,
310
				'object_id'   => $this->cmb->object_id( $object_id ),
311
				'cmb_id'      => $this->cmb->cmb_id,
312
			) );
313
314
			$this->cmb->get_field( $field )->render_column();
315
		}
316
	}
317
318
	/**
319
	 * Returns the column display.
320
	 * @since 2.2.2
321
	 */
322
	public function return_column_display( $empty, $custom_column, $object_id ) {
323
		ob_start();
324
		$this->column_display( $custom_column, $object_id );
325
		$column = ob_get_clean();
326
327
		return $column ? $column : $empty;
328
	}
329
330
	/**
331
	 * Output the CMB2 fields in an alternate context (not in a metabox).
332
	 * @since 2.2.4
333
	 */
334
	public function add_context_metabox() {
335
336
		if ( ! $this->show_on() ) {
337
			return;
338
		}
339
340
		$form = cmb2_get_metabox( $this->cmb->prop( 'id' ) );
341
342
		$form->show_form();
343
	}
344
345
	/**
346
	 * Add an additional CSS class for the form box when used in contexts outside of a metabox.
347
	 * @since 2.2.4
348
	 * @param array $classes Array of classes for the cmb2-wrap.
349
	 * @param CMB2  $cmb     This CMB2 object.
350 1
	 */
351 1
	public function add_context_class( $classes, $cmb ) {
352
353 1
		if ( ! $this->show_on() ) {
354
			return $classes;
355
		}
356
357
		// If we aren't applying one of our extended contextes, just return our array.
358
		if ( empty( $cmb->prop( 'context' ) ) || ! in_array( $cmb->prop( 'context' ), array( 'form_top', 'before_permalink', 'after_title', 'after_editor' ) ) ) {
359
			return $classes;
360 1
		}
361 1
362 1
		// Include a generic context wrapper and the postbox wrapper.
363 1
		$classes[] = 'postbox cmb2-context-wrap';
364
365
		// Include a context-type based context wrapper.
366
		$classes[] = 'cmb2-context-wrap-' . $cmb->prop( 'context' );
367 1
368
		// Include an ID based context wrapper as well.
369
		$classes[] = 'cmb2-context-wrap-' . $cmb->prop( 'id' );
370
371
		// Return the updated array of classes.
372
		return $classes;
373
	}
374
375
	/**
376
	 * Add metaboxes (to 'post' or 'comment' object types)
377
	 * @since 1.0.0
378
	 */
379
	public function add_metaboxes() {
380
381
		if ( ! $this->show_on() ) {
382
			return;
383
		}
384
385
		/**
386
		 * To keep from registering an actual post-screen metabox,
387
		 * omit the 'title' attribute from the metabox registration array.
388
		 *
389
		 * (WordPress will not display metaboxes without titles anyway)
390
		 *
391
		 * This is a good solution if you want to output your metaboxes
392
		 * Somewhere else in the post-screen
393
		 */
394
		if ( ! $this->cmb->prop( 'title' ) ) {
395
			return;
396
		}
397
398
		foreach ( $this->cmb->prop( 'object_types' ) as $post_type ) {
399
			if ( $this->cmb->prop( 'closed' ) ) {
400
				add_filter( "postbox_classes_{$post_type}_{$this->cmb->cmb_id}", array( $this, 'close_metabox_class' ) );
401
			}
402
403
			if ( count( $this->cmb->tax_metaboxes_to_remove ) ) {
404
				$this->remove_default_tax_metaboxes( $post_type );
405
			}
406
407
			add_meta_box( $this->cmb->cmb_id, $this->cmb->prop( 'title' ), array( $this, 'metabox_callback' ), $post_type, $this->cmb->prop( 'context' ), $this->cmb->prop( 'priority' ) );
408
		}
409
	}
410
411
	/**
412
	 * Remove the specified default taxonomy metaboxes for a post-type.
413
	 * @since 2.2.3
414
	 * @param string $post_type Post type to remove the metabox for.
415
	 */
416
	protected function remove_default_tax_metaboxes( $post_type ) {
417
		foreach ( $this->cmb->tax_metaboxes_to_remove as $taxonomy ) {
418
			if ( ! taxonomy_exists( $taxonomy ) ) {
419
				continue;
420
			}
421
422
			$mb_id = is_taxonomy_hierarchical( $taxonomy ) ? "{$taxonomy}div" : "tagsdiv-{$taxonomy}";
423
			remove_meta_box( $mb_id, $post_type, 'side' );
424
		}
425
	}
426
427
	/**
428
	 * Add 'closed' class to metabox
429
	 * @since  2.0.0
430
	 * @param  array  $classes Array of classes
431
	 * @return array           Modified array of classes
432
	 */
433
	public function close_metabox_class( $classes ) {
434
		$classes[] = 'closed';
435
		return $classes;
436
	}
437
438
	/**
439
	 * Display metaboxes for a post or comment object
440
	 * @since  1.0.0
441
	 */
442
	public function metabox_callback() {
443
		$object_id = 'comment' == $this->object_type ? get_comment_ID() : get_the_ID();
444
		$this->cmb->show_form( $object_id, $this->object_type );
445
	}
446
447
	/**
448
	 * Display metaboxes for new user page
449
	 * @since  1.0.0
450
	 */
451
	public function user_new_metabox( $section ) {
0 ignored issues
show
Coding Style introduced by
user_new_metabox uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
452
		if ( $section == $this->cmb->prop( 'new_user_section' ) ) {
453
			$object_id = $this->cmb->object_id();
454
			$this->cmb->object_id( isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id );
455
			$this->user_metabox();
456
		}
457
	}
458
459
	/**
460
	 * Display metaboxes for a user object
461
	 * @since  1.0.0
462
	 */
463
	public function user_metabox() {
464
		$this->show_form_for_type( 'user' );
465
	}
466
467
	/**
468
	 * Display metaboxes for a taxonomy term object
469
	 * @since  2.2.0
470
	 */
471
	public function term_metabox() {
472
		$this->show_form_for_type( 'term' );
473
	}
474
475
	/**
476
	 * Display metaboxes for an object type
477
	 * @since  2.2.0
478
	 * @param  string $type Object type
479
	 * @return void
480
	 */
481
	public function show_form_for_type( $type ) {
482
		if ( $type != $this->cmb->mb_object_type() ) {
483
			return;
484
		}
485
486
		if ( ! $this->show_on() ) {
487
			return;
488
		}
489
490
		if ( $this->cmb->prop( 'cmb_styles' ) ) {
491
			self::enqueue_cmb_css();
492
		}
493
		if ( $this->cmb->prop( 'enqueue_js' ) ) {
494
			self::enqueue_cmb_js();
495
		}
496
497
		$this->cmb->show_form( 0, $type );
498
	}
499
500
	/**
501
	 * Determines if metabox should be shown in current context
502
	 * @since  2.0.0
503
	 * @return bool Whether metabox should be added/shown
504
	 */
505
	public function show_on() {
506
		// If metabox is requesting to be conditionally shown
507
		$show = $this->cmb->should_show();
508
509
		/**
510
		 * Filter to determine if metabox should show. Default is true
511
		 *
512
		 * @param array  $show          Default is true, show the metabox
513
		 * @param mixed  $meta_box_args Array of the metabox arguments
514
		 * @param mixed  $cmb           The CMB2 instance
515
		 */
516
		$show = (bool) apply_filters( 'cmb2_show_on', $show, $this->cmb->meta_box, $this->cmb );
517
518
		return $show;
519
	}
520
521
	/**
522
	 * Get the CMB priority property set to numeric hook priority.
523
	 * @since  2.2.0
524
	 * @param  integer $default Default display hook priority.
525
	 * @return integer          Hook priority.
526
	 */
527
	public function get_priority( $default = 10 ) {
528
		$priority = $this->cmb->prop( 'priority' );
529
530
		if ( ! is_numeric( $priority ) ) {
531
			switch ( $priority ) {
532
533
				case 'high':
534
					$priority = 5;
535
					break;
536
537
				case 'low':
538
					$priority = 20;
539
					break;
540
541
				default:
542
					$priority = $default;
543
					break;
544
			}
545
		}
546
547
		return $priority;
548
	}
549
550
	/**
551
	 * Save data from post metabox
552
	 * @since  1.0.0
553
	 * @param  int    $post_id Post ID
554
	 * @param  mixed  $post    Post object
555
	 * @return null
556
	 */
557
	public function save_post( $post_id, $post = false ) {
0 ignored issues
show
Coding Style introduced by
save_post uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
558
559
		$post_type = $post ? $post->post_type : get_post_type( $post_id );
560
561
		$do_not_pass_go = (
562
			! $this->can_save( $post_type )
563
			// check user editing permissions
564
			|| ( 'page' == $post_type && ! current_user_can( 'edit_page', $post_id ) )
565
			|| ! current_user_can( 'edit_post', $post_id )
566
		);
567
568
		if ( $do_not_pass_go ) {
569
			// do not collect $200
570
			return;
571
		}
572
573
		// take a trip to reading railroad – if you pass go collect $200
574
		$this->cmb->save_fields( $post_id, 'post', $_POST );
575
	}
576
577
	/**
578
	 * Save data from comment metabox
579
	 * @since  2.0.9
580
	 * @param  int    $comment_id Comment ID
581
	 * @return null
582
	 */
583
	public function save_comment( $comment_id ) {
0 ignored issues
show
Coding Style introduced by
save_comment uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
584
585
		$can_edit = current_user_can( 'moderate_comments', $comment_id );
586
587
		if ( $this->can_save( get_comment_type( $comment_id ) ) && $can_edit ) {
588
			$this->cmb->save_fields( $comment_id, 'comment', $_POST );
589
		}
590
	}
591
592
	/**
593
	 * Save data from user fields
594
	 * @since  1.0.x
595
	 * @param  int   $user_id  User ID
596
	 * @return null
597
	 */
598
	public function save_user( $user_id ) {
0 ignored issues
show
Coding Style introduced by
save_user uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
599
		// check permissions
600
		if ( $this->can_save( 'user' ) ) {
601
			$this->cmb->save_fields( $user_id, 'user', $_POST );
602
		}
603
	}
604
605
	/**
606
	 * Save data from term fields
607
	 * @since  2.2.0
608
	 * @param  int    $term_id  Term ID
609
	 * @param  int    $tt_id    Term Taxonomy ID
610
	 * @param  string $taxonomy Taxonomy
611
	 * @return null
612
	 */
613
	public function save_term( $term_id, $tt_id, $taxonomy = '' ) {
0 ignored issues
show
Coding Style introduced by
save_term uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
614
		$taxonomy = $taxonomy ? $taxonomy : $tt_id;
615
616
		// check permissions
617
		if ( $this->taxonomy_can_save( $taxonomy ) && $this->can_save( 'term' ) ) {
618
			$this->cmb->save_fields( $term_id, 'term', $_POST );
619
		}
620
	}
621
622
	/**
623
	 * Delete term meta when a term is deleted.
624
	 * @since  2.2.0
625
	 * @param  int    $term_id  Term ID
626
	 * @param  int    $tt_id    Term Taxonomy ID
627
	 * @param  string $taxonomy Taxonomy
628
	 * @return null
629
	 */
630
	public function delete_term( $term_id, $tt_id, $taxonomy = '' ) {
631
		if ( $this->taxonomy_can_save( $taxonomy ) ) {
632
633
			$data_to_delete = array();
634
			foreach ( $this->cmb->prop( 'fields' ) as $field ) {
635
				$data_to_delete[ $field['id'] ] = '';
636
			}
637
638
			$this->cmb->save_fields( $term_id, 'term', $data_to_delete );
639
		}
640
	}
641
642
	/**
643
	 * Determines if the current object is able to be saved
644
	 * @since  2.0.9
645
	 * @param  string  $type Current post_type or comment_type
646
	 * @return bool          Whether object can be saved
647
	 */
648
	public function can_save( $type = '' ) {
0 ignored issues
show
Coding Style introduced by
can_save uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
649
		return apply_filters( 'cmb2_can_save', (
650
			$this->cmb->prop( 'save_fields' )
651
			// check nonce
652
			&& isset( $_POST[ $this->cmb->nonce() ] )
653
			&& wp_verify_nonce( $_POST[ $this->cmb->nonce() ], $this->cmb->nonce() )
654
			// check if autosave
655
			&& ! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
656
			// get the metabox types & compare it to this type
657
			&& ( $type && in_array( $type, $this->cmb->prop( 'object_types' ) ) )
658
			// Don't do updates during a switch-to-blog instance.
659
			&& ! ( is_multisite() && ms_is_switched() )
660
		) );
661
	}
662
663
	/**
664
	 * Determine if taxonomy of term being modified is cmb2-editable.
665
	 * @since  2.2.0
666
	 * @param  string $taxonomy Taxonomy of term being modified.
667
	 * @return bool             Whether taxonomy is editable.
668
	 */
669
	public function taxonomy_can_save( $taxonomy ) {
670
		if ( empty( $this->taxonomies ) || ! in_array( $taxonomy, $this->taxonomies ) ) {
671
			return false;
672
		}
673
674
		$taxonomy_object = get_taxonomy( $taxonomy );
675
		// Can the user edit this term?
676
		if ( ! isset( $taxonomy_object->cap ) || ! current_user_can( $taxonomy_object->cap->edit_terms ) ) {
677
			return false;
678
		}
679
680
		return true;
681
	}
682
683
	/**
684
	 * Enqueues the 'cmb2-display-styles' if the conditions match (has columns, on the right page, etc).
685
	 * @since  2.2.2.1
686
	 */
687
	protected function maybe_enqueue_column_display_styles() {
688
		global $pagenow;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
689
		if (
690
			$pagenow
691
			&& $this->cmb->has_columns
692
			&& $this->cmb->prop( 'cmb_styles' )
693
			&& in_array( $pagenow, array( 'edit.php', 'users.php', 'edit-comments.php', 'edit-tags.php' ), 1 )
694
			) {
695
			self::enqueue_cmb_css( 'cmb2-display-styles' );
696
		}
697
	}
698
699
	/**
700
	 * Includes CMB2 styles
701
	 * @since  2.0.0
702
	 */
703
	public static function enqueue_cmb_css( $handle = 'cmb2-styles' ) {
704
		if ( ! apply_filters( 'cmb2_enqueue_css', true ) ) {
705
			return false;
706
		}
707
708
		self::register_styles();
709
710
		/*
711
		 * White list the options as this method can be used as a hook callback
712
		 * and have a different argument passed.
713
		 */
714
		return wp_enqueue_style( 'cmb2-display-styles' === $handle ? $handle : 'cmb2-styles' );
715
	}
716
717
	/**
718
	 * Includes CMB2 JS
719
	 * @since  2.0.0
720
	 */
721
	public static function enqueue_cmb_js() {
722
		if ( ! apply_filters( 'cmb2_enqueue_js', true ) ) {
723
			return false;
724
		}
725
726
		self::register_js();
727
		return true;
728
	}
729
730
}
731