diff --git a/core/modules/block/src/BlockRepository.php b/core/modules/block/src/BlockRepository.php index c6655df..1ae94c3 100644 --- a/core/modules/block/src/BlockRepository.php +++ b/core/modules/block/src/BlockRepository.php @@ -37,6 +37,7 @@ class BlockRepository implements BlockRepositoryInterface { * * @var \Drupal\Core\Cache\CacheBackendInterface */ + protected $cacheBackend; /** * Constructs a new BlockRepository. @@ -47,6 +48,7 @@ class BlockRepository implements BlockRepositoryInterface { * The theme manager. * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler * The plugin context handler. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend */ public function __construct(EntityManagerInterface $entity_manager, ThemeManagerInterface $theme_manager, ContextHandlerInterface $context_handler, CacheBackendInterface $cache_backend) { $this->blockStorage = $entity_manager->getStorage('block'); @@ -83,13 +85,13 @@ public function getVisibleBlocksPerRegion(array $contexts) { $empty = array_fill_keys(array_keys($this->getRegionNames()), array()); $full = array(); - $cid = 'block_list:' . $this->getTheme(); - $cached = $this->cacheBackend->get($cid); - if ($cached) { + $theme = $this->getTheme(); + $cid = 'block_list:' . $theme; + if ($cached = $this->cacheBackend->get($cid)) { $blocks = $cached->data; } else { - $blocks = $this->blockStorage->loadByProperties(array('theme' => $this->getTheme())); + $blocks = $this->blockStorage->loadByProperties(['theme' => $theme]); // Add the block config entity list cache tag, so that this is invalidated // when blocks change. $this->cacheBackend->set($cid, $blocks, Cache::PERMANENT, ['config:block_list']); diff --git a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php index f589e82..0548bdc 100644 --- a/core/modules/block/tests/src/Unit/BlockRepositoryTest.php +++ b/core/modules/block/tests/src/Unit/BlockRepositoryTest.php @@ -8,6 +8,8 @@ namespace Drupal\Tests\block\Unit; use Drupal\Core\Block\BlockPluginInterface; +use Drupal\Core\Plugin\Context\Context; +use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Tests\UnitTestCase; @@ -38,6 +40,13 @@ class BlockRepositoryTest extends UnitTestCase { protected $contextHandler; /** + * The cache backend. + * + * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheBackend; + + /** * {@inheritdoc} */ protected function setUp() { @@ -61,9 +70,10 @@ protected function setUp() { $entity_manager->expects($this->any()) ->method('getStorage') ->willReturn($this->blockStorage); + $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); $this->blockRepository = $this->getMockBuilder('Drupal\block\BlockRepository') - ->setConstructorArgs([$entity_manager, $theme_manager, $this->contextHandler]) + ->setConstructorArgs([$entity_manager, $theme_manager, $this->contextHandler, $this->cacheBackend]) ->setMethods(['getRegionNames']) ->getMock(); $this->blockRepository->expects($this->once()) @@ -102,13 +112,8 @@ public function testGetVisibleBlocksPerRegion(array $blocks_config, array $expec ->method('loadByProperties') ->with(['theme' => $this->theme]) ->willReturn($blocks); - $result = []; - foreach ($this->blockRepository->getVisibleBlocksPerRegion([]) as $region => $resulting_blocks) { - $result[$region] = []; - foreach ($resulting_blocks as $plugin_id => $block) { - $result[$region][] = $plugin_id; - } - } + + $result = $this->getAllVisibleBlocks([]); $this->assertSame($result, $expected_blocks); } @@ -147,6 +152,45 @@ public function providerBlocksConfig() { * @covers ::getVisibleBlocksPerRegion */ public function testGetVisibleBlocksPerRegionWithContext() { + $contexts = []; + $contexts[] = new Context(new ContextDefinition('entity:user', 'Current user')); + + $block = $this->getMock('Drupal\block\BlockInterface'); + $block->expects($this->once()) + ->method('setContexts') + ->with($contexts) + ->willReturnSelf(); + $block->expects($this->once()) + ->method('access') + ->willReturn(TRUE); + $block->expects($this->once()) + ->method('getRegion') + ->willReturn('top'); + $blocks['block_id'] = $block; + + $this->blockStorage->expects($this->once()) + ->method('loadByProperties') + ->with(['theme' => $this->theme]) + ->willReturn($blocks); + + $result = $this->getAllVisibleBlocks($contexts); + $expected = [ + 'top' => [ + 'block_id', + ], + 'center' => [], + 'bottom' => [], + ]; + $this->assertSame($expected, $result); + } + + /** + * @covers ::getVisibleBlocksPerRegion + */ + public function testGetVisibleBlocksPerRegionFromCache() { + $this->blockStorage->expects($this->never()) + ->method('loadByProperties'); + $block = $this->getMock('Drupal\block\BlockInterface'); $block->expects($this->once()) ->method('setContexts') @@ -159,18 +203,12 @@ public function testGetVisibleBlocksPerRegionWithContext() { ->willReturn('top'); $blocks['block_id'] = $block; - $contexts = []; - $this->blockStorage->expects($this->once()) - ->method('loadByProperties') - ->with(['theme' => $this->theme]) - ->willReturn($blocks); - $result = []; - foreach ($this->blockRepository->getVisibleBlocksPerRegion($contexts) as $region => $resulting_blocks) { - $result[$region] = []; - foreach ($resulting_blocks as $plugin_id => $block) { - $result[$region][] = $plugin_id; - } - } + $this->cacheBackend->expects($this->once()) + ->method('get') + ->with('block_list:' . $this->theme) + ->willReturn((object) ['data' => $blocks]); + + $result = $this->getAllVisibleBlocks([]); $expected = [ 'top' => [ 'block_id', @@ -181,6 +219,20 @@ public function testGetVisibleBlocksPerRegionWithContext() { $this->assertSame($expected, $result); } + /** + * Calls getVisibleBlocksPerRegion() for a set of contexts. + */ + protected function getAllVisibleBlocks(array $contexts) { + $result = []; + foreach ($this->blockRepository->getVisibleBlocksPerRegion($contexts) as $region => $resulting_blocks) { + $result[$region] = []; + foreach ($resulting_blocks as $plugin_id => $block) { + $result[$region][] = $plugin_id; + } + } + return $result; + } + } interface TestContextAwareBlockInterface extends BlockPluginInterface, ContextAwarePluginInterface {