Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ class WP_REST_Templates_Controller extends WP_REST_Controller {
*/
protected $post_type;

/**
* The template being prepared for the response, so prepare_links() can reuse it.
*
* @since 7.2.0
*/
private ?WP_Block_Template $prepared_template = null;

/**
* Constructor.
*
Expand Down Expand Up @@ -832,7 +839,9 @@ public function prepare_item_for_response( $item, $request ) {
$response = rest_ensure_response( $data );

if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
$links = $this->prepare_links( $template->id );
$this->prepared_template = $template;
$links = $this->prepare_links( $template->id );
$this->prepared_template = null;
$response->add_links( $links );
if ( ! empty( $links['self']['href'] ) ) {
$actions = $this->get_available_actions();
Expand Down Expand Up @@ -984,7 +993,13 @@ protected function prepare_links( $id ) {
);

if ( post_type_supports( $this->post_type, 'revisions' ) ) {
$template = get_block_template( $id, $this->post_type );
// Reuse the template being prepared instead of querying it again for each item.
if ( $this->prepared_template instanceof WP_Block_Template && $this->prepared_template->id === $id ) {
$template = $this->prepared_template;
} else {
// Only reached when a subclass calls prepare_links() outside of prepare_item_for_response().
$template = get_block_template( $id, $this->post_type );
Comment thread
mpeshev marked this conversation as resolved.
}
if ( $template instanceof WP_Block_Template && ! empty( $template->wp_id ) ) {
$revisions = wp_get_latest_revision_id_and_total_count( $template->wp_id );
$revisions_count = ! is_wp_error( $revisions ) ? $revisions['count'] : 0;
Expand Down
50 changes: 50 additions & 0 deletions tests/phpunit/tests/rest-api/wpRestTemplatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1247,4 +1247,54 @@ public function test_prepare_item_for_database_injects_hooked_block() {
'The hooked block was not injected into the anchor block\'s ignoredHookedBlocks metadata.'
);
}

/**
* Tests that preparing a collection does not fetch each template again to build its links.
*
* @ticket 66381
*
* @covers WP_REST_Templates_Controller::prepare_links
*/
public function test_get_items_should_not_refetch_each_template_for_links() {
wp_set_current_user( self::$admin_id );

$mock = new MockAction();
add_filter( 'pre_get_block_template', array( $mock, 'filter' ) );
$response = rest_get_server()->dispatch( new WP_REST_Request( 'GET', '/wp/v2/templates' ) );

$this->assertSame( 200, $response->get_status(), 'The request should succeed.' );
$this->assertSame( 0, $mock->get_call_count(), 'Templates should not be fetched again to prepare their links.' );
}

/**
* Tests that the version history link of a customized template is kept when preparing a collection.
*
* @ticket 66381
*
* @covers WP_REST_Templates_Controller::prepare_links
*/
public function test_get_items_should_include_version_history_link_for_customized_template() {
wp_set_current_user( self::$admin_id );

$this->assertIsInt(
wp_update_post(
array(
'ID' => self::$template_post->ID,
'post_content' => 'Content for a revision.',
),
true
)
);
$revisions = wp_get_latest_revision_id_and_total_count( self::$template_post->ID );

$request = new WP_REST_Request( 'GET', '/wp/v2/templates' );
$data = rest_get_server()->response_to_data( rest_get_server()->dispatch( $request ), false );
$item = $this->find_and_normalize_template_by_id( $data, 'default//my_template' );
$found = wp_list_filter( $data, array( 'id' => 'default//my_template' ) );
$links = array_first( $found )['_links'];

$this->assertNotEmpty( $item, 'The customized template should be in the collection.' );
$this->assertSame( $revisions['count'], $links['version-history'][0]['count'], 'The version history count should match the revisions of the template.' );
$this->assertSame( $revisions['latest_id'], $links['predecessor-version'][0]['id'], 'The predecessor version should be the latest revision.' );
}
}
Loading