REST API: Include permalink_template/generated_slug for Posts

In order for clients to present permalink previews, the REST API must share the computed results of get_sample_permalink(). These two values are now exposed as permalink_template and generated_slug for public, viewable post types, but only for context=edit.

Merges [43720] to trunk.

Props danielbachhuber, rahulsprajapati.
Fixes #45017.


git-svn-id: https://develop.svn.wordpress.org/trunk@43980 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jeremy Felt 2018-12-12 02:11:22 +00:00
parent c0e80b028a
commit 894a8e02d2
5 changed files with 113 additions and 4 deletions

View File

@ -1587,6 +1587,23 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
} }
} }
$post_type_obj = get_post_type_object( $post->post_type );
if ( is_post_type_viewable( $post_type_obj ) && $post_type_obj->public ) {
if ( ! function_exists( 'get_sample_permalink' ) ) {
require_once ABSPATH . '/wp-admin/includes/post.php';
}
$sample_permalink = get_sample_permalink( $post->ID, $post->post_title, '' );
if ( in_array( 'permalink_template', $fields, true ) ) {
$data['permalink_template'] = $sample_permalink[0];
}
if ( in_array( 'generated_slug', $fields, true ) ) {
$data['generated_slug'] = $sample_permalink[1];
}
}
$context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context ); $data = $this->filter_response_by_context( $data, $context );
@ -1918,6 +1935,21 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
); );
$post_type_obj = get_post_type_object( $this->post_type ); $post_type_obj = get_post_type_object( $this->post_type );
if ( is_post_type_viewable( $post_type_obj ) && $post_type_obj->public ) {
$schema['properties']['permalink_template'] = array(
'description' => __( 'Permalink template for the object.' ),
'type' => 'string',
'context' => array( 'edit' ),
'readonly' => true,
);
$schema['properties']['generated_slug'] = array(
'description' => __( 'Slug automatically generated from the object title.' ),
'type' => 'string',
'context' => array( 'edit' ),
'readonly' => true,
);
}
if ( $post_type_obj->hierarchical ) { if ( $post_type_obj->hierarchical ) {
$schema['properties']['parent'] = array( $schema['properties']['parent'] = array(

View File

@ -40,7 +40,7 @@ abstract class WP_Test_REST_Controller_Testcase extends WP_Test_REST_TestCase {
abstract public function test_get_item_schema(); abstract public function test_get_item_schema();
public function filter_rest_url_for_leading_slash( $url, $path ) { public function filter_rest_url_for_leading_slash( $url, $path ) {
if ( is_multisite() ) { if ( is_multisite() || get_option( 'permalink_structure' ) ) {
return $url; return $url;
} }

View File

@ -1295,7 +1295,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$response = rest_get_server()->dispatch( $request ); $response = rest_get_server()->dispatch( $request );
$data = $response->get_data(); $data = $response->get_data();
$properties = $data['schema']['properties']; $properties = $data['schema']['properties'];
$this->assertEquals( 24, count( $properties ) ); $this->assertEquals( 26, count( $properties ) );
$this->assertArrayHasKey( 'author', $properties ); $this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'alt_text', $properties ); $this->assertArrayHasKey( 'alt_text', $properties );
$this->assertArrayHasKey( 'caption', $properties ); $this->assertArrayHasKey( 'caption', $properties );
@ -1307,6 +1307,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$this->assertArrayHasKey( 'comment_status', $properties ); $this->assertArrayHasKey( 'comment_status', $properties );
$this->assertArrayHasKey( 'date', $properties ); $this->assertArrayHasKey( 'date', $properties );
$this->assertArrayHasKey( 'date_gmt', $properties ); $this->assertArrayHasKey( 'date_gmt', $properties );
$this->assertArrayHasKey( 'generated_slug', $properties );
$this->assertArrayHasKey( 'guid', $properties ); $this->assertArrayHasKey( 'guid', $properties );
$this->assertArrayHasKey( 'id', $properties ); $this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'link', $properties ); $this->assertArrayHasKey( 'link', $properties );
@ -1318,6 +1319,7 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
$this->assertArrayHasKey( 'modified_gmt', $properties ); $this->assertArrayHasKey( 'modified_gmt', $properties );
$this->assertArrayHasKey( 'post', $properties ); $this->assertArrayHasKey( 'post', $properties );
$this->assertArrayHasKey( 'ping_status', $properties ); $this->assertArrayHasKey( 'ping_status', $properties );
$this->assertArrayHasKey( 'permalink_template', $properties );
$this->assertArrayHasKey( 'status', $properties ); $this->assertArrayHasKey( 'status', $properties );
$this->assertArrayHasKey( 'slug', $properties ); $this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'source_url', $properties ); $this->assertArrayHasKey( 'source_url', $properties );

View File

@ -678,12 +678,13 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te
$response = rest_get_server()->dispatch( $request ); $response = rest_get_server()->dispatch( $request );
$data = $response->get_data(); $data = $response->get_data();
$properties = $data['schema']['properties']; $properties = $data['schema']['properties'];
$this->assertEquals( 22, count( $properties ) ); $this->assertEquals( 24, count( $properties ) );
$this->assertArrayHasKey( 'author', $properties ); $this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'comment_status', $properties ); $this->assertArrayHasKey( 'comment_status', $properties );
$this->assertArrayHasKey( 'content', $properties ); $this->assertArrayHasKey( 'content', $properties );
$this->assertArrayHasKey( 'date', $properties ); $this->assertArrayHasKey( 'date', $properties );
$this->assertArrayHasKey( 'date_gmt', $properties ); $this->assertArrayHasKey( 'date_gmt', $properties );
$this->assertArrayHasKey( 'generated_slug', $properties );
$this->assertArrayHasKey( 'guid', $properties ); $this->assertArrayHasKey( 'guid', $properties );
$this->assertArrayHasKey( 'excerpt', $properties ); $this->assertArrayHasKey( 'excerpt', $properties );
$this->assertArrayHasKey( 'featured_media', $properties ); $this->assertArrayHasKey( 'featured_media', $properties );
@ -695,6 +696,7 @@ class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertArrayHasKey( 'modified_gmt', $properties ); $this->assertArrayHasKey( 'modified_gmt', $properties );
$this->assertArrayHasKey( 'parent', $properties ); $this->assertArrayHasKey( 'parent', $properties );
$this->assertArrayHasKey( 'password', $properties ); $this->assertArrayHasKey( 'password', $properties );
$this->assertArrayHasKey( 'permalink_template', $properties );
$this->assertArrayHasKey( 'ping_status', $properties ); $this->assertArrayHasKey( 'ping_status', $properties );
$this->assertArrayHasKey( 'slug', $properties ); $this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'status', $properties ); $this->assertArrayHasKey( 'status', $properties );

View File

@ -3479,7 +3479,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$response = rest_get_server()->dispatch( $request ); $response = rest_get_server()->dispatch( $request );
$data = $response->get_data(); $data = $response->get_data();
$properties = $data['schema']['properties']; $properties = $data['schema']['properties'];
$this->assertEquals( 24, count( $properties ) ); $this->assertEquals( 26, count( $properties ) );
$this->assertArrayHasKey( 'author', $properties ); $this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'comment_status', $properties ); $this->assertArrayHasKey( 'comment_status', $properties );
$this->assertArrayHasKey( 'content', $properties ); $this->assertArrayHasKey( 'content', $properties );
@ -3487,6 +3487,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertArrayHasKey( 'date_gmt', $properties ); $this->assertArrayHasKey( 'date_gmt', $properties );
$this->assertArrayHasKey( 'excerpt', $properties ); $this->assertArrayHasKey( 'excerpt', $properties );
$this->assertArrayHasKey( 'featured_media', $properties ); $this->assertArrayHasKey( 'featured_media', $properties );
$this->assertArrayHasKey( 'generated_slug', $properties );
$this->assertArrayHasKey( 'guid', $properties ); $this->assertArrayHasKey( 'guid', $properties );
$this->assertArrayHasKey( 'format', $properties ); $this->assertArrayHasKey( 'format', $properties );
$this->assertArrayHasKey( 'id', $properties ); $this->assertArrayHasKey( 'id', $properties );
@ -3495,6 +3496,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertArrayHasKey( 'modified', $properties ); $this->assertArrayHasKey( 'modified', $properties );
$this->assertArrayHasKey( 'modified_gmt', $properties ); $this->assertArrayHasKey( 'modified_gmt', $properties );
$this->assertArrayHasKey( 'password', $properties ); $this->assertArrayHasKey( 'password', $properties );
$this->assertArrayHasKey( 'permalink_template', $properties );
$this->assertArrayHasKey( 'ping_status', $properties ); $this->assertArrayHasKey( 'ping_status', $properties );
$this->assertArrayHasKey( 'slug', $properties ); $this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'status', $properties ); $this->assertArrayHasKey( 'status', $properties );
@ -3564,6 +3566,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
'excerpt', 'excerpt',
'featured_media', 'featured_media',
'format', 'format',
'generated_slug',
'guid', 'guid',
'id', 'id',
'link', 'link',
@ -3571,6 +3574,7 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
'modified', 'modified',
'modified_gmt', 'modified_gmt',
'password', 'password',
'permalink_template',
'ping_status', 'ping_status',
'slug', 'slug',
'status', 'status',
@ -4086,7 +4090,76 @@ class WP_Test_REST_Posts_Controller extends WP_Test_REST_Post_Type_Controller_Te
$this->assertArrayNotHasKey( 'https://api.w.org/action-unfiltered-html', $links ); $this->assertArrayNotHasKey( 'https://api.w.org/action-unfiltered-html', $links );
} }
public function test_generated_permalink_template_generated_slug_for_non_viewable_posts() {
register_post_type(
'private-post',
array(
'label' => 'Private Posts',
'supports' => array( 'title', 'editor', 'author' ),
'show_in_rest' => true,
'publicly_queryable' => false,
'public' => true,
'rest_base' => 'private-post',
)
);
create_initial_rest_routes();
wp_set_current_user( self::$editor_id );
$post_id = $this->factory->post->create(
array(
'post_title' => 'Permalink Template',
'post_type' => 'private-post',
'post_status' => 'draft',
)
);
// Neither 'permalink_template' and 'generated_slug' are expected for this post type.
$request = new WP_REST_Request( 'GET', '/wp/v2/private-post/' . $post_id );
$request->set_param( 'context', 'edit' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertArrayNotHasKey( 'permalink_template', $data );
$this->assertArrayNotHasKey( 'generated_slug', $data );
}
public function test_generated_permalink_template_generated_slug_for_posts() {
$this->set_permalink_structure( '/%postname%/' );
$expected_permalink_template = trailingslashit( home_url( '/%postname%/' ) );
wp_set_current_user( self::$editor_id );
$post_id = $this->factory->post->create(
array(
'post_title' => 'Permalink Template',
'post_type' => 'post',
'post_status' => 'draft',
)
);
// Both 'permalink_template' and 'generated_slug' are expected for context=edit.
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id );
$request->set_param( 'context', 'edit' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( $expected_permalink_template, $data['permalink_template'] );
$this->assertEquals( 'permalink-template', $data['generated_slug'] );
// Neither 'permalink_template' and 'generated_slug' are expected for context=view.
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $post_id );
$request->set_param( 'context', 'view' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertArrayNotHasKey( 'permalink_template', $data );
$this->assertArrayNotHasKey( 'generated_slug', $data );
}
public function tearDown() { public function tearDown() {
_unregister_post_type( 'private-post' );
_unregister_post_type( 'youseeeme' ); _unregister_post_type( 'youseeeme' );
if ( isset( $this->attachment_id ) ) { if ( isset( $this->attachment_id ) ) {
$this->remove_added_uploads(); $this->remove_added_uploads();