Completed
Push — trunk ( 90dfb1...7ce277 )
by Justin
03:29
created

CMB2_hookup::save_post()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42
Metric Value
dl 0
loc 19
rs 8.8571
ccs 0
cts 0
cp 0
cc 6
eloc 9
nc 16
nop 2
crap 42
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 {
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
	 * Array of all hooks done (to be run once)
18
	 * @var   array
19
	 * @since 2.0.0
20
	 */
21
	protected static $hooks_completed = array();
22
23
	/**
24
	 * Only allow JS registration once
25
	 * @var   bool
26
	 * @since 2.0.7
27
	 */
28
	protected static $js_registration_done = false;
29
30
	/**
31
	 * Only allow CSS registration once
32
	 * @var   bool
33
	 * @since 2.0.7
34
	 */
35
	protected static $css_registration_done = false;
36
37
	/**
38
	 * @var   CMB2 object
39
	 * @since 2.0.2
40
	 */
41
	protected $cmb;
42
43
	/**
44
	 * CMB taxonomies array for term meta
45
	 * @var   array
46
	 * @since 2.2.0
47
	 */
48
	protected $taxonomies = array();
49
50
	/**
51
	 * The object type we are performing the hookup for
52
	 * @var   string
53
	 * @since 2.0.9
54
	 */
55
	protected $object_type = 'post';
56
57
	public function __construct( CMB2 $cmb ) {
58
		$this->cmb = $cmb;
59
		$this->object_type = $this->cmb->mb_object_type();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->cmb->mb_object_type() can also be of type false. However, the property $object_type is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
60
61
		$this->universal_hooks();
62
63
		if ( is_admin() ) {
64
65
			switch ( $this->object_type ) {
66
				case 'post':
67
					return $this->post_hooks();
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
68
				case 'comment':
69
					return $this->comment_hooks();
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
70
				case 'user':
71
					return $this->user_hooks();
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
72
				case 'term':
73
					return $this->term_hooks();
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
74
			}
75
76
		}
77
	}
78
79
	public function universal_hooks() {
80
		foreach ( get_class_methods( 'CMB2_Show_Filters' ) as $filter ) {
81
			add_filter( 'cmb2_show_on', array( 'CMB2_Show_Filters', $filter ), 10, 3 );
82
		}
83
84
		if ( is_admin() ) {
85
			// register our scripts and styles for cmb
86
			$this->once( 'admin_enqueue_scripts', array( __CLASS__, 'register_scripts' ), 8 );
87
			$this->once( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) );
88
		}
89
	}
90
91
	public function post_hooks() {
92
		add_action( 'add_meta_boxes', array( $this, 'add_metaboxes' ) );
93
		add_action( 'add_attachment', array( $this, 'save_post' ) );
94
		add_action( 'edit_attachment', array( $this, 'save_post' ) );
95
		add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
96
	}
97
98
	public function comment_hooks() {
99
		add_action( 'add_meta_boxes_comment', array( $this, 'add_metaboxes' ) );
100
		add_action( 'edit_comment', array( $this, 'save_comment' ) );
101
	}
102
103
	public function user_hooks() {
104
		$priority = $this->get_priority();
105
106
		add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority );
107
		add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority );
108
		add_action( 'user_new_form', array( $this, 'user_new_metabox' ), $priority );
109
110 1
		add_action( 'personal_options_update', array( $this, 'save_user' ) );
111 1
		add_action( 'edit_user_profile_update', array( $this, 'save_user' ) );
112 1
		add_action( 'user_register', array( $this, 'save_user' ) );
113
	}
114
115
	public function term_hooks() {
116 1
		if ( ! function_exists( 'get_term_meta' ) ) {
117
			wp_die( __( 'Term Metadata is a WordPress > 4.4 feature. Please upgrade your WordPress install.', 'cmb2' ) );
118 1
		}
119
120 1
		if ( ! $this->cmb->prop( 'taxonomies' ) ) {
121 1
			wp_die( __( 'Term metaboxes configuration requires a \'taxonomies\' parameter', 'cmb2' ) );
122 1
		}
123 1
124 1
		$this->taxonomies = (array) $this->cmb->prop( 'taxonomies' );
125 1
		$show_on_term_add = $this->cmb->prop( 'new_term_section' );
126 1
		$priority         = $this->get_priority( 8 );
127 1
128 1
		foreach ( $this->taxonomies as $taxonomy ) {
129
			// Display our form data
130 1
			add_action( "{$taxonomy}_edit_form", array( $this, 'term_metabox' ), $priority, 2 );
131
132
			$show_on_add = is_array( $show_on_term_add )
133 1
				? in_array( $taxonomy, $show_on_term_add )
134
				: (bool) $show_on_term_add;
135 1
136
			$show_on_add = apply_filters( "cmb2_show_on_term_add_form_{$this->cmb->cmb_id}", $show_on_add, $this->cmb );
137 1
138
			// Display form in add-new section (unless specified not to)
139 1
			if ( $show_on_add ) {
140 1
				add_action( "{$taxonomy}_add_form_fields", array( $this, 'term_metabox' ), $priority, 2 );
141 1
			}
142 1
143 1
		}
144 1
145
		add_action( 'created_term', array( $this, 'save_term' ), 10, 3 );
146 1
		add_action( 'edited_terms', array( $this, 'save_term' ), 10, 2 );
147
		add_action( 'delete_term', array( $this, 'delete_term' ), 10, 3 );
148 1
	}
149 1
150 1
	/**
151 1
	 * Registers styles for CMB2
152 1
	 * @since 2.0.7
153 1
	 */
154 1
	protected static function register_styles() {
155 1
		if ( self::$css_registration_done ) {
156 1
			return;
157 1
		}
158 1
159 1
		// Only use minified files if SCRIPT_DEBUG is off
160 1
		$min   = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
161 1
		$front = is_admin() ? '' : '-front';
162
		$rtl = is_rtl() ? '-rtl' : '';
163 1
164 1
		// Filter required styles and register stylesheet
165 1
		$styles = apply_filters( 'cmb2_style_dependencies', array() );
166 1
		wp_register_style( 'cmb2-styles', cmb2_utils()->url( "css/cmb2{$front}{$rtl}{$min}.css" ), $styles );
167
168 1
		self::$css_registration_done = true;
169 1
	}
170
171 1
	/**
172 1
	 * Registers scripts for CMB2
173 1
	 * @since  2.0.7
174 1
	 */
175 1
	protected static function register_js() {
176 1
		if ( self::$js_registration_done ) {
177 1
			return;
178 1
		}
179
180 1
		$hook = is_admin() ? 'admin_footer' : 'wp_footer';
181
		add_action( $hook, array( 'CMB2_JS', 'enqueue' ), 8 );
182 1
183 1
		self::$js_registration_done = true;
184
	}
185
186
	/**
187
	 * Registers scripts and styles for CMB2
188
	 * @since  1.0.0
189
	 */
190
	public static function register_scripts() {
191
		self::register_styles();
192
		self::register_js();
193
	}
194
195
	/**
196
	 * Enqueues scripts and styles for CMB2 in admin_head.
197
	 * @since  1.0.0
198
	 */
199
	public function do_scripts( $hook ) {
200
		$hooks = array(
201
			'post.php',
202
			'post-new.php',
203
			'page-new.php',
204
			'page.php',
205
			'comment.php',
206
			'edit-tags.php',
207
			'term.php',
208
			'user-new.php',
209
			'profile.php',
210
			'user-edit.php',
211
		);
212
		// only pre-enqueue our scripts/styles on the proper pages
213
		// show_form_for_type will have us covered if we miss something here.
214
		if ( in_array( $hook, $hooks, true ) ) {
215
			if ( $this->cmb->prop( 'cmb_styles' ) ) {
216
				self::enqueue_cmb_css();
217
			}
218
			if ( $this->cmb->prop( 'enqueue_js' ) ) {
219
				self::enqueue_cmb_js();
220
			}
221
		}
222
	}
223
224
	/**
225
	 * Add metaboxes (to 'post' or 'comment' object types)
226
	 * @since 1.0.0
227
	 */
228
	public function add_metaboxes() {
229
230
		if ( ! $this->show_on() ) {
231
			return;
232
		}
233
234
		foreach ( $this->cmb->prop( 'object_types' ) as $post_type ) {
235
			/**
236
			 * To keep from registering an actual post-screen metabox,
237
			 * omit the 'title' attribute from the metabox registration array.
238
			 *
239
			 * (WordPress will not display metaboxes without titles anyway)
240
			 *
241
			 * This is a good solution if you want to output your metaboxes
242
			 * Somewhere else in the post-screen
243
			 */
244
			if ( $this->cmb->prop( 'title' ) ) {
245
246
				if ( $this->cmb->prop( 'closed' ) ) {
247
					add_filter( "postbox_classes_{$post_type}_{$this->cmb->cmb_id}", array( $this, 'close_metabox_class' ) );
248
				}
249
250
				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' ) );
251
			}
252
		}
253
	}
254
255
	/**
256
	 * Add 'closed' class to metabox
257
	 * @since  2.0.0
258
	 * @param  array  $classes Array of classes
259
	 * @return array           Modified array of classes
260
	 */
261
	public function close_metabox_class( $classes ) {
262
		$classes[] = 'closed';
263
		return $classes;
264
	}
265
266
	/**
267
	 * Display metaboxes for a post or comment object
268
	 * @since  1.0.0
269
	 */
270
	public function metabox_callback() {
271
		$object_id = 'comment' == $this->object_type ? get_comment_ID() : get_the_ID();
272
		$this->cmb->show_form( $object_id, $this->object_type );
273
	}
274
275
	/**
276
	 * Display metaboxes for new user page
277
	 * @since  1.0.0
278
	 */
279
	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...
280
		if ( $section == $this->cmb->prop( 'new_user_section' ) ) {
281
			$object_id = $this->cmb->object_id();
282
			$this->cmb->object_id( isset( $_REQUEST['user_id'] ) ? $_REQUEST['user_id'] : $object_id );
283
			$this->user_metabox();
284
		}
285
	}
286
287
	/**
288
	 * Display metaboxes for a user object
289
	 * @since  1.0.0
290
	 */
291
	public function user_metabox() {
292
		$this->show_form_for_type( 'user' );
293
	}
294
295
	/**
296
	 * Display metaboxes for a taxonomy term object
297
	 * @since  2.2.0
298
	 */
299
	public function term_metabox() {
300
		$this->show_form_for_type( 'term' );
301
	}
302
303
	/**
304
	 * Display metaboxes for an object type
305
	 * @since  2.2.0
306
	 * @param  string $type Object type
307
	 * @return void
308
	 */
309
	public function show_form_for_type( $type ) {
310
		if ( $type != $this->cmb->mb_object_type() ) {
311
			return;
312
		}
313
314
		if ( ! $this->show_on() ) {
315
			return;
316
		}
317
318
		if ( $this->cmb->prop( 'cmb_styles' ) ) {
319
			self::enqueue_cmb_css();
320
		}
321
		if ( $this->cmb->prop( 'enqueue_js' ) ) {
322
			self::enqueue_cmb_js();
323
		}
324
325
		$this->cmb->show_form( 0, $type );
326
	}
327
328
	/**
329
	 * Determines if metabox should be shown in current context
330
	 * @since  2.0.0
331
	 * @return bool Whether metabox should be added/shown
332
	 */
333
	public function show_on() {
334
		// If metabox is requesting to be conditionally shown
335
		$show = $this->cmb->should_show();
336
337
		/**
338
		 * Filter to determine if metabox should show. Default is true
339
		 *
340
		 * @param array  $show          Default is true, show the metabox
341
		 * @param mixed  $meta_box_args Array of the metabox arguments
342
		 * @param mixed  $cmb           The CMB2 instance
343
		 */
344
		$show = (bool) apply_filters( 'cmb2_show_on', $show, $this->cmb->meta_box, $this->cmb );
345
346
		return $show;
347
	}
348
349
	/**
350 1
	 * Get the CMB priority property set to numeric hook priority.
351 1
	 * @since  2.2.0
352
	 * @param  integer $default Default display hook priority.
353 1
	 * @return integer          Hook priority.
354
	 */
355
	public function get_priority( $default = 10 ) {
356
		$priority = $this->cmb->prop( 'priority' );
357
358
		if ( ! is_numeric( $priority ) ) {
359
			switch ( $priority ) {
360 1
361 1
				case 'high':
362 1
					$priority = 5;
363 1
					break;
364
365
				case 'low':
366
					$priority = 20;
367 1
					break;
368
369
				default:
370
					$priority = $default;
371
					break;
372
			}
373
		}
374
375
		return $priority;
376
	}
377
378
	/**
379
	 * Save data from post metabox
380
	 * @since  1.0.0
381
	 * @param  int    $post_id Post ID
382
	 * @param  mixed  $post    Post object
383
	 * @return null
384
	 */
385
	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...
386
387
		$post_type = $post ? $post->post_type : get_post_type( $post_id );
388
389
		$do_not_pass_go = (
390
			! $this->can_save( $post_type )
391
			// check user editing permissions
392
			|| ( 'page' == $post_type && ! current_user_can( 'edit_page', $post_id ) )
393
			|| ! current_user_can( 'edit_post', $post_id )
394
		);
395
396
		if ( $do_not_pass_go ) {
397
			// do not collect $200
398
			return;
399
		}
400
401
		// take a trip to reading railroad – if you pass go collect $200
402
		$this->cmb->save_fields( $post_id, 'post', $_POST );
403
	}
404
405
	/**
406
	 * Save data from comment metabox
407
	 * @since  2.0.9
408
	 * @param  int    $comment_id Comment ID
409
	 * @return null
410
	 */
411
	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...
412
413
		$can_edit = current_user_can( 'moderate_comments', $comment_id );
414
415
		if ( $this->can_save( get_comment_type( $comment_id ) ) && $can_edit ) {
416
			$this->cmb->save_fields( $comment_id, 'comment', $_POST );
417
		}
418
	}
419
420
	/**
421
	 * Save data from user fields
422
	 * @since  1.0.x
423
	 * @param  int   $user_id  User ID
424
	 * @return null
425
	 */
426
	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...
427
		// check permissions
428
		if ( $this->can_save( 'user' ) ) {
429
			$this->cmb->save_fields( $user_id, 'user', $_POST );
430
		}
431
	}
432
433
	/**
434
	 * Save data from term fields
435
	 * @since  2.2.0
436
	 * @param  int    $term_id  Term ID
437
	 * @param  int    $tt_id    Term Taxonomy ID
438
	 * @param  string $taxonomy Taxonomy
439
	 * @return null
440
	 */
441
	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...
442
		$taxonomy = $taxonomy ? $taxonomy : $tt_id;
443
444
		// check permissions
445
		if ( $this->taxonomy_can_save( $taxonomy ) && $this->can_save( 'term' ) ) {
446
			$this->cmb->save_fields( $term_id, 'term', $_POST );
447
		}
448
	}
449
450
	/**
451
	 * Delete term meta when a term is deleted.
452
	 * @since  2.2.0
453
	 * @param  int    $term_id  Term ID
454
	 * @param  int    $tt_id    Term Taxonomy ID
455
	 * @param  string $taxonomy Taxonomy
456
	 * @return null
457
	 */
458
	public function delete_term( $term_id, $tt_id, $taxonomy = '' ) {
459
		if ( $this->taxonomy_can_save( $taxonomy ) ) {
460
461
			foreach ( $this->cmb->prop( 'fields' ) as $field ) {
462
				$data_to_delete[ $field['id'] ] = '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$data_to_delete was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data_to_delete = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
463
			}
464
465
			$this->cmb->save_fields( $term_id, 'term', $data_to_delete );
0 ignored issues
show
Bug introduced by
The variable $data_to_delete does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
466
		}
467
	}
468
469
	/**
470
	 * Determines if the current object is able to be saved
471
	 * @since  2.0.9
472
	 * @param  string  $type Current post_type or comment_type
473
	 * @return bool          Whether object can be saved
474
	 */
475
	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...
476
		return (
477
			$this->cmb->prop( 'save_fields' )
478
			// check nonce
479
			&& isset( $_POST[ $this->cmb->nonce() ] )
480
			&& wp_verify_nonce( $_POST[ $this->cmb->nonce() ], $this->cmb->nonce() )
481
			// check if autosave
482
			&& ! ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
483
			// get the metabox types & compare it to this type
484
			&& ( $type && in_array( $type, $this->cmb->prop( 'object_types' ) ) )
485
		);
486
	}
487
488
	/**
489
	 * Determine if taxonomy of term being modified is cmb2-editable.
490
	 * @since  2.2.0
491
	 * @param  string $taxonomy Taxonomy of term being modified.
492
	 * @return bool             Whether taxonomy is editable.
493
	 */
494
	public function taxonomy_can_save( $taxonomy ) {
495
		if ( empty( $this->taxonomies ) || ! in_array( $taxonomy, $this->taxonomies ) ) {
496
			return false;
497
		}
498
499
		$taxonomy_object = get_taxonomy( $taxonomy );
500
		// Can the user edit this term?
501
		if ( ! isset( $taxonomy_object->cap ) || ! current_user_can( $taxonomy_object->cap->edit_terms ) ) {
502
			return false;
503
		}
504
505
		return true;
506
	}
507
508
	/**
509
	 * Ensures WordPress hook only gets fired once
510
	 * @since  2.0.0
511
	 * @param string   $action        The name of the filter to hook the $hook callback to.
512
	 * @param callback $hook          The callback to be run when the filter is applied.
513
	 * @param integer  $priority      Order the functions are executed
514
	 * @param int      $accepted_args The number of arguments the function accepts.
515
	 */
516
	public function once( $action, $hook, $priority = 10, $accepted_args = 1 ) {
517
		$key = md5( serialize( func_get_args() ) );
518
519
		if ( in_array( $key, self::$hooks_completed ) ) {
520
			return;
521
		}
522
523
		self::$hooks_completed[] = $key;
524
		add_filter( $action, $hook, $priority, $accepted_args );
525
	}
526
527
	/**
528
	 * Includes CMB2 styles
529
	 * @since  2.0.0
530
	 */
531
	public static function enqueue_cmb_css() {
532
		if ( ! apply_filters( 'cmb2_enqueue_css', true ) ) {
533
			return false;
534
		}
535
536
		self::register_styles();
537
		return wp_enqueue_style( 'cmb2-styles' );
538
	}
539
540
	/**
541
	 * Includes CMB2 JS
542
	 * @since  2.0.0
543
	 */
544
	public static function enqueue_cmb_js() {
545
		if ( ! apply_filters( 'cmb2_enqueue_js', true ) ) {
546
			return false;
547
		}
548
549
		self::register_js();
550
		return true;
551
	}
552
553
}
554