Pull merge.
[yaffs-website] / web / core / modules / layout_builder / src / Form / ConfigureBlockFormBase.php
1 <?php
2
3 namespace Drupal\layout_builder\Form;
4
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;
24
25 /**
26  * Provides a base form for configuring a block.
27  *
28  * @internal
29  */
30 abstract class ConfigureBlockFormBase extends FormBase {
31
32   use AjaxFormHelperTrait;
33   use ContextAwarePluginAssignmentTrait;
34   use LayoutBuilderContextTrait;
35   use LayoutRebuildTrait;
36
37   /**
38    * The plugin being configured.
39    *
40    * @var \Drupal\Core\Block\BlockPluginInterface
41    */
42   protected $block;
43
44   /**
45    * The layout tempstore repository.
46    *
47    * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
48    */
49   protected $layoutTempstoreRepository;
50
51   /**
52    * The block manager.
53    *
54    * @var \Drupal\Core\Block\BlockManagerInterface
55    */
56   protected $blockManager;
57
58   /**
59    * The UUID generator.
60    *
61    * @var \Drupal\Component\Uuid\UuidInterface
62    */
63   protected $uuidGenerator;
64
65   /**
66    * The plugin form manager.
67    *
68    * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
69    */
70   protected $pluginFormFactory;
71
72   /**
73    * The field delta.
74    *
75    * @var int
76    */
77   protected $delta;
78
79   /**
80    * The current region.
81    *
82    * @var string
83    */
84   protected $region;
85
86   /**
87    * The UUID of the component.
88    *
89    * @var string
90    */
91   protected $uuid;
92
93   /**
94    * The section storage.
95    *
96    * @var \Drupal\layout_builder\SectionStorageInterface
97    */
98   protected $sectionStorage;
99
100   /**
101    * Constructs a new block form.
102    *
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
108    *   The 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.
115    */
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;
123   }
124
125   /**
126    * {@inheritdoc}
127    */
128   public static function create(ContainerInterface $container) {
129     return new static(
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')
136     );
137   }
138
139   /**
140    * Builds the form for the block.
141    *
142    * @param array $form
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.
148    * @param int $delta
149    *   The delta of the section.
150    * @param \Drupal\layout_builder\SectionComponent $component
151    *   The section component containing the block.
152    *
153    * @return array
154    *   The form array.
155    */
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();
161
162     $form_state->setTemporaryValue('gathered_contexts', $this->getAvailableContexts($section_storage));
163
164     // @todo Remove once https://www.drupal.org/node/2268787 is resolved.
165     $form_state->set('block_theme', $this->config('system.theme')->get('default'));
166
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);
171
172     $form['actions']['submit'] = [
173       '#type' => 'submit',
174       '#value' => $this->submitLabel(),
175       '#button_type' => 'primary',
176     ];
177     if ($this->isAjax()) {
178       $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit';
179     }
180
181     return $form;
182   }
183
184   /**
185    * Returns the label for the submit button.
186    *
187    * @return string
188    *   Submit label.
189    */
190   abstract protected function submitLabel();
191
192   /**
193    * {@inheritdoc}
194    */
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);
198   }
199
200   /**
201    * {@inheritdoc}
202    */
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);
207
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', []));
211     }
212
213     $configuration = $this->block->getConfiguration();
214
215     $section = $this->sectionStorage->getSection($this->delta);
216     $section->getComponent($this->uuid)->setConfiguration($configuration);
217
218     $this->layoutTempstoreRepository->set($this->sectionStorage);
219     $form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
220   }
221
222   /**
223    * {@inheritdoc}
224    */
225   protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
226     return $this->rebuildAndClose($this->sectionStorage);
227   }
228
229   /**
230    * Retrieves the plugin form for a given block.
231    *
232    * @param \Drupal\Core\Block\BlockPluginInterface $block
233    *   The block plugin.
234    *
235    * @return \Drupal\Core\Plugin\PluginFormInterface
236    *   The plugin form for the block.
237    */
238   protected function getPluginForm(BlockPluginInterface $block) {
239     if ($block instanceof PluginWithFormsInterface) {
240       return $this->pluginFormFactory->createInstance($block, 'configure');
241     }
242     return $block;
243   }
244
245 }