Completed
Pull Request — trunk (#838)
by Justin
07:16
created

CMB2_hookup::save_comment()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 2
nop 1
dl 0
loc 8
ccs 0
cts 0
cp 0
crap 12
rs 9.4285
c 0
b 0
f 0
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
			case 'form_top':
88
				add_action( 'edit_form_top', array( $this, 'add_context_metaboxes' ) );
89
				break;
90
91
			case 'before_permalink':
92
				add_action( 'edit_form_before_permalink', array( $this, 'add_context_metaboxes' ) );
93
				break;
94
95
			case 'after_title':
96
				add_action( 'edit_form_after_title', array( $this, 'add_context_metaboxes' ) );
97
				break;
98
99
			case 'after_editor':
100
				add_action( 'edit_form_after_editor', array( $this, 'add_context_metaboxes' ) );
101
				break;
102
103
			default:
104
				add_action( 'add_meta_boxes', array( $this, 'add_metaboxes' ) );
105
		}
106
107
		add_action( 'add_attachment', array( $this, 'save_post' ) );
108
		add_action( 'edit_attachment', array( $this, 'save_post' ) );
109
		add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
110 1
111 1
		if ( $this->cmb->has_columns ) {
112 1
			foreach ( $this->cmb->prop( 'object_types' ) as $post_type ) {
113
				add_filter( "manage_{$post_type}_posts_columns", array( $this, 'register_column_headers' ) );
114
				add_action( "manage_{$post_type}_posts_custom_column", array( $this, 'column_display' ), 10, 2 );
115
			}
116 1
		}
117
	}
118 1
119
	public function comment_hooks() {
120 1
		add_action( 'add_meta_boxes_comment', array( $this, 'add_metaboxes' ) );
121 1
		add_action( 'edit_comment', array( $this, 'save_comment' ) );
122 1
123 1
		if ( $this->cmb->has_columns ) {
124 1
			add_filter( 'manage_edit-comments_columns', array( $this, 'register_column_headers' ) );
125 1
			add_action( 'manage_comments_custom_column', array( $this, 'column_display'  ), 10, 3 );
126 1
		}
127 1
	}
128 1
129
	public function user_hooks() {
130 1
		$priority = $this->get_priority();
131
132
		add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
133 1
		add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
134
		add_action( 'user_new_form', array( $this, 'user_new_metabox' ), $priority );
135 1
136
		add_action( 'personal_options_update', array( $this, 'save_user' ) );
137 1
		add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
138
		add_action( 'user_register', array( $this, 'save_user' ) );
139 1
140 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...
141 1
			add_filter( 'manage_users_columns', array( $this, 'register_column_headers' ) );
142 1
			add_filter( 'manage_users_custom_column', array( $this, 'return_column_display'  ), 10, 3 );
143 1
		}
144 1
	}
145
146 1
	public function term_hooks() {
147
		if ( ! function_exists( 'get_term_meta' ) ) {
148 1
			wp_die( esc_html__( 'Term Metadata is a WordPress 4.4+ feature. Please upgrade your WordPress install.', 'cmb2' ) );
149 1
		}
150 1
151 1
		if ( ! $this->cmb->prop( 'taxonomies' ) ) {
152 1
			wp_die( esc_html__( 'Term metaboxes configuration requires a "taxonomies" parameter.', 'cmb2' ) );
153 1
		}
154 1
155 1
		$this->taxonomies = (array) $this->cmb->prop( 'taxonomies' );
156 1
		$show_on_term_add = $this->cmb->prop( 'new_term_section' );
157 1
		$priority         = $this->get_priority( 8 );
158 1
159 1
		foreach ( $this->taxonomies as $taxonomy ) {
160 1
			// Display our form data
161 1
			add_action( "{$taxonomy}_edit_form", array( $this, 'term_metabox' ), $priority, 2 );
162
163 1
			$show_on_add = is_array( $show_on_term_add )
164 1
				? in_array( $taxonomy, $show_on_term_add )
165 1
				: (bool) $show_on_term_add;
166 1
167
			$show_on_add = apply_filters( "cmb2_show_on_term_add_form_{$this->cmb->cmb_id}", $show_on_add, $this->cmb );
168 1
169 1
			// Display form in add-new section (unless specified not to)
170
			if ( $show_on_add ) {
171 1
				add_action( "{$taxonomy}_add_form_fields", array( $this, 'term_metabox' ), $priority, 2 );
172 1
			}
173 1
174 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...
175 1
				add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'register_column_headers' ) );
176 1
				add_filter( "manage_{$taxonomy}_custom_column", array( $this, 'return_column_display'  ), 10, 3 );
177 1
			}
178 1
		}
179
180 1
		add_action( 'created_term', array( $this, 'save_term' ), 10, 3 );
181
		add_action( 'edited_terms', array( $this, 'save_term' ), 10, 2 );
182 1
		add_action( 'delete_term', array( $this, 'delete_term' ), 10, 3 );
183 1
184
	}
185
186
	/**
187
	 * Registers styles for CMB2
188
	 * @since 2.0.7
189
	 */
190
	protected static function register_styles() {
191
		if ( self::$css_registration_done ) {
192
			return;
193
		}
194
195
		// Only use minified files if SCRIPT_DEBUG is off
196
		$min   = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
197
		$front = is_admin() ? '' : '-front';
198
		$rtl   = is_rtl() ? '-rtl' : '';
199
200
		// Filter required styles and register stylesheet
201
		$dependencies = apply_filters( 'cmb2_style_dependencies', array() );
202
		wp_register_style( 'cmb2-styles', CMB2_Utils::url( "css/cmb2{$front}{$rtl}{$min}.css" ), $dependencies );
203
		wp_register_style( 'cmb2-display-styles', CMB2_Utils::url( "css/cmb2-display{$rtl}{$min}.css" ), $dependencies );
204
205
		self::$css_registration_done = true;
206
	}
207
208
	/**
209
	 * Registers scripts for CMB2
210
	 * @since  2.0.7
211
	 */
212
	protected static function register_js() {
213
		if ( self::$js_registration_done ) {
214
			return;
215
		}
216
217
		$hook = is_admin() ? 'admin_footer' : 'wp_footer';
218
		add_action( $hook, array( 'CMB2_JS', 'enqueue' ), 8 );
219
220
		self::$js_registration_done = true;
221
	}
222
223
	/**
224
	 * Registers scripts and styles for CMB2
225
	 * @since  1.0.0
226
	 */
227
	public static function register_scripts() {
228
		self::register_styles();
229
		self::register_js();
230
	}
231
232
	/**
233
	 * Enqueues scripts and styles for CMB2 in admin_head.
234
	 * @since  1.0.0
235
	 */
236
	public function do_scripts( $hook ) {
237
		$hooks = array(
238
			'post.php',
239
			'post-new.php',
240
			'page-new.php',
241
			'page.php',
242
			'comment.php',
243
			'edit-tags.php',
244
			'term.php',
245
			'user-new.php',
246
			'profile.php',
247
			'user-edit.php',
248
		);
249
		// only pre-enqueue our scripts/styles on the proper pages
250
		// show_form_for_type will have us covered if we miss something here.
251
		if ( in_array( $hook, $hooks, true ) ) {
252
			if ( $this->cmb->prop( 'cmb_styles' ) ) {
253
				self::enqueue_cmb_css();
254
			}
255
			if ( $this->cmb->prop( 'enqueue_js' ) ) {
256
				self::enqueue_cmb_js();
257
			}
258
		}
259
	}
260
261
	/**
262
	 * Register the CMB2 field column headers.
263
	 * @since 2.2.2
264
	 */
265
	public function register_column_headers( $columns ) {
266
		$fields = $this->cmb->prop( 'fields' );
267
268
		foreach ( $fields as $key => $field ) {
269
			if ( ! isset( $field['column'] ) ) {
270
				continue;
271
			}
272
273
			$column = $field['column'];
274
275
			if ( false === $column['position'] ) {
276
277
				$columns[ $field['id'] ] = $column['name'];
278
279
			} else {
280
281
				$before = array_slice( $columns, 0, absint( $column['position'] ) );
282
				$before[ $field['id'] ] = $column['name'];
283
				$columns = $before + $columns;
284
			}
285
286
			$column['field'] = $field;
287
			$this->columns[ $field['id'] ] = $column;
288
		}
289
290
		return $columns;
291
	}
292
293
	/**
294
	 * The CMB2 field column display output.
295
	 * @since 2.2.2
296
	 */
297
	public function column_display( $column_name, $object_id ) {
298
		if ( isset( $this->columns[ $column_name ] ) ) {
299
 			$field = new CMB2_Field( array(
300
				'field_args'  => $this->columns[ $column_name ]['field'],
301
				'object_type' => $this->object_type,
302
				'object_id'   => $this->cmb->object_id( $object_id ),
303
				'cmb_id'      => $this->cmb->cmb_id,
304
			) );
305
306
			$this->cmb->get_field( $field )->render_column();
307
		}
308
	}
309
310
	/**
311
	 * Returns the column display.
312
	 * @since 2.2.2
313
	 */
314
	public function return_column_display( $empty, $custom_column, $object_id ) {
315
		ob_start();
316
		$this->column_display( $custom_column, $object_id );
317
		$column = ob_get_clean();
318
319
		return $column ? $column : $empty;
320
	}
321
322
	/**
323
	 * Output the CMB2 box/fields in an alternate context (not in a standard metabox area).
324
	 * @since 2.2.4
325
	 */
326
	public function add_context_metaboxes() {
327
328
		if ( ! $this->show_on() ) {
329
			return;
330
		}
331
332
		$page = get_current_screen()->id;
333
334
		foreach ( $this->cmb->prop( 'object_types' ) as $object_type ) {
335
			$screen = convert_to_screen( $object_type );
336
337
			// If we're on the right post-type/object...
338
			if ( isset( $screen->id ) && $screen->id === $page ) {
339
340
				// Show the box.
341
				$this->output_context_metabox();
342
			}
343
		}
344
	}
345
346
	/**
347
	 * Output the CMB2 box/fields in an alternate context (not in a standard metabox area).
348
	 * @since 2.2.4
349
	 */
350 1
	public function output_context_metabox() {
351 1
		$title = $this->cmb->prop( 'title' );
352
353 1
		/*
354
		 * To keep from outputting the open/close markup, do not include
355
		 * a 'title' property in your metabox registration array.
356
		 *
357
		 * To output the fields 'naked' (without a postbox wrapper/style), then
358
		 * add a `'remove_box_wrap' => true` to your metabox registration array.
359
		 */
360 1
		$add_wrap = ! empty( $title ) || empty( $this->cmb->prop( 'remove_box_wrap' ) );
361 1
		$add_handle = $add_wrap && ! empty( $title );
362 1
363 1
		// Open the context-box wrap.
364
		$add_handle = $this->context_box_title_markup_open( $add_handle );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $add_handle is correct as $this->context_box_title_markup_open($add_handle) (which targets CMB2_hookup::context_box_title_markup_open()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
365
366
		// Show the form fields.
367 1
		$this->cmb->show_form();
368
369
		// Close the context-box wrap.
370
		$this->context_box_title_markup_close( $add_handle );
0 ignored issues
show
Documentation introduced by
$add_handle is of type null, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
371
	}
372
373
	/**
374
	 * Output the opening markup for a context box.
375
	 * @since 2.2.4
376
	 * @param $add_handle Whether to add the metabox handle and opening div for .inside
377
	 */
378
	public function context_box_title_markup_open( $add_handle = true ) {
379
		$title = $this->cmb->prop( 'title' );
380
381
		$page = get_current_screen()->id;
382
		add_filter( "postbox_classes_{$page}_{$this->cmb->cmb_id}", array( $this, 'postbox_classes' ) );
383
384
		echo '<div id="' . $this->cmb->cmb_id . '" class="' . postbox_classes( $this->cmb->cmb_id, $page ) . '">' . "\n";
385
386
		if ( $add_handle ) {
387
388
			echo '<button type="button" class="handlediv button-link" aria-expanded="true">';
389
				echo '<span class="screen-reader-text">' . sprintf( __( 'Toggle panel: %s' ), $title ) . '</span>';
390
				echo '<span class="toggle-indicator" aria-hidden="true"></span>';
391
			echo '</button>';
392
393
			echo '<h2 class="hndle"><span>' . esc_attr( $title ) . '</span></h2>' . "\n";
394
			echo '<div class="inside">' . "\n";
395
		}
396
	}
397
398
	/**
399
	 * Output the closing markup for a context box.
400
	 * @since 2.2.4
401
	 * @param $add_inside_close Whether to add closing div for .inside.
402
	 */
403
	public function context_box_title_markup_close( $add_inside_close = true ) {
404
405
		// Load the closing divs for a title box.
406
		if ( $add_inside_close ) {
407
			echo '</div>' . "\n"; // .inside
408
		}
409
410
		echo '</div>' . "\n"; // .context-box
411
	}
412
413
	/**
414
	 * Add metaboxes (to 'post' or 'comment' object types)
415
	 * @since 1.0.0
416
	 */
417
	public function add_metaboxes() {
418
419
		if ( ! $this->show_on() ) {
420
			return;
421
		}
422
423
		/*
424
		 * To keep from registering an actual post-screen metabox,
425
		 * omit the 'title' property from the metabox registration array.
426
		 *
427
		 * (WordPress will not display metaboxes without titles anyway)
428
		 *
429
		 * This is a good solution if you want to handle outputting your
430
		 * metaboxes/fields elsewhere in the post-screen.
431
		 */
432
		if ( ! $this->cmb->prop( 'title' ) ) {
433
			return;
434
		}
435
436
		$page = get_current_screen()->id;
437
		add_filter( "postbox_classes_{$page}_{$this->cmb->cmb_id}", array( $this, 'postbox_classes' ) );
438
439
		foreach ( $this->cmb->prop( 'object_types' ) as $object_type ) {
440
			if ( count( $this->cmb->tax_metaboxes_to_remove ) ) {
441
				$this->remove_default_tax_metaboxes( $object_type );
442
			}
443
444
			add_meta_box( $this->cmb->cmb_id, $this->cmb->prop( 'title' ), array( $this, 'metabox_callback' ), $object_type, $this->cmb->prop( 'context' ), $this->cmb->prop( 'priority' ) );
445
		}
446
	}
447
448
	/**
449
	 * Remove the specified default taxonomy metaboxes for a post-type.
450
	 * @since 2.2.3
451
	 * @param string $post_type Post type to remove the metabox for.
452
	 */
453
	protected function remove_default_tax_metaboxes( $post_type ) {
454
		foreach ( $this->cmb->tax_metaboxes_to_remove as $taxonomy ) {
455
			if ( ! taxonomy_exists( $taxonomy ) ) {
456
				continue;
457
			}
458
459
			$mb_id = is_taxonomy_hierarchical( $taxonomy ) ? "{$taxonomy}div" : "tagsdiv-{$taxonomy}";
460
			remove_meta_box( $mb_id, $post_type, 'side' );
461
		}
462
	}
463
464
	/**
465
	 * Modify metabox postbox classes.
466
	 * @since  2.2.4
467
	 * @param  array  $classes Array of classes
468
	 * @return array           Modified array of classes
469
	 */
470
	public function postbox_classes( $classes ) {
471
		if ( $this->cmb->prop( 'closed' ) && ! in_array( 'closed', $classes ) ) {
472
			$classes[] = 'closed';
473
		}
474
475
		if ( $this->cmb->is_alternate_context_box() ) {
476
			$classes = $this->alternate_context_postbox_classes( $classes );
477
		} else {
478
			$classes[] = 'cmb2-postbox';
479
		}
480
481
		return $classes;
482
	}
483
484
	/**
485
	 * Modify metabox altnernate context postbox classes.
486
	 * @since  2.2.4
487
	 * @param  array  $classes Array of classes
488
	 * @return array           Modified array of classes
489
	 */
490
	protected function alternate_context_postbox_classes( $classes ) {
491
		$classes[] = 'context-box';
492
		$classes[] = 'context-' . $this->cmb->prop( 'context' ) . '-box';
493
494
		if ( in_array( $this->cmb->cmb_id, get_hidden_meta_boxes( get_current_screen() ) ) ) {
495
			$classes[] = 'hide-if-js';
496
		}
497
498
		$add_wrap = ! empty( $this->cmb->prop( 'title' ) ) || empty( $this->cmb->prop( 'remove_box_wrap' ) );
499
500
		if ( $add_wrap ) {
501
			$classes[] = 'cmb2-postbox postbox';
502
		} else {
503
			$classes[] = 'cmb2-no-box-wrap';
504
		}
505
506
		return $classes;
507
	}
508
509
	/**
510
	 * Display metaboxes for a post or comment object
511
	 * @since  1.0.0
512
	 */
513
	public function metabox_callback() {
514
		$object_id = 'comment' == $this->object_type ? get_comment_ID() : get_the_ID();
515
		$this->cmb->show_form( $object_id, $this->object_type );
516
	}
517
518
	/**
519
	 * Display metaboxes for new user page
520
	 * @since  1.0.0
521
	 */
522
	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...
523
		if ( $section == $this->cmb->prop( 'new_user_section' ) ) {
524
			$object_id = $this->cmb->object_id();
525
			$this->cmb->object_id( isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id );
526
			$this->user_metabox();
527
		}
528
	}
529
530
	/**
531
	 * Display metaboxes for a user object
532
	 * @since  1.0.0
533
	 */
534
	public function user_metabox() {
535
		$this->show_form_for_type( 'user' );
536
	}
537
538
	/**
539
	 * Display metaboxes for a taxonomy term object
540
	 * @since  2.2.0
541
	 */
542
	public function term_metabox() {
543
		$this->show_form_for_type( 'term' );
544
	}
545
546
	/**
547
	 * Display metaboxes for an object type
548
	 * @since  2.2.0
549
	 * @param  string $type Object type
550
	 * @return void
551
	 */
552
	public function show_form_for_type( $type ) {
553
		if ( $type != $this->cmb->mb_object_type() ) {
554
			return;
555
		}
556
557
		if ( ! $this->show_on() ) {
558
			return;
559
		}
560
561
		if ( $this->cmb->prop( 'cmb_styles' ) ) {
562
			self::enqueue_cmb_css();
563
		}
564
		if ( $this->cmb->prop( 'enqueue_js' ) ) {
565
			self::enqueue_cmb_js();
566
		}
567
568
		$this->cmb->show_form( 0, $type );
569
	}
570
571
	/**
572
	 * Determines if metabox should be shown in current context
573
	 * @since  2.0.0
574
	 * @return bool Whether metabox should be added/shown
575
	 */
576
	public function show_on() {
577
		// If metabox is requesting to be conditionally shown
578
		$show = $this->cmb->should_show();
579
580
		/**
581
		 * Filter to determine if metabox should show. Default is true
582
		 *
583
		 * @param array  $show          Default is true, show the metabox
584
		 * @param mixed  $meta_box_args Array of the metabox arguments
585
		 * @param mixed  $cmb           The CMB2 instance
586
		 */
587
		$show = (bool) apply_filters( 'cmb2_show_on', $show, $this->cmb->meta_box, $this->cmb );
588
589
		return $show;
590
	}
591
592
	/**
593
	 * Get the CMB priority property set to numeric hook priority.
594
	 * @since  2.2.0
595
	 * @param  integer $default Default display hook priority.
596
	 * @return integer          Hook priority.
597
	 */
598
	public function get_priority( $default = 10 ) {
599
		$priority = $this->cmb->prop( 'priority' );
600
601
		if ( ! is_numeric( $priority ) ) {
602
			switch ( $priority ) {
603
604
				case 'high':
605
					$priority = 5;
606
					break;
607
608
				case 'low':
609
					$priority = 20;
610
					break;
611
612
				default:
613
					$priority = $default;
614
					break;
615
			}
616
		}
617
618
		return $priority;
619
	}
620
621
	/**
622
	 * Save data from post metabox
623
	 * @since  1.0.0
624
	 * @param  int    $post_id Post ID
625
	 * @param  mixed  $post    Post object
626
	 * @return null
627
	 */
628
	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...
629
630
		$post_type = $post ? $post->post_type : get_post_type( $post_id );
631
632
		$do_not_pass_go = (
633
			! $this->can_save( $post_type )
634
			// check user editing permissions
635
			|| ( 'page' == $post_type && ! current_user_can( 'edit_page', $post_id ) )
636
			|| ! current_user_can( 'edit_post', $post_id )
637
		);
638
639
		if ( $do_not_pass_go ) {
640
			// do not collect $200
641
			return;
642
		}
643
644
		// take a trip to reading railroad – if you pass go collect $200
645
		$this->cmb->save_fields( $post_id, 'post', $_POST );
646
	}
647
648
	/**
649
	 * Save data from comment metabox
650
	 * @since  2.0.9
651
	 * @param  int    $comment_id Comment ID
652
	 * @return null
653
	 */
654
	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...
655
656
		$can_edit = current_user_can( 'moderate_comments', $comment_id );
657
658
		if ( $this->can_save( get_comment_type( $comment_id ) ) && $can_edit ) {
659
			$this->cmb->save_fields( $comment_id, 'comment', $_POST );
660
		}
661
	}
662
663
	/**
664
	 * Save data from user fields
665
	 * @since  1.0.x
666
	 * @param  int   $user_id  User ID
667
	 * @return null
668
	 */
669
	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...
670
		// check permissions
671
		if ( $this->can_save( 'user' ) ) {
672
			$this->cmb->save_fields( $user_id, 'user', $_POST );
673
		}
674
	}
675
676
	/**
677
	 * Save data from term fields
678
	 * @since  2.2.0
679
	 * @param  int    $term_id  Term ID
680
	 * @param  int    $tt_id    Term Taxonomy ID
681
	 * @param  string $taxonomy Taxonomy
682
	 * @return null
683
	 */
684
	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...
685
		$taxonomy = $taxonomy ? $taxonomy : $tt_id;
686
687
		// check permissions
688
		if ( $this->taxonomy_can_save( $taxonomy ) && $this->can_save( 'term' ) ) {
689
			$this->cmb->save_fields( $term_id, 'term', $_POST );
690
		}
691
	}
692
693
	/**
694
	 * Delete term meta when a term is deleted.
695
	 * @since  2.2.0
696
	 * @param  int    $term_id  Term ID
697
	 * @param  int    $tt_id    Term Taxonomy ID
698
	 * @param  string $taxonomy Taxonomy
699
	 * @return null
700
	 */
701
	public function delete_term( $term_id, $tt_id, $taxonomy = '' ) {
702
		if ( $this->taxonomy_can_save( $taxonomy ) ) {
703
704
			$data_to_delete = array();
705
			foreach ( $this->cmb->prop( 'fields' ) as $field ) {
706
				$data_to_delete[ $field['id'] ] = '';
707
			}
708
709
			$this->cmb->save_fields( $term_id, 'term', $data_to_delete );
710
		}
711
	}
712
713
	/**
714
	 * Determines if the current object is able to be saved
715
	 * @since  2.0.9
716
	 * @param  string  $type Current post_type or comment_type
717
	 * @return bool          Whether object can be saved
718
	 */
719
	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...
720
		return apply_filters( 'cmb2_can_save', (
721
			$this->cmb->prop( 'save_fields' )
722
			// check nonce
723
			&& isset( $_POST[ $this->cmb->nonce() ] )
724
			&& wp_verify_nonce( $_POST[ $this->cmb->nonce() ], $this->cmb->nonce() )
725
			// check if autosave
726
			&& ! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
727
			// get the metabox types & compare it to this type
728
			&& ( $type && in_array( $type, $this->cmb->prop( 'object_types' ) ) )
729
			// Don't do updates during a switch-to-blog instance.
730
			&& ! ( is_multisite() && ms_is_switched() )
731
		) );
732
	}
733
734
	/**
735
	 * Determine if taxonomy of term being modified is cmb2-editable.
736
	 * @since  2.2.0
737
	 * @param  string $taxonomy Taxonomy of term being modified.
738
	 * @return bool             Whether taxonomy is editable.
739
	 */
740
	public function taxonomy_can_save( $taxonomy ) {
741
		if ( empty( $this->taxonomies ) || ! in_array( $taxonomy, $this->taxonomies ) ) {
742
			return false;
743
		}
744
745
		$taxonomy_object = get_taxonomy( $taxonomy );
746
		// Can the user edit this term?
747
		if ( ! isset( $taxonomy_object->cap ) || ! current_user_can( $taxonomy_object->cap->edit_terms ) ) {
748
			return false;
749
		}
750
751
		return true;
752
	}
753
754
	/**
755
	 * Enqueues the 'cmb2-display-styles' if the conditions match (has columns, on the right page, etc).
756
	 * @since  2.2.2.1
757
	 */
758
	protected function maybe_enqueue_column_display_styles() {
759
		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...
760
		if (
761
			$pagenow
762
			&& $this->cmb->has_columns
763
			&& $this->cmb->prop( 'cmb_styles' )
764
			&& in_array( $pagenow, array( 'edit.php', 'users.php', 'edit-comments.php', 'edit-tags.php' ), 1 )
765
			) {
766
			self::enqueue_cmb_css( 'cmb2-display-styles' );
767
		}
768
	}
769
770
	/**
771
	 * Includes CMB2 styles
772
	 * @since  2.0.0
773
	 */
774
	public static function enqueue_cmb_css( $handle = 'cmb2-styles' ) {
775
		if ( ! apply_filters( 'cmb2_enqueue_css', true ) ) {
776
			return false;
777
		}
778
779
		self::register_styles();
780
781
		/*
782
		 * White list the options as this method can be used as a hook callback
783
		 * and have a different argument passed.
784
		 */
785
		return wp_enqueue_style( 'cmb2-display-styles' === $handle ? $handle : 'cmb2-styles' );
786
	}
787
788
	/**
789
	 * Includes CMB2 JS
790
	 * @since  2.0.0
791
	 */
792
	public static function enqueue_cmb_js() {
793
		if ( ! apply_filters( 'cmb2_enqueue_js', true ) ) {
794
			return false;
795
		}
796
797
		self::register_js();
798
		return true;
799
	}
800
801
}
802