Completed
Branch develop (8edf3f)
by
unknown
02:31
created

plugin.php ➔ rest_is_ip_address()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 9.6666
1
<?php
2
/**
3
 * Plugin Name: WP REST API
4
 * Description: JSON-based REST API for WordPress, originally developed as part of GSoC 2013.
5
 * Author: WP REST API Team
6
 * Author URI: http://v2.wp-api.org
7
 * Version: 2.0-beta13
8
 * Plugin URI: https://github.com/WP-API/WP-API
9
 * License: GPL2+
10
 */
11
12
/**
13
 * WP_REST_Controller class.
14
 */
15
if ( ! class_exists( 'WP_REST_Controller' ) ) {
16
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-controller.php';
17
}
18
19
/**
20
 * WP_REST_Posts_Controller class.
21
 */
22
if ( ! class_exists( 'WP_REST_Posts_Controller' ) ) {
23
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-posts-controller.php';
24
}
25
26
/**
27
 * WP_REST_Attachments_Controller class.
28
 */
29
if ( ! class_exists( 'WP_REST_Attachments_Controller' ) ) {
30
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-attachments-controller.php';
31
}
32
33
/**
34
 * WP_REST_Post_Types_Controller class.
35
 */
36
if ( ! class_exists( 'WP_REST_Post_Types_Controller' ) ) {
37
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-post-types-controller.php';
38
}
39
40
/**
41
 * WP_REST_Post_Statuses_Controller class.
42
 */
43
if ( ! class_exists( 'WP_REST_Post_Statuses_Controller' ) ) {
44
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-post-statuses-controller.php';
45
}
46
47
/**
48
 * WP_REST_Revisions_Controller class.
49
 */
50
if ( ! class_exists( 'WP_REST_Revisions_Controller' ) ) {
51
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-revisions-controller.php';
52
}
53
54
/**
55
 * WP_REST_Taxonomies_Controller class.
56
 */
57
if ( ! class_exists( 'WP_REST_Taxonomies_Controller' ) ) {
58
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-taxonomies-controller.php';
59
}
60
61
/**
62
 * WP_REST_Terms_Controller class.
63
 */
64
if ( ! class_exists( 'WP_REST_Terms_Controller' ) ) {
65
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-terms-controller.php';
66
}
67
68
/**
69
 * WP_REST_Users_Controller class.
70
 */
71
if ( ! class_exists( 'WP_REST_Users_Controller' ) ) {
72
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-users-controller.php';
73
}
74
75
/**
76
 * WP_REST_Comments_Controller class.
77
 */
78
if ( ! class_exists( 'WP_REST_Comments_Controller' ) ) {
79
	require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-comments-controller.php';
80
}
81
82
/**
83
 * REST extras.
84
 */
85
include_once( dirname( __FILE__ ) . '/extras.php' );
86
require_once( dirname( __FILE__ ) . '/core-integration.php' );
87
88
add_filter( 'init', '_add_extra_api_post_type_arguments', 11 );
89
add_action( 'init', '_add_extra_api_taxonomy_arguments', 11 );
90
add_action( 'rest_api_init', 'create_initial_rest_routes', 0 );
91
92
/**
93
 * Adds extra post type registration arguments.
94
 *
95
 * These attributes will eventually be committed to core.
96
 *
97
 * @since 4.4.0
98
 *
99
 * @global array $wp_post_types Registered post types.
100
 */
101
function _add_extra_api_post_type_arguments() {
102
	global $wp_post_types;
103
104
	if ( isset( $wp_post_types['post'] ) ) {
105
		$wp_post_types['post']->show_in_rest = true;
106
		$wp_post_types['post']->rest_base = 'posts';
107
		$wp_post_types['post']->rest_controller_class = 'WP_REST_Posts_Controller';
108
	}
109
110 View Code Duplication
	if ( isset( $wp_post_types['page'] ) ) {
111
		$wp_post_types['page']->show_in_rest = true;
112
		$wp_post_types['page']->rest_base = 'pages';
113
		$wp_post_types['page']->rest_controller_class = 'WP_REST_Posts_Controller';
114
	}
115
116 View Code Duplication
	if ( isset( $wp_post_types['attachment'] ) ) {
117
		$wp_post_types['attachment']->show_in_rest = true;
118
		$wp_post_types['attachment']->rest_base = 'media';
119
		$wp_post_types['attachment']->rest_controller_class = 'WP_REST_Attachments_Controller';
120
	}
121
}
122
123
/**
124
 * Adds extra taxonomy registration arguments.
125
 *
126
 * These attributes will eventually be committed to core.
127
 *
128
 * @since 4.4.0
129
 *
130
 * @global array $wp_taxonomies Registered taxonomies.
131
 */
132
function _add_extra_api_taxonomy_arguments() {
133
	global $wp_taxonomies;
134
135 View Code Duplication
	if ( isset( $wp_taxonomies['category'] ) ) {
136
		$wp_taxonomies['category']->show_in_rest = true;
137
		$wp_taxonomies['category']->rest_base = 'categories';
138
		$wp_taxonomies['category']->rest_controller_class = 'WP_REST_Terms_Controller';
139
	}
140
141 View Code Duplication
	if ( isset( $wp_taxonomies['post_tag'] ) ) {
142
		$wp_taxonomies['post_tag']->show_in_rest = true;
143
		$wp_taxonomies['post_tag']->rest_base = 'tags';
144
		$wp_taxonomies['post_tag']->rest_controller_class = 'WP_REST_Terms_Controller';
145
	}
146
}
147
148
if ( ! function_exists( 'create_initial_rest_routes' ) ) {
149
	/**
150
	 * Registers default REST API routes.
151
	 *
152
	 * @since 4.4.0
153
	 */
154
	function create_initial_rest_routes() {
155
156
		foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
157
			$class = ! empty( $post_type->rest_controller_class ) ? $post_type->rest_controller_class : 'WP_REST_Posts_Controller';
158
159
			if ( ! class_exists( $class ) ) {
160
				continue;
161
			}
162
			$controller = new $class( $post_type->name );
163
			if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) {
164
				continue;
165
			}
166
167
			$controller->register_routes();
168
169
			if ( post_type_supports( $post_type->name, 'revisions' ) ) {
170
				$revisions_controller = new WP_REST_Revisions_Controller( $post_type->name );
171
				$revisions_controller->register_routes();
172
			}
173
		}
174
175
		// Post types.
176
		$controller = new WP_REST_Post_Types_Controller;
177
		$controller->register_routes();
178
179
		// Post statuses.
180
		$controller = new WP_REST_Post_Statuses_Controller;
181
		$controller->register_routes();
182
183
		// Taxonomies.
184
		$controller = new WP_REST_Taxonomies_Controller;
185
		$controller->register_routes();
186
187
		// Terms.
188
		foreach ( get_taxonomies( array( 'show_in_rest' => true ), 'object' ) as $taxonomy ) {
189
			$class = ! empty( $taxonomy->rest_controller_class ) ? $taxonomy->rest_controller_class : 'WP_REST_Terms_Controller';
190
191
			if ( ! class_exists( $class ) ) {
192
				continue;
193
			}
194
			$controller = new $class( $taxonomy->name );
195
			if ( ! is_subclass_of( $controller, 'WP_REST_Controller' ) ) {
196
				continue;
197
			}
198
199
			$controller->register_routes();
200
		}
201
202
		// Users.
203
		$controller = new WP_REST_Users_Controller;
204
		$controller->register_routes();
205
206
		// Comments.
207
		$controller = new WP_REST_Comments_Controller;
208
		$controller->register_routes();
209
	}
210
}
211
212
if ( ! function_exists( 'rest_authorization_required_code' ) ) {
213
	/**
214
	 * Returns a contextual HTTP error code for authorization failure.
215
	 *
216
	 * @return integer
217
	 */
218
	function rest_authorization_required_code() {
219
		return is_user_logged_in() ? 403 : 401;
220
	}
221
}
222
223
if ( ! function_exists( 'register_rest_field' ) ) {
224
	/**
225
	 * Registers a new field on an existing WordPress object type.
226
	 *
227
	 * @global array $wp_rest_additional_fields Holds registered fields, organized
228
	 *                                          by object type.
229
	 *
230
	 * @param string|array $object_type Object(s) the field is being registered
231
	 *                                  to, "post"|"term"|"comment" etc.
232
	 * @param string $attribute         The attribute name.
233
	 * @param array  $args {
234
	 *     Optional. An array of arguments used to handle the registered field.
235
	 *
236
	 *     @type string|array|null $get_callback    Optional. The callback function used to retrieve the field
237
	 *                                              value. Default is 'null', the field will not be returned in
238
	 *                                              the response.
239
	 *     @type string|array|null $update_callback Optional. The callback function used to set and update the
240
	 *                                              field value. Default is 'null', the value cannot be set or
241
	 *                                              updated.
242
	 *     @type string|array|null $schema          Optional. The callback function used to create the schema for
243
	 *                                              this field. Default is 'null', no schema entry will be returned.
244
	 * }
245
	 */
246
	function register_rest_field( $object_type, $attribute, $args = array() ) {
247
		$defaults = array(
248
			'get_callback'    => null,
249
			'update_callback' => null,
250
			'schema'          => null,
251
		);
252
253
		$args = wp_parse_args( $args, $defaults );
254
255
		global $wp_rest_additional_fields;
256
257
		$object_types = (array) $object_type;
258
259
		foreach ( $object_types as $object_type ) {
260
			$wp_rest_additional_fields[ $object_type ][ $attribute ] = $args;
261
		}
262
	}
263
}
264
265
if ( ! function_exists( 'register_api_field' ) ) {
266
	/**
267
	 * Backwards compat shim
268
	 */
269
	function register_api_field( $object_type, $attributes, $args = array() ) {
270
		_deprecated_function( 'register_api_field', 'WPAPI-2.0', 'register_rest_field' );
271
		register_rest_field( $object_type, $attributes, $args );
272
	}
273
}
274
275
if ( ! function_exists( 'rest_validate_request_arg' ) ) {
276
	/**
277
	 * Validate a request argument based on details registered to the route.
278
	 *
279
	 * @param  mixed            $value
280
	 * @param  WP_REST_Request  $request
281
	 * @param  string           $param
282
	 * @return WP_Error|boolean
283
	 */
284
	function rest_validate_request_arg( $value, $request, $param ) {
285
286
		$attributes = $request->get_attributes();
287 View Code Duplication
		if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
288
			return true;
289
		}
290
		$args = $attributes['args'][ $param ];
291
292 View Code Duplication
		if ( ! empty( $args['enum'] ) ) {
293
			if ( ! in_array( $value, $args['enum'] ) ) {
294
				return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not one of %s' ), $param, implode( ', ', $args['enum'] ) ) );
295
			}
296
		}
297
298 View Code Duplication
		if ( 'integer' === $args['type'] && ! is_numeric( $value ) ) {
299
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $param, 'integer' ) );
300
		}
301
302 View Code Duplication
		if ( 'boolean' === $args['type'] && ! is_bool( $value ) ) {
303
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $param, 'boolean' ) );
304
		}
305
306 View Code Duplication
		if ( 'string' === $args['type'] && ! is_string( $value ) ) {
307
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $param, 'string' ) );
308
		}
309
310
		if ( isset( $args['format'] ) ) {
311
			switch ( $args['format'] ) {
312
				case 'date-time' :
313
					if ( ! rest_parse_date( $value ) ) {
314
						return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.' ) );
315
					}
316
					break;
317
318
				case 'email' :
319
					if ( ! is_email( $value ) ) {
320
						return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) );
321
					}
322
					break;
323
				case 'ipv4' :
324
					if ( ! rest_is_ip_address( $value ) ) {
325
						return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) );
326
					}
327
					break;
328
			}
329
		}
330
331
		if ( in_array( $args['type'], array( 'numeric', 'integer' ) ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) {
332
			if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) {
333 View Code Duplication
				if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) {
334
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be greater than %d (exclusive)' ), $param, $args['minimum'] ) );
335
				} else if ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) {
336
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be greater than %d (inclusive)' ), $param, $args['minimum'] ) );
337
				}
338
			} else if ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) {
339 View Code Duplication
				if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) {
340
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be less than %d (exclusive)' ), $param, $args['maximum'] ) );
341
				} else if ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) {
342
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be less than %d (inclusive)' ), $param, $args['maximum'] ) );
343
				}
344
			} else if ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) {
345
				if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
346 View Code Duplication
					if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) {
347
						return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (exclusive) and %d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
348
					}
349
				} else if ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
350 View Code Duplication
					if ( $value >= $args['maximum'] || $value < $args['minimum'] ) {
351
						return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (inclusive) and %d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
352
					}
353
				} else if ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
354 View Code Duplication
					if ( $value > $args['maximum'] || $value <= $args['minimum'] ) {
355
						return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (exclusive) and %d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
356
					}
357
				} else if ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
358 View Code Duplication
					if ( $value > $args['maximum'] || $value < $args['minimum'] ) {
359
						return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (inclusive) and %d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
360
					}
361
				}
362
			}
363
		}
364
365
		return true;
366
	}
367
}
368
369
if ( ! function_exists( 'rest_sanitize_request_arg' ) ) {
370
	/**
371
	 * Sanitize a request argument based on details registered to the route.
372
	 *
373
	 * @param  mixed            $value
374
	 * @param  WP_REST_Request  $request
375
	 * @param  string           $param
376
	 * @return mixed
377
	 */
378
	function rest_sanitize_request_arg( $value, $request, $param ) {
379
380
		$attributes = $request->get_attributes();
381 View Code Duplication
		if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
382
			return $value;
383
		}
384
		$args = $attributes['args'][ $param ];
385
386
		if ( 'integer' === $args['type'] ) {
387
			return (int) $value;
388
		}
389
390
		if ( isset( $args['format'] ) ) {
391
			switch ( $args['format'] ) {
392
				case 'date-time' :
393
					return sanitize_text_field( $value );
394
395
				case 'email' :
396
					/*
397
					 * sanitize_email() validates, which would be unexpected
398
					 */
399
					return sanitize_text_field( $value );
400
401
				case 'uri' :
402
					return esc_url_raw( $value );
403
404
				case 'ipv4' :
405
					return sanitize_text_field( $value );
406
			}
407
		}
408
409
		return $value;
410
	}
411
412
}
413
414
if ( ! function_exists( 'rest_is_ip_address' ) ) {
415
	/**
416
	 * Determines if a IPv4 address is valid.
417
	 *
418
	 * Does not handle IPv6 addresses.
419
	 *
420
	 * @param  string $ipv4 IP 32-bit address.
421
	 * @return string|false The valid IPv4 address, otherwise false.
422
	 */
423
	function rest_is_ip_address( $ipv4 ) {
424
		$pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
425
426
		if ( ! preg_match( $pattern, $ipv4 ) ) {
427
			return false;
428
		}
429
430
		return $ipv4;
431
	}
432
}
433