Completed
Push — 2.x ( 07463f...43658f )
by Scott Kingsley
13s
created

PodsRESTHandlers::get_pod()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 4
nop 2
dl 0
loc 13
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Class PodsRESTHandlers
4
 *
5
 * Handlers for reading and writing Pods fields via REST API
6
 *
7
 * @package Pods
8
 * @since   2.5.6
9
 */
10
class PodsRESTHandlers {
11
12
	/**
13
	 * Holds a Pods object to avoid extra DB queries
14
	 *
15
	 * @since 2.5.6
16
	 *
17
	 * @var Pods
18
	 */
19
	private static $pod;
20
21
	/**
22
	 * Get Pod object
23
	 *
24
	 * @since 2.5.6
25
	 *
26
	 * @param $pod_name
27
	 * @param $id
28
	 *
29
	 * @return bool|Pods
30
	 */
31
	protected static function get_pod( $pod_name, $id ) {
32
33
		if ( ! self::$pod || self::$pod->pod != $pod_name ) {
34
			self::$pod = pods( $pod_name, $id, true );
35
		}
36
37
		if ( self::$pod && self::$pod->id != $id ) {
38
			self::$pod->fetch( $id );
39
		}
40
41
		return self::$pod;
42
43
	}
44
45
	/**
46
	 * Handler for getting custom field data.
47
	 *
48
	 * @since 2.5.6
49
	 *
50
	 * @param array           $object      The object from the response
51
	 * @param string          $field_name  Name of field
52
	 * @param WP_REST_Request $request     Current request
53
	 * @param string          $object_type Type of object
54
	 *
55
	 * @return mixed
56
	 */
57
	public static function get_handler( $object, $field_name, $request, $object_type ) {
58
59
		$pod_name = pods_v( 'type', $object );
60
61
		/**
62
		 * If $pod_name in the line above is empty then the route invoked
63
		 * may be for a taxonomy, so lets try and check for that
64
		 *
65
		 */
66
		if ( empty( $pod_name ) ) {
67
			$pod_name = pods_v( 'taxonomy', $object );
68
		}
69
70
		/**
71
		 * $pod_name is still empty, so check lets check $object_type
72
		 *
73
		 */
74
75
		if ( empty( $pod_name ) ) {
76
			if ( 'attachment' == $object_type ) {
77
				$pod_name = 'media';
78
			} else {
79
				$pod_name = $object_type;
80
			}
81
		}
82
83
		/**
84
		 * Filter the pod name
85
		 *
86
		 * @since 2.6.7
87
		 *
88
		 * @param array           $pod_name    Pod name
89
		 * @param Pods            $object      Rest object
90
		 * @param string          $field_name  Name of the field
91
		 * @param WP_REST_Request $request     Current request
92
		 * @param string          $object_type Rest Object type
93
		 */
94
		$pod_name = apply_filters( 'pods_rest_api_pod_name', $pod_name, $object, $field_name, $request, $object_type  );
95
96
		$id  = pods_v( 'id', $object );
97
98
		if ( empty( $id ) ) {
99
			$id = pods_v( 'ID', $object );
100
		}
101
		
102
		$pod = self::get_pod( $pod_name, $id );
103
104
		$value = false;
105
106
		if ( $pod && PodsRESTFields::field_allowed_to_extend( $field_name, $pod, 'read' ) ) {
107
			$params = null;
108
109
			$field_data = $pod->fields( $field_name );
110
111
			if ( 'pick' == pods_v( 'type', $field_data ) ) {
112
				$output_type = pods_v( 'rest_pick_response', $field_data['options'], 'array' );
113
114
				if ( 'array' == $output_type ) {
115
					$related_pod_items = $pod->field( $field_name, array( 'output' => 'pod' ) );
116
117
					if ( $related_pod_items ) {
118
						$fields = false;
119
						$items  = array();
120
						$depth  = pods_v( 'rest_pick_depth', $field_data['options'], 2 );
121
122
						if ( ! is_array( $related_pod_items ) ) {
123
							$related_pod_items = array( $related_pod_items );
124
						}
125
126
						/**
127
						 * @var $related_pod Pods
128
						 */
129
						foreach ( $related_pod_items as $related_pod ) {
130
							if ( ! is_object( $related_pod ) || ! is_a( $related_pod, 'Pods' ) ) {
131
								$items = $related_pod_items;
132
133
								break;
134
							}
135
136
							if ( false === $fields ) {
137
								$fields = $related_pod->fields();
138
								$fields = array_keys( $fields );
139
140
								if ( isset( $related_pod->pod_data['object_fields'] ) && ! empty( $related_pod->pod_data['object_fields'] ) ) {
141
									$fields = array_merge( $fields, array_keys( $related_pod->pod_data['object_fields'] ) );
142
								}
143
144
								/**
145
								 * What fields to show in a related field REST response.
146
								 *
147
								 * @since 0.0.1
148
								 *
149
								 * @param array                  $fields     The fields to show
150
								 * @param string                 $field_name The name of the field
151
								 * @param object|Pods            $pod        The Pods object for Pod relationship is from.
152
								 * @param object|Pods            $pod        The Pods object for Pod relationship is to.
153
								 * @param int                    $id         Current item ID
154
								 * @param object|WP_REST_Request Current     request object.
155
								 */
156
								$fields = apply_filters( 'pods_rest_api_fields_for_relationship_response', $fields, $field_name, $pod, $related_pod, $id, $request );
157
							}
158
159
							/**
160
							 * What depth to use for a related field REST response.
161
							 *
162
							 * @since 0.0.1
163
							 *
164
							 * @param array                  $depth      The depth.
165
							 * @param string                 $field_name The name of the field
166
							 * @param object|Pods            $pod        The Pods object for Pod relationship is from.
167
							 * @param object|Pods            $pod        The Pods object for Pod relationship is to.
168
							 * @param int                    $id         Current item ID
169
							 * @param object|WP_REST_Request Current     request object.
170
							 */
171
							$depth = apply_filters( 'pods_rest_api_depth_for_relationship_response', $depth, $field_name, $pod, $related_pod, $id, $request );
172
173
							$params = array(
174
								'fields' => $fields,
175
								'depth'  => $depth,
176
							);
177
178
							$items[] = $related_pod->export( $params );
179
						}
180
181
						$value = $items;
182
					}
183
				}
184
185
				$params = array(
186
					'output' => $output_type,
187
				);
188
			}
189
190
			// If no value set yet, get normal field value
191
			if ( ! $value && ! is_array( $value ) ) {
192
				$value = $pod->field( $field_name, $params );
193
			}
194
		}
195
196
		return $value;
197
198
	}
199
200
	/**
201
	 * Handler for updating custom field data.
202
	 *
203
	 * @since 2.5.6
204
	 *
205
	 * @param mixed           $value      Value to write
206
	 * @param object          $object     The object from the response
207
	 * @param string          $field_name Name of field
208
	 * @param WP_REST_Request $request     Current request
209
	 * @param string          $object_type Type of object
210
	 *
211
	 * @return bool|int
212
	 */
213
	public static function write_handler( $value, $object, $field_name, $request, $object_type ) {
214
215
		$pod_name = pods_v( 'type', $object );
216
217
		/**
218
		 * If $pod_name in the line above is empty then the route invoked
219
		 * may be for a taxonomy, so lets try and check for that
220
		 *
221
		 */
222
		if ( empty( $pod_name ) ) {
223
			$pod_name = pods_v( 'taxonomy', $object );
224
		}
225
226
		/**
227
		 * $pod_name is still empty, so check lets check $object_type
228
		 *
229
		 */
230
231
		if ( empty( $pod_name ) ) {
232
			if ( 'attachment' == $object_type ) {
233
				$pod_name = 'media';
234
			} else {
235
				$pod_name = $object_type;
236
			}
237
		}
238
239
		/**
240
		 * Filter the pod name
241
		 *
242
		 * @since 2.6.7
243
		 *
244
		 * @param array           $pod_name    Pod name
245
		 * @param Pods            $object      Rest object
246
		 * @param string          $field_name  Name of the field
247
		 * @param WP_REST_Request $request     Current request
248
		 * @param string          $object_type Rest Object type
249
		 */
250
		$pod_name = apply_filters( 'pods_rest_api_pod_name', $pod_name, $object, $field_name, $request, $object_type );
251
252
		$id = pods_v( 'id', $object );
253
254
		if ( empty( $id ) ) {
255
			$id = pods_v( 'ID', $object );
256
		}
257
		$pod = self::get_pod( $pod_name, $id );
258
259
		if ( $pod && PodsRESTFields::field_allowed_to_extend( $field_name, $pod, 'write' ) ) {
260
			$pod->save( $field_name, $value, $id );
261
262
			return $pod->field( $field_name );
263
		}
264
265
		return false;
266
267
	}
268
269
	/**
270
	 * Add REST API support to a post type
271
	 *
272
	 * @since 2.5.6
273
	 *
274
	 * @param string     $post_type_name Name of post type
275
	 * @param bool|false $rest_base      Optional. Base url segment. If not set, post type name is used
276
	 * @param string     $controller     Optional, controller class for route. If not set "WP_REST_Posts_Controller" is
277
	 *                                   used.
278
	 */
279 View Code Duplication
	public static function post_type_rest_support( $post_type_name, $rest_base = false, $controller = 'WP_REST_Posts_Controller' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
280
281
		global $wp_post_types;
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...
282
283
		// Only add support for post types that exist
284
		if ( isset( $wp_post_types[ $post_type_name ] ) ) {
285
			// Only add support if REST base not already set
286
			if ( empty( $wp_post_types[ $post_type_name ]->rest_base ) ) {
287
				if ( ! $rest_base ) {
288
					$rest_base = $post_type_name;
289
				}
290
291
				$wp_post_types[ $post_type_name ]->show_in_rest          = true;
292
				$wp_post_types[ $post_type_name ]->rest_base             = $rest_base;
293
				$wp_post_types[ $post_type_name ]->rest_controller_class = $controller;
294
			}
295
		}
296
297
	}
298
299
	/**
300
	 * Add REST API support to an already registered taxonomy.
301
	 *
302
	 * @since 2.5.6
303
	 *
304
	 * @param string     $taxonomy_name Taxonomy name.
305
	 * @param bool|false $rest_base     Optional. Base url segment. If not set, taxonomy name is used.
306
	 * @param string     $controller    Optional, controller class for route. If not set "WP_REST_Terms_Controller" is
307
	 *                                  used.
308
	 */
309 View Code Duplication
	public static function taxonomy_rest_support( $taxonomy_name, $rest_base = false, $controller = 'WP_REST_Terms_Controller' ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
310
311
		global $wp_taxonomies;
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...
312
313
		// Only add support for taxonomies that exist
314
		if ( isset( $wp_taxonomies[ $taxonomy_name ] ) ) {
315
			// Only add support if REST base not already set
316
			if ( empty( $wp_taxonomies[ $taxonomy_name ]->rest_base ) ) {
317
				if ( ! $rest_base ) {
318
					$rest_base = $taxonomy_name;
319
				}
320
321
				$wp_taxonomies[ $taxonomy_name ]->show_in_rest          = true;
322
				$wp_taxonomies[ $taxonomy_name ]->rest_base             = $rest_base;
323
				$wp_taxonomies[ $taxonomy_name ]->rest_controller_class = $controller;
324
			}
325
326
		}
327
	}
328
329
	/**
330
	 * Check if a Pod supports extending core REST response.
331
	 *
332
	 * @since 2.5.6
333
	 *
334
	 * @param array|Pods $pod Pod object or the pod_data array
335
	 *
336
	 * @return bool
337
	 */
338
	public static function pod_extends_core_route( $pod ) {
339
340
		$enabled = false;
341
342
		if ( is_object( $pod ) ) {
343
			$pod = $pod->pod_data;
344
		}
345
346
		if ( is_array( $pod ) ) {
347
			$enabled = (boolean) pods_v( 'rest_enable', $pod['options'], false );
348
		}
349
350
		return $enabled;
351
352
	}
353
354
}
355