[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