Completed
Pull Request — trunk (#541)
by Justin
07:09
created

CMB2_REST::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 9
ccs 0
cts 7
cp 0
crap 2
rs 9.6666
c 0
b 0
f 0
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.4
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_REST 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
	 * The current CMB2 REST endpoint version
18
	 * @var string
19
	 * @since 2.2.4
20
	 */
21
	const VERSION = '1';
22
23
	/**
24
	 * The CMB2 REST base namespace (v should always be followed by $version)
25
	 * @var string
26
	 * @since 2.2.4
27
	 */
28
	const NAME_SPACE = 'cmb2/v1';
29
30
	/**
31
	 * @var   CMB2 object
32
	 * @since 2.2.4
33
	 */
34
	public $cmb;
35
36
	/**
37
	 * @var   CMB2_REST[] objects
38
	 * @since 2.2.4
39
	 */
40
	public static $boxes;
41
42
	/**
43
	 * Array of readable field objects.
44
	 * @var   CMB2_Field[]
45
	 * @since 2.2.4
46
	 */
47
	protected $read_fields = array();
48
49
	/**
50
	 * Array of editable field objects.
51
	 * @var   CMB2_Field[]
52
	 * @since 2.2.4
53
	 */
54
	protected $edit_fields = array();
55
56
	/**
57
	 * whether CMB2 object is readable via the rest api.
58
	 * @var boolean
59
	 */
60
	protected $rest_read = false;
61
62
	/**
63
	 * whether CMB2 object is editable via the rest api.
64
	 * @var boolean
65
	 */
66
	protected $rest_edit = false;
67
68
	/**
69
	 * Constructor
70
	 *
71
	 * @since 2.2.4
72
	 *
73
	 * @param CMB2 $cmb The CMB2 object to be registered for the API.
74
	 */
75
	public function __construct( CMB2 $cmb ) {
76
		$this->cmb = $cmb;
77
		self::$boxes[ $cmb->cmb_id ] = $this;
78
79
		$show_value = $this->cmb->prop( 'show_in_rest' );
80
81
		$this->rest_read = self::is_readable( $show_value );
82
		$this->rest_edit = self::is_editable( $show_value );
83
	}
84
85
	/**
86
	 * Hooks to register on frontend and backend.
87
	 *
88
	 * @since  2.2.4
89
	 *
90
	 * @return void
91
	 */
92
	public function universal_hooks() {
93
		// hook up the CMB rest endpoint classes
94
		$this->once( 'rest_api_init', array( $this, 'init_routes' ), 0 );
95
96
		if ( function_exists( 'register_rest_field' ) ) {
97
			$this->once( 'rest_api_init', array( __CLASS__, 'register_cmb2_fields' ), 50 );
98
		}
99
100
		$this->declare_read_edit_fields();
101
102
		add_filter( 'is_protected_meta', array( $this, 'is_protected_meta' ), 10, 3 );
103
	}
104
105
	/**
106
	 * Initiate the CMB2 Boxes and Fields routes
107
	 *
108
	 * @since  2.2.4
109
	 *
110
	 * @return void
111
	 */
112
	public function init_routes() {
113
		$wp_rest_server = rest_get_server();
114
115
		$boxes_controller = new CMB2_REST_Controller_Boxes( $wp_rest_server );
116
		$boxes_controller->register_routes();
117
118
		$fields_controller = new CMB2_REST_Controller_Fields( $wp_rest_server );
119
		$fields_controller->register_routes();
120
	}
121
122
	/**
123
	 * Loop through REST boxes and call register_rest_field for each object type.
124
	 *
125
	 * @since  2.2.4
126
	 *
127
	 * @return void
128
	 */
129
	public static function register_cmb2_fields() {
130
		$alltypes = $taxonomies = array();
131
		$has_user = $has_comment = $has_taxonomies = false;
132
133
		foreach ( self::$boxes as $cmb_id => $rest_box ) {
134
			$types = array_flip( $rest_box->cmb->box_types() );
135
136
			if ( isset( $types['user'] ) ) {
137
				unset( $types['user'] );
138
				$has_user = true;
139
			}
140
141
			if ( isset( $types['comment'] ) ) {
142
				unset( $types['comment'] );
143
				$has_comment = true;
144
			}
145
146
			if ( isset( $types['term'] ) ) {
147
				unset( $types['term'] );
148
149
				$taxonomies = array_merge(
150
					$taxonomies,
151
					CMB2_Utils::ensure_array( $rest_box->cmb->prop( 'taxonomies' ) )
152
				);
153
154
				$has_taxonomies = true;
155
			}
156
157
			if ( ! empty( $types ) ) {
158
				$alltypes = array_merge( $alltypes, array_flip( $types ) );
159
			}
160
		}
161
162
		$alltypes = array_unique( $alltypes );
163
164
		if ( ! empty( $alltypes ) ) {
165
			self::register_rest_field( $alltypes, 'post' );
166
		}
167
168
		if ( $has_user ) {
169
			self::register_rest_field( 'user', 'user' );
170
		}
171
172
		if ( $has_comment ) {
173
			self::register_rest_field( 'comment', 'comment' );
174
		}
175
176
		if ( $has_taxonomies ) {
177
			self::register_rest_field( $taxonomies, 'term' );
178
		}
179
	}
180
181
	/**
182
	 * Wrapper for register_rest_field.
183
	 *
184
	 * @since  2.2.4
185
	 *
186
	 * @param string|array $object_types Object(s) the field is being registered
187
	 *                                   to, "post"|"term"|"comment" etc.
188
	 * @param string $object_types       Canonical object type for callbacks.
189
	 *
190
	 * @return void
191
	 */
192
	protected static function register_rest_field( $object_types, $object_type ) {
193
		register_rest_field( $object_types, 'cmb2', array(
194
			'get_callback'    => array( __CLASS__, "get_{$object_type}_rest_values" ),
195
			'update_callback' => array( __CLASS__, "update_{$object_type}_rest_values" ),
196
			'schema'          => null, // @todo add schema
197
		) );
198
	}
199
200
	/**
201
	 * Setup readable and editable fields.
202
	 *
203
	 * @since  2.2.4
204
	 *
205
	 * @return void
206
	 */
207
	protected function declare_read_edit_fields() {
208
		foreach ( $this->cmb->prop( 'fields' ) as $field ) {
209
			$show_in_rest = isset( $field['show_in_rest'] ) ? $field['show_in_rest'] : null;
210
211
			if ( false === $show_in_rest ) {
212
				continue;
213
			}
214
215
			if ( $this->can_read( $show_in_rest ) ) {
216
				$this->read_fields[] = $field['id'];
217
			}
218
219
			if ( $this->can_edit( $show_in_rest ) ) {
220
				$this->edit_fields[] = $field['id'];
221
			}
222
223
		}
224
	}
225
226
	/**
227
	 * Determines if a field is readable based on it's show_in_rest value
228
	 * and the box's show_in_rest value.
229
	 *
230
	 * @since  2.2.4
231
	 *
232
	 * @param  bool $show_in_rest Field's show_in_rest value. Default null.
233
	 *
234
	 * @return bool               Whether field is readable.
235
	 */
236
	protected function can_read( $show_in_rest ) {
237
		// if 'null', then use default box value.
238
		if ( null === $show_in_rest ) {
239
			return $this->rest_read;
240
		}
241
242
		// Else check if the value represents readable.
243
		return self::is_readable( $show_in_rest );
244
	}
245
246
	/**
247
	 * Determines if a field is editable based on it's show_in_rest value
248
	 * and the box's show_in_rest value.
249
	 *
250
	 * @since  2.2.4
251
	 *
252
	 * @param  bool $show_in_rest Field's show_in_rest value. Default null.
253
	 *
254
	 * @return bool               Whether field is editable.
255
	 */
256
	protected function can_edit( $show_in_rest ) {
257
		// if 'null', then use default box value.
258
		if ( null === $show_in_rest ) {
259
			return $this->rest_edit;
260
		}
261
262
		// Else check if the value represents editable.
263
		return self::is_editable( $show_in_rest );
264
	}
265
266
	/**
267
	 * Handler for getting post custom field data.
268
	 *
269
	 * @since  2.2.4
270
	 *
271
	 * @param  array           $object      The object data from the response
272
	 * @param  string          $field_name  Name of field
273
	 * @param  WP_REST_Request $request     Current request
274
	 * @param  string          $object_type The request object type
275
	 *
276
	 * @return mixed
277
	 */
278
	public static function get_post_rest_values( $object, $field_name, $request, $object_type ) {
279
		if ( 'cmb2' === $field_name ) {
280
			return self::get_rest_values( $object, $request, $object_type, 'post' );
281
		}
282
	}
283
284
	/**
285
	 * Handler for getting user custom field data.
286
	 *
287
	 * @since  2.2.4
288
	 *
289
	 * @param  array           $object      The object data from the response
290
	 * @param  string          $field_name  Name of field
291
	 * @param  WP_REST_Request $request     Current request
292
	 * @param  string          $object_type The request object type
293
	 *
294
	 * @return mixed
295
	 */
296
	public static function get_user_rest_values( $object, $field_name, $request, $object_type ) {
297
		if ( 'cmb2' === $field_name ) {
298
			return self::get_rest_values( $object, $request, $object_type, 'user' );
299
		}
300
	}
301
302
	/**
303
	 * Handler for getting comment custom field data.
304
	 *
305
	 * @since  2.2.4
306
	 *
307
	 * @param  array           $object      The object data from the response
308
	 * @param  string          $field_name  Name of field
309
	 * @param  WP_REST_Request $request     Current request
310
	 * @param  string          $object_type The request object type
311
	 *
312
	 * @return mixed
313
	 */
314
	public static function get_comment_rest_values( $object, $field_name, $request, $object_type ) {
315
		if ( 'cmb2' === $field_name ) {
316
			return self::get_rest_values( $object, $request, $object_type, 'comment' );
317
		}
318
	}
319
320
	/**
321
	 * Handler for getting term custom field data.
322
	 *
323
	 * @since  2.2.4
324
	 *
325
	 * @param  array           $object      The object data from the response
326
	 * @param  string          $field_name  Name of field
327
	 * @param  WP_REST_Request $request     Current request
328
	 * @param  string          $object_type The request object type
329
	 *
330
	 * @return mixed
331
	 */
332
	public static function get_term_rest_values( $object, $field_name, $request, $object_type ) {
333
		if ( 'cmb2' === $field_name ) {
334
			return self::get_rest_values( $object, $request, $object_type, 'term' );
335
		}
336
	}
337
338
	/**
339
	 * Handler for getting custom field data.
340
	 *
341
	 * @since  2.2.4
342
	 *
343
	 * @param  array           $object           The object data from the response
344
	 * @param  WP_REST_Request $request          Current request
345
	 * @param  string          $object_type      The request object type
346
	 * @param  string          $main_object_type The cmb main object type
347
	 *
348
	 * @return mixed
349
	 */
350
	protected static function get_rest_values( $object, $request, $object_type, $main_object_type = 'post' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
351
		if ( ! isset( $object['id'] ) ) {
352
			return;
353
		}
354
355
		$values = array();
356
357
		foreach ( self::$boxes as $cmb_id => $rest_box ) {
358
			$check = 'term' === $main_object_type ? 'term' : $object_type;
359
360
			// This is not the box you're looking for...
361
			if ( ! in_array( $check, $rest_box->cmb->box_types() ) ) {
362
				continue;
363
			}
364
365
			foreach ( $rest_box->read_fields as $field_id ) {
366
				$rest_box->cmb->object_id( $object['id'] );
367
				$rest_box->cmb->object_type( $main_object_type );
368
369
				$field = $rest_box->cmb->get_field( $field_id );
370
371
				$field->object_id( $object['id'] );
372
				$field->object_type( $main_object_type );
373
374
				$values[ $cmb_id ][ $field->id( true ) ] = $field->get_data();
375
			}
376
		}
377
378
		return $values;
379
	}
380
381
	/**
382
	 * Handler for updating post custom field data.
383
	 *
384
	 * @since  2.2.4
385
	 *
386
	 * @param  mixed           $value       The value of the field
0 ignored issues
show
Documentation introduced by
There is no parameter named $value. Did you maybe mean $values?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
387
	 * @param  object          $object      The object from the response
388
	 * @param  string          $field_name  Name of field
389
	 * @param  WP_REST_Request $request     Current request
390
	 * @param  string          $object_type The request object type
391
	 *
392
	 * @return bool|int
393
	 */
394
	public static function update_post_rest_values( $values, $object, $field_name, $request, $object_type ) {
395
		if ( 'cmb2' === $field_name ) {
396
			return self::update_rest_values( $values, $object, $request, $object_type, 'post' );
397
		}
398
	}
399
400
	/**
401
	 * Handler for updating user custom field data.
402
	 *
403
	 * @since  2.2.4
404
	 *
405
	 * @param  mixed           $value       The value of the field
0 ignored issues
show
Documentation introduced by
There is no parameter named $value. Did you maybe mean $values?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
406
	 * @param  object          $object      The object from the response
407
	 * @param  string          $field_name  Name of field
408
	 * @param  WP_REST_Request $request     Current request
409
	 * @param  string          $object_type The request object type
410
	 *
411
	 * @return bool|int
412
	 */
413
	public static function update_user_rest_values( $values, $object, $field_name, $request, $object_type ) {
414
		if ( 'cmb2' === $field_name ) {
415
			return self::update_rest_values( $values, $object, $request, $object_type, 'user' );
416
		}
417
	}
418
419
	/**
420
	 * Handler for updating comment custom field data.
421
	 *
422
	 * @since  2.2.4
423
	 *
424
	 * @param  mixed           $value       The value of the field
0 ignored issues
show
Documentation introduced by
There is no parameter named $value. Did you maybe mean $values?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
425
	 * @param  object          $object      The object from the response
426
	 * @param  string          $field_name  Name of field
427
	 * @param  WP_REST_Request $request     Current request
428
	 * @param  string          $object_type The request object type
429
	 *
430
	 * @return bool|int
431
	 */
432
	public static function update_comment_rest_values( $values, $object, $field_name, $request, $object_type ) {
433
		if ( 'cmb2' === $field_name ) {
434
			return self::update_rest_values( $values, $object, $request, $object_type, 'comment' );
435
		}
436
	}
437
438
	/**
439
	 * Handler for updating term custom field data.
440
	 *
441
	 * @since  2.2.4
442
	 *
443
	 * @param  mixed           $value       The value of the field
0 ignored issues
show
Documentation introduced by
There is no parameter named $value. Did you maybe mean $values?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
444
	 * @param  object          $object      The object from the response
445
	 * @param  string          $field_name  Name of field
446
	 * @param  WP_REST_Request $request     Current request
447
	 * @param  string          $object_type The request object type
448
	 *
449
	 * @return bool|int
450
	 */
451
	public static function update_term_rest_values( $values, $object, $field_name, $request, $object_type ) {
452
		if ( 'cmb2' === $field_name ) {
453
			return self::update_rest_values( $values, $object, $request, $object_type, 'term' );
454
		}
455
	}
456
457
	/**
458
	 * Handler for updating custom field data.
459
	 *
460
	 * @since  2.2.4
461
	 *
462
	 * @param  mixed           $value            The value of the field
0 ignored issues
show
Documentation introduced by
There is no parameter named $value. Did you maybe mean $values?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
463
	 * @param  object          $object           The object from the response
464
	 * @param  WP_REST_Request $request          Current request
465
	 * @param  string          $object_type      The request object type
466
	 * @param  string          $main_object_type The cmb main object type
467
	 *
468
	 * @return bool|int
469
	 */
470
	protected static function update_rest_values( $values, $object, $request, $object_type, $main_object_type = 'post' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $object_type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $main_object_type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
471
		if ( empty( $values ) || ! is_array( $values ) ) {
472
			return;
473
		}
474
475
		// @todo verify that $object_type matches this output.
476
		$data = self::get_object_data( $object );
477
		if ( ! $data ) {
478
			return;
479
		}
480
481
		$updated = array();
482
483
		// @todo Security hardening... check for object type, check for show_in_rest values.
484
		foreach ( self::$boxes as $cmb_id => $rest_box ) {
485
			if ( ! array_key_exists( $cmb_id, $values ) ) {
486
				continue;
487
			}
488
489
			$rest_box->cmb->object_id( $data['object_id'] );
490
			$rest_box->cmb->object_type( $data['object_type'] );
491
492
			// TODO: Test since refactor.
493
			$updated[ $cmb_id ] = $rest_box->sanitize_box_values( $values );
494
		}
495
496
		return $updated;
497
	}
498
499
	/**
500
	 * Loop through box fields and sanitize the values.
501
	 *
502
	 * @since  2.2.o
503
	 *
504
	 * @param  array   $values Array of values being provided.
505
	 * @return array           Array of updated/sanitized values.
506
	 */
507
	public function sanitize_box_values( array $values ) {
508
		$updated = array();
509
510
		$this->cmb->pre_process();
511
512
		foreach ( $this->edit_fields as $field_id ) {
513
			$updated[ $field_id ] = $this->sanitize_field_value( $values, $field_id );
0 ignored issues
show
Documentation introduced by
$field_id is of type object<CMB2_Field>, 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...
514
		}
515
516
		$this->cmb->after_save();
517
518
		return $updated;
519
	}
520
521
	/**
522
	 * Handles returning a sanitized field value.
523
	 *
524
	 * @since  2.2.4
525
	 *
526
	 * @param  array   $values   Array of values being provided.
527
	 * @param  string  $field_id The id of the field to update.
528
	 *
529
	 * @return mixed             The results of saving/sanitizing a field value.
530
	 */
531
	protected function sanitize_field_value( array $values, $field_id ) {
532
		if ( ! array_key_exists( $field_id, $values[ $this->cmb->cmb_id ] ) ) {
533
			return;
534
		}
535
536
		$field = $this->cmb->get_field( $field_id );
537
538
		if ( 'title' == $field->type() ) {
539
			return;
540
		}
541
542
		$field->object_id( $this->cmb->object_id() );
543
		$field->object_type( $this->cmb->object_type() );
544
545
		if ( 'group' == $field->type() ) {
546
			return $this->sanitize_group_value( $values, $field );
0 ignored issues
show
Security Bug introduced by
It seems like $field defined by $this->cmb->get_field($field_id) on line 536 can also be of type false; however, CMB2_REST::sanitize_group_value() does only seem to accept object<CMB2_Field>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
547
		}
548
549
		return $field->save_field( $values[ $this->cmb->cmb_id ][ $field_id ] );
550
	}
551
552
	/**
553
	 * Handles returning a sanitized group field value.
554
	 *
555
	 * @since  2.2.4
556
	 *
557
	 * @param  array       $values Array of values being provided.
558
	 * @param  CMB2_Field  $field  CMB2_Field object.
559
	 *
560
	 * @return mixed               The results of saving/sanitizing the group field value.
561
	 */
562
	protected function sanitize_group_value( array $values, CMB2_Field $field ) {
563
		$fields = $field->fields();
564
		if ( empty( $fields ) ) {
565
			return;
566
		}
567
568
		$this->cmb->data_to_save[ $field->_id() ] = $values[ $this->cmb->cmb_id ][ $field->_id() ];
569
570
		return $this->cmb->save_group_field( $field );
0 ignored issues
show
Documentation introduced by
$field is of type object<CMB2_Field>, but the function expects a array.

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...
571
	}
572
573
	/**
574
	 * Filter whether a meta key is protected.
575
	 *
576
	 * @since 2.2.4
577
	 *
578
	 * @param bool   $protected Whether the key is protected. Default false.
579
	 * @param string $meta_key  Meta key.
580
	 * @param string $meta_type Meta type.
581
	 */
582
	public function is_protected_meta( $protected, $meta_key, $meta_type ) {
0 ignored issues
show
Unused Code introduced by
The parameter $meta_type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
583
		if ( $this->field_can_edit( $meta_key ) ) {
584
			return false;
585
		}
586
587
		return $protected;
588
	}
589
590
	protected static function get_object_data( $object ) {
591
		$object_id = 0;
592
		if ( isset( $object->ID ) ) {
593
			$object_id   = intval( $object->ID );
594
			$object_type = isset( $object->user_login ) ? 'user' : 'post';
595
		} elseif ( isset( $object->comment_ID ) ) {
596
			$object_id   = intval( $object->comment_ID );
597
			$object_type = 'comment';
598
		} elseif ( is_array( $object ) && isset( $object['term_id'] ) ) {
599
			$object_id   = intval( $object['term_id'] );
600
			$object_type = 'term';
601
		} elseif ( isset( $object->term_id ) ) {
602
			$object_id   = intval( $object->term_id );
603
			$object_type = 'term';
604
		}
605
606
		if ( empty( $object_id ) ) {
607
			return false;
608
		}
609
610
		return compact( 'object_id', 'object_type' );
611
	}
612
613
	public function field_can_read( $field_id, $return_object = false ) {
614
		return $this->field_can( 'read_fields', $field_id, $return_object );
615
	}
616
617
	public function field_can_edit( $field_id, $return_object = false ) {
618
		return $this->field_can( 'edit_fields', $field_id, $return_object );
619
	}
620
621
	protected function field_can( $type = 'read_fields', $field_id, $return_object = false ) {
622
		if ( ! in_array( $field_id instanceof CMB2_Field ? $field_id->id() : $field_id, $this->{$type}, true ) ) {
623
			return false;
624
		}
625
626
		return $return_object ? $this->cmb->get_field( $field_id ) : true;
627
	}
628
629
	/**
630
	 * Get a CMB2_REST instance object from the registry by a CMB2 id.
631
	 *
632
	 * @since  2.2.4
633
	 *
634
	 * @param  string  $cmb_id CMB2 config id
635
	 *
636
	 * @return CMB2_REST|false The CMB2_REST object or false.
637
	 */
638
	public static function get_rest_box( $cmb_id ) {
639
		return isset( self::$boxes[ $cmb_id ] ) ? self::$boxes[ $cmb_id ] : false;
640
	}
641
642
	/**
643
	 * Remove a CMB2_REST instance object from the registry.
644
	 *
645
	 * @since  2.2.4
646
	 *
647
	 * @param string $cmb_id A CMB2 instance id.
648
	 */
649
	public static function remove( $cmb_id ) {
650
		if ( array_key_exists( $cmb_id, self::$boxes ) ) {
651
			unset( self::$boxes[ $cmb_id ] );
652
		}
653
	}
654
655
	/**
656
	 * Checks if given value is readable.
657
	 *
658
	 * Value is considered readable if it is not empty and if it does not match the editable blacklist.
659
	 *
660
	 * @since  2.2.4
661
	 *
662
	 * @param  mixed  $value Value to check.
663
	 *
664
	 * @return boolean       Whether value is considered readable.
665
	 */
666
	public static function is_readable( $value ) {
667
		return ! empty( $value ) && ! in_array( $value, array(
668
			WP_REST_Server::CREATABLE,
669
			WP_REST_Server::EDITABLE,
670
			WP_REST_Server::DELETABLE,
671
		), true );
672
	}
673
674
	/**
675
	 * Checks if given value is editable.
676
	 *
677
	 * Value is considered editable if matches the editable whitelist.
678
	 *
679
	 * @since  2.2.4
680
	 *
681
	 * @param  mixed  $value Value to check.
682
	 *
683
	 * @return boolean       Whether value is considered editable.
684
	 */
685
	public static function is_editable( $value ) {
686
		return in_array( $value, array(
687
			WP_REST_Server::EDITABLE,
688
			WP_REST_Server::ALLMETHODS,
689
		), true );
690
	}
691
692
	/**
693
	 * Magic getter for our object.
694
	 *
695
	 * @param string $field
696
	 * @throws Exception Throws an exception if the field is invalid.
697
	 *
698
	 * @return mixed
699
	 */
700
	public function __get( $field ) {
701
		switch ( $field ) {
702
			case 'read_fields':
703
			case 'edit_fields':
704
			case 'rest_read':
705
			case 'rest_edit':
706
				return $this->{$field};
707
			default:
708
				throw new Exception( 'Invalid ' . __CLASS__ . ' property: ' . $field );
709
		}
710
	}
711
712
}
713