Completed
Push — master ( 47b584...ff21ec )
by Leon
02:41
created

CMB2_Meta_Box::should_add_arg()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 2
nc 3
nop 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * CMB2 Meta Box
4
 *
5
 * @since  0.1.0
6
 *
7
 * @category  WordPress_Plugin
8
 * @package   CMB2 Admin Extension
9
 * @author    twoelevenjay
10
 * @license   GPL-2.0+
11
 */
12
13
if ( ! class_exists( 'CMB2_Meta_Box' ) ) {
14
15
	/**
16
	 * Class CMB2_Meta_Box.
17
	 */
18
	class CMB2_Meta_Box {
19
20
		/**
21
		 * Field prefix.
22
		 *
23
		 * @var string
24
		 */
25
		private $prefix = '_cmb2_';
26
27
		/**
28
		 * Instance of this class.
29
		 *
30
		 * @var object
31
		 */
32
		protected static $instance;
33
34
		/**
35
		 * Initiate CMB2 Admin Extension object.
36
		 *
37
		 * @todo For now plugin will use one main object, will consider 3 seperate objects in the future.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
38
		 * @todo Comment.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
39
		 *
40
		 * @since 0.0.1
41
		 */
42
		public function __construct() {
43
44
			add_action( 'pre_current_active_plugins', array( $this, 'hide_cmb2_plugins' ) );
45
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
46
			add_action( 'cmb2_init', array( $this, 'init_user_defined_meta_boxes_and_fields' ) );
47
		}
48
49
		/**
50
		 * Return an instance of this class.
51
		 *
52
		 * @return object A single instance of this class.
53
		 */
54
		public static function get_instance() {
55
			// If the single instance hasn't been set, set it now.
56
			if ( self::$instance === null ) {
57
				self::$instance = new self;
58
			}
59
60
			return self::$instance;
61
		}
62
63
64
		/**
65
		 * Determine if current user has permission to CMB2 view plugins.
66
		 *
67
		 * @since  0.0.1
68
		 */
69
		public function is_cmb2_allowed() {
70
71
			$cmb2_settings = get_option( '_cmb2_settings' );
72
73
			if ( empty( $cmb2_settings ) ) {
74
				// No settings saved.
75
				return true;
76
			}
77
78
			$current_user  = wp_get_current_user();
79
			$allowed_users = isset( $cmb2_settings['_cmb2_user_multicheckbox'] ) ? $cmb2_settings['_cmb2_user_multicheckbox'] : array();
80
81
			return empty( $allowed_users ) || in_array( $current_user->ID, $allowed_users, true );
82
		}
83
84
		/**
85
		 * Only show CMB2 plugins to users defined in settings.
86
		 *
87
		 * @since  0.0.1
88
		 */
89
		public function hide_cmb2_plugins() {
90
91
			global $wp_list_table;
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...
92
			if ( ! $this->is_cmb2_allowed() ) {
93
				$to_hide = array( CMB2AE_CMB2_PLUGIN_FILE, 'cmb2-admin-extension/cmb2-admin-extension.php' );
94
				$plugins = $wp_list_table->items;
95
				foreach ( array_keys( $plugins ) as $key ) {
96
					if ( in_array( $key, $to_hide, true ) ) {
97
						unset( $wp_list_table->items[$key] );
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
98
					}
99
				}
100
			}
101
		}
102
103
		/**
104
		 * Enqueue CMB2 Admin Extension scripts and styles.
105
		 *
106
		 * @since  0.0.8
107
		 */
108
		public function enqueue_scripts() {
109
110
			$screen = get_current_screen();
111
			if ( $screen->post_type === 'meta_box' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
112
113
				wp_register_style( 'cmb2_admin_styles', CMB2AE_URI . '/css/meta-box-fields.css', false, '0.0.8' );
114
				wp_enqueue_style( 'cmb2_admin_styles' );
115
				wp_enqueue_script( 'cmb2_admin_scripts', CMB2AE_URI . '/js/meta-box-fields.js', true, array( 'jquery' ), '0.0.8' );
116
			}
117
		}
118
119
		/**
120
		 * Function is_repeatable().
121
		 *
122
		 * @todo Document properly.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
123
		 * @since  0.0.6
124
		 *
125
		 * @param string $field_type A CMB2 field type.
126
		 */
127
		static function is_repeatable( $field_type ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
128
129
			$repeatable_fields = array(
130
				'text',
131
				'text_small',
132
				'text_medium',
133
				'text_email',
134
				'text_url',
135
				'text_money',
136
				'textarea',
137
				'textarea_small',
138
				'textarea_code',
139
				'text_date',
140
				'text_time',
141
				'select_timezone',
142
				'text_date_timestamp',
143
				'text_datetime_timestamp',
144
				'text_datetime_timestamp_timezone',
145
				'colorpicker',
146
				'select',
147
				'multicheck',
148
				'multicheck_inline',
149
				'file',
150
				'file_list',
151
			);
152
			return in_array( $field_type, $repeatable_fields, true );
153
		}
154
155
		/**
156
		 * Function has_options().
157
		 *
158
		 * @todo Document properly.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
159
		 * @since  0.0.6
160
		 *
161
		 * @param string $field_type A CMB2 field type.
162
		 */
163
		static function has_options( $field_type ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
164
165
			$options_fields = array(
166
				'radio',
167
				'radio_inline',
168
				'taxonomy_radio',
169
				'taxonomy_radio_inline',
170
				'select',
171
				'taxonomy_select',
172
				'multicheck',
173
				'multicheck_inline',
174
				'taxonomy_multicheck',
175
				'taxonomy_multicheck_inline',
176
			);
177
			return in_array( $field_type, $options_fields, true );
178
		}
179
180
		/**
181
		 * Function should_add_arg().
182
		 *
183
		 * @todo Conditional to check if the field argument should be added.
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
184
		 * @since  0.0.6
185
		 *
186
		 * @param array  $field      Field definition.
187
		 * @param string $field_type A CMB2 field type.
188
		 * @param string $field_key  $field key to check.
189
		 */
190
		static function should_add_arg( $field, $field_type, $field_key ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
191
192
			return ( in_array( $field['_cmb2_field_type_select'], $field_type, true ) && ( ! empty( $field[$field_key] ) && $field[$field_key] !== '' ) );
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
193
		}
194
195
		/**
196
		 * Loop through user defined meta_box and creates the custom meta boxes and fields.
197
		 *
198
		 * @since  0.0.1
199
		 */
200
		public function init_user_defined_meta_boxes_and_fields() {
201
202
			$args = array(
203
				'post_type'        => 'meta_box',
204
				'post_status'      => 'publish',
205
				'posts_per_page'   => -1,
0 ignored issues
show
introduced by
Disabling pagination is prohibited in VIP context, do not set posts_per_page to -1 ever.
Loading history...
206
				'suppress_filters' => false,
207
			);
208
209
			$prefix = $this->prefix;
210
211
			$user_meta_boxes = get_posts( $args );
212
213
			foreach ( $user_meta_boxes as $user_meta_box ) {
214
215
				$metabox_id = $user_meta_box->ID;
216
217
				$title          = get_the_title( $metabox_id );
218
				$id             = str_replace( '-', '_', $user_meta_box->post_name );
219
				$post_type      = cmbf( $metabox_id, $prefix . 'post_type_multicheckbox' );
220
				$context        = cmbf( $metabox_id, $prefix . 'context_radio' );
221
				$priority       = cmbf( $metabox_id, $prefix . 'priority_radio' );
222
				$show_names     = cmbf( $metabox_id, $prefix . 'show_names' ) === 'on' ? true : false;
223
				$disable_styles = cmbf( $metabox_id, $prefix . 'disable_styles' ) === 'on' ? true : false;
224
				$closed         = cmbf( $metabox_id, $prefix . 'closed' ) === 'on' ? true : false;
225
				$fields         = cmbf( $metabox_id, $prefix . 'custom_field' );
226
227
				/**
228
				 * Initiate the metabox.
229
				 */
230
				${ 'cmb_' . $id } = new_cmb2_box( array(
231
					'id'           => $id,
232
					'title'        => $title,
233
					'object_types' => $post_type, // Post type.
234
					'context'      => $context,
235
					'priority'     => $priority,
236
					'show_names'   => $show_names,
237
					'cmb_styles'   => $disable_styles,
238
					'closed'       => $closed,
239
				) );
240
241
				foreach ( $fields as $field ) {
242
243
					$field_id = '_' . strtolower( str_replace( ' ', '_', $field['_cmb2_name_text'] ) );
244
245
					$field_args = array(
246
						'name' => $field['_cmb2_name_text'],
247
						'desc' => $field['_cmb2_decription_textarea'],
248
						'id'   => $field_id,
249
						'type' => $field['_cmb2_field_type_select'],
250
					);
251
252
					$options = isset( $field['_cmb2_options_textarea'] ) ? $field['_cmb2_options_textarea'] : false;
253
					if ( $options ) {
254
						$options = explode( PHP_EOL, $options );
255
						foreach ( $options as $option ) {
256
							$opt_arr = explode( ',', $option );
257
							if ( ! isset( $opt_arr[1] ) ) {
258
								continue;
259
							}
260
							$field_options[$opt_arr[0]] = $opt_arr[1];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$field_options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $field_options = 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...
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
261
						}
262
						$field_args['options'] = $field_options;
0 ignored issues
show
Bug introduced by
The variable $field_options 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...
263
					}
264
					if ( strpos( $field['_cmb2_field_type_select'], 'tax' ) !== false && $field['_cmb2_tax_options_radio_inline'] !== '' ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
265
						$field_args['taxonomy'] = $field['_cmb2_tax_options_radio_inline'];
266
					}
267
					if ( strpos( $field['_cmb2_field_type_select'], 'tax' ) !== false && isset( $field['_cmb2_no_terms_text'] ) && $field['_cmb2_no_terms_text'] !== '' ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
268
						$field_args['options']['no_terms_text'] = $field['_cmb2_no_terms_text'];
269
					}
270
					if ( isset( $field['_cmb2_repeatable_checkbox'] ) && $field['_cmb2_repeatable_checkbox'] === 'on' && $this->is_repeatable( $field['_cmb2_field_type_select'] ) ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
271
						$field_args['repeatable'] = true;
272
					}
273
					if ( $field['_cmb2_field_type_select'] === 'url' && isset( $field['_cmb2_protocols_checkbox'] ) && ! empty( $field['_cmb2_protocols_checkbox'] ) ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
274
						$field_args['protocols'] = $field['_cmb2_protocols_checkbox'];
275
					}
276
					if ( $this->should_add_arg( $field, array( 'text_money' ), '_cmb2_currency_text' ) ) {
0 ignored issues
show
Documentation introduced by
array('text_money') is of type array<integer,string,{"0":"string"}>, but the function expects a string.

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...
277
						$field_args['before_field'] = $field['_cmb2_currency_text'];
278
					}
279
					if ( $this->should_add_arg( $field, array( 'text_time' ), '_cmb2_time_format' ) ) {
0 ignored issues
show
Documentation introduced by
array('text_time') is of type array<integer,string,{"0":"string"}>, but the function expects a string.

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...
280
						$field_args['time_format'] = $field['_cmb2_time_format'];
281
					}
282
					if ( $this->should_add_arg( $field, array( 'text_date', 'text_date_timestamp' ), '_cmb2_date_format' ) ) {
0 ignored issues
show
Documentation introduced by
array('text_date', 'text_date_timestamp') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string.

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...
283
						$field_args['date_format'] = $field['_cmb2_date_format'];
284
					}
285
					if ( $this->should_add_arg( $field, array( 'text_date_timestamp' ), '_cmb2_time_zone_key_select' ) ) {
0 ignored issues
show
Documentation introduced by
array('text_date_timestamp') is of type array<integer,string,{"0":"string"}>, but the function expects a string.

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...
286
						$field_args['timezone_meta_key'] = $field['_cmb2_time_zone_key_select'];
287
					}
288
					if ( isset( $field['_cmb2_none_checkbox'] ) && $field['_cmb2_none_checkbox'] === 'on' && $this->has_options( $field['_cmb2_field_type_select'] ) ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
289
						$field_args['show_option_none'] = true;
290
					}
291
					if ( strpos( $field['_cmb2_field_type_select'], 'multicheck' ) !== false && isset( $field['_cmb2_select_all_checkbox'] ) && $field['_cmb2_select_all_checkbox'] === 'on' ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
292
						$field_args['select_all_button'] = false;
293
					}
294
					if ( $this->should_add_arg( $field, array( 'file' ), '_cmb2_add_upload_file_text' ) ) {
0 ignored issues
show
Documentation introduced by
array('file') is of type array<integer,string,{"0":"string"}>, but the function expects a string.

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...
295
						$field_args['options']['add_upload_file_text'] = $field['_cmb2_add_upload_file_text'];
296
					}
297
					${ 'cmb_' . $id }->add_field( $field_args );
298
299
				}
300
			}
301
		}
302
	}
303
}
304
305
if ( ! function_exists( 'cmb2ae_metabox' ) ) {
306
	/**
307
	 * Main instance of CMB2_Meta_Box.
308
	 *
309
	 * @since  0.1.0
310
	 */
311
	function cmb2ae_metabox() {
312
		return CMB2_Meta_Box::get_instance();
313
	}
314
}
315