Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
87.59% covered (warning)
87.59%
120 / 137
82.29% covered (warning)
82.29%
79 / 96
50.00% covered (danger)
50.00%
32 / 64
57.89% covered (warning)
57.89%
11 / 19
CRAP
0.00% covered (danger)
0.00%
0 / 1
ComponentSource
87.59% covered (warning)
87.59%
120 / 137
82.29% covered (warning)
82.29%
79 / 96
50.00% covered (danger)
50.00%
32 / 64
57.89% covered (warning)
57.89%
11 / 19
404.12
0.00% covered (danger)
0.00%
0 / 1
 getChoice
100.00% covered (success)
100.00%
1 / 1
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
 getSlotDefinitions
57.14% covered (warning)
57.14%
4 / 7
50.00% covered (danger)
50.00%
3 / 6
33.33% covered (danger)
33.33%
1 / 3
0.00% covered (danger)
0.00%
0 / 1
5.67
 getSlotValues
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
6 / 6
25.00% covered (danger)
25.00%
1 / 4
100.00% covered (success)
100.00%
1 / 1
6.80
 getSlotValue
100.00% covered (success)
100.00%
1 / 1
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
 setSlotValue
100.00% covered (success)
100.00%
2 / 2
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
 setSlotRenderable
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
 getSlotPath
100.00% covered (success)
100.00%
1 / 1
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
 settingsSummary
91.67% covered (success)
91.67%
11 / 12
91.67% covered (success)
91.67%
11 / 12
36.36% covered (danger)
36.36%
4 / 11
0.00% covered (danger)
0.00%
0 / 1
15.28
 settingsFormPropsOnly
93.75% covered (success)
93.75%
15 / 16
80.00% covered (warning)
80.00%
4 / 5
33.33% covered (danger)
33.33%
1 / 3
0.00% covered (danger)
0.00%
0 / 1
5.67
 getGroup
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getComponentMetadata
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
3 / 3
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
2.50
 buildVariantSummary
87.50% covered (warning)
87.50%
7 / 8
85.71% covered (warning)
85.71%
6 / 7
50.00% covered (danger)
50.00%
3 / 6
0.00% covered (danger)
0.00%
0 / 1
6.00
 buildPropsSummary
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
8 / 8
60.00% covered (warning)
60.00%
3 / 5
100.00% covered (success)
100.00%
1 / 1
5.02
 processProperty
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 isUiStyleAttribute
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 formatUiStyleSummary
83.33% covered (warning)
83.33%
5 / 6
66.67% covered (warning)
66.67%
4 / 6
33.33% covered (danger)
33.33%
1 / 3
0.00% covered (danger)
0.00%
0 / 1
5.67
 processStandardProperty
87.50% covered (warning)
87.50%
7 / 8
80.00% covered (warning)
80.00%
4 / 5
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
3.33
 normalizeValue
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
11 / 11
66.67% covered (warning)
66.67%
4 / 6
100.00% covered (success)
100.00%
1 / 1
5.93
 flattenArrayToString
63.64% covered (warning)
63.64%
7 / 11
61.54% covered (warning)
61.54%
8 / 13
28.57% covered (danger)
28.57%
2 / 7
0.00% covered (danger)
0.00%
0 / 1
19.12
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Plugin\UiPatterns\Source;
6
7use Drupal\Core\Form\FormStateInterface;
8use Drupal\Core\StringTranslation\TranslatableMarkup;
9use Drupal\display_builder\SourceWithSlotsInterface;
10use Drupal\ui_patterns\Attribute\Source;
11use Drupal\ui_patterns\Plugin\UiPatterns\Source\ComponentSource as UpstreamComponentSource;
12
13/**
14 * Plugin implementation of the source.
15 */
16#[Source(
17  id: 'component',
18  label: new TranslatableMarkup('Component'),
19  description: new TranslatableMarkup('Add a Component'),
20  prop_types: ['slot']
21)]
22class ComponentSource extends UpstreamComponentSource implements SourceWithSlotsInterface {
23
24  /**
25   * {@inheritdoc}
26   */
27  public function getChoice(array $settings): string {
28    return $settings['component']['component_id'] ?? $settings['component_id'] ?? '';
29  }
30
31  /**
32   * {@inheritdoc}
33   */
34  public function getSlotDefinitions(): array {
35    $component_id = $this->settings['component']['component_id'] ?? '';
36
37    if (!$component_id) {
38      return [];
39    }
40
41    try {
42      $definition = $this->componentManager->getDefinition($component_id);
43    }
44    catch (\Throwable $th) {
45      return [];
46    }
47
48    return $definition['slots'] ?? [];
49  }
50
51  /**
52   * {@inheritdoc}
53   */
54  public function getSlotValues(): array {
55    $slots = [];
56
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
59        $slots[$slot_id] = $this->getSlotValue($slot_id);
60      }
61    }
62
63    return $slots;
64  }
65
66  /**
67   * {@inheritdoc}
68   */
69  public function getSlotValue(string $slot_id): array {
70    return $this->settings['component']['slots'][$slot_id]['sources'] ?? [];
71  }
72
73  /**
74   * {@inheritdoc}
75   */
76  public function setSlotValue(string $slot_id, array $slot): array {
77    $this->settings['component']['slots'][$slot_id]['sources'] = $slot;
78
79    return $this->settings;
80  }
81
82  /**
83   * {@inheritdoc}
84   */
85  public function setSlotRenderable(array $build, string $slot_id, array $slot): array {
86    $build['#slots'][$slot_id] = $slot;
87    // Prevent the slot to be generated again.
88    unset($build['#ui_patterns']['slots'][$slot_id]);
89
90    return $build;
91  }
92
93  /**
94   * {@inheritdoc}
95   */
96  public static function getSlotPath(string $slot_id): array {
97    return ['component', 'slots', $slot_id, 'sources'];
98  }
99
100  /**
101   * {@inheritdoc}
102   */
103  public function settingsSummary(): array {
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
107      return [];
108    }
109
110    if (empty($data['props']) && empty($data['variant_id'])) {
111      return [];
112    }
113
114    try {
115      $component = $this->componentManager->getDefinition($data['component_id']);
116    }
117    catch (\Throwable $th) {
118      return [];
119    }
120
121    $variant = $this->buildVariantSummary($component, $data);
122    $props = $this->buildPropsSummary($component, $data);
123
124    $items = \array_merge($variant, $props);
125
126    return $items;
127  }
128
129  /**
130   * {@inheritdoc}
131   */
132  public function settingsFormPropsOnly(array $form, FormStateInterface $form_state): array {
133    $form = $this->settingsForm($form, $form_state);
134    $data = $this->getSetting('component');
135    $component_id = $data['component_id'] ?? NULL;
136
137    if (!$component_id) {
138      return $form;
139    }
140
141    if (!isset($form['component']['component_id'])) {
142      $form['component']['component_id'] = [
143        '#type' => 'hidden',
144        '#value' => $component_id,
145      ];
146    }
147    $form['component']['#render_slots'] = FALSE;
148    $form['component']['#component_id'] = $component_id;
149
150    return \array_merge(
151      ['info' => $this->getComponentMetadata($component_id)],
152      $form
153    );
154  }
155
156  /**
157   * Get the group name for this source plugin.
158   *
159   * This method will be implemented in Drupal\ui_patterns\SourceInterface.
160   *
161   * @return string
162   *   The name of the group.
163   */
164  public function getGroup(): string {
165    $component_id = $this->settings['component']['component_id'] ?? '';
166
167    if (!$component_id) {
168      return '';
169    }
170
171    $definition = $this->componentManager->getDefinition($component_id);
172
173    return $definition['group'] ?? '';
174  }
175
176  /**
177   * Get component metadata.
178   *
179   * @param string $component_id
180   *   The component ID.
181   *
182   * @return array
183   *   A renderable array.
184   */
185  protected function getComponentMetadata(string $component_id): array {
186    $component = $this->componentManager->find($component_id);
187    $build = [];
188
189    if ($description = $component->metadata->description) {
190      $description = [
191        [
192          '#type' => 'html_tag',
193          '#tag' => 'p',
194          '#value' => $description,
195          '#attributes' => [
196            'class' => ['description'],
197          ],
198        ],
199        [
200          '#type' => 'html_tag',
201          '#tag' => 'sl-button',
202          '#value' => new TranslatableMarkup('Hide description'),
203          '#attributes' => [
204            'size' => 'small',
205            'variant' => 'default',
206            'class' => ['db-description-toggle'],
207          ],
208        ],
209      ];
210      $build[] = [
211        '#type' => 'html_tag',
212        '#tag' => 'div',
213        'content' => $description,
214      ];
215    }
216
217    return $build;
218  }
219
220  /**
221   * Builds variant summary items.
222   *
223   * @param array $component
224   *   The component definition.
225   * @param array $data
226   *   The component data.
227   *
228   * @return array
229   *   Summary items for variants.
230   */
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
233        || $data['variant_id']['source']['value'] === 'default') {
234      return [];
235    }
236
237    $variantValue = $data['variant_id']['source']['value'];
238    $variantLabel = $component['variants'][$variantValue]['title'] ?? $variantValue;
239
240    if (empty($variantLabel)) {
241      return [];
242    }
243
244    return [new TranslatableMarkup('Variant: @variant', ['@variant' => $variantLabel])];
245  }
246
247  /**
248   * Builds props summary items.
249   *
250   * @param array $component
251   *   The component definition.
252   * @param array $data
253   *   The component data.
254   *
255   * @return array
256   *   Summary items for props.
257   */
258  private function buildPropsSummary(array $component, array $data): array {
259    if (empty($data['props'])) {
260      return [];
261    }
262
263    $items = [];
264    $propertyConfigs = $component['props']['properties'] ?? [];
265
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
274        $items[] = $summaryItem;
275      }
276    }
277
278    return $items;
279  }
280
281  /**
282   * Processes a property configuration to generate a summary string.
283   *
284   * @param array $sourceConfig
285   *   The source configuration array.
286   * @param array|null $propertyConfig
287   *   The property configuration array or NULL if not available.
288   * @param string $sourceId
289   *   The source identifier.
290   *
291   * @return string|null
292   *   The formatted summary string or NULL if no value is available.
293   */
294  private function processProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
295    if ($this->isUiStyleAttribute($sourceConfig)) {
296      return $this->formatUiStyleSummary($sourceConfig, $propertyConfig);
297    }
298
299    return $this->processStandardProperty($sourceConfig, $propertyConfig, $sourceId);
300  }
301
302  /**
303   * Checks if the source configuration is for UI style attributes.
304   *
305   * @param array $sourceConfig
306   *   The source configuration array.
307   *
308   * @return bool
309   *   TRUE if it's a UI style attribute configuration, FALSE otherwise.
310   */
311  private function isUiStyleAttribute(array $sourceConfig): bool {
312    return ($sourceConfig['source_id'] ?? NULL) === 'ui_styles_attributes'
313          && isset($sourceConfig['source']['styles']['selected']);
314  }
315
316  /**
317   * Formats a UI style summary string.
318   *
319   * @param array $sourceConfig
320   *   The source configuration array.
321   * @param array|null $propertyConfig
322   *   The property configuration array or NULL if not available.
323   *
324   * @return string|null
325   *   The formatted style summary or NULL if no styles are selected.
326   */
327  private function formatUiStyleSummary(array $sourceConfig, ?array $propertyConfig): ?string {
328    $selectedStyles = $sourceConfig['source']['styles']['selected'];
329
330    if (empty($selectedStyles)) {
331      return NULL;
332    }
333
334    $mainLabel = $propertyConfig['title'] ?? '';
335    $firstStyle = \array_key_first($selectedStyles);
336
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
338  }
339
340  /**
341   * Processes a standard property configuration to generate a summary string.
342   *
343   * @param array $sourceConfig
344   *   The source configuration array.
345   * @param array|null $propertyConfig
346   *   The property configuration array or NULL if not available.
347   * @param string $sourceId
348   *   The source identifier.
349   *
350   * @return string|null
351   *   The formatted summary string or NULL if no value is available.
352   */
353  private function processStandardProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
354    if (!isset($sourceConfig['source']['value'])) {
355      return NULL;
356    }
357
358    $value = $sourceConfig['source']['value'];
359    $processedValue = self::normalizeValue($value);
360
361    if ($processedValue === NULL) {
362      return NULL;
363    }
364
365    $label = $propertyConfig['title'] ?? $sourceId;
366
367    return \sprintf('%s: %s', $label, $processedValue);
368  }
369
370  /**
371   * Normalizes a value to a string representation.
372   *
373   * @param mixed $value
374   *   The value to normalize (array or string).
375   *
376   * @return string|null
377   *   The normalized string value or NULL if empty/invalid.
378   */
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
381      $str = self::flattenArrayToString($value);
382
383      return $str !== '' ? $str : NULL;
384    }
385
386    return \is_string($value) && $value !== '' ? $value : NULL;
387  }
388
389  /**
390   * Utility to stringify a nested array.
391   *
392   * @param array $array
393   *   The $array to normalize (array or string).
394   *
395   * @return string
396   *   The flatten string.
397   */
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
422
423}

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.

ComponentSource->buildPropsSummary
258  private function buildPropsSummary(array $component, array $data): array {
259    if (empty($data['props'])) {
 
260      return [];
258  private function buildPropsSummary(array $component, array $data): array {
259    if (empty($data['props'])) {
 
263    $items = [];
264    $propertyConfigs = $component['props']['properties'] ?? [];
265
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
274        $items[] = $summaryItem;
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
274        $items[] = $summaryItem;
275      }
276    }
277
278    return $items;
279  }
258  private function buildPropsSummary(array $component, array $data): array {
259    if (empty($data['props'])) {
 
263    $items = [];
264    $propertyConfigs = $component['props']['properties'] ?? [];
265
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
274        $items[] = $summaryItem;
275      }
276    }
277
278    return $items;
279  }
258  private function buildPropsSummary(array $component, array $data): array {
259    if (empty($data['props'])) {
 
263    $items = [];
264    $propertyConfigs = $component['props']['properties'] ?? [];
265
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
274        $items[] = $summaryItem;
275      }
276    }
277
278    return $items;
279  }
258  private function buildPropsSummary(array $component, array $data): array {
259    if (empty($data['props'])) {
 
263    $items = [];
264    $propertyConfigs = $component['props']['properties'] ?? [];
265
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
 
266    foreach ($data['props'] as $sourceId => $sourceConfig) {
267      $summaryItem = $this->processProperty(
268        $sourceConfig,
269        $propertyConfigs[$sourceId] ?? NULL,
270        $sourceId
271      );
272
273      if ($summaryItem) {
274        $items[] = $summaryItem;
275      }
276    }
277
278    return $items;
279  }
ComponentSource->buildVariantSummary
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
234      return [];
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
237    $variantValue = $data['variant_id']['source']['value'];
238    $variantLabel = $component['variants'][$variantValue]['title'] ?? $variantValue;
239
240    if (empty($variantLabel)) {
 
241      return [];
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
237    $variantValue = $data['variant_id']['source']['value'];
238    $variantLabel = $component['variants'][$variantValue]['title'] ?? $variantValue;
239
240    if (empty($variantLabel)) {
 
244    return [new TranslatableMarkup('Variant: @variant', ['@variant' => $variantLabel])];
245  }
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
234      return [];
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
237    $variantValue = $data['variant_id']['source']['value'];
238    $variantLabel = $component['variants'][$variantValue]['title'] ?? $variantValue;
239
240    if (empty($variantLabel)) {
 
241      return [];
231  private function buildVariantSummary(array $component, array $data): array {
232    if (!isset($data['variant_id']['source']['value'])
 
233        || $data['variant_id']['source']['value'] === 'default') {
 
237    $variantValue = $data['variant_id']['source']['value'];
238    $variantLabel = $component['variants'][$variantValue]['title'] ?? $variantValue;
239
240    if (empty($variantLabel)) {
 
244    return [new TranslatableMarkup('Variant: @variant', ['@variant' => $variantLabel])];
245  }
ComponentSource->flattenArrayToString
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
 
403        if (\is_int($key)) {
 
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
 
402      if (\is_array($value)) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
 
403        if (\is_int($key)) {
 
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
 
402      if (\is_array($value)) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
 
410      elseif (!empty($value)) {
 
411        if (\is_int($key)) {
 
411        if (\is_int($key)) {
412          $result[] = (string) $value;
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
 
410      elseif (!empty($value)) {
 
411        if (\is_int($key)) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
 
410      elseif (!empty($value)) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
398  private static function flattenArrayToString(array $array): string {
399    $result = [];
400
401    foreach ($array as $key => $value) {
 
401    foreach ($array as $key => $value) {
402      if (\is_array($value)) {
403        if (\is_int($key)) {
404          $result[] = self::flattenArrayToString($value);
405        }
406        else {
407          $result[] = $key . ': {' . self::flattenArrayToString($value) . '}';
408        }
409      }
410      elseif (!empty($value)) {
411        if (\is_int($key)) {
412          $result[] = (string) $value;
413        }
414        else {
415          $result[] = "{$key}{$value}";
416        }
417      }
418    }
419
420    return \implode(', ', $result);
421  }
ComponentSource->formatUiStyleSummary
327  private function formatUiStyleSummary(array $sourceConfig, ?array $propertyConfig): ?string {
328    $selectedStyles = $sourceConfig['source']['styles']['selected'];
329
330    if (empty($selectedStyles)) {
 
331      return NULL;
327  private function formatUiStyleSummary(array $sourceConfig, ?array $propertyConfig): ?string {
328    $selectedStyles = $sourceConfig['source']['styles']['selected'];
329
330    if (empty($selectedStyles)) {
 
334    $mainLabel = $propertyConfig['title'] ?? '';
335    $firstStyle = \array_key_first($selectedStyles);
336
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
 
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
 
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
338  }
327  private function formatUiStyleSummary(array $sourceConfig, ?array $propertyConfig): ?string {
328    $selectedStyles = $sourceConfig['source']['styles']['selected'];
329
330    if (empty($selectedStyles)) {
 
334    $mainLabel = $propertyConfig['title'] ?? '';
335    $firstStyle = \array_key_first($selectedStyles);
336
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
 
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
 
337    return $firstStyle ? \sprintf('%s - %s', $mainLabel, $firstStyle) : NULL;
338  }
ComponentSource->getChoice
27  public function getChoice(array $settings): string {
28    return $settings['component']['component_id'] ?? $settings['component_id'] ?? '';
29  }
ComponentSource->getComponentMetadata
185  protected function getComponentMetadata(string $component_id): array {
186    $component = $this->componentManager->find($component_id);
187    $build = [];
188
189    if ($description = $component->metadata->description) {
 
192          '#type' => 'html_tag',
193          '#tag' => 'p',
194          '#value' => $description,
195          '#attributes' => [
196            'class' => ['description'],
197          ],
198        ],
199        [
200          '#type' => 'html_tag',
201          '#tag' => 'sl-button',
202          '#value' => new TranslatableMarkup('Hide description'),
203          '#attributes' => [
204            'size' => 'small',
205            'variant' => 'default',
206            'class' => ['db-description-toggle'],
207          ],
208        ],
209      ];
210      $build[] = [
211        '#type' => 'html_tag',
212        '#tag' => 'div',
213        'content' => $description,
214      ];
215    }
216
217    return $build;
 
217    return $build;
218  }
185  protected function getComponentMetadata(string $component_id): array {
186    $component = $this->componentManager->find($component_id);
187    $build = [];
188
189    if ($description = $component->metadata->description) {
 
217    return $build;
218  }
ComponentSource->getGroup
165    $component_id = $this->settings['component']['component_id'] ?? '';
166
167    if (!$component_id) {
 
168      return '';
165    $component_id = $this->settings['component']['component_id'] ?? '';
166
167    if (!$component_id) {
 
171    $definition = $this->componentManager->getDefinition($component_id);
172
173    return $definition['group'] ?? '';
174  }
ComponentSource->getSlotDefinitions
35    $component_id = $this->settings['component']['component_id'] ?? '';
36
37    if (!$component_id) {
 
38      return [];
35    $component_id = $this->settings['component']['component_id'] ?? '';
36
37    if (!$component_id) {
 
41    try {
42      $definition = $this->componentManager->getDefinition($component_id);
 
48    return $definition['slots'] ?? [];
49  }
44    catch (\Throwable $th) {
 
45      return [];
ComponentSource->getSlotPath
96  public static function getSlotPath(string $slot_id): array {
97    return ['component', 'slots', $slot_id, 'sources'];
98  }
ComponentSource->getSlotValue
69  public function getSlotValue(string $slot_id): array {
70    return $this->settings['component']['slots'][$slot_id]['sources'] ?? [];
71  }
ComponentSource->getSlotValues
55    $slots = [];
56
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
59        $slots[$slot_id] = $this->getSlotValue($slot_id);
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
59        $slots[$slot_id] = $this->getSlotValue($slot_id);
60      }
61    }
62
63    return $slots;
64  }
55    $slots = [];
56
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
59        $slots[$slot_id] = $this->getSlotValue($slot_id);
60      }
61    }
62
63    return $slots;
64  }
55    $slots = [];
56
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
59        $slots[$slot_id] = $this->getSlotValue($slot_id);
60      }
61    }
62
63    return $slots;
64  }
55    $slots = [];
56
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
 
57    foreach ($this->settings['component']['slots'] ?? [] as $slot_id => $slot) {
58      if (isset($slot['sources'])) {
59        $slots[$slot_id] = $this->getSlotValue($slot_id);
60      }
61    }
62
63    return $slots;
64  }
ComponentSource->isUiStyleAttribute
311  private function isUiStyleAttribute(array $sourceConfig): bool {
312    return ($sourceConfig['source_id'] ?? NULL) === 'ui_styles_attributes'
 
313          && isset($sourceConfig['source']['styles']['selected']);
 
313          && isset($sourceConfig['source']['styles']['selected']);
314  }
311  private function isUiStyleAttribute(array $sourceConfig): bool {
312    return ($sourceConfig['source_id'] ?? NULL) === 'ui_styles_attributes'
 
313          && isset($sourceConfig['source']['styles']['selected']);
314  }
ComponentSource->normalizeValue
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
 
381      $str = self::flattenArrayToString($value);
382
383      return $str !== '' ? $str : NULL;
 
383      return $str !== '' ? $str : NULL;
 
383      return $str !== '' ? $str : NULL;
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
 
381      $str = self::flattenArrayToString($value);
382
383      return $str !== '' ? $str : NULL;
 
383      return $str !== '' ? $str : NULL;
 
383      return $str !== '' ? $str : NULL;
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
387  }
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
387  }
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
387  }
379  private static function normalizeValue($value): ?string {
380    if (\is_array($value)) {
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
 
386    return \is_string($value) && $value !== '' ? $value : NULL;
387  }
ComponentSource->processProperty
294  private function processProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
295    if ($this->isUiStyleAttribute($sourceConfig)) {
 
296      return $this->formatUiStyleSummary($sourceConfig, $propertyConfig);
294  private function processProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
295    if ($this->isUiStyleAttribute($sourceConfig)) {
 
299    return $this->processStandardProperty($sourceConfig, $propertyConfig, $sourceId);
300  }
ComponentSource->processStandardProperty
353  private function processStandardProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
354    if (!isset($sourceConfig['source']['value'])) {
 
355      return NULL;
353  private function processStandardProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
354    if (!isset($sourceConfig['source']['value'])) {
 
358    $value = $sourceConfig['source']['value'];
359    $processedValue = self::normalizeValue($value);
360
361    if ($processedValue === NULL) {
 
362      return NULL;
353  private function processStandardProperty(array $sourceConfig, ?array $propertyConfig, string $sourceId): ?string {
354    if (!isset($sourceConfig['source']['value'])) {
 
358    $value = $sourceConfig['source']['value'];
359    $processedValue = self::normalizeValue($value);
360
361    if ($processedValue === NULL) {
 
365    $label = $propertyConfig['title'] ?? $sourceId;
366
367    return \sprintf('%s: %s', $label, $processedValue);
368  }
ComponentSource->setSlotRenderable
85  public function setSlotRenderable(array $build, string $slot_id, array $slot): array {
86    $build['#slots'][$slot_id] = $slot;
87    // Prevent the slot to be generated again.
88    unset($build['#ui_patterns']['slots'][$slot_id]);
89
90    return $build;
91  }
ComponentSource->setSlotValue
76  public function setSlotValue(string $slot_id, array $slot): array {
77    $this->settings['component']['slots'][$slot_id]['sources'] = $slot;
78
79    return $this->settings;
80  }
ComponentSource->settingsFormPropsOnly
132  public function settingsFormPropsOnly(array $form, FormStateInterface $form_state): array {
133    $form = $this->settingsForm($form, $form_state);
134    $data = $this->getSetting('component');
135    $component_id = $data['component_id'] ?? NULL;
136
137    if (!$component_id) {
 
138      return $form;
132  public function settingsFormPropsOnly(array $form, FormStateInterface $form_state): array {
133    $form = $this->settingsForm($form, $form_state);
134    $data = $this->getSetting('component');
135    $component_id = $data['component_id'] ?? NULL;
136
137    if (!$component_id) {
 
141    if (!isset($form['component']['component_id'])) {
 
143        '#type' => 'hidden',
144        '#value' => $component_id,
145      ];
146    }
147    $form['component']['#render_slots'] = FALSE;
 
147    $form['component']['#render_slots'] = FALSE;
148    $form['component']['#component_id'] = $component_id;
149
150    return \array_merge(
151      ['info' => $this->getComponentMetadata($component_id)],
152      $form
153    );
154  }
132  public function settingsFormPropsOnly(array $form, FormStateInterface $form_state): array {
133    $form = $this->settingsForm($form, $form_state);
134    $data = $this->getSetting('component');
135    $component_id = $data['component_id'] ?? NULL;
136
137    if (!$component_id) {
 
141    if (!isset($form['component']['component_id'])) {
 
147    $form['component']['#render_slots'] = FALSE;
148    $form['component']['#component_id'] = $component_id;
149
150    return \array_merge(
151      ['info' => $this->getComponentMetadata($component_id)],
152      $form
153    );
154  }
ComponentSource->settingsSummary
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
107      return [];
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
111      return [];
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
114    try {
115      $component = $this->componentManager->getDefinition($data['component_id']);
 
121    $variant = $this->buildVariantSummary($component, $data);
122    $props = $this->buildPropsSummary($component, $data);
123
124    $items = \array_merge($variant, $props);
125
126    return $items;
127  }
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
111      return [];
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
114    try {
115      $component = $this->componentManager->getDefinition($data['component_id']);
 
121    $variant = $this->buildVariantSummary($component, $data);
122    $props = $this->buildPropsSummary($component, $data);
123
124    $items = \array_merge($variant, $props);
125
126    return $items;
127  }
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
107      return [];
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
111      return [];
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
114    try {
115      $component = $this->componentManager->getDefinition($data['component_id']);
 
121    $variant = $this->buildVariantSummary($component, $data);
122    $props = $this->buildPropsSummary($component, $data);
123
124    $items = \array_merge($variant, $props);
125
126    return $items;
127  }
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
111      return [];
104    $data = $this->getSetting('component');
105
106    if (empty($data) || !isset($data['component_id'])) {
 
106    if (empty($data) || !isset($data['component_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
110    if (empty($data['props']) && empty($data['variant_id'])) {
 
114    try {
115      $component = $this->componentManager->getDefinition($data['component_id']);
 
121    $variant = $this->buildVariantSummary($component, $data);
122    $props = $this->buildPropsSummary($component, $data);
123
124    $items = \array_merge($variant, $props);
125
126    return $items;
127  }
117    catch (\Throwable $th) {
 
118      return [];