Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 56
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
DesignTokensPanel
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 11
462
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
 label
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
 buildForm
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
42
 validateForm
0.00% covered (danger)
0.00%
0 / 5
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
 alterElement
0.00% covered (danger)
0.00%
0 / 6
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
 onAttachToRoot
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
 onAttachToSlot
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
 onActive
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
 onDelete
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
 isApplicable
0.00% covered (danger)
0.00%
0 / 2
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
 filterValues
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Plugin\display_builder\Island;
6
7use Drupal\Core\Form\FormStateInterface;
8use Drupal\Core\StringTranslation\TranslatableMarkup;
9use Drupal\display_builder\Attribute\Island;
10use Drupal\display_builder\IslandPluginBase;
11use Drupal\display_builder\IslandType;
12use Drupal\display_builder\IslandWithFormInterface;
13use Drupal\display_builder\IslandWithFormTrait;
14use Drupal\display_builder\RenderableAltererInterface;
15use Drupal\ui_skins\CssVariable\CssVariablePluginManagerInterface;
16use Drupal\ui_skins\UiSkinsUtility;
17use Symfony\Component\DependencyInjection\ContainerInterface;
18
19/**
20 * Skins island plugin implementation.
21 *
22 * @todo must move to UI Styles module.
23 */
24#[Island(
25  id: 'tokens',
26  label: new TranslatableMarkup('Design tokens (CSS variables)'),
27  description: new TranslatableMarkup('Override CSS variables for the active component or block.'),
28  type: IslandType::Contextual,
29  modules: ['ui_skins'],
30)]
31class DesignTokensPanel extends IslandPluginBase implements IslandWithFormInterface, RenderableAltererInterface {
32
33  use IslandWithFormTrait;
34
35  /**
36   * The UI Skins CSS variables manager.
37   */
38  protected CssVariablePluginManagerInterface $cssVariablePluginManager;
39
40  /**
41   * {@inheritdoc}
42   */
43  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
44    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
45    $instance->cssVariablePluginManager = $container->get('plugin.manager.ui_skins.css_variable');
46
47    return $instance;
48  }
49
50  /**
51   * {@inheritdoc}
52   */
53  public function label(): string {
54    return 'Tokens';
55  }
56
57  /**
58   * {@inheritdoc}
59   */
60  public function buildForm(array &$form, FormStateInterface $form_state): void {
61    $data = $form_state->getBuildInfo()['args'][0];
62    $instance = $data['instance'] ?? [];
63    $grouped_plugin_definitions = $this->cssVariablePluginManager->getGroupedDefinitions();
64
65    if (empty($grouped_plugin_definitions)) {
66      return;
67    }
68
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
70      $variables = [];
71
72      foreach ($definitions as $definition_id => $definition) {
73        $default = $definition->getDefaultValues();
74
75        if (!isset($default[':root'])) {
76          continue;
77        }
78        $variables[$definition_id] = [
79          '#type' => $definition->getType(),
80          '#title' => $definition->getLabel(),
81          '#default_value' => $instance[$definition_id] ?? $default[':root'] ?? '',
82        ];
83      }
84
85      if (!empty($variables)) {
86        $variables['#type'] = 'details';
87        $variables['#title'] = $group;
88        $form[$group] = $variables;
89      }
90    }
91  }
92
93  /**
94   * {@inheritdoc}
95   */
96  public function validateForm(array &$form, FormStateInterface $form_state): void {
97    $variables = $form_state->getValues();
98    $variables = $this->filterValues($variables);
99    $variables = $form_state->setValues($variables);
100    // Those two lines are necessary to prevent the form from being rebuilt.
101    // if rebuilt, the form state values will have both the computed ones
102    // and the raw ones (wrapper key and values).
103    $form_state->setRebuild(FALSE);
104    $form_state->setExecuted();
105  }
106
107  /**
108   * {@inheritdoc}
109   */
110  public function alterElement(array $element, array $data = []): array {
111    $inline_css = [];
112
113    foreach ($data as $variable => $value) {
114      $variable = UiSkinsUtility::getCssVariableName($variable);
115      $inline_css[] = "{$variable}{$value};";
116    }
117    $element['#attributes']['style'] = \implode(' ', $inline_css);
118
119    return $element;
120  }
121
122  /**
123   * {@inheritdoc}
124   */
125  public function onAttachToRoot(string $builder_id, string $instance_id): array {
126    return $this->reloadWithInstanceData($builder_id, $instance_id);
127  }
128
129  /**
130   * {@inheritdoc}
131   */
132  public function onAttachToSlot(string $builder_id, string $instance_id, string $parent_id): array {
133    return $this->reloadWithInstanceData($builder_id, $instance_id);
134  }
135
136  /**
137   * {@inheritdoc}
138   */
139  public function onActive(string $builder_id, array $data): array {
140    return $this->reloadWithLocalData($builder_id, $data);
141  }
142
143  /**
144   * {@inheritdoc}
145   */
146  public function onDelete(string $builder_id, string $parent_id): array {
147    return $this->reloadWithLocalData($builder_id, []);
148  }
149
150  /**
151   * {@inheritdoc}
152   */
153  public function isApplicable(): bool {
154    return parent::isApplicable() && \Drupal::service('module_handler')
155      ->moduleExists('ui_skins');
156  }
157
158  /**
159   * Extract values to save in configuration.
160   *
161   * @param array $variables
162   *   The variables to filter.
163   *
164   * @return array
165   *   An array of filtered variables.
166   */
167  protected function filterValues(array $variables): array {
168    $cleaned_variables = [];
169
170    foreach ($variables as $variable => $value) {
171      /** @var \Drupal\ui_skins\Definition\CssVariableDefinition $plugin_definition */
172      $plugin_definition = $this->cssVariablePluginManager->getDefinition($variable, FALSE);
173
174      if (!$plugin_definition) {
175        continue;
176      }
177
178      // Remove values that do not differ from the default values of the plugin.
179      if ($plugin_definition->isDefaultScopeValue(':root', $value)) {
180        continue;
181      }
182
183      $cleaned_variables[$variable] = $value;
184    }
185
186    return $cleaned_variables;
187  }
188
189}

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.

DesignTokensPanel->alterElement
110  public function alterElement(array $element, array $data = []): array {
111    $inline_css = [];
112
113    foreach ($data as $variable => $value) {
113    foreach ($data as $variable => $value) {
113    foreach ($data as $variable => $value) {
113    foreach ($data as $variable => $value) {
114      $variable = UiSkinsUtility::getCssVariableName($variable);
115      $inline_css[] = "{$variable}{$value};";
116    }
117    $element['#attributes']['style'] = \implode(' ', $inline_css);
118
119    return $element;
120  }
DesignTokensPanel->buildForm
60  public function buildForm(array &$form, FormStateInterface $form_state): void {
61    $data = $form_state->getBuildInfo()['args'][0];
62    $instance = $data['instance'] ?? [];
63    $grouped_plugin_definitions = $this->cssVariablePluginManager->getGroupedDefinitions();
64
65    if (empty($grouped_plugin_definitions)) {
66      return;
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
70      $variables = [];
71
72      foreach ($definitions as $definition_id => $definition) {
72      foreach ($definitions as $definition_id => $definition) {
72      foreach ($definitions as $definition_id => $definition) {
73        $default = $definition->getDefaultValues();
74
75        if (!isset($default[':root'])) {
76          continue;
72      foreach ($definitions as $definition_id => $definition) {
73        $default = $definition->getDefaultValues();
74
75        if (!isset($default[':root'])) {
76          continue;
77        }
78        $variables[$definition_id] = [
79          '#type' => $definition->getType(),
72      foreach ($definitions as $definition_id => $definition) {
73        $default = $definition->getDefaultValues();
74
75        if (!isset($default[':root'])) {
76          continue;
77        }
78        $variables[$definition_id] = [
79          '#type' => $definition->getType(),
80          '#title' => $definition->getLabel(),
81          '#default_value' => $instance[$definition_id] ?? $default[':root'] ?? '',
82        ];
83      }
84
85      if (!empty($variables)) {
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
70      $variables = [];
71
72      foreach ($definitions as $definition_id => $definition) {
73        $default = $definition->getDefaultValues();
74
75        if (!isset($default[':root'])) {
76          continue;
77        }
78        $variables[$definition_id] = [
79          '#type' => $definition->getType(),
80          '#title' => $definition->getLabel(),
81          '#default_value' => $instance[$definition_id] ?? $default[':root'] ?? '',
82        ];
83      }
84
85      if (!empty($variables)) {
86        $variables['#type'] = 'details';
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
69    foreach ($grouped_plugin_definitions as $group => $definitions) {
70      $variables = [];
71
72      foreach ($definitions as $definition_id => $definition) {
73        $default = $definition->getDefaultValues();
74
75        if (!isset($default[':root'])) {
76          continue;
77        }
78        $variables[$definition_id] = [
79          '#type' => $definition->getType(),
80          '#title' => $definition->getLabel(),
81          '#default_value' => $instance[$definition_id] ?? $default[':root'] ?? '',
82        ];
83      }
84
85      if (!empty($variables)) {
86        $variables['#type'] = 'details';
87        $variables['#title'] = $group;
88        $form[$group] = $variables;
89      }
90    }
91  }
DesignTokensPanel->create
43  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static {
44    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
45    $instance->cssVariablePluginManager = $container->get('plugin.manager.ui_skins.css_variable');
46
47    return $instance;
48  }
DesignTokensPanel->filterValues
167  protected function filterValues(array $variables): array {
168    $cleaned_variables = [];
169
170    foreach ($variables as $variable => $value) {
170    foreach ($variables as $variable => $value) {
170    foreach ($variables as $variable => $value) {
171      /** @var \Drupal\ui_skins\Definition\CssVariableDefinition $plugin_definition */
172      $plugin_definition = $this->cssVariablePluginManager->getDefinition($variable, FALSE);
173
174      if (!$plugin_definition) {
175        continue;
179      if ($plugin_definition->isDefaultScopeValue(':root', $value)) {
180        continue;
170    foreach ($variables as $variable => $value) {
171      /** @var \Drupal\ui_skins\Definition\CssVariableDefinition $plugin_definition */
172      $plugin_definition = $this->cssVariablePluginManager->getDefinition($variable, FALSE);
173
174      if (!$plugin_definition) {
175        continue;
176      }
177
178      // Remove values that do not differ from the default values of the plugin.
179      if ($plugin_definition->isDefaultScopeValue(':root', $value)) {
180        continue;
181      }
182
183      $cleaned_variables[$variable] = $value;
170    foreach ($variables as $variable => $value) {
171      /** @var \Drupal\ui_skins\Definition\CssVariableDefinition $plugin_definition */
172      $plugin_definition = $this->cssVariablePluginManager->getDefinition($variable, FALSE);
173
174      if (!$plugin_definition) {
175        continue;
176      }
177
178      // Remove values that do not differ from the default values of the plugin.
179      if ($plugin_definition->isDefaultScopeValue(':root', $value)) {
180        continue;
181      }
182
183      $cleaned_variables[$variable] = $value;
184    }
185
186    return $cleaned_variables;
187  }
DesignTokensPanel->isApplicable
154    return parent::isApplicable() && \Drupal::service('module_handler')
154    return parent::isApplicable() && \Drupal::service('module_handler')
155      ->moduleExists('ui_skins');
155      ->moduleExists('ui_skins');
156  }
DesignTokensPanel->label
54    return 'Tokens';
55  }
DesignTokensPanel->onActive
139  public function onActive(string $builder_id, array $data): array {
140    return $this->reloadWithLocalData($builder_id, $data);
141  }
DesignTokensPanel->onAttachToRoot
125  public function onAttachToRoot(string $builder_id, string $instance_id): array {
126    return $this->reloadWithInstanceData($builder_id, $instance_id);
127  }
DesignTokensPanel->onAttachToSlot
132  public function onAttachToSlot(string $builder_id, string $instance_id, string $parent_id): array {
133    return $this->reloadWithInstanceData($builder_id, $instance_id);
134  }
DesignTokensPanel->onDelete
146  public function onDelete(string $builder_id, string $parent_id): array {
147    return $this->reloadWithLocalData($builder_id, []);
148  }
DesignTokensPanel->validateForm
96  public function validateForm(array &$form, FormStateInterface $form_state): void {
97    $variables = $form_state->getValues();
98    $variables = $this->filterValues($variables);
99    $variables = $form_state->setValues($variables);
100    // Those two lines are necessary to prevent the form from being rebuilt.
101    // if rebuilt, the form state values will have both the computed ones
102    // and the raw ones (wrapper key and values).
103    $form_state->setRebuild(FALSE);
104    $form_state->setExecuted();
105  }