[wp-trac] [WordPress Trac] #55600: Can't save registered post meta field of type string that equals registered default value via REST API

WordPress Trac noreply at wordpress.org
Thu Apr 21 13:47:24 UTC 2022


#55600: Can't save registered post meta field of type string that equals registered
default value via REST API
--------------------------------+-----------------------------
 Reporter:  kraftner            |      Owner:  (none)
     Type:  defect (bug)        |     Status:  new
 Priority:  normal              |  Milestone:  Awaiting Review
Component:  Options, Meta APIs  |    Version:
 Severity:  normal              |   Keywords:
  Focuses:  rest-api            |
--------------------------------+-----------------------------
 == Current behaviour

 Currently if you register a post meta key as string and set a default
 value:

 {{{
 register_post_meta(
   'my_cpt,
   'my_meta',
   [
     'show_in_rest' => true,
     'single' => true,
     'type' => 'string',
     'default' => 'foo'
   ]
 );
 }}}

 and then save the default value it is not actually being written to the
 database.

 If you save any other type, e.g. a boolean


 {{{
 register_post_meta(
   'my_cpt,
   'my_meta',
   [
     'show_in_rest' => true,
     'single' => true,
     'type' => 'boolean',
     'default' => true
   ]
 );
 }}}

 it is being written to the database.

 Also not saving via the REST API, but via `update_metadata()` works for
 strings.

 == What seems to happen

 The problem seems to happen like this:

 - Post meta is only saved if it differs from the currently stored value.
 - So before saving each field the new value is compared with the stored
 value.
 - When doing so the assumption is (rightfully) that all stored data is a
 string since that is how post meta is stored in the DB.
 - If the key doesn't exist though, the comparison happens with the default
 value.
 - The default value though isn't necessarily a string, but is handled as
 such in the strict equality check.
 - So the strict equality check fails on anything but a string field.

 **-> String fields can't save the default value, anything else can.**

 == How did it come to this?

 I am not absolutely sure what is actually the intended behavior, but I
 assume if there is nothing stored in the DB the value should be saved,
 even if it equals the default.

 I assume this because the behavior of `update_metadata()`
 [https://core.trac.wordpress.org/changeset/48402 got changed] to only
 consider DB data, not default values for the comparison by retrieving the
 stored data using `get_metadata_raw()` instead of `get_metadata()`.

 `WP_REST_Meta_Fields` duplicates some of the checks in `update_metadata()`
 ([https://github.com/WordPress/wordpress-
 develop/blob/14d9ca8da64688f799695eb9683e6ac8166cd4ee/src/wp-includes
 /rest-api/fields/class-wp-rest-meta-fields.php#L382 even explicitly states
 that in a comment]) but `WP_REST_Meta_Fields::update_meta_value()` (and
 some other places in that class) didn't get the change to use
 `get_metadata_raw()` instead of `get_metadata()`.

 I assume this got overlooked when introducing the default metadata values
 in https://core.trac.wordpress.org/changeset/48402

 It seems that replacing get_metadata with get_metadata_raw in that class
 should fix the issue, but I haven't found time yet to prepare a patch, so
 I thought I'd at least document the issue for now to see if someone else
 finds time for a fix before me.

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


More information about the wp-trac mailing list