9236d023b4436d370e021a2cfe19042ad7febd88
[yaffs-website] / web / core / modules / layout_builder / src / Plugin / Block / InlineBlock.php
1 <?php
2
3 namespace Drupal\layout_builder\Plugin\Block;
4
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;
18
19 /**
20  * Defines an inline block plugin type.
21  *
22  * @Block(
23  *  id = "inline_block",
24  *  admin_label = @Translation("Inline block"),
25  *  category = @Translation("Inline blocks"),
26  *  deriver = "Drupal\layout_builder\Plugin\Derivative\InlineBlockDeriver",
27  * )
28  *
29  * @internal
30  *   Plugin classes are internal.
31  */
32 class InlineBlock extends BlockBase implements ContainerFactoryPluginInterface, RefinableDependentAccessInterface {
33
34   use RefinableDependentAccessTrait;
35
36   /**
37    * The entity type manager.
38    *
39    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
40    */
41   protected $entityTypeManager;
42
43   /**
44    * The block content entity.
45    *
46    * @var \Drupal\block_content\BlockContentInterface
47    */
48   protected $blockContent;
49
50   /**
51    * The entity display repository.
52    *
53    * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
54    */
55   protected $entityDisplayRepository;
56
57   /**
58    * Whether a new block is being created.
59    *
60    * @var bool
61    */
62   protected $isNew = TRUE;
63
64   /**
65    * Constructs a new InlineBlock.
66    *
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.
77    */
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);
80
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'])) {
84       $this->isNew = FALSE;
85     }
86   }
87
88   /**
89    * {@inheritdoc}
90    */
91   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
92     return new static(
93       $configuration,
94       $plugin_id,
95       $plugin_definition,
96       $container->get('entity_type.manager'),
97       $container->get('entity_display.repository')
98     );
99   }
100
101   /**
102    * {@inheritdoc}
103    */
104   public function defaultConfiguration() {
105     return [
106       'view_mode' => 'full',
107       'block_revision_id' => NULL,
108       'block_serialized' => NULL,
109     ];
110   }
111
112   /**
113    * {@inheritdoc}
114    */
115   public function blockForm($form, FormStateInterface $form_state) {
116     $block = $this->getEntity();
117
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']],
123       '#block' => $block,
124     ];
125
126     $options = $this->entityDisplayRepository->getViewModeOptionsByBundle('block_content', $block->bundle());
127
128     $form['view_mode'] = [
129       '#type' => 'select',
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,
135     ];
136     return $form;
137   }
138
139   /**
140    * Process callback to insert a Custom Block form.
141    *
142    * @param array $element
143    *   The containing element.
144    * @param \Drupal\Core\Form\FormStateInterface $form_state
145    *   The form state.
146    *
147    * @return array
148    *   The containing element, with the Custom Block form inserted.
149    */
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;
156     return $element;
157   }
158
159   /**
160    * {@inheritdoc}
161    */
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']);
172   }
173
174   /**
175    * {@inheritdoc}
176    */
177   public function blockSubmit($form, FormStateInterface $form_state) {
178     $this->configuration['view_mode'] = $form_state->getValue('view_mode');
179
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);
189   }
190
191   /**
192    * {@inheritdoc}
193    */
194   protected function blockAccess(AccountInterface $account) {
195     if ($entity = $this->getEntity()) {
196       return $entity->access('view', $account, TRUE);
197     }
198     return AccessResult::forbidden();
199   }
200
201   /**
202    * {@inheritdoc}
203    */
204   public function build() {
205     $block = $this->getEntity();
206     return $this->entityTypeManager->getViewBuilder($block->getEntityTypeId())->view($block, $this->configuration['view_mode']);
207   }
208
209   /**
210    * Loads or creates the block content entity of the block.
211    *
212    * @return \Drupal\block_content\BlockContentInterface
213    *   The block content entity.
214    */
215   protected function getEntity() {
216     if (!isset($this->blockContent)) {
217       if (!empty($this->configuration['block_serialized'])) {
218         $this->blockContent = unserialize($this->configuration['block_serialized']);
219       }
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;
223       }
224       else {
225         $this->blockContent = $this->entityTypeManager->getStorage('block_content')->create([
226           'type' => $this->getDerivativeId(),
227           'reusable' => FALSE,
228         ]);
229       }
230       if ($this->blockContent instanceof RefinableDependentAccessInterface && $dependee = $this->getAccessDependency()) {
231         $this->blockContent->setAccessDependency($dependee);
232       }
233     }
234     return $this->blockContent;
235   }
236
237   /**
238    * {@inheritdoc}
239    */
240   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
241     $form = parent::buildConfigurationForm($form, $form_state);
242     if ($this->isNew) {
243       // If the Content Block is new then don't provide a default label.
244       unset($form['label']['#default_value']);
245     }
246     $form['label']['#description'] = $this->t('The title of the block as shown to the user.');
247     return $form;
248   }
249
250   /**
251    * Saves the block_content entity for this plugin.
252    *
253    * @param bool $new_revision
254    *   Whether to create new revision.
255    * @param bool $duplicate_block
256    *   Whether to duplicate the "block_content" entity.
257    */
258   public function saveBlockContent($new_revision = FALSE, $duplicate_block = FALSE) {
259     /** @var \Drupal\block_content\BlockContentInterface $block */
260     $block = NULL;
261     if (!empty($this->configuration['block_serialized'])) {
262       $block = unserialize($this->configuration['block_serialized']);
263     }
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']);
267       }
268       if ($block) {
269         $block = $block->createDuplicate();
270       }
271     }
272
273     if ($block) {
274       if ($new_revision) {
275         $block->setNewRevision();
276       }
277       $block->save();
278       $this->configuration['block_revision_id'] = $block->getRevisionId();
279       $this->configuration['block_serialized'] = NULL;
280     }
281   }
282
283 }