WordPress REST API (Version 2) - Version 2.0-beta7

Version Description

Download this release

Release Info

Developer danielbachhuber
Plugin Icon 128x128 WordPress REST API (Version 2)
Version 2.0-beta7
Comparing to
See all releases

Code changes from version 2.0-beta6 to 2.0-beta7

CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
  # Changelog
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ## 2.0 Beta 6.0
4
 
5
  - Remove global inclusion of wp-admin/includes/admin.php
1
  # Changelog
2
 
3
+ ## 2.0 Beta 7.0
4
+
5
+ - Sync infrastructure from WordPress core as of r35691.
6
+
7
+ * Remove `register_api_field()` because it's conceptually tied to `WP_REST_Controller` [#34730](https://core.trac.wordpress.org/ticket/34730)
8
+ * Update the REST API header links to use api.w.org [#34303](https://core.trac.wordpress.org/ticket/34303)
9
+ * Require the `$namespace` argument in `register_rest_route()` [#34416](https://core.trac.wordpress.org/ticket/34416)
10
+ * Include `enum` and `description` in help data [#34543](https://core.trac.wordpress.org/ticket/34543)
11
+ * Save `preg_match` iterations in `WP_REST_Server` [#34488](https://core.trac.wordpress.org/ticket/34488)
12
+ * Don't return route URL in `WP_REST_Request:get_params()` [#34647](https://core.trac.wordpress.org/ticket/34647)
13
+
14
+ - Restore `register_api_field()` within the plugin.
15
+
16
+ (props @danielbachhuber, [#1748](https://github.com/WP-API/WP-API/pull/1748))
17
+
18
+ - Require admin functions for use of `wp_handle_upload()`, fixing fatal.
19
+
20
+ (props @joehoyle, [#1746](https://github.com/WP-API/WP-API/pull/1746))
21
+
22
+ - Properly handle requesting terms where `parent=0` and `0` is a string.
23
+
24
+ (props @danielbachhuber, [#1739](https://github.com/WP-API/WP-API/pull/1739))
25
+
26
+ - Prevent PHP error notice when `&filter` isn't an array.
27
+
28
+ (props @danielbachhuber, [#1734](https://github.com/WP-API/WP-API/pull/1734))
29
+
30
+ - Change link relations to use api.w.org.
31
+
32
+ (props @danielbachhuber, [#1726](https://github.com/WP-API/WP-API/pull/1726))
33
+
34
+
35
  ## 2.0 Beta 6.0
36
 
37
  - Remove global inclusion of wp-admin/includes/admin.php
core/wp-includes/rest-api/class-wp-rest-request.php CHANGED
@@ -341,7 +341,7 @@ class WP_REST_Request implements ArrayAccess {
341
  * Used when checking parameters in get_param().
342
  *
343
  * @since 4.4.0
344
- * @access public
345
  *
346
  * @return array List of types to check, in order of priority.
347
  */
341
  * Used when checking parameters in get_param().
342
  *
343
  * @since 4.4.0
344
+ * @access protected
345
  *
346
  * @return array List of types to check, in order of priority.
347
  */
core/wp-includes/rest-api/class-wp-rest-response.php CHANGED
@@ -243,8 +243,12 @@ class WP_REST_Response extends WP_HTTP_Response {
243
  $error = new WP_Error;
244
 
245
  if ( is_array( $this->get_data() ) ) {
246
- foreach ( $this->get_data() as $err ) {
247
- $error->add( $err['code'], $err['message'], $err['data'] );
 
 
 
 
248
  }
249
  } else {
250
  $error->add( $this->get_status(), '', array( 'status' => $this->get_status() ) );
243
  $error = new WP_Error;
244
 
245
  if ( is_array( $this->get_data() ) ) {
246
+ $data = $this->get_data();
247
+ $error->add( $data['code'], $data['message'], $data['data'] );
248
+ if ( ! empty( $data['additional_errors'] ) ) {
249
+ foreach( $data['additional_errors'] as $err ) {
250
+ $error->add( $err['code'], $err['message'], $err['data'] );
251
+ }
252
  }
253
  } else {
254
  $error->add( $this->get_status(), '', array( 'status' => $this->get_status() ) );
core/wp-includes/rest-api/class-wp-rest-server.php CHANGED
@@ -162,14 +162,21 @@ class WP_REST_Server {
162
  $status = 500;
163
  }
164
 
165
- $data = array();
166
 
167
  foreach ( (array) $error->errors as $code => $messages ) {
168
  foreach ( (array) $messages as $message ) {
169
- $data[] = array( 'code' => $code, 'message' => $message, 'data' => $error->get_error_data( $code ) );
170
  }
171
  }
172
 
 
 
 
 
 
 
 
173
  $response = new WP_REST_Response( $data, $status );
174
 
175
  return $response;
@@ -198,7 +205,7 @@ class WP_REST_Server {
198
 
199
  $error = compact( 'code', 'message' );
200
 
201
- return wp_json_encode( array( $error ) );
202
  }
203
 
204
  /**
@@ -763,6 +770,12 @@ class WP_REST_Server {
763
  $path = $request->get_route();
764
 
765
  foreach ( $this->get_routes() as $route => $handlers ) {
 
 
 
 
 
 
766
  foreach ( $handlers as $handler ) {
767
  $callback = $handler['callback'];
768
  $response = null;
@@ -771,17 +784,13 @@ class WP_REST_Server {
771
  continue;
772
  }
773
 
774
- $match = preg_match( '@^' . $route . '$@i', $path, $args );
775
-
776
- if ( ! $match ) {
777
- continue;
778
- }
779
-
780
  if ( ! is_callable( $callback ) ) {
781
  $response = new WP_Error( 'rest_invalid_handler', __( 'The handler for the route is invalid' ), array( 'status' => 500 ) );
782
  }
783
 
784
  if ( ! is_wp_error( $response ) ) {
 
 
785
 
786
  $request->set_url_params( $args );
787
  $request->set_attributes( $handler );
@@ -1064,6 +1073,12 @@ class WP_REST_Server {
1064
  if ( isset( $opts['default'] ) ) {
1065
  $arg_data['default'] = $opts['default'];
1066
  }
 
 
 
 
 
 
1067
  $endpoint_data['args'][ $key ] = $arg_data;
1068
  }
1069
  }
162
  $status = 500;
163
  }
164
 
165
+ $errors = array();
166
 
167
  foreach ( (array) $error->errors as $code => $messages ) {
168
  foreach ( (array) $messages as $message ) {
169
+ $errors[] = array( 'code' => $code, 'message' => $message, 'data' => $error->get_error_data( $code ) );
170
  }
171
  }
172
 
173
+ $data = $errors[0];
174
+ if ( count( $errors ) > 1 ) {
175
+ // Remove the primary error.
176
+ array_shift( $errors );
177
+ $data['additional_errors'] = $errors;
178
+ }
179
+
180
  $response = new WP_REST_Response( $data, $status );
181
 
182
  return $response;
205
 
206
  $error = compact( 'code', 'message' );
207
 
208
+ return wp_json_encode( $error );
209
  }
210
 
211
  /**
770
  $path = $request->get_route();
771
 
772
  foreach ( $this->get_routes() as $route => $handlers ) {
773
+ $match = preg_match( '@^' . $route . '$@i', $path, $args );
774
+
775
+ if ( ! $match ) {
776
+ continue;
777
+ }
778
+
779
  foreach ( $handlers as $handler ) {
780
  $callback = $handler['callback'];
781
  $response = null;
784
  continue;
785
  }
786
 
 
 
 
 
 
 
787
  if ( ! is_callable( $callback ) ) {
788
  $response = new WP_Error( 'rest_invalid_handler', __( 'The handler for the route is invalid' ), array( 'status' => 500 ) );
789
  }
790
 
791
  if ( ! is_wp_error( $response ) ) {
792
+ // Remove the redundant preg_match argument.
793
+ unset( $args[0] );
794
 
795
  $request->set_url_params( $args );
796
  $request->set_attributes( $handler );
1073
  if ( isset( $opts['default'] ) ) {
1074
  $arg_data['default'] = $opts['default'];
1075
  }
1076
+ if ( isset( $opts['enum'] ) ) {
1077
+ $arg_data['enum'] = $opts['enum'];
1078
+ }
1079
+ if ( isset( $opts['description'] ) ) {
1080
+ $arg_data['description'] = $opts['description'];
1081
+ }
1082
  $endpoint_data['args'][ $key ] = $arg_data;
1083
  }
1084
  }
core/wp-includes/rest-api/rest-functions.php CHANGED
@@ -20,11 +20,25 @@
20
  * multiple methods. Default empty array.
21
  * @param bool $override Optional. If the route already exists, should we override it? True overrides,
22
  * false merges (with newer overriding if duplicate keys exist). Default false.
 
23
  */
24
  function register_rest_route( $namespace, $route, $args = array(), $override = false ) {
25
  /** @var WP_REST_Server $wp_rest_server */
26
  global $wp_rest_server;
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  if ( isset( $args['callback'] ) ) {
29
  // Upgrade a single set to multiple.
30
  $args = array( $args );
@@ -44,62 +58,9 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
44
  $arg_group = array_merge( $defaults, $arg_group );
45
  }
46
 
47
- if ( $namespace ) {
48
- $full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' );
49
- } else {
50
- /*
51
- * Non-namespaced routes are not allowed, with the exception of the main
52
- * and namespace indexes. If you really need to register a
53
- * non-namespaced route, call `WP_REST_Server::register_route` directly.
54
- */
55
- _doing_it_wrong( 'register_rest_route', 'Routes must be namespaced with plugin name and version', 'WPAPI-2.0' );
56
-
57
- $full_route = '/' . trim( $route, '/' );
58
- }
59
-
60
  $wp_rest_server->register_route( $namespace, $full_route, $args, $override );
61
- }
62
-
63
- /**
64
- * Registers a new field on an existing WordPress object type.
65
- *
66
- * @since 4.4.0
67
- *
68
- * @global array $wp_rest_additional_fields Holds registered fields, organized
69
- * by object type.
70
- *
71
- * @param string|array $object_type Object(s) the field is being registered
72
- * to, "post"|"term"|"comment" etc.
73
- * @param string $attribute The attribute name.
74
- * @param array $args {
75
- * Optional. An array of arguments used to handle the registered field.
76
- *
77
- * @type string|array|null $get_callback Optional. The callback function used to retrieve the field
78
- * value. Default is 'null', the field will not be returned in
79
- * the response.
80
- * @type string|array|null $update_callback Optional. The callback function used to set and update the
81
- * field value. Default is 'null', the value cannot be set or
82
- * updated.
83
- * @type string|array|null $schema Optional. The callback function used to create the schema for
84
- * this field. Default is 'null', no schema entry will be returned.
85
- * }
86
- */
87
- function register_api_field( $object_type, $attribute, $args = array() ) {
88
- $defaults = array(
89
- 'get_callback' => null,
90
- 'update_callback' => null,
91
- 'schema' => null,
92
- );
93
-
94
- $args = wp_parse_args( $args, $defaults );
95
-
96
- global $wp_rest_additional_fields;
97
-
98
- $object_types = (array) $object_type;
99
-
100
- foreach ( $object_types as $object_type ) {
101
- $wp_rest_additional_fields[ $object_type ][ $attribute ] = $args;
102
- }
103
  }
104
 
105
  /**
@@ -132,9 +93,10 @@ function rest_api_register_rewrites() {
132
  /**
133
  * Registers the default REST API filters.
134
  *
135
- * @since 4.4.0
 
136
  *
137
- * @internal This will live in default-filters.php
138
  */
139
  function rest_api_default_filters() {
140
  // Deprecated reporting.
@@ -255,7 +217,7 @@ function get_rest_url( $blog_id = null, $path = '/', $scheme = 'rest' ) {
255
  }
256
 
257
  if ( is_ssl() ) {
258
- // If the current host is the same as the REST URL host, force the REST URL scheme to HTTPS
259
  if ( $_SERVER['SERVER_NAME'] === parse_url( get_home_url( $blog_id ), PHP_URL_HOST ) ) {
260
  $url = set_url_scheme( $url, 'https' );
261
  }
@@ -361,8 +323,10 @@ function rest_ensure_response( $response ) {
361
  */
362
  function rest_handle_deprecated_function( $function, $replacement, $version ) {
363
  if ( ! empty( $replacement ) ) {
 
364
  $string = sprintf( __( '%1$s (since %2$s; use %3$s instead)' ), $function, $version, $replacement );
365
  } else {
 
366
  $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function, $version );
367
  }
368
 
@@ -380,8 +344,10 @@ function rest_handle_deprecated_function( $function, $replacement, $version ) {
380
  */
381
  function rest_handle_deprecated_argument( $function, $replacement, $version ) {
382
  if ( ! empty( $replacement ) ) {
 
383
  $string = sprintf( __( '%1$s (since %2$s; %3$s)' ), $function, $version, $replacement );
384
  } else {
 
385
  $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function, $version );
386
  }
387
 
@@ -526,7 +492,7 @@ function rest_output_link_wp_head() {
526
  return;
527
  }
528
 
529
- echo "<link rel='https://github.com/WP-API/WP-API' href='" . esc_url( $api_root ) . "' />\n";
530
  }
531
 
532
  /**
@@ -545,7 +511,7 @@ function rest_output_link_header() {
545
  return;
546
  }
547
 
548
- header( 'Link: <' . esc_url_raw( $api_root ) . '>; rel="https://github.com/WP-API/WP-API"', false );
549
  }
550
 
551
  /**
20
  * multiple methods. Default empty array.
21
  * @param bool $override Optional. If the route already exists, should we override it? True overrides,
22
  * false merges (with newer overriding if duplicate keys exist). Default false.
23
+ * @return bool True on success, false on error.
24
  */
25
  function register_rest_route( $namespace, $route, $args = array(), $override = false ) {
26
  /** @var WP_REST_Server $wp_rest_server */
27
  global $wp_rest_server;
28
 
29
+ if ( empty( $namespace ) ) {
30
+ /*
31
+ * Non-namespaced routes are not allowed, with the exception of the main
32
+ * and namespace indexes. If you really need to register a
33
+ * non-namespaced route, call `WP_REST_Server::register_route` directly.
34
+ */
35
+ _doing_it_wrong( 'register_rest_route', 'Routes must be namespaced with plugin or theme name and version.', '4.4.0' );
36
+ return false;
37
+ } else if ( empty( $route ) ) {
38
+ _doing_it_wrong( 'register_rest_route', 'Route must be specified.', '4.4.0' );
39
+ return false;
40
+ }
41
+
42
  if ( isset( $args['callback'] ) ) {
43
  // Upgrade a single set to multiple.
44
  $args = array( $args );
58
  $arg_group = array_merge( $defaults, $arg_group );
59
  }
60
 
61
+ $full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' );
 
 
 
 
 
 
 
 
 
 
 
 
62
  $wp_rest_server->register_route( $namespace, $full_route, $args, $override );
63
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  /**
93
  /**
94
  * Registers the default REST API filters.
95
  *
96
+ * Attached to the {@see 'rest_api_init'} action
97
+ * to make testing and disabling these filters easier.
98
  *
99
+ * @since 4.4.0
100
  */
101
  function rest_api_default_filters() {
102
  // Deprecated reporting.
217
  }
218
 
219
  if ( is_ssl() ) {
220
+ // If the current host is the same as the REST URL host, force the REST URL scheme to HTTPS.
221
  if ( $_SERVER['SERVER_NAME'] === parse_url( get_home_url( $blog_id ), PHP_URL_HOST ) ) {
222
  $url = set_url_scheme( $url, 'https' );
223
  }
323
  */
324
  function rest_handle_deprecated_function( $function, $replacement, $version ) {
325
  if ( ! empty( $replacement ) ) {
326
+ /* translators: 1: function name, 2: WordPress version number, 3: new function name */
327
  $string = sprintf( __( '%1$s (since %2$s; use %3$s instead)' ), $function, $version, $replacement );
328
  } else {
329
+ /* translators: 1: function name, 2: WordPress version number */
330
  $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function, $version );
331
  }
332
 
344
  */
345
  function rest_handle_deprecated_argument( $function, $replacement, $version ) {
346
  if ( ! empty( $replacement ) ) {
347
+ /* translators: 1: function name, 2: WordPress version number, 3: new argument name */
348
  $string = sprintf( __( '%1$s (since %2$s; %3$s)' ), $function, $version, $replacement );
349
  } else {
350
+ /* translators: 1: function name, 2: WordPress version number */
351
  $string = sprintf( __( '%1$s (since %2$s; no alternative available)' ), $function, $version );
352
  }
353
 
492
  return;
493
  }
494
 
495
+ echo "<link rel='https://api.w.org/' href='" . esc_url( $api_root ) . "' />\n";
496
  }
497
 
498
  /**
511
  return;
512
  }
513
 
514
+ header( 'Link: <' . esc_url_raw( $api_root ) . '>; rel="https://api.w.org/"', false );
515
  }
516
 
517
  /**
lib/endpoints/class-wp-rest-attachments-controller.php CHANGED
@@ -395,6 +395,8 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
395
  $overrides['action'] = 'wp_handle_mock_upload';
396
  }
397
 
 
 
398
  $file = wp_handle_upload( $files['file'], $overrides );
399
 
400
  if ( isset( $file['error'] ) ) {
395
  $overrides['action'] = 'wp_handle_mock_upload';
396
  }
397
 
398
+ /** Include admin functions to get access to wp_handle_upload() */
399
+ require_once ABSPATH . 'wp-admin/includes/admin.php';
400
  $file = wp_handle_upload( $files['file'], $overrides );
401
 
402
  if ( isset( $file['error'] ) ) {
lib/endpoints/class-wp-rest-posts-controller.php CHANGED
@@ -89,7 +89,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
89
  $args['paged'] = $request['page'];
90
  $args['posts_per_page'] = $request['per_page'];
91
 
92
- if ( isset( $request['filter'] ) ) {
93
  $args = array_merge( $args, $request['filter'] );
94
  unset( $args['filter'] );
95
  }
@@ -1212,7 +1212,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
1212
  // If we have a featured image, add that.
1213
  if ( $featured_image = get_post_thumbnail_id( $post->ID ) ) {
1214
  $image_url = rest_url( 'wp/v2/media/' . $featured_image );
1215
- $links['http://v2.wp-api.org/featuredmedia'] = array(
1216
  'href' => $image_url,
1217
  'embeddable' => true,
1218
  );
@@ -1220,14 +1220,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
1220
  if ( ! in_array( $post->post_type, array( 'attachment', 'nav_menu_item', 'revision' ) ) ) {
1221
  $attachments_url = rest_url( 'wp/v2/media' );
1222
  $attachments_url = add_query_arg( 'post_parent', $post->ID, $attachments_url );
1223
- $links['http://v2.wp-api.org/attachment'] = array(
1224
  'href' => $attachments_url,
1225
  );
1226
  }
1227
 
1228
  $taxonomies = get_object_taxonomies( $post->post_type );
1229
  if ( ! empty( $taxonomies ) ) {
1230
- $links['http://v2.wp-api.org/term'] = array();
1231
 
1232
  foreach ( $taxonomies as $tax ) {
1233
  $taxonomy_obj = get_taxonomy( $tax );
@@ -1239,7 +1239,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
1239
  $tax_base = ! empty( $taxonomy_obj->rest_base ) ? $taxonomy_obj->rest_base : $tax;
1240
  $terms_url = rest_url( trailingslashit( $base ) . $post->ID . '/terms/' . $tax_base );
1241
 
1242
- $links['http://v2.wp-api.org/term'][] = array(
1243
  'href' => $terms_url,
1244
  'taxonomy' => $tax,
1245
  'embeddable' => true,
@@ -1248,7 +1248,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
1248
  }
1249
 
1250
  if ( post_type_supports( $post->post_type, 'custom-fields' ) ) {
1251
- $links['http://v2.wp-api.org/meta'] = array(
1252
  'href' => rest_url( trailingslashit( $base ) . $post->ID . '/meta' ),
1253
  'embeddable' => true,
1254
  );
89
  $args['paged'] = $request['page'];
90
  $args['posts_per_page'] = $request['per_page'];
91
 
92
+ if ( is_array( $request['filter'] ) ) {
93
  $args = array_merge( $args, $request['filter'] );
94
  unset( $args['filter'] );
95
  }
1212
  // If we have a featured image, add that.
1213
  if ( $featured_image = get_post_thumbnail_id( $post->ID ) ) {
1214
  $image_url = rest_url( 'wp/v2/media/' . $featured_image );
1215
+ $links['http://api.w.org/featuredmedia'] = array(
1216
  'href' => $image_url,
1217
  'embeddable' => true,
1218
  );
1220
  if ( ! in_array( $post->post_type, array( 'attachment', 'nav_menu_item', 'revision' ) ) ) {
1221
  $attachments_url = rest_url( 'wp/v2/media' );
1222
  $attachments_url = add_query_arg( 'post_parent', $post->ID, $attachments_url );
1223
+ $links['http://api.w.org/attachment'] = array(
1224
  'href' => $attachments_url,
1225
  );
1226
  }
1227
 
1228
  $taxonomies = get_object_taxonomies( $post->post_type );
1229
  if ( ! empty( $taxonomies ) ) {
1230
+ $links['http://api.w.org/term'] = array();
1231
 
1232
  foreach ( $taxonomies as $tax ) {
1233
  $taxonomy_obj = get_taxonomy( $tax );
1239
  $tax_base = ! empty( $taxonomy_obj->rest_base ) ? $taxonomy_obj->rest_base : $tax;
1240
  $terms_url = rest_url( trailingslashit( $base ) . $post->ID . '/terms/' . $tax_base );
1241
 
1242
+ $links['http://api.w.org/term'][] = array(
1243
  'href' => $terms_url,
1244
  'taxonomy' => $tax,
1245
  'embeddable' => true,
1248
  }
1249
 
1250
  if ( post_type_supports( $post->post_type, 'custom-fields' ) ) {
1251
+ $links['http://api.w.org/meta'] = array(
1252
  'href' => rest_url( trailingslashit( $base ) . $post->ID . '/meta' ),
1253
  'embeddable' => true,
1254
  );
lib/endpoints/class-wp-rest-terms-controller.php CHANGED
@@ -640,6 +640,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
640
  $query_params['parent'] = array(
641
  'description' => 'Limit result set to terms assigned to a specific parent term.',
642
  'type' => 'integer',
 
643
  );
644
  }
645
  return $query_params;
640
  $query_params['parent'] = array(
641
  'description' => 'Limit result set to terms assigned to a specific parent term.',
642
  'type' => 'integer',
643
+ 'sanitize_callback' => 'absint',
644
  );
645
  }
646
  return $query_params;
plugin.php CHANGED
@@ -4,7 +4,7 @@
4
  * Description: JSON-based REST API for WordPress, developed as part of GSoC 2013.
5
  * Author: WP REST API Team
6
  * Author URI: http://wp-api.org
7
- * Version: 2.0-beta6
8
  * Plugin URI: https://github.com/WP-API/WP-API
9
  * License: GPL2+
10
  */
@@ -219,3 +219,45 @@ function create_initial_rest_routes() {
219
  $controller = new WP_REST_Comments_Controller;
220
  $controller->register_routes();
221
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  * Description: JSON-based REST API for WordPress, developed as part of GSoC 2013.
5
  * Author: WP REST API Team
6
  * Author URI: http://wp-api.org
7
+ * Version: 2.0-beta7
8
  * Plugin URI: https://github.com/WP-API/WP-API
9
  * License: GPL2+
10
  */
219
  $controller = new WP_REST_Comments_Controller;
220
  $controller->register_routes();
221
  }
222
+
223
+ if ( ! function_exists( 'register_api_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_api_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
+ }
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: rmccue, rachelbaker, danielbachhuber, joehoyle
3
  Tags: json, rest, api, rest-api
4
  Requires at least: 4.3
5
  Tested up to: 4.4
6
- Stable tag: 2.0-beta6
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -36,6 +36,37 @@ For full-flavoured API support, you'll need to be using pretty permalinks to use
36
 
37
  == Changelog ==
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  = 2.0 Beta 6.0 =
40
 
41
  * Remove global inclusion of wp-admin/includes/admin.php
3
  Tags: json, rest, api, rest-api
4
  Requires at least: 4.3
5
  Tested up to: 4.4
6
+ Stable tag: 2.0-beta7
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
36
 
37
  == Changelog ==
38
 
39
+ = 2.0 Beta 7.0 =
40
+
41
+ * Sync infrastructure from WordPress core as of r35691.
42
+
43
+ * Remove `register_api_field()` because it's conceptually tied to `WP_REST_Controller` [#34730](https://core.trac.wordpress.org/ticket/34730)
44
+ * Update the REST API header links to use api.w.org [#34303](https://core.trac.wordpress.org/ticket/34303)
45
+ * Require the `$namespace` argument in `register_rest_route()` [#34416](https://core.trac.wordpress.org/ticket/34416)
46
+ * Include `enum` and `description` in help data [#34543](https://core.trac.wordpress.org/ticket/34543)
47
+ * Save `preg_match` iterations in `WP_REST_Server` [#34488](https://core.trac.wordpress.org/ticket/34488)
48
+ * Don't return route URL in `WP_REST_Request:get_params()` [#34647](https://core.trac.wordpress.org/ticket/34647)
49
+
50
+ * Restore `register_api_field()` within the plugin.
51
+
52
+ (props @danielbachhuber, [#1748](https://github.com/WP-API/WP-API/pull/1748))
53
+
54
+ * Require admin functions for use of `wp_handle_upload()`, fixing fatal.
55
+
56
+ (props @joehoyle, [#1746](https://github.com/WP-API/WP-API/pull/1746))
57
+
58
+ * Properly handle requesting terms where `parent=0` and `0` is a string.
59
+
60
+ (props @danielbachhuber, [#1739](https://github.com/WP-API/WP-API/pull/1739))
61
+
62
+ * Prevent PHP error notice when `&filter` isn't an array.
63
+
64
+ (props @danielbachhuber, [#1734](https://github.com/WP-API/WP-API/pull/1734))
65
+
66
+ * Change link relations to use api.w.org.
67
+
68
+ (props @danielbachhuber, [#1726](https://github.com/WP-API/WP-API/pull/1726))
69
+
70
  = 2.0 Beta 6.0 =
71
 
72
  * Remove global inclusion of wp-admin/includes/admin.php