Mercurial > hg > isophonics-drupal-site
comparison 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 |
comparison
equal
deleted
inserted
replaced
16:c2387f117808 | 17:129ea1e6d783 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\layout_builder\EventSubscriber; | |
4 | |
5 use Drupal\block_content\BlockContentEvents; | |
6 use Drupal\block_content\BlockContentInterface; | |
7 use Drupal\block_content\Event\BlockContentGetDependencyEvent; | |
8 use Drupal\Core\Database\Connection; | |
9 use Drupal\Core\Entity\EntityInterface; | |
10 use Drupal\Core\Entity\EntityTypeManagerInterface; | |
11 use Drupal\layout_builder\InlineBlockUsage; | |
12 use Drupal\layout_builder\LayoutEntityHelperTrait; | |
13 use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
14 | |
15 /** | |
16 * An event subscriber that returns an access dependency for inline blocks. | |
17 * | |
18 * When used within the layout builder the access dependency for inline blocks | |
19 * will be explicitly set but if access is evaluated outside of the layout | |
20 * builder then the dependency may not have been set. | |
21 * | |
22 * A known example of when the access dependency will not have been set is when | |
23 * determining 'view' or 'download' access to a file entity that is attached | |
24 * to a content block via a field that is using the private file system. The | |
25 * file access handler will evaluate access on the content block without setting | |
26 * the dependency. | |
27 * | |
28 * @internal | |
29 * | |
30 * @see \Drupal\file\FileAccessControlHandler::checkAccess() | |
31 * @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess() | |
32 */ | |
33 class SetInlineBlockDependency implements EventSubscriberInterface { | |
34 | |
35 use LayoutEntityHelperTrait; | |
36 | |
37 /** | |
38 * The entity type manager. | |
39 * | |
40 * @var \Drupal\Core\Entity\EntityTypeManagerInterface | |
41 */ | |
42 protected $entityTypeManager; | |
43 | |
44 /** | |
45 * The database connection. | |
46 * | |
47 * @var \Drupal\Core\Database\Connection | |
48 */ | |
49 protected $database; | |
50 | |
51 /** | |
52 * The inline block usage service. | |
53 * | |
54 * @var \Drupal\layout_builder\InlineBlockUsage | |
55 */ | |
56 protected $usage; | |
57 | |
58 /** | |
59 * Constructs SetInlineBlockDependency object. | |
60 * | |
61 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager | |
62 * The entity type manager. | |
63 * @param \Drupal\Core\Database\Connection $database | |
64 * The database connection. | |
65 * @param \Drupal\layout_builder\InlineBlockUsage $usage | |
66 * The inline block usage service. | |
67 */ | |
68 public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database, InlineBlockUsage $usage) { | |
69 $this->entityTypeManager = $entity_type_manager; | |
70 $this->database = $database; | |
71 $this->usage = $usage; | |
72 } | |
73 | |
74 /** | |
75 * {@inheritdoc} | |
76 */ | |
77 public static function getSubscribedEvents() { | |
78 return [ | |
79 BlockContentEvents::BLOCK_CONTENT_GET_DEPENDENCY => 'onGetDependency', | |
80 ]; | |
81 } | |
82 | |
83 /** | |
84 * Handles the BlockContentEvents::INLINE_BLOCK_GET_DEPENDENCY event. | |
85 * | |
86 * @param \Drupal\block_content\Event\BlockContentGetDependencyEvent $event | |
87 * The event. | |
88 */ | |
89 public function onGetDependency(BlockContentGetDependencyEvent $event) { | |
90 if ($dependency = $this->getInlineBlockDependency($event->getBlockContentEntity())) { | |
91 $event->setAccessDependency($dependency); | |
92 } | |
93 } | |
94 | |
95 /** | |
96 * Get the access dependency of an inline block. | |
97 * | |
98 * If the block is used in an entity that entity will be returned as the | |
99 * dependency. | |
100 * | |
101 * For revisionable entities the entity will only be returned if it is used in | |
102 * the latest revision of the entity. For inline blocks that are not used in | |
103 * the latest revision but are used in a previous revision the entity will not | |
104 * be returned because calling | |
105 * \Drupal\Core\Access\AccessibleInterface::access() will only check access on | |
106 * the latest revision. Therefore if the previous revision of the entity was | |
107 * returned as the dependency access would be granted to inline block | |
108 * regardless of whether the user has access to the revision in which the | |
109 * inline block was used. | |
110 * | |
111 * @param \Drupal\block_content\BlockContentInterface $block_content | |
112 * The block content entity. | |
113 * | |
114 * @return \Drupal\Core\Entity\EntityInterface|null | |
115 * Returns the layout dependency. | |
116 * | |
117 * @see \Drupal\block_content\BlockContentAccessControlHandler::checkAccess() | |
118 * @see \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender() | |
119 */ | |
120 protected function getInlineBlockDependency(BlockContentInterface $block_content) { | |
121 $layout_entity_info = $this->usage->getUsage($block_content->id()); | |
122 if (empty($layout_entity_info)) { | |
123 // If the block does not have usage information then we cannot set a | |
124 // dependency. It may be used by another module besides layout builder. | |
125 return NULL; | |
126 } | |
127 /** @var \Drupal\layout_builder\InlineBlockUsage $usage */ | |
128 $layout_entity_storage = $this->entityTypeManager->getStorage($layout_entity_info->layout_entity_type); | |
129 $layout_entity = $layout_entity_storage->load($layout_entity_info->layout_entity_id); | |
130 if ($this->isLayoutCompatibleEntity($layout_entity)) { | |
131 if ($this->isBlockRevisionUsedInEntity($layout_entity, $block_content)) { | |
132 return $layout_entity; | |
133 } | |
134 | |
135 } | |
136 return NULL; | |
137 } | |
138 | |
139 /** | |
140 * Determines if a block content revision is used in an entity. | |
141 * | |
142 * @param \Drupal\Core\Entity\EntityInterface $layout_entity | |
143 * The layout entity. | |
144 * @param \Drupal\block_content\BlockContentInterface $block_content | |
145 * The block content revision. | |
146 * | |
147 * @return bool | |
148 * TRUE if the block content revision is used as an inline block in the | |
149 * layout entity. | |
150 */ | |
151 protected function isBlockRevisionUsedInEntity(EntityInterface $layout_entity, BlockContentInterface $block_content) { | |
152 $sections_blocks_revision_ids = $this->getInlineBlockRevisionIdsInSections($this->getEntitySections($layout_entity)); | |
153 return in_array($block_content->getRevisionId(), $sections_blocks_revision_ids); | |
154 } | |
155 | |
156 } |