Completed
Push — 2.x ( 564e6b...070e4c )
by Scott Kingsley
9s
created

PodsRESTHandlers   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 274
Duplicated Lines 10.95 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 6
Bugs 0 Features 1
Metric Value
c 6
b 0
f 1
dl 30
loc 274
rs 8.8
wmc 36
lcom 1
cbo 2

6 Methods

Rating   Name   Duplication   Size   Complexity  
B get_pod() 0 13 5
D get_handler() 0 119 19
A write_handler() 0 17 3
A post_type_rest_support() 15 15 3
A taxonomy_rest_support() 15 15 3
A pod_extends_core_route() 0 15 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
		if ( empty( $pod_name ) && 'attachment' == $object_type ) {
71
			$pod_name = 'media';
72
		}
73
		$id  = pods_v( 'id', $object );
74
75
		if ( empty( $id ) ) {
76
			$id = pods_v( 'ID', $object );
77
		}
78
		
79
		$pod = self::get_pod( $pod_name, $id );
80
81
		$value = false;
82
83
		if ( $pod && PodsRESTFields::field_allowed_to_extend( $field_name, $pod, 'read' ) ) {
84
			$params = null;
85
86
			$field_data = $pod->fields( $field_name );
87
88
			if ( 'pick' == pods_v( 'type', $field_data ) ) {
89
				$output_type = pods_v( 'rest_pick_response', $field_data['options'], 'array' );
90
91
				if ( 'array' == $output_type ) {
92
					$related_pod_items = $pod->field( $field_name, array( 'output' => 'pod' ) );
93
94
					if ( $related_pod_items ) {
95
						$fields = false;
96
						$items  = array();
97
						$depth  = pods_v( 'rest_pick_depth', $field_data['options'], 2 );
98
99
						if ( ! is_array( $related_pod_items ) ) {
100
							$related_pod_items = array( $related_pod_items );
101
						}
102
103
						/**
104
						 * @var $related_pod Pods
105
						 */
106
						foreach ( $related_pod_items as $related_pod ) {
107
							if ( ! is_object( $related_pod ) || ! is_a( $related_pod, 'Pods' ) ) {
108
								$items = $related_pod_items;
109
110
								break;
111
							}
112
113
							if ( false === $fields ) {
114
								$fields = $related_pod->fields();
115
								$fields = array_keys( $fields );
116
117
								if ( isset( $related_pod->pod_data['object_fields'] ) && ! empty( $related_pod->pod_data['object_fields'] ) ) {
118
									$fields = array_merge( $fields, array_keys( $related_pod->pod_data['object_fields'] ) );
119
								}
120
121
								/**
122
								 * What fields to show in a related field REST response.
123
								 *
124
								 * @since 0.0.1
125
								 *
126
								 * @param array                  $fields     The fields to show
127
								 * @param string                 $field_name The name of the field
128
								 * @param object|Pods            $pod        The Pods object for Pod relationship is from.
129
								 * @param object|Pods            $pod        The Pods object for Pod relationship is to.
130
								 * @param int                    $id         Current item ID
131
								 * @param object|WP_REST_Request Current     request object.
132
								 */
133
								$fields = apply_filters( 'pods_rest_api_fields_for_relationship_response', $fields, $field_name, $pod, $related_pod, $id, $request );
134
							}
135
136
							/**
137
							 * What depth to use for a related field REST response.
138
							 *
139
							 * @since 0.0.1
140
							 *
141
							 * @param array                  $depth      The depth.
142
							 * @param string                 $field_name The name of the field
143
							 * @param object|Pods            $pod        The Pods object for Pod relationship is from.
144
							 * @param object|Pods            $pod        The Pods object for Pod relationship is to.
145
							 * @param int                    $id         Current item ID
146
							 * @param object|WP_REST_Request Current     request object.
147
							 */
148
							$depth = apply_filters( 'pods_rest_api_depth_for_relationship_response', $depth, $field_name, $pod, $related_pod, $id, $request );
149
150
							$params = array(
151
								'fields' => $fields,
152
								'depth'  => $depth,
153
							);
154
155
							$items[] = $related_pod->export( $params );
156
						}
157
158
						$value = $items;
159
					}
160
				}
161
162
				$params = array(
163
					'output' => $output_type,
164
				);
165
			}
166
167
			// If no value set yet, get normal field value
168
			if ( ! $value && ! is_array( $value ) ) {
169
				$value = $pod->field( $field_name, $params );
170
			}
171
		}
172
173
		return $value;
174
175
	}
176
177
	/**
178
	 * Handler for updating custom field data.
179
	 *
180
	 * @since 2.5.6
181
	 *
182
	 * @param mixed  $value      Value to write
183
	 * @param object $object     The object from the response
184
	 * @param string $field_name Name of field
185
	 *
186
	 * @return bool|int
187
	 */
188
	public static function write_handler( $value, $object, $field_name ) {
189
190
		$pod_name = pods_v( 'type', $object );
191
192
		$id = pods_v( 'id', $object );
193
194
		$pod = self::get_pod( $pod_name, $id );
195
196
		if ( $pod && PodsRESTFields::field_allowed_to_extend( $field_name, $pod, 'write' ) ) {
197
			$pod->save( $field_name, $value, $id );
198
199
			return $pod->field( $field_name );
200
		}
201
202
		return false;
203
204
	}
205
206
	/**
207
	 * Add REST API support to a post type
208
	 *
209
	 * @since 2.5.6
210
	 *
211
	 * @param string     $post_type_name Name of post type
212
	 * @param bool|false $rest_base      Optional. Base url segment. If not set, post type name is used
213
	 * @param string     $controller     Optional, controller class for route. If not set "WP_REST_Posts_Controller" is
214
	 *                                   used.
215
	 */
216 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...
217
218
		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...
219
220
		if ( isset( $wp_post_types[ $post_type_name ] ) ) {
221
			if ( ! $rest_base ) {
222
				$rest_base = $post_type_name;
223
			}
224
225
			$wp_post_types[ $post_type_name ]->show_in_rest          = true;
226
			$wp_post_types[ $post_type_name ]->rest_base             = $rest_base;
227
			$wp_post_types[ $post_type_name ]->rest_controller_class = $controller;
228
		}
229
230
	}
231
232
	/**
233
	 * Add REST API support to an already registered taxonomy.
234
	 *
235
	 * @since 2.5.6
236
	 *
237
	 * @param string     $taxonomy_name Taxonomy name.
238
	 * @param bool|false $rest_base     Optional. Base url segment. If not set, taxonomy name is used.
239
	 * @param string     $controller    Optional, controller class for route. If not set "WP_REST_Terms_Controller" is
240
	 *                                  used.
241
	 */
242 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...
243
244
		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...
245
246
		if ( isset( $wp_taxonomies[ $taxonomy_name ] ) ) {
247
			if ( ! $rest_base ) {
248
				$rest_base = $taxonomy_name;
249
			}
250
251
			$wp_taxonomies[ $taxonomy_name ]->show_in_rest          = true;
252
			$wp_taxonomies[ $taxonomy_name ]->rest_base             = $rest_base;
253
			$wp_taxonomies[ $taxonomy_name ]->rest_controller_class = $controller;
254
		}
255
256
	}
257
258
	/**
259
	 * Check if a Pod supports extending core REST response.
260
	 *
261
	 * @since 2.5.6
262
	 *
263
	 * @param array|Pods $pod Pod object or the pod_data array
264
	 *
265
	 * @return bool
266
	 */
267
	public static function pod_extends_core_route( $pod ) {
268
269
		$enabled = false;
270
271
		if ( is_object( $pod ) ) {
272
			$pod = $pod->pod_data;
273
		}
274
275
		if ( is_array( $pod ) ) {
276
			$enabled = (boolean) pods_v( 'rest_enable', $pod['options'], false );
277
		}
278
279
		return $enabled;
280
281
	}
282
283
}