3 namespace Drupal\layout_builder\Form;
5 use Drupal\Component\Uuid\UuidInterface;
6 use Drupal\Core\Block\BlockManagerInterface;
7 use Drupal\Core\Block\BlockPluginInterface;
8 use Drupal\Core\DependencyInjection\ClassResolverInterface;
9 use Drupal\Core\Form\FormBase;
10 use Drupal\Core\Form\FormStateInterface;
11 use Drupal\Core\Form\SubformState;
12 use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
13 use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
14 use Drupal\Core\Plugin\ContextAwarePluginInterface;
15 use Drupal\Core\Plugin\PluginFormFactoryInterface;
16 use Drupal\Core\Plugin\PluginWithFormsInterface;
17 use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
18 use Drupal\layout_builder\Controller\LayoutRebuildTrait;
19 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
20 use Drupal\layout_builder\SectionComponent;
21 use Drupal\layout_builder\SectionStorageInterface;
22 use Symfony\Component\DependencyInjection\ContainerInterface;
25 * Provides a base form for configuring a block.
29 abstract class ConfigureBlockFormBase extends FormBase {
31 use AjaxFormHelperTrait;
32 use ContextAwarePluginAssignmentTrait;
33 use LayoutBuilderContextTrait;
34 use LayoutRebuildTrait;
37 * The plugin being configured.
39 * @var \Drupal\Core\Block\BlockPluginInterface
44 * The layout tempstore repository.
46 * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
48 protected $layoutTempstoreRepository;
53 * @var \Drupal\Core\Block\BlockManagerInterface
55 protected $blockManager;
60 * @var \Drupal\Component\Uuid\UuidInterface
62 protected $uuidGenerator;
65 * The plugin form manager.
67 * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
69 protected $pluginFormFactory;
86 * The UUID of the component.
93 * The section storage.
95 * @var \Drupal\layout_builder\SectionStorageInterface
97 protected $sectionStorage;
100 * Constructs a new block form.
102 * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
103 * The layout tempstore repository.
104 * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
105 * The context repository.
106 * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
108 * @param \Drupal\Component\Uuid\UuidInterface $uuid
109 * The UUID generator.
110 * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
111 * The class resolver.
112 * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $plugin_form_manager
113 * The plugin form manager.
115 public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, ContextRepositoryInterface $context_repository, BlockManagerInterface $block_manager, UuidInterface $uuid, ClassResolverInterface $class_resolver, PluginFormFactoryInterface $plugin_form_manager) {
116 $this->layoutTempstoreRepository = $layout_tempstore_repository;
117 $this->contextRepository = $context_repository;
118 $this->blockManager = $block_manager;
119 $this->uuidGenerator = $uuid;
120 $this->classResolver = $class_resolver;
121 $this->pluginFormFactory = $plugin_form_manager;
127 public static function create(ContainerInterface $container) {
129 $container->get('layout_builder.tempstore_repository'),
130 $container->get('context.repository'),
131 $container->get('plugin.manager.block'),
132 $container->get('uuid'),
133 $container->get('class_resolver'),
134 $container->get('plugin_form.factory')
139 * Builds the form for the block.
142 * An associative array containing the structure of the form.
143 * @param \Drupal\Core\Form\FormStateInterface $form_state
144 * The current state of the form.
145 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
146 * The section storage being configured.
148 * The delta of the section.
149 * @param \Drupal\layout_builder\SectionComponent $component
150 * The section component containing the block.
155 public function doBuildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, SectionComponent $component = NULL) {
156 $this->sectionStorage = $section_storage;
157 $this->delta = $delta;
158 $this->uuid = $component->getUuid();
159 $this->block = $component->getPlugin();
161 $form_state->setTemporaryValue('gathered_contexts', $this->getAvailableContexts($section_storage));
163 // @todo Remove once https://www.drupal.org/node/2268787 is resolved.
164 $form_state->set('block_theme', $this->config('system.theme')->get('default'));
166 $form['#tree'] = TRUE;
167 $form['settings'] = [];
168 $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
169 $form['settings'] = $this->getPluginForm($this->block)->buildConfigurationForm($form['settings'], $subform_state);
171 $form['actions']['submit'] = [
173 '#value' => $this->submitLabel(),
174 '#button_type' => 'primary',
176 if ($this->isAjax()) {
177 $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit';
184 * Returns the label for the submit button.
189 abstract protected function submitLabel();
194 public function validateForm(array &$form, FormStateInterface $form_state) {
195 $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
196 $this->getPluginForm($this->block)->validateConfigurationForm($form['settings'], $subform_state);
202 public function submitForm(array &$form, FormStateInterface $form_state) {
203 // Call the plugin submit handler.
204 $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
205 $this->getPluginForm($this->block)->submitConfigurationForm($form, $subform_state);
207 // If this block is context-aware, set the context mapping.
208 if ($this->block instanceof ContextAwarePluginInterface) {
209 $this->block->setContextMapping($subform_state->getValue('context_mapping', []));
212 $configuration = $this->block->getConfiguration();
214 $section = $this->sectionStorage->getSection($this->delta);
215 $section->getComponent($this->uuid)->setConfiguration($configuration);
217 $this->layoutTempstoreRepository->set($this->sectionStorage);
218 $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
224 protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
225 return $this->rebuildAndClose($this->sectionStorage);
229 * Retrieves the plugin form for a given block.
231 * @param \Drupal\Core\Block\BlockPluginInterface $block
234 * @return \Drupal\Core\Plugin\PluginFormInterface
235 * The plugin form for the block.
237 protected function getPluginForm(BlockPluginInterface $block) {
238 if ($block instanceof PluginWithFormsInterface) {
239 return $this->pluginFormFactory->createInstance($block, 'configure');