CMB2_REST   F
last analyzed

Complexity

Total Complexity 95

Size/Duplication

Total Lines 772
Duplicated Lines 0 %

Test Coverage

Coverage 83.64%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 95
eloc 188
c 1
b 0
f 0
dl 0
loc 772
ccs 179
cts 214
cp 0.8364
rs 2

33 Methods

Rating   Name   Duplication   Size   Complexity  
A maybe_init_and_hookup() 0 9 3
A can_read() 0 8 2
C register_cmb2_fields() 0 49 10
A universal_hooks() 0 13 2
A is_editable() 0 5 1
A is_readable() 0 6 2
A can_edit() 0 8 2
B get_object_id() 0 20 10
A register_rest_field() 0 5 1
A field_can_read() 0 2 1
A get_post_rest_values() 0 3 2
A is_protected_meta() 0 6 2
A declare_read_edit_fields() 0 14 6
A get_all() 0 2 1
A update_term_rest_values() 0 3 2
A __get() 0 9 5
A sanitize_field_value() 0 19 4
A remove() 0 3 2
A update_user_rest_values() 0 3 2
A __construct() 0 8 1
A sanitize_group_value() 0 9 2
A get_term_rest_values() 0 3 2
A update_post_rest_values() 0 3 2
A get_user_rest_values() 0 3 2
A init_routes() 0 8 1
A sanitize_box_values() 0 12 2
A get_rest_box() 0 2 2
B update_rest_values() 0 29 7
A get_comment_rest_values() 0 3 2
A get_rest_values() 0 26 5
A update_comment_rest_values() 0 3 2
A field_can() 0 6 4
A field_can_edit() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like CMB2_REST often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CMB2_REST, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Handles hooking CMB2 objects/fields into the WordPres REST API
4
 * which can allow fields to be read and/or updated.
5
 *
6
 * @since  2.2.3
7
 *
8
 * @category  WordPress_Plugin
9
 * @package   CMB2
10
 * @author    CMB2 team
11
 * @license   GPL-2.0+
12
 * @link      https://cmb2.io
13
 *
14
 * @property-read read_fields Array of readable field objects.
15
 * @property-read edit_fields Array of editable field objects.
16
 * @property-read rest_read   Whether CMB2 object is readable via the rest api.
17
 * @property-read rest_edit   Whether CMB2 object is editable via the rest api.
18
 */
19
class CMB2_REST extends CMB2_Hookup_Base {
20
21
	/**
22
	 * The current CMB2 REST endpoint version
23
	 *
24
	 * @var string
25
	 * @since 2.2.3
26
	 */
27
	const VERSION = '1';
28
29
	/**
30
	 * The CMB2 REST base namespace (v should always be followed by $version)
31
	 *
32
	 * @var string
33
	 * @since 2.2.3
34
	 */
35
	const NAME_SPACE = 'cmb2/v1';
36
37
	/**
38
	 * @var   CMB2 object
39
	 * @since 2.2.3
40
	 */
41
	public $cmb;
42
43
	/**
44
	 * @var   CMB2_REST[] objects
45
	 * @since 2.2.3
46
	 */
47
	protected static $boxes = array();
48
49
	/**
50
	 * @var   array Array of cmb ids for each type.
51
	 * @since 2.2.3
52
	 */
53
	protected static $type_boxes = array(
54
		'post' => array(),
55
		'user' => array(),
56
		'comment' => array(),
57
		'term' => array(),
58
	);
59
60
	/**
61
	 * Array of readable field objects.
62
	 *
63
	 * @var   CMB2_Field[]
64
	 * @since 2.2.3
65
	 */
66
	protected $read_fields = array();
67
68
	/**
69
	 * Array of editable field objects.
70
	 *
71
	 * @var   CMB2_Field[]
72
	 * @since 2.2.3
73
	 */
74
	protected $edit_fields = array();
75
76
	/**
77
	 * Whether CMB2 object is readable via the rest api.
78
	 *
79
	 * @var boolean
80
	 */
81
	protected $rest_read = false;
82
83
	/**
84
	 * Whether CMB2 object is editable via the rest api.
85
	 *
86
	 * @var boolean
87
	 */
88
	protected $rest_edit = false;
89
90
	/**
91
	 * A functionalized constructor, used for the hookup action callbacks.
92
	 *
93
	 * @since  2.2.6
94
	 *
95
	 * @param  CMB2 $cmb The CMB2 object to hookup
96
	 *
97
	 * @return CMB2_Hookup_Base $hookup The hookup object.
98
	 */
99
	public static function maybe_init_and_hookup( CMB2 $cmb ) {
100
		if ( $cmb->prop( 'show_in_rest' ) && function_exists( 'rest_get_server' ) ) {
101
102
			$hookup = new self( $cmb );
103
104
			return $hookup->universal_hooks();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $hookup->universal_hooks() targeting CMB2_REST::universal_hooks() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

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

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

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

Loading history...
105
		}
106
107
		return false;
108
	}
109
110
	/**
111
	 * Constructor
112
	 *
113
	 * @since 2.2.3
114
	 *
115
	 * @param CMB2 $cmb The CMB2 object to be registered for the API.
116
	 */
117 38
	public function __construct( CMB2 $cmb ) {
118 38
		$this->cmb = $cmb;
119 38
		self::$boxes[ $cmb->cmb_id ] = $this;
0 ignored issues
show
Bug Best Practice introduced by
The property $cmb_id is declared protected in CMB2_Base. Since you implement __get, consider adding a @property or @property-read.
Loading history...
120
121 38
		$show_value = $this->cmb->prop( 'show_in_rest' );
122
123 38
		$this->rest_read = self::is_readable( $show_value );
124 38
		$this->rest_edit = self::is_editable( $show_value );
125 38
	}
126
127
	/**
128
	 * Hooks to register on frontend and backend.
129
	 *
130
	 * @since  2.2.3
131
	 *
132
	 * @return void
133
	 */
134 38
	public function universal_hooks() {
135
		// hook up the CMB rest endpoint classes
136 38
		$this->once( 'rest_api_init', array( __CLASS__, 'init_routes' ), 0 );
137
138 38
		if ( function_exists( 'register_rest_field' ) ) {
139 38
			$this->once( 'rest_api_init', array( __CLASS__, 'register_cmb2_fields' ), 50 );
140
		}
141
142 38
		$this->declare_read_edit_fields();
143
144 38
		add_filter( 'is_protected_meta', array( $this, 'is_protected_meta' ), 10, 3 );
145
146 38
		return $this;
147
	}
148
149
	/**
150
	 * Initiate the CMB2 Boxes and Fields routes
151
	 *
152
	 * @since  2.2.3
153
	 *
154
	 * @return void
155
	 */
156 1
	public static function init_routes() {
157 1
		$wp_rest_server = rest_get_server();
0 ignored issues
show
Bug introduced by
The function rest_get_server was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

157
		$wp_rest_server = /** @scrutinizer ignore-call */ rest_get_server();
Loading history...
158
159 1
		$boxes_controller = new CMB2_REST_Controller_Boxes( $wp_rest_server );
160 1
		$boxes_controller->register_routes();
161
162 1
		$fields_controller = new CMB2_REST_Controller_Fields( $wp_rest_server );
163 1
		$fields_controller->register_routes();
164 1
	}
165
166
	/**
167
	 * Loop through REST boxes and call register_rest_field for each object type.
168
	 *
169
	 * @since  2.2.3
170
	 *
171
	 * @return void
172
	 */
173 38
	public static function register_cmb2_fields() {
174 38
		$alltypes = $taxonomies = array();
175
176 38
		foreach ( self::$boxes as $cmb_id => $rest_box ) {
177 38
			$types = array_flip( $rest_box->cmb->box_types( array( 'post' ) ) );
178
179 38
			if ( isset( $types['user'] ) ) {
180 10
				unset( $types['user'] );
181 10
				self::$type_boxes['user'][ $cmb_id ] = $cmb_id;
182
			}
183
184 38
			if ( isset( $types['comment'] ) ) {
185 10
				unset( $types['comment'] );
186 10
				self::$type_boxes['comment'][ $cmb_id ] = $cmb_id;
187
			}
188
189 38
			if ( isset( $types['term'] ) ) {
190 10
				unset( $types['term'] );
191
192 10
				$taxonomies = array_merge(
193 10
					$taxonomies,
194 10
					CMB2_Utils::ensure_array( $rest_box->cmb->prop( 'taxonomies' ) )
195
				);
196
197 10
				self::$type_boxes['term'][ $cmb_id ] = $cmb_id;
198
			}
199
200 38
			if ( ! empty( $types ) ) {
201 38
				$alltypes = array_merge( $alltypes, array_flip( $types ) );
202 38
				self::$type_boxes['post'][ $cmb_id ] = $cmb_id;
203
			}
204
		}
205
206 38
		$alltypes = array_unique( $alltypes );
207
208 38
		if ( ! empty( $alltypes ) ) {
209 38
			self::register_rest_field( $alltypes, 'post' );
0 ignored issues
show
Bug introduced by
$alltypes of type array is incompatible with the type string expected by parameter $object_types of CMB2_REST::register_rest_field(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

209
			self::register_rest_field( /** @scrutinizer ignore-type */ $alltypes, 'post' );
Loading history...
210
		}
211
212 38
		if ( ! empty( self::$type_boxes['user'] ) ) {
213 10
			self::register_rest_field( 'user', 'user' );
214
		}
215
216 38
		if ( ! empty( self::$type_boxes['comment'] ) ) {
217 10
			self::register_rest_field( 'comment', 'comment' );
218
		}
219
220 38
		if ( ! empty( self::$type_boxes['term'] ) ) {
221 10
			self::register_rest_field( $taxonomies, 'term' );
0 ignored issues
show
Bug introduced by
$taxonomies of type array is incompatible with the type string expected by parameter $object_types of CMB2_REST::register_rest_field(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

221
			self::register_rest_field( /** @scrutinizer ignore-type */ $taxonomies, 'term' );
Loading history...
222
		}
223 38
	}
224
225
	/**
226
	 * Wrapper for register_rest_field.
227
	 *
228
	 * @since  2.2.3
229
	 *
230
	 * @param string|array $object_types Object(s) the field is being registered
231
	 *                                   to, "post"|"term"|"comment" etc.
232
	 * @param string       $object_types       Canonical object type for callbacks.
233
	 *
234
	 * @return void
235
	 */
236 38
	protected static function register_rest_field( $object_types, $object_type ) {
237 38
		register_rest_field( $object_types, 'cmb2', array(
0 ignored issues
show
Bug introduced by
The function register_rest_field was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

237
		/** @scrutinizer ignore-call */ 
238
  register_rest_field( $object_types, 'cmb2', array(
Loading history...
238 38
			'get_callback'    => array( __CLASS__, "get_{$object_type}_rest_values" ),
239 38
			'update_callback' => array( __CLASS__, "update_{$object_type}_rest_values" ),
240
			'schema'          => null, // @todo add schema
241
		) );
242 38
	}
243
244
	/**
245
	 * Setup readable and editable fields.
246
	 *
247
	 * @since  2.2.3
248
	 *
249
	 * @return void
250
	 */
251 38
	protected function declare_read_edit_fields() {
252 38
		foreach ( $this->cmb->prop( 'fields' ) as $field ) {
253 38
			$show_in_rest = isset( $field['show_in_rest'] ) ? $field['show_in_rest'] : null;
254
255 38
			if ( false === $show_in_rest ) {
256
				continue;
257
			}
258
259 38
			if ( $this->can_read( $show_in_rest ) ) {
260 38
				$this->read_fields[] = $field['id'];
261
			}
262
263 38
			if ( $this->can_edit( $show_in_rest ) ) {
264 38
				$this->edit_fields[] = $field['id'];
265
			}
266
		}
267 38
	}
268
269
	/**
270
	 * Determines if a field is readable based on it's show_in_rest value
271
	 * and the box's show_in_rest value.
272
	 *
273
	 * @since  2.2.3
274
	 *
275
	 * @param  bool $show_in_rest Field's show_in_rest value. Default null.
276
	 *
277
	 * @return bool               Whether field is readable.
278
	 */
279 38
	protected function can_read( $show_in_rest ) {
280
		// if 'null', then use default box value.
281 38
		if ( null === $show_in_rest ) {
0 ignored issues
show
introduced by
The condition null === $show_in_rest is always false.
Loading history...
282 38
			return $this->rest_read;
283
		}
284
285
		// Else check if the value represents readable.
286 4
		return self::is_readable( $show_in_rest );
287
	}
288
289
	/**
290
	 * Determines if a field is editable based on it's show_in_rest value
291
	 * and the box's show_in_rest value.
292
	 *
293
	 * @since  2.2.3
294
	 *
295
	 * @param  bool $show_in_rest Field's show_in_rest value. Default null.
296
	 *
297
	 * @return bool               Whether field is editable.
298
	 */
299 38
	protected function can_edit( $show_in_rest ) {
300
		// if 'null', then use default box value.
301 38
		if ( null === $show_in_rest ) {
0 ignored issues
show
introduced by
The condition null === $show_in_rest is always false.
Loading history...
302 38
			return $this->rest_edit;
303
		}
304
305
		// Else check if the value represents editable.
306 4
		return self::is_editable( $show_in_rest );
307
	}
308
309
	/**
310
	 * Handler for getting post custom field data.
311
	 *
312
	 * @since  2.2.3
313
	 *
314
	 * @param  array           $object      The object data from the response
315
	 * @param  string          $field_name  Name of field
316
	 * @param  WP_REST_Request $request     Current request
0 ignored issues
show
Bug introduced by
The type WP_REST_Request was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
317
	 * @param  string          $object_type The request object type
318
	 *
319
	 * @return mixed
320
	 */
321 4
	public static function get_post_rest_values( $object, $field_name, $request, $object_type ) {
322 4
		if ( 'cmb2' === $field_name ) {
323 4
			return self::get_rest_values( $object, $request, $object_type, 'post' );
324
		}
325
	}
326
327
	/**
328
	 * Handler for getting user custom field data.
329
	 *
330
	 * @since  2.2.3
331
	 *
332
	 * @param  array           $object      The object data from the response
333
	 * @param  string          $field_name  Name of field
334
	 * @param  WP_REST_Request $request     Current request
335
	 * @param  string          $object_type The request object type
336
	 *
337
	 * @return mixed
338
	 */
339 2
	public static function get_user_rest_values( $object, $field_name, $request, $object_type ) {
340 2
		if ( 'cmb2' === $field_name ) {
341 2
			return self::get_rest_values( $object, $request, $object_type, 'user' );
342
		}
343
	}
344
345
	/**
346
	 * Handler for getting comment custom field data.
347
	 *
348
	 * @since  2.2.3
349
	 *
350
	 * @param  array           $object      The object data from the response
351
	 * @param  string          $field_name  Name of field
352
	 * @param  WP_REST_Request $request     Current request
353
	 * @param  string          $object_type The request object type
354
	 *
355
	 * @return mixed
356
	 */
357 2
	public static function get_comment_rest_values( $object, $field_name, $request, $object_type ) {
358 2
		if ( 'cmb2' === $field_name ) {
359 2
			return self::get_rest_values( $object, $request, $object_type, 'comment' );
360
		}
361
	}
362
363
	/**
364
	 * Handler for getting term custom field data.
365
	 *
366
	 * @since  2.2.3
367
	 *
368
	 * @param  array           $object      The object data from the response
369
	 * @param  string          $field_name  Name of field
370
	 * @param  WP_REST_Request $request     Current request
371
	 * @param  string          $object_type The request object type
372
	 *
373
	 * @return mixed
374
	 */
375 2
	public static function get_term_rest_values( $object, $field_name, $request, $object_type ) {
376 2
		if ( 'cmb2' === $field_name ) {
377 2
			return self::get_rest_values( $object, $request, $object_type, 'term' );
378
		}
379
	}
380
381
	/**
382
	 * Handler for getting custom field data.
383
	 *
384
	 * @since  2.2.3
385
	 *
386
	 * @param  array           $object           The object data from the response
387
	 * @param  WP_REST_Request $request          Current request
388
	 * @param  string          $object_type      The request object type
389
	 * @param  string          $main_object_type The cmb main object type
390
	 *
391
	 * @return mixed
392
	 */
393 10
	protected static function get_rest_values( $object, $request, $object_type, $main_object_type = 'post' ) {
394 10
		if ( ! isset( $object['id'] ) ) {
395
			return;
396
		}
397
398 10
		$values = array();
399
400 10
		if ( ! empty( self::$type_boxes[ $main_object_type ] ) ) {
401 10
			foreach ( self::$type_boxes[ $main_object_type ] as $cmb_id ) {
402 10
				$rest_box = self::$boxes[ $cmb_id ];
403
404 10
				foreach ( $rest_box->read_fields as $field_id ) {
405 10
					$rest_box->cmb->object_id( $object['id'] );
406 10
					$rest_box->cmb->object_type( $main_object_type );
407
408 10
					$field = $rest_box->cmb->get_field( $field_id );
409
410 10
					$field->object_id( $object['id'] );
411 10
					$field->object_type( $main_object_type );
412
413 10
					$values[ $cmb_id ][ $field->id( true ) ] = $field->get_data();
414
				}
415
			}
416
		}
417
418 10
		return $values;
419
	}
420
421
	/**
422
	 * Handler for updating post custom field data.
423
	 *
424
	 * @since  2.2.3
425
	 *
426
	 * @param  mixed           $values      The value of the field
427
	 * @param  object          $object      The object from the response
428
	 * @param  string          $field_name  Name of field
429
	 * @param  WP_REST_Request $request     Current request
430
	 * @param  string          $object_type The request object type
431
	 *
432
	 * @return bool|int
433
	 */
434 2
	public static function update_post_rest_values( $values, $object, $field_name, $request, $object_type ) {
435 2
		if ( 'cmb2' === $field_name ) {
436 2
			return self::update_rest_values( $values, $object, $request, $object_type, 'post' );
437
		}
438
	}
439
440
	/**
441
	 * Handler for updating user custom field data.
442
	 *
443
	 * @since  2.2.3
444
	 *
445
	 * @param  mixed           $values      The value of the field
446
	 * @param  object          $object      The object from the response
447
	 * @param  string          $field_name  Name of field
448
	 * @param  WP_REST_Request $request     Current request
449
	 * @param  string          $object_type The request object type
450
	 *
451
	 * @return bool|int
452
	 */
453 1
	public static function update_user_rest_values( $values, $object, $field_name, $request, $object_type ) {
454 1
		if ( 'cmb2' === $field_name ) {
455 1
			return self::update_rest_values( $values, $object, $request, $object_type, 'user' );
456
		}
457
	}
458
459
	/**
460
	 * Handler for updating comment custom field data.
461
	 *
462
	 * @since  2.2.3
463
	 *
464
	 * @param  mixed           $values      The value of the field
465
	 * @param  object          $object      The object from the response
466
	 * @param  string          $field_name  Name of field
467
	 * @param  WP_REST_Request $request     Current request
468
	 * @param  string          $object_type The request object type
469
	 *
470
	 * @return bool|int
471
	 */
472 1
	public static function update_comment_rest_values( $values, $object, $field_name, $request, $object_type ) {
473 1
		if ( 'cmb2' === $field_name ) {
474 1
			return self::update_rest_values( $values, $object, $request, $object_type, 'comment' );
475
		}
476
	}
477
478
	/**
479
	 * Handler for updating term custom field data.
480
	 *
481
	 * @since  2.2.3
482
	 *
483
	 * @param  mixed           $values      The value of the field
484
	 * @param  object          $object      The object from the response
485
	 * @param  string          $field_name  Name of field
486
	 * @param  WP_REST_Request $request     Current request
487
	 * @param  string          $object_type The request object type
488
	 *
489
	 * @return bool|int
490
	 */
491 1
	public static function update_term_rest_values( $values, $object, $field_name, $request, $object_type ) {
492 1
		if ( 'cmb2' === $field_name ) {
493 1
			return self::update_rest_values( $values, $object, $request, $object_type, 'term' );
494
		}
495
	}
496
497
	/**
498
	 * Handler for updating custom field data.
499
	 *
500
	 * @since  2.2.3
501
	 *
502
	 * @param  mixed           $values           The value of the field
503
	 * @param  object          $object           The object from the response
504
	 * @param  WP_REST_Request $request          Current request
505
	 * @param  string          $object_type      The request object type
506
	 * @param  string          $main_object_type The cmb main object type
507
	 *
508
	 * @return bool|int
509
	 */
510 5
	protected static function update_rest_values( $values, $object, $request, $object_type, $main_object_type = 'post' ) {
511 5
		if ( empty( $values ) || ! is_array( $values ) ) {
512
			return;
513
		}
514
515 5
		$object_id = self::get_object_id( $object, $main_object_type );
516
517 5
		if ( ! $object_id ) {
518
			return;
519
		}
520
521 5
		$updated = array();
522
523 5
		if ( ! empty( self::$type_boxes[ $main_object_type ] ) ) {
524 5
			foreach ( self::$type_boxes[ $main_object_type ] as $cmb_id ) {
525 5
				$rest_box = self::$boxes[ $cmb_id ];
526
527 5
				if ( ! array_key_exists( $cmb_id, $values ) ) {
528
					continue;
529
				}
530
531 5
				$rest_box->cmb->object_id( $object_id );
532 5
				$rest_box->cmb->object_type( $main_object_type );
533
534 5
				$updated[ $cmb_id ] = $rest_box->sanitize_box_values( $values );
535
			}
536
		}
537
538 5
		return $updated;
539
	}
540
541
	/**
542
	 * Loop through box fields and sanitize the values.
543
	 *
544
	 * @since  2.2.o
545
	 *
546
	 * @param  array $values Array of values being provided.
547
	 * @return array           Array of updated/sanitized values.
548
	 */
549 5
	public function sanitize_box_values( array $values ) {
550 5
		$updated = array();
551
552 5
		$this->cmb->pre_process();
553
554 5
		foreach ( $this->edit_fields as $field_id ) {
555 5
			$updated[ $field_id ] = $this->sanitize_field_value( $values, $field_id );
0 ignored issues
show
Bug introduced by
$field_id of type CMB2_Field is incompatible with the type string expected by parameter $field_id of CMB2_REST::sanitize_field_value(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

555
			$updated[ $field_id ] = $this->sanitize_field_value( $values, /** @scrutinizer ignore-type */ $field_id );
Loading history...
556
		}
557
558 5
		$this->cmb->after_save();
559
560 5
		return $updated;
561
	}
562
563
	/**
564
	 * Handles returning a sanitized field value.
565
	 *
566
	 * @since  2.2.3
567
	 *
568
	 * @param  array  $values   Array of values being provided.
569
	 * @param  string $field_id The id of the field to update.
570
	 *
571
	 * @return mixed             The results of saving/sanitizing a field value.
572
	 */
573 5
	protected function sanitize_field_value( array $values, $field_id ) {
574 5
		if ( ! array_key_exists( $field_id, $values[ $this->cmb->cmb_id ] ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The property $cmb_id is declared protected in CMB2_Base. Since you implement __get, consider adding a @property or @property-read.
Loading history...
575 4
			return;
576
		}
577
578 5
		$field = $this->cmb->get_field( $field_id );
579
580 5
		if ( 'title' == $field->type() ) {
581
			return;
582
		}
583
584 5
		$field->object_id( $this->cmb->object_id() );
0 ignored issues
show
Bug introduced by
It seems like $this->cmb->object_id() can also be of type string; however, parameter $object_id of CMB2_Base::object_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

584
		$field->object_id( /** @scrutinizer ignore-type */ $this->cmb->object_id() );
Loading history...
585 5
		$field->object_type( $this->cmb->object_type() );
586
587 5
		if ( 'group' == $field->type() ) {
588
			return $this->sanitize_group_value( $values, $field );
0 ignored issues
show
Bug introduced by
It seems like $field can also be of type false; however, parameter $field of CMB2_REST::sanitize_group_value() does only seem to accept CMB2_Field, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

588
			return $this->sanitize_group_value( $values, /** @scrutinizer ignore-type */ $field );
Loading history...
589
		}
590
591 5
		return $field->save_field( $values[ $this->cmb->cmb_id ][ $field_id ] );
592
	}
593
594
	/**
595
	 * Handles returning a sanitized group field value.
596
	 *
597
	 * @since  2.2.3
598
	 *
599
	 * @param  array      $values Array of values being provided.
600
	 * @param  CMB2_Field $field  CMB2_Field object.
601
	 *
602
	 * @return mixed               The results of saving/sanitizing the group field value.
603
	 */
604
	protected function sanitize_group_value( array $values, CMB2_Field $field ) {
605
		$fields = $field->fields();
606
		if ( empty( $fields ) ) {
607
			return;
608
		}
609
610
		$this->cmb->data_to_save[ $field->_id() ] = $values[ $this->cmb->cmb_id ][ $field->_id() ];
0 ignored issues
show
Bug Best Practice introduced by
The property $cmb_id is declared protected in CMB2_Base. Since you implement __get, consider adding a @property or @property-read.
Loading history...
611
612
		return $this->cmb->save_group_field( $field );
613
	}
614
615
	/**
616
	 * Filter whether a meta key is protected.
617
	 *
618
	 * @since 2.2.3
619
	 *
620
	 * @param bool   $protected Whether the key is protected. Default false.
621
	 * @param string $meta_key  Meta key.
622
	 * @param string $meta_type Meta type.
623
	 */
624
	public function is_protected_meta( $protected, $meta_key, $meta_type ) {
625
		if ( $this->field_can_edit( $meta_key ) ) {
626
			return false;
627
		}
628
629
		return $protected;
630
	}
631
632 6
	protected static function get_object_id( $object, $object_type = 'post' ) {
633
		switch ( $object_type ) {
634 6
			case 'user':
635 5
			case 'post':
636 4
				if ( isset( $object->ID ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
637 4
					return intval( $object->ID );
638
				}
639 3
			case 'comment':
640 2
				if ( isset( $object->comment_ID ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
641 2
					return intval( $object->comment_ID );
642
				}
643 2
			case 'term':
644 2
				if ( is_array( $object ) && isset( $object['term_id'] ) ) {
645 1
					return intval( $object['term_id'] );
646 2
				} elseif ( isset( $object->term_id ) ) {
647 2
					return intval( $object->term_id );
648
				}
649
		}
650
651 1
		return 0;
652
	}
653
654
	/**
655
	 * Checks if a given field can be read.
656
	 *
657
	 * @since  2.2.3
658
	 *
659
	 * @param  string|CMB2_Field $field_id      Field ID or CMB2_Field object.
660
	 * @param  boolean           $return_object Whether to return the Field object.
661
	 *
662
	 * @return mixed                            False if field can't be read or true|CMB2_Field object.
663
	 */
664 8
	public function field_can_read( $field_id, $return_object = false ) {
665 8
		return $this->field_can( 'read_fields', $field_id, $return_object );
666
	}
667
668
	/**
669
	 * Checks if a given field can be edited.
670
	 *
671
	 * @since  2.2.3
672
	 *
673
	 * @param  string|CMB2_Field $field_id      Field ID or CMB2_Field object.
674
	 * @param  boolean           $return_object Whether to return the Field object.
675
	 *
676
	 * @return mixed                            False if field can't be edited or true|CMB2_Field object.
677
	 */
678 8
	public function field_can_edit( $field_id, $return_object = false ) {
679 8
		return $this->field_can( 'edit_fields', $field_id, $return_object );
680
	}
681
682
	/**
683
	 * Checks if a given field can be read or edited.
684
	 *
685
	 * @since  2.2.3
686
	 *
687
	 * @param  string            $type          Whether we are checking for read or edit fields.
688
	 * @param  string|CMB2_Field $field_id      Field ID or CMB2_Field object.
689
	 * @param  boolean           $return_object Whether to return the Field object.
690
	 *
691
	 * @return mixed                            False if field can't be read or edited or true|CMB2_Field object.
692
	 */
693 12
	protected function field_can( $type = 'read_fields', $field_id, $return_object = false ) {
694 12
		if ( ! in_array( $field_id instanceof CMB2_Field ? $field_id->id() : $field_id, $this->{$type}, true ) ) {
695 2
			return false;
696
		}
697
698 11
		return $return_object ? $this->cmb->get_field( $field_id ) : true;
699
	}
700
701
	/**
702
	 * Get a CMB2_REST instance object from the registry by a CMB2 id.
703
	 *
704
	 * @since  2.2.3
705
	 *
706
	 * @param  string $cmb_id CMB2 config id
707
	 *
708
	 * @return CMB2_REST|false The CMB2_REST object or false.
709
	 */
710 13
	public static function get_rest_box( $cmb_id ) {
711 13
		return isset( self::$boxes[ $cmb_id ] ) ? self::$boxes[ $cmb_id ] : false;
712
	}
713
714
	/**
715
	 * Remove a CMB2_REST instance object from the registry.
716
	 *
717
	 * @since  2.2.3
718
	 *
719
	 * @param string $cmb_id A CMB2 instance id.
720
	 */
721
	public static function remove( $cmb_id ) {
722
		if ( array_key_exists( $cmb_id, self::$boxes ) ) {
723
			unset( self::$boxes[ $cmb_id ] );
724
		}
725
	}
726
727
	/**
728
	 * Retrieve all CMB2_REST instances from the registry.
729
	 *
730
	 * @since  2.2.3
731
	 * @return CMB2[] Array of all registered CMB2_REST instances.
732
	 */
733 38
	public static function get_all() {
734 38
		return self::$boxes;
735
	}
736
737
	/**
738
	 * Checks if given value is readable.
739
	 *
740
	 * Value is considered readable if it is not empty and if it does not match the editable blacklist.
741
	 *
742
	 * @since  2.2.3
743
	 *
744
	 * @param  mixed $value Value to check.
745
	 *
746
	 * @return boolean       Whether value is considered readable.
747
	 */
748 38
	public static function is_readable( $value ) {
749 38
		return ! empty( $value ) && ! in_array( $value, array(
750 38
			WP_REST_Server::CREATABLE,
0 ignored issues
show
Bug introduced by
The type WP_REST_Server was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
751
			WP_REST_Server::EDITABLE,
752
			WP_REST_Server::DELETABLE,
753 38
		), true );
754
	}
755
756
	/**
757
	 * Checks if given value is editable.
758
	 *
759
	 * Value is considered editable if matches the editable whitelist.
760
	 *
761
	 * @since  2.2.3
762
	 *
763
	 * @param  mixed $value Value to check.
764
	 *
765
	 * @return boolean       Whether value is considered editable.
766
	 */
767 38
	public static function is_editable( $value ) {
768 38
		return in_array( $value, array(
769 38
			WP_REST_Server::EDITABLE,
770
			WP_REST_Server::ALLMETHODS,
771 38
		), true );
772
	}
773
774
	/**
775
	 * Magic getter for our object.
776
	 *
777
	 * @param string $field
778
	 * @throws Exception Throws an exception if the field is invalid.
779
	 *
780
	 * @return mixed
781
	 */
782 17
	public function __get( $field ) {
783
		switch ( $field ) {
784 17
			case 'read_fields':
785 17
			case 'edit_fields':
786 16
			case 'rest_read':
787 3
			case 'rest_edit':
788 17
				return $this->{$field};
789
			default:
790
				throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
791
		}
792
	}
793
794
}
795