Commit dacdef95 authored by catch's avatar catch

Issue #2878673 by Berdir, amateescu, larowlan: Cache loadEntityByUuid() calls for block_content

parent 9b674084
services:
block_content.uuid_lookup:
class: \Drupal\block_content\BlockContentUuidLookup
arguments: ['@cache.bootstrap', '@lock', '@entity_type.manager']
tags:
- { name: needs_destruction }
<?php
namespace Drupal\block_content;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheCollector;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Lock\LockBackendInterface;
/**
* A cache collector that caches IDs for block_content UUIDs.
*
* As block_content entities are used as block plugin derivatives, it is a
* fairly safe limitation that there are not hundreds of them, a site will
* likely run into problems with too many block content entities in other places
* than a cache that only stores UUID's and IDs. The same assumption is not true
* for other content entities.
*
* @internal
*/
class BlockContentUuidLookup extends CacheCollector {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Constructs a BlockContentUuidLookup instance.
*
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend.
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* The lock backend.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(CacheBackendInterface $cache, LockBackendInterface $lock, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct('block_content_uuid', $cache, $lock);
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
protected function resolveCacheMiss($key) {
$ids = $this->entityTypeManager->getStorage('block_content')->getQuery()
->condition('uuid', $key)
->execute();
// Only cache if there is a match, otherwise creating new entities would
// require to invalidate the cache.
$id = reset($ids);
if ($id) {
$this->storage[$key] = $id;
$this->persist($key);
}
return $id;
}
}
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
namespace Drupal\block_content\Plugin\Block; namespace Drupal\block_content\Plugin\Block;
use Drupal\block_content\BlockContentUuidLookup;
use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase; use Drupal\Core\Block\BlockBase;
use Drupal\Core\Block\BlockManagerInterface; use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Routing\UrlGeneratorInterface;
...@@ -32,11 +34,11 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter ...@@ -32,11 +34,11 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter
protected $blockManager; protected $blockManager;
/** /**
* The entity manager service. * The entity type manager service.
* *
* @var \Drupal\Core\Entity\EntityManagerInterface * @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/ */
protected $entityManager; protected $entityTypeManager;
/** /**
* The Drupal account to use for checking for access to block. * The Drupal account to use for checking for access to block.
...@@ -59,6 +61,20 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter ...@@ -59,6 +61,20 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter
*/ */
protected $urlGenerator; protected $urlGenerator;
/**
* The block content UUID lookup service.
*
* @var \Drupal\block_content\BlockContentUuidLookup
*/
protected $uuidLookup;
/**
* The entity display repository.
*
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
*/
protected $entityDisplayRepository;
/** /**
* Constructs a new BlockContentBlock. * Constructs a new BlockContentBlock.
* *
...@@ -70,20 +86,26 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter ...@@ -70,20 +86,26 @@ class BlockContentBlock extends BlockBase implements ContainerFactoryPluginInter
* The plugin implementation definition. * The plugin implementation definition.
* @param \Drupal\Core\Block\BlockManagerInterface $block_manager * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
* The Plugin Block Manager. * The Plugin Block Manager.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager service. * The entity type manager service.
* @param \Drupal\Core\Session\AccountInterface $account * @param \Drupal\Core\Session\AccountInterface $account
* The account for which view access should be checked. * The account for which view access should be checked.
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
* The URL generator. * The URL generator.
* @param \Drupal\block_content\BlockContentUuidLookup $uuid_lookup
* The block content UUID lookup service.
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
* The entity display repository.
*/ */
public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockManagerInterface $block_manager, EntityManagerInterface $entity_manager, AccountInterface $account, UrlGeneratorInterface $url_generator) { public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockManagerInterface $block_manager, EntityTypeManagerInterface $entity_type_manager, AccountInterface $account, UrlGeneratorInterface $url_generator, BlockContentUuidLookup $uuid_lookup, EntityDisplayRepositoryInterface $entity_display_repository) {
parent::__construct($configuration, $plugin_id, $plugin_definition); parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->blockManager = $block_manager; $this->blockManager = $block_manager;
$this->entityManager = $entity_manager; $this->entityTypeManager = $entity_type_manager;
$this->account = $account; $this->account = $account;
$this->urlGenerator = $url_generator; $this->urlGenerator = $url_generator;
$this->uuidLookup = $uuid_lookup;
$this->entityDisplayRepository = $entity_display_repository;
} }
/** /**
...@@ -95,9 +117,11 @@ public static function create(ContainerInterface $container, array $configuratio ...@@ -95,9 +117,11 @@ public static function create(ContainerInterface $container, array $configuratio
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
$container->get('plugin.manager.block'), $container->get('plugin.manager.block'),
$container->get('entity.manager'), $container->get('entity_type.manager'),
$container->get('current_user'), $container->get('current_user'),
$container->get('url_generator') $container->get('url_generator'),
$container->get('block_content.uuid_lookup'),
$container->get('entity_display.repository')
); );
} }
...@@ -118,9 +142,11 @@ public function defaultConfiguration() { ...@@ -118,9 +142,11 @@ public function defaultConfiguration() {
* Adds body and description fields to the block configuration form. * Adds body and description fields to the block configuration form.
*/ */
public function blockForm($form, FormStateInterface $form_state) { public function blockForm($form, FormStateInterface $form_state) {
$uuid = $this->getDerivativeId(); $block = $this->getEntity();
$block = $this->entityManager->loadEntityByUuid('block_content', $uuid); if (!$block) {
$options = $this->entityManager->getViewModeOptionsByBundle('block_content', $block->bundle()); return $form;
}
$options = $this->entityDisplayRepository->getViewModeOptionsByBundle('block_content', $block->bundle());
$form['view_mode'] = [ $form['view_mode'] = [
'#type' => 'select', '#type' => 'select',
...@@ -158,7 +184,7 @@ protected function blockAccess(AccountInterface $account) { ...@@ -158,7 +184,7 @@ protected function blockAccess(AccountInterface $account) {
*/ */
public function build() { public function build() {
if ($block = $this->getEntity()) { if ($block = $this->getEntity()) {
return $this->entityManager->getViewBuilder($block->getEntityTypeId())->view($block, $this->configuration['view_mode']); return $this->entityTypeManager->getViewBuilder($block->getEntityTypeId())->view($block, $this->configuration['view_mode']);
} }
else { else {
return [ return [
...@@ -180,7 +206,9 @@ public function build() { ...@@ -180,7 +206,9 @@ public function build() {
protected function getEntity() { protected function getEntity() {
if (!isset($this->blockContent)) { if (!isset($this->blockContent)) {
$uuid = $this->getDerivativeId(); $uuid = $this->getDerivativeId();
$this->blockContent = $this->entityManager->loadEntityByUuid('block_content', $uuid); if ($id = $this->uuidLookup->get($uuid)) {
$this->blockContent = $this->entityTypeManager->getStorage('block_content')->load($id);
}
} }
return $this->blockContent; return $this->blockContent;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment