diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index a04de73bd64e4..74504e013238c 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -1660,7 +1660,9 @@ function wp_ajax_add_meta() { $meta_id = add_meta( $post_id ); - if ( ! $meta_id ) { + if ( is_wp_error( $meta_id ) ) { + wp_die( $meta_id->get_error_message() ); + } elseif ( ! $meta_id ) { wp_die( __( 'Please provide a custom field value.' ) ); } } else { @@ -1669,7 +1671,9 @@ function wp_ajax_add_meta() { } else { $meta_id = add_meta( $post_id ); - if ( ! $meta_id ) { + if ( is_wp_error( $meta_id ) ) { + wp_die( $meta_id->get_error_message() ); + } elseif ( ! $meta_id ) { wp_die( __( 'Please provide a custom field value.' ) ); } } @@ -1707,7 +1711,7 @@ function wp_ajax_add_meta() { ! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) || ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) ) { - wp_die( -1 ); + wp_die( __( 'Sorry, you are not allowed to edit this custom field.' ) ); } if ( $meta->meta_value !== $value || $meta->meta_key !== $key ) { diff --git a/src/wp-admin/includes/post.php b/src/wp-admin/includes/post.php index 39d267b623037..b7fd3d4a5d6f6 100644 --- a/src/wp-admin/includes/post.php +++ b/src/wp-admin/includes/post.php @@ -1001,9 +1001,12 @@ function write_post() { * Adds post meta data defined in the `$_POST` superglobal for a post with given ID. * * @since 1.2.0 + * @since 7.1.0 Returns a WP_Error object when the meta key is protected or the user + * does not have the capability to add post meta. * * @param int $post_id - * @return int|bool + * @return int|bool|WP_Error Meta ID on success, false if no key/value pair was provided, + * WP_Error if the meta key is protected or the user lacks capability. */ function add_meta( $post_id ) { $post_id = (int) $post_id; @@ -1029,7 +1032,10 @@ function add_meta( $post_id ) { } if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_id, $metakey ) ) { - return false; + return new WP_Error( + 'protected_meta', + __( 'Sorry, you are not allowed to add this custom field.' ) + ); } $metakey = wp_slash( $metakey ); diff --git a/tests/phpunit/tests/admin/includesPost.php b/tests/phpunit/tests/admin/includesPost.php index d9d39d8da727d..1e6f10cd12640 100644 --- a/tests/phpunit/tests/admin/includesPost.php +++ b/tests/phpunit/tests/admin/includesPost.php @@ -1163,6 +1163,65 @@ public function test_add_meta_allows_empty_values() { $this->assertSame( '', get_post_meta( $p, 'testkey', true ) ); } + /** + * Data provider for test_add_meta_authorization. + * + * @return array[] + */ + public function data_add_meta_authorization() { + return array( + 'has capability, unprotected metakey' => array( + 'metakey' => 'ordinary_key', + 'role' => 'administrator', + 'expected_error' => false, + ), + 'no capability, unprotected metakey' => array( + 'metakey' => 'ordinary_key', + 'role' => 'subscriber', + 'expected_error' => true, + ), + 'has capability, protected metakey' => array( + 'metakey' => '_protected_testkey', + 'role' => 'administrator', + 'expected_error' => true, + ), + 'no capability, protected metakey' => array( + 'metakey' => '_protected_testkey', + 'role' => 'subscriber', + 'expected_error' => true, + ), + ); + } + + /** + * @ticket 32565 + * + * @covers ::add_meta + * + * @dataProvider data_add_meta_authorization + */ + public function test_add_meta_authorization( string $metakey, string $role, bool $expected_error ) { + $post_id = self::factory()->post->create(); + $user_id = 'administrator' === $role ? self::$admin_id : self::factory()->user->create( array( 'role' => $role ) ); + + $_POST = array( + 'metakeyinput' => $metakey, + 'metavalue' => 'test_value', + ); + + wp_set_current_user( $user_id ); + + $result = add_meta( $post_id ); + + if ( $expected_error ) { + $this->assertWPError( $result ); + $this->assertSame( 'protected_meta', $result->get_error_code() ); + } else { + $this->assertIsInt( $result ); + $this->assertSame( 'test_value', get_post_meta( $post_id, $metakey, true ) ); + } + } + /** * Test the post type support in post_exists(). *