Skip to content
Merged
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
45 changes: 44 additions & 1 deletion classes/class-blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,13 @@ public function get_meta_boxes( $post_id ) {
*/
private $user_blocks = null;

/**
* Prepared blocks list cache for the current request.
*
* @var array
*/
private $blocks_result_cache = array();

/**
* Add block.
*
Expand All @@ -925,6 +932,7 @@ public function add_block( $data ) {
}

$this->user_blocks[] = apply_filters( 'lzb/add_user_block', $data );
$this->clear_blocks_result_cache();
}

/**
Expand All @@ -937,6 +945,7 @@ public function remove_block( $block_slug ) {
foreach ( $this->user_blocks as $k => $val ) {
if ( isset( $val['slug'] ) && $val['slug'] === $block_slug ) {
unset( $this->user_blocks[ $k ] );
$this->clear_blocks_result_cache();
}
}
}
Expand Down Expand Up @@ -1145,6 +1154,16 @@ public function marshal_block_data_with_controls( $id = null, $post_title = null
* @return array|null
*/
public function get_blocks( $db_only = false, $no_cache = false, $keep_duplicates = false ) {
if ( $no_cache ) {
$this->clear_blocks_result_cache();
}

$result_cache_key = $this->get_blocks_result_cache_key( $db_only, $keep_duplicates );

if ( ! $no_cache && isset( $this->blocks_result_cache[ $result_cache_key ] ) ) {
return apply_filters( 'lzb/get_blocks', $this->blocks_result_cache[ $result_cache_key ] );
}

// fetch blocks.
if ( null === $this->blocks || $no_cache ) {
// Try to get blocks from transient cache first.
Expand Down Expand Up @@ -1215,12 +1234,35 @@ public function get_blocks( $db_only = false, $no_cache = false, $keep_duplicate
}
}

return apply_filters( 'lzb/get_blocks', $unique_result );
$result = $unique_result;
}

if ( ! $no_cache ) {
$this->blocks_result_cache[ $result_cache_key ] = $result;
}

return apply_filters( 'lzb/get_blocks', $result );
}

/**
* Get the request cache key for prepared get_blocks() results.
*
* @param bool $db_only - get blocks from database only.
* @param bool $keep_duplicates - get blocks with same slugs.
*
* @return string
*/
private function get_blocks_result_cache_key( $db_only, $keep_duplicates ) {
return ( $db_only ? 'db' : 'all' ) . ':' . ( $keep_duplicates ? 'duplicates' : 'unique' );
}

/**
* Clear prepared blocks list cache for the current request.
*/
private function clear_blocks_result_cache() {
$this->blocks_result_cache = array();
}

/**
* Get specific block data by name.
*
Expand Down Expand Up @@ -1339,6 +1381,7 @@ public function clear_blocks_cache() {

// Also reset in-memory cache.
$this->blocks = null;
$this->clear_blocks_result_cache();

// Reset cache hash.
self::$cache_hash = null;
Expand Down
130 changes: 130 additions & 0 deletions tests/phpunit/BlockRegistrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,134 @@ public function test_no_duplicated_blocks() {

lazyblocks()->blocks()->remove_block( $block_slug );
}

public function test_get_blocks_does_not_prepare_user_blocks_more_than_once_per_request() {
$block_slug = 'lazyblock/request-cache-test';
$prepare_count = 0;

$count_prepare = function( $block_data ) use ( &$prepare_count ) {
if ( isset( $block_data['slug'] ) && 'lazyblock/' === $block_data['slug'] ) {
$prepare_count++;
}

return $block_data;
};

add_filter( 'lzb/block_data', $count_prepare );

lazyblocks()->add_block( array(
'slug' => $block_slug,
) );

lazyblocks()->blocks()->get_blocks();
lazyblocks()->blocks()->get_blocks();

remove_filter( 'lzb/block_data', $count_prepare );
lazyblocks()->blocks()->remove_block( $block_slug );

$this->assertEquals(
1,
$prepare_count
);
}

public function test_get_blocks_request_cache_is_cleared_when_user_blocks_change() {
$first_block_slug = 'lazyblock/request-cache-first';
$second_block_slug = 'lazyblock/request-cache-second';

lazyblocks()->add_block( array(
'slug' => $first_block_slug,
) );

lazyblocks()->blocks()->get_blocks();

$this->assertNotNull( lazyblocks()->blocks()->get_block( $first_block_slug ) );

lazyblocks()->add_block( array(
'slug' => $second_block_slug,
) );

$this->assertNotNull( lazyblocks()->blocks()->get_block( $second_block_slug ) );

lazyblocks()->blocks()->remove_block( $first_block_slug );

$this->assertNull( lazyblocks()->blocks()->get_block( $first_block_slug ) );

lazyblocks()->blocks()->remove_block( $second_block_slug );
}

public function test_get_blocks_filter_runs_on_repeated_calls() {
$block_slug = 'lazyblock/request-cache-filter';
$filter_count = 0;

$count_filter = function( $blocks ) use ( &$filter_count ) {
$filter_count++;

return $blocks;
};

add_filter( 'lzb/get_blocks', $count_filter );

lazyblocks()->add_block( array(
'slug' => $block_slug,
) );

lazyblocks()->blocks()->get_blocks();
lazyblocks()->blocks()->get_blocks();

remove_filter( 'lzb/get_blocks', $count_filter );
lazyblocks()->blocks()->remove_block( $block_slug );

$this->assertEquals(
2,
$filter_count
);
}

public function test_get_blocks_no_cache_clears_prepared_request_cache() {
$block_slug = 'lazyblock/request-cache-no-cache';

$set_first_description = function( $block_data ) {
if ( isset( $block_data['slug'] ) && 'lazyblock/' === $block_data['slug'] ) {
$block_data['description'] = 'First description';
}

return $block_data;
};

$set_second_description = function( $block_data ) {
if ( isset( $block_data['slug'] ) && 'lazyblock/' === $block_data['slug'] ) {
$block_data['description'] = 'Second description';
}

return $block_data;
};

add_filter( 'lzb/block_data', $set_first_description );

lazyblocks()->add_block( array(
'slug' => $block_slug,
) );

$block = lazyblocks()->blocks()->get_block( $block_slug );

$this->assertEquals(
'First description',
$block['description']
);

remove_filter( 'lzb/block_data', $set_first_description );
add_filter( 'lzb/block_data', $set_second_description );

lazyblocks()->blocks()->get_blocks( false, true );
$block = lazyblocks()->blocks()->get_block( $block_slug );

remove_filter( 'lzb/block_data', $set_second_description );
lazyblocks()->blocks()->remove_block( $block_slug );

$this->assertEquals(
'Second description',
$block['description']
);
}
}
Loading