Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
DisplayBuilderItemList
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 17
930
0.00% covered (danger)
0.00%
0 / 1
 getPrefix
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
 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 / 13
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 / 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
 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 / 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
 getInstanceId
0.00% covered (danger)
0.00%
0 / 9
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
 getSources
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 saveSources
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 checkAccess
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
 initInstanceIfMissing
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
 getInitialSources
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 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
 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
 getEntityViewDisplay
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
42
 getInstance
0.00% covered (danger)
0.00%
0 / 4
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\Field;
6
7use Drupal\Core\Access\AccessResultInterface;
8use Drupal\Core\Entity\EntityTypeManagerInterface;
9use Drupal\Core\Field\MapFieldItemList;
10use Drupal\Core\Plugin\Context\Context;
11use Drupal\Core\Plugin\Context\ContextDefinition;
12use Drupal\Core\Plugin\Context\EntityContext;
13use Drupal\Core\Session\AccountInterface;
14use Drupal\Core\Url;
15use Drupal\display_builder\DisplayBuildableInterface;
16use Drupal\display_builder\InstanceInterface;
17use Drupal\display_builder\ProfileInterface;
18use Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface;
19use Drupal\display_builder_entity_view\Entity\DisplayBuilderOverridableInterface;
20use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
21
22/**
23 * Defines an item list class for layout section fields.
24 *
25 * @internal
26 *   Plugin classes are internal.
27 *
28 * @see \Drupal\layout_builder\Plugin\Field\FieldType\LayoutSectionItem
29 *
30 * phpcs:disable DrupalPractice.Objects.GlobalDrupal.GlobalDrupal
31 */
32final class DisplayBuilderItemList extends MapFieldItemList implements DisplayBuildableInterface {
33
34  /**
35   * The entity type manager.
36   */
37  protected ?EntityTypeManagerInterface $entityTypeManager;
38
39  /**
40   * The loaded display builder instance.
41   */
42  protected ?InstanceInterface $instance;
43
44  /**
45   * {@inheritdoc}
46   */
47  public static function getPrefix(): string {
48    return 'entity_override__';
49  }
50
51  /**
52   * {@inheritdoc}
53   */
54  public static function getContextRequirement(): string {
55    return 'content';
56  }
57
58  /**
59   * {@inheritdoc}
60   */
61  public function getBuilderUrl(): Url {
62    \assert(\is_string($this->getName()));
63    $entity = $this->getEntity();
64    $entity_view = self::getEntityViewDisplay(
65      $entity->getEntityTypeId(),
66      $entity->bundle(),
67      $this->getName(),
68    );
69    $entity_type_id = $entity_view->getTargetEntityTypeId();
70    $parameters = [
71      $entity_type_id => $entity->id(),
72      'view_mode_name' => $entity_view->getMode(),
73    ];
74
75    return Url::fromRoute("entity.{$entity_type_id}.display_builder.{$entity_view->getMode()}", $parameters);
76  }
77
78  /**
79   * {@inheritdoc}
80   */
81  public static function checkInstanceId(string $instance_id): ?array {
82    if (!\str_starts_with($instance_id, self::getPrefix())) {
83      return NULL;
84    }
85    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
86
87    return [
88      'entity_type_id' => $entity_type_id,
89      'entity_id' => $entity_id,
90      'field_name' => $field_name,
91    ];
92  }
93
94  /**
95   * {@inheritdoc}
96   */
97  public static function getUrlFromInstanceId(string $instance_id): Url {
98    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
99
100    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
101    $display = self::getEntityViewDisplay($entity_type_id, $entity->bundle(), $field_name);
102    $params = [
103      $entity_type_id => $entity_id,
104      'view_mode_name' => $display->getMode(),
105    ];
106
107    $route_name = \sprintf('entity.%s.display_builder.%s', $entity_type_id, $display->getMode());
108
109    return Url::fromRoute($route_name, $params);
110  }
111
112  /**
113   * {@inheritdoc}
114   */
115  public static function getDisplayUrlFromInstanceId(string $instance_id): Url {
116    return Url::fromRoute('<front>');
117  }
118
119  /**
120   * {@inheritdoc}
121   */
122  public function getProfile(): ?ProfileInterface {
123    \assert(\is_string($this->getName()));
124    $entity = $this->getEntity();
125
126    $entity_view = self::getEntityViewDisplay(
127      $entity->getEntityTypeId(),
128      $entity->bundle(),
129      $this->getName(),
130    );
131    \assert($entity_view instanceof DisplayBuilderOverridableInterface);
132
133    return $entity_view->getDisplayBuilderOverrideProfile();
134  }
135
136  /**
137   * {@inheritdoc}
138   */
139  public function getInstanceId(): ?string {
140    // Usually an entity is new if no ID exists for it yet.
141    if ($this->getEntity()->isNew()) {
142      return NULL;
143    }
144
145    $entity = $this->getEntity();
146
147    return \sprintf('%s%s__%s__%s',
148      self::getPrefix(),
149      $entity->getEntityTypeId(),
150      $entity->id(),
151      $this->getName()
152    );
153  }
154
155  /**
156   * {@inheritdoc}
157   */
158  public function getSources(): array {
159    $data = [];
160
161    foreach ($this->list as $offset => $item) {
162      $data[$offset] = $item->getValue();
163    }
164
165    return $data;
166  }
167
168  /**
169   * {@inheritdoc}
170   */
171  public function saveSources(): void {
172    $data = $this->getInstance()->getCurrentState();
173    $this->list = [];
174
175    foreach ($data as $offset => $item) {
176      $this->list[$offset] = $this->createItem($offset, $item);
177    }
178    $this->getEntity()->save();
179  }
180
181  /**
182   * {@inheritdoc}
183   */
184  public static function checkAccess(string $instance_id, AccountInterface $account): AccessResultInterface {
185    [, $entity_type_id, $entity_id] = \explode('__', $instance_id);
186
187    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
188
189    return $entity->access('update', $account, TRUE);
190  }
191
192  /**
193   * {@inheritdoc}
194   */
195  public function initInstanceIfMissing(): void {
196    /** @var \Drupal\display_builder\InstanceStorage $storage */
197    $storage = $this->entityTypeManager()->getStorage('display_builder_instance');
198
199    /** @var \Drupal\display_builder\InstanceInterface $instance */
200    $instance = $storage->load($this->getInstanceId());
201
202    if (!$instance) {
203      $instance = $storage->createFromImplementation($this);
204      $instance->save();
205    }
206  }
207
208  /**
209   * {@inheritdoc}
210   */
211  public function getInitialSources(): array {
212    $sources = $this->getSources();
213    $entity = $this->getEntity();
214
215    if (\count($sources) === 0) {
216      \assert(\is_string($this->getName()));
217      $display = self::getEntityViewDisplay($entity->getEntityTypeId(), $entity->bundle(), $this->getName());
218
219      if ($display->getProfile() !== NULL) {
220        $sources = $display->getSources();
221      }
222    }
223
224    return $sources;
225  }
226
227  /**
228   * {@inheritdoc}
229   */
230  public function getInitialContext(): array {
231    $entity = $this->getEntity();
232    $bundle = $entity->bundle();
233    \assert(\is_string($this->getName()));
234
235    $view_mode = self::getEntityViewDisplay($entity->getEntityTypeId(), $bundle, $this->getName())->getMode();
236    $contexts = [
237      'entity' => EntityContext::fromEntity($entity),
238      'bundle' => new Context(ContextDefinition::create('string'), $bundle),
239      'view_mode' => new Context(ContextDefinition::create('string'), $view_mode),
240    ];
241
242    return RequirementsContext::addToContext([self::getContextRequirement()], $contexts);
243  }
244
245  /**
246   * Get the entity type manager.
247   *
248   * @return \Drupal\Core\Entity\EntityTypeManagerInterface
249   *   The entity type manager.
250   */
251  protected function entityTypeManager(): EntityTypeManagerInterface {
252    return $this->entityTypeManager ??= \Drupal::service('entity_type.manager');
253  }
254
255  /**
256   * Get entity view display entity.
257   *
258   * @param string $entity_type_id
259   *   Entity type ID.
260   * @param string $bundle
261   *   Entity's bundle which support fields.
262   * @param string $fieldName
263   *   Field name of the display.
264   *
265   * @return \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface|null
266   *   The corresponding entity view display.
267   */
268  private static function getEntityViewDisplay(string $entity_type_id, string $bundle, string $fieldName): ?DisplayBuilderEntityDisplayInterface {
269    /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface[] $displays */
270    $displays = \Drupal::entityTypeManager()->getStorage('entity_view_display')->loadByProperties([
271      'targetEntityType' => $entity_type_id,
272    ]);
273
274    foreach ($displays as $display) {
275      if ($display instanceof DisplayBuilderOverridableInterface
276        && $display->getDisplayBuilderOverrideField() === $fieldName
277        && $display->getTargetEntityTypeId()
278        && $display->getTargetBundle() === $bundle
279      ) {
280        return $display;
281      }
282    }
283
284    return NULL;
285  }
286
287  /**
288   * Gets the Display Builder instance.
289   *
290   * @return \Drupal\display_builder\InstanceInterface|null
291   *   A display builder instance.
292   */
293  private function getInstance(): ?InstanceInterface {
294    if (!isset($this->instance)) {
295      /** @var \Drupal\display_builder\InstanceInterface|null $instance */
296      $instance = $this->entityTypeManager()->getStorage('display_builder_instance')->load($this->getInstanceId());
297      $this->instance = $instance;
298    }
299
300    return $this->instance;
301  }
302
303}

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.

DisplayBuilderItemList->checkAccess
184  public static function checkAccess(string $instance_id, AccountInterface $account): AccessResultInterface {
185    [, $entity_type_id, $entity_id] = \explode('__', $instance_id);
186
187    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
188
189    return $entity->access('update', $account, TRUE);
DisplayBuilderItemList->checkInstanceId
81  public static function checkInstanceId(string $instance_id): ?array {
82    if (!\str_starts_with($instance_id, self::getPrefix())) {
83      return NULL;
85    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
86
87    return [
88      'entity_type_id' => $entity_type_id,
89      'entity_id' => $entity_id,
90      'field_name' => $field_name,
DisplayBuilderItemList->entityTypeManager
252    return $this->entityTypeManager ??= \Drupal::service('entity_type.manager');
DisplayBuilderItemList->getBuilderUrl
62    \assert(\is_string($this->getName()));
63    $entity = $this->getEntity();
64    $entity_view = self::getEntityViewDisplay(
65      $entity->getEntityTypeId(),
66      $entity->bundle(),
67      $this->getName(),
68    );
69    $entity_type_id = $entity_view->getTargetEntityTypeId();
70    $parameters = [
71      $entity_type_id => $entity->id(),
72      'view_mode_name' => $entity_view->getMode(),
73    ];
74
75    return Url::fromRoute("entity.{$entity_type_id}.display_builder.{$entity_view->getMode()}", $parameters);
DisplayBuilderItemList->getContextRequirement
55    return 'content';
DisplayBuilderItemList->getDisplayUrlFromInstanceId
115  public static function getDisplayUrlFromInstanceId(string $instance_id): Url {
116    return Url::fromRoute('<front>');
DisplayBuilderItemList->getEntityViewDisplay
268  private static function getEntityViewDisplay(string $entity_type_id, string $bundle, string $fieldName): ?DisplayBuilderEntityDisplayInterface {
269    /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface[] $displays */
270    $displays = \Drupal::entityTypeManager()->getStorage('entity_view_display')->loadByProperties([
271      'targetEntityType' => $entity_type_id,
272    ]);
273
274    foreach ($displays as $display) {
274    foreach ($displays as $display) {
275      if ($display instanceof DisplayBuilderOverridableInterface
276        && $display->getDisplayBuilderOverrideField() === $fieldName
277        && $display->getTargetEntityTypeId()
278        && $display->getTargetBundle() === $bundle
280        return $display;
274    foreach ($displays as $display) {
275      if ($display instanceof DisplayBuilderOverridableInterface
276        && $display->getDisplayBuilderOverrideField() === $fieldName
277        && $display->getTargetEntityTypeId()
278        && $display->getTargetBundle() === $bundle
279      ) {
280        return $display;
281      }
282    }
283
284    return NULL;
DisplayBuilderItemList->getInitialContext
231    $entity = $this->getEntity();
232    $bundle = $entity->bundle();
233    \assert(\is_string($this->getName()));
234
235    $view_mode = self::getEntityViewDisplay($entity->getEntityTypeId(), $bundle, $this->getName())->getMode();
236    $contexts = [
237      'entity' => EntityContext::fromEntity($entity),
238      'bundle' => new Context(ContextDefinition::create('string'), $bundle),
239      'view_mode' => new Context(ContextDefinition::create('string'), $view_mode),
240    ];
241
242    return RequirementsContext::addToContext([self::getContextRequirement()], $contexts);
DisplayBuilderItemList->getInitialSources
212    $sources = $this->getSources();
213    $entity = $this->getEntity();
214
215    if (\count($sources) === 0) {
216      \assert(\is_string($this->getName()));
217      $display = self::getEntityViewDisplay($entity->getEntityTypeId(), $entity->bundle(), $this->getName());
218
219      if ($display->getProfile() !== NULL) {
220        $sources = $display->getSources();
221      }
222    }
223
224    return $sources;
224    return $sources;
DisplayBuilderItemList->getInstance
294    if (!isset($this->instance)) {
296      $instance = $this->entityTypeManager()->getStorage('display_builder_instance')->load($this->getInstanceId());
297      $this->instance = $instance;
298    }
299
300    return $this->instance;
300    return $this->instance;
DisplayBuilderItemList->getInstanceId
141    if ($this->getEntity()->isNew()) {
142      return NULL;
145    $entity = $this->getEntity();
146
147    return \sprintf('%s%s__%s__%s',
148      self::getPrefix(),
149      $entity->getEntityTypeId(),
150      $entity->id(),
151      $this->getName()
DisplayBuilderItemList->getPrefix
48    return 'entity_override__';
DisplayBuilderItemList->getProfile
123    \assert(\is_string($this->getName()));
124    $entity = $this->getEntity();
125
126    $entity_view = self::getEntityViewDisplay(
127      $entity->getEntityTypeId(),
128      $entity->bundle(),
129      $this->getName(),
130    );
131    \assert($entity_view instanceof DisplayBuilderOverridableInterface);
132
133    return $entity_view->getDisplayBuilderOverrideProfile();
DisplayBuilderItemList->getSources
159    $data = [];
160
161    foreach ($this->list as $offset => $item) {
161    foreach ($this->list as $offset => $item) {
161    foreach ($this->list as $offset => $item) {
161    foreach ($this->list as $offset => $item) {
162      $data[$offset] = $item->getValue();
163    }
164
165    return $data;
DisplayBuilderItemList->getUrlFromInstanceId
97  public static function getUrlFromInstanceId(string $instance_id): Url {
98    [, $entity_type_id, $entity_id, $field_name] = \explode('__', $instance_id);
99
100    $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
101    $display = self::getEntityViewDisplay($entity_type_id, $entity->bundle(), $field_name);
102    $params = [
103      $entity_type_id => $entity_id,
104      'view_mode_name' => $display->getMode(),
105    ];
106
107    $route_name = \sprintf('entity.%s.display_builder.%s', $entity_type_id, $display->getMode());
108
109    return Url::fromRoute($route_name, $params);
DisplayBuilderItemList->initInstanceIfMissing
197    $storage = $this->entityTypeManager()->getStorage('display_builder_instance');
198
199    /** @var \Drupal\display_builder\InstanceInterface $instance */
200    $instance = $storage->load($this->getInstanceId());
201
202    if (!$instance) {
203      $instance = $storage->createFromImplementation($this);
204      $instance->save();
205    }
206  }
206  }
DisplayBuilderItemList->saveSources
172    $data = $this->getInstance()->getCurrentState();
173    $this->list = [];
174
175    foreach ($data as $offset => $item) {
175    foreach ($data as $offset => $item) {
175    foreach ($data as $offset => $item) {
175    foreach ($data as $offset => $item) {
176      $this->list[$offset] = $this->createItem($offset, $item);
177    }
178    $this->getEntity()->save();
179  }