3 namespace Drupal\layout_builder\Form;
5 use Drupal\Component\Uuid\UuidInterface;
6 use Drupal\Core\Ajax\AjaxFormHelperTrait;
7 use Drupal\Core\Block\BlockManagerInterface;
8 use Drupal\Core\Block\BlockPluginInterface;
9 use Drupal\Core\DependencyInjection\ClassResolverInterface;
10 use Drupal\Core\Form\FormBase;
11 use Drupal\Core\Form\FormStateInterface;
12 use Drupal\Core\Form\SubformState;
13 use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
14 use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
15 use Drupal\Core\Plugin\ContextAwarePluginInterface;
16 use Drupal\Core\Plugin\PluginFormFactoryInterface;
17 use Drupal\Core\Plugin\PluginWithFormsInterface;
18 use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
19 use Drupal\layout_builder\Controller\LayoutRebuildTrait;
20 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
21 use Drupal\layout_builder\SectionComponent;
22 use Drupal\layout_builder\SectionStorageInterface;
23 use Symfony\Component\DependencyInjection\ContainerInterface;
26 * Provides a base form for configuring a block.
30 abstract class ConfigureBlockFormBase extends FormBase {
32 use AjaxFormHelperTrait;
33 use ContextAwarePluginAssignmentTrait;
34 use LayoutBuilderContextTrait;
35 use LayoutRebuildTrait;
38 * The plugin being configured.
40 * @var \Drupal\Core\Block\BlockPluginInterface
45 * The layout tempstore repository.
47 * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
49 protected $layoutTempstoreRepository;
54 * @var \Drupal\Core\Block\BlockManagerInterface
56 protected $blockManager;
61 * @var \Drupal\Component\Uuid\UuidInterface
63 protected $uuidGenerator;
66 * The plugin form manager.
68 * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
70 protected $pluginFormFactory;
87 * The UUID of the component.
94 * The section storage.
96 * @var \Drupal\layout_builder\SectionStorageInterface
98 protected $sectionStorage;
101 * Constructs a new block form.
103 * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
104 * The layout tempstore repository.
105 * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
106 * The context repository.
107 * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
109 * @param \Drupal\Component\Uuid\UuidInterface $uuid
110 * The UUID generator.
111 * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
112 * The class resolver.
113 * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_manager
114 * The plugin form manager.
116 public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, ContextRepositoryInterface $context_repository, BlockManagerInterface $block_manager, UuidInterface $uuid, ClassResolverInterface $class_resolver, PluginFormFactoryInterface $plugin_form_manager) {
117 $this->layoutTempstoreRepository = $layout_tempstore_repository;
118 $this->contextRepository = $context_repository;
119 $this->blockManager = $block_manager;
120 $this->uuidGenerator = $uuid;
121 $this->classResolver = $class_resolver;
122 $this->pluginFormFactory = $plugin_form_manager;
128 public static function create(ContainerInterface $container) {
130 $container->get('layout_builder.tempstore_repository'),
131 $container->get('context.repository'),
132 $container->get('plugin.manager.block'),
133 $container->get('uuid'),
134 $container->get('class_resolver'),
135 $container->get('plugin_form.factory')
140 * Builds the form for the block.
143 * An associative array containing the structure of the form.
144 * @param \Drupal\Core\Form\FormStateInterface $form_state
145 * The current state of the form.
146 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
147 * The section storage being configured.
149 * The delta of the section.
150 * @param \Drupal\layout_builder\SectionComponent $component
151 * The section component containing the block.
156 public function doBuildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, SectionComponent $component = NULL) {
157 $this->sectionStorage = $section_storage;
158 $this->delta = $delta;
159 $this->uuid = $component->getUuid();
160 $this->block = $component->getPlugin();
162 $form_state->setTemporaryValue('gathered_contexts', $this->getAvailableContexts($section_storage));
164 // @todo Remove once https://www.drupal.org/node/2268787 is resolved.
165 $form_state->set('block_theme', $this->config('system.theme')->get('default'));
167 $form['#tree'] = TRUE;
168 $form['settings'] = [];
169 $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
170 $form['settings'] = $this->getPluginForm($this->block)->buildConfigurationForm($form['settings'], $subform_state);
172 $form['actions']['submit'] = [
174 '#value' => $this->submitLabel(),
175 '#button_type' => 'primary',
177 if ($this->isAjax()) {
178 $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit';
185 * Returns the label for the submit button.
190 abstract protected function submitLabel();
195 public function validateForm(array &$form, FormStateInterface $form_state) {
196 $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
197 $this->getPluginForm($this->block)->validateConfigurationForm($form['settings'], $subform_state);
203 public function submitForm(array &$form, FormStateInterface $form_state) {
204 // Call the plugin submit handler.
205 $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
206 $this->getPluginForm($this->block)->submitConfigurationForm($form, $subform_state);
208 // If this block is context-aware, set the context mapping.
209 if ($this->block instanceof ContextAwarePluginInterface) {
210 $this->block->setContextMapping($subform_state->getValue('context_mapping', []));
213 $configuration = $this->block->getConfiguration();
215 $section = $this->sectionStorage->getSection($this->delta);
216 $section->getComponent($this->uuid)->setConfiguration($configuration);
218 $this->layoutTempstoreRepository->set($this->sectionStorage);
219 $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
225 protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
226 return $this->rebuildAndClose($this->sectionStorage);
230 * Retrieves the plugin form for a given block.
232 * @param \Drupal\Core\Block\BlockPluginInterface $block
235 * @return \Drupal\Core\Plugin\PluginFormInterface
236 * The plugin form for the block.
238 protected function getPluginForm(BlockPluginInterface $block) {
239 if ($block instanceof PluginWithFormsInterface) {
240 return $this->pluginFormFactory->createInstance($block, 'configure');