Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Templates API: return post modified datetime in response #51362

Merged
merged 10 commits into from
Jun 15, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public function get_template_fallback( $request ) {
/**
* Add revisions to the response.
*
* @since 6.3.0 Added prepare_revision_links() method to get revision links.
*
* @param WP_Block_Template $item Template instance.
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response Response object.
Expand Down Expand Up @@ -98,7 +100,7 @@ public function prepare_item_for_response( $item, $request ) { // phpcs:ignore V
/**
* Adds revisions to links.
*
* @since 6.2.0
* @since 6.3.0
*
* @param WP_Block_Template $template Template instance.
* @return array Links for the given post.
Expand Down
31 changes: 31 additions & 0 deletions lib/compat/wordpress-6.3/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,34 @@ function gutenberg_update_global_styles_rest_controller( $args, $post_type ) {
return $args;
}
add_filter( 'register_post_type_args', 'gutenberg_update_global_styles_rest_controller', 10, 2 );

/**
* Add the `modified` value to the `wp_template` schema.
*
* @since 6.3.0 Added 'modified' property and response value.
*/
function add_modified_wp_template_schema() {
register_rest_field(
array( 'wp_template', 'wp_template_part' ),
'modified',
array(
'schema' => array(
'description' => __( "The date the post was last modified, in the site's timezone.", 'gutenberg' ),
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
'type' => 'string',
'format' => 'date-time',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'get_callback' => function( $object ) {
if ( ! empty( $object['wp_id'] ) ) {
$post = get_post( $object['wp_id'] );
if ( $post && isset( $post->post_modified ) ) {
return mysql_to_rfc3339( $post->post_modified );
}
}
return null;
},
)
);
}
add_filter( 'rest_api_init', 'add_modified_wp_template_schema' );
192 changes: 178 additions & 14 deletions phpunit/class-gutenberg-rest-templates-controller-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@ class Gutenberg_REST_Templates_Controller_Test extends WP_Test_REST_Controller_T
* @var int
*/
protected static $admin_id;
private static $post;

protected function find_and_normalize_template_by_id( $templates, $id ) {
foreach ( $templates as $template ) {
if ( $template['id'] === $id ) {
unset( $template['content'] );
unset( $template['_links'] );
return $template;
}
}

return null;
}

public function set_up() {
parent::set_up();
switch_theme( 'emptytheme' );
}

/**
Expand All @@ -17,11 +29,28 @@ public function set_up() {
* @param WP_UnitTest_Factory $factory Helper that lets us create fake data.
*/
public static function wpSetupBeforeClass( $factory ) {
switch_theme( 'emptytheme' );
self::$admin_id = $factory->user->create(
array(
'role' => 'administrator',
)
);

// Set up template post.
$args = array(
'post_type' => 'wp_template',
'post_name' => 'my_template',
'post_title' => 'My Template',
'post_content' => 'Content',
'post_excerpt' => 'Description of my template.',
'tax_input' => array(
'wp_theme' => array(
get_stylesheet(),
),
),
);
self::$post = self::factory()->post->create_and_get( $args );
wp_set_post_terms( self::$post->ID, get_stylesheet(), 'wp_theme' );
}

public function test_register_routes() {
Expand Down Expand Up @@ -63,42 +92,177 @@ public function test_get_template_fallback() {
}

/**
* @doesNotPerformAssertions
* @covers WP_REST_Templates_Controller::get_item_schema
*/
public function test_context_param() {}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/templates' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertCount( 15, $properties );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'theme', $properties );
$this->assertArrayHasKey( 'type', $properties );
$this->assertArrayHasKey( 'source', $properties );
$this->assertArrayHasKey( 'origin', $properties );
$this->assertArrayHasKey( 'content', $properties );
$this->assertArrayHasKey( 'title', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'status', $properties );
$this->assertArrayHasKey( 'wp_id', $properties );
$this->assertArrayHasKey( 'has_theme_file', $properties );
$this->assertArrayHasKey( 'is_custom', $properties );
$this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'modified', $properties );
}

/**
* @doesNotPerformAssertions
* @covers WP_REST_Templates_Controller::get_item
*/
public function test_get_items() {}
public function test_get_item() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/templates/emptytheme//my_template' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
unset( $data['content'] );
unset( $data['_links'] );

$this->assertSame(
array(
'id' => 'emptytheme//my_template',
'theme' => 'emptytheme',
'slug' => 'my_template',
'source' => 'custom',
'origin' => null,
'type' => 'wp_template',
'description' => 'Description of my template.',
'title' => array(
'raw' => 'My Template',
'rendered' => 'My Template',
),
'status' => 'publish',
'wp_id' => self::$post->ID,
'has_theme_file' => false,
'is_custom' => true,
'author' => 0,
'modified' => mysql_to_rfc3339( self::$post->post_modified ),
),
$data
);
}

/**
* @doesNotPerformAssertions
* @covers WP_REST_Templates_Controller::get_items
*/
public function test_get_item() {}
public function test_get_items() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/templates' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();

$this->assertSame(
array(
'id' => 'emptytheme//my_template',
'theme' => 'emptytheme',
'slug' => 'my_template',
'source' => 'custom',
'origin' => null,
'type' => 'wp_template',
'description' => 'Description of my template.',
'title' => array(
'raw' => 'My Template',
'rendered' => 'My Template',
),
'status' => 'publish',
'wp_id' => self::$post->ID,
'has_theme_file' => false,
'is_custom' => true,
'author' => 0,
'modified' => mysql_to_rfc3339( self::$post->post_modified ),
),
$this->find_and_normalize_template_by_id( $data, 'emptytheme//my_template' )
);
}

/**
* @doesNotPerformAssertions
* @covers WP_REST_Templates_Controller::update_item
*/
public function test_create_item() {}
public function test_update_item() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'PUT', '/wp/v2/templates/emptytheme//my_template' );
$request->set_body_params(
array(
'title' => 'My new Index Title',
)
);

$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( 'My new Index Title', $data['title']['raw'] );
$this->assertSame( 'custom', $data['source'] );
$this->assertIsString( $data['modified'] );
}

/**
* @doesNotPerformAssertions
* @covers WP_REST_Templates_Controller::create_item
*/
public function test_update_item() {}
public function test_create_item() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/templates' );
$request->set_body_params(
array(
'slug' => 'my_custom_template',
'description' => 'Just a description',
'title' => 'My Template',
'content' => 'Content',
'author' => self::$admin_id,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
unset( $data['_links'] );
unset( $data['wp_id'] );

$this->assertSame(
array(
'id' => 'emptytheme//my_custom_template',
'theme' => 'emptytheme',
'content' => array(
'raw' => 'Content',
),
'slug' => 'my_custom_template',
'source' => 'custom',
'origin' => null,
'type' => 'wp_template',
'description' => 'Just a description',
'title' => array(
'raw' => 'My Template',
'rendered' => 'My Template',
),
'status' => 'publish',
'has_theme_file' => false,
'is_custom' => true,
'author' => self::$admin_id,
'modified' => $data['modified'],
),
$data
);
}

/**
* @doesNotPerformAssertions
*/
public function test_delete_item() {}
public function test_context_param() {}

/**
* @doesNotPerformAssertions
*/
public function test_prepare_item() {}
public function test_delete_item() {}

/**
* @doesNotPerformAssertions
*/
public function test_get_item_schema() {}
public function test_prepare_item() {}
}