Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 173
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
HtmxEvents
0.00% covered (danger)
0.00%
0 / 173
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 18
812
0.00% covered (danger)
0.00%
0 / 1
 onClickDelete
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onClickSavePreset
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onClickPaste
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onClickDuplicate
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onRootDrop
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onSlotDrop
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onInstanceClick
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 onInstanceFormChange
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 onInstanceUpdateButtonClick
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
42
 onThirdPartyFormChange
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onUndo
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onRedo
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onReset
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onRevert
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onClear
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onSave
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setHtmxAttributes
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setHtmxAttributesOnSubKey
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder;
6
7use Drupal\Component\Render\MarkupInterface;
8use Drupal\Core\Url;
9
10/**
11 * The HTMX Events class.
12 */
13class HtmxEvents {
14
15  use HtmxTrait;
16
17  /**
18   * Delete on click.
19   *
20   * @param array $build
21   *   The render array.
22   * @param string $builder_id
23   *   The instance entity ID.
24   * @param string $node_id
25   *   The node id of the source.
26   *
27   * @return array
28   *   The render array.
29   */
30  public function onClickDelete(array $build, string $builder_id, string $node_id): array {
31    $url = new Url(
32      'display_builder.api_delete',
33      [
34        'display_builder_instance' => $builder_id,
35        'node_id' => $node_id,
36      ]
37    );
38
39    $attributes = [
40      'hx-on:click' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "close")', $builder_id),
41    ];
42
43    return $this->setHtmxAttributes($build, $url, 'click consume', 'delete', $attributes);
44  }
45
46  /**
47   * Save as preset on click.
48   *
49   * @param array $build
50   *   The render array.
51   * @param string $builder_id
52   *   The instance entity ID.
53   * @param string $node_id
54   *   The node id of the source.
55   * @param string|\Drupal\Component\Render\MarkupInterface $prompt
56   *   The prompt before save.
57   *
58   * @return array
59   *   The render array.
60   */
61  public function onClickSavePreset(array $build, string $builder_id, string $node_id, MarkupInterface|string $prompt): array {
62    $url = new Url(
63      'display_builder.api_save_preset',
64      [
65        'display_builder_instance' => $builder_id,
66        'node_id' => $node_id,
67      ]
68    );
69
70    return $this->setHtmxAttributes($build, $url, 'click consume', 'post', ['hx-prompt' => $prompt]);
71  }
72
73  /**
74   * Paste on click.
75   *
76   * @param array $build
77   *   The render array.
78   * @param string $builder_id
79   *   The instance entity ID.
80   * @param string $node_id
81   *   The node id to copy.
82   * @param string $parent_id
83   *   The instance id target.
84   * @param string $slot_id
85   *   The instance target slot id.
86   * @param string $slot_position
87   *   The slot position.
88   *
89   * @return array
90   *   The render array.
91   */
92  public function onClickPaste(array $build, string $builder_id, string $node_id, string $parent_id, string $slot_id, string $slot_position): array {
93    $url = new Url(
94      'display_builder.api_paste',
95      [
96        'display_builder_instance' => $builder_id,
97        'node_id' => $node_id,
98        'parent_id' => $parent_id,
99        'slot_id' => $slot_id,
100        'slot_position' => $slot_position,
101      ]
102    );
103
104    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
105  }
106
107  /**
108   * Duplicate on placeholder click.
109   *
110   * @param array $build
111   *   The render array.
112   * @param string $builder_id
113   *   The instance entity ID.
114   * @param string $node_id
115   *   The node id to copy.
116   * @param string $parent_id
117   *   The instance id target.
118   * @param string $slot_id
119   *   The instance target slot id.
120   * @param string $slot_position
121   *   The slot position.
122   *
123   * @return array
124   *   The render array.
125   */
126  public function onClickDuplicate(array $build, string $builder_id, string $node_id, string $parent_id, string $slot_id, string $slot_position): array {
127    $url = new Url(
128      'display_builder.api_duplicate',
129      [
130        'display_builder_instance' => $builder_id,
131        'node_id' => $node_id,
132        'parent_id' => $parent_id,
133        'slot_id' => $slot_id,
134        'slot_position' => $slot_position,
135      ]
136    );
137
138    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
139  }
140
141  /**
142   * Drop a component_id, a block_id, or an instance_id, to the root dropzone.
143   *
144   * @param array $build
145   *   The render array.
146   * @param string $builder_id
147   *   The instance entity ID.
148   * @param string $island_id
149   *   The island initiating the event.
150   *
151   * @return array
152   *   The render array.
153   */
154  public function onRootDrop(array $build, string $builder_id, string $island_id): array {
155    $url = new Url(
156      'display_builder.api_root_attach',
157      [
158        'display_builder_instance' => $builder_id,
159        'from' => $island_id,
160      ]
161    );
162
163    $attributes = [
164      'hx-on:dragend' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "dragend")', $builder_id),
165    ];
166
167    return $this->setHtmxAttributes($build, $url, 'dragend consume', 'post', $attributes);
168  }
169
170  /**
171   * Drop a component_id, a block_id, or an instance_id, to a component slot.
172   *
173   * @param array $build
174   *   The render array.
175   * @param string $builder_id
176   *   The instance entity ID.
177   * @param string $island_id
178   *   The island initiating the event.
179   * @param string $node_id
180   *   The node id of the source.
181   * @param string $slot
182   *   The slot.
183   *
184   * @return array
185   *   The render array.
186   */
187  public function onSlotDrop(array $build, string $builder_id, string $island_id, string $node_id, string $slot): array {
188    $url = new Url(
189      'display_builder.api_slot_attach',
190      [
191        'display_builder_instance' => $builder_id,
192        'node_id' => $node_id,
193        'slot' => $slot,
194        'from' => $island_id,
195      ]
196    );
197
198    $attributes = [
199      'hx-on:dragend' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "dragend")', $builder_id),
200    ];
201
202    return $this->setHtmxAttributes($build, $url, 'dragend consume', 'post', $attributes);
203  }
204
205  /**
206   * When a component or block is clicked.
207   *
208   * @param array $build
209   *   The render array.
210   * @param string $builder_id
211   *   The instance entity ID.
212   * @param string $node_id
213   *   The node id of the source.
214   * @param string $title
215   *   The instance title.
216   * @param int $index
217   *   The instance index.
218   *
219   * @return array
220   *   The render array.
221   */
222  public function onInstanceClick(array $build, string $builder_id, string $node_id, string $title, int $index): array {
223    $url = new Url(
224      'display_builder.api_get',
225      [
226        'display_builder_instance' => $builder_id,
227        'node_id' => $node_id,
228      ]
229    );
230
231    $attributes = [
232      'tabindex' => '0',
233      'data-node-id' => $node_id,
234      'hx-on:click' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "click")', $builder_id),
235    ];
236
237    // If not set before we add information for contextual menu or drawer label.
238    if (!isset($build['#attributes']['data-node-title'])) {
239      // Only for icon case, remove suffix without loading label.
240      $attributes['data-node-title'] = \ucfirst(\trim(\str_replace(['renderable', '_'], ['', ' '], $title)));
241    }
242
243    if (!isset($build['#attributes']['data-slot-position'])) {
244      $attributes['data-slot-position'] = $index;
245    }
246
247    return $this->setHtmxAttributes($build, $url, 'click consume', 'get', $attributes);
248  }
249
250  /**
251   * When a value is changed in an instance island form.
252   *
253   * @param array $build
254   *   The render array.
255   * @param string $builder_id
256   *   The instance entity ID.
257   * @param string $island_id
258   *   The island initiating the event.
259   * @param string $node_id
260   *   The node id of the source.
261   *
262   * @return array
263   *   The render array.
264   */
265  public function onInstanceFormChange(array $build, string $builder_id, string $island_id, string $node_id): array {
266    $url = new Url(
267      'display_builder.api_update',
268      [
269        'display_builder_instance' => $builder_id,
270        'node_id' => $node_id,
271        'from' => $island_id,
272      ]
273    );
274
275    $extra_attr = [];
276
277    // Specific Wysiwyg extra code to make it work.
278    if (isset($build['source']['value']['#type']) && $build['source']['value']['#type'] === 'text_format') {
279      $extra_attr['hx-on:htmx:config-request'] = 'fixWysiwygUpdate(this, event)';
280      $build['#attached']['library'][] = 'display_builder/wysiwyg_fixes.js';
281    }
282
283    return $this->setHtmxAttributesOnSubKey($build, $url, 'change consume', 'put', $extra_attr, 'source');
284  }
285
286  /**
287   * When the update button is clicked in an instance island form.
288   *
289   * @param array $build
290   *   The render array.
291   * @param string $builder_id
292   *   The instance entity ID.
293   * @param string $island_id
294   *   The island initiating the event.
295   * @param string $node_id
296   *   The node id of the source.
297   *
298   * @return array
299   *   The render array.
300   */
301  public function onInstanceUpdateButtonClick(array $build, string $builder_id, string $island_id, string $node_id): array {
302    if (!isset($build['update']) || !isset($build['source']) || !isset($build['source']['#id'])) {
303      return $build;
304    }
305    $url = new Url(
306      'display_builder.api_update',
307      [
308        'display_builder_instance' => $builder_id,
309        'node_id' => $node_id,
310        'from' => $island_id,
311      ]
312    );
313
314    $extra_attr = [
315      'hx-include' => '#' . $build['source']['#id'],
316    ];
317
318    // Specific Wysiwyg extra code to make it work.
319    if (isset($build['source']['value']['#type']) && $build['source']['value']['#type'] === 'text_format') {
320      $extra_attr['hx-on:htmx:config-request'] = 'fixWysiwygUpdate(this, event)';
321      $build['#attached']['library'][] = 'display_builder/wysiwyg_fixes.js';
322    }
323
324    return $this->setHtmxAttributesOnSubKey($build, $url, 'click consume', 'put', $extra_attr, 'update');
325  }
326
327  /**
328   * When a value is changed in a third party island.
329   *
330   * @param array $build
331   *   The render array.
332   * @param string $builder_id
333   *   The instance entity ID.
334   * @param string $node_id
335   *   The node id of the source.
336   * @param string $island_id
337   *   The island id.
338   *
339   * @return array
340   *   The render array.
341   */
342  public function onThirdPartyFormChange(array $build, string $builder_id, string $node_id, string $island_id): array {
343    $url = new Url(
344      'display_builder.api_third_party_settings_update',
345      [
346        'display_builder_instance' => $builder_id,
347        'node_id' => $node_id,
348        'island_id' => $island_id,
349      ]
350    );
351
352    return $this->setHtmxAttributes($build, $url, 'change', 'put');
353  }
354
355  /**
356   * When the undo button is clicked.
357   *
358   * @param array $build
359   *   The render array.
360   * @param string $builder_id
361   *   The instance entity ID.
362   *
363   * @return array
364   *   The render array.
365   */
366  public function onUndo(array $build, string $builder_id): array {
367    $url = new Url(
368      'display_builder.api_undo',
369      [
370        'display_builder_instance' => $builder_id,
371      ]
372    );
373
374    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
375  }
376
377  /**
378   * When the undo button is clicked.
379   *
380   * @param array $build
381   *   The render array.
382   * @param string $builder_id
383   *   The instance entity ID.
384   *
385   * @return array
386   *   The render array.
387   */
388  public function onRedo(array $build, string $builder_id): array {
389    $url = new Url(
390      'display_builder.api_redo',
391      [
392        'display_builder_instance' => $builder_id,
393      ]
394    );
395
396    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
397  }
398
399  /**
400   * When the restore button is clicked.
401   *
402   * @param array $build
403   *   The render array.
404   * @param string $builder_id
405   *   The instance entity ID.
406   *
407   * @return array
408   *   The render array.
409   */
410  public function onReset(array $build, string $builder_id): array {
411    $url = new Url(
412      'display_builder.api_restore',
413      [
414        'display_builder_instance' => $builder_id,
415      ]
416    );
417
418    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
419  }
420
421  /**
422   * When the revert button is clicked.
423   *
424   * @param array $build
425   *   The render array.
426   * @param string $builder_id
427   *   The instance entity ID.
428   *
429   * @return array
430   *   The render array.
431   */
432  public function onRevert(array $build, string $builder_id): array {
433    $url = new Url(
434      'display_builder.api_revert',
435      [
436        'display_builder_instance' => $builder_id,
437      ]
438    );
439
440    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
441  }
442
443  /**
444   * When the history clear button is clicked.
445   *
446   * @param array $build
447   *   The render array.
448   * @param string $builder_id
449   *   The instance entity ID.
450   *
451   * @return array
452   *   The render array.
453   */
454  public function onClear(array $build, string $builder_id): array {
455    $url = new Url(
456      'display_builder.api_clear',
457      [
458        'display_builder_instance' => $builder_id,
459      ]
460    );
461
462    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
463  }
464
465  /**
466   * When the save button is clicked.
467   *
468   * @param array $build
469   *   The render array.
470   * @param string $builder_id
471   *   The instance entity ID.
472   *
473   * @return array
474   *   The render array.
475   */
476  public function onSave(array $build, string $builder_id): array {
477    $url = new Url(
478      'display_builder.api_save',
479      [
480        'display_builder_instance' => $builder_id,
481      ]
482    );
483
484    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
485  }
486
487  /**
488   * Sets HTMX attributes for a given URL, trigger, and method.
489   *
490   * @param array $build
491   *   The render array to modify.
492   * @param \Drupal\Core\Url $url
493   *   The URL for the HTMX request.
494   * @param string $trigger
495   *   The HTMX trigger.
496   * @param string $method
497   *   The HTTP method.
498   * @param array $extra_attr
499   *   (Optional) Extra attributes to add.
500   *
501   * @return array
502   *   The modified render array.
503   */
504  private function setHtmxAttributes(array $build, Url $url, string $trigger, string $method, array $extra_attr = []): array {
505    $attr = $this->setTrigger($trigger, $method, $url);
506    $attr = \array_merge($attr, $extra_attr);
507    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $attr);
508
509    return $build;
510  }
511
512  /**
513   * Sets HTMX attributes for a given URL, trigger, and method on a subkey.
514   *
515   * @param array $build
516   *   The render array to modify.
517   * @param \Drupal\Core\Url $url
518   *   The URL for the HTMX request.
519   * @param string $trigger
520   *   The HTMX trigger.
521   * @param string $method
522   *   The HTTP method.
523   * @param array $extra_attr
524   *   (Optional) Extra attributes to add.
525   * @param string $source_key
526   *   The name of the key to modify, example : update, source.
527   *
528   * @return array
529   *   The modified render array.
530   */
531  private function setHtmxAttributesOnSubKey(array $build, Url $url, string $trigger, string $method, array $extra_attr, string $source_key): array {
532    if (!isset($build[$source_key])) {
533      return $build;
534    }
535    $attr = $this->setTrigger($trigger, $method, $url);
536    $attr = \array_merge($attr, $extra_attr);
537    $build[$source_key]['#attributes'] = \array_merge($build[$source_key]['#attributes'] ?? [], $attr);
538
539    return $build;
540  }
541
542}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

HtmxEvents->onClear
454  public function onClear(array $build, string $builder_id): array {
455    $url = new Url(
456      'display_builder.api_clear',
457      [
458        'display_builder_instance' => $builder_id,
459      ]
460    );
461
462    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onClickDelete
30  public function onClickDelete(array $build, string $builder_id, string $node_id): array {
31    $url = new Url(
32      'display_builder.api_delete',
33      [
34        'display_builder_instance' => $builder_id,
35        'node_id' => $node_id,
36      ]
37    );
38
39    $attributes = [
40      'hx-on:click' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "close")', $builder_id),
41    ];
42
43    return $this->setHtmxAttributes($build, $url, 'click consume', 'delete', $attributes);
HtmxEvents->onClickDuplicate
126  public function onClickDuplicate(array $build, string $builder_id, string $node_id, string $parent_id, string $slot_id, string $slot_position): array {
127    $url = new Url(
128      'display_builder.api_duplicate',
129      [
130        'display_builder_instance' => $builder_id,
131        'node_id' => $node_id,
132        'parent_id' => $parent_id,
133        'slot_id' => $slot_id,
134        'slot_position' => $slot_position,
135      ]
136    );
137
138    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onClickPaste
92  public function onClickPaste(array $build, string $builder_id, string $node_id, string $parent_id, string $slot_id, string $slot_position): array {
93    $url = new Url(
94      'display_builder.api_paste',
95      [
96        'display_builder_instance' => $builder_id,
97        'node_id' => $node_id,
98        'parent_id' => $parent_id,
99        'slot_id' => $slot_id,
100        'slot_position' => $slot_position,
101      ]
102    );
103
104    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onClickSavePreset
61  public function onClickSavePreset(array $build, string $builder_id, string $node_id, MarkupInterface|string $prompt): array {
62    $url = new Url(
63      'display_builder.api_save_preset',
64      [
65        'display_builder_instance' => $builder_id,
66        'node_id' => $node_id,
67      ]
68    );
69
70    return $this->setHtmxAttributes($build, $url, 'click consume', 'post', ['hx-prompt' => $prompt]);
HtmxEvents->onInstanceClick
222  public function onInstanceClick(array $build, string $builder_id, string $node_id, string $title, int $index): array {
223    $url = new Url(
224      'display_builder.api_get',
225      [
226        'display_builder_instance' => $builder_id,
227        'node_id' => $node_id,
228      ]
229    );
230
231    $attributes = [
232      'tabindex' => '0',
233      'data-node-id' => $node_id,
234      'hx-on:click' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "click")', $builder_id),
235    ];
236
237    // If not set before we add information for contextual menu or drawer label.
238    if (!isset($build['#attributes']['data-node-title'])) {
240      $attributes['data-node-title'] = \ucfirst(\trim(\str_replace(['renderable', '_'], ['', ' '], $title)));
241    }
242
243    if (!isset($build['#attributes']['data-slot-position'])) {
243    if (!isset($build['#attributes']['data-slot-position'])) {
244      $attributes['data-slot-position'] = $index;
245    }
246
247    return $this->setHtmxAttributes($build, $url, 'click consume', 'get', $attributes);
247    return $this->setHtmxAttributes($build, $url, 'click consume', 'get', $attributes);
HtmxEvents->onInstanceFormChange
265  public function onInstanceFormChange(array $build, string $builder_id, string $island_id, string $node_id): array {
266    $url = new Url(
267      'display_builder.api_update',
268      [
269        'display_builder_instance' => $builder_id,
270        'node_id' => $node_id,
271        'from' => $island_id,
272      ]
273    );
274
275    $extra_attr = [];
276
277    // Specific Wysiwyg extra code to make it work.
278    if (isset($build['source']['value']['#type']) && $build['source']['value']['#type'] === 'text_format') {
278    if (isset($build['source']['value']['#type']) && $build['source']['value']['#type'] === 'text_format') {
279      $extra_attr['hx-on:htmx:config-request'] = 'fixWysiwygUpdate(this, event)';
280      $build['#attached']['library'][] = 'display_builder/wysiwyg_fixes.js';
281    }
282
283    return $this->setHtmxAttributesOnSubKey($build, $url, 'change consume', 'put', $extra_attr, 'source');
283    return $this->setHtmxAttributesOnSubKey($build, $url, 'change consume', 'put', $extra_attr, 'source');
HtmxEvents->onInstanceUpdateButtonClick
301  public function onInstanceUpdateButtonClick(array $build, string $builder_id, string $island_id, string $node_id): array {
302    if (!isset($build['update']) || !isset($build['source']) || !isset($build['source']['#id'])) {
302    if (!isset($build['update']) || !isset($build['source']) || !isset($build['source']['#id'])) {
302    if (!isset($build['update']) || !isset($build['source']) || !isset($build['source']['#id'])) {
303      return $build;
305    $url = new Url(
306      'display_builder.api_update',
307      [
308        'display_builder_instance' => $builder_id,
309        'node_id' => $node_id,
310        'from' => $island_id,
311      ]
312    );
313
314    $extra_attr = [
315      'hx-include' => '#' . $build['source']['#id'],
316    ];
317
318    // Specific Wysiwyg extra code to make it work.
319    if (isset($build['source']['value']['#type']) && $build['source']['value']['#type'] === 'text_format') {
319    if (isset($build['source']['value']['#type']) && $build['source']['value']['#type'] === 'text_format') {
320      $extra_attr['hx-on:htmx:config-request'] = 'fixWysiwygUpdate(this, event)';
321      $build['#attached']['library'][] = 'display_builder/wysiwyg_fixes.js';
322    }
323
324    return $this->setHtmxAttributesOnSubKey($build, $url, 'click consume', 'put', $extra_attr, 'update');
324    return $this->setHtmxAttributesOnSubKey($build, $url, 'click consume', 'put', $extra_attr, 'update');
HtmxEvents->onRedo
388  public function onRedo(array $build, string $builder_id): array {
389    $url = new Url(
390      'display_builder.api_redo',
391      [
392        'display_builder_instance' => $builder_id,
393      ]
394    );
395
396    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onReset
410  public function onReset(array $build, string $builder_id): array {
411    $url = new Url(
412      'display_builder.api_restore',
413      [
414        'display_builder_instance' => $builder_id,
415      ]
416    );
417
418    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onRevert
432  public function onRevert(array $build, string $builder_id): array {
433    $url = new Url(
434      'display_builder.api_revert',
435      [
436        'display_builder_instance' => $builder_id,
437      ]
438    );
439
440    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onRootDrop
154  public function onRootDrop(array $build, string $builder_id, string $island_id): array {
155    $url = new Url(
156      'display_builder.api_root_attach',
157      [
158        'display_builder_instance' => $builder_id,
159        'from' => $island_id,
160      ]
161    );
162
163    $attributes = [
164      'hx-on:dragend' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "dragend")', $builder_id),
165    ];
166
167    return $this->setHtmxAttributes($build, $url, 'dragend consume', 'post', $attributes);
HtmxEvents->onSave
476  public function onSave(array $build, string $builder_id): array {
477    $url = new Url(
478      'display_builder.api_save',
479      [
480        'display_builder_instance' => $builder_id,
481      ]
482    );
483
484    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->onSlotDrop
187  public function onSlotDrop(array $build, string $builder_id, string $island_id, string $node_id, string $slot): array {
188    $url = new Url(
189      'display_builder.api_slot_attach',
190      [
191        'display_builder_instance' => $builder_id,
192        'node_id' => $node_id,
193        'slot' => $slot,
194        'from' => $island_id,
195      ]
196    );
197
198    $attributes = [
199      'hx-on:dragend' => \sprintf('Drupal.displayBuilder.handleSecondDrawer(%s, this, event, "dragend")', $builder_id),
200    ];
201
202    return $this->setHtmxAttributes($build, $url, 'dragend consume', 'post', $attributes);
HtmxEvents->onThirdPartyFormChange
342  public function onThirdPartyFormChange(array $build, string $builder_id, string $node_id, string $island_id): array {
343    $url = new Url(
344      'display_builder.api_third_party_settings_update',
345      [
346        'display_builder_instance' => $builder_id,
347        'node_id' => $node_id,
348        'island_id' => $island_id,
349      ]
350    );
351
352    return $this->setHtmxAttributes($build, $url, 'change', 'put');
HtmxEvents->onUndo
366  public function onUndo(array $build, string $builder_id): array {
367    $url = new Url(
368      'display_builder.api_undo',
369      [
370        'display_builder_instance' => $builder_id,
371      ]
372    );
373
374    return $this->setHtmxAttributes($build, $url, 'click consume', 'post');
HtmxEvents->setHtmxAttributes
504  private function setHtmxAttributes(array $build, Url $url, string $trigger, string $method, array $extra_attr = []): array {
505    $attr = $this->setTrigger($trigger, $method, $url);
506    $attr = \array_merge($attr, $extra_attr);
507    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $attr);
508
509    return $build;
HtmxEvents->setHtmxAttributesOnSubKey
531  private function setHtmxAttributesOnSubKey(array $build, Url $url, string $trigger, string $method, array $extra_attr, string $source_key): array {
532    if (!isset($build[$source_key])) {
533      return $build;
535    $attr = $this->setTrigger($trigger, $method, $url);
536    $attr = \array_merge($attr, $extra_attr);
537    $build[$source_key]['#attributes'] = \array_merge($build[$source_key]['#attributes'] ?? [], $attr);
538
539    return $build;