REST API: Support meta registration for specific object subtypes.

Introduce an `object_subtype` argument to the args array for `register_meta()` which can be used to limit meta registration to a single subtype (e.g. a custom post type or taxonomy, vs all posts or taxonomies).

Introduce `register_post_meta()` and `register_term_meta()` wrapper methods for `register_meta` to provide a convenient interface for the common case of registering meta for a specific taxonomy or post type. These methods work the way plugin developers have often expected `register_meta` to function, and should be used in place of direct `register_meta` where possible.

Props flixos90, tharsheblows, spacedmonkey.
Fixes #38323.



git-svn-id: https://develop.svn.wordpress.org/trunk@43378 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
K. Adam White
2018-06-21 21:06:50 +00:00
parent cdd9910f01
commit a830dbcab3
14 changed files with 1042 additions and 164 deletions
+230 -24
View File
@@ -3,10 +3,24 @@
* @group meta
*/
class Tests_Meta_Register_Meta extends WP_UnitTestCase {
protected static $post_id;
protected static $term_id;
protected static $comment_id;
protected static $user_id;
public static function wpSetUpBeforeClass( $factory ) {
self::$post_id = $factory->post->create();
self::$post_id = $factory->post->create( array( 'post_type' => 'page' ) );
self::$term_id = $factory->term->create( array( 'taxonomy' => 'category' ) );
self::$comment_id = $factory->comment->create();
self::$user_id = $factory->user->create();
}
public static function wpTearDownAfterClass() {
wp_delete_post( self::$post_id, true );
wp_delete_term( self::$term_id, 'category' );
wp_delete_comment( self::$comment_id, true );
self::delete_user( self::$user_id );
}
public function _old_sanitize_meta_cb( $meta_value, $meta_key, $meta_type ) {
@@ -74,18 +88,20 @@ class Tests_Meta_Register_Meta extends WP_UnitTestCase {
$expected = array(
'post' => array(
'flight_number' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => null,
'auth_callback' => '__return_true',
'show_in_rest' => false,
'' => array(
'flight_number' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => null,
'auth_callback' => '__return_true',
'show_in_rest' => false,
),
),
),
);
$this->assertEquals( $actual, $expected );
$this->assertEquals( $expected, $actual );
}
public function test_register_meta_with_term_object_type_populates_wp_meta_keys() {
@@ -96,18 +112,20 @@ class Tests_Meta_Register_Meta extends WP_UnitTestCase {
$expected = array(
'term' => array(
'category_icon' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => null,
'auth_callback' => '__return_true',
'show_in_rest' => false,
'' => array(
'category_icon' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => null,
'auth_callback' => '__return_true',
'show_in_rest' => false,
),
),
),
);
$this->assertEquals( $actual, $expected );
$this->assertEquals( $expected, $actual );
}
public function test_register_meta_with_deprecated_sanitize_callback_does_not_populate_wp_meta_keys() {
@@ -148,13 +166,15 @@ class Tests_Meta_Register_Meta extends WP_UnitTestCase {
$expected = array(
'post' => array(
'flight_number' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ),
'auth_callback' => '__return_true',
'show_in_rest' => false,
'' => array(
'flight_number' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ),
'auth_callback' => '__return_true',
'show_in_rest' => false,
),
),
),
);
@@ -301,4 +321,190 @@ class Tests_Meta_Register_Meta extends WP_UnitTestCase {
$this->assertEmpty( $meta );
}
/**
* @ticket 38323
* @dataProvider data_get_types_and_subtypes
*/
public function test_register_meta_with_subtype_populates_wp_meta_keys( $type, $subtype ) {
global $wp_meta_keys;
register_meta( $type, 'flight_number', array( 'object_subtype' => $subtype ) );
$expected = array(
$type => array(
$subtype => array(
'flight_number' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => null,
'auth_callback' => '__return_true',
'show_in_rest' => false,
),
),
),
);
$actual = $wp_meta_keys;
// Reset global so subsequent data tests do not get polluted.
$wp_meta_keys = array();
$this->assertEquals( $expected, $actual );
}
/**
* @ticket 38323
* @dataProvider data_get_types_and_subtypes
*/
public function test_unregister_meta_with_subtype_unpopulates_wp_meta_keys( $type, $subtype ) {
global $wp_meta_keys;
register_meta( $type, 'flight_number', array( 'object_subtype' => $subtype ) );
unregister_meta_key( $type, 'flight_number', $subtype );
$actual = $wp_meta_keys;
// Reset global so subsequent data tests do not get polluted.
$wp_meta_keys = array();
$this->assertEmpty( $actual );
}
/**
* @ticket 38323
* @dataProvider data_get_types_and_subtypes
*/
public function test_unregister_meta_without_subtype_keeps_subtype_meta_key( $type, $subtype ) {
global $wp_meta_keys;
register_meta( $type, 'flight_number', array( 'object_subtype' => $subtype ) );
// Unregister meta key without subtype.
unregister_meta_key( $type, 'flight_number' );
$expected = array(
$type => array(
$subtype => array(
'flight_number' => array(
'type' => 'string',
'description' => '',
'single' => false,
'sanitize_callback' => null,
'auth_callback' => '__return_true',
'show_in_rest' => false,
),
),
),
);
$actual = $wp_meta_keys;
// Reset global so subsequent data tests do not get polluted.
$wp_meta_keys = array();
$this->assertEquals( $expected, $actual );
}
/**
* @ticket 38323
* @dataProvider data_get_types_and_subtypes
*/
public function test_get_registered_meta_keys_with_subtype( $type, $subtype ) {
register_meta( $type, 'registered_key1', array( 'object_subtype' => $subtype ) );
register_meta( $type, 'registered_key2', array( 'object_subtype' => $subtype ) );
$meta_keys = get_registered_meta_keys( $type, $subtype );
$this->assertArrayHasKey( 'registered_key1', $meta_keys );
$this->assertArrayHasKey( 'registered_key2', $meta_keys );
$this->assertEmpty( get_registered_meta_keys( $type ) );
}
/**
* @ticket 38323
* @dataProvider data_get_types_and_subtypes
*/
public function test_get_registered_metadata_with_subtype( $type, $subtype ) {
register_meta( $type, 'registered_key1', array() );
// This will override the above registration for objects of $subtype.
register_meta( $type, 'registered_key1', array(
'object_subtype' => $subtype,
'single' => true,
) );
// For testing with $single => false.
register_meta( $type, 'registered_key2', array(
'object_subtype' => $subtype,
) );
// Register another meta key for a different subtype.
register_meta( $type, 'registered_key3', array(
'object_subtype' => 'other_subtype',
) );
$object_property_name = $type . '_id';
$object_id = self::$$object_property_name;
add_metadata( $type, $object_id, 'registered_key1', 'value1' );
add_metadata( $type, $object_id, 'registered_key2', 'value2' );
add_metadata( $type, $object_id, 'registered_key3', 'value3' );
$meta = get_registered_metadata( $type, $object_id );
$key1 = get_registered_metadata( $type, $object_id, 'registered_key1' );
$key2 = get_registered_metadata( $type, $object_id, 'registered_key2' );
$key3 = get_registered_metadata( $type, $object_id, 'registered_key3' );
$this->assertSame( array( 'registered_key1', 'registered_key2' ), array_keys( $meta ) );
$this->assertSame( 'value1', $meta['registered_key1'][0] );
$this->assertSame( 'value2', $meta['registered_key2'][0] );
$this->assertSame( 'value1', $key1 );
$this->assertSame( array( 'value2' ), $key2 );
$this->assertFalse( $key3 );
}
/**
* @ticket 38323
* @dataProvider data_get_types_and_subtypes
*/
public function test_get_object_subtype( $type, $expected_subtype ) {
$object_property_name = $type . '_id';
$object_id = self::$$object_property_name;
$this->assertSame( $expected_subtype, get_object_subtype( $type, $object_id ) );
}
/**
* @ticket 38323
*/
public function test_get_object_subtype_custom() {
add_filter( 'get_object_subtype_customtype', array( $this, 'filter_get_object_subtype_for_customtype' ), 10, 2 );
$subtype_for_3 = get_object_subtype( 'customtype', 3 );
$subtype_for_4 = get_object_subtype( 'customtype', 4 );
$this->assertSame( 'odd', $subtype_for_3 );
$this->assertSame( 'even', $subtype_for_4 );
}
public function filter_get_object_subtype_for_customtype( $subtype, $object_id ) {
if ( $object_id % 2 === 1 ) {
return 'odd';
}
return 'even';
}
public function data_get_types_and_subtypes() {
return array(
array( 'post', 'page' ),
array( 'term', 'category' ),
array( 'comment', 'comment' ),
array( 'user', 'user' ),
);
}
}