3 namespace Drupal\layout_builder\Plugin\Block;
5 use Drupal\block_content\Access\RefinableDependentAccessInterface;
6 use Drupal\block_content\Access\RefinableDependentAccessTrait;
7 use Drupal\Component\Utility\NestedArray;
8 use Drupal\Core\Access\AccessResult;
9 use Drupal\Core\Block\BlockBase;
10 use Drupal\Core\Entity\Entity\EntityFormDisplay;
11 use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
12 use Drupal\Core\Entity\EntityTypeManagerInterface;
13 use Drupal\Core\Form\FormStateInterface;
14 use Drupal\Core\Form\SubformStateInterface;
15 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
16 use Drupal\Core\Session\AccountInterface;
17 use Symfony\Component\DependencyInjection\ContainerInterface;
20 * Defines an inline block plugin type.
23 * id = "inline_block",
24 * admin_label = @Translation("Inline block"),
25 * category = @Translation("Inline blocks"),
26 * deriver = "Drupal\layout_builder\Plugin\Derivative\InlineBlockDeriver",
30 * Plugin classes are internal.
32 class InlineBlock extends BlockBase implements ContainerFactoryPluginInterface, RefinableDependentAccessInterface {
34 use RefinableDependentAccessTrait;
37 * The entity type manager.
39 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
41 protected $entityTypeManager;
44 * The block content entity.
46 * @var \Drupal\block_content\BlockContentInterface
48 protected $blockContent;
51 * The entity display repository.
53 * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
55 protected $entityDisplayRepository;
58 * Whether a new block is being created.
62 protected $isNew = TRUE;
65 * Constructs a new InlineBlock.
67 * @param array $configuration
68 * A configuration array containing information about the plugin instance.
69 * @param string $plugin_id
70 * The plugin ID for the plugin instance.
71 * @param mixed $plugin_definition
72 * The plugin implementation definition.
73 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
74 * The entity type manager service.
75 * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
76 * The entity display repository.
78 public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository) {
79 parent::__construct($configuration, $plugin_id, $plugin_definition);
81 $this->entityTypeManager = $entity_type_manager;
82 $this->entityDisplayRepository = $entity_display_repository;
83 if (!empty($this->configuration['block_revision_id']) || !empty($this->configuration['block_serialized'])) {
91 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
96 $container->get('entity_type.manager'),
97 $container->get('entity_display.repository')
104 public function defaultConfiguration() {
106 'view_mode' => 'full',
107 'block_revision_id' => NULL,
108 'block_serialized' => NULL,
115 public function blockForm($form, FormStateInterface $form_state) {
116 $block = $this->getEntity();
118 // Add the entity form display in a process callback so that #parents can
119 // be successfully propagated to field widgets.
120 $form['block_form'] = [
121 '#type' => 'container',
122 '#process' => [[static::class, 'processBlockForm']],
126 $options = $this->entityDisplayRepository->getViewModeOptionsByBundle('block_content', $block->bundle());
128 $form['view_mode'] = [
130 '#options' => $options,
131 '#title' => $this->t('View mode'),
132 '#description' => $this->t('The view mode in which to render the block.'),
133 '#default_value' => $this->configuration['view_mode'],
134 '#access' => count($options) > 1,
140 * Process callback to insert a Custom Block form.
142 * @param array $element
143 * The containing element.
144 * @param \Drupal\Core\Form\FormStateInterface $form_state
148 * The containing element, with the Custom Block form inserted.
150 public static function processBlockForm(array $element, FormStateInterface $form_state) {
151 /** @var \Drupal\block_content\BlockContentInterface $block */
152 $block = $element['#block'];
153 EntityFormDisplay::collectRenderDisplay($block, 'edit')->buildForm($block, $element, $form_state);
154 $element['revision_log']['#access'] = FALSE;
155 $element['info']['#access'] = FALSE;
162 public function blockValidate($form, FormStateInterface $form_state) {
163 $block_form = $form['block_form'];
164 /** @var \Drupal\block_content\BlockContentInterface $block */
165 $block = $block_form['#block'];
166 $form_display = EntityFormDisplay::collectRenderDisplay($block, 'edit');
167 $complete_form_state = $form_state instanceof SubformStateInterface ? $form_state->getCompleteFormState() : $form_state;
168 $form_display->extractFormValues($block, $block_form, $complete_form_state);
169 $form_display->validateFormValues($block, $block_form, $complete_form_state);
170 // @todo Remove when https://www.drupal.org/project/drupal/issues/2948549 is closed.
171 $form_state->setTemporaryValue('block_form_parents', $block_form['#parents']);
177 public function blockSubmit($form, FormStateInterface $form_state) {
178 $this->configuration['view_mode'] = $form_state->getValue('view_mode');
180 // @todo Remove when https://www.drupal.org/project/drupal/issues/2948549 is closed.
181 $block_form = NestedArray::getValue($form, $form_state->getTemporaryValue('block_form_parents'));
182 /** @var \Drupal\block_content\BlockContentInterface $block */
183 $block = $block_form['#block'];
184 $form_display = EntityFormDisplay::collectRenderDisplay($block, 'edit');
185 $complete_form_state = $form_state instanceof SubformStateInterface ? $form_state->getCompleteFormState() : $form_state;
186 $form_display->extractFormValues($block, $block_form, $complete_form_state);
187 $block->setInfo($this->configuration['label']);
188 $this->configuration['block_serialized'] = serialize($block);
194 protected function blockAccess(AccountInterface $account) {
195 if ($entity = $this->getEntity()) {
196 return $entity->access('view', $account, TRUE);
198 return AccessResult::forbidden();
204 public function build() {
205 $block = $this->getEntity();
206 return $this->entityTypeManager->getViewBuilder($block->getEntityTypeId())->view($block, $this->configuration['view_mode']);
210 * Loads or creates the block content entity of the block.
212 * @return \Drupal\block_content\BlockContentInterface
213 * The block content entity.
215 protected function getEntity() {
216 if (!isset($this->blockContent)) {
217 if (!empty($this->configuration['block_serialized'])) {
218 $this->blockContent = unserialize($this->configuration['block_serialized']);
220 elseif (!empty($this->configuration['block_revision_id'])) {
221 $entity = $this->entityTypeManager->getStorage('block_content')->loadRevision($this->configuration['block_revision_id']);
222 $this->blockContent = $entity;
225 $this->blockContent = $this->entityTypeManager->getStorage('block_content')->create([
226 'type' => $this->getDerivativeId(),
230 if ($this->blockContent instanceof RefinableDependentAccessInterface && $dependee = $this->getAccessDependency()) {
231 $this->blockContent->setAccessDependency($dependee);
234 return $this->blockContent;
240 public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
241 $form = parent::buildConfigurationForm($form, $form_state);
243 // If the Content Block is new then don't provide a default label.
244 unset($form['label']['#default_value']);
246 $form['label']['#description'] = $this->t('The title of the block as shown to the user.');
251 * Saves the block_content entity for this plugin.
253 * @param bool $new_revision
254 * Whether to create new revision.
255 * @param bool $duplicate_block
256 * Whether to duplicate the "block_content" entity.
258 public function saveBlockContent($new_revision = FALSE, $duplicate_block = FALSE) {
259 /** @var \Drupal\block_content\BlockContentInterface $block */
261 if (!empty($this->configuration['block_serialized'])) {
262 $block = unserialize($this->configuration['block_serialized']);
264 if ($duplicate_block) {
265 if (empty($block) && !empty($this->configuration['block_revision_id'])) {
266 $block = $this->entityTypeManager->getStorage('block_content')->loadRevision($this->configuration['block_revision_id']);
269 $block = $block->createDuplicate();
275 $block->setNewRevision();
278 $this->configuration['block_revision_id'] = $block->getRevisionId();
279 $this->configuration['block_serialized'] = NULL;