Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
LayoutBuilderEntityViewDisplay
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 5
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 preSave
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 getDisplayBuilderOverrideField
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
 initialImport
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 importFromLayoutBuilder
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder_entity_view\Entity;
6
7use Drupal\Core\Entity\EntityStorageInterface;
8use Drupal\Core\Entity\EntityTypeManagerInterface;
9use Drupal\Core\Extension\ModuleExtensionList;
10use Drupal\display_builder\ConfigFormBuilderInterface;
11use Drupal\display_builder\InstanceInterface;
12use Drupal\display_builder_entity_view\BuilderDataConverter;
13use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay as CoreLayoutBuilderEntityViewDisplay;
14use Drupal\ui_patterns\Element\ComponentElementBuilder;
15use Drupal\ui_patterns\Entity\SampleEntityGeneratorInterface;
16use Drupal\ui_patterns\SourcePluginManager;
17
18/**
19 * Provides an entity view display entity that has a display builder.
20 *
21 * When Layout Builder is activated, extends Layout Builder.
22 *
23 * @see \Drupal\display_builder_entity_view\Hook\DisplayBuilderEntityViewHook::entityTypeAlter()
24 * @see \Drupal\display_builder_entity_view\Entity\EntityViewDisplay
25 */
26class LayoutBuilderEntityViewDisplay extends CoreLayoutBuilderEntityViewDisplay implements DisplayBuilderEntityDisplayInterface, DisplayBuilderOverridableInterface {
27
28  use EntityViewDisplayTrait;
29
30  /**
31   * The source plugin manager.
32   */
33  protected SourcePluginManager $sourcePluginManager;
34
35  /**
36   * The entity type manager.
37   */
38  protected EntityTypeManagerInterface $entityTypeManager;
39
40  /**
41   * The component element builder service.
42   */
43  protected ComponentElementBuilder $componentElementBuilder;
44
45  /**
46   * The sample entity generator.
47   */
48  protected SampleEntityGeneratorInterface $sampleEntityGenerator;
49
50  /**
51   * The list of modules.
52   */
53  protected ModuleExtensionList $modules;
54
55  /**
56   * The data converter from Manage Display and Layout Builder.
57   */
58  protected BuilderDataConverter $dataConverter;
59
60  /**
61   * The loaded display builder instance.
62   */
63  protected ?InstanceInterface $instance;
64
65  /**
66   * Constructs the LayoutBuilderEntityViewDisplay.
67   *
68   * @param array $values
69   *   The values to initialize the entity with.
70   * @param string $entity_type
71   *   The entity type ID.
72   */
73  public function __construct(array $values, $entity_type) {
74    $this->entityFieldManager = \Drupal::service('entity_field.manager');
75    parent::__construct($values, $entity_type);
76    $this->sourcePluginManager = \Drupal::service('plugin.manager.ui_patterns_source');
77    $this->entityTypeManager = \Drupal::service('entity_type.manager');
78    $this->componentElementBuilder = \Drupal::service('ui_patterns.component_element_builder');
79    $this->sampleEntityGenerator = \Drupal::service('ui_patterns.sample_entity_generator');
80    $this->modules = \Drupal::service('extension.list.module');
81    $this->dataConverter = \Drupal::service('display_builder_entity_view.builder_data_converter');
82  }
83
84  /**
85   * {@inheritdoc}
86   */
87  public function preSave(EntityStorageInterface $storage): void {
88    // If the update is made from Layout Builder, convert the data and copy
89    // to Display Builder's third party settings storage.
90    if (isset($this->form_id) && $this->form_id === 'entity_view_display_layout_builder_form') {
91      if ($this->getProfile()) {
92        $this->importFromLayoutBuilder();
93      }
94    }
95    parent::preSave($storage);
96  }
97
98  /**
99   * Returns the field name used to store overridden displays.
100   *
101   * @return string|null
102   *   The field name used to store overridden displays, or NULL if not set.
103   *
104   * @see Drupal\display_builder_entity_view\Entity\DisplayBuilderOverridableInterface
105   */
106  public function getDisplayBuilderOverrideField(): ?string {
107    return $this->getThirdPartySetting('display_builder', ConfigFormBuilderInterface::OVERRIDE_FIELD_PROPERTY);
108  }
109
110  /**
111   * Initial import from existing data.
112   *
113   * @return array
114   *   List of UI Patterns sources.
115   *
116   * @see EntityViewDisplayTrait::initInstanceIfMissing()
117   * @see EntityViewDisplay::initialImport()
118   */
119  protected function initialImport(): array {
120    if ($this->getThirdPartySetting('layout_builder', 'enabled')) {
121      $sections = $this->getThirdPartySetting('layout_builder', 'sections', []);
122
123      if (!\is_array($sections)) {
124        $sections = [];
125      }
126
127      return $this->dataConverter->convertFromLayoutBuilder($sections);
128    }
129
130    // If Layout Builder is not used, import from Manage Display data.
131    return $this->dataConverter->convertFromManageDisplay($this->getTargetEntityTypeId(), $this->getTargetBundle(), $this->content);
132  }
133
134  /**
135   * Import and convert data from layout builder.
136   *
137   * This is not used for the first import but for the following saves.
138   *
139   * @see LayoutBuilderEntityViewDisplay::preSave()
140   */
141  protected function importFromLayoutBuilder(): void {
142    if (!$this->getInstanceId()) {
143      return;
144    }
145    $sections = $this->getThirdPartySetting('layout_builder', 'sections');
146    $sources = $this->dataConverter->convertFromLayoutBuilder($sections);
147
148    /** @var \Drupal\display_builder\InstanceStorage $storage */
149    $storage = $this->entityTypeManager->getStorage('display_builder_instance');
150    /** @var \Drupal\display_builder\InstanceInterface $instance */
151    $instance = $storage->load($this->getInstanceId());
152    $instance->setNewPresent($sources, 'Import from Layout Builder');
153    $instance->save();
154  }
155
156}