Completed
Pull Request — master (#193)
by
unknown
09:54
created

Decorator   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 322
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 322
rs 9
c 0
b 0
f 0
wmc 35
lcom 1
cbo 2

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A register_fields() 0 22 3
A get_containers() 0 5 2
A filter_fields() 0 3 1
A load_post_meta_field_value() 0 4 1
A load_term_meta_field_value() 0 4 1
A load_comment_meta_field_value() 0 4 1
A load_user_meta_field_value() 0 4 1
A load_field_value() 0 16 2
A update_post_meta_field_value() 0 4 1
A update_term_meta_field_value() 0 4 1
A update_comment_meta_field_value() 0 4 1
A update_user_meta_field_value() 0 4 1
B update_field_value() 0 25 5
A get_field_type() 0 4 2
A get_current_field() 0 5 2
A get_post_meta_container_settings() 0 3 1
A get_term_meta_container_settings() 0 3 1
A get_user_meta_container_settings() 0 3 1
A get_comment_meta_container_settings() 0 3 1
B get_object_id() 0 16 5
1
<?php 
2
namespace Carbon_Fields\REST;
3
4
use Carbon_Fields\Container\Container;
5
use Carbon_Fields\Updater\Updater;
6
7
/**
8
 * This class modifies the default REST routes
9
 * using the WordPress' register_rest_field() function 
10
 */
11
12
class Decorator {
13
14
	/**
15
	 * Instance of the Data_Manager class
16
	 * 
17
	 * @var object
18
	 */
19
	public $data_manager;
20
21
	/**
22
	 * All fields that need to be registeres
23
	 *
24
	 * @var array
25
	 */
26
	private $fields = array();
27
28
	function __construct( $data_manager ) {
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...
29
		$this->data_manager = $data_manager;
30
		add_action( 'rest_api_init', array( $this, 'register_fields' ) );
31
	}
32
33
	/**
34
	 * Registers Carbon Fields using
35
	 * the register_rest_field() function
36
	 */
37
	public function register_fields() {
38
		$containers = $this->get_containers();
39
40
		$this->fields = array_map( array( $this, 'filter_fields' ), $containers );
41
		$this->fields = call_user_func_array( 'array_merge', $this->fields );
0 ignored issues
show
Documentation Bug introduced by
It seems like call_user_func_array('ar..._merge', $this->fields) of type * is incompatible with the declared type array of property $fields.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
42
43
		foreach ( $containers as $container ) {
44
			$fields  = $this->filter_fields( $container );
45
			$context = strtolower( $container->type );
46
			$types   = call_user_func( array( __CLASS__, "get_{$context}_container_settings" ), $container );
47
48
			foreach ( $fields as $field ) {
49
				register_rest_field( $types,
50
					$field->get_name(), array(
51
						'get_callback'    => array( $this, "load_{$context}_field_value" ),
52
						'update_callback' => array( $this, "update_{$context}_field_value" ),
53
						'schema'          => null,
54
					)
55
				);
56
			}
57
		}
58
	}
59
60
	/**
61
	 * Return all containers that 
62
	 * should be visible in the REST API responses
63
	 *
64
	 * @return array
65
	 */
66
	public function get_containers() {
67
		return array_filter( Container::$active_containers, function( $container ) {
68
			return $container->type !== 'Theme_Options' && $container->get_rest_visibility(); 
69
		} );
70
	}
71
72
	/**
73
	 * Return all fields attached to a container
74
	 * that should be included in the REST API response
75
	 * 
76
	 * @param object $container
77
	 * @return array
78
	 */
79
	public function filter_fields( $container ) {
80
		return $this->data_manager->filter_fields( $container->get_fields() );
81
	}
82
83
	/**
84
	 * Wrapper method for loading Post Meta values, 
85
	 * needed to pass the correct $context
86
	 * 
87
	 * @param array $object Details of current object.
88
	 * @param string $field_name Name of field.
89
	 * @param WP_REST_Request $request Current request
90
	 * @return mixed
91
	 */
92
	public function load_post_meta_field_value( $object, $field_name, $request ) {
93
		$context = 'Post_Meta';
94
		return $this->load_field_value( $object, $field_name, $request, $context );
95
	}
96
	
97
	/**
98
	 * Wrapper method for loading Term Meta values, 
99
	 * needed to pass the correct $context
100
	 * 
101
	 * @param array $object Details of current object.
102
	 * @param string $field_name Name of field.
103
	 * @param WP_REST_Request $request Current request
104
	 * @return mixed
105
	 */
106
	public function load_term_meta_field_value( $object, $field_name, $request ) {
107
		$context = 'Term_Meta';
108
		return $this->load_field_value( $object, $field_name, $request, $context );
109
	}
110
111
	/**
112
	 * Wrapper method for loading Comment Meta values, 
113
	 * needed to pass the correct $context
114
	 * 
115
	 * @param array $object Details of current object.
116
	 * @param string $field_name Name of field.
117
	 * @param WP_REST_Request $request Current request
118
	 * @return mixed
119
	 */
120
	public function load_comment_meta_field_value( $object, $field_name, $request ) {
121
		$context = 'Comment_Meta';
122
		return $this->load_field_value( $object, $field_name, $request, $context );
123
	}
124
125
	/**
126
	 * Wrapper method for loading User Meta values, 
127
	 * needed to pass the correct $context
128
	 * 
129
	 * @param array $object Details of current object.
130
	 * @param string $field_name Name of field.
131
	 * @param WP_REST_Request $request Current request
132
	 * @return mixed
133
	 */
134
	public function load_user_meta_field_value( $object, $field_name, $request ) {
135
		$context = 'User_Meta';
136
		return $this->load_field_value( $object, $field_name, $request, $context );
137
	}
138
139
	/**
140
	 * Get the value of the "$field_name" field
141
	 *
142
	 * @param array $object Details of current object.
143
 	 * @param string $field_name Name of field.
144
 	 * @param WP_REST_Request $request Current request
145
 	 * @param string $context Post_Meta|Term_Meta|User_Meta|Comment_Meta
146
 	 * @return mixed
147
	 */	
148
	public function load_field_value( $object, $field_name, $request, $context ) {
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...
149
		$field = $this->get_current_field( $field_name, $context );
150
151
		if ( empty( $field ) ) {
152
			return '';
153
		}   
154
155
		$field = array_pop( $field );
156
		
157
		$field->get_datastore()->set_id( $object['id'] );
158
		$field->load();
159
160
		$field_type = $this->get_field_type( $field );
161
162
		return call_user_func( array( $this->data_manager, "load_{$field_type}_field_value" ), $field );
163
	}
164
165
	/**
166
	 * Wrapper method for updating Post Meta fields,
167
	 * need to pass the correct $context
168
	 * 
169
	 * @param mixed $value The value of the field
170
	 * @param object $object The object from the request
171
	 * @param string $field_name Name of field
172
	 */
173
	public function update_post_meta_field_value( $value, $object, $field_name ) {
174
		$context = 'Post_Meta';
175
		$this->update_field_value( $value, $object, $field_name, $context );
176
	}
177
178
	/**
179
	 * Wrapper method for updating Term Meta fields,
180
	 * need to pass the correct $context
181
	 * 
182
	 * @param mixed $value The value of the field
183
	 * @param object $object The object from the request
184
	 * @param string $field_name Name of field
185
	 */
186
	public function update_term_meta_field_value( $value, $object, $field_name ) {
187
		$context = 'Term_Meta';
188
		$this->update_field_value( $value, $object, $field_name, $context );
189
	}
190
191
	/**
192
	 * Wrapper method for updating Comment Meta fields,
193
	 * need to pass the correct $context
194
	 * 
195
	 * @param mixed $value The value of the field
196
	 * @param object $object The object from the request
197
	 * @param string $field_name Name of field
198
	 */
199
	public function update_comment_meta_field_value( $value, $object, $field_name ) {
200
		$context = 'Comment_Meta';
201
		$this->update_field_value( $value, $object, $field_name, $context );
202
	}
203
204
	/**
205
	 * Wrapper method for updating User Meta fields,
206
	 * need to pass the correct $context
207
	 * 
208
	 * @param mixed $value The value of the field
209
	 * @param object $object The object from the request
210
	 * @param string $field_name Name of field
211
	 */
212
	public function update_user_meta_field_value( $value, $object, $field_name ) {
213
		$context = 'User_Meta';
214
		$this->update_field_value( $value, $object, $field_name, $context );
215
	}
216
217
	/**
218
	 * Handler for updating custom field data.
219
	 *
220
	 * @param mixed $value The value of the field
221
	 * @param object $object The object from the request
222
	 * @param string $field_name Name of field
223
	 * @param string $context Post_Meta|Term_Meta|User_Meta|Comment_Meta
224
	 */
225
	public function update_field_value( $value, $object, $field_name, $context ) {
226
		if ( ! $value || ! is_string( $value ) ) {
227
			return;
228
		}
229
		
230
		$field = $this->get_current_field( $field_name, $context );
231
232
		if ( empty( $field ) ) {
233
			return;
234
		}
235
		
236
		$field     = array_pop( $field );
237
		$type      = strtolower( $field->type );
238
		$context   = strtolower( $context );
239
		$object_id = self::get_object_id( $object, $context );
240
241
		Updater::$is_rest_request = true;
242
		
243
		try {
244
			call_user_func( "Carbon_Fields\Updater\Updater::update_field", $context, $object_id, $field_name, $value, $type );	
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Carbon_Fields\Updater\Updater::update_field does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
245
		} catch ( \Exception $e ) {
246
			echo wp_strip_all_tags( $e->getMessage() );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'wp_strip_all_tags'
Loading history...
247
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method update_field_value() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
248
		}
249
	}
250
251
	/**
252
	 * Get the type of a field
253
	 * 
254
	 * @param object $field
255
	 * @return string
256
	 */
257
	public function get_field_type( $field ) {
258
		$type_to_lower = strtolower( $field->type );
259
		return in_array( $type_to_lower, $this->data_manager->special_field_types ) ? $type_to_lower : 'generic';
260
	}
261
262
	/**
263
	 * Get field based on it's name
264
	 * @param  string $field_name 
265
	 * @return array
266
	 */
267
	public function get_current_field( $field_name, $context ) {
268
		return array_filter( $this->fields, function( $field ) use ( $field_name, $context ) { 
269
			return ( $field->get_name() === $field_name ) && ( $field->get_context() === $context );
270
		} );
271
	}
272
273
	/**
274
	 * Get Post Meta Container visibility settings
275
	 *
276
	 * @return array
277
	 */	
278
	public static function get_post_meta_container_settings( $container ) {
279
		return $container->settings['post_type'];
280
	}
281
282
	/**
283
	 * Get Term Meta Container visibility settings
284
	 *
285
	 * @return array
286
	 */	
287
	public static function get_term_meta_container_settings( $container ) {
288
		return $container->settings['taxonomy'];
289
	}
290
291
	/**
292
	 * Get User Meta Container visibility settings
293
	 *
294
	 * @return string
295
	 */	
296
	public static function get_user_meta_container_settings( $container ) {
1 ignored issue
show
Unused Code introduced by
The parameter $container 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...
297
		return 'user';
298
	}
299
300
	/**
301
	 * Get Comment Meta Container visibility settings
302
	 * 
303
	 * @return string
304
	 */	
305
	public static function get_comment_meta_container_settings( $container ) {
0 ignored issues
show
Unused Code introduced by
The parameter $container 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...
306
		return 'comment';
307
	}
308
309
	/**
310
	 * Retrieve ID from object
311
	 * based on $context
312
	 * 
313
	 * @param  object $object
314
	 * @param  string $context
315
	 * @return string
316
	 */
317
	public static function get_object_id( $object, $context ) {
318
		switch ( $context ) {
319
			case 'post_meta': // fallthrough intended
320
			case 'user_meta': 
321
				return $object->ID;
322
				break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
323
324
			case 'term_meta':
325
				return $object->term_id;
326
				break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
327
328
			case 'comment_meta' : 
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
329
				return $object->comment_ID;
330
				break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
331
		}
332
	}
333
}