Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 158
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
PresetLibraryPanel
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 158
0.00% covered (danger)
0.00%
0 / 6
306
0.00% covered (danger)
0.00%
0 / 1
 create
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
 build
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 onPresetSave
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
 buildPresets
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 144
0.00% covered (danger)
0.00%
0 / 1
56
 buildPresetItem
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getPresetGroup
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 4
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\Plugin\display_builder\Island;
6
7use Drupal\Core\Entity\EntityStorageInterface;
8use Drupal\Core\StringTranslation\TranslatableMarkup;
9use Drupal\Core\Url;
10use Drupal\display_builder\Attribute\Island;
11use Drupal\display_builder\BlockLibrarySourceHelper;
12use Drupal\display_builder\Entity\PatternPresetInterface;
13use Drupal\display_builder\InstanceInterface;
14use Drupal\display_builder\Island\IslandPluginBase;
15use Drupal\display_builder\Island\IslandType;
16use Symfony\Component\DependencyInjection\ContainerInterface;
17
18/**
19 * Preset island plugin implementation.
20 */
21#[Island(
22  id: 'preset_library',
23  label: new TranslatableMarkup('Presets'),
24  description: new TranslatableMarkup('List of preset, already build group of components.'),
25  type: IslandType::Library,
26)]
27class PresetLibraryPanel extends IslandPluginBase {
28
29  /**
30   * The Pattern preset storage.
31   */
32  protected EntityStorageInterface $presetConfigStorage;
33
34  /**
35   * {@inheritdoc}
36   */
37  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
38    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
39    $instance->presetConfigStorage = $container->get('entity_type.manager')->getStorage('pattern_preset');
40
41    return $instance;
42  }
43
44  /**
45   * {@inheritdoc}
46   */
47  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
48    $builder_id = (string) $builder->id();
49    $entity_ids = $this->presetConfigStorage->getQuery()
50      ->accessCheck(TRUE)
51      ->condition('status', TRUE)
52      ->sort('weight', 'ASC')
53      ->execute();
54    /** @var \Drupal\display_builder\Entity\PatternPresetInterface[] $presets */
55    $presets = $this->presetConfigStorage->loadMultiple($entity_ids);
56    $contexts = $this->configuration['contexts'] ?? [];
57
58    foreach ($presets as $preset_id => $preset) {
59      if (!$preset->areContextsSatisfied($contexts)) {
60        unset($presets[$preset_id]);
61      }
62    }
63
64    if (empty($presets)) {
65      $content = [
66        [
67          '#type' => 'html_tag',
68          '#tag' => 'p',
69        ],
70        [
71          '#type' => 'html_tag',
72          '#tag' => 'p',
73          '#value' => $this->t('Pattern presets are reusable arrangements of components and blocks.'),
74        ],
75        [
76          '#type' => 'html_tag',
77          '#tag' => 'p',
78          '#value' => $this->t('Add presets from the contextual menu.'),
79        ],
80      ];
81    }
82    else {
83      $content = $this->buildPresets($builder_id, $presets);
84    }
85
86    return [
87      '#type' => 'component',
88      '#component' => 'display_builder:library_panel',
89      '#slots' => [
90        'content' => $content,
91      ],
92      '#cache' => [
93        'tags' => $this->presetConfigStorage->getEntityType()->getListCacheTags(),
94      ],
95    ];
96  }
97
98  /**
99   * {@inheritdoc}
100   */
101  public function onPresetSave(InstanceInterface $instance): array {
102    return $this->reloadWithGlobalData($instance);
103  }
104
105  /**
106   * Build preset as placeholder grouped.
107   *
108   * @param string $builder_id
109   *   Builder ID.
110   * @param \Drupal\display_builder\Entity\PatternPresetInterface[] $presets
111   *   The presets to build.
112   *
113   * @return array
114   *   Array of grouped preset plugins.
115   */
116  private function buildPresets(string $builder_id, array $presets): array {
117    $build = [];
118    $grouped_presets = [];
119
120    foreach ($presets as $preset_id => $preset) {
121      $group_key = $this->getPresetGroup($preset);
122      $grouped_presets[$group_key][$preset_id] = $preset;
123    }
124
125    $formatted_groups = [];
126
127    foreach ($grouped_presets as $group_name => $presets_in_group) {
128      $formatted_groups[$group_name] = [
129        'label' => $group_name,
130        'choices' => $presets_in_group,
131      ];
132    }
133
134    $is_single_group = \count($formatted_groups) === 1;
135
136    if (!$is_single_group) {
137      BlockLibrarySourceHelper::sortGroupedChoices($formatted_groups);
138    }
139
140    foreach ($formatted_groups as $group_data) {
141      if (!$is_single_group) {
142        $build[] = [
143          '#type' => 'html_tag',
144          '#tag' => 'h4',
145          '#value' => $group_data['label'],
146          '#attributes' => [
147            'class' => ['db-filter-hide-on-search'],
148          ],
149        ];
150      }
151
152      foreach ($group_data['choices'] as $preset) {
153        $build[] = $this->buildPresetItem($builder_id, $preset, TRUE);
154      }
155    }
156
157    $build = $this->buildDraggables($builder_id, $build);
158    $build['#source_contexts'] = $this->configuration['contexts'] ?? [];
159
160    return $build;
161  }
162
163  /**
164   * Build a preset item.
165   *
166   * @param string $builder_id
167   *   Builder ID.
168   * @param \Drupal\display_builder\Entity\PatternPresetInterface $preset
169   *   The preset entity.
170   * @param bool $with_preview
171   *   Whether to include preview attributes.
172   *
173   * @return array
174   *   The render array for the preset item.
175   */
176  private function buildPresetItem(string $builder_id, PatternPresetInterface $preset, bool $with_preview): array {
177    $keywords = \sprintf('%s %s', $preset->get('label'), $preset->get('description') ?? '');
178    $vals = ['preset_id' => $preset->id()];
179
180    if ($with_preview) {
181      $url = Url::fromRoute('display_builder.api_preset_preview', $vals);
182
183      $build = $this->buildPlaceholderButtonWithPreview($builder_id, $preset->get('label'), $vals, $url, $keywords);
184    }
185    else {
186      $build = $this->buildPlaceholderButton($preset->get('label'), $vals, $keywords);
187    }
188
189    $build['#attributes']['data-instance-id'][] = $preset->id();
190
191    return $build;
192  }
193
194  /**
195   * Gets the preset's group from the preset entity in the database.
196   *
197   * @param \Drupal\display_builder\Entity\PatternPresetInterface $preset
198   *   The preset entity.
199   *
200   * @return string
201   *   The group name, fallback to 'Others'.
202   */
203  private function getPresetGroup(PatternPresetInterface $preset): string {
204    return $preset->getGroup() ? (string) $preset->getGroup() : (string) $this->t('Others');
205  }
206
207}

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.

PresetLibraryPanel->build
47  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
48    $builder_id = (string) $builder->id();
49    $entity_ids = $this->presetConfigStorage->getQuery()
50      ->accessCheck(TRUE)
51      ->condition('status', TRUE)
52      ->sort('weight', 'ASC')
53      ->execute();
54    /** @var \Drupal\display_builder\Entity\PatternPresetInterface[] $presets */
55    $presets = $this->presetConfigStorage->loadMultiple($entity_ids);
56    $contexts = $this->configuration['contexts'] ?? [];
57
58    foreach ($presets as $preset_id => $preset) {
58    foreach ($presets as $preset_id => $preset) {
58    foreach ($presets as $preset_id => $preset) {
59      if (!$preset->areContextsSatisfied($contexts)) {
58    foreach ($presets as $preset_id => $preset) {
59      if (!$preset->areContextsSatisfied($contexts)) {
60        unset($presets[$preset_id]);
58    foreach ($presets as $preset_id => $preset) {
58    foreach ($presets as $preset_id => $preset) {
59      if (!$preset->areContextsSatisfied($contexts)) {
60        unset($presets[$preset_id]);
61      }
62    }
63
64    if (empty($presets)) {
64    if (empty($presets)) {
65      $content = [
66        [
67          '#type' => 'html_tag',
83      $content = $this->buildPresets($builder_id, $presets);
84    }
85
86    return [
87      '#type' => 'component',
87      '#type' => 'component',
88      '#component' => 'display_builder:library_panel',
89      '#slots' => [
90        'content' => $content,
91      ],
92      '#cache' => [
93        'tags' => $this->presetConfigStorage->getEntityType()->getListCacheTags(),
94      ],
95    ];
96  }
PresetLibraryPanel->buildPresetItem
176  private function buildPresetItem(string $builder_id, PatternPresetInterface $preset, bool $with_preview): array {
177    $keywords = \sprintf('%s %s', $preset->get('label'), $preset->get('description') ?? '');
178    $vals = ['preset_id' => $preset->id()];
179
180    if ($with_preview) {
180    if ($with_preview) {
181      $url = Url::fromRoute('display_builder.api_preset_preview', $vals);
186      $build = $this->buildPlaceholderButton($preset->get('label'), $vals, $keywords);
187    }
188
189    $build['#attributes']['data-instance-id'][] = $preset->id();
189    $build['#attributes']['data-instance-id'][] = $preset->id();
190
191    return $build;
192  }
PresetLibraryPanel->buildPresets
116  private function buildPresets(string $builder_id, array $presets): array {
117    $build = [];
118    $grouped_presets = [];
119
120    foreach ($presets as $preset_id => $preset) {
120    foreach ($presets as $preset_id => $preset) {
120    foreach ($presets as $preset_id => $preset) {
120    foreach ($presets as $preset_id => $preset) {
121      $group_key = $this->getPresetGroup($preset);
122      $grouped_presets[$group_key][$preset_id] = $preset;
123    }
124
125    $formatted_groups = [];
126
127    foreach ($grouped_presets as $group_name => $presets_in_group) {
127    foreach ($grouped_presets as $group_name => $presets_in_group) {
127    foreach ($grouped_presets as $group_name => $presets_in_group) {
127    foreach ($grouped_presets as $group_name => $presets_in_group) {
128      $formatted_groups[$group_name] = [
129        'label' => $group_name,
130        'choices' => $presets_in_group,
131      ];
132    }
133
134    $is_single_group = \count($formatted_groups) === 1;
135
136    if (!$is_single_group) {
137      BlockLibrarySourceHelper::sortGroupedChoices($formatted_groups);
138    }
139
140    foreach ($formatted_groups as $group_data) {
140    foreach ($formatted_groups as $group_data) {
140    foreach ($formatted_groups as $group_data) {
141      if (!$is_single_group) {
143          '#type' => 'html_tag',
144          '#tag' => 'h4',
145          '#value' => $group_data['label'],
146          '#attributes' => [
147            'class' => ['db-filter-hide-on-search'],
148          ],
149        ];
150      }
151
152      foreach ($group_data['choices'] as $preset) {
152      foreach ($group_data['choices'] as $preset) {
152      foreach ($group_data['choices'] as $preset) {
152      foreach ($group_data['choices'] as $preset) {
153        $build[] = $this->buildPresetItem($builder_id, $preset, TRUE);
140    foreach ($formatted_groups as $group_data) {
141      if (!$is_single_group) {
142        $build[] = [
143          '#type' => 'html_tag',
144          '#tag' => 'h4',
145          '#value' => $group_data['label'],
146          '#attributes' => [
147            'class' => ['db-filter-hide-on-search'],
148          ],
149        ];
150      }
151
152      foreach ($group_data['choices'] as $preset) {
140    foreach ($formatted_groups as $group_data) {
141      if (!$is_single_group) {
142        $build[] = [
143          '#type' => 'html_tag',
144          '#tag' => 'h4',
145          '#value' => $group_data['label'],
146          '#attributes' => [
147            'class' => ['db-filter-hide-on-search'],
148          ],
149        ];
150      }
151
152      foreach ($group_data['choices'] as $preset) {
153        $build[] = $this->buildPresetItem($builder_id, $preset, TRUE);
154      }
155    }
156
157    $build = $this->buildDraggables($builder_id, $build);
158    $build['#source_contexts'] = $this->configuration['contexts'] ?? [];
159
160    return $build;
161  }
PresetLibraryPanel->create
37  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
38    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
39    $instance->presetConfigStorage = $container->get('entity_type.manager')->getStorage('pattern_preset');
40
41    return $instance;
42  }
PresetLibraryPanel->getPresetGroup
203  private function getPresetGroup(PatternPresetInterface $preset): string {
204    return $preset->getGroup() ? (string) $preset->getGroup() : (string) $this->t('Others');
204    return $preset->getGroup() ? (string) $preset->getGroup() : (string) $this->t('Others');
204    return $preset->getGroup() ? (string) $preset->getGroup() : (string) $this->t('Others');
204    return $preset->getGroup() ? (string) $preset->getGroup() : (string) $this->t('Others');
205  }
PresetLibraryPanel->onPresetSave
101  public function onPresetSave(InstanceInterface $instance): array {
102    return $this->reloadWithGlobalData($instance);
103  }