Skip to content

Commit

Permalink
Add cache invalidation for header images
Browse files Browse the repository at this point in the history
Introduce `invalidate_header_images_cache` function to clear cached header images when custom header meta is updated or deleted. Add corresponding unit tests to ensure cache invalidation logic works correctly.
  • Loading branch information
Paul Bearne committed Sep 12, 2024
1 parent dfc0e2a commit b859689
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/wp-includes/theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -1547,11 +1547,33 @@ function get_uploaded_header_images() {
}
}

set_transient( $transient_key, $header_images, HOUR_IN_SECONDS );
set_transient( $transient_key, $header_images, DAY_IN_SECONDS );

return $header_images;
}

/**
* Invalidates the cache for header images when a custom header image is changed or deleted.
*
* @since 6.7
*
* @param int $meta_id The meta ID of the attachment meta data.
* @param int $post_id The post ID of the attachment.
* @param string $meta_key The meta key of the attachment meta data.
* @param mixed $meta_value The new value of the attachment meta data.
*
* @return void
*/
function invalidate_header_images_cache( $meta_id, $post_id, $meta_key, $meta_value ) {
if ( '_wp_attachment_is_custom_header' === $meta_key ) {
$stylesheet = get_option( 'stylesheet' );
$transient_key = 'uploaded_header_images' . $stylesheet;
delete_transient( $transient_key );
}
}
add_action( 'updated_post_meta', 'invalidate_header_images_cache', 10, 4 );
add_action( 'deleted_post_meta', 'invalidate_header_images_cache', 10, 4 );

/**
* Gets the header image data.
*
Expand Down
2 changes: 2 additions & 0 deletions tests/phpunit/tests/theme/getUploadedHeaderImages.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
/**
* @group themes
*
* @coversDefaultClass ::get_uploaded_header_images
*/
class Tests_Theme_GetUploadedHeaderImages extends WP_UnitTestCase {
public $custom_image_header;
Expand Down
112 changes: 112 additions & 0 deletions tests/phpunit/tests/theme/invalidateHeaderImagesCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* @group themes
*
* @coversDefaultClass ::invalidate_header_images_cache
*/
class Tests_Theme_invalidateHeaderImagesCache extends WP_UnitTestCase {
public $custom_image_header;

public function set_up() {
parent::set_up();
$this->custom_image_header = new Custom_Image_Header( '__return_null' );
}

/**
* @ticket 49446
*/
public function test_invalidate_header_images_cache_meta_updated() {
$id = wp_insert_attachment(
array(
'post_status' => 'publish',
'post_title' => 'foo.png',
'post_type' => 'post',
'guid' => 'http://localhost/foo.png',
)
);

// Create initial crop object.
$cropped_1 = 'foo-cropped-1.png';
$object = wp_copy_parent_attachment_properties( $cropped_1, $id, 'custom-header' );

// Ensure no previous crop exists.
$previous = $this->custom_image_header->get_previous_crop( $object );
$this->assertFalse( $previous );

// Create the initial crop attachment and set it as the header.
$cropped_1_id = $this->custom_image_header->insert_attachment( $object, $cropped_1 );
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
update_post_meta( $cropped_1_id, $key, time() );
update_post_meta( $cropped_1_id, '_wp_attachment_is_custom_header', get_stylesheet() );

$expected = array(
$cropped_1_id => array(
'attachment_id' => $cropped_1_id,
'url' => 'http://example.org/wp-content/uploads/foo-cropped-1.png',
'thumbnail_url' => 'http://example.org/wp-content/uploads/foo-cropped-1.png',
'alt_text' => '',
'attachment_parent' => $id,
),
);

$num_queries = get_num_queries() + 4;

$this->assertSame( $expected, get_uploaded_header_images() );

$this->assertSame( $num_queries, get_num_queries() );
update_post_meta( $cropped_1_id, '_wp_attachment_is_custom_header', 'updated' );

$stylesheet = get_option( 'stylesheet' );
$transient_key = 'uploaded_header_images' . $stylesheet;
$this->assertFalse( get_transient( $transient_key ), 'cache cleared' );
}

/**
* @ticket 49446
*/
public function test_invalidate_header_images_cache_meta_deleted() {
$id = wp_insert_attachment(
array(
'post_status' => 'publish',
'post_title' => 'foo.png',
'post_type' => 'post',
'guid' => 'http://localhost/foo.png',
)
);

// Create initial crop object.
$cropped_1 = 'foo-cropped-1.png';
$object = wp_copy_parent_attachment_properties( $cropped_1, $id, 'custom-header' );

// Ensure no previous crop exists.
$previous = $this->custom_image_header->get_previous_crop( $object );
$this->assertFalse( $previous );

// Create the initial crop attachment and set it as the header.
$cropped_1_id = $this->custom_image_header->insert_attachment( $object, $cropped_1 );
$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
update_post_meta( $cropped_1_id, $key, time() );
update_post_meta( $cropped_1_id, '_wp_attachment_is_custom_header', get_stylesheet() );

$expected = array(
$cropped_1_id => array(
'attachment_id' => $cropped_1_id,
'url' => 'http://example.org/wp-content/uploads/foo-cropped-1.png',
'thumbnail_url' => 'http://example.org/wp-content/uploads/foo-cropped-1.png',
'alt_text' => '',
'attachment_parent' => $id,
),
);

$num_queries = get_num_queries() + 4;

$this->assertSame( $expected, get_uploaded_header_images() );

$this->assertSame( $num_queries, get_num_queries() );
delete_post_meta( $cropped_1_id, '_wp_attachment_is_custom_header' );

$stylesheet = get_option( 'stylesheet' );
$transient_key = 'uploaded_header_images' . $stylesheet;
$this->assertFalse( get_transient( $transient_key ), 'cache cleared' );
}
}

0 comments on commit b859689

Please sign in to comment.