Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProfileIslandPluginForm
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 9
272
0.00% covered (danger)
0.00%
0 / 1
 __construct
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
 editFormTitle
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
 getEntityFromRouteMatch
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
 validateForm
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
 form
0.00% covered (danger)
0.00%
0 / 11
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
 save
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
20
 actions
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
 copyFormValuesToEntity
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
 getIslandPlugin
0.00% covered (danger)
0.00%
0 / 6
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\Form;
6
7use Drupal\Core\DependencyInjection\AutowireTrait;
8use Drupal\Core\Entity\EntityForm;
9use Drupal\Core\Entity\EntityInterface;
10use Drupal\Core\Form\FormStateInterface;
11use Drupal\Core\Form\SubformState;
12use Drupal\Core\Plugin\CachedDiscoveryClearerInterface;
13use Drupal\Core\Plugin\PluginFormInterface;
14use Drupal\Core\Routing\RouteMatchInterface;
15use Drupal\display_builder\Entity\Profile;
16use Drupal\display_builder\Island\IslandInterface;
17use Drupal\display_builder\Island\IslandPluginManagerInterface;
18use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
19
20/**
21 * Display builder plugin form.
22 */
23final class ProfileIslandPluginForm extends EntityForm {
24
25  use AutowireTrait;
26
27  /**
28   * The route parameter for the island plugin.
29   */
30  protected string $islandId;
31
32  /**
33   * The island plugin.
34   */
35  private ?IslandInterface $island = NULL;
36
37  public function __construct(
38    protected IslandPluginManagerInterface $islandPluginManager,
39    private readonly CachedDiscoveryClearerInterface $pluginCacheClearer,
40  ) {}
41
42  /**
43   * Returns the title of the edit plugin form.
44   *
45   * Used as a static route title callback by the routing system, which
46   * does not instantiate the form class. \Drupal::service() is the
47   * correct pattern here.
48   *
49   * @param string $island_id
50   *   The island ID.
51   *
52   * @return string
53   *   The title of the edit plugin form.
54   */
55  public static function editFormTitle(string $island_id): string {
56    // phpcs:ignore Drupal.Classes.FullyQualifiedNamespace -- static route callback, DI unavailable.
57    /** @var \Drupal\display_builder\Island\IslandPluginManagerInterface $manager */
58    $manager = \Drupal::service('plugin.manager.db_island');
59    $island = $manager->createInstance($island_id, []);
60
61    return (string) $island->label();
62  }
63
64  /**
65   * {@inheritdoc}
66   */
67  public function getEntityFromRouteMatch(RouteMatchInterface $route_match, $entity_type_id): EntityInterface {
68    $this->islandId = $route_match->getParameter('island_id');
69
70    return parent::getEntityFromRouteMatch($route_match, $entity_type_id);
71  }
72
73  /**
74   * {@inheritdoc}
75   */
76  public function validateForm(array &$form, FormStateInterface $form_state): void {
77    parent::validateForm($form, $form_state);
78    $island = $this->getIslandPlugin();
79
80    if ($island instanceof PluginFormInterface) {
81      $subform_state = SubformState::createForSubform($form['configuration'], $form, $form_state);
82      $island->validateConfigurationForm($form['configuration'], $subform_state);
83    }
84  }
85
86  /**
87   * {@inheritdoc}
88   */
89  public function form(array $form, FormStateInterface $form_state): array {
90    $form = parent::form($form, $form_state);
91    $island = $this->getIslandPlugin();
92
93    if (!($island instanceof PluginFormInterface)) {
94      throw new AccessDeniedHttpException('The island plugin does not support configuration.');
95    }
96    $form['configuration'] = [
97      '#type' => 'container',
98      '#tree' => TRUE,
99    ];
100    $subform_state = SubformState::createForSubform($form['configuration'], $form, $form_state);
101    $form['configuration'] = $island->buildConfigurationForm($form['configuration'], $subform_state);
102
103    return $form;
104  }
105
106  /**
107   * {@inheritdoc}
108   */
109  public function save(array $form, FormStateInterface $form_state): int {
110    $result = parent::save($form, $form_state);
111
112    // Clear the plugin cache so changes are applied on front theme builder.
113    $this->pluginCacheClearer->clearCachedDefinitions();
114
115    $message_args = ['%label' => $this->entity->label()];
116    $this->messenger()->addStatus(
117      match ($result) {
118        SAVED_NEW => $this->t('Created new display builder config %label.', $message_args),
119        SAVED_UPDATED => $this->t('Updated display builder config %label.', $message_args),
120        default => '',
121      }
122    );
123
124    return $result;
125  }
126
127  /**
128   * {@inheritdoc}
129   */
130  protected function actions(array $form, FormStateInterface $form_state): array {
131    $actions = parent::actions($form, $form_state);
132    unset($actions['delete']);
133
134    return $actions;
135  }
136
137  /**
138   * {@inheritdoc}
139   */
140  protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state): void {
141    \assert($entity instanceof Profile);
142    parent::copyFormValuesToEntity($entity, $form, $form_state);
143    $island = $this->getIslandPlugin();
144
145    if ($island instanceof PluginFormInterface) {
146      $subform_state = SubformState::createForSubform($form['configuration'], $form, $form_state);
147      $island->submitConfigurationForm($form['configuration'], $subform_state);
148      $entity->setIslandConfiguration($this->islandId, $island->getConfiguration());
149    }
150  }
151
152  /**
153   * Retrieves the configured island plugin.
154   */
155  private function getIslandPlugin(): IslandInterface {
156    if ($this->island !== NULL) {
157      return $this->island;
158    }
159    /** @var \Drupal\display_builder\Entity\Profile $entity */
160    $entity = $this->entity;
161    $island_configuration = $entity->getIslandConfiguration($this->islandId);
162    $this->island = $this->islandPluginManager->createInstance($this->islandId, $island_configuration);
163
164    return $this->island;
165  }
166
167}