Skip to content

Commit

Permalink
Templates API: return post modified datetime in response (WordPress#5…
Browse files Browse the repository at this point in the history
…1362)

* All these file changes are so that we can add `modified` to the template and template part objects in the rest response for WP_REST_Templates_Controller
For theme templates, it will add the modified value when we have a post id (which is once the template is first save after user change)

* Modified property is returned when updated.

* Modified property is returned when created.

* _wp_build_title_and_description_for_single_post_type_block_template and _wp_build_title_and_description_for_taxonomy_block_template have to be ported across too because they expect WP_Block_Template, not Gutenberg_Block_Template

* Revert changes that required pulling all files across and using hooks to add the field to the response.

* Now adding the value of `modified` to the response using the get_callback method on the register_rest_field filter, which is the way I should have done it in the first place :)

* Formatting date according post_modified rules found in https://developer.wordpress.org/reference/classes/wp_rest_posts_controller/prepare_item_for_response/

* Whoops, forgot to wrap date expectations in mysql_to_rfc3339

* Update lib/compat/wordpress-6.3/rest-api.php

Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com>

---------

Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
  • Loading branch information
2 people authored and sethrubenstein committed Jul 13, 2023
1 parent 5adbecd commit d46de2d
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 15 deletions.
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
30 changes: 30 additions & 0 deletions lib/compat/wordpress-6.3/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,33 @@ function gutenberg_register_global_styles_endpoints() {
}
add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' );

/**
* 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 template was last modified, in the site's timezone.", 'gutenberg' ),
'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() {}
}

0 comments on commit d46de2d

Please sign in to comment.