Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
62.28% covered (warning)
62.28%
71 / 114
51.11% covered (warning)
51.11%
23 / 45
15.91% covered (danger)
15.91%
7 / 44
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
WireframePanelBase
62.28% covered (warning)
62.28%
71 / 114
51.11% covered (warning)
51.11%
23 / 45
15.91% covered (danger)
15.91%
7 / 44
16.67% covered (danger)
16.67%
1 / 6
396.64
0.00% covered (danger)
0.00%
0 / 1
 create
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 build
42.86% covered (danger)
42.86%
3 / 7
66.67% covered (warning)
66.67%
2 / 3
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 buildSingleComponent
88.00% covered (warning)
88.00%
44 / 50
64.29% covered (warning)
64.29%
9 / 14
11.76% covered (danger)
11.76%
2 / 17
0.00% covered (danger)
0.00%
0 / 1
40.66
 buildSingleBlock
83.33% covered (warning)
83.33%
15 / 18
71.43% covered (warning)
71.43%
5 / 7
12.50% covered (danger)
12.50%
1 / 8
0.00% covered (danger)
0.00%
0 / 1
21.75
 addThirdPartySettingsSummary
22.22% covered (danger)
22.22%
2 / 9
16.67% covered (danger)
16.67%
2 / 12
12.50% covered (danger)
12.50%
1 / 8
0.00% covered (danger)
0.00%
0 / 1
30.12
 addComponentSettingsSummary
14.81% covered (danger)
14.81%
4 / 27
50.00% covered (danger)
50.00%
4 / 8
12.50% covered (danger)
12.50%
1 / 8
0.00% covered (danger)
0.00%
0 / 1
14.72
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Plugin\display_builder\Island;
6
7use Drupal\Core\StringTranslation\TranslatableMarkup;
8use Drupal\display_builder\InstanceInterface;
9use Drupal\display_builder\Island\IslandPluginManagerInterface;
10use Drupal\display_builder\SourceWithSlotsInterface;
11use Drupal\display_builder\ThirdPartySettingsInterface;
12use Symfony\Component\DependencyInjection\ContainerInterface;
13
14/**
15 * Shared implementation for the schematic (wireframe) View panels.
16 *
17 * Renders a hierarchical, preview-less "card per element" view built from the
18 * display_builder:layer component. Scaffold panel extend it; Scaffold
19 * additionally renders an allowlist of components with their real output.
20 */
21abstract class WireframePanelBase extends BuilderPanel {
22
23  /**
24   * Island plugins manager.
25   */
26  protected IslandPluginManagerInterface $islandManager;
27
28  /**
29   * {@inheritdoc}
30   */
31  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
32    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
33    $instance->islandManager = $container->get('plugin.manager.db_island');
34
35    return $instance;
36  }
37
38  /**
39   * {@inheritdoc}
40   */
41  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
42    $build = $this->buildRootDropzone($builder, $data);
43
44    if (empty($build['#slots']['content'] ?? [])) {
45      // Load en empty component to have any assets with it.
46      $build['#slots']['content'] = [
47        '#type' => 'component',
48        '#component' => 'display_builder:layer',
49      ];
50    }
51
52    return $build;
53  }
54
55  /**
56   * {@inheritdoc}
57   */
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
62      return NULL;
63    }
64
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
113      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $testid_source);
114    }
115    elseif (isset($data['source_id'])) {
116      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $data['source_id']);
117    }
118    elseif (\is_string(\reset($data))) {
119      $build['#attributes']['data-testid'] = \sprintf('layer_%s', \reset($data));
120    }
121
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
127
128  /**
129   * {@inheritdoc}
130   */
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
135      $label['summary'] = (string) $this->t('Field: @label', ['@label' => $label['label']]);
136    }
137
138    $build = [
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
149      $this->logger->error('[WireframePanelBase::buildSingleBlock] missing instance ID. <pre>' . \print_r($data, TRUE) . '</pre>');
150
151      return $build;
152    }
153
154    $build = $this->addThirdPartySettingsSummary($data, $build);
155
156    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $this->buildNodeAttributes($label['summary'], $index, $data['source_id'] ?? NULL));
157    $build['#attributes']['data-testid'] = $label['label'] ?? '_' . $index;
158
159    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $label['summary'], $index);
160  }
161
162  /**
163   * Add third party settings summary to layer's info slot.
164   *
165   * @param array $data
166   *   The node data.
167   * @param array $build
168   *   The layer component renderable array.
169   *
170   * @return array
171   *   The layer component renderable array.
172   */
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
175      return $build;
176    }
177
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
196
197  /**
198   * Add config settings summary to layer's info slot.
199   *
200   * @param \Drupal\display_builder\SourceWithSlotsInterface $source
201   *   The source plugin.
202   * @param array $build
203   *   The layer component renderable array.
204   *
205   * @return array
206   *   The layer component renderable array.
207   */
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
222      return $build;
223    }
224
225    $summary = [
226      [
227        '#type' => 'html_tag',
228        '#tag' => 'em',
229        '#value' => new TranslatableMarkup('Config'),
230      ],
231      [
232        '#type' => 'html_tag',
233        '#tag' => 'ul',
234        '#attributes' => [
235          'class' => ['summary'],
236        ],
237        0 => $items,
238      ],
239    ];
240
241    $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
242
243    return $build;
244  }
245
246}

Paths

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

WireframePanelBase->addComponentSettingsSummary
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
212      if ($item !== NULL) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
222      return $build;
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
212      if ($item !== NULL) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
227        '#type' => 'html_tag',
228        '#tag' => 'em',
229        '#value' => new TranslatableMarkup('Config'),
230      ],
231      [
232        '#type' => 'html_tag',
233        '#tag' => 'ul',
234        '#attributes' => [
235          'class' => ['summary'],
236        ],
237        0 => $items,
238      ],
239    ];
240
241    $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
242
243    return $build;
244  }
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
212      if ($item !== NULL) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
222      return $build;
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
212      if ($item !== NULL) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
227        '#type' => 'html_tag',
228        '#tag' => 'em',
229        '#value' => new TranslatableMarkup('Config'),
230      ],
231      [
232        '#type' => 'html_tag',
233        '#tag' => 'ul',
234        '#attributes' => [
235          'class' => ['summary'],
236        ],
237        0 => $items,
238      ],
239    ];
240
241    $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
242
243    return $build;
244  }
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
222      return $build;
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
227        '#type' => 'html_tag',
228        '#tag' => 'em',
229        '#value' => new TranslatableMarkup('Config'),
230      ],
231      [
232        '#type' => 'html_tag',
233        '#tag' => 'ul',
234        '#attributes' => [
235          'class' => ['summary'],
236        ],
237        0 => $items,
238      ],
239    ];
240
241    $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
242
243    return $build;
244  }
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
222      return $build;
208  private function addComponentSettingsSummary(SourceWithSlotsInterface $source, array $build): array {
209    $items = [];
210
211    foreach ($source->settingsSummary() as $item) {
 
211    foreach ($source->settingsSummary() as $item) {
212      if ($item !== NULL) {
213        $items[] = [
214          '#type' => 'html_tag',
215          '#tag' => 'li',
216          '#value' => $item,
217        ];
218      }
219    }
220
221    if (empty($items)) {
 
227        '#type' => 'html_tag',
228        '#tag' => 'em',
229        '#value' => new TranslatableMarkup('Config'),
230      ],
231      [
232        '#type' => 'html_tag',
233        '#tag' => 'ul',
234        '#attributes' => [
235          'class' => ['summary'],
236        ],
237        0 => $items,
238      ],
239    ];
240
241    $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
242
243    return $build;
244  }
WireframePanelBase->addThirdPartySettingsSummary
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
175      return $build;
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
 
185        continue;
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
 
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
 
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
 
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
 
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
173  private function addThirdPartySettingsSummary(array $data, array $build): array {
174    if (!isset($data['third_party_settings'])) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
 
178    foreach ($data['third_party_settings'] as $provider => $settings) {
179      // In Display Builder, third_party_settings providers can be:
180      // - an island plugin ID (our 'normal' way)
181      // - a Drupal module name (the Drupal way, found in displays imported and
182      // converted, not leveraged by us for now but we may do it later).
183      // So, let's check the plugin ID exists before running logic.
184      if (!$this->islandManager->hasDefinition($provider)) {
185        continue;
186      }
187      $island = $this->islandManager->createInstance($provider, $settings);
188
189      if ($island instanceof ThirdPartySettingsInterface && $summary = $island->getSummary()) {
190        $build['#slots']['info'] = \array_merge($build['#slots']['info'] ?? [], $summary);
191      }
192    }
193
194    return $build;
195  }
WireframePanelBase->build
41  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
42    $build = $this->buildRootDropzone($builder, $data);
43
44    if (empty($build['#slots']['content'] ?? [])) {
 
46      $build['#slots']['content'] = [
47        '#type' => 'component',
48        '#component' => 'display_builder:layer',
49      ];
50    }
51
52    return $build;
 
52    return $build;
53  }
41  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
42    $build = $this->buildRootDropzone($builder, $data);
43
44    if (empty($build['#slots']['content'] ?? [])) {
 
52    return $build;
53  }
WireframePanelBase->buildSingleBlock
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
135      $label['summary'] = (string) $this->t('Field: @label', ['@label' => $label['label']]);
136    }
137
138    $build = [
139      '#type' => 'component',
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
149      $this->logger->error('[WireframePanelBase::buildSingleBlock] missing instance ID. <pre>' . \print_r($data, TRUE) . '</pre>');
150
151      return $build;
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
135      $label['summary'] = (string) $this->t('Field: @label', ['@label' => $label['label']]);
136    }
137
138    $build = [
139      '#type' => 'component',
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
154    $build = $this->addThirdPartySettingsSummary($data, $build);
155
156    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $this->buildNodeAttributes($label['summary'], $index, $data['source_id'] ?? NULL));
157    $build['#attributes']['data-testid'] = $label['label'] ?? '_' . $index;
158
159    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $label['summary'], $index);
160  }
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
149      $this->logger->error('[WireframePanelBase::buildSingleBlock] missing instance ID. <pre>' . \print_r($data, TRUE) . '</pre>');
150
151      return $build;
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
154    $build = $this->addThirdPartySettingsSummary($data, $build);
155
156    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $this->buildNodeAttributes($label['summary'], $index, $data['source_id'] ?? NULL));
157    $build['#attributes']['data-testid'] = $label['label'] ?? '_' . $index;
158
159    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $label['summary'], $index);
160  }
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
135      $label['summary'] = (string) $this->t('Field: @label', ['@label' => $label['label']]);
136    }
137
138    $build = [
139      '#type' => 'component',
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
149      $this->logger->error('[WireframePanelBase::buildSingleBlock] missing instance ID. <pre>' . \print_r($data, TRUE) . '</pre>');
150
151      return $build;
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
135      $label['summary'] = (string) $this->t('Field: @label', ['@label' => $label['label']]);
136    }
137
138    $build = [
139      '#type' => 'component',
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
154    $build = $this->addThirdPartySettingsSummary($data, $build);
155
156    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $this->buildNodeAttributes($label['summary'], $index, $data['source_id'] ?? NULL));
157    $build['#attributes']['data-testid'] = $label['label'] ?? '_' . $index;
158
159    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $label['summary'], $index);
160  }
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
149      $this->logger->error('[WireframePanelBase::buildSingleBlock] missing instance ID. <pre>' . \print_r($data, TRUE) . '</pre>');
150
151      return $build;
131  protected function buildSingleBlock(InstanceInterface $instance, string $node_id, array $data, int $index = 0): array {
132    $label = $this->slotSourceProxy->getLabelWithSummary($data, $this->configuration['contexts'] ?? []);
133
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
134    if (isset($data['source_id']) && $data['source_id'] === 'entity_field') {
 
139      '#type' => 'component',
140      '#component' => 'display_builder:layer',
141      '#slots' => [
142        'title' => $label['summary'],
143      ],
144    ];
145
146    $node_id = $node_id ?: $data['node_id'] ?? NULL;
147
148    if (!$node_id) {
 
154    $build = $this->addThirdPartySettingsSummary($data, $build);
155
156    $build['#attributes'] = \array_merge($build['#attributes'] ?? [], $this->buildNodeAttributes($label['summary'], $index, $data['source_id'] ?? NULL));
157    $build['#attributes']['data-testid'] = $label['label'] ?? '_' . $index;
158
159    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $label['summary'], $index);
160  }
WireframePanelBase->buildSingleComponent
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
62      return NULL;
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
112    if ($testid_source !== NULL) {
113      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $testid_source);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
115    elseif (isset($data['source_id'])) {
116      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $data['source_id']);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
119      $build['#attributes']['data-testid'] = \sprintf('layer_%s', \reset($data));
120    }
121
122    $build = $this->addThirdPartySettingsSummary($data, $build);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
112    if ($testid_source !== NULL) {
113      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $testid_source);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
115    elseif (isset($data['source_id'])) {
116      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $data['source_id']);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
119      $build['#attributes']['data-testid'] = \sprintf('layer_%s', \reset($data));
120    }
121
122    $build = $this->addThirdPartySettingsSummary($data, $build);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
112    if ($testid_source !== NULL) {
113      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $testid_source);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
115    elseif (isset($data['source_id'])) {
116      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $data['source_id']);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
119      $build['#attributes']['data-testid'] = \sprintf('layer_%s', \reset($data));
120    }
121
122    $build = $this->addThirdPartySettingsSummary($data, $build);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
112    if ($testid_source !== NULL) {
113      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $testid_source);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
115    elseif (isset($data['source_id'])) {
116      $build['#attributes']['data-testid'] = \sprintf('layer_%s', $data['source_id']);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
119      $build['#attributes']['data-testid'] = \sprintf('layer_%s', \reset($data));
120    }
121
122    $build = $this->addThirdPartySettingsSummary($data, $build);
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
58  protected function buildSingleComponent(InstanceInterface $instance, string $node_id, SourceWithSlotsInterface $source, array $data, int $index = 0): ?array {
59    $info = $this->resolveComponentInfo($source, $data, $node_id);
60
61    if ($info === NULL) {
 
65    ['label' => $label, 'instance_id' => $node_id] = $info;
66
67    $slots = [];
68
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
 
69    foreach ($source->getSlotDefinitions() as $slot_id => $definition) {
70      $dropzone = [
71        '#type' => 'component',
72        '#component' => 'display_builder:dropzone',
73        '#attributes' => \array_merge(
74          [
75            // Required for JavaScript @see components/dropzone/dropzone.js.
76            'data-db-id' => (string) $instance->id(),
77            'data-testid' => 'dropzone_' . $slot_id,
78          ],
79          $this->buildSlotAttributes($slot_id, $definition['title'], $node_id, $label)
80        ),
81      ];
82
83      if ($sources = $source->getSlotValue($slot_id)) {
84        $dropzone['#slots']['content'] = $this->digFromSlot($instance, $sources);
85      }
86      $dropzone = $this->htmxEvents->onSlotDrop($dropzone, (string) $instance->id(), $this->getPluginID(), $node_id, $slot_id);
87      $slots[] = [
88        [
89          '#plain_text' => $definition['title'],
90        ],
91        $dropzone,
92      ];
93    }
94
95    $build = [
96      '#type' => 'component',
97      '#component' => 'display_builder:layer',
98      '#slots' => [
99        'title' => $label,
100        'children' => $slots,
101      ],
102      '#attributes' => \array_merge(
103        $this->buildNodeAttributes($label, $index)
104      ),
105    ];
106
107    $testid_source = $data['source']['component']['component_id']
108      ?? $data['source']['plugin_id']
109      ?? $data['source']['derivable_context']
110      ?? NULL;
111
112    if ($testid_source !== NULL) {
 
115    elseif (isset($data['source_id'])) {
 
118    elseif (\is_string(\reset($data))) {
 
122    $build = $this->addThirdPartySettingsSummary($data, $build);
123    $build = $this->addComponentSettingsSummary($source, $build);
124
125    return $this->htmxEvents->onInstanceClick($build, (string) $instance->id(), $node_id, $source->label(), $index);
126  }
WireframePanelBase->create
31  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
32    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
33    $instance->islandManager = $container->get('plugin.manager.db_island');
34
35    return $instance;
36  }