[wp-trac] [WordPress Trac] #40889: REST API: New terms creation with meta causes PHP Notice

WordPress Trac noreply at wordpress.org
Tue May 30 23:29:08 UTC 2017


#40889: REST API: New terms creation with meta causes PHP Notice
--------------------------+-----------------------------
 Reporter:  caercam       |      Owner:
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  REST API      |    Version:  4.7
 Severity:  normal        |   Keywords:
  Focuses:  rest-api      |
--------------------------+-----------------------------
 Creating new terms with the REST API works fine, as long as there is no
 meta attached:

 {{{
 POST https://localhost:8080/wp-json/wp/v2/categories
 X-WP-Nonce: 1234567890
 Content-Type: application/json
 {"name":"A new category","description":"This is a new
 category.","meta":{"custom_meta":"Custom Meta Value"}}
  -- response --
 403 Forbidden

 <br />
 <b>Notice</b>:  Undefined property: WP_Error::$taxonomy in
 <b>/var/www/wp47/wp-includes/capabilities.php</b> on line <b>282</b><br />
 {"code":"rest_cannot_update","message":"Sorry, you are not allowed to edit
 the custom_meta custom field.","data":{"key":"custom_meta","status":403}}
 }}}

 For the record, here's what happens as far as I can tell. Probably more
 detailled than what's really needed, but there's two different issues here
 so I'd rather be precise.

 1. `WP_REST_Terms_Controller::create_item()` calls
 `WP_REST_Meta_Fields::update_value()` with two arguments:
 `$request['meta']`, which is what we want, and `$request['id']`, which at
 this point is `null`, because we are creating a new term, not editing an
 existing one.
 2. `WP_REST_Meta_Fields::update_value()` loops through the registered meta
 keys and calls `WP_REST_Meta_Fields::update_meta_value()` or
 `WP_REST_Meta_Fields::update_multi_meta_value()`.
 3. Because `WP_REST_Terms_Controller::create_item()` casted as integer an
 ID that does not exist, both meta_value update methods get a `$object_id`
 = `0`, and use that value to check for permission to edit meta.
 4. Now it's capabilities fairy: `current_user_can()` calls
 `WP_User::has_cap()` which calls `map_meta_cap()` which checks for the
 term existence with a simple boolean test on the result of `get_term()`.
 5. But, because of `$object_id` value being `0`, `get_term()` returns a
 `WP_Error` instance, the check mentionned in 4. fails, and we get the
 "Undefined property" notice that end up in the REST API request response.

 TL;DR: Two issues here:
 1. `WP_REST_Terms_Controller::create_item()` passes an unexisting value to
 the meta_value upate methods, indirectly triggering a bug in
 `map_meta_cap()`;
 2. `map_meta_cap()` does not break as it should if `get_term()` returns an
 error.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/40889>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list