Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 87 |
|
0.00% |
0 / 27 |
CRAP | |
0.00% |
0 / 1 |
IslandPluginBase | |
0.00% |
0 / 87 |
|
0.00% |
0 / 27 |
1406 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
create | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
build | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
20 | |||
afterBuild | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
isApplicable | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
12 | |||
label | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
keyboardShortcuts | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getTypeId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getHtmlId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getIcon | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onAttachToRoot | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onAttachToSlot | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onMove | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onActive | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onUpdate | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onDelete | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onHistoryChange | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onSave | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onPresetSave | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getConfiguration | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setConfiguration | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
defaultConfiguration | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
configurationSummary | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
reloadWithGlobalData | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
reloadWithLocalData | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
reloadWithInstanceData | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
getArgs | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Drupal\display_builder; |
6 | |
7 | use Drupal\Component\Plugin\Definition\PluginDefinitionInterface; |
8 | use Drupal\Component\Plugin\PluginBase; |
9 | use Drupal\Core\Entity\EntityTypeManagerInterface; |
10 | use Drupal\Core\Form\FormState; |
11 | use Drupal\Core\Form\FormStateInterface; |
12 | use Drupal\Core\StringTranslation\StringTranslationTrait; |
13 | use Drupal\Core\Theme\ComponentPluginManager; |
14 | use Drupal\ui_patterns\SourcePluginManager; |
15 | use Symfony\Component\DependencyInjection\ContainerInterface; |
16 | |
17 | /** |
18 | * Base class for island plugins. |
19 | */ |
20 | abstract class IslandPluginBase extends PluginBase implements IslandInterface { |
21 | |
22 | use HtmxTrait; |
23 | use RenderableBuilderTrait; |
24 | use StringTranslationTrait; |
25 | |
26 | /** |
27 | * The island data. |
28 | */ |
29 | protected array $data; |
30 | |
31 | /** |
32 | * The builder id. |
33 | */ |
34 | protected string $builderId; |
35 | |
36 | /** |
37 | * The builder instance entity. |
38 | */ |
39 | protected ?InstanceInterface $builder = NULL; |
40 | |
41 | /** |
42 | * The current island id which trigger action. |
43 | */ |
44 | protected string $currentIslandId; |
45 | |
46 | /** |
47 | * The instance id for this plugin. |
48 | */ |
49 | protected ?string $instanceId = NULL; |
50 | |
51 | /** |
52 | * {@inheritdoc} |
53 | */ |
54 | public function __construct( |
55 | array $configuration, |
56 | $plugin_id, |
57 | $plugin_definition, |
58 | protected ComponentPluginManager $sdcManager, |
59 | protected HtmxEvents $htmxEvents, |
60 | protected EntityTypeManagerInterface $entityTypeManager, |
61 | protected SourcePluginManager $sourceManager, |
62 | ) { |
63 | parent::__construct($configuration, $plugin_id, $plugin_definition); |
64 | $this->data = $configuration; |
65 | $this->setConfiguration($configuration); |
66 | } |
67 | |
68 | /** |
69 | * {@inheritdoc} |
70 | */ |
71 | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static { |
72 | return new static( |
73 | $configuration, |
74 | $plugin_id, |
75 | $plugin_definition, |
76 | $container->get('plugin.manager.sdc'), |
77 | $container->get('display_builder.htmx_events'), |
78 | $container->get('entity_type.manager'), |
79 | $container->get('plugin.manager.ui_patterns_source'), |
80 | ); |
81 | } |
82 | |
83 | /** |
84 | * {@inheritdoc} |
85 | */ |
86 | public function build(InstanceInterface $builder, array $data = [], array $options = []): array { |
87 | $this->builder = $builder; |
88 | |
89 | $builder_id = (string) $builder->id(); |
90 | $this->builderId = $builder_id; |
91 | $this->instanceId = $data['_node_id'] ?? NULL; |
92 | |
93 | // First, get specific data for the plugin. |
94 | if (isset($data['_third_party_settings'][$this->getPluginId()])) { |
95 | $this->data = $data['_third_party_settings'][$this->getPluginId()]; |
96 | } |
97 | // Otherwise, fallback on global data. |
98 | else { |
99 | $this->data = $data; |
100 | } |
101 | |
102 | if (!$this->isApplicable()) { |
103 | return []; |
104 | } |
105 | |
106 | if ($this instanceof IslandWithFormInterface) { |
107 | $contexts = $this->configuration['contexts'] ?? []; |
108 | |
109 | $form_state = new FormState(); |
110 | |
111 | // We have to force form to not rebuild, otherwise, we are losing data |
112 | // of an island plugin when another is submitted. |
113 | // Example: submitting Styles Panel make lose default form values for |
114 | // Instance Form Panel. |
115 | $form_state->setRebuild(FALSE); |
116 | $form_state->setExecuted(); |
117 | |
118 | $form_state->addBuildInfo('args', [$this->getArgs(), $contexts, $options]); |
119 | $build = \Drupal::formBuilder()->buildForm($this::getFormClass(), $form_state); |
120 | |
121 | return $this->afterBuild($build, $form_state); |
122 | } |
123 | |
124 | return []; |
125 | } |
126 | |
127 | /** |
128 | * {@inheritdoc} |
129 | */ |
130 | public function afterBuild(array $element, FormStateInterface $form_state): array { |
131 | if (!$this->isApplicable()) { |
132 | return []; |
133 | } |
134 | |
135 | $definition = $this->getPluginDefinition(); |
136 | $island_id = $definition instanceof PluginDefinitionInterface ? $definition->id() : ($definition['id'] ?? ''); |
137 | |
138 | return $this->htmxEvents->onThirdPartyFormChange($element, $this->builderId, $this->instanceId, $island_id); |
139 | } |
140 | |
141 | /** |
142 | * {@inheritdoc} |
143 | */ |
144 | public function isApplicable(): bool { |
145 | $definition = $this->getPluginDefinition(); |
146 | |
147 | return $this->instanceId !== NULL && \is_array($definition) && !empty($this->data); |
148 | } |
149 | |
150 | /** |
151 | * {@inheritdoc} |
152 | */ |
153 | public function label(): string { |
154 | // Cast the label to a string since it is a TranslatableMarkup object. |
155 | return (string) $this->pluginDefinition['label']; |
156 | } |
157 | |
158 | /** |
159 | * {@inheritdoc} |
160 | */ |
161 | public static function keyboardShortcuts(): array { |
162 | return []; |
163 | } |
164 | |
165 | /** |
166 | * {@inheritdoc} |
167 | */ |
168 | public function getTypeId(): string { |
169 | return $this->pluginDefinition['type']->value; |
170 | } |
171 | |
172 | /** |
173 | * {@inheritdoc} |
174 | */ |
175 | public function getHtmlId(string $builder_id): string { |
176 | return \implode('-', ['island', $builder_id, $this->pluginDefinition['id']]); |
177 | } |
178 | |
179 | /** |
180 | * {@inheritdoc} |
181 | */ |
182 | public function getIcon(): ?string { |
183 | return $this->pluginDefinition['icon'] ?? NULL; |
184 | } |
185 | |
186 | /** |
187 | * {@inheritdoc} |
188 | */ |
189 | public function onAttachToRoot(string $builder_id, string $instance_id): array { |
190 | return []; |
191 | } |
192 | |
193 | /** |
194 | * {@inheritdoc} |
195 | */ |
196 | public function onAttachToSlot(string $builder_id, string $instance_id, string $parent_id): array { |
197 | return []; |
198 | } |
199 | |
200 | /** |
201 | * {@inheritdoc} |
202 | */ |
203 | public function onMove(string $builder_id, string $instance_id): array { |
204 | return []; |
205 | } |
206 | |
207 | /** |
208 | * {@inheritdoc} |
209 | */ |
210 | public function onActive(string $builder_id, array $data): array { |
211 | return []; |
212 | } |
213 | |
214 | /** |
215 | * {@inheritdoc} |
216 | */ |
217 | public function onUpdate(string $builder_id, string $instance_id): array { |
218 | return []; |
219 | } |
220 | |
221 | /** |
222 | * {@inheritdoc} |
223 | */ |
224 | public function onDelete(string $builder_id, string $parent_id): array { |
225 | return []; |
226 | } |
227 | |
228 | /** |
229 | * {@inheritdoc} |
230 | */ |
231 | public function onHistoryChange(string $builder_id): array { |
232 | return []; |
233 | } |
234 | |
235 | /** |
236 | * {@inheritdoc} |
237 | */ |
238 | public function onSave(string $builder_id): array { |
239 | return []; |
240 | } |
241 | |
242 | /** |
243 | * {@inheritdoc} |
244 | */ |
245 | public function onPresetSave(string $builder_id): array { |
246 | return []; |
247 | } |
248 | |
249 | /** |
250 | * {@inheritdoc} |
251 | */ |
252 | public function getConfiguration(): array { |
253 | return \array_merge($this->defaultConfiguration(), $this->configuration); |
254 | } |
255 | |
256 | /** |
257 | * {@inheritdoc} |
258 | */ |
259 | public function setConfiguration(array $configuration): void { |
260 | $this->configuration = \array_merge($this->defaultConfiguration(), $configuration); |
261 | } |
262 | |
263 | /** |
264 | * {@inheritdoc} |
265 | */ |
266 | public function defaultConfiguration(): array { |
267 | return []; |
268 | } |
269 | |
270 | /** |
271 | * {@inheritdoc} |
272 | */ |
273 | public function configurationSummary(): array { |
274 | return []; |
275 | } |
276 | |
277 | /** |
278 | * Helper method to reload island with global data. |
279 | * |
280 | * @param string $builder_id |
281 | * The builder ID. |
282 | * |
283 | * @return array |
284 | * Returns a render array with out-of-band commands. |
285 | */ |
286 | protected function reloadWithGlobalData(string $builder_id): array { |
287 | if (!$this->builder) { |
288 | // @todo pass \Drupal\display_builder\InstanceInterface object in |
289 | // parameters instead of loading again. |
290 | /** @var \Drupal\display_builder\InstanceInterface $builder */ |
291 | $builder = $this->entityTypeManager->getStorage('display_builder_instance')->load($builder_id); |
292 | $this->builder = $builder; |
293 | } |
294 | $data = $this->builder->getCurrentState(); |
295 | |
296 | return $this->addOutOfBand( |
297 | $this->build($this->builder, $data), |
298 | '#' . $this->getHtmlId($builder_id), |
299 | 'innerHTML' |
300 | ); |
301 | } |
302 | |
303 | /** |
304 | * Helper method to reload island with provided local data. |
305 | * |
306 | * @param string $builder_id |
307 | * The builder ID. |
308 | * @param array $data |
309 | * The local data array to use for building the island. |
310 | * |
311 | * @return array |
312 | * Returns a render array with out-of-band commands. |
313 | */ |
314 | protected function reloadWithLocalData(string $builder_id, array $data): array { |
315 | if (!$this->builder) { |
316 | // @todo pass \Drupal\display_builder\InstanceInterface object in |
317 | // parameters instead of loading again. |
318 | /** @var \Drupal\display_builder\InstanceInterface $builder */ |
319 | $builder = $this->entityTypeManager->getStorage('display_builder_instance')->load($builder_id); |
320 | $this->builder = $builder; |
321 | } |
322 | |
323 | return $this->addOutOfBand( |
324 | $this->build($this->builder, $data), |
325 | '#' . $this->getHtmlId($builder_id), |
326 | 'innerHTML' |
327 | ); |
328 | } |
329 | |
330 | /** |
331 | * Helper method to reload island with instance-specific data. |
332 | * |
333 | * @param string $builder_id |
334 | * The builder ID. |
335 | * @param string $instance_id |
336 | * The instance ID. |
337 | * |
338 | * @return array |
339 | * Returns a render array with out-of-band commands. |
340 | */ |
341 | protected function reloadWithInstanceData(string $builder_id, string $instance_id): array { |
342 | if (!$this->builder) { |
343 | // @todo pass \Drupal\display_builder\InstanceInterface object in |
344 | // parameters instead of loading again. |
345 | /** @var \Drupal\display_builder\InstanceInterface $builder */ |
346 | $builder = $this->entityTypeManager->getStorage('display_builder_instance')->load($builder_id); |
347 | $this->builder = $builder; |
348 | } |
349 | $data = $this->builder->get($instance_id); |
350 | |
351 | return $this->addOutOfBand( |
352 | $this->build($this->builder, $data), |
353 | '#' . $this->getHtmlId($builder_id), |
354 | 'innerHTML' |
355 | ); |
356 | } |
357 | |
358 | /** |
359 | * Get args passed to plugin. |
360 | * |
361 | * @return array |
362 | * Array of arguments. |
363 | */ |
364 | private function getArgs(): array { |
365 | return [ |
366 | 'island_id' => $this->getPluginId(), |
367 | 'builder_id' => $this->builderId, |
368 | 'instance_id' => $this->instanceId, |
369 | 'instance' => $this->data, |
370 | ]; |
371 | } |
372 | |
373 | } |