Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
80.65% covered (warning)
80.65%
25 / 31
78.57% covered (warning)
78.57%
22 / 28
32.00% covered (danger)
32.00%
8 / 25
45.45% covered (danger)
45.45%
5 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Profile
80.65% covered (warning)
80.65%
25 / 31
78.57% covered (warning)
78.57%
22 / 28
32.00% covered (danger)
32.00%
8 / 25
45.45% covered (danger)
45.45%
5 / 11
132.51
0.00% covered (danger)
0.00%
0 / 1
 getIslandConfiguration
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIslandConfigurations
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setIslandConfiguration
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
3 / 3
50.00% covered (danger)
50.00%
1 / 2
100.00% covered (success)
100.00%
1 / 1
2.50
 getEnabledIslands
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
8 / 8
33.33% covered (danger)
33.33%
2 / 6
100.00% covered (success)
100.00%
1 / 1
8.74
 getPermissionName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRoles
80.00% covered (warning)
80.00%
4 / 5
66.67% covered (warning)
66.67%
2 / 3
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 isLibraryFlat
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
 getLibraryTabsDisplay
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
 getContextualTabsDisplay
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
 getViewPanelsDisplay
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
 toUrl
88.89% covered (warning)
88.89%
8 / 9
85.71% covered (warning)
85.71%
6 / 7
12.50% covered (danger)
12.50%
1 / 8
0.00% covered (danger)
0.00%
0 / 1
14.72
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Entity;
6
7use Drupal\Core\Config\Entity\ConfigEntityBase;
8use Drupal\Core\Entity\Attribute\ConfigEntityType;
9use Drupal\Core\Entity\EntityDeleteForm;
10use Drupal\Core\StringTranslation\TranslatableMarkup;
11use Drupal\Core\Url;
12use Drupal\display_builder\Form\ProfileForm;
13use Drupal\display_builder\Form\ProfileIslandPluginForm;
14use Drupal\display_builder\ProfileAccessControlHandler;
15use Drupal\display_builder\ProfileViewBuilder;
16use Drupal\display_builder_ui\ProfileListBuilder;
17use Drupal\user\Entity\Role;
18use Drupal\user\RoleInterface;
19
20/**
21 * Defines the display builder entity type.
22 */
23#[ConfigEntityType(
24  id: 'display_builder_profile',
25  label: new TranslatableMarkup('Display builder profile'),
26  label_collection: new TranslatableMarkup('Display builder profiles'),
27  label_singular: new TranslatableMarkup('display builder profile'),
28  label_plural: new TranslatableMarkup('display builders profiles'),
29  entity_keys: [
30    'id' => 'id',
31    'label' => 'label',
32    'description' => 'description',
33    'weight' => 'weight',
34  ],
35  handlers: [
36    'access' => ProfileAccessControlHandler::class,
37    'route_provider' => [
38      'html' => 'Drupal\display_builder\Routing\ProfileRouteProvider',
39    ],
40    'view_builder' => ProfileViewBuilder::class,
41    'list_builder' => ProfileListBuilder::class,
42    'form' => [
43      'add' => ProfileForm::class,
44      'edit' => ProfileForm::class,
45      'delete' => EntityDeleteForm::class,
46      'edit-plugin' => ProfileIslandPluginForm::class,
47    ],
48  ],
49  links: [
50    'add-form' => '/admin/structure/display-builder/add',
51    'edit-form' => '/admin/structure/display-builder/{display_builder_profile}',
52    'edit-plugin-form' => '/admin/structure/display-builder/{display_builder_profile}/edit/{island_id}',
53    'delete-form' => '/admin/structure/display-builder/{display_builder_profile}/delete',
54    'collection' => '/admin/structure/display-builder',
55  ],
56  admin_permission: 'administer display builder profile',
57  constraints: [
58    'ImmutableProperties' => [
59      'id',
60    ],
61  ],
62  // Example: display_builder.profile.default.yml.
63  config_prefix: 'profile',
64  config_export: [
65    'id',
66    'label',
67    'description',
68    'islands',
69    'library_flat',
70    'library_tabs_display',
71    'contextual_tabs_display',
72    'view_panels_display',
73    'weight',
74  ],
75)]
76final class Profile extends ConfigEntityBase implements ProfileInterface {
77
78  /**
79   * The display builder config ID.
80   */
81  protected string $id;
82
83  /**
84   * The display builder label.
85   */
86  protected string $label;
87
88  /**
89   * The display builder description.
90   */
91  protected string $description;
92
93  /**
94   * The islands configuration for storage.
95   */
96  protected ?array $islands = [];
97
98  /**
99   * Weight to order the entity in lists.
100   *
101   * @var int
102   */
103  protected $weight = 0;
104
105  /**
106   * Whether library panels are merged into a single flat list.
107   */
108  protected bool $library_flat = FALSE;
109
110  /**
111   * How library tabs (Components, Blocks, Presets...) are displayed.
112   */
113  protected string $library_tabs_display = 'label';
114
115  /**
116   * How contextual panel tabs are displayed.
117   */
118  protected string $contextual_tabs_display = 'icon';
119
120  /**
121   * How View panels (main area tabs, sidebar buttons) are displayed.
122   */
123  protected string $view_panels_display = 'icon_label';
124
125  /**
126   * {@inheritdoc}
127   */
128  public function getIslandConfiguration(string $island_id): array {
129    return $this->islands[$island_id] ?? [];
130  }
131
132  /**
133   * {@inheritdoc}
134   */
135  public function getIslandConfigurations(): array {
136    return $this->islands ?? [];
137  }
138
139  /**
140   * {@inheritdoc}
141   */
142  public function setIslandConfiguration(string $island_id, array $configuration = []): void {
143    // When $configuration is updated from ProfileIslandPluginForm,
144    // 'weight', 'status' and 'region' properties are missing but they must not
145    // be reset.
146    $configuration['weight'] ??= $this->islands[$island_id]['weight'] ?? 0;
147    $configuration['status'] ??= $this->islands[$island_id]['status'] ?? FALSE;
148
149    // Only View islands have regions.
150    if (isset($this->islands[$island_id]['region'])) {
151      $configuration['region'] ??= $this->islands[$island_id]['region'];
152    }
153
154    $this->islands[$island_id] = $configuration;
155  }
156
157  /**
158   * {@inheritdoc}
159   */
160  public function getEnabledIslands(): array {
161    $island_enabled = [];
162
163    foreach ($this->islands as $island_id => $configuration) {
164      if (isset($configuration['status']) && $configuration['status']) {
165        $island_enabled[$island_id] = $configuration['weight'] ?? 0;
166      }
167    }
168
169    return $island_enabled;
170  }
171
172  /**
173   * {@inheritdoc}
174   */
175  public function getPermissionName(): string {
176    return 'use display builder ' . $this->id();
177  }
178
179  /**
180   * {@inheritdoc}
181   */
182  public function getRoles(): array {
183    // Do not list any roles if the permission does not exist.
184    $permission = $this->getPermissionName();
185
186    if (empty($permission)) {
187      return [];
188    }
189
190    $roles = \array_filter(Role::loadMultiple(), static fn (RoleInterface $role) => $role->hasPermission($permission));
191
192    return \array_map(static fn (RoleInterface $role) => $role->label(), $roles);
193  }
194
195  /**
196   * {@inheritdoc}
197   */
198  public function isLibraryFlat(): bool {
199    return $this->library_flat;
200  }
201
202  /**
203   * {@inheritdoc}
204   */
205  public function getLibraryTabsDisplay(): string {
206    return $this->library_tabs_display;
207  }
208
209  /**
210   * {@inheritdoc}
211   */
212  public function getContextualTabsDisplay(): string {
213    return $this->contextual_tabs_display;
214  }
215
216  /**
217   * {@inheritdoc}
218   */
219  public function getViewPanelsDisplay(): string {
220    return $this->view_panels_display;
221  }
222
223  /**
224   * {@inheritdoc}
225   */
226  public function toUrl($rel = NULL, array $options = []): Url {
227    if ($rel === 'edit-plugin-form' && $this->id() && isset($options['island_id'])) {
228      $island_id = $options['island_id'];
229      unset($options['island_id']);
230
231      return Url::fromRoute(
232        'entity.display_builder_profile.edit_plugin_form',
233        ['display_builder_profile' => $this->id(), 'island_id' => $island_id],
234        $options
235      );
236    }
237
238    return parent::toUrl($rel, $options);
239  }
240
241}