Make WordPress Core

Opened 3 years ago

Last modified 3 years ago

#53942 assigned defect (bug)

Non-single post meta multiple value update breaks post save through REST API

Reported by: iknowsomething's profile iknowsomething Owned by:
Milestone: Awaiting Review Priority: normal
Severity: blocker Version: 5.8
Component: REST API Keywords: needs-patch
Focuses: rest-api Cc:

Description

This is a follow-up to #52787.

Same situation as in #52787, but this time while updating non-single meta multiple values at once like { meta: { metaKey: [1, 2, 3] } }, REST API fires update_multi_meta_value(), which tries first to delete old values in the database. When no meta value is present in database, get_metadata() returns defaults as $current_values and then trying to delete them anyway (non-existent in fact). This causes update_multi_meta_value() to return WP_Error('rest_meta_database_error') on delete_metadata() failure.

BTW, error messages could be more specific from 'Could not update the meta value of %s in database.' to 'Could not update/delete...' and 'Could not update/add...'.

Change History (1)

#1 @iknowsomething
3 years ago

Temporary workaround could use short-circuit filter in delete_metadata() and might look like this:

<?php
$meta_type = 'post';
add_filter( "delete_{$meta_type}_metadata", 'skip_delete', 10, 3);

function skip_delete( $delete, $object_id, $meta_key ) {
    // If it's not about this meta, forward previous hook result
    if ( 'my_meta_key' != $meta_key ) {
        return $delete;
    }

    // Skip delete if meta doesn't exist in database
    $current_meta_value = get_metadata_raw( $meta_type = 'post', $object_id, wp_slash( $meta_key ) );
    if ( null === $current_meta_value ) {
        return true;
    }

    // Do not skip on all other cases
    return null;
}
Last edited 3 years ago by iknowsomething (previous) (diff)
Note: See TracTickets for help on using tickets.