Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 154
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 22
CRAP
0.00% covered (danger)
0.00%
0 / 1
EntityViewOverride
0.00% covered (danger)
0.00%
0 / 150
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 22
2352
0.00% covered (danger)
0.00%
0 / 1
 __construct
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
 getContextRequirement
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
 getBuilderUrl
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
 checkInstanceId
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
 getUrlFromInstanceId
0.00% covered (danger)
0.00%
0 / 13
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
 getDisplayUrlFromInstanceId
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
 getProfile
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
 getSources
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
 saveSources
0.00% covered (danger)
0.00%
0 / 7
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
 checkAccess
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
 getInstanceId
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
 setRevision
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 collectInstances
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 getInitializationMessage
0.00% covered (danger)
0.00%
0 / 5
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
 getInitialSources
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
42
 getInitialContext
0.00% covered (danger)
0.00%
0 / 10
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
 collectInstancesByField
0.00% covered (danger)
0.00%
0 / 15
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
 time
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
 entityTypeManager
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
 displayBuildableManager
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
 dataConverter
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
 getEntityViewDisplay
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder_entity_view\Plugin\display_builder\Buildable;
6
7use Drupal\Component\Datetime\TimeInterface;
8use Drupal\Core\Access\AccessResult;
9use Drupal\Core\Access\AccessResultInterface;
10use Drupal\Core\Entity\ContentEntityInterface;
11use Drupal\Core\Entity\EntityStorageInterface;
12use Drupal\Core\Entity\EntityTypeManagerInterface;
13use Drupal\Core\Entity\Query\QueryInterface;
14use Drupal\Core\Entity\RevisionableEntityBundleInterface;
15use Drupal\Core\Entity\RevisionLogInterface;
16use Drupal\Core\Field\FieldItemListInterface;
17use Drupal\Core\Plugin\Context\Context;
18use Drupal\Core\Plugin\Context\ContextDefinition;
19use Drupal\Core\Plugin\Context\EntityContext;
20use Drupal\Core\Session\AccountInterface;
21use Drupal\Core\StringTranslation\TranslatableMarkup;
22use Drupal\Core\Url;
23use Drupal\display_builder\Attribute\DisplayBuildable;
24use Drupal\display_builder\DisplayBuildableInterface;
25use Drupal\display_builder\DisplayBuildablePluginBase;
26use Drupal\display_builder\DisplayBuildablePluginManager;
27use Drupal\display_builder\ProfileInterface;
28use Drupal\display_builder_entity_view\BuilderDataConverter;
29use Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface;
30use Drupal\display_builder_entity_view\Entity\DisplayBuilderOverridableInterface;
31use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
32
33/**
34 * Plugin implementation of the display_buildable.
35 */
36#[DisplayBuildable(
37  id: 'entity_view_override',
38  label: new TranslatableMarkup('Entity view override'),
39  instance_prefix: 'entity_override__',
40)]
41final class EntityViewOverride extends DisplayBuildablePluginBase {
42
43  /**
44   * The time service.
45   */
46  protected ?TimeInterface $time;
47
48  /**
49   * The data converter from Manage Display and Layout Builder.
50   */
51  protected BuilderDataConverter $dataConverter;
52
53  /**
54   * The field items where the override is stored.
55   */
56  private FieldItemListInterface $field;
57
58  /**
59   * The display buildable plugin manager.
60   */
61  private DisplayBuildablePluginManager $displayBuildableManager;
62
63  /**
64   * The overridden display.
65   */
66  private DisplayBuilderEntityDisplayInterface $display;
67
68  /**
69   * {@inheritdoc}
70   */
71  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
72    parent::__construct($configuration, $plugin_id, $plugin_definition);
73    $this->field = $configuration['field'];
74    \assert(\is_string($this->field->getName()));
75    $entity = $this->field->getEntity();
76    $this->display = self::getEntityViewDisplay(
77      $entity->getEntityTypeId(),
78      $entity->bundle(),
79      $this->field->getName(),
80    );
81  }
82
83  /**
84   * {@inheritdoc}
85   */
86  public static function getContextRequirement(): string {
87    return 'content';
88  }
89
90  /**
91   * {@inheritdoc}
92   */
93  public function getBuilderUrl(): Url {
94    \assert(\is_string($this->field->getName()));
95    $entity = $this->field->getEntity();
96    $entity_type_id = $this->display->getTargetEntityTypeId();
97    $parameters = [
98      $entity_type_id => $entity->id(),
99      'view_mode_name' => $this->display->getMode(),
100    ];
101
102    return Url::fromRoute(\sprintf('entity.%s.display_builder.%s', $entity_type_id, $this->display->getMode()), $parameters);
103  }
104
105  /**
106   * {@inheritdoc}
107   */
108  public static function checkInstanceId(string $instance_id): ?array {
109    if (!\str_starts_with($instance_id, self::getPrefix())) {
110      return NULL;
111    }
112    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
113
114    return [
115      'entity_type_id' => $entity_type_id,
116      'entity_id' => $entity_id,
117      'field_name' => $field_name,
118    ];
119  }
120
121  /**
122   * {@inheritdoc}
123   */
124  public static function getUrlFromInstanceId(string $instance_id): Url {
125    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
126
127    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
128
129    if (!$entity) {
130      return Url::fromRoute('entity.display_builder_instance.collection');
131    }
132
133    $display = self::getEntityViewDisplay($entity_type_id, $entity->bundle(), $field_name);
134
135    if (!$display) {
136      return Url::fromRoute('entity.display_builder_instance.collection');
137    }
138    $params = [
139      $entity_type_id => $entity_id,
140      'view_mode_name' => $display->getMode(),
141    ];
142
143    $route_name = \sprintf('entity.%s.display_builder.%s', $entity_type_id, $display->getMode());
144
145    return Url::fromRoute($route_name, $params);
146  }
147
148  /**
149   * {@inheritdoc}
150   */
151  public static function getDisplayUrlFromInstanceId(string $instance_id): Url {
152    return Url::fromRoute('<front>');
153  }
154
155  /**
156   * {@inheritdoc}
157   */
158  public function getProfile(): ?ProfileInterface {
159    \assert($this->display instanceof DisplayBuilderOverridableInterface);
160
161    return $this->display->getDisplayBuilderOverrideProfile();
162  }
163
164  /**
165   * {@inheritdoc}
166   */
167  public function getSources(): array {
168    return $this->field->getValue();
169  }
170
171  /**
172   * {@inheritdoc}
173   */
174  public function saveSources(): void {
175    $data = $this->getInstance()->getCurrentState();
176    $entity = $this->field->getEntity();
177
178    if ($entity instanceof ContentEntityInterface) {
179      $this->setRevision($entity);
180    }
181    $entity->save();
182    $this->field->setValue($data);
183    $this->field->getEntity()->save();
184  }
185
186  /**
187   * {@inheritdoc}
188   */
189  public static function checkAccess(string $instance_id, AccountInterface $account): AccessResultInterface {
190    [, $entity_type_id, $entity_id] = \explode('__', $instance_id);
191    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
192
193    if (!$entity) {
194      return AccessResult::neutral();
195    }
196
197    return $entity->access('update', $account, TRUE);
198  }
199
200  /**
201   * {@inheritdoc}
202   */
203  public function getInstanceId(): ?string {
204    // Usually an entity is new if no ID exists for it yet.
205    if ($this->field->getEntity()->isNew()) {
206      return NULL;
207    }
208
209    $entity = $this->field->getEntity();
210
211    return \sprintf(
212      '%s%s__%s__%s',
213      self::getPrefix(),
214      $entity->getEntityTypeId(),
215      $entity->id(),
216      $this->field->getName()
217    );
218  }
219
220  /**
221   * Set revision if appropriate.
222   *
223   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
224   *   The entity to set revision if appropriate.
225   */
226  public function setRevision(ContentEntityInterface $entity): void {
227    $bundle = $entity->getBundleEntity();
228
229    if ($bundle instanceof RevisionableEntityBundleInterface
230      && !$bundle->shouldCreateNewRevision()
231    ) {
232      return;
233    }
234
235    $entity->setNewRevision();
236
237    if ($entity instanceof RevisionLogInterface) {
238      $entity->setRevisionLogMessage($this->t('Updated using Display Builder.')->render());
239      $entity->setRevisionCreationTime($this->time()->getCurrentTime());
240    }
241  }
242
243  /**
244   * {@inheritdoc}
245   */
246  public static function collectInstances(?EntityTypeManagerInterface $entityTypeManager = NULL): array {
247    $instances = [];
248    $entityTypeManager = \Drupal::service('entity_type.manager');
249    $storage = $entityTypeManager->getStorage('entity_view_display');
250    $instance_storage = $entityTypeManager->getStorage('display_builder_instance');
251    $entity_query = $entity_storage = [];
252
253    foreach ($storage->loadMultiple() as $display) {
254      /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
255      $display_builder = $display->getThirdPartySettings('display_builder');
256
257      if (!isset($display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY], $display_builder[DisplayBuildableInterface::OVERRIDE_PROFILE_PROPERTY])) {
258        continue;
259      }
260
261      $entity_type = $display->getTargetEntityTypeId();
262      $field_name = $display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY] ?? NULL;
263
264      if (!$field_name) {
265        continue;
266      }
267      $entity_storage[$entity_type] ??= $entityTypeManager->getStorage($entity_type);
268      $entity_query[$entity_type] ??= $entity_storage[$entity_type]->getQuery()->accessCheck(FALSE);
269      $instances = \array_merge($instances, self::collectInstancesByField($field_name, $entity_type, $instance_storage, $entity_query[$entity_type]));
270    }
271
272    return $instances;
273  }
274
275  /**
276   * {@inheritdoc}
277   */
278  protected function getInitializationMessage(): TranslatableMarkup {
279    if ($this->initialDataSource === 'display_builder') {
280      return $this->t('Copy from Entity View Display configuration.');
281    }
282
283    if ($this->initialDataSource === 'layout_builder_override') {
284      return $this->t('Import from Layout Builder override.');
285    }
286
287    return $this->t('Initialization from existing content.');
288  }
289
290  /**
291   * {@inheritdoc}
292   */
293  protected function getInitialSources(): array {
294    $sources = $this->getSources();
295
296    // 1. Keep the existing override value if existing.
297    if (\count($sources) > 0) {
298      return $sources;
299    }
300
301    // 2. Convert the Layout Builder Override if exists.
302    // There is always a single Layout Builder override per bundle: `default`.
303    // There could be many Display Builder overrides per bundle, one for each
304    // display, so we need to check.
305    if ($this->display->getMode() === 'default') {
306      $entity = $this->field->getEntity();
307      // @see: use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage::$FIELD_NAME
308      $field_name = 'layout_builder__layout';
309
310      if ($entity->hasField($field_name) && !$entity->get($field_name)->isEmpty()) {
311        $content = $entity->get($field_name)->first()->getValue();
312        $this->initialDataSource = 'layout_builder_override';
313
314        return $this->dataConverter()->convertFromLayoutBuilder($content);
315      }
316    }
317
318    // 3. Copy entity view display value.
319    \assert(\is_string($this->field->getName()));
320    /** @var \Drupal\display_builder\DisplayBuildableInterface $buildable */
321    $buildable = $this->displayBuildableManager()->createInstance('entity_view', ['entity' => $this->display]);
322
323    if ($buildable->getProfile() !== NULL) {
324      $sources = $buildable->getSources();
325    }
326    $this->initialDataSource = 'display_builder';
327
328    return $sources;
329  }
330
331  /**
332   * {@inheritdoc}
333   */
334  protected function getInitialContext(): array {
335    $entity = $this->field->getEntity();
336    $bundle = $entity->bundle();
337    \assert(\is_string($this->field->getName()));
338
339    $view_mode = $this->display->getMode();
340    $contexts = [
341      'entity' => EntityContext::fromEntity($entity),
342      'bundle' => new Context(ContextDefinition::create('string'), $bundle),
343      'view_mode' => new Context(ContextDefinition::create('string'), $view_mode),
344    ];
345
346    return RequirementsContext::addToContext([self::getContextRequirement()], $contexts);
347  }
348
349  /**
350   * Collect instances by field storage.
351   *
352   * @param string $field_name
353   *   Field name.
354   * @param string $entity_type
355   *   Entity type ID.
356   * @param \Drupal\Core\Entity\EntityStorageInterface $instance_storage
357   *   Instance entity storage handler.
358   * @param \Drupal\Core\Entity\Query\QueryInterface $entity_query
359   *   Entity query handler.
360   *
361   * @return array
362   *   A associative array of Instance entities or null values.
363   */
364  protected static function collectInstancesByField(string $field_name, string $entity_type, EntityStorageInterface $instance_storage, QueryInterface $entity_query): array {
365    $instances = [];
366    $entity_query->exists($field_name);
367    // QueryInterface::execute() returns an integer for count queries or an
368    // array of ids.
369    /** @var array $ids */
370    $ids = $entity_query->execute();
371
372    if (empty($ids)) {
373      return [];
374    }
375
376    foreach ($ids as $id) {
377      $instance_id = \sprintf(
378        '%s%s__%s__%s',
379        self::getPrefix(),
380        $entity_type,
381        $id,
382        $field_name,
383      );
384      // We are OK with keeping the null values if the instance entity
385      // doesn't exists in storage. So the caller can decide to create
386      // the missing Instance entities.
387      $instances[$instance_id] = $instance_storage->load($instance_id);
388    }
389
390    return $instances;
391  }
392
393  /**
394   * Get the time service.
395   *
396   * @return \Drupal\Component\Datetime\TimeInterface
397   *   The time service.
398   */
399  protected function time(): TimeInterface {
400    return $this->time ??= \Drupal::service('datetime.time');
401  }
402
403  /**
404   * Get the entity type manager.
405   *
406   * @return \Drupal\Core\Entity\EntityTypeManagerInterface
407   *   The entity type manager.
408   */
409  protected function entityTypeManager(): EntityTypeManagerInterface {
410    return $this->entityTypeManager ??= \Drupal::service('entity_type.manager');
411  }
412
413  /**
414   * Gets the display buildable manager.
415   *
416   * @return \Drupal\display_builder\DisplayBuildablePluginManager
417   *   The manager for display buildable.
418   */
419  protected function displayBuildableManager(): DisplayBuildablePluginManager {
420    return $this->displayBuildableManager ??= \Drupal::service('plugin.manager.display_buildable');
421  }
422
423  /**
424   * Get the data converter from Manage Display and Layout Builder.
425   *
426   * @return \Drupal\display_builder_entity_view\BuilderDataConverter
427   *   The converter.
428   */
429  protected function dataConverter(): BuilderDataConverter {
430    return $this->dataConverter ??= \Drupal::service('display_builder_entity_view.builder_data_converter');
431  }
432
433  /**
434   * Get entity view display entity.
435   *
436   * @param string $entity_type_id
437   *   Entity type ID.
438   * @param string $bundle
439   *   Entity's bundle which support fields.
440   * @param string $fieldName
441   *   Field name of the display.
442   *
443   * @return \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface|null
444   *   The corresponding entity view display.
445   */
446  private static function getEntityViewDisplay(string $entity_type_id, string $bundle, string $fieldName): ?DisplayBuilderEntityDisplayInterface {
447    /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface[] $displays */
448    $displays = \Drupal::entityTypeManager()->getStorage('entity_view_display')->loadByProperties([
449      'targetEntityType' => $entity_type_id,
450    ]);
451
452    foreach ($displays as $display) {
453      if ($display instanceof DisplayBuilderOverridableInterface
454        && $display->getDisplayBuilderOverrideField() === $fieldName
455        && $display->getTargetEntityTypeId()
456        && $display->getTargetBundle() === $bundle
457      ) {
458        return $display;
459      }
460    }
461
462    return NULL;
463  }
464
465}

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.

EntityViewOverride->__construct
71  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
72    parent::__construct($configuration, $plugin_id, $plugin_definition);
73    $this->field = $configuration['field'];
74    \assert(\is_string($this->field->getName()));
75    $entity = $this->field->getEntity();
76    $this->display = self::getEntityViewDisplay(
77      $entity->getEntityTypeId(),
78      $entity->bundle(),
79      $this->field->getName(),
80    );
81  }
EntityViewOverride->checkAccess
189  public static function checkAccess(string $instance_id, AccountInterface $account): AccessResultInterface {
190    [, $entity_type_id, $entity_id] = \explode('__', $instance_id);
191    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
192
193    if (!$entity) {
194      return AccessResult::neutral();
197    return $entity->access('update', $account, TRUE);
198  }
EntityViewOverride->checkInstanceId
108  public static function checkInstanceId(string $instance_id): ?array {
109    if (!\str_starts_with($instance_id, self::getPrefix())) {
110      return NULL;
112    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
113
114    return [
115      'entity_type_id' => $entity_type_id,
116      'entity_id' => $entity_id,
117      'field_name' => $field_name,
118    ];
119  }
EntityViewOverride->collectInstances
246  public static function collectInstances(?EntityTypeManagerInterface $entityTypeManager = NULL): array {
247    $instances = [];
248    $entityTypeManager = \Drupal::service('entity_type.manager');
249    $storage = $entityTypeManager->getStorage('entity_view_display');
250    $instance_storage = $entityTypeManager->getStorage('display_builder_instance');
251    $entity_query = $entity_storage = [];
252
253    foreach ($storage->loadMultiple() as $display) {
253    foreach ($storage->loadMultiple() as $display) {
255      $display_builder = $display->getThirdPartySettings('display_builder');
256
257      if (!isset($display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY], $display_builder[DisplayBuildableInterface::OVERRIDE_PROFILE_PROPERTY])) {
257      if (!isset($display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY], $display_builder[DisplayBuildableInterface::OVERRIDE_PROFILE_PROPERTY])) {
257      if (!isset($display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY], $display_builder[DisplayBuildableInterface::OVERRIDE_PROFILE_PROPERTY])) {
258        continue;
261      $entity_type = $display->getTargetEntityTypeId();
262      $field_name = $display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY] ?? NULL;
263
264      if (!$field_name) {
265        continue;
253    foreach ($storage->loadMultiple() as $display) {
254      /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
255      $display_builder = $display->getThirdPartySettings('display_builder');
256
257      if (!isset($display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY], $display_builder[DisplayBuildableInterface::OVERRIDE_PROFILE_PROPERTY])) {
258        continue;
259      }
260
261      $entity_type = $display->getTargetEntityTypeId();
262      $field_name = $display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY] ?? NULL;
263
264      if (!$field_name) {
265        continue;
266      }
267      $entity_storage[$entity_type] ??= $entityTypeManager->getStorage($entity_type);
253    foreach ($storage->loadMultiple() as $display) {
254      /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
255      $display_builder = $display->getThirdPartySettings('display_builder');
256
257      if (!isset($display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY], $display_builder[DisplayBuildableInterface::OVERRIDE_PROFILE_PROPERTY])) {
258        continue;
259      }
260
261      $entity_type = $display->getTargetEntityTypeId();
262      $field_name = $display_builder[DisplayBuildableInterface::OVERRIDE_FIELD_PROPERTY] ?? NULL;
263
264      if (!$field_name) {
265        continue;
266      }
267      $entity_storage[$entity_type] ??= $entityTypeManager->getStorage($entity_type);
268      $entity_query[$entity_type] ??= $entity_storage[$entity_type]->getQuery()->accessCheck(FALSE);
269      $instances = \array_merge($instances, self::collectInstancesByField($field_name, $entity_type, $instance_storage, $entity_query[$entity_type]));
270    }
271
272    return $instances;
273  }
EntityViewOverride->collectInstancesByField
364  protected static function collectInstancesByField(string $field_name, string $entity_type, EntityStorageInterface $instance_storage, QueryInterface $entity_query): array {
365    $instances = [];
366    $entity_query->exists($field_name);
367    // QueryInterface::execute() returns an integer for count queries or an
368    // array of ids.
369    /** @var array $ids */
370    $ids = $entity_query->execute();
371
372    if (empty($ids)) {
373      return [];
376    foreach ($ids as $id) {
376    foreach ($ids as $id) {
376    foreach ($ids as $id) {
377      $instance_id = \sprintf(
378        '%s%s__%s__%s',
379        self::getPrefix(),
376    foreach ($ids as $id) {
377      $instance_id = \sprintf(
378        '%s%s__%s__%s',
379        self::getPrefix(),
380        $entity_type,
381        $id,
382        $field_name,
383      );
384      // We are OK with keeping the null values if the instance entity
385      // doesn't exists in storage. So the caller can decide to create
386      // the missing Instance entities.
387      $instances[$instance_id] = $instance_storage->load($instance_id);
388    }
389
390    return $instances;
391  }
EntityViewOverride->dataConverter
430    return $this->dataConverter ??= \Drupal::service('display_builder_entity_view.builder_data_converter');
431  }
EntityViewOverride->displayBuildableManager
420    return $this->displayBuildableManager ??= \Drupal::service('plugin.manager.display_buildable');
421  }
EntityViewOverride->entityTypeManager
410    return $this->entityTypeManager ??= \Drupal::service('entity_type.manager');
411  }
EntityViewOverride->getBuilderUrl
94    \assert(\is_string($this->field->getName()));
95    $entity = $this->field->getEntity();
96    $entity_type_id = $this->display->getTargetEntityTypeId();
97    $parameters = [
98      $entity_type_id => $entity->id(),
99      'view_mode_name' => $this->display->getMode(),
100    ];
101
102    return Url::fromRoute(\sprintf('entity.%s.display_builder.%s', $entity_type_id, $this->display->getMode()), $parameters);
103  }
EntityViewOverride->getContextRequirement
87    return 'content';
88  }
EntityViewOverride->getDisplayUrlFromInstanceId
151  public static function getDisplayUrlFromInstanceId(string $instance_id): Url {
152    return Url::fromRoute('<front>');
153  }
EntityViewOverride->getEntityViewDisplay
446  private static function getEntityViewDisplay(string $entity_type_id, string $bundle, string $fieldName): ?DisplayBuilderEntityDisplayInterface {
447    /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface[] $displays */
448    $displays = \Drupal::entityTypeManager()->getStorage('entity_view_display')->loadByProperties([
449      'targetEntityType' => $entity_type_id,
450    ]);
451
452    foreach ($displays as $display) {
452    foreach ($displays as $display) {
453      if ($display instanceof DisplayBuilderOverridableInterface
454        && $display->getDisplayBuilderOverrideField() === $fieldName
454        && $display->getDisplayBuilderOverrideField() === $fieldName
455        && $display->getTargetEntityTypeId()
455        && $display->getTargetEntityTypeId()
456        && $display->getTargetBundle() === $bundle
456        && $display->getTargetBundle() === $bundle
458        return $display;
452    foreach ($displays as $display) {
452    foreach ($displays as $display) {
453      if ($display instanceof DisplayBuilderOverridableInterface
454        && $display->getDisplayBuilderOverrideField() === $fieldName
455        && $display->getTargetEntityTypeId()
456        && $display->getTargetBundle() === $bundle
457      ) {
458        return $display;
459      }
460    }
461
462    return NULL;
463  }
EntityViewOverride->getInitialContext
335    $entity = $this->field->getEntity();
336    $bundle = $entity->bundle();
337    \assert(\is_string($this->field->getName()));
338
339    $view_mode = $this->display->getMode();
340    $contexts = [
341      'entity' => EntityContext::fromEntity($entity),
342      'bundle' => new Context(ContextDefinition::create('string'), $bundle),
343      'view_mode' => new Context(ContextDefinition::create('string'), $view_mode),
344    ];
345
346    return RequirementsContext::addToContext([self::getContextRequirement()], $contexts);
347  }
EntityViewOverride->getInitialSources
294    $sources = $this->getSources();
295
296    // 1. Keep the existing override value if existing.
297    if (\count($sources) > 0) {
298      return $sources;
305    if ($this->display->getMode() === 'default') {
306      $entity = $this->field->getEntity();
307      // @see: use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage::$FIELD_NAME
308      $field_name = 'layout_builder__layout';
309
310      if ($entity->hasField($field_name) && !$entity->get($field_name)->isEmpty()) {
310      if ($entity->hasField($field_name) && !$entity->get($field_name)->isEmpty()) {
310      if ($entity->hasField($field_name) && !$entity->get($field_name)->isEmpty()) {
311        $content = $entity->get($field_name)->first()->getValue();
312        $this->initialDataSource = 'layout_builder_override';
313
314        return $this->dataConverter()->convertFromLayoutBuilder($content);
319    \assert(\is_string($this->field->getName()));
320    /** @var \Drupal\display_builder\DisplayBuildableInterface $buildable */
321    $buildable = $this->displayBuildableManager()->createInstance('entity_view', ['entity' => $this->display]);
322
323    if ($buildable->getProfile() !== NULL) {
324      $sources = $buildable->getSources();
325    }
326    $this->initialDataSource = 'display_builder';
326    $this->initialDataSource = 'display_builder';
327
328    return $sources;
329  }
EntityViewOverride->getInitializationMessage
279    if ($this->initialDataSource === 'display_builder') {
280      return $this->t('Copy from Entity View Display configuration.');
283    if ($this->initialDataSource === 'layout_builder_override') {
284      return $this->t('Import from Layout Builder override.');
287    return $this->t('Initialization from existing content.');
288  }
EntityViewOverride->getInstanceId
205    if ($this->field->getEntity()->isNew()) {
206      return NULL;
209    $entity = $this->field->getEntity();
210
211    return \sprintf(
212      '%s%s__%s__%s',
213      self::getPrefix(),
214      $entity->getEntityTypeId(),
215      $entity->id(),
216      $this->field->getName()
217    );
218  }
EntityViewOverride->getProfile
159    \assert($this->display instanceof DisplayBuilderOverridableInterface);
160
161    return $this->display->getDisplayBuilderOverrideProfile();
162  }
EntityViewOverride->getSources
168    return $this->field->getValue();
169  }
EntityViewOverride->getUrlFromInstanceId
124  public static function getUrlFromInstanceId(string $instance_id): Url {
125    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
126
127    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
128
129    if (!$entity) {
130      return Url::fromRoute('entity.display_builder_instance.collection');
133    $display = self::getEntityViewDisplay($entity_type_id, $entity->bundle(), $field_name);
134
135    if (!$display) {
136      return Url::fromRoute('entity.display_builder_instance.collection');
139      $entity_type_id => $entity_id,
140      'view_mode_name' => $display->getMode(),
141    ];
142
143    $route_name = \sprintf('entity.%s.display_builder.%s', $entity_type_id, $display->getMode());
144
145    return Url::fromRoute($route_name, $params);
146  }
EntityViewOverride->saveSources
175    $data = $this->getInstance()->getCurrentState();
176    $entity = $this->field->getEntity();
177
178    if ($entity instanceof ContentEntityInterface) {
179      $this->setRevision($entity);
180    }
181    $entity->save();
181    $entity->save();
182    $this->field->setValue($data);
183    $this->field->getEntity()->save();
184  }
EntityViewOverride->setRevision
226  public function setRevision(ContentEntityInterface $entity): void {
227    $bundle = $entity->getBundleEntity();
228
229    if ($bundle instanceof RevisionableEntityBundleInterface
230      && !$bundle->shouldCreateNewRevision()
230      && !$bundle->shouldCreateNewRevision()
232      return;
235    $entity->setNewRevision();
236
237    if ($entity instanceof RevisionLogInterface) {
238      $entity->setRevisionLogMessage($this->t('Updated using Display Builder.')->render());
239      $entity->setRevisionCreationTime($this->time()->getCurrentTime());
240    }
241  }
241  }
EntityViewOverride->time
400    return $this->time ??= \Drupal::service('datetime.time');
401  }