Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,30 @@ public function create_post_autosave( $post_data, array $meta = array() ) {
// Check if meta values have changed.
if ( ! empty( $meta ) ) {
$revisioned_meta_keys = wp_post_revision_meta_keys( $post->post_type );
$registered_meta = array_merge(
get_registered_meta_keys( 'post' ),
get_registered_meta_keys( 'post', $post->post_type )
);

/*
* Meta keys registered with 'single' => false store each of their values in a
* separate row, so they must be read, compared, and stored as a list of values.
* Keys without a registration are treated as single, matching previous behavior.
*/
$is_single_meta = array();

foreach ( $revisioned_meta_keys as $meta_key ) {
$is_single_meta[ $meta_key ] = ! isset( $registered_meta[ $meta_key ]['single'] ) || $registered_meta[ $meta_key ]['single'];
}

foreach ( $revisioned_meta_keys as $meta_key ) {
// get_metadata_raw is used to avoid retrieving the default value.
$old_meta = get_metadata_raw( 'post', $post_id, $meta_key, true );
$new_meta = $meta[ $meta_key ] ?? '';
$old_meta = get_metadata_raw( 'post', $post_id, $meta_key, $is_single_meta[ $meta_key ] );
$new_meta = $meta[ $meta_key ] ?? ( $is_single_meta[ $meta_key ] ? '' : array() );

if ( ! $is_single_meta[ $meta_key ] && null === $old_meta ) {
$old_meta = array();
}

if ( $new_meta !== $old_meta ) {
$autosave_is_different = true;
Expand Down Expand Up @@ -441,8 +461,23 @@ public function create_post_autosave( $post_data, array $meta = array() ) {
// Attached any passed meta values that have revisions enabled.
if ( ! empty( $meta ) ) {
foreach ( $revisioned_meta_keys as $meta_key ) {
if ( isset( $meta[ $meta_key ] ) ) {
if ( ! isset( $meta[ $meta_key ] ) ) {
continue;
}

if ( $is_single_meta[ $meta_key ] ) {
update_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta[ $meta_key ] ) );
continue;
}

/*
* update_metadata() would overwrite every row sharing the meta key with the
* same value, so replace the stored values instead, as _wp_copy_post_meta() does.
*/
delete_metadata( 'post', $revision_id, $meta_key );

foreach ( (array) $meta[ $meta_key ] as $meta_value ) {
add_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta_value ) );
}
}
}
Expand Down
58 changes: 58 additions & 0 deletions tests/phpunit/tests/rest-api/rest-autosaves-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,64 @@ public function test_update_item_with_json_meta() {
$this->assertNotNull( $values );
}

/**
* @ticket 65754
*/
public function test_update_item_with_multiple_value_meta() {
wp_set_current_user( self::$editor_id );

register_post_meta(
'post',
'foo_multi',
array(
'show_in_rest' => true,
'revisions_enabled' => true,
'single' => false,
'type' => 'string',
)
);

$post_id = self::factory()->post->create(
array(
'post_content' => 'Original content.',
'post_author' => self::$editor_id,
)
);

add_post_meta( $post_id, 'foo_multi', 'bar' );
add_post_meta( $post_id, 'foo_multi', 'baz' );

$request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . $post_id . '/autosaves' );
$request->add_header( 'Content-Type', 'application/x-www-form-urlencoded' );
$request->set_body_params(
$this->set_post_data(
array(
'id' => $post_id,
'content' => 'Autosaved content.',
'meta' => array(
'foo_multi' => array( 'bar', 'qux' ),
),
)
)
);

$response = rest_get_server()->dispatch( $request );
$this->check_create_autosave_response( $response );

$data = $response->get_data();

$this->assertSame(
array( 'bar', 'qux' ),
get_post_meta( $data['id'], 'foo_multi' ),
'The autosave revision should store each meta value in its own row.'
);
$this->assertSame(
array( 'bar', 'qux' ),
$data['meta']['foo_multi'],
'The response should return the autosaved meta values.'
);
}

public function test_update_item_nopriv() {
wp_set_current_user( self::$contributor_id );

Expand Down
Loading