Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 145
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
BuilderDataConverter
0.00% covered (danger)
0.00%
0 / 145
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 77
0.00% covered (danger)
0.00%
0 / 16
2070
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertFromManageDisplay
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
 convertFromLayoutBuilder
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 convertSingleField
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertExtraField
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertUiPatternsLayout
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 extractThirdPartySettings
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 moveUiStylesAttributesSource
0.00% covered (danger)
0.00%
0 / 10
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
 convertLayout
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 extractUiStylesData
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 convertLayoutBuilderComponent
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
56
 convertFieldBlock
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertExtraFieldBlock
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 convertUiPatternsBlock
0.00% covered (danger)
0.00%
0 / 10
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
 convertBlock
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 updateContextMapping
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder_entity_view;
6
7use Drupal\Component\Plugin\Definition\PluginDefinitionInterface;
8use Drupal\Component\Utility\NestedArray;
9use Drupal\Component\Utility\SortArray;
10use Drupal\Core\Block\BlockPluginInterface;
11use Drupal\Core\Entity\EntityFieldManagerInterface;
12use Drupal\layout_builder\Section;
13use Drupal\layout_builder\SectionComponent;
14
15/**
16 * Convert data between Layout Builder and Display Builder.
17 */
18class BuilderDataConverter {
19
20  public function __construct(
21    protected EntityFieldManagerInterface $entityFieldManager,
22  ) {}
23
24  /**
25   * Convert "Manage display" formatters to UI Patterns sources.
26   *
27   * @param string $entity_type
28   *   Entity type ID.
29   * @param string $bundle
30   *   Bundle.
31   * @param array $fields
32   *   Configuration of activated fields.
33   *
34   * @return array
35   *   List of UI Patterns sources.
36   */
37  public function convertFromManageDisplay(string $entity_type, string $bundle, array $fields): array {
38    $sources = [];
39    \uasort($fields, [SortArray::class, 'sortByWeightElement']);
40
41    $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
42
43    foreach ($fields as $field_id => $field) {
44      if (!isset($field['type'])) {
45        // Probably an extra field.
46        $sources[] = $this->convertExtraField($field_id);
47
48        // @todo Do we need to check if it is really an extra field?
49        continue;
50      }
51
52      if (isset($definitions[$field_id]) && !$definitions[$field_id]->isDisplayConfigurable('view')) {
53        // Hidden from Manage Display.
54        continue;
55      }
56      $sources[] = $this->convertSingleField($entity_type, $bundle, $field_id, $field);
57    }
58
59    return $sources;
60  }
61
62  /**
63   * Convert from Layout Builder.
64   *
65   * @param array $sections
66   *   A list of layout builder section, so the root of Layout Builder data.
67   *
68   * @return array
69   *   A list of UI Patterns sources.
70   */
71  public function convertFromLayoutBuilder(array $sections): array {
72    $sources = [];
73
74    foreach ($sections as $section) {
75      $deriver = $section->getLayout()->getPluginDefinition()->getDeriver();
76
77      if ($deriver === 'Drupal\ui_patterns_layouts\Plugin\Derivative\ComponentLayout') {
78        $sources[] = $this->convertUiPatternsLayout($section);
79
80        continue;
81      }
82      $sources[] = $this->convertLayout($section);
83    }
84
85    return $sources;
86  }
87
88  /**
89   * Convert field formatter plugin data to a source.
90   *
91   * Used for conversion from both Manage Display and Layout Builder.
92   *
93   * @param string $entity_type
94   *   Entity type ID.
95   * @param string $bundle
96   *   Bundle.
97   * @param string $field
98   *   Field name.
99   * @param array $data
100   *   Field formatter data.
101   *
102   * @return array
103   *   A single UI Patterns source.
104   */
105  protected function convertSingleField(string $entity_type, string $bundle, string $field, array $data): array {
106    $derivable_context = \implode(':', [$entity_type, $bundle, $field]);
107    $source = [
108      'source_id' => 'field_formatter:' . $derivable_context,
109      'source' => $data,
110    ];
111
112    return [
113      'source_id' => 'entity_field',
114      'source' => [
115        'derivable_context' => 'field:' . $derivable_context,
116        'field:' . $derivable_context => [
117          'value' => [
118            'sources' => [$source],
119          ],
120        ],
121      ],
122    ];
123  }
124
125  /**
126   * Convert an extra field.
127   *
128   * @param string $field_name
129   *   The machine name of the extra field.
130   *
131   * @return array
132   *   A single UI Patterns source.
133   */
134  protected function convertExtraField(string $field_name): array {
135    return [
136      'source_id' => 'extra_field',
137      'source' => [
138        'field' => $field_name,
139      ],
140    ];
141  }
142
143  /**
144   * Convert UI Patterns layout plugin.
145   *
146   * @param \Drupal\layout_builder\Section $section
147   *   A single layout builder section.
148   *
149   * @return array
150   *   A single UI Patterns source.
151   */
152  protected function convertUiPatternsLayout(Section $section): array {
153    $slots = [];
154    $components = $section->getComponents();
155
156    foreach ($components as $component) {
157      $source = $this->convertLayoutBuilderComponent($component);
158
159      if ($source) {
160        $source = $this->extractUiStylesData($component, $source);
161        $slots[$component->getRegion()]['sources'][] = $source;
162      }
163    }
164
165    $data = [
166      'source_id' => 'component',
167      'source' => [
168        'component' => $section->getLayoutSettings()['ui_patterns'],
169      ],
170    ];
171    // Sometimes, this value is null, so let's override it.
172    $data['source']['component']['component_id'] = \str_replace('ui_patterns:', '', $section->getLayoutId());
173
174    $data = $this->extractThirdPartySettings($data, $section);
175    $data = $this->moveUiStylesAttributesSource($data);
176
177    if ($slots) {
178      $data['source']['component']['slots'] = $slots;
179    }
180
181    return $data;
182  }
183
184  /**
185   * Extract third party settings.
186   *
187   * @param array $data
188   *   A single UI Patterns source.
189   * @param \Drupal\layout_builder\Section $section
190   *   A single layout builder section.
191   *
192   * @return array
193   *   A single UI Patterns source.
194   */
195  protected function extractThirdPartySettings(array $data, Section $section): array {
196    foreach ($section->getThirdPartyProviders() ?: [] as $provider_id) {
197      // In Layout builder, ThirdPartyProviders are Drupal modules. In Display
198      // Builder, they are Island plugins. So, 'ui_styles' become 'styles'. We
199      // are not calling the island 'ui_styles' in order to be ready when the
200      // API will land in Core. See https://www.drupal.org/i/3517033.
201      if ($provider_id === 'ui_styles') {
202        $data['third_party_settings']['styles'] = $section->getThirdPartySettings($provider_id);
203
204        continue;
205      }
206      $data['third_party_settings'][$provider_id] = $section->getThirdPartySettings($provider_id);
207    }
208
209    return $data;
210  }
211
212  /**
213   * Move data from UI Style's attribute source to 3rd party settings.
214   *
215   * @param array $data
216   *   A UI Patterns source data.
217   *
218   * @return array
219   *   The same UI Patterns source data, maybe altered.
220   */
221  protected function moveUiStylesAttributesSource(array $data): array {
222    if ($data['source']['component']['props']['attributes']['source_id'] !== 'ui_styles_attributes') {
223      return $data;
224    }
225    // We keep this order because it is the priority order in UI styles.
226    $styles_1 = [
227      'selected' => $data['source']['component']['props']['attributes']['source']['styles']['selected'],
228      'extra' => $data['source']['component']['props']['attributes']['source']['extra'],
229    ];
230    $styles_2 = $data['third_party_settings']['styles'] ?? [];
231    $data['third_party_settings']['styles'] = NestedArray::mergeDeep($styles_1, $styles_2);
232    $data['source']['component']['props']['attributes'] = [];
233
234    return $data;
235  }
236
237  /**
238   * Convert regular layout plugin.
239   *
240   * @param \Drupal\layout_builder\Section $section
241   *   A single layout builder section.
242   *
243   * @return array
244   *   A single UI Patterns source.
245   */
246  protected function convertLayout(Section $section): array {
247    $slots = [];
248    $components = $section->getComponents();
249
250    foreach ($components as $component) {
251      $source = $this->convertLayoutBuilderComponent($component);
252      $source = $this->extractUiStylesData($component, $source);
253
254      if ($source) {
255        $source = $this->extractUiStylesData($component, $source);
256        $slots[$component->getRegion()][] = $source;
257      }
258    }
259
260    $data = [
261      'source_id' => 'layout',
262      'source' => [
263        'layout_id' => $section->getLayoutId(),
264        'settings' => $section->getLayoutSettings(),
265      ],
266    ];
267
268    if ($slots) {
269      $data['source']['regions'] = $slots;
270    }
271
272    $data = $this->extractThirdPartySettings($data, $section);
273
274    return $data;
275  }
276
277  /**
278   * Extract UI Styles data.
279   *
280   * In Display Builder, we don't render through ThemeManager::render() so we
281   * don't load block.html.twig and we don't have block wrapper and block title
282   * attributes. So, let's ignore title styles and let's merge wrapper styles
283   * with block styles (which keep priority).
284   *
285   * @param \Drupal\layout_builder\SectionComponent $component
286   *   A single layout builder component.
287   * @param array $source
288   *   The already converted UI Patterns source.
289   *
290   * @return array
291   *   The altered UI Patterns source.
292   */
293  protected function extractUiStylesData(SectionComponent $component, array $source): array {
294    $additional = $component->toArray()['additional'] ?? [];
295
296    $styles = \array_unique(\array_merge($additional['ui_styles_wrapper'] ?? [], $additional['ui_styles'] ?? []));
297
298    if ($styles) {
299      $source['third_party_settings']['styles']['selected'] = $styles;
300    }
301
302    $extra = \trim(($additional['ui_styles_wrapper_extra'] ?? '') . ' ' . ($additional['ui_styles_extra'] ?? ''));
303
304    if ($extra) {
305      $source['third_party_settings']['styles']['extra'] = $extra;
306    }
307
308    return $source;
309  }
310
311  /**
312   * Convert layout builder component.
313   *
314   * @param \Drupal\layout_builder\SectionComponent $component
315   *   A single layout builder component.
316   *
317   * @return array
318   *   A single UI Patterns source.
319   */
320  protected function convertLayoutBuilderComponent(SectionComponent $component): array {
321    /** @var \Drupal\Core\Block\BlockPluginInterface $block */
322    $block = $component->getPlugin();
323    $definition = $block->getPluginDefinition();
324
325    $class = $definition instanceof PluginDefinitionInterface ? $definition->getClass() : $definition['class'];
326
327    if ($class === 'Drupal\layout_builder\Plugin\Block\FieldBlock') {
328      return $this->convertFieldBlock($block);
329    }
330
331    $provider = $definition instanceof PluginDefinitionInterface ? $definition->getProvider() : $definition['provider'];
332
333    if ($provider === 'ui_patterns_blocks') {
334      return $this->convertUiPatternsBlock($block);
335    }
336
337    $id = $definition instanceof PluginDefinitionInterface ? $definition->id() : $definition['id'];
338
339    if ($id === 'extra_field_block') {
340      return $this->convertExtraFieldBlock($block);
341    }
342
343    return $this->convertBlock($block);
344  }
345
346  /**
347   * Convert a Layout Builder field block.
348   *
349   * @param \Drupal\Core\Block\BlockPluginInterface $block
350   *   A block plugin.
351   *
352   * @return array
353   *   A single UI Patterns source.
354   */
355  protected function convertFieldBlock(BlockPluginInterface $block): array {
356    $config = $block->getConfiguration();
357    [, $entity_type, $bundle, $field_name] = \explode(':', $config['id']);
358
359    return $this->convertSingleField($entity_type, $bundle, $field_name, $config['formatter']);
360  }
361
362  /**
363   * Convert an extra field block.
364   *
365   * @param \Drupal\Core\Block\BlockPluginInterface $block
366   *   A block plugin.
367   *
368   * @return array
369   *   A single UI Patterns source.
370   */
371  protected function convertExtraFieldBlock(BlockPluginInterface $block): array {
372    [,,, $field_name] = \explode(':', $block->getPluginId());
373
374    return $this->convertExtraField($field_name);
375  }
376
377  /**
378   * Convert a UI Patterns block plugin.
379   *
380   * @param \Drupal\Core\Block\BlockPluginInterface $block
381   *   A block plugin.
382   *
383   * @return array
384   *   A single UI Patterns source.
385   */
386  protected function convertUiPatternsBlock(BlockPluginInterface $block): array {
387    $config = $block->getConfiguration();
388
389    // Sometimes, this value is null, so let's override it.
390    if (!isset($config['ui_patterns']['component_id'])) {
391      // See: \Drupal\ui_patterns_blocks\Plugin\Block\ComponentBlock.
392      $config['ui_patterns']['component_id'] = \str_replace('ui_patterns:', '', $config['id']);
393      // See: \Drupal\ui_patterns_blocks\Plugin\Block\EntityComponentBlock.
394      $config['ui_patterns']['component_id'] = \str_replace('ui_patterns_entity:', '', $config['id']);
395    }
396
397    return [
398      'source_id' => 'component',
399      'source' => [
400        'component' => $config['ui_patterns'],
401      ],
402    ];
403  }
404
405  /**
406   * Convert a generic block plugin.
407   *
408   * @param \Drupal\Core\Block\BlockPluginInterface $block
409   *   A block plugin.
410   *
411   * @return array
412   *   A single UI Patterns source.
413   */
414  protected function convertBlock(BlockPluginInterface $block): array {
415    $block_id = $block->getPluginId();
416    $blockConfiguration = $this->updateContextMapping($block->getConfiguration());
417
418    return [
419      'source_id' => 'block',
420      'source' => [
421        'plugin_id' => $block_id,
422        $block_id => $blockConfiguration,
423      ],
424    ];
425  }
426
427  /**
428   * Update plugin configuration context mapping.
429   *
430   * @param array $configuration
431   *   A configuration array from a plugin.
432   *
433   * @return array
434   *   The updated configuration.
435   */
436  protected function updateContextMapping(array $configuration): array {
437    if (isset($configuration['context_mapping']) && \is_array($configuration['context_mapping'])) {
438      foreach ($configuration['context_mapping'] as $key => $value) {
439        if ($value === 'layout_builder.entity') {
440          $configuration['context_mapping'][$key] = 'entity';
441        }
442      }
443    }
444
445    return $configuration;
446  }
447
448}

Branches

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

BuilderDataConverter->__construct
21    protected EntityFieldManagerInterface $entityFieldManager,
22  ) {}
BuilderDataConverter->convertBlock
414  protected function convertBlock(BlockPluginInterface $block): array {
415    $block_id = $block->getPluginId();
416    $blockConfiguration = $this->updateContextMapping($block->getConfiguration());
417
418    return [
419      'source_id' => 'block',
420      'source' => [
421        'plugin_id' => $block_id,
422        $block_id => $blockConfiguration,
423      ],
424    ];
425  }
BuilderDataConverter->convertExtraField
134  protected function convertExtraField(string $field_name): array {
135    return [
136      'source_id' => 'extra_field',
137      'source' => [
138        'field' => $field_name,
139      ],
140    ];
141  }
BuilderDataConverter->convertExtraFieldBlock
371  protected function convertExtraFieldBlock(BlockPluginInterface $block): array {
372    [,,, $field_name] = \explode(':', $block->getPluginId());
373
374    return $this->convertExtraField($field_name);
375  }
BuilderDataConverter->convertFieldBlock
355  protected function convertFieldBlock(BlockPluginInterface $block): array {
356    $config = $block->getConfiguration();
357    [, $entity_type, $bundle, $field_name] = \explode(':', $config['id']);
358
359    return $this->convertSingleField($entity_type, $bundle, $field_name, $config['formatter']);
360  }
BuilderDataConverter->convertFromLayoutBuilder
71  public function convertFromLayoutBuilder(array $sections): array {
72    $sources = [];
73
74    foreach ($sections as $section) {
74    foreach ($sections as $section) {
75      $deriver = $section->getLayout()->getPluginDefinition()->getDeriver();
76
77      if ($deriver === 'Drupal\ui_patterns_layouts\Plugin\Derivative\ComponentLayout') {
78        $sources[] = $this->convertUiPatternsLayout($section);
79
80        continue;
74    foreach ($sections as $section) {
75      $deriver = $section->getLayout()->getPluginDefinition()->getDeriver();
76
77      if ($deriver === 'Drupal\ui_patterns_layouts\Plugin\Derivative\ComponentLayout') {
78        $sources[] = $this->convertUiPatternsLayout($section);
79
80        continue;
81      }
82      $sources[] = $this->convertLayout($section);
74    foreach ($sections as $section) {
75      $deriver = $section->getLayout()->getPluginDefinition()->getDeriver();
76
77      if ($deriver === 'Drupal\ui_patterns_layouts\Plugin\Derivative\ComponentLayout') {
78        $sources[] = $this->convertUiPatternsLayout($section);
79
80        continue;
81      }
82      $sources[] = $this->convertLayout($section);
83    }
84
85    return $sources;
86  }
BuilderDataConverter->convertFromManageDisplay
37  public function convertFromManageDisplay(string $entity_type, string $bundle, array $fields): array {
38    $sources = [];
39    \uasort($fields, [SortArray::class, 'sortByWeightElement']);
40
41    $definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle);
42
43    foreach ($fields as $field_id => $field) {
43    foreach ($fields as $field_id => $field) {
43    foreach ($fields as $field_id => $field) {
44      if (!isset($field['type'])) {
46        $sources[] = $this->convertExtraField($field_id);
47
48        // @todo Do we need to check if it is really an extra field?
49        continue;
52      if (isset($definitions[$field_id]) && !$definitions[$field_id]->isDisplayConfigurable('view')) {
52      if (isset($definitions[$field_id]) && !$definitions[$field_id]->isDisplayConfigurable('view')) {
52      if (isset($definitions[$field_id]) && !$definitions[$field_id]->isDisplayConfigurable('view')) {
54        continue;
43    foreach ($fields as $field_id => $field) {
44      if (!isset($field['type'])) {
45        // Probably an extra field.
46        $sources[] = $this->convertExtraField($field_id);
47
48        // @todo Do we need to check if it is really an extra field?
49        continue;
50      }
51
52      if (isset($definitions[$field_id]) && !$definitions[$field_id]->isDisplayConfigurable('view')) {
53        // Hidden from Manage Display.
54        continue;
55      }
56      $sources[] = $this->convertSingleField($entity_type, $bundle, $field_id, $field);
43    foreach ($fields as $field_id => $field) {
44      if (!isset($field['type'])) {
45        // Probably an extra field.
46        $sources[] = $this->convertExtraField($field_id);
47
48        // @todo Do we need to check if it is really an extra field?
49        continue;
50      }
51
52      if (isset($definitions[$field_id]) && !$definitions[$field_id]->isDisplayConfigurable('view')) {
53        // Hidden from Manage Display.
54        continue;
55      }
56      $sources[] = $this->convertSingleField($entity_type, $bundle, $field_id, $field);
57    }
58
59    return $sources;
60  }
BuilderDataConverter->convertLayout
246  protected function convertLayout(Section $section): array {
247    $slots = [];
248    $components = $section->getComponents();
249
250    foreach ($components as $component) {
250    foreach ($components as $component) {
251      $source = $this->convertLayoutBuilderComponent($component);
252      $source = $this->extractUiStylesData($component, $source);
253
254      if ($source) {
250    foreach ($components as $component) {
251      $source = $this->convertLayoutBuilderComponent($component);
252      $source = $this->extractUiStylesData($component, $source);
253
254      if ($source) {
255        $source = $this->extractUiStylesData($component, $source);
250    foreach ($components as $component) {
250    foreach ($components as $component) {
251      $source = $this->convertLayoutBuilderComponent($component);
252      $source = $this->extractUiStylesData($component, $source);
253
254      if ($source) {
255        $source = $this->extractUiStylesData($component, $source);
256        $slots[$component->getRegion()][] = $source;
257      }
258    }
259
260    $data = [
261      'source_id' => 'layout',
262      'source' => [
263        'layout_id' => $section->getLayoutId(),
264        'settings' => $section->getLayoutSettings(),
265      ],
266    ];
267
268    if ($slots) {
269      $data['source']['regions'] = $slots;
270    }
271
272    $data = $this->extractThirdPartySettings($data, $section);
272    $data = $this->extractThirdPartySettings($data, $section);
273
274    return $data;
275  }
BuilderDataConverter->convertLayoutBuilderComponent
320  protected function convertLayoutBuilderComponent(SectionComponent $component): array {
321    /** @var \Drupal\Core\Block\BlockPluginInterface $block */
322    $block = $component->getPlugin();
323    $definition = $block->getPluginDefinition();
324
325    $class = $definition instanceof PluginDefinitionInterface ? $definition->getClass() : $definition['class'];
325    $class = $definition instanceof PluginDefinitionInterface ? $definition->getClass() : $definition['class'];
325    $class = $definition instanceof PluginDefinitionInterface ? $definition->getClass() : $definition['class'];
325    $class = $definition instanceof PluginDefinitionInterface ? $definition->getClass() : $definition['class'];
326
327    if ($class === 'Drupal\layout_builder\Plugin\Block\FieldBlock') {
328      return $this->convertFieldBlock($block);
331    $provider = $definition instanceof PluginDefinitionInterface ? $definition->getProvider() : $definition['provider'];
331    $provider = $definition instanceof PluginDefinitionInterface ? $definition->getProvider() : $definition['provider'];
331    $provider = $definition instanceof PluginDefinitionInterface ? $definition->getProvider() : $definition['provider'];
331    $provider = $definition instanceof PluginDefinitionInterface ? $definition->getProvider() : $definition['provider'];
332
333    if ($provider === 'ui_patterns_blocks') {
334      return $this->convertUiPatternsBlock($block);
337    $id = $definition instanceof PluginDefinitionInterface ? $definition->id() : $definition['id'];
337    $id = $definition instanceof PluginDefinitionInterface ? $definition->id() : $definition['id'];
337    $id = $definition instanceof PluginDefinitionInterface ? $definition->id() : $definition['id'];
337    $id = $definition instanceof PluginDefinitionInterface ? $definition->id() : $definition['id'];
338
339    if ($id === 'extra_field_block') {
340      return $this->convertExtraFieldBlock($block);
343    return $this->convertBlock($block);
344  }
BuilderDataConverter->convertSingleField
105  protected function convertSingleField(string $entity_type, string $bundle, string $field, array $data): array {
106    $derivable_context = \implode(':', [$entity_type, $bundle, $field]);
107    $source = [
108      'source_id' => 'field_formatter:' . $derivable_context,
109      'source' => $data,
110    ];
111
112    return [
113      'source_id' => 'entity_field',
114      'source' => [
115        'derivable_context' => 'field:' . $derivable_context,
116        'field:' . $derivable_context => [
117          'value' => [
118            'sources' => [$source],
119          ],
120        ],
121      ],
122    ];
123  }
BuilderDataConverter->convertUiPatternsBlock
386  protected function convertUiPatternsBlock(BlockPluginInterface $block): array {
387    $config = $block->getConfiguration();
388
389    // Sometimes, this value is null, so let's override it.
390    if (!isset($config['ui_patterns']['component_id'])) {
392      $config['ui_patterns']['component_id'] = \str_replace('ui_patterns:', '', $config['id']);
393      // See: \Drupal\ui_patterns_blocks\Plugin\Block\EntityComponentBlock.
394      $config['ui_patterns']['component_id'] = \str_replace('ui_patterns_entity:', '', $config['id']);
395    }
396
397    return [
398      'source_id' => 'component',
398      'source_id' => 'component',
399      'source' => [
400        'component' => $config['ui_patterns'],
401      ],
402    ];
403  }
BuilderDataConverter->convertUiPatternsLayout
152  protected function convertUiPatternsLayout(Section $section): array {
153    $slots = [];
154    $components = $section->getComponents();
155
156    foreach ($components as $component) {
156    foreach ($components as $component) {
157      $source = $this->convertLayoutBuilderComponent($component);
158
159      if ($source) {
156    foreach ($components as $component) {
157      $source = $this->convertLayoutBuilderComponent($component);
158
159      if ($source) {
160        $source = $this->extractUiStylesData($component, $source);
156    foreach ($components as $component) {
156    foreach ($components as $component) {
157      $source = $this->convertLayoutBuilderComponent($component);
158
159      if ($source) {
160        $source = $this->extractUiStylesData($component, $source);
161        $slots[$component->getRegion()]['sources'][] = $source;
162      }
163    }
164
165    $data = [
166      'source_id' => 'component',
167      'source' => [
168        'component' => $section->getLayoutSettings()['ui_patterns'],
169      ],
170    ];
171    // Sometimes, this value is null, so let's override it.
172    $data['source']['component']['component_id'] = \str_replace('ui_patterns:', '', $section->getLayoutId());
173
174    $data = $this->extractThirdPartySettings($data, $section);
175    $data = $this->moveUiStylesAttributesSource($data);
176
177    if ($slots) {
178      $data['source']['component']['slots'] = $slots;
179    }
180
181    return $data;
181    return $data;
182  }
BuilderDataConverter->extractThirdPartySettings
195  protected function extractThirdPartySettings(array $data, Section $section): array {
196    foreach ($section->getThirdPartyProviders() ?: [] as $provider_id) {
196    foreach ($section->getThirdPartyProviders() ?: [] as $provider_id) {
201      if ($provider_id === 'ui_styles') {
202        $data['third_party_settings']['styles'] = $section->getThirdPartySettings($provider_id);
203
204        continue;
196    foreach ($section->getThirdPartyProviders() ?: [] as $provider_id) {
197      // In Layout builder, ThirdPartyProviders are Drupal modules. In Display
198      // Builder, they are Island plugins. So, 'ui_styles' become 'styles'. We
199      // are not calling the island 'ui_styles' in order to be ready when the
200      // API will land in Core. See https://www.drupal.org/i/3517033.
201      if ($provider_id === 'ui_styles') {
202        $data['third_party_settings']['styles'] = $section->getThirdPartySettings($provider_id);
203
204        continue;
205      }
206      $data['third_party_settings'][$provider_id] = $section->getThirdPartySettings($provider_id);
196    foreach ($section->getThirdPartyProviders() ?: [] as $provider_id) {
197      // In Layout builder, ThirdPartyProviders are Drupal modules. In Display
198      // Builder, they are Island plugins. So, 'ui_styles' become 'styles'. We
199      // are not calling the island 'ui_styles' in order to be ready when the
200      // API will land in Core. See https://www.drupal.org/i/3517033.
201      if ($provider_id === 'ui_styles') {
202        $data['third_party_settings']['styles'] = $section->getThirdPartySettings($provider_id);
203
204        continue;
205      }
206      $data['third_party_settings'][$provider_id] = $section->getThirdPartySettings($provider_id);
207    }
208
209    return $data;
210  }
BuilderDataConverter->extractUiStylesData
293  protected function extractUiStylesData(SectionComponent $component, array $source): array {
294    $additional = $component->toArray()['additional'] ?? [];
295
296    $styles = \array_unique(\array_merge($additional['ui_styles_wrapper'] ?? [], $additional['ui_styles'] ?? []));
297
298    if ($styles) {
299      $source['third_party_settings']['styles']['selected'] = $styles;
300    }
301
302    $extra = \trim(($additional['ui_styles_wrapper_extra'] ?? '') . ' ' . ($additional['ui_styles_extra'] ?? ''));
302    $extra = \trim(($additional['ui_styles_wrapper_extra'] ?? '') . ' ' . ($additional['ui_styles_extra'] ?? ''));
303
304    if ($extra) {
305      $source['third_party_settings']['styles']['extra'] = $extra;
306    }
307
308    return $source;
308    return $source;
309  }
BuilderDataConverter->moveUiStylesAttributesSource
221  protected function moveUiStylesAttributesSource(array $data): array {
222    if ($data['source']['component']['props']['attributes']['source_id'] !== 'ui_styles_attributes') {
223      return $data;
227      'selected' => $data['source']['component']['props']['attributes']['source']['styles']['selected'],
228      'extra' => $data['source']['component']['props']['attributes']['source']['extra'],
229    ];
230    $styles_2 = $data['third_party_settings']['styles'] ?? [];
231    $data['third_party_settings']['styles'] = NestedArray::mergeDeep($styles_1, $styles_2);
232    $data['source']['component']['props']['attributes'] = [];
233
234    return $data;
235  }
BuilderDataConverter->updateContextMapping
436  protected function updateContextMapping(array $configuration): array {
437    if (isset($configuration['context_mapping']) && \is_array($configuration['context_mapping'])) {
437    if (isset($configuration['context_mapping']) && \is_array($configuration['context_mapping'])) {
437    if (isset($configuration['context_mapping']) && \is_array($configuration['context_mapping'])) {
438      foreach ($configuration['context_mapping'] as $key => $value) {
438      foreach ($configuration['context_mapping'] as $key => $value) {
438      foreach ($configuration['context_mapping'] as $key => $value) {
439        if ($value === 'layout_builder.entity') {
438      foreach ($configuration['context_mapping'] as $key => $value) {
439        if ($value === 'layout_builder.entity') {
440          $configuration['context_mapping'][$key] = 'entity';
438      foreach ($configuration['context_mapping'] as $key => $value) {
438      foreach ($configuration['context_mapping'] as $key => $value) {
439        if ($value === 'layout_builder.entity') {
440          $configuration['context_mapping'][$key] = 'entity';
441        }
442      }
443    }
444
445    return $configuration;
445    return $configuration;
446  }