Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 217
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 56
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProfileForm
0.00% covered (danger)
0.00%
0 / 217
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 56
0.00% covered (danger)
0.00%
0 / 7
756
0.00% covered (danger)
0.00%
0 / 1
 form
0.00% covered (danger)
0.00%
0 / 86
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 submitForm
0.00% covered (danger)
0.00%
0 / 6
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
 save
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
42
 buildIslandTypeTable
0.00% covered (danger)
0.00%
0 / 29
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
 buildIslandRow
0.00% covered (danger)
0.00%
0 / 71
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
30
 copyFormValuesToEntity
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 moduleExtensionList
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
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Form;
6
7use Drupal\Component\Utility\Html;
8use Drupal\Component\Utility\NestedArray;
9use Drupal\Core\DependencyInjection\AutowireTrait;
10use Drupal\Core\Entity\EntityForm;
11use Drupal\Core\Entity\EntityInterface;
12use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
13use Drupal\Core\Extension\ModuleExtensionList;
14use Drupal\Core\Form\FormStateInterface;
15use Drupal\Core\Plugin\PluginFormInterface;
16use Drupal\display_builder\Entity\Profile;
17use Drupal\display_builder\IslandInterface;
18use Drupal\display_builder\IslandType;
19use Drupal\display_builder\ProfileInterface;
20use Drupal\user\RoleInterface;
21
22/**
23 * Display builder form.
24 */
25final class ProfileForm extends EntityForm {
26
27  use AutowireTrait;
28
29  /**
30   * Module extension list.
31   */
32  protected ModuleExtensionList $moduleExtensionList;
33
34  /**
35   * {@inheritdoc}
36   */
37  public function form(array $form, FormStateInterface $form_state): array {
38    $form = parent::form($form, $form_state);
39    /** @var \Drupal\display_builder\ProfileInterface $entity */
40    $entity = $this->entity;
41
42    $form['label'] = [
43      '#type' => 'textfield',
44      '#title' => $this->t('Label'),
45      '#maxlength' => 255,
46      '#default_value' => $entity->label(),
47      '#required' => TRUE,
48    ];
49
50    $form['id'] = [
51      '#type' => 'machine_name',
52      '#default_value' => $this->entity->id(),
53      '#machine_name' => [
54        'exists' => [Profile::class, 'load'],
55      ],
56      '#disabled' => !$entity->isNew(),
57    ];
58
59    $form['description'] = [
60      '#type' => 'textarea',
61      '#title' => $this->t('Description'),
62      '#default_value' => $entity->get('description'),
63    ];
64
65    // Add user role access selection. Not available at creation because the
66    // permissions are not set yet by ProfilePermissions.
67    if (!$entity->isNew()) {
68      $roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple();
69      \ksort($roles);
70      $form['roles'] = [
71        '#type' => 'checkboxes',
72        '#title' => $this->t('Roles'),
73        '#options' => \array_map(static fn (RoleInterface $role) => Html::escape((string) $role->label()), $roles),
74        '#default_value' => \array_keys($entity->getRoles()),
75      ];
76    }
77
78    // Inform on two time save for the island specific configurations.
79    if ($this->entity->isNew()) {
80      $form['islands_notice'] = [
81        '#prefix' => '<div class="messages messages--warning">',
82        '#markup' => $this->t('Island configuration will be available only after saving this form.'),
83        '#suffix' => '</div>',
84      ];
85    }
86
87    $path = $this->moduleExtensionList()->getPath('display_builder');
88    $form['islands_intro'] = [
89      [
90        '#type' => 'html_tag',
91        '#tag' => 'label',
92        '#value' => $this->t('Islands'),
93        '#attributes' => [
94          'class' => ['form-item__label'],
95        ],
96      ],
97      [
98        '#type' => 'html_tag',
99        '#tag' => 'img',
100        '#attributes' => [
101          'src' => base_path() . $path . '/assets/images/islands-regions.png',
102          'width' => '1200',
103        ],
104        '#prefix' => '<div style="text-align: center;">',
105        '#suffix' => '</div>',
106      ],
107    ];
108
109    $form['islands'] = [
110      '#type' => 'vertical_tabs',
111    ];
112
113    $island_configuration = $entity->get('islands') ?? [];
114
115    /** @var \Drupal\display_builder\IslandPluginManagerInterface $islandPluginManager */
116    $islandPluginManager = \Drupal::service('plugin.manager.db_island'); // phpcs:ignore
117    $island_by_types = $islandPluginManager->getIslandsByTypes();
118    $labels = [
119      'view' => $this->t('View panels'),
120      'button' => $this->t('Toolbar buttons'),
121      'contextual' => $this->t('Contextual panels'),
122      'library' => $this->t('Library panels'),
123      'menu' => $this->t('Menu items'),
124    ];
125    // Sort the types according to the labels.
126    $island_by_types = \array_merge($labels, $island_by_types);
127
128    foreach ($island_by_types as $type => $islands) {
129      $form['islands'][$type] = [
130        '#type' => 'details',
131        '#title' => $labels[$type] ?? $type,
132        '#description' => IslandType::description($type),
133        '#group' => 'islands',
134        'content' => $this->buildIslandTypeTable(IslandType::from($type), $islands, $island_configuration),
135      ];
136    }
137
138    $form['status'] = [
139      '#type' => 'checkbox',
140      '#title' => $this->t('Enabled'),
141      '#default_value' => $entity->status(),
142    ];
143
144    return $form;
145  }
146
147  /**
148   * {@inheritdoc}
149   */
150  public function submitForm(array &$form, FormStateInterface $form_state): ProfileInterface {
151    parent::submitForm($form, $form_state);
152
153    // Save user permissions.
154    /** @var \Drupal\display_builder\ProfileInterface $entity */
155    $entity = $this->entity;
156
157    if ($permission = $entity->getPermissionName()) {
158      foreach ($form_state->getValue('roles') ?? [] as $rid => $enabled) {
159        user_role_change_permissions($rid, [$permission => $enabled]);
160      }
161    }
162
163    return $entity;
164  }
165
166  /**
167   * {@inheritdoc}
168   */
169  public function save(array $form, FormStateInterface $form_state): int {
170    $result = parent::save($form, $form_state);
171
172    // Clear the plugin cache so changes are applied on front theme builder.
173    /** @var \Drupal\Core\Plugin\CachedDiscoveryClearerInterface $pluginCacheClearer */
174    $pluginCacheClearer = \Drupal::service('plugin.cache_clearer'); // phpcs:ignore
175    $pluginCacheClearer->clearCachedDefinitions();
176
177    $message_args = ['%label' => $this->entity->label()];
178    $this->messenger()->addStatus(
179      match ($result) {
180        SAVED_NEW => $this->t('Created new display builder config %label.', $message_args),
181        SAVED_UPDATED => $this->t('Updated display builder config %label.', $message_args),
182        default => '',
183      }
184    );
185
186    // Set the initial default configuration and stay on the form to allow
187    // islands configuration.
188    if ($result === SAVED_NEW) {
189      $form_state->setRedirect('entity.display_builder_profile.edit_form', ['display_builder_profile' => $this->entity->id()]);
190    }
191    elseif ($result === SAVED_UPDATED) {
192      $form_state->setRedirect('entity.display_builder_profile.collection');
193    }
194
195    return $result;
196  }
197
198  /**
199   * Build island type table.
200   *
201   * @param \Drupal\display_builder\IslandType $type
202   *   Island type from IslandType enum.
203   * @param array $islands
204   *   List of island plugins.
205   * @param array $configuration
206   *   Configuration of all islands from this type.
207   *
208   * @return array
209   *   A renderable array.
210   */
211  protected function buildIslandTypeTable(IslandType $type, array $islands, array $configuration): array {
212    $type = $type->value;
213    $table = [
214      '#type' => 'table',
215      '#header' => [
216        'drag' => '',
217        'status' => $this->t('Enabled'),
218        'name' => $this->t('Island'),
219        'summary' => $this->t('Configuration'),
220        'region' => empty(IslandType::regions($type)) ? '' : $this->t('Region'),
221        'actions' => $this->t('Actions'),
222        'weight' => $this->t('Weight'),
223      ],
224      '#attributes' => ['id' => 'db-islands-' . $type],
225      '#tabledrag' => [
226        [
227          'action' => 'order',
228          'relationship' => 'sibling',
229          'group' => 'draggable-weight-' . $type,
230        ],
231      ],
232      // We don't want to submit the island type level. We already know the
233      // type of each islands thanks to IslandInterface::getTypeId() so let's
234      // keep the storage flat.
235      '#parents' => ['islands'],
236    ];
237
238    foreach ($islands as $id => $island) {
239      $table[$id] = $this->buildIslandRow($island, $configuration[$id] ?? []);
240    }
241
242    // Order rows by weight.
243    \uasort($table, static function ($a, $b) {
244      if (isset($a['#weight'], $b['#weight'])) {
245        return (int) $a['#weight'] - (int) $b['#weight'];
246      }
247    });
248
249    return $table;
250  }
251
252  /**
253   * Build island row.
254   *
255   * @param \Drupal\display_builder\IslandInterface $island
256   *   Island plugin.
257   * @param array $configuration
258   *   Configuration of this specific island.
259   *
260   * @return array
261   *   A renderable array.
262   */
263  protected function buildIslandRow(IslandInterface $island, array $configuration): array {
264    $id = $island->getPluginId();
265    $definition = (array) $island->getPluginDefinition();
266    $type = $island->getTypeId();
267    /** @var \Drupal\display_builder\IslandPluginManagerInterface $islandPluginManager */
268    $islandPluginManager = \Drupal::service('plugin.manager.db_island'); // phpcs:ignore
269    /** @var \Drupal\display_builder\IslandConfigurationFormInterface $instance */
270    $instance = $islandPluginManager->createInstance($id, $configuration);
271    $weight = isset($configuration['weight']) ? (string) $configuration['weight'] : '0';
272
273    $row = [];
274    $row['#attributes']['class'] = ['draggable'];
275    $row['#weight'] = (int) $weight;
276
277    $row[''] = [];
278    $row['status'] = [
279      '#type' => 'checkbox',
280      '#title' => $this->t('Enabled'),
281      '#title_display' => 'invisible',
282      '#default_value' => $configuration['status'] ?? $definition['enabled_by_default'] ?? FALSE,
283    ];
284    $row['name'] = [
285      '#type' => 'inline_template',
286      '#template' => '<strong >{{ name }}</strong><br>{{ description }}',
287      '#context' => [
288        'name' => $definition['label'] ?? '',
289        'description' => $definition['description'] ?? '',
290      ],
291    ];
292    $row['summary'] = [
293      '#markup' => \implode('<br>', $instance->configurationSummary()),
294    ];
295
296    $regions = IslandType::regions($type);
297
298    if (!empty($regions)) {
299      $row['region'] = [
300        '#type' => 'radios',
301        '#title' => $this->t('Region'),
302        '#title_display' => 'invisible',
303        '#options' => $regions,
304        '#default_value' => $configuration['region'] ?? $definition['default_region'] ?? NULL,
305      ];
306    }
307    else {
308      $row['region'] = [];
309    }
310
311    if ($island instanceof PluginFormInterface && !$this->entity->isNew()) {
312      $row['actions'] = [
313        '#type' => 'link',
314        '#title' => $this->t('Configure'),
315        '#url' => $this->entity->toUrl('edit-plugin-form', [
316          'island_id' => $id,
317          'query' => [
318            'destination' => $this->entity->toUrl()->toString(),
319          ],
320        ]),
321        '#attributes' => [
322          'class' => ['use-ajax', 'button', 'button--small'],
323          'data-dialog-type' => 'modal',
324          'data-dialog-options' => \json_encode([
325            'width' => 700,
326          ]),
327        ],
328        '#states' => [
329          'visible' => [
330            'input[name="islands[' . $id . '][status]"]' => ['checked' => TRUE],
331          ],
332        ],
333      ];
334    }
335    else {
336      $row['actions'] = ['#markup' => ''];
337    }
338
339    $row['weight'] = [
340      '#type' => 'weight',
341      '#default_value' => $weight,
342      '#title' => $this->t('Weight'),
343      '#title_display' => 'invisible',
344      '#attributes' => [
345        'class' => ['draggable-weight-' . $type],
346      ],
347    ];
348
349    return $row;
350  }
351
352  /**
353   * {@inheritdoc}
354   */
355  protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state): void {
356    $values = $form_state->getValues();
357
358    /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
359    $entity = $entity;
360
361    if ($this->entity instanceof EntityWithPluginCollectionInterface) {
362      // Do not manually update values represented by plugin collections.
363      $values = \array_diff_key($values, $this->entity->getPluginCollections());
364    }
365
366    foreach ($values as $key => $value) {
367      if ($key === 'islands') {
368        $value = NestedArray::mergeDeep($entity->get('islands'), $value);
369      }
370      $entity->set($key, $value);
371    }
372  }
373
374  /**
375   * Wraps the module extension list service repository service.
376   *
377   * @return \Drupal\Core\Extension\ModuleExtensionList
378   *   The module extension list service.
379   */
380  protected function moduleExtensionList(): ModuleExtensionList {
381    return $this->moduleExtensionList ??= \Drupal::service('extension.list.module'); // phpcs:ignore
382  }
383
384}

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.

ProfileForm->buildIslandRow
263  protected function buildIslandRow(IslandInterface $island, array $configuration): array {
264    $id = $island->getPluginId();
265    $definition = (array) $island->getPluginDefinition();
266    $type = $island->getTypeId();
267    /** @var \Drupal\display_builder\IslandPluginManagerInterface $islandPluginManager */
268    $islandPluginManager = \Drupal::service('plugin.manager.db_island'); // phpcs:ignore
269    /** @var \Drupal\display_builder\IslandConfigurationFormInterface $instance */
270    $instance = $islandPluginManager->createInstance($id, $configuration);
271    $weight = isset($configuration['weight']) ? (string) $configuration['weight'] : '0';
271    $weight = isset($configuration['weight']) ? (string) $configuration['weight'] : '0';
271    $weight = isset($configuration['weight']) ? (string) $configuration['weight'] : '0';
271    $weight = isset($configuration['weight']) ? (string) $configuration['weight'] : '0';
272
273    $row = [];
274    $row['#attributes']['class'] = ['draggable'];
275    $row['#weight'] = (int) $weight;
276
277    $row[''] = [];
278    $row['status'] = [
279      '#type' => 'checkbox',
280      '#title' => $this->t('Enabled'),
281      '#title_display' => 'invisible',
282      '#default_value' => $configuration['status'] ?? $definition['enabled_by_default'] ?? FALSE,
283    ];
284    $row['name'] = [
285      '#type' => 'inline_template',
286      '#template' => '<strong >{{ name }}</strong><br>{{ description }}',
287      '#context' => [
288        'name' => $definition['label'] ?? '',
289        'description' => $definition['description'] ?? '',
290      ],
291    ];
292    $row['summary'] = [
293      '#markup' => \implode('<br>', $instance->configurationSummary()),
294    ];
295
296    $regions = IslandType::regions($type);
297
298    if (!empty($regions)) {
298    if (!empty($regions)) {
299      $row['region'] = [
300        '#type' => 'radios',
308      $row['region'] = [];
309    }
310
311    if ($island instanceof PluginFormInterface && !$this->entity->isNew()) {
311    if ($island instanceof PluginFormInterface && !$this->entity->isNew()) {
311    if ($island instanceof PluginFormInterface && !$this->entity->isNew()) {
311    if ($island instanceof PluginFormInterface && !$this->entity->isNew()) {
311    if ($island instanceof PluginFormInterface && !$this->entity->isNew()) {
312      $row['actions'] = [
313        '#type' => 'link',
336      $row['actions'] = ['#markup' => ''];
337    }
338
339    $row['weight'] = [
340      '#type' => 'weight',
340      '#type' => 'weight',
341      '#default_value' => $weight,
342      '#title' => $this->t('Weight'),
343      '#title_display' => 'invisible',
344      '#attributes' => [
345        'class' => ['draggable-weight-' . $type],
346      ],
347    ];
348
349    return $row;
350  }
ProfileForm->buildIslandTypeTable
211  protected function buildIslandTypeTable(IslandType $type, array $islands, array $configuration): array {
212    $type = $type->value;
213    $table = [
214      '#type' => 'table',
215      '#header' => [
216        'drag' => '',
217        'status' => $this->t('Enabled'),
218        'name' => $this->t('Island'),
219        'summary' => $this->t('Configuration'),
220        'region' => empty(IslandType::regions($type)) ? '' : $this->t('Region'),
220        'region' => empty(IslandType::regions($type)) ? '' : $this->t('Region'),
220        'region' => empty(IslandType::regions($type)) ? '' : $this->t('Region'),
220        'region' => empty(IslandType::regions($type)) ? '' : $this->t('Region'),
221        'actions' => $this->t('Actions'),
222        'weight' => $this->t('Weight'),
223      ],
224      '#attributes' => ['id' => 'db-islands-' . $type],
225      '#tabledrag' => [
226        [
227          'action' => 'order',
228          'relationship' => 'sibling',
229          'group' => 'draggable-weight-' . $type,
230        ],
231      ],
232      // We don't want to submit the island type level. We already know the
233      // type of each islands thanks to IslandInterface::getTypeId() so let's
234      // keep the storage flat.
235      '#parents' => ['islands'],
236    ];
237
238    foreach ($islands as $id => $island) {
238    foreach ($islands as $id => $island) {
238    foreach ($islands as $id => $island) {
238    foreach ($islands as $id => $island) {
239      $table[$id] = $this->buildIslandRow($island, $configuration[$id] ?? []);
240    }
241
242    // Order rows by weight.
243    \uasort($table, static function ($a, $b) {
244      if (isset($a['#weight'], $b['#weight'])) {
245        return (int) $a['#weight'] - (int) $b['#weight'];
246      }
247    });
248
249    return $table;
250  }
ProfileForm->copyFormValuesToEntity
355  protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state): void {
356    $values = $form_state->getValues();
357
358    /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
359    $entity = $entity;
360
361    if ($this->entity instanceof EntityWithPluginCollectionInterface) {
363      $values = \array_diff_key($values, $this->entity->getPluginCollections());
364    }
365
366    foreach ($values as $key => $value) {
366    foreach ($values as $key => $value) {
366    foreach ($values as $key => $value) {
366    foreach ($values as $key => $value) {
367      if ($key === 'islands') {
368        $value = NestedArray::mergeDeep($entity->get('islands'), $value);
369      }
370      $entity->set($key, $value);
366    foreach ($values as $key => $value) {
367      if ($key === 'islands') {
368        $value = NestedArray::mergeDeep($entity->get('islands'), $value);
369      }
370      $entity->set($key, $value);
366    foreach ($values as $key => $value) {
367      if ($key === 'islands') {
368        $value = NestedArray::mergeDeep($entity->get('islands'), $value);
369      }
370      $entity->set($key, $value);
371    }
372  }
ProfileForm->form
37  public function form(array $form, FormStateInterface $form_state): array {
38    $form = parent::form($form, $form_state);
39    /** @var \Drupal\display_builder\ProfileInterface $entity */
40    $entity = $this->entity;
41
42    $form['label'] = [
43      '#type' => 'textfield',
44      '#title' => $this->t('Label'),
45      '#maxlength' => 255,
46      '#default_value' => $entity->label(),
47      '#required' => TRUE,
48    ];
49
50    $form['id'] = [
51      '#type' => 'machine_name',
52      '#default_value' => $this->entity->id(),
53      '#machine_name' => [
54        'exists' => [Profile::class, 'load'],
55      ],
56      '#disabled' => !$entity->isNew(),
57    ];
58
59    $form['description'] = [
60      '#type' => 'textarea',
61      '#title' => $this->t('Description'),
62      '#default_value' => $entity->get('description'),
63    ];
64
65    // Add user role access selection. Not available at creation because the
66    // permissions are not set yet by ProfilePermissions.
67    if (!$entity->isNew()) {
68      $roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple();
69      \ksort($roles);
70      $form['roles'] = [
71        '#type' => 'checkboxes',
72        '#title' => $this->t('Roles'),
73        '#options' => \array_map(static fn (RoleInterface $role) => Html::escape((string) $role->label()), $roles),
74        '#default_value' => \array_keys($entity->getRoles()),
75      ];
76    }
77
78    // Inform on two time save for the island specific configurations.
79    if ($this->entity->isNew()) {
79    if ($this->entity->isNew()) {
81        '#prefix' => '<div class="messages messages--warning">',
82        '#markup' => $this->t('Island configuration will be available only after saving this form.'),
83        '#suffix' => '</div>',
84      ];
85    }
86
87    $path = $this->moduleExtensionList()->getPath('display_builder');
87    $path = $this->moduleExtensionList()->getPath('display_builder');
88    $form['islands_intro'] = [
89      [
90        '#type' => 'html_tag',
91        '#tag' => 'label',
92        '#value' => $this->t('Islands'),
93        '#attributes' => [
94          'class' => ['form-item__label'],
95        ],
96      ],
97      [
98        '#type' => 'html_tag',
99        '#tag' => 'img',
100        '#attributes' => [
101          'src' => base_path() . $path . '/assets/images/islands-regions.png',
102          'width' => '1200',
103        ],
104        '#prefix' => '<div style="text-align: center;">',
105        '#suffix' => '</div>',
106      ],
107    ];
108
109    $form['islands'] = [
110      '#type' => 'vertical_tabs',
111    ];
112
113    $island_configuration = $entity->get('islands') ?? [];
114
115    /** @var \Drupal\display_builder\IslandPluginManagerInterface $islandPluginManager */
116    $islandPluginManager = \Drupal::service('plugin.manager.db_island'); // phpcs:ignore
117    $island_by_types = $islandPluginManager->getIslandsByTypes();
118    $labels = [
119      'view' => $this->t('View panels'),
120      'button' => $this->t('Toolbar buttons'),
121      'contextual' => $this->t('Contextual panels'),
122      'library' => $this->t('Library panels'),
123      'menu' => $this->t('Menu items'),
124    ];
125    // Sort the types according to the labels.
126    $island_by_types = \array_merge($labels, $island_by_types);
127
128    foreach ($island_by_types as $type => $islands) {
128    foreach ($island_by_types as $type => $islands) {
128    foreach ($island_by_types as $type => $islands) {
128    foreach ($island_by_types as $type => $islands) {
129      $form['islands'][$type] = [
130        '#type' => 'details',
131        '#title' => $labels[$type] ?? $type,
132        '#description' => IslandType::description($type),
133        '#group' => 'islands',
134        'content' => $this->buildIslandTypeTable(IslandType::from($type), $islands, $island_configuration),
135      ];
136    }
137
138    $form['status'] = [
139      '#type' => 'checkbox',
140      '#title' => $this->t('Enabled'),
141      '#default_value' => $entity->status(),
142    ];
143
144    return $form;
145  }
ProfileForm->moduleExtensionList
381    return $this->moduleExtensionList ??= \Drupal::service('extension.list.module'); // phpcs:ignore
382  }
ProfileForm->save
169  public function save(array $form, FormStateInterface $form_state): int {
170    $result = parent::save($form, $form_state);
171
172    // Clear the plugin cache so changes are applied on front theme builder.
173    /** @var \Drupal\Core\Plugin\CachedDiscoveryClearerInterface $pluginCacheClearer */
174    $pluginCacheClearer = \Drupal::service('plugin.cache_clearer'); // phpcs:ignore
175    $pluginCacheClearer->clearCachedDefinitions();
176
177    $message_args = ['%label' => $this->entity->label()];
178    $this->messenger()->addStatus(
179      match ($result) {
180        SAVED_NEW => $this->t('Created new display builder config %label.', $message_args),
181        SAVED_UPDATED => $this->t('Updated display builder config %label.', $message_args),
181        SAVED_UPDATED => $this->t('Updated display builder config %label.', $message_args),
180        SAVED_NEW => $this->t('Created new display builder config %label.', $message_args),
181        SAVED_UPDATED => $this->t('Updated display builder config %label.', $message_args),
182        default => '',
182        default => '',
183      }
184    );
185
186    // Set the initial default configuration and stay on the form to allow
187    // islands configuration.
188    if ($result === SAVED_NEW) {
188    if ($result === SAVED_NEW) {
189      $form_state->setRedirect('entity.display_builder_profile.edit_form', ['display_builder_profile' => $this->entity->id()]);
191    elseif ($result === SAVED_UPDATED) {
192      $form_state->setRedirect('entity.display_builder_profile.collection');
193    }
194
195    return $result;
195    return $result;
196  }
ProfileForm->submitForm
150  public function submitForm(array &$form, FormStateInterface $form_state): ProfileInterface {
151    parent::submitForm($form, $form_state);
152
153    // Save user permissions.
154    /** @var \Drupal\display_builder\ProfileInterface $entity */
155    $entity = $this->entity;
156
157    if ($permission = $entity->getPermissionName()) {
158      foreach ($form_state->getValue('roles') ?? [] as $rid => $enabled) {
158      foreach ($form_state->getValue('roles') ?? [] as $rid => $enabled) {
158      foreach ($form_state->getValue('roles') ?? [] as $rid => $enabled) {
158      foreach ($form_state->getValue('roles') ?? [] as $rid => $enabled) {
159        user_role_change_permissions($rid, [$permission => $enabled]);
160      }
161    }
162
163    return $entity;
163    return $entity;
164  }
{closure:/var/www/html/web/modules/custom/display_builder/src/Form/ProfileForm.php:243-247}
243    \uasort($table, static function ($a, $b) {
244      if (isset($a['#weight'], $b['#weight'])) {
244      if (isset($a['#weight'], $b['#weight'])) {
244      if (isset($a['#weight'], $b['#weight'])) {
245        return (int) $a['#weight'] - (int) $b['#weight'];
247    });
{closure:/var/www/html/web/modules/custom/display_builder/src/Form/ProfileForm.php:73-73}
73        '#options' => \array_map(static fn (RoleInterface $role) => Html::escape((string) $role->label()), $roles),