Mercurial > hg > isophonics-drupal-site
view core/modules/layout_builder/src/EventSubscriber/SetInlineBlockDependency.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | |
children | af1871eacc83 |
line wrap: on
line source
<?php namespace Drupal\layout_builder\EventSubscriber; use Drupal\block_content\BlockContentEvents; use Drupal\block_content\BlockContentInterface; use Drupal\block_content\Event\BlockContentGetDependencyEvent; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\layout_builder\InlineBlockUsage; use Drupal\layout_builder\LayoutEntityHelperTrait; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * An event subscriber that returns an access dependency for inline blocks. * * When used within the layout builder the access dependency for inline blocks * will be explicitly set but if access is evaluated outside of the layout * builder then the dependency may not have been set. * * A known example of when the access dependency will not have been set is when * determining 'view' or 'download' access to a file entity that is attached * to a content block via a field that is using the private file system. The * file access handler will evaluate access on the content block without setting * the dependency. * * @internal * * @see \Drupal\file\FileAccessControlHandler::checkAccess() * @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess() */ class SetInlineBlockDependency implements EventSubscriberInterface { use LayoutEntityHelperTrait; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * The database connection. * * @var \Drupal\Core\Database\Connection */ protected $database; /** * The inline block usage service. * * @var \Drupal\layout_builder\InlineBlockUsage */ protected $usage; /** * Constructs SetInlineBlockDependency object. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\Core\Database\Connection $database * The database connection. * @param \Drupal\layout_builder\InlineBlockUsage $usage * The inline block usage service. */ public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database, InlineBlockUsage $usage) { $this->entityTypeManager = $entity_type_manager; $this->database = $database; $this->usage = $usage; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ BlockContentEvents::BLOCK_CONTENT_GET_DEPENDENCY => 'onGetDependency', ]; } /** * Handles the BlockContentEvents::INLINE_BLOCK_GET_DEPENDENCY event. * * @param \Drupal\block_content\Event\BlockContentGetDependencyEvent $event * The event. */ public function onGetDependency(BlockContentGetDependencyEvent $event) { if ($dependency = $this->getInlineBlockDependency($event->getBlockContentEntity())) { $event->setAccessDependency($dependency); } } /** * Get the access dependency of an inline block. * * If the block is used in an entity that entity will be returned as the * dependency. * * For revisionable entities the entity will only be returned if it is used in * the latest revision of the entity. For inline blocks that are not used in * the latest revision but are used in a previous revision the entity will not * be returned because calling * \Drupal\Core\Access\AccessibleInterface::access() will only check access on * the latest revision. Therefore if the previous revision of the entity was * returned as the dependency access would be granted to inline block * regardless of whether the user has access to the revision in which the * inline block was used. * * @param \Drupal\block_content\BlockContentInterface $block_content * The block content entity. * * @return \Drupal\Core\Entity\EntityInterface|null * Returns the layout dependency. * * @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess() * @see \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender() */ protected function getInlineBlockDependency(BlockContentInterface $block_content) { $layout_entity_info = $this->usage->getUsage($block_content->id()); if (empty($layout_entity_info)) { // If the block does not have usage information then we cannot set a // dependency. It may be used by another module besides layout builder. return NULL; } /** @var \Drupal\layout_builder\InlineBlockUsage $usage */ $layout_entity_storage = $this->entityTypeManager->getStorage($layout_entity_info->layout_entity_type); $layout_entity = $layout_entity_storage->load($layout_entity_info->layout_entity_id); if ($this->isLayoutCompatibleEntity($layout_entity)) { if ($this->isBlockRevisionUsedInEntity($layout_entity, $block_content)) { return $layout_entity; } } return NULL; } /** * Determines if a block content revision is used in an entity. * * @param \Drupal\Core\Entity\EntityInterface $layout_entity * The layout entity. * @param \Drupal\block_content\BlockContentInterface $block_content * The block content revision. * * @return bool * TRUE if the block content revision is used as an inline block in the * layout entity. */ protected function isBlockRevisionUsedInEntity(EntityInterface $layout_entity, BlockContentInterface $block_content) { $sections_blocks_revision_ids = $this->getInlineBlockRevisionIdsInSections($this->getEntitySections($layout_entity)); return in_array($block_content->getRevisionId(), $sections_blocks_revision_ids); } }